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