blob: 42cf8b469a2e6e85c50d23b3a2df4f6a7d3e2d6f [file] [log] [blame]
Alek Du7eac5442008-06-05 17:38:56 +08001/*
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
22#define MRST_SPI_TIMEOUT 0x200000
Alek Duc8496d12008-07-10 14:46:17 +080023static int spi_inited = 0;
Alek Du7eac5442008-06-05 17:38:56 +080024static struct mrst_spi_reg *pspi = 0;
25
26static void spi_init()
27{
28 u32 ctrlr0;
29
30 pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI0;
31
32 /* disable SPI controller first */
33 pspi->ssienr = 0x0;
34
35 /* set control param, 16 bits, transmit only mode */
36 ctrlr0 = pspi->ctrlr0;
37
38 ctrlr0 &= 0xfcc0;
39 ctrlr0 |= (0xf | (FRF_SPI << SPI_FRF_OFFSET)
40 | (TMOD_TO << SPI_TMOD_OFFSET));
41 pspi->ctrlr0 = ctrlr0;
42
43 /* set a default baud rate, 115200 */
44 /* feng, need make sure SPIC and MAXIM3110 match */
45 //spi_enable_clk(32);
Alek Dub7b30002008-08-21 09:49:20 +080046 pspi->baudr = 2;
Alek Du7eac5442008-06-05 17:38:56 +080047
48 /* need set the transmit threshhol? */
Feng Tang0d20f9c2008-11-20 17:20:56 +080049 /* pspi->txftlr = 0x3; */
Alek Du7eac5442008-06-05 17:38:56 +080050
51 /* disable all INT for early phase */
52 pspi->imr &= 0xffffff00;
53
54 /* select one slave SPI device */
Alek Du3f5527f2008-06-17 14:08:35 +080055 pspi->ser = 0x2;
Alek Du7eac5442008-06-05 17:38:56 +080056
57 /* enable the HW, this should be the last step for HW init */
58 pspi->ssienr |= 0x1;
59
60 spi_inited = 1;
61}
62
63/* set the ratio rate, INT */
64static void max3110_write_config(void)
65{
66 u16 config;
67
68 /* 115200, TM not set, no parity, 8bit word */
Alek Dub7b30002008-08-21 09:49:20 +080069 config = 0xc001;
Alek Du7eac5442008-06-05 17:38:56 +080070 pspi->dr[0] = config;
71}
72
Alek Duc883a5c2008-10-21 14:21:35 +080073static void spi_uart_delay(volatile unsigned int loops)
74{
75 while (loops--);
76}
77
Alek Du7eac5442008-06-05 17:38:56 +080078/* transfer char to a eligibal word and send to max3110 */
Alek Duc8496d12008-07-10 14:46:17 +080079static void max3110_write_data(char c)
Alek Du7eac5442008-06-05 17:38:56 +080080{
81 u16 data;
Alek Du7eac5442008-06-05 17:38:56 +080082
Alek Duc883a5c2008-10-21 14:21:35 +080083 spi_uart_delay(0x8000);
Alek Du7eac5442008-06-05 17:38:56 +080084 data = 0x8000 | c;
85 pspi->dr[0] = data;
Alek Duc883a5c2008-10-21 14:21:35 +080086 spi_uart_delay(0x8000);
Alek Du7eac5442008-06-05 17:38:56 +080087}
88
89/* slave select should be called in the read/write function */
90static int spi_max3110_putc(char c)
91{
92 unsigned int timeout;
93 u32 sr;
94 u32 test;
95
96 /* read RX FIFO out if there is any */
97 while ((pspi->sr & SR_RF_NOT_EMPT) && pspi->rxflr ) {
98 timeout = MRST_SPI_TIMEOUT;
99 while (timeout--) {
100 if (!(pspi->sr & SR_BUSY))
101 break;
102 }
103
104 if (timeout == 0xffffffff)
105 return -1;
106 test = pspi->dr[0];
107 }
108
109 timeout = MRST_SPI_TIMEOUT;
110 /* early putc need make sure the TX FIFO is empty */
111 while (timeout--) {
112 sr = pspi->sr;
113 if ( (sr & SR_BUSY) || !(sr & SR_TF_EMPT))
114 continue;
115 else
116 break;
117 }
118
119 if (timeout == 0xffffffff)
120 return -1;
121
122 max3110_write_data(c);
123
124 return 0;
125}
126
127
128void bs_spi_printk(const char *str)
129{
130 if (!spi_inited)
131 spi_init();
132
133 if (!str)
134 return;
135
136 /*
137 * here we assume only 1 write_config is enough,
138 * if not will call it for each putc
139 */
140 max3110_write_config();
141
142 while (*str) {
143 if (*str == '\n')
144 spi_max3110_putc('\r');
145 spi_max3110_putc(*str++);
146 }
147}