Home | History | Annotate | Download | only in bootstub
      1 /*
      2  * spi-uart debug routings
      3  * Copyright (C) 2008, Feng Tang <feng.tang (at) 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 
     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 */
     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 */
     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 */
     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 
    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