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>
This commit is contained in:
Vadim Bendebury 2014-04-23 14:00:59 -07:00 committed by Marc Jones
parent 4f062ae381
commit f17680b23c
2 changed files with 156 additions and 120 deletions

View File

@ -1,25 +1,22 @@
/* * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.* */ /* * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.* */
#include <common.h> #include <types.h>
#include <linux/mtd/ipq_nand.h> #include <cdp.h>
#include <asm/arch-ipq806x/gpio.h> #include <gpio.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/arch-ipq806x/clock.h>
#include <asm/arch-ipq806x/ebi2.h>
#include <asm/arch-ipq806x/smem.h>
#include <asm/errno.h>
#include "ipq806x_board_param.h"
#include "ipq806x_cdp.h"
#include <asm/arch-ipq806x/nss/msm_ipq806x_gmac.h>
#include <asm/arch-ipq806x/timer.h>
#include <nand.h>
#include <phy.h>
DECLARE_GLOBAL_DATA_PTR; void ipq_configure_gpio(const gpio_func_data_t *gpio, unsigned count)
{
int i;
for (i = 0; i < count; i++) {
gpio_tlmm_config(gpio->gpio, gpio->func, gpio->dir,
gpio->pull, gpio->drvstr, gpio->enable);
gpio++;
}
}
#if 0
/* Watchdog bite time set to default reset value */ /* Watchdog bite time set to default reset value */
#define RESET_WDT_BITE_TIME 0x31F3 #define RESET_WDT_BITE_TIME 0x31F3
@ -354,17 +351,6 @@ int get_eth_mac_address(uchar *enetaddr, uint no_of_macs)
return ret; return ret;
} }
void ipq_configure_gpio(gpio_func_data_t *gpio, uint count)
{
int i;
for (i = 0; i < count; i++) {
gpio_tlmm_config(gpio->gpio, gpio->func, gpio->dir,
gpio->pull, gpio->drvstr, gpio->enable);
gpio++;
}
}
int board_eth_init(bd_t *bis) int board_eth_init(bd_t *bis)
{ {
int status; int status;
@ -377,3 +363,4 @@ int board_eth_init(bd_t *bis)
status = ipq_gmac_init(gboard_param->gmac_cfg); status = ipq_gmac_init(gboard_param->gmac_cfg);
return status; return status;
} }
#endif

View File

@ -31,16 +31,56 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include <arch/io.h>
#include <common.h> #include <boot/coreboot_tables.h>
#include <asm/arch-ipq806x/gsbi.h> #include <console/console.h>
#include <asm/arch-ipq806x/clock.h> #include <delay.h>
#include <asm/arch-ipq806x/uart.h> #include <clock.h>
#include <serial.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 #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); 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) static unsigned int msm_boot_uart_dm_init_rx_transfer(unsigned int uart_dm_base)
{ {
/* Reset receiver */ /* 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)); MSM_BOOT_UART_DM_CR(uart_dm_base));
/* Enable receiver */ /* 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)); 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)); MSM_BOOT_UART_DM_DMRX(uart_dm_base));
/* Clear stale event */ /* 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)); MSM_BOOT_UART_DM_CR(uart_dm_base));
/* Enable stale event */ /* 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)); MSM_BOOT_UART_DM_CR(uart_dm_base));
return MSM_BOOT_UART_DM_E_SUCCESS; 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 * 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. * @wait is true, else returns %MSM_BOOT_UART_DM_E_RX_NOT_READY.
*/ */
#if 0 /* Not used yet */
static unsigned int static unsigned int
msm_boot_uart_dm_read(unsigned int *data, int *count, int wait) 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; unsigned int base = 0;
uint32_t status_reg; uint32_t status_reg;
base = gboard_param->uart_dm_base; base = uart_board_param.uart_dm_base;
if (data == NULL) if (data == NULL)
return MSM_BOOT_UART_DM_E_INVAL; 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 */ /* Check for DM_RXSTALE for RX transfer to finish */
while (!(status_reg & MSM_BOOT_UART_DM_RXSTALE)) { 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) if (!wait)
return MSM_BOOT_UART_DM_E_RX_NOT_READY; return MSM_BOOT_UART_DM_E_RX_NOT_READY;
} }
/* Check for Overrun error. We'll just reset Error Status */ /* 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) { 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)); MSM_BOOT_UART_DM_CR(base));
total_rx_data = rx_data_read = 0; total_rx_data = rx_data_read = 0;
msm_boot_uart_dm_init(base); 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 */ /* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */
if (total_rx_data == 0) 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 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 */ /* WAR for http://prism/CR/548280 */
if (*data == 0) { 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; return MSM_BOOT_UART_DM_E_SUCCESS;
} }
#endif
/** /**
* msm_boot_uart_replace_lr_with_cr - replaces "\n" with "\r\n" * 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. * "\r\n". Currently keeping it simple than efficient.
*/ */
static unsigned int 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, int num_of_chars,
char *data_out, int *num_of_chars_out) 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. * till space becomes available.
*/ */
static unsigned int 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_word_count = 0;
unsigned int tx_char_left = 0, tx_char = 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; int i = 0;
char *tx_data = NULL; char *tx_data = NULL;
char new_data[1024]; 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)) if ((data == NULL) || (num_of_chars <= 0))
return MSM_BOOT_UART_DM_E_INVAL; 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. /* Check if transmit FIFO is empty.
* If not we'll wait for TX_READY interrupt. */ * If not we'll wait for TX_READY interrupt. */
if (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXEMT)) { if (!(readl_i(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)) while (!(readl_i(MSM_BOOT_UART_DM_ISR(base)) &
__udelay(1); MSM_BOOT_UART_DM_TX_READY))
udelay(1);
} }
/* We are here. FIFO is ready to be written. */ /* We are here. FIFO is ready to be written. */
/* Write number of characters 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 */ /* 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 /* We use four-character word FIFO. So we need to divide data into
* four characters and write in UART_DM_TF register */ * 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); PACK_CHARS_INTO_WORDS(tx_data, tx_char, tx_word);
/* Wait till TX FIFO has space */ /* Wait till TX FIFO has space */
while (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXRDY)) while (!(readl_i(MSM_BOOT_UART_DM_SR(base)) &
__udelay(1); MSM_BOOT_UART_DM_SR_TXRDY))
udelay(1);
/* TX FIFO has space. Write the chars */ /* 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_char_left = num_of_chars - (i + 1) * 4;
tx_data = tx_data + 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) 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_i(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_i(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_i(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT,
writel(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(base)); 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_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; 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 */ /* Configure UART mode registers MR1 and MR2 */
/* Hardware flow control isn't supported */ /* 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 */ /* 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 */ /* 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 * Configure Tx and Rx watermarks configuration registers
* TX watermark value is set to 0 - interrupt is generated when * TX watermark value is set to 0 - interrupt is generated when
* FIFO level is less than or equal to 0 * 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 */ /* 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 */ /* Configure Interrupt Programming Register */
/* Set initial Stale timeout value */ /* 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)); MSM_BOOT_UART_DM_IPR(uart_dm_base));
/* Configure IRDA if required */ /* Configure IRDA if required */
/* Disabling IRDA mode */ /* 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 */ /* Configure hunt character value in HCR register */
/* Keep it in reset state */ /* 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 * 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 */ /* Enable/Disable Rx/Tx DM interfaces */
/* Data Mover not currently utilized. */ /* 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 */ /* 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)); MSM_BOOT_UART_DM_CR(uart_dm_base));
/* Initialize Receive Path */ /* 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. * 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; unsigned int dm_base, gsbi_base;
dm_base = gboard_param->uart_dm_base; dm_base = uart_board_param.uart_dm_base;
gsbi_base = gboard_param->uart_gsbi_base; gsbi_base = uart_board_param.uart_gsbi_base;
ipq_configure_gpio(gboard_param->dbg_uart_gpio, NO_OF_DBG_UART_GPIOS); ipq_configure_gpio(uart_board_param.dbg_uart_gpio,
NO_OF_DBG_UART_GPIOS);
/* Configure the uart clock */ /* Configure the uart clock */
uart_clock_config(gboard_param->uart_gsbi, uart_clock_config(uart_board_param.uart_gsbi,
gboard_param->mnd_value.m_value, uart_board_param.mnd_value.m_value,
gboard_param->mnd_value.n_value, uart_board_param.mnd_value.n_value,
gboard_param->mnd_value.d_value, uart_board_param.mnd_value.d_value,
gboard_param->clk_dummy); 0);
writel(GSBI_PROTOCOL_CODE_I2C_UART << writel_i(GSBI_PROTOCOL_CODE_I2C_UART <<
GSBI_CTRL_REG_PROTOCOL_CODE_S, GSBI_CTRL_REG_PROTOCOL_CODE_S,
GSBI_CTRL_REG(gsbi_base)); 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 */ /* Intialize UART_DM */
msm_boot_uart_dm_init(dm_base); 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 * @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); 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 * @s: string to transmit
*/ */
static void ipq806x_serial_puts(const char *s) void uart_tx_flush(int idx)
{ {
while (*s != '\0') unsigned int base = uart_board_param.uart_dm_base;
serial_putc(*s++);
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 * 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 */ /* Return if data is already read */
if (valid_data) if (valid_data)
return 1; return 1;
/* Read data from the FIFO */ /* 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 0;
return 1; return 1;
} }
#endif
/** /**
* ipq806x_serial_getc - reads a character * ipq806x_serial_getc - reads a character
* *
* Returns the character read from serial port. * 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 */ /* wait for incoming data */
} }
#endif
byte = (int)word & 0xff; byte = (uint8_t)(word & 0xff);
word = word >> 8; word = word >> 8;
valid_data--; valid_data--;
return byte; return byte;
} }
#ifndef __PRE_RAM__
static struct serial_device ipq_serial_device = { /* TODO: Implement fuction */
.name = "ipq_serial", void uart_fill_lb(void *data)
.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)
{
serial_register(&ipq_serial_device);
} }
#endif