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
24 static int spi_inited = 0;
25 int no_uart_used = 0;
26 static volatile struct mrst_spi_reg *pspi = 0;
27 
spi_init()28 static 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 */
max3110_write_config(void)80 static 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 */
max3110_write_data(char c)90 static 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 */
spi_max3110_putc(char c)99 static 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 
bs_spi_printk(const char * str)122 void 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