18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
38c2ecf20Sopenharmony_ci * reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
68c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the NetLogic
98c2ecf20Sopenharmony_ci * license below:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
128c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
138c2ecf20Sopenharmony_ci * are met:
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
168c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
178c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
188c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
198c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
208c2ecf20Sopenharmony_ci *    distribution.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
238c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
248c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
268c2ecf20Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
278c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
288c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
298c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
308c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
318c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
328c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#ifndef __XLP_HAL_UART_H__
368c2ecf20Sopenharmony_ci#define __XLP_HAL_UART_H__
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/* UART Specific registers */
398c2ecf20Sopenharmony_ci#define UART_RX_DATA		0x00
408c2ecf20Sopenharmony_ci#define UART_TX_DATA		0x00
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define UART_INT_EN		0x01
438c2ecf20Sopenharmony_ci#define UART_INT_ID		0x02
448c2ecf20Sopenharmony_ci#define UART_FIFO_CTL		0x02
458c2ecf20Sopenharmony_ci#define UART_LINE_CTL		0x03
468c2ecf20Sopenharmony_ci#define UART_MODEM_CTL		0x04
478c2ecf20Sopenharmony_ci#define UART_LINE_STS		0x05
488c2ecf20Sopenharmony_ci#define UART_MODEM_STS		0x06
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define UART_DIVISOR0		0x00
518c2ecf20Sopenharmony_ci#define UART_DIVISOR1		0x01
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#define BASE_BAUD		(XLP_IO_CLK/16)
548c2ecf20Sopenharmony_ci#define BAUD_DIVISOR(baud)	(BASE_BAUD / baud)
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* LCR mask values */
578c2ecf20Sopenharmony_ci#define LCR_5BITS		0x00
588c2ecf20Sopenharmony_ci#define LCR_6BITS		0x01
598c2ecf20Sopenharmony_ci#define LCR_7BITS		0x02
608c2ecf20Sopenharmony_ci#define LCR_8BITS		0x03
618c2ecf20Sopenharmony_ci#define LCR_STOPB		0x04
628c2ecf20Sopenharmony_ci#define LCR_PENAB		0x08
638c2ecf20Sopenharmony_ci#define LCR_PODD		0x00
648c2ecf20Sopenharmony_ci#define LCR_PEVEN		0x10
658c2ecf20Sopenharmony_ci#define LCR_PONE		0x20
668c2ecf20Sopenharmony_ci#define LCR_PZERO		0x30
678c2ecf20Sopenharmony_ci#define LCR_SBREAK		0x40
688c2ecf20Sopenharmony_ci#define LCR_EFR_ENABLE		0xbf
698c2ecf20Sopenharmony_ci#define LCR_DLAB		0x80
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci/* MCR mask values */
728c2ecf20Sopenharmony_ci#define MCR_DTR			0x01
738c2ecf20Sopenharmony_ci#define MCR_RTS			0x02
748c2ecf20Sopenharmony_ci#define MCR_DRS			0x04
758c2ecf20Sopenharmony_ci#define MCR_IE			0x08
768c2ecf20Sopenharmony_ci#define MCR_LOOPBACK		0x10
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/* FCR mask values */
798c2ecf20Sopenharmony_ci#define FCR_RCV_RST		0x02
808c2ecf20Sopenharmony_ci#define FCR_XMT_RST		0x04
818c2ecf20Sopenharmony_ci#define FCR_RX_LOW		0x00
828c2ecf20Sopenharmony_ci#define FCR_RX_MEDL		0x40
838c2ecf20Sopenharmony_ci#define FCR_RX_MEDH		0x80
848c2ecf20Sopenharmony_ci#define FCR_RX_HIGH		0xc0
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci/* IER mask values */
878c2ecf20Sopenharmony_ci#define IER_ERXRDY		0x1
888c2ecf20Sopenharmony_ci#define IER_ETXRDY		0x2
898c2ecf20Sopenharmony_ci#define IER_ERLS		0x4
908c2ecf20Sopenharmony_ci#define IER_EMSC		0x8
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#if !defined(LOCORE) && !defined(__ASSEMBLY__)
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#define nlm_read_uart_reg(b, r)		nlm_read_reg(b, r)
958c2ecf20Sopenharmony_ci#define nlm_write_uart_reg(b, r, v)	nlm_write_reg(b, r, v)
968c2ecf20Sopenharmony_ci#define nlm_get_uart_pcibase(node, inst)	\
978c2ecf20Sopenharmony_ci	nlm_pcicfg_base(cpu_is_xlp9xx() ?  XLP9XX_IO_UART_OFFSET(node) : \
988c2ecf20Sopenharmony_ci						XLP_IO_UART_OFFSET(node, inst))
998c2ecf20Sopenharmony_ci#define nlm_get_uart_regbase(node, inst)	\
1008c2ecf20Sopenharmony_ci			(nlm_get_uart_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic inline void
1038c2ecf20Sopenharmony_cinlm_uart_set_baudrate(uint64_t base, int baud)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	uint32_t lcr;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	lcr = nlm_read_uart_reg(base, UART_LINE_CTL);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	/* enable divisor register, and write baud values */
1108c2ecf20Sopenharmony_ci	nlm_write_uart_reg(base, UART_LINE_CTL, lcr | (1 << 7));
1118c2ecf20Sopenharmony_ci	nlm_write_uart_reg(base, UART_DIVISOR0,
1128c2ecf20Sopenharmony_ci			(BAUD_DIVISOR(baud) & 0xff));
1138c2ecf20Sopenharmony_ci	nlm_write_uart_reg(base, UART_DIVISOR1,
1148c2ecf20Sopenharmony_ci			((BAUD_DIVISOR(baud) >> 8) & 0xff));
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	/* restore default lcr */
1178c2ecf20Sopenharmony_ci	nlm_write_uart_reg(base, UART_LINE_CTL, lcr);
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic inline void
1218c2ecf20Sopenharmony_cinlm_uart_outbyte(uint64_t base, char c)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	uint32_t lsr;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	for (;;) {
1268c2ecf20Sopenharmony_ci		lsr = nlm_read_uart_reg(base, UART_LINE_STS);
1278c2ecf20Sopenharmony_ci		if (lsr & 0x20)
1288c2ecf20Sopenharmony_ci			break;
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	nlm_write_uart_reg(base, UART_TX_DATA, (int)c);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic inline char
1358c2ecf20Sopenharmony_cinlm_uart_inbyte(uint64_t base)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	int data, lsr;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	for (;;) {
1408c2ecf20Sopenharmony_ci		lsr = nlm_read_uart_reg(base, UART_LINE_STS);
1418c2ecf20Sopenharmony_ci		if (lsr & 0x80) { /* parity/frame/break-error - push a zero */
1428c2ecf20Sopenharmony_ci			data = 0;
1438c2ecf20Sopenharmony_ci			break;
1448c2ecf20Sopenharmony_ci		}
1458c2ecf20Sopenharmony_ci		if (lsr & 0x01) {	/* Rx data */
1468c2ecf20Sopenharmony_ci			data = nlm_read_uart_reg(base, UART_RX_DATA);
1478c2ecf20Sopenharmony_ci			break;
1488c2ecf20Sopenharmony_ci		}
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	return (char)data;
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic inline int
1558c2ecf20Sopenharmony_cinlm_uart_init(uint64_t base, int baud, int databits, int stopbits,
1568c2ecf20Sopenharmony_ci	int parity, int int_en, int loopback)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	uint32_t lcr;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	lcr = 0;
1618c2ecf20Sopenharmony_ci	if (databits >= 8)
1628c2ecf20Sopenharmony_ci		lcr |= LCR_8BITS;
1638c2ecf20Sopenharmony_ci	else if (databits == 7)
1648c2ecf20Sopenharmony_ci		lcr |= LCR_7BITS;
1658c2ecf20Sopenharmony_ci	else if (databits == 6)
1668c2ecf20Sopenharmony_ci		lcr |= LCR_6BITS;
1678c2ecf20Sopenharmony_ci	else
1688c2ecf20Sopenharmony_ci		lcr |= LCR_5BITS;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	if (stopbits > 1)
1718c2ecf20Sopenharmony_ci		lcr |= LCR_STOPB;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	lcr |= parity << 3;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	/* setup default lcr */
1768c2ecf20Sopenharmony_ci	nlm_write_uart_reg(base, UART_LINE_CTL, lcr);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	/* Reset the FIFOs */
1798c2ecf20Sopenharmony_ci	nlm_write_uart_reg(base, UART_LINE_CTL, FCR_RCV_RST | FCR_XMT_RST);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	nlm_uart_set_baudrate(base, baud);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	if (loopback)
1848c2ecf20Sopenharmony_ci		nlm_write_uart_reg(base, UART_MODEM_CTL, 0x1f);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (int_en)
1878c2ecf20Sopenharmony_ci		nlm_write_uart_reg(base, UART_INT_EN, IER_ERXRDY | IER_ETXRDY);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	return 0;
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci#endif /* !LOCORE && !__ASSEMBLY__ */
1928c2ecf20Sopenharmony_ci#endif /* __XLP_HAL_UART_H__ */
193