spi_flash.c revision 163533
139297Sfenner/****************************************************************************** 239297Sfenner * 339297Sfenner * Filename: spi_flash.c 439297Sfenner * 539297Sfenner * Instantiation of SPI flash control routines supporting AT45DB161B 639297Sfenner * 739297Sfenner * Revision information: 839297Sfenner * 939297Sfenner * 17JAN2005 kb_admin initial creation 1039297Sfenner * adapted from external sources 1139297Sfenner * tested for basic operation only!!! 1239297Sfenner * 1339297Sfenner * BEGIN_KBDD_BLOCK 1439297Sfenner * No warranty, expressed or implied, is included with this software. It is 1539297Sfenner * provided "AS IS" and no warranty of any kind including statutory or aspects 1639297Sfenner * relating to merchantability or fitness for any purpose is provided. All 1739297Sfenner * intellectual property rights of others is maintained with the respective 1839297Sfenner * owners. This software is not copyrighted and is intended for reference 1939297Sfenner * only. 2039297Sfenner * END_BLOCK 2139297Sfenner * 2239297Sfenner * $FreeBSD: head/sys/boot/arm/at91/libat91/spi_flash.c 163533 2006-10-20 09:12:05Z imp $ 23127668Sbms *****************************************************************************/ 24127668Sbms 2539297Sfenner#include "at91rm9200.h" 2639297Sfenner#include "spi_flash.h" 2756893Sfenner#include "lib.h" 2856893Sfenner 2956893Sfenner/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 3056893Sfenner 31127668Sbms 3239297Sfennerstatic spiCommand_t spi_command; 3339297Sfennerstatic char tx_commandBuffer[8], rx_commandBuffer[8]; 3439297Sfenner 3539297Sfenner/* 3639297Sfenner * .KB_C_FN_DEFINITION_START 3739297Sfenner * void SendCommand(spiCommand_t *pCommand) 3839297Sfenner * Private function sends 8-bit value to the device and returns the 8-bit 3939297Sfenner * value in response. 4039297Sfenner * .KB_C_FN_DEFINITION_END 4139297Sfenner */ 4239297Sfennerstatic void 4339297SfennerSendCommand(spiCommand_t *pCommand) 4439297Sfenner{ 45127668Sbms AT91PS_SPI pSPI = AT91C_BASE_SPI; 46127668Sbms 47127668Sbms pSPI->SPI_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS; 48127668Sbms 49127668Sbms pSPI->SPI_RPR = (unsigned)pCommand->rx_cmd; 50127668Sbms pSPI->SPI_RCR = pCommand->rx_cmd_size; 51127668Sbms pSPI->SPI_TPR = (unsigned)pCommand->tx_cmd; 5239297Sfenner pSPI->SPI_TCR = pCommand->tx_cmd_size; 53127668Sbms 54127668Sbms pSPI->SPI_TNPR = (unsigned)pCommand->tx_data; 5539297Sfenner pSPI->SPI_TNCR = pCommand->tx_data_size; 56127668Sbms pSPI->SPI_RNPR = (unsigned)pCommand->rx_data; 57127668Sbms pSPI->SPI_RNCR = pCommand->rx_data_size; 58127668Sbms 59127668Sbms pSPI->SPI_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN; 60127668Sbms 61127668Sbms // wait for completion 62127668Sbms while (!(pSPI->SPI_SR & AT91C_SPI_SPENDRX)) 63127668Sbms Delay(700); 64127668Sbms} 65127668Sbms 66127668Sbms 67127668Sbms/* 68127668Sbms * .KB_C_FN_DEFINITION_START 69127668Sbms * char GetFlashStatus(void) 70127668Sbms * Private function to return device status. 71127668Sbms * .KB_C_FN_DEFINITION_END 7239297Sfenner */ 7339297Sfennerstatic char 7439297SfennerGetFlashStatus(void) 7539297Sfenner{ 7639297Sfenner p_memset((char *)&spi_command, 0, sizeof(spi_command)); 7739297Sfenner p_memset(tx_commandBuffer, 0, 8); 7839297Sfenner tx_commandBuffer[0] = STATUS_REGISTER_READ; 7939297Sfenner p_memset(rx_commandBuffer, 0, 8); 8039297Sfenner spi_command.tx_cmd = tx_commandBuffer; 8139297Sfenner spi_command.rx_cmd = rx_commandBuffer; 8239297Sfenner spi_command.rx_cmd_size = 2; 8339297Sfenner spi_command.tx_cmd_size = 2; 8439297Sfenner SendCommand(&spi_command); 8539297Sfenner return (rx_commandBuffer[1]); 8639297Sfenner} 8739297Sfenner 8839297Sfenner/* 8939297Sfenner * .KB_C_FN_DEFINITION_START 9039297Sfenner * void WaitForDeviceReady(void) 9139297Sfenner * Private function to poll until the device is ready for next operation. 9239297Sfenner * .KB_C_FN_DEFINITION_END 9339297Sfenner */ 94static void 95WaitForDeviceReady(void) 96{ 97 while (!(GetFlashStatus() & 0x80)) ; 98} 99 100/*************************** GLOBAL FUNCTIONS ********************************/ 101 102 103/* 104 * .KB_C_FN_DEFINITION_START 105 * void SPI_ReadFlash(unsigned flash_addr, unsigned dest_addr, unsigned size) 106 * Global function to read the SPI flash device using the continuous read 107 * array command. 108 * .KB_C_FN_DEFINITION_END 109 */ 110void 111SPI_ReadFlash(unsigned flash_addr, char *dest_addr, unsigned size) 112{ 113 unsigned pageAddress, byteAddress; 114 115 // determine page address 116 pageAddress = flash_addr / FLASH_PAGE_SIZE; 117 118 // determine byte address 119 byteAddress = flash_addr % FLASH_PAGE_SIZE; 120 121 p_memset(tx_commandBuffer, 0, 8); 122 tx_commandBuffer[0] = CONTINUOUS_ARRAY_READ_HF; 123 tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF); 124 tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) | 125 ((byteAddress >> 8) & 0x7); 126 tx_commandBuffer[3] = byteAddress & 0xFF; 127 spi_command.tx_cmd = tx_commandBuffer; 128 spi_command.tx_cmd_size = 5; 129 spi_command.tx_data_size = size; 130 spi_command.tx_data = dest_addr; 131 132 p_memset(rx_commandBuffer, 0, 8); 133 spi_command.rx_cmd = rx_commandBuffer; 134 spi_command.rx_cmd_size = 5; 135 spi_command.rx_data_size = size; 136 spi_command.rx_data = dest_addr; 137 138 SendCommand(&spi_command); 139} 140 141 142/* 143 * .KB_C_FN_DEFINITION_START 144 * void SPI_WriteFlash(unsigned flash_addr, unsigned src_addr, unsigned size) 145 * Global function to program the SPI flash device. Notice the warning 146 * provided in lower-level functions regarding corruption of data in non- 147 * page aligned write operations. 148 * .KB_C_FN_DEFINITION_END 149 */ 150void 151SPI_WriteFlash(unsigned flash_addr, char *src_addr, unsigned size) 152{ 153 unsigned pageAddress, byteAddress; 154 155 // determine page address 156 pageAddress = flash_addr / FLASH_PAGE_SIZE; 157 158 // determine byte address 159 byteAddress = flash_addr % FLASH_PAGE_SIZE; 160 161 p_memset(tx_commandBuffer, 0, 8); 162 tx_commandBuffer[0] = PROGRAM_THROUGH_BUFFER; 163 tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF); 164 tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) | 165 ((byteAddress >> 8) & 0x7); 166 tx_commandBuffer[3] = (byteAddress & 0xFF); 167 168 p_memset(rx_commandBuffer, 0, 8); 169 170 spi_command.tx_cmd = tx_commandBuffer; 171 spi_command.rx_cmd = rx_commandBuffer; 172 spi_command.rx_cmd_size = 4; 173 spi_command.tx_cmd_size = 4; 174 175 spi_command.tx_data_size = size; 176 spi_command.tx_data = src_addr; 177 spi_command.rx_data_size = size; 178 spi_command.rx_data = src_addr; 179 180 SendCommand(&spi_command); 181 182 WaitForDeviceReady(); 183} 184 185/* 186 * .KB_C_FN_DEFINITION_START 187 * void SPI_InitFlash(void) 188 * Global function to initialize the SPI flash device/accessor functions. 189 * .KB_C_FN_DEFINITION_END 190 */ 191void 192SPI_InitFlash(void) 193{ 194 AT91PS_PIO pPio; 195 AT91PS_SPI pSPI = AT91C_BASE_SPI; 196 unsigned value; 197 198 // enable CS0, CLK, MOSI, MISO 199 pPio = (AT91PS_PIO)AT91C_BASE_PIOA; 200 pPio->PIO_ASR = AT91C_PA3_NPCS0 | AT91C_PA1_MOSI | AT91C_PA0_MISO | 201 AT91C_PA2_SPCK; 202 pPio->PIO_PDR = AT91C_PA3_NPCS0 | AT91C_PA1_MOSI | AT91C_PA0_MISO | 203 AT91C_PA2_SPCK; 204 205 // enable clocks to SPI 206 AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_SPI; 207 208 // reset the SPI 209 pSPI->SPI_CR = AT91C_SPI_SWRST; 210 211 pSPI->SPI_MR = (0xf << 24) | AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | 212 (0xE << 16); 213 214 pSPI->SPI_CSR[0] = AT91C_SPI_CPOL | (4 << 16) | (2 << 8); 215 pSPI->SPI_CR = AT91C_SPI_SPIEN; 216 217 pSPI->SPI_PTCR = AT91C_PDC_TXTDIS; 218 pSPI->SPI_PTCR = AT91C_PDC_RXTDIS; 219 pSPI->SPI_RNPR = 0; 220 pSPI->SPI_RNCR = 0; 221 pSPI->SPI_TNPR = 0; 222 pSPI->SPI_TNCR = 0; 223 pSPI->SPI_RPR = 0; 224 pSPI->SPI_RCR = 0; 225 pSPI->SPI_TPR = 0; 226 pSPI->SPI_TCR = 0; 227 pSPI->SPI_PTCR = AT91C_PDC_RXTEN; 228 pSPI->SPI_PTCR = AT91C_PDC_TXTEN; 229 230 value = pSPI->SPI_RDR; 231 value = pSPI->SPI_SR; 232 233 // Increment real time counter every SLCK 234 AT91C_BASE_ST->ST_RTMR = 1; 235 236 if (((value = GetFlashStatus()) & 0xFC) != 0xBC) 237 printf(" Bad SPI status: 0x%x\n", value); 238} 239