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/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++);
+	}
+}