255 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			255 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/***********************************************************************
							 | 
						|||
| 
								 | 
							
								*   Copyright(C) 2011, NXP Semiconductor
							 | 
						|||
| 
								 | 
							
								*   All rights reserved.
							 | 
						|||
| 
								 | 
							
								*
							 | 
						|||
| 
								 | 
							
								* Software that is described herein is for illustrative purposes only
							 | 
						|||
| 
								 | 
							
								* which provides customers with programming information regarding the
							 | 
						|||
| 
								 | 
							
								* products. This software is supplied "AS IS" without any warranties.
							 | 
						|||
| 
								 | 
							
								* NXP Semiconductors assumes no responsibility or liability for the
							 | 
						|||
| 
								 | 
							
								* use of the software, conveys no license or title under any patent,
							 | 
						|||
| 
								 | 
							
								* copyright, or mask work right to the product. NXP Semiconductors
							 | 
						|||
| 
								 | 
							
								* reserves the right to make changes in the software without
							 | 
						|||
| 
								 | 
							
								* notification. NXP Semiconductors also make no representation or
							 | 
						|||
| 
								 | 
							
								* warranty that such application will be suitable for the specified
							 | 
						|||
| 
								 | 
							
								* use without further testing or modification.
							 | 
						|||
| 
								 | 
							
								* Permission to use, copy, modify, and distribute this software and its
							 | 
						|||
| 
								 | 
							
								* documentation is hereby granted, under NXP Semiconductors<EFBFBD>
							 | 
						|||
| 
								 | 
							
								* relevant copyright in the software, without fee, provided that it
							 | 
						|||
| 
								 | 
							
								* is used in conjunction with NXP Semiconductors microcontrollers.  This
							 | 
						|||
| 
								 | 
							
								* copyright, permission, and disclaimer notice must appear in all copies of
							 | 
						|||
| 
								 | 
							
								* this code.
							 | 
						|||
| 
								 | 
							
								**********************************************************************/
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifndef SPIFI_ROM_API_H
							 | 
						|||
| 
								 | 
							
								#define SPIFI_ROM_API_H
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#include <stdint.h>
							 | 
						|||
| 
								 | 
							
								/* define the symbol TESTING in the environment	if test output desired */
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* maintain LONGEST_PROT >= the length (in bytes) of the largest
							 | 
						|||
| 
								 | 
							
									protection block of any serial flash that this driver handles */
							 | 
						|||
| 
								 | 
							
								#define LONGEST_PROT 68
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								typedef uint8_t uc;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifndef NULL
							 | 
						|||
| 
								 | 
							
								#define NULL ((void *)0)
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* protection/sector descriptors */
							 | 
						|||
| 
								 | 
							
								typedef struct {
							 | 
						|||
| 
								 | 
							
									uint32_t base;
							 | 
						|||
| 
								 | 
							
									uc flags;
							 | 
						|||
| 
								 | 
							
									int8_t log2;
							 | 
						|||
| 
								 | 
							
									uint16_t rept;
							 | 
						|||
| 
								 | 
							
								} protEnt;
							 | 
						|||
| 
								 | 
							
								/* bits in the flags byte */
							 | 
						|||
| 
								 | 
							
								enum {RWPROT=1};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* overall data structure includes # sectors, length of protection reg, 
							 | 
						|||
| 
								 | 
							
								   array of descriptors 
							 | 
						|||
| 
								 | 
							
								typedef struct {
							 | 
						|||
| 
								 | 
							
									uint16_t sectors;
							 | 
						|||
| 
								 | 
							
									uint16_t protBytes;
							 | 
						|||
| 
								 | 
							
									protEnt *entries;
							 | 
						|||
| 
								 | 
							
								} protDesc;	*/
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								typedef union {
							 | 
						|||
| 
								 | 
							
									uint16_t hw;
							 | 
						|||
| 
								 | 
							
									uc byte[2];
							 | 
						|||
| 
								 | 
							
								}stat_t;
							 | 
						|||
| 
								 | 
							
								/* the object that init returns, and other routines use as an operand */
							 | 
						|||
| 
								 | 
							
								typedef struct {
							 | 
						|||
| 
								 | 
							
									uint32_t base, regbase, devSize, memSize;
							 | 
						|||
| 
								 | 
							
									uc mfger, devType, devID, busy;
							 | 
						|||
| 
								 | 
							
									stat_t stat;
							 | 
						|||
| 
								 | 
							
									uint16_t reserved;
							 | 
						|||
| 
								 | 
							
									uint16_t set_prot, write_prot;
							 | 
						|||
| 
								 | 
							
									uint32_t mem_cmd, prog_cmd;
							 | 
						|||
| 
								 | 
							
									uint16_t sectors, protBytes;
							 | 
						|||
| 
								 | 
							
									uint32_t opts, errCheck;
							 | 
						|||
| 
								 | 
							
									uc erase_shifts[4], erase_ops[4];
							 | 
						|||
| 
								 | 
							
									protEnt *protEnts;
							 | 
						|||
| 
								 | 
							
									char prot[LONGEST_PROT];
							 | 
						|||
| 
								 | 
							
								} SPIFIobj;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* operands of program and erase */
							 | 
						|||
| 
								 | 
							
								typedef struct {
							 | 
						|||
| 
								 | 
							
									char *dest;
							 | 
						|||
| 
								 | 
							
									uint32_t length;
							 | 
						|||
| 
								 | 
							
								    char *scratch;
							 | 
						|||
| 
								 | 
							
									int32_t protect;
							 | 
						|||
| 
								 | 
							
									uint32_t options;
							 | 
						|||
| 
								 | 
							
								} SPIFIopers;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* instruction classes for wait_busy */
							 | 
						|||
| 
								 | 
							
								typedef enum {stat_inst, block_erase, prog_inst, chip_erase} inst_type;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* bits in options operands (MODE3, RCVCLK, and FULLCLK 
							 | 
						|||
| 
								 | 
							
									have the same relationship as in the Control register) */
							 | 
						|||
| 
								 | 
							
								#define S_MODE3 1
							 | 
						|||
| 
								 | 
							
								#define S_MODE0 0
							 | 
						|||
| 
								 | 
							
								#define S_MINIMAL 2
							 | 
						|||
| 
								 | 
							
								#define S_MAXIMAL 0
							 | 
						|||
| 
								 | 
							
								#define S_FORCE_ERASE 4
							 | 
						|||
| 
								 | 
							
								#define S_ERASE_NOT_REQD 8
							 | 
						|||
| 
								 | 
							
								#define S_CALLER_ERASE 8
							 | 
						|||
| 
								 | 
							
								#define S_ERASE_AS_REQD 0
							 | 
						|||
| 
								 | 
							
								#define S_VERIFY_PROG 0x10
							 | 
						|||
| 
								 | 
							
								#define S_VERIFY_ERASE 0x20
							 | 
						|||
| 
								 | 
							
								#define S_NO_VERIFY 0
							 | 
						|||
| 
								 | 
							
								#define S_RCVCLK 0x80
							 | 
						|||
| 
								 | 
							
								#define S_INTCLK 0
							 | 
						|||
| 
								 | 
							
								#define S_FULLCLK 0x40
							 | 
						|||
| 
								 | 
							
								#define S_HALFCLK 0
							 | 
						|||
| 
								 | 
							
								#define S_DUAL 0x100
							 | 
						|||
| 
								 | 
							
								#define S_CALLER_PROT 0x200
							 | 
						|||
| 
								 | 
							
								#define S_DRIVER_PROT 0
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* the following values in the first post-address memory command byte work
							 | 
						|||
| 
								 | 
							
								   for all known quad devices that support "no opcode" operation */
							 | 
						|||
| 
								 | 
							
								#define NO_OPCODE_FOLLOWS 0xA5
							 | 
						|||
| 
								 | 
							
								#define    OPCODE_FOLLOWS 0xFF
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* basic SPI commands for serial flash */
							 | 
						|||
| 
								 | 
							
								#define BASE_READ_CMD        (CMD_RD<<OPCODE_SHIFT|4<<FRAMEFORM_SHIFT|UNL_DATA)
							 | 
						|||
| 
								 | 
							
								#define FAST_READ_CMD (CMD_READ_FAST<<OPCODE_SHIFT|4<<FRAMEFORM_SHIFT|1<<INTLEN_SHIFT|UNL_DATA)
							 | 
						|||
| 
								 | 
							
								#define BASE_PROG_CMD      (CMD_PROG<<OPCODE_SHIFT|4<<FRAMEFORM_SHIFT|DOUT)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* the length of a standard	program command is 256 on all devices */
							 | 
						|||
| 
								 | 
							
								#define PROG_SIZE 256
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* options in obj->opts (mostly for setMulti) */
							 | 
						|||
| 
								 | 
							
								/* used by Winbond: send 0xA3 command so hardware can read faster */
							 | 
						|||
| 
								 | 
							
								#define OPT_SEND_A3        1
							 | 
						|||
| 
								 | 
							
								/* used by SST: send 0x38 command to enable quad and allow full command set */
							 | 
						|||
| 
								 | 
							
								#define OPT_SEND_38        2
							 | 
						|||
| 
								 | 
							
								/* used by Winbond and others: read status reg 2, check it, 
							 | 
						|||
| 
								 | 
							
									if necessary write it back with Quad Enable set */
							 | 
						|||
| 
								 | 
							
								#define OPT_35_OR02_01     4
							 | 
						|||
| 
								 | 
							
								/* used by Atmel: read Configuration register, if necessary set Quad Enable */
							 | 
						|||
| 
								 | 
							
								#define OPT_3F_OR80_3E     8
							 | 
						|||
| 
								 | 
							
								/* used by Numonyx to set all-quad mode: only for parts that include RSTQIO */
							 | 
						|||
| 
								 | 
							
								#define OPT_65_CLR_C0_61   0x10
							 | 
						|||
| 
								 | 
							
								/* used by Numonyx: send 0x81 command to write Volatile Configuration Register
							 | 
						|||
| 
								 | 
							
								   to set # dummy bytes and allow XIP mode */
							 | 
						|||
| 
								 | 
							
								#define OPT_81          0x20
							 | 
						|||
| 
								 | 
							
								/* set for devices without full device erase command (Numonyx type 0x40) */
							 | 
						|||
| 
								 | 
							
								#define OPT_NO_DEV_ERASE 0x40
							 | 
						|||
| 
								 | 
							
								/* used by Macronix: status reg 2 includes selection between write-protect 
							 | 
						|||
| 
								 | 
							
									in status reg and command-based */
							 | 
						|||
| 
								 | 
							
								#define OPT_WPSEL       0x80
							 | 
						|||
| 
								 | 
							
								/* set when protection data has been read into the SPIFI object */
							 | 
						|||
| 
								 | 
							
								#define OPT_PROT_READ  0x100
							 | 
						|||
| 
								 | 
							
								/* set if device needs 4-byte address (and maybe 0x4B command = use 4-byte address) */
							 | 
						|||
| 
								 | 
							
								#define OPT_4BAD       0x200
							 | 
						|||
| 
								 | 
							
								/* set if setMulti should set the Dual bit in Control reg */
							 | 
						|||
| 
								 | 
							
								#define OPT_DUAL	   0x400
							 | 
						|||
| 
								 | 
							
								/* send "# dummy bits" in C0 command to Winbond */
							 | 
						|||
| 
								 | 
							
								#define OPT_C0         0x800
							 | 
						|||
| 
								 | 
							
								/* set QE for Chingis */
							 | 
						|||
| 
								 | 
							
								#define OPT_05_OR40_01 0x1000
							 | 
						|||
| 
								 | 
							
								/* write status does not go busy */
							 | 
						|||
| 
								 | 
							
								#define OPT_01_NO_BUSY 0x2000
							 | 
						|||
| 
								 | 
							
								/* protection mode bits moved from protMode byte to opts  Fri May 13 2011 */
							 | 
						|||
| 
								 | 
							
								#define OPT_PROT_STAT 0x4000
							 | 
						|||
| 
								 | 
							
								#define OPT_PROT_REG  0x8000
							 | 
						|||
| 
								 | 
							
								#define OPT_PROT_CMD3 0x10000
							 | 
						|||
| 
								 | 
							
								#define OPT_PROT_CMDE 0x20000
							 | 
						|||
| 
								 | 
							
								#define OPT_PROT_MASK 0x3C000
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#define OPT_ALL_QUAD  0x40000
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifndef OMIT_ROM_TABLE
							 | 
						|||
| 
								 | 
							
								/* interface to ROM API */
							 | 
						|||
| 
								 | 
							
								typedef struct {
							 | 
						|||
| 
								 | 
							
								  int32_t (*spifi_init)      (SPIFIobj *obj, uint32_t csHigh, uint32_t options, 
							 | 
						|||
| 
								 | 
							
								                          uint32_t mhz);
							 | 
						|||
| 
								 | 
							
								  int32_t (*spifi_program)   (SPIFIobj *obj, char *source, SPIFIopers *opers);
							 | 
						|||
| 
								 | 
							
								  int32_t (*spifi_erase)     (SPIFIobj *obj, SPIFIopers *opers);
							 | 
						|||
| 
								 | 
							
								  /* mode switching */
							 | 
						|||
| 
								 | 
							
								  void (*cancel_mem_mode)(SPIFIobj *obj);
							 | 
						|||
| 
								 | 
							
								  void (*set_mem_mode)   (SPIFIobj *obj);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  /* mid level functions */
							 | 
						|||
| 
								 | 
							
								  int32_t (*checkAd)         (SPIFIobj *obj, SPIFIopers *opers);
							 | 
						|||
| 
								 | 
							
								  int32_t (*setProt)         (SPIFIobj *obj, SPIFIopers *opers, char *change, 
							 | 
						|||
| 
								 | 
							
								                          char *saveProt);
							 | 
						|||
| 
								 | 
							
								  int32_t (*check_block)     (SPIFIobj *obj, char *source, SPIFIopers *opers, 
							 | 
						|||
| 
								 | 
							
								                          uint32_t check_program);
							 | 
						|||
| 
								 | 
							
								  int32_t (*send_erase_cmd)  (SPIFIobj *obj, uint8_t op, uint32_t addr);
							 | 
						|||
| 
								 | 
							
								  uint32_t (*ck_erase)   (SPIFIobj *obj, uint32_t *addr, uint32_t length);
							 | 
						|||
| 
								 | 
							
								  int32_t (*prog_block)      (SPIFIobj *obj, char *source, SPIFIopers *opers, 
							 | 
						|||
| 
								 | 
							
								                          uint32_t *left_in_page);
							 | 
						|||
| 
								 | 
							
								  uint32_t (*ck_prog)    (SPIFIobj *obj, char *source, char *dest, uint32_t length);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								  /* low level functions */
							 | 
						|||
| 
								 | 
							
								  void(*setSize)         (SPIFIobj *obj, int32_t value);
							 | 
						|||
| 
								 | 
							
								  int32_t (*setDev)          (SPIFIobj *obj, uint32_t opts, uint32_t mem_cmd, 
							 | 
						|||
| 
								 | 
							
								                          uint32_t prog_cmd);
							 | 
						|||
| 
								 | 
							
								  uint32_t (*cmd)        (uc op, uc addrLen, uc intLen, uint16_t len);
							 | 
						|||
| 
								 | 
							
								  uint32_t (*readAd)     (SPIFIobj *obj, uint32_t cmd, uint32_t addr);
							 | 
						|||
| 
								 | 
							
								  void (*send04)         (SPIFIobj *obj, uc op, uc len, uint32_t value);
							 | 
						|||
| 
								 | 
							
								  void (*wren_sendAd)    (SPIFIobj *obj, uint32_t cmd, uint32_t addr, uint32_t value);
							 | 
						|||
| 
								 | 
							
								  int32_t (*write_stat)      (SPIFIobj *obj, uc len, uint16_t value);
							 | 
						|||
| 
								 | 
							
								  int32_t (*wait_busy)       (SPIFIobj *obj, uc prog_or_erase);
							 | 
						|||
| 
								 | 
							
								} SPIFI_RTNS;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#define define_spifi_romPtr(name) const SPIFI_RTNS *name=*((SPIFI_RTNS **)SPIFI_ROM_PTR)
							 | 
						|||
| 
								 | 
							
								#endif /* OMIT_ROM_TABLE */
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifdef USE_SPIFI_LIB
							 | 
						|||
| 
								 | 
							
								extern SPIFI_RTNS spifi_table;
							 | 
						|||
| 
								 | 
							
								#endif	/* USE_SPIFI_LIB */
							 | 
						|||
| 
								 | 
							
								 
							 | 
						|||
| 
								 | 
							
								/* example of using this interface:
							 | 
						|||
| 
								 | 
							
								#include "spifi_rom_api.h"
							 | 
						|||
| 
								 | 
							
								#define CSHIGH 4
							 | 
						|||
| 
								 | 
							
								#define SPIFI_MHZ 80
							 | 
						|||
| 
								 | 
							
								#define source_data_ad (char *)1234
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									int32_t rc;
							 | 
						|||
| 
								 | 
							
									SPIFIopers opers;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									define_spifi_romPtr(spifi);
							 | 
						|||
| 
								 | 
							
									SPIFIobj *obj = malloc(sizeof(SPIFIobj));
							 | 
						|||
| 
								 | 
							
									if (!obj) { can't allocate memory }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									rc = spifi->spifi_init (obj, CSHIGH, S_FULLCLK+S_RCVCLK, SPIFI_MHZ);
							 | 
						|||
| 
								 | 
							
									if (rc) { investigate init error rc }
							 | 
						|||
| 
								 | 
							
									printf ("the serial flash contains %d bytes\n", obj->devSize);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									opers.dest = where_to_program;
							 | 
						|||
| 
								 | 
							
									opers.length = how_many_bytes;
							 | 
						|||
| 
								 | 
							
									opers.scratch = NULL;			// unprogrammed data is not saved/restored
							 | 
						|||
| 
								 | 
							
									opers.protect = -1;				// save & restore protection
							 | 
						|||
| 
								 | 
							
									opers.options = S_VERIFY_PROG;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									rc = spifi->spifi_program (obj, source_data_ad, &opers);
							 | 
						|||
| 
								 | 
							
									if (rc) { investigate program error rc }
							 | 
						|||
| 
								 | 
							
								*/
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* these are for normal users, including boot code */
							 | 
						|||
| 
								 | 
							
								int32_t spifi_init (SPIFIobj *obj, uint32_t csHigh, uint32_t options, uint32_t mhz);
							 | 
						|||
| 
								 | 
							
								int32_t spifi_program (SPIFIobj *obj, char *source, SPIFIopers *opers);
							 | 
						|||
| 
								 | 
							
								int32_t spifi_erase (SPIFIobj *obj, SPIFIopers *opers);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* these are used by the manufacturer-specific init functions */
							 | 
						|||
| 
								 | 
							
								void setSize (SPIFIobj *obj, int32_t value);
							 | 
						|||
| 
								 | 
							
								int32_t setDev (SPIFIobj *obj, uint32_t opts, uint32_t mem_cmd, uint32_t prog_cmd);
							 | 
						|||
| 
								 | 
							
								uint32_t read04(SPIFIobj *obj, uc op, uc len);
							 | 
						|||
| 
								 | 
							
								int32_t write_stat (SPIFIobj *obj, uc len, uint16_t value);
							 | 
						|||
| 
								 | 
							
								void setProtEnts(SPIFIobj *obj, const protEnt *p, uint32_t protTabLen);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								/* needs to be defined for each platform */
							 | 
						|||
| 
								 | 
							
								void pullMISO(int high);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#ifdef TESTING
							 | 
						|||
| 
								 | 
							
								/* used by testing code */
							 | 
						|||
| 
								 | 
							
								unsigned short getProtBytes (SPIFIobj *obj, unsigned short *sectors);
							 | 
						|||
| 
								 | 
							
								/* predeclare a debug routine */
							 | 
						|||
| 
								 | 
							
								void wait_sample (volatile unsigned *addr, unsigned mask, unsigned value);
							 | 
						|||
| 
								 | 
							
								#endif
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#endif /* SPIFI_ROM_API_H */
							 |