1/*
2 * spi-uart debug routings
3 * Copyright (C) 2008, Feng Tang <feng.tang@intel.com> Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include "spi-uart.h"
21#include "bootstub.h"
22
23#define MRST_SPI_TIMEOUT	0x200000
24static int spi_inited = 0;
25int no_uart_used = 0;
26static volatile struct mrst_spi_reg *pspi = 0;
27
28static void spi_init()
29{
30	u32 ctrlr0;
31	u32 *clk_reg, clk_cdiv;
32
33	switch (*(int *)SPI_TYPE) {
34	case SPI_1:
35		if (mid_identify_cpu() == MID_CPU_CHIP_CLOVERVIEW)
36			pspi = (struct mrst_spi_reg *)CTP_REGBASE_SPI1;
37		else
38			pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI1;
39		break;
40
41	case SPI_0:
42	default:
43		if (mid_identify_cpu() == MID_CPU_CHIP_CLOVERVIEW)
44			pspi = (struct mrst_spi_reg *)CTP_REGBASE_SPI0;
45		else
46			pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI0;
47	}
48
49	/* disable SPI controller first */
50	pspi->ssienr = 0x0;
51
52	/* set control param, 16 bits, transmit only mode */
53	ctrlr0 = pspi->ctrlr0;
54
55	ctrlr0 &= 0xfcc0;
56	ctrlr0 |= (0xf | (FRF_SPI << SPI_FRF_OFFSET)
57		       | (TMOD_TO << SPI_TMOD_OFFSET));
58	pspi->ctrlr0 = ctrlr0;
59
60	/* set a default baud rate, 115200 */
61	/* get SPI controller operating freq info */
62	clk_reg = (u32 *)MRST_CLK_SPI0_REG;
63	clk_cdiv  = ((*clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
64	pspi->baudr = MRST_SPI_CLK_BASE / (clk_cdiv + 1) / 115200;
65
66	/* disable all INT for early phase */
67	pspi->imr &= 0xffffff00;
68
69	/* select one slave SPI device */
70	pspi->ser = 0x2;
71
72	/* enable the HW, this should be the last step for HW init */
73	pspi->ssienr |= 0x1;
74
75	spi_inited = 1;
76
77}
78
79/* set the ratio rate, INT */
80static void max3110_write_config(void)
81{
82	u16 config;
83
84	/* 115200, TM not set, no parity, 8bit word */
85	config = 0xc001;
86	pspi->dr[0] = config;
87}
88
89/* transfer char to a eligibal word and send to max3110 */
90static void max3110_write_data(char c)
91{
92	u16 data;
93
94	data = 0x8000 | c;
95	pspi->dr[0] = data;
96}
97
98/* slave select should be called in the read/write function */
99static int spi_max3110_putc(char c)
100{
101	unsigned int timeout;
102	u32 sr;
103
104	timeout = MRST_SPI_TIMEOUT;
105	/* early putc need make sure the TX FIFO is not full*/
106	while (timeout--) {
107		sr = pspi->sr;
108		if (!(sr & SR_TF_NOT_FULL))
109			continue;
110		else
111			break;
112	}
113
114	if (timeout == 0xffffffff)
115		return -1;
116
117	max3110_write_data(c);
118
119	return 0;
120}
121
122void bs_spi_printk(const char *str)
123{
124	if ( no_uart_used )
125		return;
126
127	if (!spi_inited) {
128		spi_init();
129		max3110_write_config();
130	}
131
132	if (!str)
133		return;
134
135	while (*str) {
136		if (*str == '\n')
137			spi_max3110_putc('\r');
138		spi_max3110_putc(*str++);
139	}
140}
141