summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2006-08-10 18:14:35 +0000
committerimp <imp@FreeBSD.org>2006-08-10 18:14:35 +0000
commitf67340299e289ea376548b9f3e20250e51bbe46d (patch)
tree4749b014b833e221768865c47824bd179d347124 /sys/boot
parent349e8420c62cf61979807e1193b4eaf4fc8c2a6e (diff)
downloadFreeBSD-src-f67340299e289ea376548b9f3e20250e51bbe46d.zip
FreeBSD-src-f67340299e289ea376548b9f3e20250e51bbe46d.tar.gz
MFp4:
Remove obsolete files in list Add spi flash reading routines
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/arm/at91/libat91/Makefile4
-rw-r--r--sys/boot/arm/at91/libat91/spi_flash.c238
-rw-r--r--sys/boot/arm/at91/libat91/spi_flash.h54
3 files changed, 294 insertions, 2 deletions
diff --git a/sys/boot/arm/at91/libat91/Makefile b/sys/boot/arm/at91/libat91/Makefile
index c8dbb52..7c323b0 100644
--- a/sys/boot/arm/at91/libat91/Makefile
+++ b/sys/boot/arm/at91/libat91/Makefile
@@ -4,8 +4,8 @@
LIB= at91
INTERNALLIB=
-SRCS=at91rm9200_lowlevel.c eeprom.c emac.c env_vars.c getc.c loader_prompt.c \
- p_string.c putchar.c printf.c xmodem.c
+SRCS=at91rm9200_lowlevel.c eeprom.c emac.c getc.c \
+ p_string.c putchar.c printf.c spi_flash.c xmodem.c
NO_MAN=
.if ${MK_TAG_LIST} != "no"
diff --git a/sys/boot/arm/at91/libat91/spi_flash.c b/sys/boot/arm/at91/libat91/spi_flash.c
new file mode 100644
index 0000000..3df2e91
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/spi_flash.c
@@ -0,0 +1,238 @@
+/******************************************************************************
+ *
+ * Filename: spi_flash.c
+ *
+ * Instantiation of SPI flash control routines supporting AT45DB161B
+ *
+ * Revision information:
+ *
+ * 17JAN2005 kb_admin initial creation
+ * adapted from external sources
+ * tested for basic operation only!!!
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ *****************************************************************************/
+
+#include "at91rm9200.h"
+#include "spi_flash.h"
+#include "lib.h"
+
+/*********************** PRIVATE FUNCTIONS/DATA ******************************/
+
+
+static spiCommand_t spi_command;
+static char tx_commandBuffer[8], rx_commandBuffer[8];
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SendCommand(spiCommand_t *pCommand)
+ * Private function sends 8-bit value to the device and returns the 8-bit
+ * value in response.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+SendCommand(spiCommand_t *pCommand)
+{
+ AT91PS_SPI pSPI = AT91C_BASE_SPI;
+
+ pSPI->SPI_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
+
+ pSPI->SPI_RPR = (unsigned)pCommand->rx_cmd;
+ pSPI->SPI_RCR = pCommand->rx_cmd_size;
+ pSPI->SPI_TPR = (unsigned)pCommand->tx_cmd;
+ pSPI->SPI_TCR = pCommand->tx_cmd_size;
+
+ pSPI->SPI_TNPR = (unsigned)pCommand->tx_data;
+ pSPI->SPI_TNCR = pCommand->tx_data_size;
+ pSPI->SPI_RNPR = (unsigned)pCommand->rx_data;
+ pSPI->SPI_RNCR = pCommand->rx_data_size;
+
+ pSPI->SPI_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
+
+ // wait for completion
+ while (!(pSPI->SPI_SR & AT91C_SPI_SPENDRX))
+ Delay(700);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * char GetFlashStatus(void)
+ * Private function to return device status.
+ * .KB_C_FN_DEFINITION_END
+ */
+static char
+GetFlashStatus(void)
+{
+ p_memset((char *)&spi_command, 0, sizeof(spi_command));
+ p_memset(tx_commandBuffer, 0, 8);
+ tx_commandBuffer[0] = STATUS_REGISTER_READ;
+ p_memset(rx_commandBuffer, 0, 8);
+ spi_command.tx_cmd = tx_commandBuffer;
+ spi_command.rx_cmd = rx_commandBuffer;
+ spi_command.rx_cmd_size = 2;
+ spi_command.tx_cmd_size = 2;
+ SendCommand(&spi_command);
+ return (rx_commandBuffer[1]);
+}
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void WaitForDeviceReady(void)
+ * Private function to poll until the device is ready for next operation.
+ * .KB_C_FN_DEFINITION_END
+ */
+static void
+WaitForDeviceReady(void)
+{
+ while (!(GetFlashStatus() & 0x80)) ;
+}
+
+/*************************** GLOBAL FUNCTIONS ********************************/
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SPI_ReadFlash(unsigned flash_addr, unsigned dest_addr, unsigned size)
+ * Global function to read the SPI flash device using the continuous read
+ * array command.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+SPI_ReadFlash(unsigned flash_addr, char *dest_addr, unsigned size)
+{
+ unsigned pageAddress, byteAddress;
+
+ // determine page address
+ pageAddress = flash_addr / FLASH_PAGE_SIZE;
+
+ // determine byte address
+ byteAddress = flash_addr % FLASH_PAGE_SIZE;
+
+ p_memset(tx_commandBuffer, 0, 8);
+ tx_commandBuffer[0] = CONTINUOUS_ARRAY_READ_HF;
+ tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF);
+ tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) |
+ ((byteAddress >> 8) & 0x7);
+ tx_commandBuffer[3] = byteAddress & 0xFF;
+ spi_command.tx_cmd = tx_commandBuffer;
+ spi_command.tx_cmd_size = 5;
+ spi_command.tx_data_size = size;
+ spi_command.tx_data = dest_addr;
+
+ p_memset(rx_commandBuffer, 0, 8);
+ spi_command.rx_cmd = rx_commandBuffer;
+ spi_command.rx_cmd_size = 5;
+ spi_command.rx_data_size = size;
+ spi_command.rx_data = dest_addr;
+
+ SendCommand(&spi_command);
+}
+
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SPI_WriteFlash(unsigned flash_addr, unsigned src_addr, unsigned size)
+ * Global function to program the SPI flash device. Notice the warning
+ * provided in lower-level functions regarding corruption of data in non-
+ * page aligned write operations.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+SPI_WriteFlash(unsigned flash_addr, char *src_addr, unsigned size)
+{
+ unsigned pageAddress, byteAddress;
+
+ // determine page address
+ pageAddress = flash_addr / FLASH_PAGE_SIZE;
+
+ // determine byte address
+ byteAddress = flash_addr % FLASH_PAGE_SIZE;
+
+ p_memset(tx_commandBuffer, 0, 8);
+ tx_commandBuffer[0] = PROGRAM_THROUGH_BUFFER;
+ tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF);
+ tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) |
+ ((byteAddress >> 8) & 0x7);
+ tx_commandBuffer[3] = (byteAddress & 0xFF);
+
+ p_memset(rx_commandBuffer, 0, 8);
+
+ spi_command.tx_cmd = tx_commandBuffer;
+ spi_command.rx_cmd = rx_commandBuffer;
+ spi_command.rx_cmd_size = 4;
+ spi_command.tx_cmd_size = 4;
+
+ spi_command.tx_data_size = size;
+ spi_command.tx_data = src_addr;
+ spi_command.rx_data_size = size;
+ spi_command.rx_data = src_addr;
+
+ SendCommand(&spi_command);
+
+ WaitForDeviceReady();
+}
+
+/*
+ * .KB_C_FN_DEFINITION_START
+ * void SPI_InitFlash(void)
+ * Global function to initialize the SPI flash device/accessor functions.
+ * .KB_C_FN_DEFINITION_END
+ */
+void
+SPI_InitFlash(void)
+{
+ AT91PS_PIO pPio;
+ AT91PS_SPI pSPI = AT91C_BASE_SPI;
+ unsigned value;
+
+ // enable CS0, CLK, MOSI, MISO
+ pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
+ pPio->PIO_ASR = AT91C_PA3_NPCS0 | AT91C_PA1_MOSI | AT91C_PA0_MISO |
+ AT91C_PA2_SPCK;
+ pPio->PIO_PDR = AT91C_PA3_NPCS0 | AT91C_PA1_MOSI | AT91C_PA0_MISO |
+ AT91C_PA2_SPCK;
+
+ // enable clocks to SPI
+ AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_SPI;
+
+ // reset the SPI
+ pSPI->SPI_CR = AT91C_SPI_SWRST;
+
+ pSPI->SPI_MR = (0xf << 24) | AT91C_SPI_MSTR | AT91C_SPI_MODFDIS |
+ (0xE << 16);
+
+ pSPI->SPI_CSR[0] = AT91C_SPI_CPOL | (4 << 16) | (2 << 8);
+ pSPI->SPI_CR = AT91C_SPI_SPIEN;
+
+ pSPI->SPI_PTCR = AT91C_PDC_TXTDIS;
+ pSPI->SPI_PTCR = AT91C_PDC_RXTDIS;
+ pSPI->SPI_RNPR = 0;
+ pSPI->SPI_RNCR = 0;
+ pSPI->SPI_TNPR = 0;
+ pSPI->SPI_TNCR = 0;
+ pSPI->SPI_RPR = 0;
+ pSPI->SPI_RCR = 0;
+ pSPI->SPI_TPR = 0;
+ pSPI->SPI_TCR = 0;
+ pSPI->SPI_PTCR = AT91C_PDC_RXTEN;
+ pSPI->SPI_PTCR = AT91C_PDC_TXTEN;
+
+ value = pSPI->SPI_RDR;
+ value = pSPI->SPI_SR;
+
+ // Increment real time counter every SLCK
+ AT91C_BASE_ST->ST_RTMR = 1;
+
+ if (((value = GetFlashStatus()) & 0xFC) != 0xBC)
+ printf(" Bad SPI status: 0x%x\r\n", value);
+}
diff --git a/sys/boot/arm/at91/libat91/spi_flash.h b/sys/boot/arm/at91/libat91/spi_flash.h
new file mode 100644
index 0000000..e3df2e0
--- /dev/null
+++ b/sys/boot/arm/at91/libat91/spi_flash.h
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ *
+ * Filename: spi_flash.h
+ *
+ * Definition of flash control routines supporting AT45DB161B
+ *
+ * Revision information:
+ *
+ * 17JAN2005 kb_admin initial creation
+ *
+ * BEGIN_KBDD_BLOCK
+ * No warranty, expressed or implied, is included with this software. It is
+ * provided "AS IS" and no warranty of any kind including statutory or aspects
+ * relating to merchantability or fitness for any purpose is provided. All
+ * intellectual property rights of others is maintained with the respective
+ * owners. This software is not copyrighted and is intended for reference
+ * only.
+ * END_BLOCK
+ *
+ * $FreeBSD$
+ ******************************************************************************/
+
+#ifndef _SPI_FLASH_H_
+#define _SPI_FLASH_H_
+
+typedef struct {
+ char *tx_cmd;
+ unsigned tx_cmd_size;
+ char *rx_cmd;
+ unsigned rx_cmd_size;
+ char *tx_data;
+ unsigned tx_data_size;
+ char *rx_data;
+ unsigned rx_data_size;
+} spiCommand_t;
+
+void SPI_ReadFlash(unsigned flash_addr, char *dest_addr, unsigned size);
+void SPI_WriteFlash(unsigned flash_addr, char *dest_addr, unsigned size);
+void SPI_InitFlash(void);
+
+void SPI_GetId(unsigned *id);
+
+#define FLASH_PAGE_SIZE 1056
+
+// Flash commands
+
+#define CONTINUOUS_ARRAY_READ 0xE8
+#define CONTINUOUS_ARRAY_READ_HF 0x0B
+#define CONTINUOUS_ARRAY_READ_LF 0x03
+#define STATUS_REGISTER_READ 0xD7
+#define PROGRAM_THROUGH_BUFFER 0x82
+#define MANUFACTURER_ID 0x9F
+
+#endif
OpenPOWER on IntegriCloud