00001 /* ---------------------------------------------------------------------------- */ 00002 /* Atmel Microcontroller Software Support */ 00003 /* SAM Software Package License */ 00004 /* ---------------------------------------------------------------------------- */ 00005 /* Copyright (c) 2015, Atmel Corporation */ 00006 /* */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without */ 00010 /* modification, are permitted provided that the following condition is met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, */ 00013 /* this list of conditions and the disclaimer below. */ 00014 /* */ 00015 /* Atmel's name may not be used to endorse or promote products derived from */ 00016 /* this software without specific prior written permission. */ 00017 /* */ 00018 /* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ 00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ 00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ 00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ 00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ 00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ 00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ 00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ 00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ 00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00028 /* ---------------------------------------------------------------------------- */ 00029 00030 //------------------------------------------------------------------------------ 00031 // Headers 00032 //------------------------------------------------------------------------------ 00033 00034 #include "at26.h" 00035 #include "board.h" 00036 #include <assert.h> 00037 00038 //------------------------------------------------------------------------------ 00039 // Internal definitions 00040 //------------------------------------------------------------------------------ 00041 00042 /// SPI clock frequency used in Hz. 00043 #define SPCK 1000000 00044 00045 /// SPI chip select configuration value. 00046 #define CSR (SPI_CSR_NCPHA | \ 00047 SPID_CSR_DLYBCT(BOARD_MCK, 100) | \ 00048 SPID_CSR_DLYBS(BOARD_MCK, 5) | \ 00049 SPID_CSR_SCBR(BOARD_MCK, SPCK)) 00050 00051 /// Number of recognized dataflash. 00052 #define NUMDATAFLASH (sizeof(at26Devices) / sizeof(At26Desc)) 00053 00054 //------------------------------------------------------------------------------ 00055 // Internal variables 00056 //------------------------------------------------------------------------------ 00057 00058 /// Array of recognized serial firmware dataflash chips. 00059 static const At26Desc at26Devices[] = { 00060 // name, Jedec ID, size, page size, block size, block erase command 00061 {"AT25DF041A" , 0x0001441F, 512 * 1024 , 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00062 {"AT25DF161" , 0x0002461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00063 {"AT26DF081A" , 0x0001451F, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00064 {"AT26DF0161" , 0x0000461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00065 {"AT26DF161A" , 0x0001461F, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00066 {"AT26DF321" , 0x0000471F, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00067 {"AT25DF512B" , 0x0001651F, 64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_32K}, 00068 {"AT25DF512B" , 0x0000651F, 64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_32K}, 00069 {"AT25DF021" , 0x0000431F, 256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00070 {"AT26DF641" , 0x0000481F, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00071 // Manufacturer: ST 00072 {"M25P05" , 0x00102020, 64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K}, 00073 {"M25P10" , 0x00112020, 128 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_64K}, 00074 {"M25P20" , 0x00122020, 256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00075 {"M25P40" , 0x00132020, 512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00076 {"M25P80" , 0x00142020, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00077 {"M25P16" , 0x00152020, 2 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00078 {"M25P32" , 0x00162020, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00079 {"M25P64" , 0x00172020, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00080 // Manufacturer: Windbond 00081 {"W25X10" , 0x001130EF, 128 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00082 {"W25X20" , 0x001230EF, 256 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00083 {"W25X40" , 0x001330EF, 512 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00084 {"W25X80" , 0x001430EF, 1 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00085 // Manufacturer: Macronix 00086 {"MX25L512" , 0x001020C2, 64 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00087 {"MX25L3205" , 0x001620C2, 4 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00088 {"MX25L6405" , 0x001720C2, 8 * 1024 * 1024, 256, 64 * 1024, AT26_BLOCK_ERASE_64K}, 00089 // Other 00090 {"SST25VF512" , 0x000048BF, 64 * 1024, 256, 32 * 1024, AT26_BLOCK_ERASE_32K} 00091 }; 00092 00093 //------------------------------------------------------------------------------ 00094 // Exported functions 00095 //------------------------------------------------------------------------------ 00096 00097 //------------------------------------------------------------------------------ 00098 /// Initializes an AT26 driver instance with the given SPI driver and chip 00099 /// select value. 00100 /// \param pAt26 Pointer to an AT26 driver instance. 00101 /// \param pSpid Pointer to an SPI driver instance. 00102 /// \param cs Chip select value to communicate with the serial flash. 00103 //------------------------------------------------------------------------------ 00104 void AT26_Configure(At26 *pAt26, Spid *pSpid, unsigned char cs) 00105 { 00106 SpidCmd *pCommand; 00107 00108 assert(pAt26 != NULL); 00109 assert(pSpid != NULL); 00110 assert(cs < 4); 00111 00112 // Configure the SPI chip select for the serial flash 00113 SPID_ConfigureCS(pSpid, cs, CSR); 00114 00115 // Initialize the AT26 fields 00116 pAt26->pSpid = pSpid; 00117 pAt26->pDesc = 0; 00118 00119 // Initialize the command structure 00120 pCommand = &(pAt26->command); 00121 pCommand->pCmd = (unsigned char *) pAt26->pCmdBuffer; 00122 pCommand->callback = 0; 00123 pCommand->pArgument = 0; 00124 pCommand->spiCs = cs; 00125 } 00126 00127 //------------------------------------------------------------------------------ 00128 /// Returns 1 if the serial flash driver is currently busy executing a command; 00129 /// otherwise returns 0. 00130 /// \param pAt26 Pointer to an At26 driver instance. 00131 //------------------------------------------------------------------------------ 00132 unsigned char AT26_IsBusy(At26 *pAt26) 00133 { 00134 return SPID_IsBusy(pAt26->pSpid); 00135 } 00136 00137 //------------------------------------------------------------------------------ 00138 /// Sends a command to the serial flash through the SPI. The command is made up 00139 /// of two parts: the first is used to transmit the command byte and optionally, 00140 /// address and dummy bytes. The second part is the data to send or receive. 00141 /// This function does not block: it returns as soon as the transfer has been 00142 /// started. An optional callback can be invoked to notify the end of transfer. 00143 /// Return 0 if successful; otherwise, returns AT26_ERROR_BUSY if the AT26 00144 /// driver is currently executing a command, or AT26_ERROR_SPI if the command 00145 /// cannot be sent because of a SPI error. 00146 /// \param pAt26 Pointer to an At26 driver instance. 00147 /// \param cmd Command byte. 00148 /// \param cmdSize Size of command (command byte + address bytes + dummy bytes). 00149 /// \param pData Data buffer. 00150 /// \param dataSize Number of bytes to send/receive. 00151 /// \param address Address to transmit. 00152 /// \param callback Optional user-provided callback to invoke at end of transfer. 00153 /// \param pArgument Optional argument to the callback function. 00154 //------------------------------------------------------------------------------ 00155 unsigned char AT26_SendCommand( 00156 At26 *pAt26, 00157 unsigned char cmd, 00158 unsigned char cmdSize, 00159 unsigned char *pData, 00160 unsigned int dataSize, 00161 unsigned int address, 00162 SpidCallback callback, 00163 void *pArgument) 00164 00165 { 00166 SpidCmd *pCommand; 00167 00168 assert(pAt26 != NULL); 00169 00170 // Check if the SPI driver is available 00171 if (AT26_IsBusy(pAt26)) 00172 00173 return AT26_ERROR_BUSY; 00174 00175 // Store command and address in command buffer 00176 pAt26->pCmdBuffer[0] = (cmd & 0x000000FF) 00177 | ((address & 0x0000FF) << 24) 00178 | ((address & 0x00FF00) << 8) 00179 | ((address & 0xFF0000) >> 8); 00180 00181 // Update the SPI transfer descriptor 00182 pCommand = &(pAt26->command); 00183 pCommand->cmdSize = cmdSize; 00184 pCommand->pData = pData; 00185 pCommand->dataSize = dataSize; 00186 pCommand->callback = callback; 00187 pCommand->pArgument = pArgument; 00188 00189 // Start the SPI transfer 00190 if (SPID_SendCommand(pAt26->pSpid, pCommand)) 00191 00192 return AT26_ERROR_SPI; 00193 00194 return 0; 00195 } 00196 00197 //------------------------------------------------------------------------------ 00198 /// Tries to detect a serial firmware flash device given its JEDEC identifier. 00199 /// The JEDEC id can be retrieved by sending the correct command to the device. 00200 /// Returns the corresponding AT26 descriptor if found; otherwise returns 0. 00201 /// \param pAt26 Pointer to an AT26 driver instance. 00202 /// \param jedecId JEDEC identifier of device. 00203 //------------------------------------------------------------------------------ 00204 const At26Desc *AT26_FindDevice(At26 *pAt26, unsigned int jedecId) 00205 { 00206 unsigned int i = 0; 00207 00208 assert(pAt26 != NULL); 00209 00210 // Search if device is recognized 00211 pAt26->pDesc = 0; 00212 00213 while ((i < NUMDATAFLASH) && !(pAt26->pDesc)) { 00214 00215 if (jedecId == at26Devices[i].jedecId) 00216 00217 pAt26->pDesc = &(at26Devices[i]); 00218 00219 i++; 00220 } 00221 00222 return (pAt26->pDesc); 00223 } 00224