diff options
Diffstat (limited to 'src/soc/qualcomm')
-rw-r--r-- | src/soc/qualcomm/ipq806x/uart.c | 233 |
1 files changed, 141 insertions, 92 deletions
diff --git a/src/soc/qualcomm/ipq806x/uart.c b/src/soc/qualcomm/ipq806x/uart.c index c65f876821..f7b5d0295e 100644 --- a/src/soc/qualcomm/ipq806x/uart.c +++ b/src/soc/qualcomm/ipq806x/uart.c @@ -31,16 +31,56 @@ * SUCH DAMAGE. */ - -#include <common.h> -#include <asm/arch-ipq806x/gsbi.h> -#include <asm/arch-ipq806x/clock.h> -#include <asm/arch-ipq806x/uart.h> -#include <serial.h> +#include <arch/io.h> +#include <boot/coreboot_tables.h> +#include <console/console.h> +#include <delay.h> +#include <clock.h> +#include <gpio.h> +#include <gsbi.h> +#include <console/uart.h> +#include <ipq_uart.h> +#include <stdint.h> +#include <stdlib.h> #define FIFO_DATA_SIZE 4 -extern board_ipq806x_params_t *gboard_param; +typedef struct { + unsigned uart_dm_base; + unsigned uart_gsbi_base; + unsigned uart_gsbi; + uart_clk_mnd_t mnd_value; + gpio_func_data_t dbg_uart_gpio[NO_OF_DBG_UART_GPIOS]; +} uart_params_t; + +/* + * All constants lifted from u-boot's + * board/qcom/ipq806x_cdp/ipq806x_board_param.h + */ +static const uart_params_t uart_board_param = { + .uart_dm_base = UART4_DM_BASE, + .uart_gsbi_base = UART_GSBI4_BASE, + .uart_gsbi = GSBI_4, + .mnd_value = { 12, 625, 313 }, + .dbg_uart_gpio = { + { + .gpio = 10, + .func = 1, + .dir = GPIO_OUTPUT, + .pull = GPIO_NO_PULL, + .drvstr = GPIO_12MA, + .enable = GPIO_DISABLE + }, + { + .gpio = 11, + .func = 1, + .dir = GPIO_INPUT, + .pull = GPIO_NO_PULL, + .drvstr = GPIO_12MA, + .enable = GPIO_DISABLE + }, + } +}; static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base); @@ -57,21 +97,21 @@ static unsigned int word = 0; static unsigned int msm_boot_uart_dm_init_rx_transfer(unsigned int uart_dm_base) { /* Reset receiver */ - writel(MSM_BOOT_UART_DM_CMD_RESET_RX, + writel_i(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(uart_dm_base)); /* Enable receiver */ - writel(MSM_BOOT_UART_DM_CR_RX_ENABLE, + writel_i(MSM_BOOT_UART_DM_CR_RX_ENABLE, MSM_BOOT_UART_DM_CR(uart_dm_base)); - writel(MSM_BOOT_UART_DM_DMRX_DEF_VALUE, + writel_i(MSM_BOOT_UART_DM_DMRX_DEF_VALUE, MSM_BOOT_UART_DM_DMRX(uart_dm_base)); /* Clear stale event */ - writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, + writel_i(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(uart_dm_base)); /* Enable stale event */ - writel(MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT, + writel_i(MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT, MSM_BOOT_UART_DM_CR(uart_dm_base)); return MSM_BOOT_UART_DM_E_SUCCESS; @@ -86,6 +126,7 @@ static unsigned int msm_boot_uart_dm_init_rx_transfer(unsigned int uart_dm_base) * Reads a word from the RX FIFO. If no data is available blocks if * @wait is true, else returns %MSM_BOOT_UART_DM_E_RX_NOT_READY. */ + #if 0 /* Not used yet */ static unsigned int msm_boot_uart_dm_read(unsigned int *data, int *count, int wait) { @@ -94,24 +135,24 @@ msm_boot_uart_dm_read(unsigned int *data, int *count, int wait) unsigned int base = 0; uint32_t status_reg; - base = gboard_param->uart_dm_base; + base = uart_board_param.uart_dm_base; if (data == NULL) return MSM_BOOT_UART_DM_E_INVAL; - status_reg = readl(MSM_BOOT_UART_DM_MISR(base)); + status_reg = readl_i(MSM_BOOT_UART_DM_MISR(base)); /* Check for DM_RXSTALE for RX transfer to finish */ while (!(status_reg & MSM_BOOT_UART_DM_RXSTALE)) { - status_reg = readl(MSM_BOOT_UART_DM_MISR(base)); + status_reg = readl_i(MSM_BOOT_UART_DM_MISR(base)); if (!wait) return MSM_BOOT_UART_DM_E_RX_NOT_READY; } /* Check for Overrun error. We'll just reset Error Status */ - if (readl(MSM_BOOT_UART_DM_SR(base)) & + if (readl_i(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_UART_OVERRUN) { - writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, + writel_i(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, MSM_BOOT_UART_DM_CR(base)); total_rx_data = rx_data_read = 0; msm_boot_uart_dm_init(base); @@ -120,10 +161,10 @@ msm_boot_uart_dm_read(unsigned int *data, int *count, int wait) /* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */ if (total_rx_data == 0) - total_rx_data = readl(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base)); + total_rx_data = readl_i(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base)); /* Data available in FIFO; read a word. */ - *data = readl(MSM_BOOT_UART_DM_RF(base, 0)); + *data = readl_i(MSM_BOOT_UART_DM_RF(base, 0)); /* WAR for http://prism/CR/548280 */ if (*data == 0) { @@ -149,6 +190,7 @@ msm_boot_uart_dm_read(unsigned int *data, int *count, int wait) return MSM_BOOT_UART_DM_E_SUCCESS; } +#endif /** * msm_boot_uart_replace_lr_with_cr - replaces "\n" with "\r\n" @@ -160,7 +202,7 @@ msm_boot_uart_dm_read(unsigned int *data, int *count, int wait) * "\r\n". Currently keeping it simple than efficient. */ static unsigned int -msm_boot_uart_replace_lr_with_cr(char *data_in, +msm_boot_uart_replace_lr_with_cr(unsigned char *data_in, int num_of_chars, char *data_out, int *num_of_chars_out) { @@ -190,7 +232,7 @@ msm_boot_uart_replace_lr_with_cr(char *data_in, * till space becomes available. */ static unsigned int -msm_boot_uart_dm_write(char *data, unsigned int num_of_chars) +msm_boot_uart_dm_write(unsigned char *data, unsigned int num_of_chars) { unsigned int tx_word_count = 0; unsigned int tx_char_left = 0, tx_char = 0; @@ -198,7 +240,7 @@ msm_boot_uart_dm_write(char *data, unsigned int num_of_chars) int i = 0; char *tx_data = NULL; char new_data[1024]; - unsigned int base = gboard_param->uart_dm_base; + unsigned int base = uart_board_param.uart_dm_base; if ((data == NULL) || (num_of_chars <= 0)) return MSM_BOOT_UART_DM_E_INVAL; @@ -216,17 +258,19 @@ msm_boot_uart_dm_write(char *data, unsigned int num_of_chars) /* Check if transmit FIFO is empty. * If not we'll wait for TX_READY interrupt. */ - if (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXEMT)) { - while (!(readl(MSM_BOOT_UART_DM_ISR(base)) & MSM_BOOT_UART_DM_TX_READY)) - __udelay(1); + if (!(readl_i(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXEMT)) { + while (!(readl_i(MSM_BOOT_UART_DM_ISR(base)) & + MSM_BOOT_UART_DM_TX_READY)) + udelay(1); } /* We are here. FIFO is ready to be written. */ /* Write number of characters to be written */ - writel(num_of_chars, MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base)); + writel_i(num_of_chars, MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base)); /* Clear TX_READY interrupt */ - writel(MSM_BOOT_UART_DM_GCMD_RES_TX_RDY_INT, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_GCMD_RES_TX_RDY_INT, + MSM_BOOT_UART_DM_CR(base)); /* We use four-character word FIFO. So we need to divide data into * four characters and write in UART_DM_TF register */ @@ -239,11 +283,12 @@ msm_boot_uart_dm_write(char *data, unsigned int num_of_chars) PACK_CHARS_INTO_WORDS(tx_data, tx_char, tx_word); /* Wait till TX FIFO has space */ - while (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXRDY)) - __udelay(1); + while (!(readl_i(MSM_BOOT_UART_DM_SR(base)) & + MSM_BOOT_UART_DM_SR_TXRDY)) + udelay(1); /* TX FIFO has space. Write the chars */ - writel(tx_word, MSM_BOOT_UART_DM_TF(base, 0)); + writel_i(tx_word, MSM_BOOT_UART_DM_TF(base, 0)); tx_char_left = num_of_chars - (i + 1) * 4; tx_data = tx_data + 4; } @@ -257,11 +302,12 @@ msm_boot_uart_dm_write(char *data, unsigned int num_of_chars) */ static unsigned int msm_boot_uart_dm_reset(unsigned int base) { - writel(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(base)); - writel(MSM_BOOT_UART_DM_CMD_RESET_TX, MSM_BOOT_UART_DM_CR(base)); - writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, MSM_BOOT_UART_DM_CR(base)); - writel(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(base)); - writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RESET_TX, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, + MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(base)); + writel_i(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(base)); return MSM_BOOT_UART_DM_E_SUCCESS; } @@ -274,36 +320,40 @@ static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base) { /* Configure UART mode registers MR1 and MR2 */ /* Hardware flow control isn't supported */ - writel(0x0, MSM_BOOT_UART_DM_MR1(uart_dm_base)); + writel_i(0x0, MSM_BOOT_UART_DM_MR1(uart_dm_base)); /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */ - writel(MSM_BOOT_UART_DM_8_N_1_MODE, MSM_BOOT_UART_DM_MR2(uart_dm_base)); + writel_i(MSM_BOOT_UART_DM_8_N_1_MODE, + MSM_BOOT_UART_DM_MR2(uart_dm_base)); /* Configure Interrupt Mask register IMR */ - writel(MSM_BOOT_UART_DM_IMR_ENABLED, MSM_BOOT_UART_DM_IMR(uart_dm_base)); + writel_i(MSM_BOOT_UART_DM_IMR_ENABLED, + MSM_BOOT_UART_DM_IMR(uart_dm_base)); /* * Configure Tx and Rx watermarks configuration registers * TX watermark value is set to 0 - interrupt is generated when * FIFO level is less than or equal to 0 */ - writel(MSM_BOOT_UART_DM_TFW_VALUE, MSM_BOOT_UART_DM_TFWR(uart_dm_base)); + writel_i(MSM_BOOT_UART_DM_TFW_VALUE, + MSM_BOOT_UART_DM_TFWR(uart_dm_base)); /* RX watermark value */ - writel(MSM_BOOT_UART_DM_RFW_VALUE, MSM_BOOT_UART_DM_RFWR(uart_dm_base)); + writel_i(MSM_BOOT_UART_DM_RFW_VALUE, + MSM_BOOT_UART_DM_RFWR(uart_dm_base)); /* Configure Interrupt Programming Register */ /* Set initial Stale timeout value */ - writel(MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB, + writel_i(MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB, MSM_BOOT_UART_DM_IPR(uart_dm_base)); /* Configure IRDA if required */ /* Disabling IRDA mode */ - writel(0x0, MSM_BOOT_UART_DM_IRDA(uart_dm_base)); + writel_i(0x0, MSM_BOOT_UART_DM_IRDA(uart_dm_base)); /* Configure hunt character value in HCR register */ /* Keep it in reset state */ - writel(0x0, MSM_BOOT_UART_DM_HCR(uart_dm_base)); + writel_i(0x0, MSM_BOOT_UART_DM_HCR(uart_dm_base)); /* * Configure Rx FIFO base address @@ -318,10 +368,10 @@ static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base) /* Enable/Disable Rx/Tx DM interfaces */ /* Data Mover not currently utilized. */ - writel(0x0, MSM_BOOT_UART_DM_DMEN(uart_dm_base)); + writel_i(0x0, MSM_BOOT_UART_DM_DMEN(uart_dm_base)); /* Enable transmitter */ - writel(MSM_BOOT_UART_DM_CR_TX_ENABLE, + writel_i(MSM_BOOT_UART_DM_CR_TX_ENABLE, MSM_BOOT_UART_DM_CR(uart_dm_base)); /* Initialize Receive Path */ @@ -331,110 +381,109 @@ static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base) } /** - * uart_dm_init - initializes UART + * uart_init - initializes UART * * Initializes clocks, GPIO and UART controller. */ -static int uart_dm_init(void) +void uart_init(int idx) { + /* Note int idx isn't used in this driver. */ unsigned int dm_base, gsbi_base; - dm_base = gboard_param->uart_dm_base; - gsbi_base = gboard_param->uart_gsbi_base; - ipq_configure_gpio(gboard_param->dbg_uart_gpio, NO_OF_DBG_UART_GPIOS); + dm_base = uart_board_param.uart_dm_base; + gsbi_base = uart_board_param.uart_gsbi_base; + ipq_configure_gpio(uart_board_param.dbg_uart_gpio, + NO_OF_DBG_UART_GPIOS); /* Configure the uart clock */ - uart_clock_config(gboard_param->uart_gsbi, - gboard_param->mnd_value.m_value, - gboard_param->mnd_value.n_value, - gboard_param->mnd_value.d_value, - gboard_param->clk_dummy); + uart_clock_config(uart_board_param.uart_gsbi, + uart_board_param.mnd_value.m_value, + uart_board_param.mnd_value.n_value, + uart_board_param.mnd_value.d_value, + 0); - writel(GSBI_PROTOCOL_CODE_I2C_UART << + writel_i(GSBI_PROTOCOL_CODE_I2C_UART << GSBI_CTRL_REG_PROTOCOL_CODE_S, GSBI_CTRL_REG(gsbi_base)); - writel(UART_DM_CLK_RX_TX_BIT_RATE, MSM_BOOT_UART_DM_CSR(dm_base)); + writel_i(UART_DM_CLK_RX_TX_BIT_RATE, MSM_BOOT_UART_DM_CSR(dm_base)); + /* Intialize UART_DM */ msm_boot_uart_dm_init(dm_base); +} - return 0; +#if 0 /* Not used yet */ +uint32_t uartmem_getbaseaddr(void) +{ + return uart_board_param.uart_dm_base; } +#endif /** - * ipq806x_serial_putc - transmits a character + * uart_tx_byte - transmits a character * @c: character to transmit */ -static void ipq806x_serial_putc(char c) +void uart_tx_byte(int idx, unsigned char c) { msm_boot_uart_dm_write(&c, 1); } /** - * ipq806x_serial_puts - transmits a string of data + * uart_tx_flush - transmits a string of data * @s: string to transmit */ -static void ipq806x_serial_puts(const char *s) +void uart_tx_flush(int idx) { - while (*s != '\0') - serial_putc(*s++); + unsigned int base = uart_board_param.uart_dm_base; + + while (!(readl_i(MSM_BOOT_UART_DM_SR(base)) & + MSM_BOOT_UART_DM_SR_TXEMT)) + ; } /** - * ipq806x_serial_tstc - checks if data available for reading + * uart_can_rx_byte - checks if data available for reading * * Returns 1 if data available, 0 otherwise */ -static int ipq806x_serial_tstc(void) + #if 0 /* Not used yet */ +int uart_can_rx_byte(void) { /* Return if data is already read */ if (valid_data) return 1; /* Read data from the FIFO */ - if (msm_boot_uart_dm_read(&word, &valid_data, 0) != MSM_BOOT_UART_DM_E_SUCCESS) + if (msm_boot_uart_dm_read(&word, &valid_data, 0) != + MSM_BOOT_UART_DM_E_SUCCESS) return 0; return 1; } +#endif /** * ipq806x_serial_getc - reads a character * * Returns the character read from serial port. */ -static int ipq806x_serial_getc(void) +uint8_t uart_rx_byte(int idx) { - int byte; + uint8_t byte; - while (!serial_tstc()) { +#if 0 /* Not used yet */ + while (!uart_can_rx_byte()) { /* wait for incoming data */ } - - byte = (int)word & 0xff; +#endif + byte = (uint8_t)(word & 0xff); word = word >> 8; valid_data--; return byte; } - -static struct serial_device ipq_serial_device = { - .name = "ipq_serial", - .start = uart_dm_init, - .getc = ipq806x_serial_getc, - .tstc = ipq806x_serial_tstc, - .putc = ipq806x_serial_putc, - .puts = ipq806x_serial_puts, -}; - -__weak struct serial_device *default_serial_console(void) -{ - return &ipq_serial_device; -} - -/** - * ipq806x_serial_init - initializes serial controller - */ -void ipq806x_serial_initialize(void) +#ifndef __PRE_RAM__ +/* TODO: Implement fuction */ +void uart_fill_lb(void *data) { - serial_register(&ipq_serial_device); } +#endif |