17eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/* 27eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * spi-uart debug routings 37eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * Copyright (C) 2008, Feng Tang <feng.tang@intel.com> Intel Corporation. 47eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * 57eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * This program is free software; you can redistribute it and/or modify it 67eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * under the terms and conditions of the GNU General Public License, 77eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * version 2, as published by the Free Software Foundation. 87eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * 97eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * This program is distributed in the hope it will be useful, but WITHOUT 107eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 117eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 127eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * more details. 137eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * 147eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * You should have received a copy of the GNU General Public License along with 157eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * this program; if not, write to the Free Software Foundation, Inc., 167eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 177eac544cd39f0d9070b977eff43d18360ed2b553Alek Du * 187eac544cd39f0d9070b977eff43d18360ed2b553Alek Du */ 197eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 207eac544cd39f0d9070b977eff43d18360ed2b553Alek Du#include "spi-uart.h" 21a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du#include "bootstub.h" 227eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 237eac544cd39f0d9070b977eff43d18360ed2b553Alek Du#define MRST_SPI_TIMEOUT 0x200000 24c8496d189ca8e443b6a56e66e4069a0dbe694941Alek Dustatic int spi_inited = 0; 25aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernstint no_uart_used = 0; 26a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Dustatic volatile struct mrst_spi_reg *pspi = 0; 277eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 287eac544cd39f0d9070b977eff43d18360ed2b553Alek Dustatic void spi_init() 297eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{ 307eac544cd39f0d9070b977eff43d18360ed2b553Alek Du u32 ctrlr0; 31438855bcdd65afc849689f334bc2c7e870301573Jacob Pan u32 *clk_reg, clk_cdiv; 327eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 33a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du switch (*(int *)SPI_TYPE) { 34aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst case SPI_1: 35aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst if (mid_identify_cpu() == MID_CPU_CHIP_CLOVERVIEW) 364c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai pspi = (struct mrst_spi_reg *)CTP_REGBASE_SPI1; 374c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai else 384c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI1; 39a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du break; 40aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst 41aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst case SPI_0: 42a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du default: 43aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst if (mid_identify_cpu() == MID_CPU_CHIP_CLOVERVIEW) 444c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai pspi = (struct mrst_spi_reg *)CTP_REGBASE_SPI0; 454c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai else 464c56e4505d7b0f66515667edd56ba49c84b63172Leonard Mai pspi = (struct mrst_spi_reg *)MRST_REGBASE_SPI0; 47a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du } 48aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst 497eac544cd39f0d9070b977eff43d18360ed2b553Alek Du /* disable SPI controller first */ 507eac544cd39f0d9070b977eff43d18360ed2b553Alek Du pspi->ssienr = 0x0; 517eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 527eac544cd39f0d9070b977eff43d18360ed2b553Alek Du /* set control param, 16 bits, transmit only mode */ 537eac544cd39f0d9070b977eff43d18360ed2b553Alek Du ctrlr0 = pspi->ctrlr0; 547eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 557eac544cd39f0d9070b977eff43d18360ed2b553Alek Du ctrlr0 &= 0xfcc0; 567eac544cd39f0d9070b977eff43d18360ed2b553Alek Du ctrlr0 |= (0xf | (FRF_SPI << SPI_FRF_OFFSET) 577eac544cd39f0d9070b977eff43d18360ed2b553Alek Du | (TMOD_TO << SPI_TMOD_OFFSET)); 587eac544cd39f0d9070b977eff43d18360ed2b553Alek Du pspi->ctrlr0 = ctrlr0; 597eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 607eac544cd39f0d9070b977eff43d18360ed2b553Alek Du /* set a default baud rate, 115200 */ 61438855bcdd65afc849689f334bc2c7e870301573Jacob Pan /* get SPI controller operating freq info */ 62438855bcdd65afc849689f334bc2c7e870301573Jacob Pan clk_reg = (u32 *)MRST_CLK_SPI0_REG; 63438855bcdd65afc849689f334bc2c7e870301573Jacob Pan clk_cdiv = ((*clk_reg) & CLK_SPI_CDIV_MASK) >> CLK_SPI_CDIV_OFFSET; 64438855bcdd65afc849689f334bc2c7e870301573Jacob Pan pspi->baudr = MRST_SPI_CLK_BASE / (clk_cdiv + 1) / 115200; 657eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 667eac544cd39f0d9070b977eff43d18360ed2b553Alek Du /* disable all INT for early phase */ 677eac544cd39f0d9070b977eff43d18360ed2b553Alek Du pspi->imr &= 0xffffff00; 687eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 697eac544cd39f0d9070b977eff43d18360ed2b553Alek Du /* select one slave SPI device */ 703f5527f01970ef108b0b3e2463ecc04bb277acbcAlek Du pspi->ser = 0x2; 717eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 727eac544cd39f0d9070b977eff43d18360ed2b553Alek Du /* enable the HW, this should be the last step for HW init */ 737eac544cd39f0d9070b977eff43d18360ed2b553Alek Du pspi->ssienr |= 0x1; 747eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 757eac544cd39f0d9070b977eff43d18360ed2b553Alek Du spi_inited = 1; 76aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst 777eac544cd39f0d9070b977eff43d18360ed2b553Alek Du} 787eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 797eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/* set the ratio rate, INT */ 807eac544cd39f0d9070b977eff43d18360ed2b553Alek Dustatic void max3110_write_config(void) 817eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{ 827eac544cd39f0d9070b977eff43d18360ed2b553Alek Du u16 config; 837eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 847eac544cd39f0d9070b977eff43d18360ed2b553Alek Du /* 115200, TM not set, no parity, 8bit word */ 85b7b3000b47443bd625f6bad0a89ce5b86d2b5b3dAlek Du config = 0xc001; 867eac544cd39f0d9070b977eff43d18360ed2b553Alek Du pspi->dr[0] = config; 877eac544cd39f0d9070b977eff43d18360ed2b553Alek Du} 887eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 897eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/* transfer char to a eligibal word and send to max3110 */ 90c8496d189ca8e443b6a56e66e4069a0dbe694941Alek Dustatic void max3110_write_data(char c) 917eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{ 927eac544cd39f0d9070b977eff43d18360ed2b553Alek Du u16 data; 937eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 947eac544cd39f0d9070b977eff43d18360ed2b553Alek Du data = 0x8000 | c; 957eac544cd39f0d9070b977eff43d18360ed2b553Alek Du pspi->dr[0] = data; 967eac544cd39f0d9070b977eff43d18360ed2b553Alek Du} 977eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 987eac544cd39f0d9070b977eff43d18360ed2b553Alek Du/* slave select should be called in the read/write function */ 997eac544cd39f0d9070b977eff43d18360ed2b553Alek Dustatic int spi_max3110_putc(char c) 1007eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{ 1017eac544cd39f0d9070b977eff43d18360ed2b553Alek Du unsigned int timeout; 1027eac544cd39f0d9070b977eff43d18360ed2b553Alek Du u32 sr; 1037eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 1047eac544cd39f0d9070b977eff43d18360ed2b553Alek Du timeout = MRST_SPI_TIMEOUT; 105a24ea5cfb4209b37f8d42f9ed5584ae9cce85bfcAlek Du /* early putc need make sure the TX FIFO is not full*/ 1067eac544cd39f0d9070b977eff43d18360ed2b553Alek Du while (timeout--) { 1077eac544cd39f0d9070b977eff43d18360ed2b553Alek Du sr = pspi->sr; 108a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du if (!(sr & SR_TF_NOT_FULL)) 1097eac544cd39f0d9070b977eff43d18360ed2b553Alek Du continue; 1107eac544cd39f0d9070b977eff43d18360ed2b553Alek Du else 1117eac544cd39f0d9070b977eff43d18360ed2b553Alek Du break; 1127eac544cd39f0d9070b977eff43d18360ed2b553Alek Du } 1137eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 1147eac544cd39f0d9070b977eff43d18360ed2b553Alek Du if (timeout == 0xffffffff) 1157eac544cd39f0d9070b977eff43d18360ed2b553Alek Du return -1; 1167eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 1177eac544cd39f0d9070b977eff43d18360ed2b553Alek Du max3110_write_data(c); 1187eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 1197eac544cd39f0d9070b977eff43d18360ed2b553Alek Du return 0; 1207eac544cd39f0d9070b977eff43d18360ed2b553Alek Du} 1217eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 1227eac544cd39f0d9070b977eff43d18360ed2b553Alek Duvoid bs_spi_printk(const char *str) 1237eac544cd39f0d9070b977eff43d18360ed2b553Alek Du{ 124aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst if ( no_uart_used ) 125aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst return; 126aecaba3b298855b0ce93f94897a0e2b5269639a7Eric Ernst 127a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du if (!spi_inited) { 1287eac544cd39f0d9070b977eff43d18360ed2b553Alek Du spi_init(); 129a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du max3110_write_config(); 130a8cef7fc4c8686fd903b444b0d1ac0a071d05f5dAlek Du } 1317eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 1327eac544cd39f0d9070b977eff43d18360ed2b553Alek Du if (!str) 1337eac544cd39f0d9070b977eff43d18360ed2b553Alek Du return; 1347eac544cd39f0d9070b977eff43d18360ed2b553Alek Du 1357eac544cd39f0d9070b977eff43d18360ed2b553Alek Du while (*str) { 1367eac544cd39f0d9070b977eff43d18360ed2b553Alek Du if (*str == '\n') 1377eac544cd39f0d9070b977eff43d18360ed2b553Alek Du spi_max3110_putc('\r'); 1387eac544cd39f0d9070b977eff43d18360ed2b553Alek Du spi_max3110_putc(*str++); 1397eac544cd39f0d9070b977eff43d18360ed2b553Alek Du } 1407eac544cd39f0d9070b977eff43d18360ed2b553Alek Du} 141