17eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/*
27eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * spi-uart debug routings
37eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * Copyright (C) 2008, Feng Tang <feng.tang@intel.com> Intel Corporation.
47eac544cd39f0d9070b977eff43d18360ed2b553Alek Du *
57eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * This program is free software; you can redistribute it and/or modify it
67eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * under the terms and conditions of the GNU General Public License,
77eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * version 2, as published by the Free Software Foundation.
87eac544cd39f0d9070b977eff43d18360ed2b553Alek Du *
97eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * This program is distributed in the hope it will be useful, but WITHOUT
107eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
117eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
127eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * more details.
137eac544cd39f0d9070b977eff43d18360ed2b553Alek Du *
147eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * You should have received a copy of the GNU General Public License along with
157eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * this program; if not, write to the Free Software Foundation, Inc.,
167eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
177eac544cd39f0d9070b977eff43d18360ed2b553Alek Du *
187eac544cd39f0d9070b977eff43d18360ed2b553Alek Du */
197eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
207eac544cd39f0d9070b977eff43d18360ed2b553Alek Du#include "spi-uart.h"
21a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du#include "bootstub.h"
227eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
237eac544cd39f0d9070b977eff43d18360ed2b553Alek Du#define MRST_SPI_TIMEOUT	0x200000
24c8496d189ca8e443b6a56e66e4069a0dbe694941Alek Dustatic int spi_inited = 0;
25aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernstint no_uart_used = 0;
26a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Dustatic volatile struct mrst_spi_reg *pspi = 0;
277eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
287eac544cd39f0d9070b977eff43d18360ed2b553Alek Dustatic void spi_init()
297eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{
307eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	u32 ctrlr0;
31438855bcdd65afc849689f334bc2c7e870301573Jacob Pan	u32 *clk_reg, clk_cdiv;
327eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
33a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du	switch (*(int *)SPI_TYPE) {
34aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst	case SPI_1:
35aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst		if (mid_identify_cpu() == MID_CPU_CHIP_CLOVERVIEW)
364c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai			pspi = (struct mrst_spi_reg *)CTP_REGBASE_SPI1;
374c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai		else
384c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai			pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI1;
39a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du		break;
40aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst
41aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst	case SPI_0:
42a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du	default:
43aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst		if (mid_identify_cpu() == MID_CPU_CHIP_CLOVERVIEW)
444c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai			pspi = (struct mrst_spi_reg *)CTP_REGBASE_SPI0;
454c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai		else
464c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai			pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI0;
47a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du	}
48aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst
497eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	/* disable SPI controller first */
507eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	pspi->ssienr = 0x0;
517eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
527eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	/* set control param, 16 bits, transmit only mode */
537eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	ctrlr0 = pspi->ctrlr0;
547eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
557eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	ctrlr0 &= 0xfcc0;
567eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	ctrlr0 |= (0xf | (FRF_SPI << SPI_FRF_OFFSET)
577eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		       | (TMOD_TO << SPI_TMOD_OFFSET));
587eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	pspi->ctrlr0 = ctrlr0;
597eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
607eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	/* set a default baud rate, 115200 */
61438855bcdd65afc849689f334bc2c7e870301573Jacob Pan	/* get SPI controller operating freq info */
62438855bcdd65afc849689f334bc2c7e870301573Jacob Pan	clk_reg = (u32 *)MRST_CLK_SPI0_REG;
63438855bcdd65afc849689f334bc2c7e870301573Jacob Pan	clk_cdiv  = ((*clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
64438855bcdd65afc849689f334bc2c7e870301573Jacob Pan	pspi->baudr = MRST_SPI_CLK_BASE / (clk_cdiv + 1) / 115200;
657eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
667eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	/* disable all INT for early phase */
677eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	pspi->imr &= 0xffffff00;
687eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
697eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	/* select one slave SPI device */
703f5527f01970ef108b0b3e2463ecc04bb277acbcAlek Du	pspi->ser = 0x2;
717eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
727eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	/* enable the HW, this should be the last step for HW init */
737eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	pspi->ssienr |= 0x1;
747eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
757eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	spi_inited = 1;
76aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst
777eac544cd39f0d9070b977eff43d18360ed2b553Alek Du}
787eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
797eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/* set the ratio rate, INT */
807eac544cd39f0d9070b977eff43d18360ed2b553Alek Dustatic void max3110_write_config(void)
817eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{
827eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	u16 config;
837eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
847eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	/* 115200, TM not set, no parity, 8bit word */
85b7b3000b47443bd625f6bad0a89ce5b86d2b5b3dAlek Du	config = 0xc001;
867eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	pspi->dr[0] = config;
877eac544cd39f0d9070b977eff43d18360ed2b553Alek Du}
887eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
897eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/* transfer char to a eligibal word and send to max3110 */
90c8496d189ca8e443b6a56e66e4069a0dbe694941Alek Dustatic void max3110_write_data(char c)
917eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{
927eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	u16 data;
937eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
947eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	data = 0x8000 | c;
957eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	pspi->dr[0] = data;
967eac544cd39f0d9070b977eff43d18360ed2b553Alek Du}
977eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
987eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/* slave select should be called in the read/write function */
997eac544cd39f0d9070b977eff43d18360ed2b553Alek Dustatic int spi_max3110_putc(char c)
1007eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{
1017eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	unsigned int timeout;
1027eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	u32 sr;
1037eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
1047eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	timeout = MRST_SPI_TIMEOUT;
105a24ea5cfb4209b37f8d42f9ed5584ae9cce85bfcAlek Du	/* early putc need make sure the TX FIFO is not full*/
1067eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	while (timeout--) {
1077eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		sr = pspi->sr;
108a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du		if (!(sr & SR_TF_NOT_FULL))
1097eac544cd39f0d9070b977eff43d18360ed2b553Alek Du			continue;
1107eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		else
1117eac544cd39f0d9070b977eff43d18360ed2b553Alek Du			break;
1127eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	}
1137eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
1147eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	if (timeout == 0xffffffff)
1157eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		return -1;
1167eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
1177eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	max3110_write_data(c);
1187eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
1197eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	return 0;
1207eac544cd39f0d9070b977eff43d18360ed2b553Alek Du}
1217eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
1227eac544cd39f0d9070b977eff43d18360ed2b553Alek Duvoid bs_spi_printk(const char *str)
1237eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{
124aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst	if ( no_uart_used )
125aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst		return;
126aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst
127a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du	if (!spi_inited) {
1287eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		spi_init();
129a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du		max3110_write_config();
130a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du	}
1317eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
1327eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	if (!str)
1337eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		return;
1347eac544cd39f0d9070b977eff43d18360ed2b553Alek Du
1357eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	while (*str) {
1367eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		if (*str == '\n')
1377eac544cd39f0d9070b977eff43d18360ed2b553Alek Du			spi_max3110_putc('\r');
1387eac544cd39f0d9070b977eff43d18360ed2b553Alek Du		spi_max3110_putc(*str++);
1397eac544cd39f0d9070b977eff43d18360ed2b553Alek Du	}
1407eac544cd39f0d9070b977eff43d18360ed2b553Alek Du}
141