aboutsummaryrefslogtreecommitdiff
path: root/src/soc/qualcomm/ipq806x/uart.c
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2014-04-23 14:00:59 -0700
committerMarc Jones <marc.jones@se-eng.com>2014-12-30 20:18:33 +0100
commitf17680b23c3b334bfbe81a03e08d05e04cc0334e (patch)
tree9eeb5e904e0033301b4d8f53118917962a0270d0 /src/soc/qualcomm/ipq806x/uart.c
parent4f062ae381db3c7e5b1b64ce22db374f63f048d7 (diff)
ipq8064: prepare uart driver for use in coreboot
The IO accessor wrappers are used to allow integer register addresses. A structure defining UART interface configuration is declared and defined. A few long lines are wrapped. Interface functions are renamed to match the wrapper API. cdp.c is edited to fit into coreboot compilation environment, and the only function required by the UART driver if exposed, the rest are compiled out for now. BUG=chrome-os-partner:27784 TEST=after all patches are applied the serial console on AP148 becomes operational. Original-Change-Id: I80c824d085036c0f90c52aad77843e87976dbe49 Original-Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/196662 Original-Reviewed-by: Stefan Reinauer <reinauer@chromium.org> (cherry picked from commit 5e9af53a069cd048334a3a28f0a4ce9df7c96992) Signed-off-by: Marc Jones <marc.jones@se-eng.com> Change-Id: I80c824d085036c0f90c52aad77843e87976dbe49 Reviewed-on: http://review.coreboot.org/7874 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Diffstat (limited to 'src/soc/qualcomm/ipq806x/uart.c')
-rw-r--r--src/soc/qualcomm/ipq806x/uart.c233
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