Skip to content

UART driver for Sue Creek #384

Description

@lgirdwood

@zhigang-wu please use this as starting point for UART, it must not block and should use IRQ for Tx/Rx data.

/* * Copyright (c) 2017, Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Intel Corporation nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Author: Zhigang Wu <zhigang.wu@intel.com> */#include<errno.h>#include<reef/io.h>#include<reef/dw-uart.h>/* uart register list */#defineDW_REG_THR	0
#defineDW_REG_RBR	0
#defineDW_REG_BRDL	0
#defineDW_REG_BRDH	4
#defineDW_REG_FCR	8
#defineDW_REG_LCR	12
#defineDW_REG_LSR	20
#defineuart_read(dev, reg)\
io_reg_read(dev->port + reg)
#defineuart_write(dev, reg, value)\
io_reg_write(dev->port + reg, value)
/* lcr register *//* *	0x0 -- 5bits *	0x1 -- 6bits *	0x2 -- 7bits *	0x3 -- 8bits */#defineLCR_DLS(x)	(x << 0)
/* 0-1stop, 1-1.5stop */#defineLCR_STOP(x)	(x << 2)
/* 0-parity disabled, 1-parity enabled */#defineLCR_PEN(x)	(x << 3)
#defineLCR_DLAB_BIT	(1 << 7)
/* fcr register *//* 0-fifo disabled; 1-enabled */#defineFCR_FIFOE(x)	(x << 0)
/* 0-mode0, 1-mode1 */#defineFCR_MODE(x) (x << 3)
#defineFCR_RCVR_RST	(1 << 1
#defineFCR_XMIT_RST	(1 << 2)
/* lsr register */#defineLSR_TEMT	(1 << 2)	/* transmitter empty *//* TODO: this goes in sof/uart.h */structuart*uart {
char*tx_buffer;
char*rx_buffer;
char*tx_read_ptr;	/* read this char into HW */char*tx_write_ptr;	/* write this char into circular buffer */char*rx_read_ptr;
char*rx_write_ptr;
intrx_buffer_size;
inttx_buffer_size;
void*private;
structuart_pdata*pdata;
};
/* TODO: this goes in platform/uart.c */staticstructuart_pdatadw_pdata= {
.baud=1152000,	/* Baud rate */
.port=DW_REG_BASEADDR,
.timeout=DW_TIMEOUT,
};
/* All Tx/Rx is done by IRQ handler */staticintdw_uart_irq(void*data)
{
structuart*uart=data;
/* TODO check we have new data to send *//* check Tx is ready for next char */if (uart_read(dev, DW_REG_LSR) &LSR_TEMT) {
/* write to output reg */uart_write(dev, DW_REG_THR, uart->tx_read_ptr);
/* update tx read ptr and check for wrap */uart->tx_read_ptr++;
if (uart->tx_read_ptr >= uart->rx_buffer+uart->rx_buffer_size)
uart->tx_read_ptr=uart->rx_buffer;
}
/* TODO check Rx HW for new data */
}
staticintdw_uart_write_data(structuart*uart, char*data, intlen)
{
/* TODO copy data to Tx circular buffer */
}
staticintdw_uart_read_data(structuart*uart, char*data, intlen)
{
/* TODO copy data from Rx circular buffer */
}
staticintdw_uart_probe(structuart*uart)
{
structuart_pdata*pdata=uart->pdata;
uint32_tdivisor, tmp;
/* TODO: register IRQ handler for Tx/Rx UART FIFO updates.*/if (uart->baud!=0) {
divisor= (SUE_SYS_CLK_FREQ / baud) >> 4;
/* configure the baudrate */tmp=uart_read(dev, DW_REG_LCR);
uart_write(dev, DW_REG_LCR, LCR_DLAB_BIT);
uart_write(dev, DW_REG_BRDL,
(uint8_t)(divisor&0xFF));
uart_write(dev, DW_REG_BRDH,
(uint8_t)((divisor >> 8) &0xFF));
/* restore to access baudrate divisor registers */uart_write(dev, DW_REG_LCR, tmp);
}
/* TODO read this from pdata, i.e. stop bits, parity etc *//* 8Bit-data, 1-stop bit, no parity, clear DLAB */uart_write(dev, DW_REG_LCR,
LCR_DLS(3) | LCR_STOP(0) | LCR_PEN(0));
/* FIFO enalbe, mode0, Tx/Rx FIFO reset */uart_write(dev, DW_REG_FCR,
FCR_FIFOE(1) | FCR_MODE(0) | FCR_RCVR_RST | FCR_XMIT_RST);
/* reset port */uart_write(dev, DW_REG_RBR, 0);
return0;
}
conststructuart_opsdw_uart_ops= {
.set_config=dw_uart_set_config,
.probe=dw_uart_probe,
.tx_data=dw_uart_write_data,
.rx_data=dw_uart_read_data, };

Metadata

Metadata

Assignees

Labels

P2Critical bugs or normal featuresenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions