From 4bbdf966d4afbf279550c7115c64e60d94ca3fe8 Mon Sep 17 00:00:00 2001
From: Antonio Borneo <borneo.antonio@gmail.com>
Date: Wed, 17 Nov 2010 11:28:46 +0800
Subject: STR750: Add SMI interface support

Modified spearsmi driver to include support for STR75x
Added missing initialization in tcl file for STR750

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
---
 src/flash/nor/spearsmi.c | 78 ++++++++++++++++++++++++++----------------------
 tcl/target/str750.cfg    | 12 ++++++++
 2 files changed, 55 insertions(+), 35 deletions(-)

diff --git a/src/flash/nor/spearsmi.c b/src/flash/nor/spearsmi.c
index 5e6a2c47..10b54036 100644
--- a/src/flash/nor/spearsmi.c
+++ b/src/flash/nor/spearsmi.c
@@ -42,8 +42,6 @@
 #include <jtag/jtag.h>
 #include <helper/time_support.h>
 
-#define JTAG_ID_3XX_6XX  (0x07926041)
-
 #define SMI_READ_REG(a) (_SMI_READ_REG(a))
 #define _SMI_READ_REG(a)        	\
 {	                                \
@@ -84,12 +82,6 @@
 
 #define SMI_BANK_SIZE      (0x01000000)
 
-#define SMI_BASE_3XX_6XX   (0xf8000000)
-#define SMI_CFGREG_3XX_6XX (0xfc000000)
-
-/* #define SMI_BASE_13XX      (0xe6000000) */
-/* #define SMI_CFGREG_13XX    (0xea000000) */
-
 #define SMI_CR1 (0x00) /* Control register 1 */
 #define SMI_CR2 (0x04) /* Control register 2 */
 #define SMI_SR  (0x08) /* Status register */
@@ -192,6 +184,20 @@ static struct flash_device flash_devices[] = {
 	FLASH_ID(NULL,             0,    0,          0,     0,       0)
 };
 
+struct spearsmi_target {
+	char *name;
+	uint32_t tap_idcode;
+	uint32_t smi_base;
+	uint32_t io_base;
+};
+
+static struct spearsmi_target target_devices[] = {
+	/* name,          tap_idcode, smi_base,   io_base */
+	{ "SPEAr3xx/6xx", 0x07926041, 0xf8000000, 0xfc000000 },
+	{ "STR75x",       0x4f1f0041, 0x80000000, 0x90000000 },
+	{ NULL,           0,          0,          0 }
+};
+
 FLASH_BANK_COMMAND_HANDLER(spearsmi_flash_bank_command)
 {
 	struct spearsmi_flash_bank *spearsmi_info;
@@ -602,44 +608,46 @@ static int spearsmi_probe(struct flash_bank *bank)
 	uint32_t io_base;
 	struct flash_sector *sectors;
 	uint32_t id = 0; /* silence uninitialized warning */
+	struct spearsmi_target *target_device;
 	int retval;
 
 	if (spearsmi_info->probed)
 		free(bank->sectors);
 	spearsmi_info->probed = 0;
 
-	/* check for SPEAr device */
-	switch (target->tap->idcode)
-	{
-		case JTAG_ID_3XX_6XX:
-			/* SPEAr3xx/6xx */
-			spearsmi_info->io_base = SMI_CFGREG_3XX_6XX;
-			switch (bank->base)
-			{
-				case SMI_BASE_3XX_6XX:
-					spearsmi_info->bank_num = SMI_SEL_BANK0;
-					break;
-				case SMI_BASE_3XX_6XX + SMI_BANK_SIZE:
-					spearsmi_info->bank_num = SMI_SEL_BANK1;
-					break;
-				case SMI_BASE_3XX_6XX + 2*SMI_BANK_SIZE:
-					spearsmi_info->bank_num = SMI_SEL_BANK2;
-					break;
-				case SMI_BASE_3XX_6XX + 3*SMI_BANK_SIZE:
-					spearsmi_info->bank_num = SMI_SEL_BANK3;
-					break;
-				default:
-					LOG_ERROR("Invalid base address 0x%" PRIx32, bank->base);
-					return ERROR_FAIL;
-			}
+	for (target_device=target_devices ; target_device->name ; ++target_device)
+		if (target_device->tap_idcode == target->tap->idcode)
 			break;
+	if (!target_device->name)
+	{
+		LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SMI capable",
+				target->tap->idcode);
+		return ERROR_FAIL;
+	}
 
+	switch (bank->base - target_device->smi_base)
+	{
+		case 0:
+			spearsmi_info->bank_num = SMI_SEL_BANK0;
+			break;
+		case SMI_BANK_SIZE:
+			spearsmi_info->bank_num = SMI_SEL_BANK1;
+			break;
+		case 2*SMI_BANK_SIZE:
+			spearsmi_info->bank_num = SMI_SEL_BANK2;
+			break;
+		case 3*SMI_BANK_SIZE:
+			spearsmi_info->bank_num = SMI_SEL_BANK3;
+			break;
 		default:
-			LOG_ERROR("0x%" PRIx32 " is invalid id for SPEAr device",
-				target->tap->idcode);
+			LOG_ERROR("Invalid SMI base address 0x%" PRIx32, bank->base);
 			return ERROR_FAIL;
 	}
-	io_base = spearsmi_info->io_base;
+	io_base = target_device->io_base;
+	spearsmi_info->io_base = io_base;
+
+	LOG_DEBUG("Valid SMI on device %s at address 0x%" PRIx32,
+		target_device->name, bank->base);
 
 	/* read and decode flash ID; returns in SW mode */
 	retval = read_flash_id(bank, &id);
diff --git a/tcl/target/str750.cfg b/tcl/target/str750.cfg
index 7d9f0343..2fabc126 100644
--- a/tcl/target/str750.cfg
+++ b/tcl/target/str750.cfg
@@ -39,6 +39,7 @@ $_TARGETNAME configure -event reset-start  { adapter_khz 10 }
 $_TARGETNAME configure -event reset-init {
 	adapter_khz 3000
 
+	init_smi
 # Because the hardware cannot be interrogated for the protection state
 # of sectors, initialize all the sectors to be unprotected. The initial
 # state is reflected by the driver, too.
@@ -58,3 +59,14 @@ flash bank $_FLASHNAME str7x 0x20000000 0x00040000 0 0 $_TARGETNAME STR75x
 set _FLASHNAME $_CHIPNAME.flash1
 flash bank $_FLASHNAME str7x 0x200C0000 0x00004000 0 0 $_TARGETNAME STR75x
 
+# Serial NOR on SMI CS0.
+set _FLASHNAME $_CHIPNAME.snor
+flash bank $_FLASHNAME spearsmi 0x80000000 0 0 0 $_TARGETNAME
+
+source [find mem_helper.tcl]
+
+proc init_smi {} {
+	mmw 0x60000030 0x01000000 0x00000000; # enable clock for GPIO regs
+	mmw 0xffffe420 0x00000001 0x00000000; # set SMI_EN bit
+	mmw 0x90000000 0x00000001 0x00000000; # set BLOCK_EN_1
+}
-- 
cgit v1.2.3