blob: 21448b9143bc15df46b3d6a7c410e5a976e9a2d7 [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"
Alek Dua8cef7f2009-06-04 15:02:03 +080021#include "bootstub.h"
Alek Du7eac5442008-06-05 17:38:56 +080022
23#define MRST_SPI_TIMEOUT 0x200000
Alek Duc8496d12008-07-10 14:46:17 +080024static int spi_inited = 0;
Alek Dua8cef7f2009-06-04 15:02:03 +080025static volatile struct mrst_spi_reg *pspi = 0;
Alek Du7eac5442008-06-05 17:38:56 +080026
27static void spi_init()
28{
29 u32 ctrlr0;
Jacob Pan438855b2009-08-20 12:37:15 -070030 u32 *clk_reg, clk_cdiv;
Alek Du7eac5442008-06-05 17:38:56 +080031
Alek Dua8cef7f2009-06-04 15:02:03 +080032 switch (*(int *)SPI_TYPE) {
33 case 0:
34 pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI0;
35 break;
36 case 1:
37 pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI1;
38 break;
39 default:
40 pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI0;
41 }
Alek Du7eac5442008-06-05 17:38:56 +080042 /* disable SPI controller first */
43 pspi->ssienr = 0x0;
44
45 /* set control param, 16 bits, transmit only mode */
46 ctrlr0 = pspi->ctrlr0;
47
48 ctrlr0 &= 0xfcc0;
49 ctrlr0 |= (0xf | (FRF_SPI << SPI_FRF_OFFSET)
50 | (TMOD_TO << SPI_TMOD_OFFSET));
51 pspi->ctrlr0 = ctrlr0;
52
53 /* set a default baud rate, 115200 */
Jacob Pan438855b2009-08-20 12:37:15 -070054 /* get SPI controller operating freq info */
55 clk_reg = (u32 *)MRST_CLK_SPI0_REG;
56 clk_cdiv = ((*clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET;
57 pspi->baudr = MRST_SPI_CLK_BASE / (clk_cdiv + 1) / 115200;
Alek Du7eac5442008-06-05 17:38:56 +080058
Alek Du7eac5442008-06-05 17:38:56 +080059 /* disable all INT for early phase */
60 pspi->imr &= 0xffffff00;
61
62 /* select one slave SPI device */
Alek Du3f5527f2008-06-17 14:08:35 +080063 pspi->ser = 0x2;
Alek Du7eac5442008-06-05 17:38:56 +080064
65 /* enable the HW, this should be the last step for HW init */
66 pspi->ssienr |= 0x1;
67
68 spi_inited = 1;
69}
70
71/* set the ratio rate, INT */
72static void max3110_write_config(void)
73{
74 u16 config;
75
76 /* 115200, TM not set, no parity, 8bit word */
Alek Dub7b30002008-08-21 09:49:20 +080077 config = 0xc001;
Alek Du7eac5442008-06-05 17:38:56 +080078 pspi->dr[0] = config;
79}
80
81/* transfer char to a eligibal word and send to max3110 */
Alek Duc8496d12008-07-10 14:46:17 +080082static void max3110_write_data(char c)
Alek Du7eac5442008-06-05 17:38:56 +080083{
84 u16 data;
Alek Du7eac5442008-06-05 17:38:56 +080085
86 data = 0x8000 | c;
87 pspi->dr[0] = data;
Alek Du7eac5442008-06-05 17:38:56 +080088}
89
90/* slave select should be called in the read/write function */
91static int spi_max3110_putc(char c)
92{
93 unsigned int timeout;
94 u32 sr;
Alek Du7eac5442008-06-05 17:38:56 +080095
96 timeout = MRST_SPI_TIMEOUT;
Alek Dua24ea5c2009-05-26 09:56:47 +080097 /* early putc need make sure the TX FIFO is not full*/
Alek Du7eac5442008-06-05 17:38:56 +080098 while (timeout--) {
99 sr = pspi->sr;
Alek Dua8cef7f2009-06-04 15:02:03 +0800100 if (!(sr & SR_TF_NOT_FULL))
Alek Du7eac5442008-06-05 17:38:56 +0800101 continue;
102 else
103 break;
104 }
105
106 if (timeout == 0xffffffff)
107 return -1;
108
109 max3110_write_data(c);
110
111 return 0;
112}
113
Alek Du7eac5442008-06-05 17:38:56 +0800114void bs_spi_printk(const char *str)
115{
Alek Dua8cef7f2009-06-04 15:02:03 +0800116 if (!spi_inited) {
Alek Du7eac5442008-06-05 17:38:56 +0800117 spi_init();
Alek Dua8cef7f2009-06-04 15:02:03 +0800118 max3110_write_config();
119 }
Alek Du7eac5442008-06-05 17:38:56 +0800120
121 if (!str)
122 return;
123
Alek Du7eac5442008-06-05 17:38:56 +0800124 while (*str) {
125 if (*str == '\n')
126 spi_max3110_putc('\r');
127 spi_max3110_putc(*str++);
128 }
129}