summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c4682c6)
raw | patch | inline | side by side (parent: c4682c6)
author | Mike Line <m-line1@ti.com> | |
Tue, 21 Dec 2010 23:23:12 +0000 (18:23 -0500) | ||
committer | Mike Line <m-line1@ti.com> | |
Tue, 21 Dec 2010 23:23:12 +0000 (18:23 -0500) |
19 files changed:
src/device/c64x/make/makefile | patch | blob | history | |
src/device/c661x/c661x.c | patch | blob | history | |
src/device/c661x/target.h | patch | blob | history | |
src/device/device.h | patch | blob | history | |
src/driver/c64x/make/makefile | patch | blob | history | |
src/driver/nand/nand.c | patch | blob | history | |
src/hw/c64x/make/makefile | patch | blob | history | |
src/hw/nands/emif25/nandemif25.c | patch | blob | history | |
src/hw/nands/nandhwapi.h | patch | blob | history | |
src/hw/nands/spi/nandspi.c | [new file with mode: 0644] | patch | blob |
src/hw/spi/spi.c | [new file with mode: 0644] | patch | blob |
src/hw/spi/spi_api.h | [new file with mode: 0644] | patch | blob |
src/hw/spi/spi_loc.h | [new file with mode: 0644] | patch | blob |
src/ibl.h | patch | blob | history | |
src/main/iblinit.c | patch | blob | history | |
src/make/Makefile | patch | blob | history | |
src/make/ibl_c661x/ibl_objs_template.inc | patch | blob | history | |
src/util/i2cConfig/makestg2 | patch | blob | history | |
src/util/i2cWrite/makestg2 | patch | blob | history |
index da83c7be558617851488b84451bc4a24bbbd568e..d1cb5b1c01f085a8175426a4d3e99d80b8087000 100644 (file)
C6X_C_DIR+= ;$(IBL_ROOT)/hw/cpdma
C6X_C_DIR+= ;$(IBL_ROOT)/hw/pa
C6X_C_DIR+= ;$(IBL_ROOT)/hw/serdes
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands
C6X_C_DIR+= ;$(IBL_ROOT)/driver/eth
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/spi
export C6X_C_DIR
vpath % $(IBL_ROOT)/device/$(TARGET)
index 96e5edcfdfd6a6c12ba95fd23334ba67d60b2619..e908fe70e51f3d6b59a6aac2b19e5bc3e9acd620 100644 (file)
--- a/src/device/c661x/c661x.c
+++ b/src/device/c661x/c661x.c
#include "pa_api.h"
#include "serdes_api.h"
#include "net.h"
+#include "nandhwapi.h"
+#include "spi_api.h"
#include <string.h>
extern cregister unsigned int DNUM;
/**
- * @brief Enable the pass through version of the nand controller
+ * @brief Enable EMIF25 or SPI interface to the NAND
*
- * @details On the evm the nand controller is enabled by setting
- * gpio 14 high
*/
#ifndef EXCLUDE_NAND
int32 deviceConfigureForNand(void)
{
+
+#ifndef EXCLUDE_NAND_SPI
+
+ if (ibl.nandConfig.interface == ibl_NAND_IF_SPI) {
+
+ spiConfig_t spiCfg;
+ uint32 v;
+ SINT16 ret;
+
+ /* SPI is module number 3 only on the c6618. On the c6616 the SPI is in the
+ * always on domain */
+ v = *((Uint32 *)DEVICE_JTAG_ID_REG);
+ if (v == DEVICE_C6618_JTAG_ID_VAL)
+ devicePowerPeriph (3);
+
+ /* Translate to the low level driver */
+ spiCfg.port = 0;
+ spiCfg.mode = ibl.spiConfig.mode;
+ spiCfg.addrWidth = ibl.spiConfig.addrWidth;
+ spiCfg.npin = ibl.spiConfig.nPins;
+ spiCfg.csel = ibl.spiConfig.csel;
+ spiCfg.c2tdelay = ibl.spiConfig.c2tdelay;
+
+ /* On c661x devices the PLL module has a built in divide by 6, and the SPI
+ * has a maximum clock divider value of 0xff */
+ v = ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz / (DEVICE_SPI_MOD_DIVIDER * ibl.spiConfig.busFreqMHz);
+ if (v > 0xff)
+ v = 0xff;
+
+ spiCfg.clkdiv = (UINT16) v;
+
+ ret = hwSpiConfig (&spiCfg);
+
+ if (ret != 0) {
+ iblStatus.iblFail = ibl_FAIL_CODE_SPI_PARAMS;
+ return (-1);
+ }
+
+ }
+
+#endif
+
return (0);
}
}
+/**
+ * @brief Return the NAND interface (EMIF25 or SPI) used based on the value
+ * of interface
+ */
+#ifndef EXCLUDE_NAND_EMIF
+nandCtbl_t nandEmifCtbl = {
+
+ nandHwDriverInit,
+ nandHwDriverReadBytes,
+ nandHwDriverReadPage,
+ nandHwDriverClose
+
+};
+#endif
+
+#ifndef EXCLUDE_NAND_SPI
+nandCtbl_t nandSpiCtbl = {
+
+
+ nandHwSpiDriverInit,
+ nandHwSpiDriverReadBytes,
+ nandHwSpiDriverReadPage,
+ nandHwSpiDriverClose
+
+};
+#endif
+
+nandCtbl_t *deviceGetNandCtbl (int32 interface)
+{
+
+#ifndef EXCLUDE_NAND_SPI
+
+ if (interface == ibl_NAND_IF_SPI)
+ return (&nandSpiCtbl);
+
+#endif
+
+#ifndef EXCLUDE_NAND_EMIF
+ if ((interface >= ibl_NAND_IF_CHIPSEL_2) && (interface <= ibl_NAND_IF_CHIPSEL_5))
+ return (&nandEmifCtbl);
+
+#endif
+
+ return (NULL);
+
+}
+
index a282ecdedc54386d3687bd7c3854770a28621528..ea10352cab42a7fdc97c24a538b0a51e2120a805 100644 (file)
*/
#define DEVICE_PSC_BASE 0x02350000u
+/**
+ * @brief
+ * The SPI module base and module divider
+ */
+#define DEVICE_SPI_BASE(x) 0x20bf0000u
+#define DEVICE_SPI_MOD_DIVIDER 6
/**
* @brief
diff --git a/src/device/device.h b/src/device/device.h
index 952f328980342b06b8a6b96513d722b6b8422ed6..12a075bc37b8fa9cde6577746734c9055adeb954 100644 (file)
--- a/src/device/device.h
+++ b/src/device/device.h
*/
bool deviceIsLittleEndian(void);
-#endif
-
/**
* @brief
*/
void chipDelay32 (uint32 nCycles);
+
+/**
+ * @brief
+ * Return the NAND interface function table
+ *
+ * @details
+ * Some devices support multiple NAND interface at once (EMIF25 and SPI).
+ * This function returns to the lower level driver the pointer to the
+ * table to use. The table is selected in the ibl configuration.
+ */
+typedef struct nandCtbl_s {
+
+ Int32 (*nct_driverInit) (int32 cs, void *nandDevInfo);
+ Int32 (*nct_driverReadBytes) (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, Uint8 *data);
+ Int32 (*nct_driverReadPage) (Uint32 block, Uint32 page, Uint8 *data);
+ Int32 (*nct_driverClose) (void);
+
+} nandCtbl_t;
+
+nandCtbl_t *deviceGetNandCtbl (int32 interface);
+
+
+
+#endif
index 9a1e1a05308a102b0801467b04d7c0d3a2bd061c..bb7d45e6ceb7141aa73d2c50cb032d205e3a8bdd 100644 (file)
C6X_C_DIR+= ;$(IBL_ROOT)/cfg/$(TARGET)
C6X_C_DIR+= ;$(IBL_ROOT)/hw/timer
C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands
+C6X_C_DIR+= ;$(IBL_ROOT)/device
+C6X_C_DIR+= ;$(IBL_ROOT)/device/$(TARGET)
export C6X_C_DIR
vpath % $(subst ;,$(PATHSEP), $(ECODIR)/$(ETHDIR); $(ECODIR)/$(STRMDIR); $(ECODIR)/$(TIMDIR); $(ECODIR)/$(NANDDIR) )
diff --git a/src/driver/nand/nand.c b/src/driver/nand/nand.c
index 496b7bdee12c9c9759a2f2a63abe6b345c9a42f3..40528c588300a7748a6d6a75a3a3e34d39490c7a 100644 (file)
--- a/src/driver/nand/nand.c
+++ b/src/driver/nand/nand.c
#include "types.h"
#include "ibl.h"
#include "iblloc.h"
+#include "device.h"
#include "nand.h"
#include "nandhwapi.h"
#include <string.h>
Uint8 *blocks; /**< There is one byte per block. A non-zero value indicates
that the block is bad */
+ nandCtbl_t *nand_if; /**< Current low level interface (GPIO, EMIF or SPI) */
+
+
} nandmcb_t;
nandmcb_t nandmcb;
+
/**
* @b Description
* @n
return (0);
/* Otherwise load the desired page */
- if (nandHwDriverReadPage((Uint32)(nandmcb.logicalToPhysMap[desiredBlock]), desiredPage, nandmcb.page) < 0)
- return (-2);
+ if (nandmcb.nand_if->nct_driverReadPage != NULL) {
+ if ((*nandmcb.nand_if->nct_driverReadPage)((Uint32)(nandmcb.logicalToPhysMap[desiredBlock]), desiredPage, nandmcb.page) < 0)
+ return (-2);
+ }
/* Update the currently loaded block/page info */
nandmcb.currentLogicalBlock = desiredBlock;
* This function initializes the nand control structure and reads the bad block info
* from the nand.
*/
-Int32 nand_open (void *ptr_driver, void (*asyncComplete)(void *), int32 chipSelect)
+Int32 nand_open (void *ptr_driver, void (*asyncComplete)(void *))
{
iblNand_t *ibln = (iblNand_t *)ptr_driver;
@@ -182,9 +189,19 @@ Int32 nand_open (void *ptr_driver, void (*asyncComplete)(void *), int32 chipSele
nandmcb.physToLogicalMap = NULL;
nandmcb.blocks = NULL;
- ret = nandHwDriverInit (ibln->cs, &nandmcb.devInfo);
- if (ret < 0)
- nand_free_return (ret);
+ nandmcb.nand_if = deviceGetNandCtbl (ibln->interface);
+
+ if (nandmcb.nand_if != NULL) {
+
+ ret = (*nandmcb.nand_if->nct_driverInit)(ibln->interface, (void *)&nandmcb.devInfo);
+ if (ret < 0)
+ nand_free_return (ret);
+
+ } else {
+
+ return (-1);
+
+ }
/* allocate memory for the page data and the logical to physical block map */
size = nandmcb.devInfo.pageSizeBytes + nandmcb.devInfo.pageEccBytes;
@@ -213,22 +230,25 @@ Int32 nand_open (void *ptr_driver, void (*asyncComplete)(void *), int32 chipSele
/* Bad blocks are identified by reading page 0 and page 1. If the first
* byte in these pages is not 0xff then the block is bad */
+ if (nandmcb.nand_if == NULL)
+ return (-1);
+
nandmcb.numBadBlocks = 0;
for (i = 0; i < nandmcb.devInfo.totalBlocks; i++) {
- ret = nandHwDriverReadBytes (i, 0, nandmcb.devInfo.pageSizeBytes, 1, &nandmcb.page[0]);
- if (ret < 0)
- nand_free_return (ret);
+ ret = (*nandmcb.nand_if->nct_driverReadBytes)(i, 0, nandmcb.devInfo.pageSizeBytes, 1, &nandmcb.page[0]);
+ if (ret < 0)
+ nand_free_return (ret);
- ret = nandHwDriverReadBytes (i, 1, nandmcb.devInfo.pageSizeBytes, 1, &nandmcb.page[1]);
- if (ret < 0)
- nand_free_return (ret);
+ ret = (*nandmcb.nand_if->nct_driverReadBytes)(i, 1, nandmcb.devInfo.pageSizeBytes, 1, &nandmcb.page[1]);
+ if (ret < 0)
+ nand_free_return (ret);
- if ((nandmcb.page[0] != 0xff) || (nandmcb.page[1] != 0xff)) {
- nandmcb.blocks[i] = 0xff;
- nandmcb.numBadBlocks += 1;
- } else
- nandmcb.blocks[i] = 0;
+ if ((nandmcb.page[0] != 0xff) || (nandmcb.page[1] != 0xff)) {
+ nandmcb.blocks[i] = 0xff;
+ nandmcb.numBadBlocks += 1;
+ } else
+ nandmcb.blocks[i] = 0;
}
Int32 i;
Int32 pIdx;
+
+ if (nandmcb.nand_if == NULL)
+ return (-1);
+
/* Convert the global file position to an offset in the currently cached page */
pIdx = nandmcb.fpos % nandmcb.devInfo.pageSizeBytes;
/* Load the new page */
- if (nandHwDriverReadPage((Uint32)(nandmcb.logicalToPhysMap[nandmcb.currentLogicalBlock]), nandmcb.currentPage, nandmcb.page) < 0)
+ if ((*nandmcb.nand_if->nct_driverReadPage)((Uint32)(nandmcb.logicalToPhysMap[nandmcb.currentLogicalBlock]), nandmcb.currentPage, nandmcb.page) < 0)
return (-2);
}
Uint32 origLogicalBlock;
Uint32 origPage;
+
+ if (nandmcb.nand_if == NULL)
+ return (-1);
+
origPos = nandmcb.fpos;
origLogicalBlock = nandmcb.currentLogicalBlock;
origPage = nandmcb.currentPage;
if ( (origLogicalBlock != nandmcb.currentLogicalBlock) ||
(origPage != nandmcb.currentPage) ) {
- if (nandHwDriverReadPage((Uint32)(nandmcb.logicalToPhysMap[origLogicalBlock]), origPage, nandmcb.page) < 0)
+ if ((*nandmcb.nand_if->nct_driverReadPage)((Uint32)(nandmcb.logicalToPhysMap[origLogicalBlock]), origPage, nandmcb.page) < 0)
return (-2);
}
*/
Int32 nand_close (void)
{
- nandHwDriverClose ();
+ if (nandmcb.nand_if != NULL)
+ nandHwDriverClose ();
+
return (nand_free_return (0));
}
index e6ed3f6111818d00c72f0468b719278eb7c80e51..6e7540b880b856b8c0d2b805efa626a8fb0b65cd 100644 (file)
else
ifeq ($(TARGET),c661x)
CSRC= t64.c pll.c cfgpll.c cfgpll2.c mdio.c i2c.c psc.c cpsw.c qm.c cpdma.c pa.c sgmii.c serdes.c gmacsl.c emif4.c
- CSRC+= nandemif25.c
+ CSRC+= nandemif25.c spi.c nandspi.c
else
CSRC= t64.c cpmacdrv.c pll.c psc.c emif31.c mdio.c gpio.c nandgpio.c i2c.c nandwrgpio.c sgmii.c cfgpll.c cfgpll2.c
- CSRC+= qm.c cpdma.c pa.c serdes.c gmacsl.c emif4.c nandemif25.c
+ CSRC+= qm.c cpdma.c pa.c serdes.c gmacsl.c emif4.c nandemif25.c spi.c nandspi.c
endif
endif
endif
C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands
C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands/gpio
C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands/emif25
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/nands/spi
C6X_C_DIR+= ;$(IBL_ROOT)/hw/i2c
C6X_C_DIR+= ;$(IBL_ROOT)/hw/sgmii
C6X_C_DIR+= ;$(IBL_ROOT)/hw/cpsw
C6X_C_DIR+= ;$(IBL_ROOT)/hw/cpdma
C6X_C_DIR+= ;$(IBL_ROOT)/hw/pa
+C6X_C_DIR+= ;$(IBL_ROOT)/hw/spi
C6X_C_DIR+= ;$(IBL_ROOT)/ecc
export C6X_C_DIR
vpath % $(ECODIR)/macs/cpmacsl
vpath % $(ECODIR)/ddrs/emif4
vpath % $(ECODIR)/nands/emif25
+ vpath % $(ECODIR)/nands/spi
+ vpath % $(ECODIR)/spi
endif
index 3801a154ff0c4c0aeeb33faf179b75277e0bb5fc..878da613f4b2918a4667e50532404538edbc96c3 100644 (file)
v = v | (1 << (gCs + 8 - 2));
DEVICE_REG32_W (DEVICE_EMIF25_BASE + NAND_FLASH_CTL_REG, v);
- nandHwDriverReadBytes (block, page, i << 8, 256, data);
+ nandHwDriverReadBytes (block, page, i << 8, 256, blockp);
/* Read the ECC value computed by the hardware */
v = DEVICE_REG32_R (DEVICE_EMIF25_BASE + NAND_FLASH_ECC_REG(gCs));
index 8042dc92b087ef50b2afed279045af0454163ee1..44ac03a9d9e406c19fddad40c269fab5fcf7738c 100644 (file)
--- a/src/hw/nands/nandhwapi.h
+++ b/src/hw/nands/nandhwapi.h
#define NAND_INVALID_ADDR -812
#define NAND_ECC_FAILURE -813
#define NAND_INVALID_CS -814
+#define NAND_READ_FAILURE -815
/* Information used only for programming flash */
-/* Driver functions */
+/* Driver functions, EMIF and GPIO interface */
Int32 nandHwDriverInit (int32 cs, nandDevInfo_t *devInfo);
Int32 nandHwDriverReadBytes (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, Uint8 *data);
Int32 nandHwDriverReadPage(Uint32 block, Uint32 page, Uint8 *data);
Int32 nandHwDriverWritePage (Uint32 block, Uint32 page, Uint8 *data, nandProgramInfo_t *winfo);
Int32 nandHwDriverBlockErase (Uint32 uiBlockNumber, nandProgramInfo_t *winfo);
+/* Driver functions, SPI interface */
+Int32 nandHwSpiDriverInit (int32 cs, nandDevInfo_t *devInfo);
+Int32 nandHwSpiDriverReadBytes (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, Uint8 *data);
+Int32 nandHwSpiDriverReadPage(Uint32 block, Uint32 page, Uint8 *data);
+Int32 nandHwSpiDriverClose (void);
+
diff --git a/src/hw/nands/spi/nandspi.c b/src/hw/nands/spi/nandspi.c
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+#include "types.h"
+#include "ibl.h"
+#include "iblcfg.h"
+#include "nandhwapi.h"
+#include "ecc.h"
+#include "target.h"
+#include "spi_api.h"
+
+nandDevInfo_t *hwSpiDevInfo; /* Pointer to the NAND configuration */
+
+/**
+ * @brief
+ * Initialize the NAND SPI configuration. The SPI interface
+ * must be initialized seperately at a higher level
+ */
+Int32 nandHwSpiDriverInit (int32 cs, nandDevInfo_t *devInfo)
+{
+
+ hwSpiDevInfo = devInfo;
+
+ return (0);
+
+}
+
+
+/**
+ * @brief
+ * Read bytes without ECC correction
+ */
+Int32 nandHwSpiDriverReadBytes (Uint32 block, Uint32 page, Uint32 byte, Uint32 nbytes, uint8 *data)
+{
+ Uint32 uAddr;
+
+ uAddr = (block << hwSpiDevInfo->blockOffset) + (page << hwSpiDevInfo->pageOffset) +
+ (byte << hwSpiDevInfo->columnOffset);
+
+
+ if (hwSpiRead (uAddr, nbytes, data) != 0)
+ return (-1);
+
+ return (0);
+
+}
+
+
+/**
+ * @brief
+ * Read a complete page of data
+ */
+Int32 nandHwSpiDriverReadPage (Uint32 block, Uint32 page, Uint8 *data)
+{
+ Int32 i;
+ Int32 nSegs;
+ Uint8 *blockp;
+ Uint8 *eccp;
+ Uint8 eccCalc[3];
+
+
+ /* Read the entire page, including the extra bytes. The array data
+ * has been sized to handle the full page */
+ if (nandHwSpiDriverReadBytes (block, page, 0, hwSpiDevInfo->pageSizeBytes + hwSpiDevInfo->pageEccBytes, data))
+ return (NAND_READ_FAILURE);
+
+
+
+ /* Break the page into segments of 256 bytes for ECC correction */
+ nSegs = hwSpiDevInfo->pageSizeBytes >> 8;
+
+ for (i = 0; i < nSegs; i++) {
+
+ blockp = &data[i << 8];
+ eccp = &data[hwSpiDevInfo->pageSizeBytes + hwSpiDevInfo->pageEccBytes - ((nSegs - i) * 3)];
+ eccComputeECC (blockp, eccCalc);
+
+ if (eccCorrectData (blockp, eccp, eccCalc) != ECC_SUCCESS)
+ return (NAND_ECC_FAILURE);
+
+ }
+
+ return (0);
+
+}
+
+/**
+ * @brief
+ * Close the driver
+ */
+int32 nandHwSpiDriverClose (void)
+{
+ return (0);
+
+}
+
+
+
+
+
diff --git a/src/hw/spi/spi.c b/src/hw/spi/spi.c
--- /dev/null
+++ b/src/hw/spi/spi.c
@@ -0,0 +1,260 @@
+/**********************************************************************************************
+ * FILE PURPOSE: The SPI boot driver
+ **********************************************************************************************
+ * FILE NAME: spi.c
+ *
+ * DESCRIPTION: Implements an SPI eeprom read.
+ *
+ **********************************************************************************************/
+#include "types.h"
+#include "device.h"
+#include "spi_api.h"
+#include "spi_loc.h"
+
+typedef struct spimcb_s
+{
+ spiConfig_t spiCfg;
+
+} spimcb_t;
+
+spimcb_t spimcb;
+
+
+/**********************************************************************************************
+ * FUNCTION PURPOSE: Initialize the SPI interface
+ **********************************************************************************************
+ * DESCRIPTION: The SPI interface is setup. Only format register 0 is configured
+ **********************************************************************************************/
+SINT16 hwSpiConfig (spiConfig_t *cfg)
+{
+ UINT32 v;
+
+ if ((cfg->addrWidth != 24) && (cfg->addrWidth != 16))
+ return (SPI_INVALID_ADDR_WIDTH);
+
+ if ((cfg->npin != 4) && (cfg->npin != 5))
+ return (SPI_INVALID_NPIN);
+
+ /* Store the configuration for subsequent reads */
+ spimcb.spiCfg = *cfg;
+
+
+ /* Reset */
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_RESET);
+
+ /* Release Reset */
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIGCR0, SPI_REG_VAL_SPIGCR0_ENABLE);
+
+ /* Master mode */
+ if (cfg->npin == 4)
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIPC0, SPI_REG_VAL_SPIPC0_4PIN);
+ else
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIPC0, SPI_REG_VAL_SPIPC0_5PIN);
+
+ /* Format 0 register */
+ v = 0;
+ if (cfg->clkdiv > 0)
+ SPI_REG_SPIFMT_SET_PRESCALE(v, cfg->clkdiv - 1);
+ else
+ SPI_REG_SPIFMT_SET_PRESCALE(v, 0);
+
+ SPI_REG_SPIFMT_SET_CHARLEN(v, 8);
+ SPI_REG_SPIFMT_SET_MODE(v, cfg->mode);
+ SPI_REG_SPIFMT_SET_SHIFTDIR(v, SPI_REG_VAL_SPIFMT_SHIFT_MSB_FIRST);
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIFMT(0), v);
+
+ /* Chip select to transmit delay */
+ v = 0;
+ SPI_REG_SPIDELAY_SET_C2T(v, cfg->c2tdelay);
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIDELAY, v);
+
+
+ return (0);
+
+} /* hwSpiConfig */
+
+
+/*************************************************************************************************
+ * FUNCTION PURPOSE: Perform an SPI transfer
+ *************************************************************************************************
+ * DESCRIPTION: A bi-directional transfer is done
+ *************************************************************************************************/
+SINT16 hw_spi_xfer (UINT16 nbytes, UINT8 *dataOut, UINT8 *dataIn, spiConfig_t *cfg, BOOL terminate)
+{
+ UINT32 v;
+ UINT32 i;
+ UINT32 tcount;
+ UINT32 timeout;
+ UINT32 spidat1;
+
+
+ /* The SPIDAT1 upper 16 bits */
+ spidat1 = 0;
+ SPI_REG_SPIDAT1_SET_CSHOLD(spidat1, 1);
+ SPI_REG_SPIDAT1_SET_WDELAY(spidat1, 1);
+ SPI_REG_SPIDAT1_SET_CSNR(spidat1, cfg->csel);
+
+
+ /* The timeout is used to prevent traps.
+ *
+ * Each bit on the SPI bus will clock in at MOD_DIVIDER * cfg->clkdiv
+ * cpu cycles. So the timeout is based on the MOD_DIVIDER * cfg->clkdiv
+ * product. The actual number of cycles the loop takes isnt known
+ * with too much accuracy since the code is in C, so assume the
+ * compiler is spectacular and condenses each loop into just one
+ * cpu cycle. In that case it would take MOD_DIVIDER * cfg->clkdiv * 8
+ * passes through the loop to get the data byte. Since the compiler
+ * is slower then that the timeout value is good. But an extra
+ * x20 is thrown in just to be safe. */
+
+ timeout = (cfg->clkdiv + 1) * 8 * 20 * DEVICE_SPI_MOD_DIVIDER;
+
+
+ /* Clear out any pending read data */
+ do {
+ v = DEVICE_REG32_R (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIBUF);
+ v = DEVICE_REG32_R (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIFLG);
+ } while (SPI_REG_SPIFLG_RX_DATA(v));
+
+
+ /* Perform the transfer */
+ for (i = 0; i < nbytes; i++) {
+
+
+ /* For the last byte release the hold */
+ if ((terminate == TRUE) && (i == (nbytes - 1))) {
+ SPI_REG_SPIDAT1_SET_CSHOLD(spidat1, 0);
+ }
+
+ tcount = 0;
+
+ do {
+
+ v = DEVICE_REG32_R (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIFLG);
+ tcount += 1;
+
+ } while ( (SPI_REG_SPIFLG_TX_EMPTY(v) == 0) && (tcount < timeout) );
+
+ if (tcount >= timeout) {
+
+ /* Disable transfer */
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIGCR1, SPI_REG_VAL_SPIGCR1_XFER_DISABLE);
+
+ return (SPI_TIMEOUT);
+ }
+
+ if (dataOut != NULL)
+ v = dataOut[i];
+ else
+ v = 0;
+
+
+ /* Send the data */
+ SPI_REG_SPIDAT1_SET_DATA(spidat1, v);
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIDAT1, spidat1);
+
+ /* Receive the data */
+ tcount = 0;
+
+ do {
+
+ v = DEVICE_REG32_R (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIFLG);
+ tcount += 1;
+
+ } while ( (SPI_REG_SPIFLG_RX_DATA(v) == 0) && (tcount < timeout) );
+
+ if (tcount >= timeout) {
+
+ /* Disable transfer */
+ DEVICE_REG32_W (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIGCR1, SPI_REG_VAL_SPIGCR1_XFER_DISABLE);
+
+ return (SPI_TIMEOUT);
+ }
+
+
+ v = DEVICE_REG32_R (DEVICE_SPI_BASE(cfg->port) + SPI_REG_SPIBUF);
+
+ if (dataIn != NULL)
+ dataIn[i] = v & 0xff;
+
+
+ }
+
+ return (0);
+
+}
+
+
+
+
+/*************************************************************************************************
+ * FUNCTION PURPOSE: Read a block of data
+ *************************************************************************************************
+ * DESCRIPTION: A single data block of a fixed size is read
+ *************************************************************************************************/
+SINT16 hwSpiRead (UINT32 addr, UINT16 sizeBytes, UINT8 *data)
+{
+ UINT32 n;
+ UINT8 command[4];
+ UINT16 ret;
+
+ /* Do nothing for a read of 0 bytes */
+ if (sizeBytes == 0)
+ return (0);
+
+ /* Format the read command and address */
+ command[0] = SPI_COMMAND_READ;
+ if (spimcb.spiCfg.addrWidth == 24) {
+ n = 4;
+ command[1] = (addr >> 16) & 0xff;
+ command[2] = (addr >> 8) & 0xff;
+ command[3] = addr & 0xff;
+
+ } else if (spimcb.spiCfg.addrWidth == 16) {
+ n = 3;
+ command[1] = (addr >> 8) & 0xff;
+ command[2] = addr & 0xff;
+
+ } else {
+ return (SPI_INVALID_ADDR_WIDTH);
+ }
+
+
+ /* Enable the device for transfer */
+ DEVICE_REG32_W (DEVICE_SPI_BASE(spimcb.spiCfg.port) + SPI_REG_SPIGCR1, SPI_REG_VAL_SPIGCR1_XFER);
+
+ /* Send the command and address */
+ ret = hw_spi_xfer (n, command, NULL, &spimcb.spiCfg, FALSE);
+ if (ret != 0)
+ return (ret);
+
+
+ /* Read the data */
+ ret = hw_spi_xfer (sizeBytes, NULL, data, &spimcb.spiCfg, TRUE);
+ if (ret != 0)
+ return (ret);
+
+
+ DEVICE_REG32_W (DEVICE_SPI_BASE(spimcb.spifg.port) + SPI_REG_SPIGCR1, SPI_REG_VAL_SPIGCR1_XFER_DISABLE);
+ return (0);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hw/spi/spi_api.h b/src/hw/spi/spi_api.h
--- /dev/null
+++ b/src/hw/spi/spi_api.h
@@ -0,0 +1,39 @@
+#ifndef _SPI_API_H
+#define _SPI_API_H
+/*****************************************************************************************************
+ * FILE PURPOSE: Define the boot SPI driver
+ *****************************************************************************************************
+ * DESCRIPTION: The SPI API is defined
+ *
+ *****************************************************************************************************/
+
+typedef struct spiConfig_s {
+
+ UINT16 port;
+ UINT16 mode;
+ UINT16 addrWidth;
+ UINT16 npin;
+ UINT16 csel;
+ UINT16 clkdiv;
+ UINT16 c2tdelay;
+
+} spiConfig_t;
+
+SINT16 hwSpiConfig (spiConfig_t *spiCfg);
+SINT16 hwSpiRead (UINT32 addr, UINT16 sizeBytes, UINT8 *data);
+
+/* Return values */
+#define SPI_INVALID_ADDR_WIDTH -1
+#define SPI_INVALID_NPIN -2
+#define SPI_TIMEOUT -3
+#define SPI_NOT_ENOUGH_BYTES -4
+
+
+
+
+
+#endif /* _SPI_API_H */
+
+
+
+
diff --git a/src/hw/spi/spi_loc.h b/src/hw/spi/spi_loc.h
--- /dev/null
+++ b/src/hw/spi/spi_loc.h
@@ -0,0 +1,55 @@
+#ifndef _SPI_LOC_H
+#define _SPI_LOC_H
+/************************************************************************************************
+ * FILE PURPOSE: LOCAL SPI definitions
+ ************************************************************************************************
+ * FILE NAME: spi_loc.h
+ *
+ * DESCRIPTION: Defines the SPI hardware operation
+ *
+ ************************************************************************************************/
+
+/* Register offsets */
+#define SPI_REG_SPIGCR0 0x00
+#define SPI_REG_SPIGCR1 0x04
+#define SPI_REG_SPIFLG 0x10
+#define SPI_REG_SPIPC0 0x14
+#define SPI_REG_SPIDAT1 0x3c
+#define SPI_REG_SPIBUF 0x40
+#define SPI_REG_SPIDELAY 0x48
+#define SPI_REG_SPIFMT(x) (0x50 + ((x)*4))
+
+/* Register values */
+#define SPI_REG_VAL_SPIGCR0_RESET 0x0
+#define SPI_REG_VAL_SPIGCR0_ENABLE 0x1
+
+#define SPI_REG_VAL_SPIGCR1_XFER 0x01000003
+#define SPI_REG_VAL_SPIGCR1_XFER_DISABLE 0
+
+#define SPI_REG_SPIFLG_TX_EMPTY(v) ((v) & 0x0200)
+#define SPI_REG_SPIFLG_RX_DATA(v) ((v) & 0x0100)
+
+#define SPI_REG_VAL_SPIPC0_4PIN 0x01010e01 /* 1 pin input, 1 pin output, clock, cs0 */
+#define SPI_REG_VAL_SPIPC0_5PIN 0x01010e03 /* Same as 3 pin with cs1 as well */
+
+#define SPI_REG_SPIFMT_SET_PRESCALE(v, dev) (v) = BOOT_SET_BITFIELD((v),dev, 15, 8)
+#define SPI_REG_SPIFMT_SET_CHARLEN(v, wid) (v) = BOOT_SET_BITFIELD((v),wid, 4, 0)
+#define SPI_REG_SPIFMT_SET_MODE(v, mode) (v) = BOOT_SET_BITFIELD((v),mode, 17, 16)
+#define SPI_REG_SPIFMT_SET_SHIFTDIR(v, dir) (v) = BOOT_SET_BITFIELD((v),dir, 20, 20)
+
+#define SPI_REG_VAL_SPIFMT_SHIFT_MSB_FIRST 0
+
+
+#define SPI_REG_SPIDELAY_SET_C2T(v, delay) (v) = BOOT_SET_BITFIELD((v), delay, 31, 24)
+
+
+#define SPI_REG_SPIDAT1_SET_CSHOLD(v, hold) (v) = BOOT_SET_BITFIELD((v), hold, 28, 28)
+#define SPI_REG_SPIDAT1_SET_WDELAY(v, delay) (v) = BOOT_SET_BITFIELD((v), delay, 26, 26)
+#define SPI_REG_SPIDAT1_SET_CSNR(v, csel) (v) = BOOT_SET_BITFIELD((v), csel, 23, 16)
+#define SPI_REG_SPIDAT1_SET_DATA(v, data) (v) = BOOT_SET_BITFIELD((v), data, 15, 0)
+
+
+/* Commands */
+#define SPI_COMMAND_READ 3
+
+#endif /* _SPI_LOC_H */
diff --git a/src/ibl.h b/src/ibl.h
index 0ab5f75c59ed16d6f911c97eeceb2336f07febf1..d09fbfabf0f3e89e3a9b22b510281eedeb907d71 100644 (file)
--- a/src/ibl.h
+++ b/src/ibl.h
uint32 nandPriority; /**< The nand boot priority. @ref iblPeriphPriority */
int32 bootFormat; /**< The format of the boot data file. @ref iblBootFormats */
- int32 cs; /**< The nand chip select space */
+ int32 interface; /**< The nand interface @ref iblNandIf */
iblBinBlob_t blob; /**< Used only if the format is ibl_BOOT_FORMAT_BBLOB */
nandDevInfo_t nandInfo; /** Low level device info */
} iblNand_t;
+
+/**
+ * @defgroup iblNandIf defines the interface used for NAND memory. Not all values
+ * are valid for all devices.
+ *
+ * @ingroup iblNandIf
+ * @{
+ */
+/** @def ibl_NAND_IF_GPIO - GPIO interface */
+#define ibl_NAND_IF_GPIO 0
+
+/** @def ibl_NAND_IF_CHIPSEL_2 - EMIF interface using chip select 2 */
+#define ibl_NAND_IF_CHIPSEL_2 2
+
+/** @def ibl_NAND_IF_CHIPSEL_3 - EMIF interface using chip select 3 */
+#define ibl_NAND_IF_CHIPSEL_3 3
+
+/** @def ibl_NAND_IF_CHIPSEL_4 - EMIF interface using chip select 4 */
+#define ibl_NAND_IF_CHIPSEL_4 4
+
+/** @def ibl_NAND_IF_CHIPSEL_5 - EMIF interface using chip select 5 */
+#define ibl_NAND_IF_CHIPSEL_5 5
+
+/** @def ibl_NAND_IF_SPI - NAND interface through SPI */
+#define ibl_NAND_IF_SPI 100
+
+
+/* @} */
+
+
+/**
+ * @brief
+ * SPI configuration used for either NOR or NAND
+ */
+typedef struct iblSpi_s
+{
+ int16 addrWidth; /**< 16 or 24 are the only valid values */
+ int16 nPins; /**< 4 or 5 are the only valid values */
+ int16 mode; /**< Clock / data polarities (valid values 0-3) */
+ int16 csel; /**< Chip select value (5 pin). Only 0b10 and 0b01 are valid */
+ uint16 c2tdelay; /**< Setup time between chip select and the transaction */
+ uint16 busFreqMHz; /**< Bus speed */
+
+} iblSpi_t;
+
/**
iblNand_t nandConfig; /**< NAND configuration @ref iblNand_t */
- uint16 chkSum; /**< Ones complement checksum over the whole config structure */
+ iblSpi_t spiConfig; /**< SPI configuration @ref iblSpi_s */
+ uint16 chkSum; /**< Ones complement checksum over the whole config structure */
-/* iblI2c_t i2cConfig; */
-/* iblSpi_t spiConfig; */
} ibl_t;
*/
#define ibl_FAIL_CODE_PA 702 /**< Packet Accelerator setup failed */
+
+/**
+ * @def ibl_FAIL_CODE_SPI_PARAMS
+ */
+#define ibl_FAIL_CODE_SPI_PARAMS 703 /**< Invalid SPI configuration found */
/* @} */
diff --git a/src/main/iblinit.c b/src/main/iblinit.c
index 0e81aebf0666d5b2d1bcfee8e5342b040beac6f3..c39999962a4b3a140fb67e7ed42c06734569b5a9 100644 (file)
--- a/src/main/iblinit.c
+++ b/src/main/iblinit.c
ibl.nandConfig.nandPriority = swap32val (ibl.nandConfig.nandPriority);
ibl.nandConfig.bootFormat = swap32val (ibl.nandConfig.bootFormat);
+ ibl.nandConfig.interface = swap32val (ibl.nandConfig.interface);
ibl.nandConfig.blob.startAddress = swap32val (ibl.nandConfig.blob.startAddress);
ibl.nandConfig.blob.sizeBytes = swap32val (ibl.nandConfig.blob.sizeBytes);
ibl.nandConfig.blob.branchAddress = swap32val (ibl.nandConfig.blob.branchAddress);
ibl.nandConfig.nandInfo.columnOffset = swap32val (ibl.nandConfig.nandInfo.columnOffset);
ibl.nandConfig.nandInfo.postCommand = swap16val (ibl.nandConfig.nandInfo.postCommand);
+ ibl.spiConfig.addrWidth = swap16val (ibl.spiConfig.addrWidth);
+ ibl.spiConfig.nPins = swap16val (ibl.spiConfig.nPins);
+ ibl.spiConfig.csel = swap16val (ibl.spiConfig.csel);
+ ibl.spiConfig.c2tdelay = swap16val (ibl.spiConfig.c2tdelay);
+ ibl.spiConfig.busFreqMHz = swap16val (ibl.spiConfig.busFreqMHz);
+
ibl.chkSum = swap16val (ibl.chkSum);
}
diff --git a/src/make/Makefile b/src/make/Makefile
index a6108f1a1437d4e89209e9f22ef8d308976cf333..67c6a38a93528ae2d7beda0296a58d6964c3b7a4 100644 (file)
--- a/src/make/Makefile
+++ b/src/make/Makefile
make -f makestg1 ARCH=c64x TARGET=c6457 I2C_BUS_ADDR=0x51 COMPACT_I2C=yes ENDIAN_MODE=big EXCLUDES='ELF NAND BIS' I2C_SIZE_BYTES=0x8000 c6457
cp ibl_c6457/i2crom.dat ibl_c6457/i2crom_0x51.dat
+# The 6618 EVM
+evm_c6618:
+ make -f makestg1 ARCH=c64x TARGET=c661x I2C_BUS_ADDR=0x50 ENDIAN_MODE=little EXCLUDES= DEBUG=YES c661x
+
# Test - builds all the targets, with single component exclusion
test_build:
make -f makestg1 ARCH=c64x TARGET=c6455 I2C_BUS_ADDR=0x50 COMPACT_I2C=no ENDIAN_MODE=both EXCLUDES= c6455
index ae2b82e3e5df95787eb95558911a80507027d466..c619ddc0b3b0b36dc908791be8046b3efe91dc7f 100644 (file)
#ifndef EXCLUDE_NAND
../nandboot/c64x/make/nandboot.ENDIAN_TAG.oc
-../hw/c64x/make/nandemif25.ENDIAN_TAG.oc
../driver/c64x/make/nand.ENDIAN_TAG.oc
../ecc/c64x/make/3byte_ecc.ENDIAN_TAG.oc
+
+ #ifndef EXCLUDE_NAND_EMIF
+ ../hw/c64x/make/nandemif25.ENDIAN_TAG.oc
+ #endif
+
+ #ifndef EXCLUDE_NAND_SPI
+ ../hw/c64x/make/nandspi.ENDIAN_TAG.oc
+ #endif
+
+#endif
+
+#ifndef EXCLUDE_SPI
+../hw/c64x/make/spi.ENDIAN_TAG.oc
#endif
index 0443787a7e97410e25f4be274cc2ff8c45259220..63b69434d92493beeb4e20a5e88cbed28a92b9db 100644 (file)
# The PLL object files are device specific
PLL_PATH= ../../hw/c64x/make
ifeq ($(TARGET),c661x)
- PLL_OBJS= $(PLL_PATH)/pll.$(IEXT).oc $(PLL_PATH)/cfgpll.$(IEXT).oc $(PLL_PATH)/cfgpll2.$(IEXT).oc
+ PLL_OBJS= $(PLL_PATH)/pll.$(IEXT).oc $(PLL_PATH)/cfgpll.$(IEXT).oc $(PLL_PATH)/cfgpll2.$(IEXT).oc
+ PLL_OBJS+= ../../device/c64x/make/c64x.$(IEXT).oa
else
PLL_OBJS= $(PLL_PATH)/pll.$(IEXT).oc
endif
index 77e3288a29d3fcd364062fb2881ea8290d99278c..ab47afb4607fde77f7a0e0034fd113e8bd69a12d 100644 (file)
# The PLL object files are device specific
PLL_PATH= ../../hw/c64x/make
ifeq ($(TARGET),c661x)
- PLL_OBJS= $(PLL_PATH)/pll.$(IEXT).oc $(PLL_PATH)/cfgpll.$(IEXT).oc $(PLL_PATH)/cfgpll2.$(IEXT).oc
+ PLL_OBJS= $(PLL_PATH)/pll.$(IEXT).oc $(PLL_PATH)/cfgpll.$(IEXT).oc $(PLL_PATH)/cfgpll2.$(IEXT).oc
+ PLL_OBJS+= ../../device/c64x/make/c64x.$(IEXT).oa
else
PLL_OBJS= $(PLL_PATH)/pll.$(IEXT).oc
endif