* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+/* SPEAr Serial Memory Interface (SMI) controller is a SPI bus controller
+ * specifically designed for SPI memories.
+ * Only SPI "mode 3" (CPOL=1 and CPHA=1) is supported.
+ * Two working modes are available:
+ * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
+ * on the bus.
+ * - HW mode: the SPI but is under SMI control. Memory content is directly
+ * accessible in CPU memory space. CPU can read, write and execute memory
+ * content. */
+
/* ATTENTION:
* To have flash memory mapped in CPU memory space, the SMI controller
* have to be in "HW mode". This requires following constraints:
#endif
#include "imp.h"
-#include "spearsmi.h"
#include <jtag/jtag.h>
#include <helper/time_support.h>
#define SMI_PROBE_TIMEOUT (100)
#define SMI_MAX_TIMEOUT (3000)
+struct spearsmi_flash_bank
+{
+ int probed;
+ uint32_t io_base;
+ uint32_t bank_num;
+ struct flash_device *dev;
+};
+
/* data structure to maintain flash ids from different vendors */
struct flash_device {
char *name;
.size_in_bytes = size \
}
+/* List below is taken from Linux driver. It is not exhaustive of all the
+ * possible SPI memories, nor exclusive for SMI. Could be shared with
+ * other SPI drivers. */
static struct flash_device flash_devices[] = {
/* name, erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
FLASH_ID("st m25p05", 0xd8, 0x00102020, 0x80, 0x8000, 0x10000),
return ERROR_FLASH_OPERATION_FAILED;
}
+/* Read the status register of the external SPI flash chip.
+ * The operation is triggered by setting SMI_RSR bit.
+ * SMI sends the proper SPI command (0x05) and returns value in SMI_SR */
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
{
struct target *target = bank->target;
/* clear transmit finished flag */
SMI_CLEAR_TFF();
- /* Check write enabled */
*status = SMI_READ_REG(SMI_SR) & 0x0000ffff;
/* clean-up SMI_CR2 */
return ERROR_FAIL;
}
+/* Send "write enable" command to SPI flash chip.
+ * The operation is triggered by setting SMI_WE bit, and SMI sends
+ * the proper SPI command (0x06) */
static int smi_write_enable(struct flash_bank *bank)
{
struct target *target = bank->target;
/* clear transmit finished flag */
SMI_CLEAR_TFF();
- /* send erase command */
+ /* send SPI command "block erase" */
cmd = erase_command(spearsmi_info, bank->sectors[sector].offset);
SMI_WRITE_REG(SMI_TR, cmd);
SMI_WRITE_REG(SMI_CR2, spearsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4);
/* clear transmit finished flag */
SMI_CLEAR_TFF();
- /* Require read flash ID */
+ /* Send SPI command "read ID" */
SMI_WRITE_REG(SMI_TR, SMI_READ_ID);
SMI_WRITE_REG(SMI_CR2,
spearsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1);
/* clear transmit finished flag */
SMI_CLEAR_TFF();
- /* read ID */
+ /* read ID from Receive Register */
*id = SMI_READ_REG(SMI_RR) & 0x00ffffff;
return ERROR_OK;
}
if (retval != ERROR_OK)
return retval;
+ spearsmi_info->dev = NULL;
for (struct flash_device *p = flash_devices; p->name ; p++)
if (p->device_id == id) {
spearsmi_info->dev = p;