SSP: Added SPI UART via SSP5

BZ: 114933

Merrifield uses SPI via SSP rather than a dedicated SPI peripheral
Moved volatile definitions to types.h

Based off code by Courtney A. Drant

Change-Id: I3a8fbe364f2fcf860ac47f431b93868fb7b598d9
Signed-off-by: Mark F. Brown <mark.f.brown@intel.com>
Signed-off-by: Courtney A. Drant <courtney.a.drant@intel.com>
Reviewed-on: http://android.intel.com:8080/112531
Reviewed-by: Fourdan, Olivier <olivier.fourdan@intel.com>
Tested-by: Fourdan, Olivier <olivier.fourdan@intel.com>
Reviewed-by: Fert, Laurent <laurent.fert@intel.com>
Reviewed-by: cactus <cactus@intel.com>
Tested-by: cactus <cactus@intel.com>
diff --git a/Makefile b/Makefile
index 1d0944a..8f3ed29 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-OBJ=bootstub.o spi-uart.o head.o sfi.o e820_bios.o
+OBJ=bootstub.o spi-uart.o head.o sfi.o e820_bios.o ssp-uart.o
 CMDLINE_SIZE ?= 0x400
 CFLAGS=-m32 -ffreestanding -Wall -DCMDLINE_SIZE=${CMDLINE_SIZE}
 CC ?= gcc
@@ -20,6 +20,9 @@
 spi-uart.o:spi-uart.c spi-uart.h
 	${CC} $(CFLAGS) -c spi-uart.c
 
+ssp-uart.o:ssp-uart.c ssp-uart.h
+	${CC} $(CFLAGS) -c ssp-uart.c
+
 sfi.o:sfi.c
 	${CC} $(CFLAGS) -c sfi.c
 
diff --git a/bootstub.c b/bootstub.c
index fb1d765..435910d 100644
--- a/bootstub.c
+++ b/bootstub.c
@@ -23,10 +23,9 @@
 #include "bootstub.h"
 #include "bootparam.h"
 #include "spi-uart.h"
+#include "ssp-uart.h"
 #include "sfi.h"
 
-#define bs_printk(x) { if (! *(int *)SPI_UART_SUPPRESSION) bs_spi_printk(x);}
-
 extern int no_uart_used;
 
 static void *memcpy(void *dest, const void *src, size_t count)
@@ -149,6 +148,10 @@
 		return MID_CPU_CHIP_CLOVERVIEW;
 	case VALLEYVIEW2_FAMILY:
 		return MID_CPU_CHIP_VALLEYVIEW2;
+	case TANGIER_FAMILY:
+		return MID_CPU_CHIP_TANGIER;
+	case ANNIEDALE_FAMILY:
+		return MID_CPU_CHIP_ANNIEDALE;
 	default:
 		return MID_CPU_CHIP_OTHER;
 	}
@@ -169,6 +172,16 @@
 			bs_printk("CLV detected\n");
 			break;
 
+		case MID_CPU_CHIP_TANGIER:
+			*(int *)SPI_TYPE = SPI_2;
+			bs_printk("MRD detected\n");
+			break;
+
+		case MID_CPU_CHIP_ANNIEDALE:
+			*(int *)SPI_TYPE = SPI_2;
+			bs_printk("ANN detected\n");
+			break;
+
 		case MID_CPU_CHIP_VALLEYVIEW2:
 		case MID_CPU_CHIP_OTHER:
 		default:
@@ -186,3 +199,20 @@
 	bs_printk("Jump to kernel 32bit entry ...\n");
 	return get_32bit_entry((unsigned char *)BZIMAGE_OFFSET);
 }
+
+void bs_printk(const char *str)
+{
+	if (*(int *)SPI_UART_SUPPRESSION)
+		return;
+
+	switch (*(int *)SPI_TYPE) {
+
+	case SPI_1:
+                bs_spi_printk(str);
+                break;
+
+        case SPI_2:
+                bs_ssp_printk(str);
+                break;
+	}
+}
diff --git a/bootstub.h b/bootstub.h
index 8db1690..21b08bb 100644
--- a/bootstub.h
+++ b/bootstub.h
@@ -8,11 +8,15 @@
 #define PENWELL_FAMILY		0x20670
 #define CLOVERVIEW_FAMILY	0x30650
 #define VALLEYVIEW2_FAMILY	0x30670
+#define TANGIER_FAMILY		0x406A0
+#define ANNIEDALE_FAMILY	0x506A0
 
 #define MID_CPU_CHIP_LINCROFT	1
 #define MID_CPU_CHIP_PENWELL	2
 #define MID_CPU_CHIP_CLOVERVIEW 3
 #define MID_CPU_CHIP_VALLEYVIEW2 4
+#define MID_CPU_CHIP_TANGIER	5
+#define MID_CPU_CHIP_ANNIEDALE	6
 #define MID_CPU_CHIP_OTHER		0xFF
 
 #define CMDLINE_OFFSET		0x1100000
@@ -22,6 +26,7 @@
 #define SPI_TYPE		(SPI_UART_SUPPRESSION + 4) /*0:SPI0  1:SPI1*/
 #define SPI_0		0
 #define SPI_1		1
+#define SPI_2		2
 
 #define STACK_OFFSET		0x1101000
 #define BZIMAGE_OFFSET		0x1102000
@@ -53,6 +58,7 @@
          ((u64)(limit & 0x0000ffff)))
 int get_e820_by_bios(void *e820_buf);
 int mid_identify_cpu(void);
+void bs_printk(const char *str);
 #endif
 
 #endif
diff --git a/sfi.c b/sfi.c
index 1b75c9e..f5e5656 100644
--- a/sfi.c
+++ b/sfi.c
@@ -23,8 +23,6 @@
 #include "spi-uart.h"
 #include "sfi.h"
 
-#define bs_printk(x) { if (!*(int *)SPI_UART_SUPPRESSION) bs_spi_printk(x); }
-
 #define SFI_BASE_ADDR		0x000E0000
 #define SFI_LENGTH		0x00020000
 
diff --git a/spi-uart.h b/spi-uart.h
index 21bedd1..69f0f17 100644
--- a/spi-uart.h
+++ b/spi-uart.h
@@ -5,9 +5,6 @@
 
 #include "types.h"
 
-typedef volatile unsigned short vu16;
-typedef volatile unsigned int	vu32;
-
 #define MRST_REGBASE_SPI0	0xff128000
 #define MRST_REGBASE_SPI1	0xff128400
 #define MRST_REGBASE_SPI2	0xff128800
diff --git a/ssp-uart.c b/ssp-uart.c
new file mode 100644
index 0000000..7a379dc
--- /dev/null
+++ b/ssp-uart.c
@@ -0,0 +1,77 @@
+/*
+ * ssp-uart.c SPI via SSP
+ * Copyright (C) 2011, Mark F. Brown <mark.f.brown@intel.com> Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "ssp-uart.h"
+#include "bootstub.h"
+
+#define SSP_TIMEOUT	0xAFF
+#define SSP_SLAVE	0x02 /* Slave select */
+#define SSP_SSCR0	0x00C0008F
+#define SSP_SSCR1	0x10000000
+
+static int ssp_inited = 0;
+static volatile struct ssp_reg *pspi = 0;
+
+#define WRITE_DATA                  (2<<14)
+
+static void ssp_init()
+{
+	pspi = (struct ssp_reg*)TNG_SSP5_ADDR_BASE;
+	pspi->SSPx_SSFS = SSP_SLAVE;
+	pspi->SSPx_SSCR1 = SSP_SSCR1;
+	pspi->SSPx_SSCR0 = SSP_SSCR0;
+
+	ssp_inited = 1;
+}
+
+static void ssp_max3110_putc(char c)
+{
+	vu32 SSCR0 = 0;
+	vu32 i;
+
+	pspi = (struct ssp_reg*)TNG_SSP5_ADDR_BASE;
+	SSCR0 = (WRITE_DATA | c);
+	pspi->SSPx_SSDR = SSCR0;
+
+	for (i = 0; i < SSP_TIMEOUT; i++)
+	{
+		SSCR0 = pspi->SSPx_SSSR;
+		if ((SSCR0 & 0xF00) == 0) break;
+	}
+
+	SSCR0 = pspi->SSPx_SSDR;
+}
+
+void bs_ssp_printk(const char *str)
+{
+	if (!str)
+		return;
+
+	if (!ssp_inited)
+	{
+		ssp_init();
+	}
+
+	while (*str) {
+		if (*str == '\n')
+			ssp_max3110_putc('\r');
+
+		ssp_max3110_putc(*str++);
+	}
+}
diff --git a/ssp-uart.h b/ssp-uart.h
new file mode 100644
index 0000000..8ae6863
--- /dev/null
+++ b/ssp-uart.h
@@ -0,0 +1,32 @@
+#ifndef _SSP_UART
+#define _SSP_UART
+
+#include "types.h"
+
+#define TNG_SSP5_ADDR_BASE      0xFF189000
+
+struct ssp_reg {
+	vu32 SSPx_SSCR0;      // 0x00
+	vu32 SSPx_SSCR1;      // 0x04
+	vu32 SSPx_SSSR;       // 0x08
+	vu32 SSPx_SSITR;      // 0x0C
+	vu32 SSPx_SSDR;       // 0x10
+	vu32 SSPx_DUMMY1;     //0x14
+	vu32 SSPx_DUMMY2;     //0x18
+	vu32 SSPx_DUMMY3;     //0x1c
+	vu32 SSPx_DUMMY4;     //0x20
+	vu32 SSPx_DUMMY5;     //0x24
+	vu32 SSPx_SSTO;       // 0x28
+	vu32 SSPx_SSPSP;      // 0x2C
+	vu32 SSPx_SSTSA;      // 0x30
+	vu32 SSPx_SSRSA;      // 0x34
+	vu32 SSPx_SSTSS;      // 0x38
+	vu32 SSPx_SSACD;      // 0x3C
+	vu32 SSPx_SSCR2;      // 0x40
+	vu32 SSPx_SSFS;       // 0x44
+	vu32 SSPx_FRAME_CNT;  // 0x48
+};
+
+extern void bs_ssp_printk(const char *str);
+
+#endif
diff --git a/types.h b/types.h
index b84de8e..5983418 100644
--- a/types.h
+++ b/types.h
@@ -17,4 +17,7 @@
 
 typedef unsigned int size_t;
 
+typedef volatile unsigned short vu16;
+typedef volatile unsigned int	vu32;
+
 #endif