|
@@ -18,6 +18,7 @@
|
|
|
#include <malloc.h>
|
|
|
#include <asm/io.h>
|
|
|
#include <asm/mach-common/bits/spi.h>
|
|
|
+#include <asm/mach-common/bits/dma.h>
|
|
|
|
|
|
/* Forcibly phase out these */
|
|
|
#ifdef CONFIG_SPI_FLASH_NUM_SECTORS
|
|
@@ -185,7 +186,7 @@ static struct manufacturer_info flash_manufacturers[] = {
|
|
|
},
|
|
|
};
|
|
|
|
|
|
-#define TIMEOUT 5000 /* timeout of 5 seconds */
|
|
|
+#define TIMEOUT 5000 /* timeout of 5 seconds */
|
|
|
|
|
|
/* If part has multiple SPI flashes, assume SPI0 as that is
|
|
|
* the one we can boot off of ...
|
|
@@ -213,6 +214,7 @@ static void SPI_INIT(void)
|
|
|
/* [#3541] This delay appears to be necessary, but not sure
|
|
|
* exactly why as the history behind it is non-existant.
|
|
|
*/
|
|
|
+ *pSPI_CTL = 0;
|
|
|
udelay(CONFIG_CCLK_HZ / 25000000);
|
|
|
|
|
|
/* enable SPI pins: SSEL, MOSI, MISO, SCK */
|
|
@@ -229,14 +231,13 @@ static void SPI_INIT(void)
|
|
|
#endif
|
|
|
|
|
|
/* initate communication upon write of TDBR */
|
|
|
- *pSPI_CTL = (SPE|MSTR|CPHA|CPOL|0x01);
|
|
|
+ *pSPI_CTL = (SPE | MSTR | CPHA | CPOL | TDBR_CORE);
|
|
|
*pSPI_BAUD = CONFIG_SPI_BAUD;
|
|
|
}
|
|
|
|
|
|
static void SPI_DEINIT(void)
|
|
|
{
|
|
|
- /* put SPI settings back to reset state */
|
|
|
- *pSPI_CTL = 0x0400;
|
|
|
+ *pSPI_CTL = 0;
|
|
|
*pSPI_BAUD = 0;
|
|
|
SSYNC();
|
|
|
}
|
|
@@ -622,9 +623,10 @@ static void transmit_address(uint32_t addr)
|
|
|
* int pnData - pointer to store value read from flash
|
|
|
* long lCount - number of elements to read
|
|
|
*/
|
|
|
+#ifdef CONFIG_SPI_READFLASH_NODMA
|
|
|
static int read_flash(unsigned long address, long count, uchar *buffer)
|
|
|
{
|
|
|
- size_t i;
|
|
|
+ size_t i, j;
|
|
|
|
|
|
/* Send the read command to SPI device */
|
|
|
SPI_ON();
|
|
@@ -638,16 +640,134 @@ static int read_flash(unsigned long address, long count, uchar *buffer)
|
|
|
|
|
|
/* After the SPI device address has been placed on the MOSI pin the data can be */
|
|
|
/* received on the MISO pin. */
|
|
|
+ j = flash.sector_size << 1;
|
|
|
for (i = 1; i <= count; ++i) {
|
|
|
*buffer++ = spi_write_read_byte(0);
|
|
|
- if (i % flash.sector_size == 0)
|
|
|
+ if (!j--) {
|
|
|
puts(".");
|
|
|
+ j = flash.sector_size;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ SPI_OFF();
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#else
|
|
|
+
|
|
|
+#ifdef __ADSPBF54x__
|
|
|
+#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA4_IRQ_STATUS
|
|
|
+#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA4_IRQ_STATUS
|
|
|
+#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA4_CURR_DESC_PTR
|
|
|
+#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA4_CONFIG
|
|
|
+#elif defined(__ADSPBF533__) || defined(__ADSPBF532__) || defined(__ADSPBF531__) || \
|
|
|
+ defined(__ADSPBF538__) || defined(__ADSPBF539__)
|
|
|
+#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA5_IRQ_STATUS
|
|
|
+#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA5_IRQ_STATUS
|
|
|
+#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA5_CURR_DESC_PTR
|
|
|
+#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA5_CONFIG
|
|
|
+#elif defined(__ADSPBF561__)
|
|
|
+#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA16_IRQ_STATUS
|
|
|
+#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA16_IRQ_STATUS
|
|
|
+#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA16_CURR_DESC_PTR
|
|
|
+#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA16_CONFIG
|
|
|
+#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) || \
|
|
|
+ defined(__ADSPBF52x__) || defined(__ADSPBF51x__)
|
|
|
+#define bfin_write_DMA_SPI_IRQ_STATUS bfin_write_DMA7_IRQ_STATUS
|
|
|
+#define bfin_read_DMA_SPI_IRQ_STATUS bfin_read_DMA7_IRQ_STATUS
|
|
|
+#define bfin_write_DMA_SPI_CURR_DESC_PTR bfin_write_DMA7_CURR_DESC_PTR
|
|
|
+#define bfin_write_DMA_SPI_CONFIG bfin_write_DMA7_CONFIG
|
|
|
+#else
|
|
|
+#error "Please provide SPI DMA channel defines"
|
|
|
+#endif
|
|
|
+
|
|
|
+struct dmadesc_array {
|
|
|
+ unsigned long start_addr;
|
|
|
+ unsigned short cfg;
|
|
|
+ unsigned short x_count;
|
|
|
+ short x_modify;
|
|
|
+ unsigned short y_count;
|
|
|
+ short y_modify;
|
|
|
+} __attribute__((packed));
|
|
|
+
|
|
|
+/*
|
|
|
+ * Read a value from flash for verify purpose
|
|
|
+ * Inputs: unsigned long ulStart - holds the SPI start address
|
|
|
+ * int pnData - pointer to store value read from flash
|
|
|
+ * long lCount - number of elements to read
|
|
|
+ */
|
|
|
+
|
|
|
+static int read_flash(unsigned long address, long count, uchar *buffer)
|
|
|
+{
|
|
|
+ unsigned int ndsize;
|
|
|
+ struct dmadesc_array dma[2];
|
|
|
+ /* Send the read command to SPI device */
|
|
|
+
|
|
|
+ if (!count)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ dma[0].start_addr = (unsigned long)buffer;
|
|
|
+ dma[0].x_modify = 1;
|
|
|
+ if (count <= 65536) {
|
|
|
+ blackfin_dcache_flush_invalidate_range(buffer, buffer + count);
|
|
|
+ ndsize = NDSIZE_5;
|
|
|
+ dma[0].cfg = NDSIZE_0 | WNR | WDSIZE_8 | FLOW_STOP | DMAEN | DI_EN;
|
|
|
+ dma[0].x_count = count;
|
|
|
+ } else {
|
|
|
+ blackfin_dcache_flush_invalidate_range(buffer, buffer + 65536 - 1);
|
|
|
+ ndsize = NDSIZE_7;
|
|
|
+ dma[0].cfg = NDSIZE_5 | WNR | WDSIZE_8 | FLOW_ARRAY | DMAEN | DMA2D;
|
|
|
+ dma[0].x_count = 0; /* 2^16 */
|
|
|
+ dma[0].y_count = count >> 16; /* count / 2^16 */
|
|
|
+ dma[0].y_modify = 1;
|
|
|
+ dma[1].start_addr = (unsigned long)(buffer + (count & ~0xFFFF));
|
|
|
+ dma[1].cfg = NDSIZE_0 | WNR | WDSIZE_8 | FLOW_STOP | DMAEN | DI_EN;
|
|
|
+ dma[1].x_count = count & 0xFFFF; /* count % 2^16 */
|
|
|
+ dma[1].x_modify = 1;
|
|
|
}
|
|
|
|
|
|
+ bfin_write_DMA_SPI_CONFIG(0);
|
|
|
+ bfin_write_DMA_SPI_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
|
|
+ bfin_write_DMA_SPI_CURR_DESC_PTR(dma);
|
|
|
+
|
|
|
+ SPI_ON();
|
|
|
+
|
|
|
+ spi_write_read_byte(flash.ops->read);
|
|
|
+ transmit_address(address);
|
|
|
+
|
|
|
+#ifndef CONFIG_SPI_FLASH_SLOW_READ
|
|
|
+ /* Send dummy byte when doing SPI fast reads */
|
|
|
+ spi_write_read_byte(0);
|
|
|
+#endif
|
|
|
+
|
|
|
+ bfin_write_DMA_SPI_CONFIG(ndsize | FLOW_ARRAY | DMAEN);
|
|
|
+ *pSPI_CTL = (MSTR | CPHA | CPOL | RDBR_DMA | SPE | SZ);
|
|
|
+ SSYNC();
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We already invalidated the first 64k,
|
|
|
+ * now while we just wait invalidate the remaining part.
|
|
|
+ * Its not likely that the DMA is going to overtake
|
|
|
+ */
|
|
|
+ if (count > 65536)
|
|
|
+ blackfin_dcache_flush_invalidate_range(buffer + 65536,
|
|
|
+ buffer + count);
|
|
|
+
|
|
|
+ while (!(bfin_read_DMA_SPI_IRQ_STATUS() & DMA_DONE))
|
|
|
+ if (ctrlc())
|
|
|
+ break;
|
|
|
+
|
|
|
SPI_OFF();
|
|
|
|
|
|
+ *pSPI_CTL = 0;
|
|
|
+
|
|
|
+ bfin_write_DMA_SPI_CONFIG(0);
|
|
|
+
|
|
|
+ *pSPI_CTL = (SPE | MSTR | CPHA | CPOL | TDBR_CORE);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
static long address_to_sector(unsigned long address)
|
|
|
{
|