130581040SÁlvaro Fernández Rojas /*
230581040SÁlvaro Fernández Rojas  * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
330581040SÁlvaro Fernández Rojas  *
430581040SÁlvaro Fernández Rojas  * Derived from linux/drivers/tty/serial/bcm63xx_uart.c:
530581040SÁlvaro Fernández Rojas  *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
630581040SÁlvaro Fernández Rojas  *
730581040SÁlvaro Fernández Rojas  * SPDX-License-Identifier:	GPL-2.0+
830581040SÁlvaro Fernández Rojas  */
930581040SÁlvaro Fernández Rojas 
1030581040SÁlvaro Fernández Rojas #include <clk.h>
11*9d922450SSimon Glass #include <dm.h>
1230581040SÁlvaro Fernández Rojas #include <debug_uart.h>
1330581040SÁlvaro Fernández Rojas #include <errno.h>
1430581040SÁlvaro Fernández Rojas #include <serial.h>
1530581040SÁlvaro Fernández Rojas #include <asm/io.h>
1630581040SÁlvaro Fernández Rojas #include <asm/types.h>
1730581040SÁlvaro Fernández Rojas 
1830581040SÁlvaro Fernández Rojas /* UART Control register */
1930581040SÁlvaro Fernández Rojas #define UART_CTL_REG			0x0
2030581040SÁlvaro Fernández Rojas #define UART_CTL_RXTIMEOUT_MASK		0x1f
2130581040SÁlvaro Fernández Rojas #define UART_CTL_RXTIMEOUT_5		0x5
2230581040SÁlvaro Fernández Rojas #define UART_CTL_RSTRXFIFO_SHIFT	6
2330581040SÁlvaro Fernández Rojas #define UART_CTL_RSTRXFIFO_MASK		(1 << UART_CTL_RSTRXFIFO_SHIFT)
2430581040SÁlvaro Fernández Rojas #define UART_CTL_RSTTXFIFO_SHIFT	7
2530581040SÁlvaro Fernández Rojas #define UART_CTL_RSTTXFIFO_MASK		(1 << UART_CTL_RSTTXFIFO_SHIFT)
2630581040SÁlvaro Fernández Rojas #define UART_CTL_STOPBITS_SHIFT		8
2730581040SÁlvaro Fernández Rojas #define UART_CTL_STOPBITS_MASK		(0xf << UART_CTL_STOPBITS_SHIFT)
2830581040SÁlvaro Fernández Rojas #define UART_CTL_STOPBITS_1		(0x7 << UART_CTL_STOPBITS_SHIFT)
2930581040SÁlvaro Fernández Rojas #define UART_CTL_BITSPERSYM_SHIFT	12
3030581040SÁlvaro Fernández Rojas #define UART_CTL_BITSPERSYM_MASK	(0x3 << UART_CTL_BITSPERSYM_SHIFT)
3130581040SÁlvaro Fernández Rojas #define UART_CTL_BITSPERSYM_8		(0x3 << UART_CTL_BITSPERSYM_SHIFT)
3230581040SÁlvaro Fernández Rojas #define UART_CTL_XMITBRK_SHIFT		14
3330581040SÁlvaro Fernández Rojas #define UART_CTL_XMITBRK_MASK		(1 << UART_CTL_XMITBRK_SHIFT)
3430581040SÁlvaro Fernández Rojas #define UART_CTL_RSVD_SHIFT		15
3530581040SÁlvaro Fernández Rojas #define UART_CTL_RSVD_MASK		(1 << UART_CTL_RSVD_SHIFT)
3630581040SÁlvaro Fernández Rojas #define UART_CTL_RXPAREVEN_SHIFT	16
3730581040SÁlvaro Fernández Rojas #define UART_CTL_RXPAREVEN_MASK		(1 << UART_CTL_RXPAREVEN_SHIFT)
3830581040SÁlvaro Fernández Rojas #define UART_CTL_RXPAREN_SHIFT		17
3930581040SÁlvaro Fernández Rojas #define UART_CTL_RXPAREN_MASK		(1 << UART_CTL_RXPAREN_SHIFT)
4030581040SÁlvaro Fernández Rojas #define UART_CTL_TXPAREVEN_SHIFT	18
4130581040SÁlvaro Fernández Rojas #define UART_CTL_TXPAREVEN_MASK		(1 << UART_CTL_TXPAREVEN_SHIFT)
4230581040SÁlvaro Fernández Rojas #define UART_CTL_TXPAREN_SHIFT		19
4330581040SÁlvaro Fernández Rojas #define UART_CTL_TXPAREN_MASK		(1 << UART_CTL_TXPAREN_SHIFT)
4430581040SÁlvaro Fernández Rojas #define UART_CTL_LOOPBACK_SHIFT		20
4530581040SÁlvaro Fernández Rojas #define UART_CTL_LOOPBACK_MASK		(1 << UART_CTL_LOOPBACK_SHIFT)
4630581040SÁlvaro Fernández Rojas #define UART_CTL_RXEN_SHIFT		21
4730581040SÁlvaro Fernández Rojas #define UART_CTL_RXEN_MASK		(1 << UART_CTL_RXEN_SHIFT)
4830581040SÁlvaro Fernández Rojas #define UART_CTL_TXEN_SHIFT		22
4930581040SÁlvaro Fernández Rojas #define UART_CTL_TXEN_MASK		(1 << UART_CTL_TXEN_SHIFT)
5030581040SÁlvaro Fernández Rojas #define UART_CTL_BRGEN_SHIFT		23
5130581040SÁlvaro Fernández Rojas #define UART_CTL_BRGEN_MASK		(1 << UART_CTL_BRGEN_SHIFT)
5230581040SÁlvaro Fernández Rojas 
5330581040SÁlvaro Fernández Rojas /* UART Baudword register */
5430581040SÁlvaro Fernández Rojas #define UART_BAUD_REG			0x4
5530581040SÁlvaro Fernández Rojas 
5630581040SÁlvaro Fernández Rojas /* UART FIFO Config register */
5730581040SÁlvaro Fernández Rojas #define UART_FIFO_CFG_REG		0x8
5830581040SÁlvaro Fernández Rojas #define UART_FIFO_CFG_RX_SHIFT		8
5930581040SÁlvaro Fernández Rojas #define UART_FIFO_CFG_RX_MASK		(0xf << UART_FIFO_CFG_RX_SHIFT)
6030581040SÁlvaro Fernández Rojas #define UART_FIFO_CFG_RX_4		(0x4 << UART_FIFO_CFG_RX_SHIFT)
6130581040SÁlvaro Fernández Rojas #define UART_FIFO_CFG_TX_SHIFT		12
6230581040SÁlvaro Fernández Rojas #define UART_FIFO_CFG_TX_MASK		(0xf << UART_FIFO_CFG_TX_SHIFT)
6330581040SÁlvaro Fernández Rojas #define UART_FIFO_CFG_TX_4		(0x4 << UART_FIFO_CFG_TX_SHIFT)
6430581040SÁlvaro Fernández Rojas 
6530581040SÁlvaro Fernández Rojas /* UART Interrupt register */
6630581040SÁlvaro Fernández Rojas #define UART_IR_REG			0x10
6730581040SÁlvaro Fernández Rojas #define UART_IR_STAT(x)			(1 << (x))
6830581040SÁlvaro Fernández Rojas #define UART_IR_TXEMPTY			5
6930581040SÁlvaro Fernández Rojas #define UART_IR_RXOVER			7
7030581040SÁlvaro Fernández Rojas #define UART_IR_RXNOTEMPTY		11
7130581040SÁlvaro Fernández Rojas 
7230581040SÁlvaro Fernández Rojas /* UART FIFO register */
7330581040SÁlvaro Fernández Rojas #define UART_FIFO_REG			0x14
7430581040SÁlvaro Fernández Rojas #define UART_FIFO_VALID_MASK		0xff
7530581040SÁlvaro Fernández Rojas #define UART_FIFO_FRAMEERR_SHIFT	8
7630581040SÁlvaro Fernández Rojas #define UART_FIFO_FRAMEERR_MASK		(1 << UART_FIFO_FRAMEERR_SHIFT)
7730581040SÁlvaro Fernández Rojas #define UART_FIFO_PARERR_SHIFT		9
7830581040SÁlvaro Fernández Rojas #define UART_FIFO_PARERR_MASK		(1 << UART_FIFO_PARERR_SHIFT)
7930581040SÁlvaro Fernández Rojas #define UART_FIFO_BRKDET_SHIFT		10
8030581040SÁlvaro Fernández Rojas #define UART_FIFO_BRKDET_MASK		(1 << UART_FIFO_BRKDET_SHIFT)
8130581040SÁlvaro Fernández Rojas #define UART_FIFO_ANYERR_MASK		(UART_FIFO_FRAMEERR_MASK |	\
8230581040SÁlvaro Fernández Rojas 					UART_FIFO_PARERR_MASK |		\
8330581040SÁlvaro Fernández Rojas 					UART_FIFO_BRKDET_MASK)
8430581040SÁlvaro Fernández Rojas 
8530581040SÁlvaro Fernández Rojas struct bcm6345_serial_priv {
8630581040SÁlvaro Fernández Rojas 	void __iomem *base;
8730581040SÁlvaro Fernández Rojas 	ulong uartclk;
8830581040SÁlvaro Fernández Rojas };
8930581040SÁlvaro Fernández Rojas 
9030581040SÁlvaro Fernández Rojas /* enable rx & tx operation on uart */
9130581040SÁlvaro Fernández Rojas static void bcm6345_serial_enable(void __iomem *base)
9230581040SÁlvaro Fernández Rojas {
9330581040SÁlvaro Fernández Rojas 	setbits_be32(base + UART_CTL_REG, UART_CTL_BRGEN_MASK |
9430581040SÁlvaro Fernández Rojas 		     UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK);
9530581040SÁlvaro Fernández Rojas }
9630581040SÁlvaro Fernández Rojas 
9730581040SÁlvaro Fernández Rojas /* disable rx & tx operation on uart */
9830581040SÁlvaro Fernández Rojas static void bcm6345_serial_disable(void __iomem *base)
9930581040SÁlvaro Fernández Rojas {
10030581040SÁlvaro Fernández Rojas 	clrbits_be32(base + UART_CTL_REG, UART_CTL_BRGEN_MASK |
10130581040SÁlvaro Fernández Rojas 		     UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK);
10230581040SÁlvaro Fernández Rojas }
10330581040SÁlvaro Fernández Rojas 
10430581040SÁlvaro Fernández Rojas /* clear all unread data in rx fifo and unsent data in tx fifo */
10530581040SÁlvaro Fernández Rojas static void bcm6345_serial_flush(void __iomem *base)
10630581040SÁlvaro Fernández Rojas {
10730581040SÁlvaro Fernández Rojas 	/* empty rx and tx fifo */
10830581040SÁlvaro Fernández Rojas 	setbits_be32(base + UART_CTL_REG, UART_CTL_RSTRXFIFO_MASK |
10930581040SÁlvaro Fernández Rojas 		     UART_CTL_RSTTXFIFO_MASK);
11030581040SÁlvaro Fernández Rojas 
11130581040SÁlvaro Fernández Rojas 	/* read any pending char to make sure all irq status are cleared */
11230581040SÁlvaro Fernández Rojas 	readl_be(base + UART_FIFO_REG);
11330581040SÁlvaro Fernández Rojas }
11430581040SÁlvaro Fernández Rojas 
11530581040SÁlvaro Fernández Rojas static int bcm6345_serial_init(void __iomem *base, ulong clk, u32 baudrate)
11630581040SÁlvaro Fernández Rojas {
11730581040SÁlvaro Fernández Rojas 	u32 val;
11830581040SÁlvaro Fernández Rojas 
11930581040SÁlvaro Fernández Rojas 	/* mask all irq and flush port */
12030581040SÁlvaro Fernández Rojas 	bcm6345_serial_disable(base);
12130581040SÁlvaro Fernández Rojas 	bcm6345_serial_flush(base);
12230581040SÁlvaro Fernández Rojas 
12330581040SÁlvaro Fernández Rojas 	/* set uart control config */
12430581040SÁlvaro Fernández Rojas 	clrsetbits_be32(base + UART_CTL_REG,
12530581040SÁlvaro Fernández Rojas 			/* clear rx timeout */
12630581040SÁlvaro Fernández Rojas 			UART_CTL_RXTIMEOUT_MASK |
12730581040SÁlvaro Fernández Rojas 			/* clear stop bits */
12830581040SÁlvaro Fernández Rojas 			UART_CTL_STOPBITS_MASK |
12930581040SÁlvaro Fernández Rojas 			/* clear bits per symbol */
13030581040SÁlvaro Fernández Rojas 			UART_CTL_BITSPERSYM_MASK |
13130581040SÁlvaro Fernández Rojas 			/* clear xmit break */
13230581040SÁlvaro Fernández Rojas 			UART_CTL_XMITBRK_MASK |
13330581040SÁlvaro Fernández Rojas 			/* clear reserved bit */
13430581040SÁlvaro Fernández Rojas 			UART_CTL_RSVD_MASK |
13530581040SÁlvaro Fernández Rojas 			/* disable parity */
13630581040SÁlvaro Fernández Rojas 			UART_CTL_RXPAREN_MASK |
13730581040SÁlvaro Fernández Rojas 			UART_CTL_TXPAREN_MASK |
13830581040SÁlvaro Fernández Rojas 			/* disable loopback */
13930581040SÁlvaro Fernández Rojas 			UART_CTL_LOOPBACK_MASK,
14030581040SÁlvaro Fernández Rojas 			/* set timeout to 5 */
14130581040SÁlvaro Fernández Rojas 			UART_CTL_RXTIMEOUT_5 |
14230581040SÁlvaro Fernández Rojas 			/* set 8 bits/symbol */
14330581040SÁlvaro Fernández Rojas 			UART_CTL_BITSPERSYM_8 |
1446b7185f3SÁlvaro Fernández Rojas 			/* set 1 stop bit */
1456b7185f3SÁlvaro Fernández Rojas 			UART_CTL_STOPBITS_1 |
14630581040SÁlvaro Fernández Rojas 			/* set parity to even */
14730581040SÁlvaro Fernández Rojas 			UART_CTL_RXPAREVEN_MASK |
14830581040SÁlvaro Fernández Rojas 			UART_CTL_TXPAREVEN_MASK);
14930581040SÁlvaro Fernández Rojas 
15030581040SÁlvaro Fernández Rojas 	/* set uart fifo config */
15130581040SÁlvaro Fernández Rojas 	clrsetbits_be32(base + UART_FIFO_CFG_REG,
15230581040SÁlvaro Fernández Rojas 			/* clear fifo config */
15330581040SÁlvaro Fernández Rojas 			UART_FIFO_CFG_RX_MASK |
15430581040SÁlvaro Fernández Rojas 			UART_FIFO_CFG_TX_MASK,
15530581040SÁlvaro Fernández Rojas 			/* set fifo config to 4 */
15630581040SÁlvaro Fernández Rojas 			UART_FIFO_CFG_RX_4 |
15730581040SÁlvaro Fernández Rojas 			UART_FIFO_CFG_TX_4);
15830581040SÁlvaro Fernández Rojas 
15930581040SÁlvaro Fernández Rojas 	/* set baud rate */
16024f85482SÁlvaro Fernández Rojas 	val = ((clk / baudrate) >> 4);
16130581040SÁlvaro Fernández Rojas 	if (val & 0x1)
16224f85482SÁlvaro Fernández Rojas 		val = (val >> 1);
16330581040SÁlvaro Fernández Rojas 	else
16424f85482SÁlvaro Fernández Rojas 		val = (val >> 1) - 1;
16530581040SÁlvaro Fernández Rojas 	writel_be(val, base + UART_BAUD_REG);
16630581040SÁlvaro Fernández Rojas 
16730581040SÁlvaro Fernández Rojas 	/* clear interrupts */
16830581040SÁlvaro Fernández Rojas 	writel_be(0, base + UART_IR_REG);
16930581040SÁlvaro Fernández Rojas 
17030581040SÁlvaro Fernández Rojas 	/* enable uart */
17130581040SÁlvaro Fernández Rojas 	bcm6345_serial_enable(base);
17230581040SÁlvaro Fernández Rojas 
17330581040SÁlvaro Fernández Rojas 	return 0;
17430581040SÁlvaro Fernández Rojas }
17530581040SÁlvaro Fernández Rojas 
17630581040SÁlvaro Fernández Rojas static int bcm6345_serial_pending(struct udevice *dev, bool input)
17730581040SÁlvaro Fernández Rojas {
17830581040SÁlvaro Fernández Rojas 	struct bcm6345_serial_priv *priv = dev_get_priv(dev);
17930581040SÁlvaro Fernández Rojas 	u32 val = readl_be(priv->base + UART_IR_REG);
18030581040SÁlvaro Fernández Rojas 
18130581040SÁlvaro Fernández Rojas 	if (input)
18230581040SÁlvaro Fernández Rojas 		return !!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY));
18330581040SÁlvaro Fernández Rojas 	else
18430581040SÁlvaro Fernández Rojas 		return !(val & UART_IR_STAT(UART_IR_TXEMPTY));
18530581040SÁlvaro Fernández Rojas }
18630581040SÁlvaro Fernández Rojas 
18730581040SÁlvaro Fernández Rojas static int bcm6345_serial_setbrg(struct udevice *dev, int baudrate)
18830581040SÁlvaro Fernández Rojas {
18930581040SÁlvaro Fernández Rojas 	struct bcm6345_serial_priv *priv = dev_get_priv(dev);
19030581040SÁlvaro Fernández Rojas 
19130581040SÁlvaro Fernández Rojas 	return bcm6345_serial_init(priv->base, priv->uartclk, baudrate);
19230581040SÁlvaro Fernández Rojas }
19330581040SÁlvaro Fernández Rojas 
19430581040SÁlvaro Fernández Rojas static int bcm6345_serial_putc(struct udevice *dev, const char ch)
19530581040SÁlvaro Fernández Rojas {
19630581040SÁlvaro Fernández Rojas 	struct bcm6345_serial_priv *priv = dev_get_priv(dev);
19730581040SÁlvaro Fernández Rojas 	u32 val;
19830581040SÁlvaro Fernández Rojas 
19930581040SÁlvaro Fernández Rojas 	val = readl_be(priv->base + UART_IR_REG);
20030581040SÁlvaro Fernández Rojas 	if (!(val & UART_IR_STAT(UART_IR_TXEMPTY)))
20130581040SÁlvaro Fernández Rojas 		return -EAGAIN;
20230581040SÁlvaro Fernández Rojas 
20330581040SÁlvaro Fernández Rojas 	writel_be(ch, priv->base + UART_FIFO_REG);
20430581040SÁlvaro Fernández Rojas 
20530581040SÁlvaro Fernández Rojas 	return 0;
20630581040SÁlvaro Fernández Rojas }
20730581040SÁlvaro Fernández Rojas 
20830581040SÁlvaro Fernández Rojas static int bcm6345_serial_getc(struct udevice *dev)
20930581040SÁlvaro Fernández Rojas {
21030581040SÁlvaro Fernández Rojas 	struct bcm6345_serial_priv *priv = dev_get_priv(dev);
21130581040SÁlvaro Fernández Rojas 	u32 val;
21230581040SÁlvaro Fernández Rojas 
21330581040SÁlvaro Fernández Rojas 	val = readl_be(priv->base + UART_IR_REG);
21430581040SÁlvaro Fernández Rojas 	if (val & UART_IR_STAT(UART_IR_RXOVER))
21530581040SÁlvaro Fernández Rojas 		setbits_be32(priv->base + UART_CTL_REG,
21630581040SÁlvaro Fernández Rojas 			     UART_CTL_RSTRXFIFO_MASK);
21730581040SÁlvaro Fernández Rojas 	if (!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY)))
21830581040SÁlvaro Fernández Rojas 		return -EAGAIN;
21930581040SÁlvaro Fernández Rojas 
22030581040SÁlvaro Fernández Rojas 	val = readl_be(priv->base + UART_FIFO_REG);
22130581040SÁlvaro Fernández Rojas 	if (val & UART_FIFO_ANYERR_MASK)
22230581040SÁlvaro Fernández Rojas 		return -EAGAIN;
22330581040SÁlvaro Fernández Rojas 
22430581040SÁlvaro Fernández Rojas 	return val & UART_FIFO_VALID_MASK;
22530581040SÁlvaro Fernández Rojas }
22630581040SÁlvaro Fernández Rojas 
22730581040SÁlvaro Fernández Rojas static int bcm6345_serial_probe(struct udevice *dev)
22830581040SÁlvaro Fernández Rojas {
22930581040SÁlvaro Fernández Rojas 	struct bcm6345_serial_priv *priv = dev_get_priv(dev);
23030581040SÁlvaro Fernández Rojas 	struct clk clk;
23130581040SÁlvaro Fernández Rojas 	fdt_addr_t addr;
23230581040SÁlvaro Fernández Rojas 	fdt_size_t size;
23330581040SÁlvaro Fernández Rojas 	int ret;
23430581040SÁlvaro Fernández Rojas 
23530581040SÁlvaro Fernández Rojas 	/* get address */
23630581040SÁlvaro Fernández Rojas 	addr = dev_get_addr_size_index(dev, 0, &size);
23730581040SÁlvaro Fernández Rojas 	if (addr == FDT_ADDR_T_NONE)
23830581040SÁlvaro Fernández Rojas 		return -EINVAL;
23930581040SÁlvaro Fernández Rojas 
24030581040SÁlvaro Fernández Rojas 	priv->base = ioremap(addr, size);
24130581040SÁlvaro Fernández Rojas 
24230581040SÁlvaro Fernández Rojas 	/* get clock rate */
24330581040SÁlvaro Fernández Rojas 	ret = clk_get_by_index(dev, 0, &clk);
24430581040SÁlvaro Fernández Rojas 	if (ret < 0)
24530581040SÁlvaro Fernández Rojas 		return ret;
24624f85482SÁlvaro Fernández Rojas 	priv->uartclk = clk_get_rate(&clk);
24730581040SÁlvaro Fernández Rojas 	clk_free(&clk);
24830581040SÁlvaro Fernández Rojas 
24930581040SÁlvaro Fernández Rojas 	/* initialize serial */
25030581040SÁlvaro Fernández Rojas 	return bcm6345_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
25130581040SÁlvaro Fernández Rojas }
25230581040SÁlvaro Fernández Rojas 
25330581040SÁlvaro Fernández Rojas static const struct dm_serial_ops bcm6345_serial_ops = {
25430581040SÁlvaro Fernández Rojas 	.putc = bcm6345_serial_putc,
25530581040SÁlvaro Fernández Rojas 	.pending = bcm6345_serial_pending,
25630581040SÁlvaro Fernández Rojas 	.getc = bcm6345_serial_getc,
25730581040SÁlvaro Fernández Rojas 	.setbrg = bcm6345_serial_setbrg,
25830581040SÁlvaro Fernández Rojas };
25930581040SÁlvaro Fernández Rojas 
26030581040SÁlvaro Fernández Rojas static const struct udevice_id bcm6345_serial_ids[] = {
26130581040SÁlvaro Fernández Rojas 	{ .compatible = "brcm,bcm6345-uart" },
26230581040SÁlvaro Fernández Rojas 	{ /* sentinel */ }
26330581040SÁlvaro Fernández Rojas };
26430581040SÁlvaro Fernández Rojas 
26530581040SÁlvaro Fernández Rojas U_BOOT_DRIVER(bcm6345_serial) = {
26630581040SÁlvaro Fernández Rojas 	.name = "bcm6345-uart",
26730581040SÁlvaro Fernández Rojas 	.id = UCLASS_SERIAL,
26830581040SÁlvaro Fernández Rojas 	.of_match = bcm6345_serial_ids,
26930581040SÁlvaro Fernández Rojas 	.probe = bcm6345_serial_probe,
27030581040SÁlvaro Fernández Rojas 	.priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv),
27130581040SÁlvaro Fernández Rojas 	.ops = &bcm6345_serial_ops,
27230581040SÁlvaro Fernández Rojas 	.flags = DM_FLAG_PRE_RELOC,
27330581040SÁlvaro Fernández Rojas };
27430581040SÁlvaro Fernández Rojas 
27530581040SÁlvaro Fernández Rojas #ifdef CONFIG_DEBUG_UART_BCM6345
27630581040SÁlvaro Fernández Rojas static inline void _debug_uart_init(void)
27730581040SÁlvaro Fernández Rojas {
27830581040SÁlvaro Fernández Rojas 	void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
27930581040SÁlvaro Fernández Rojas 
28030581040SÁlvaro Fernández Rojas 	bcm6345_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
28130581040SÁlvaro Fernández Rojas }
28230581040SÁlvaro Fernández Rojas 
28330581040SÁlvaro Fernández Rojas static inline void wait_xfered(void __iomem *base)
28430581040SÁlvaro Fernández Rojas {
28530581040SÁlvaro Fernández Rojas 	do {
28630581040SÁlvaro Fernández Rojas 		u32 val = readl_be(base + UART_IR_REG);
28730581040SÁlvaro Fernández Rojas 		if (val & UART_IR_STAT(UART_IR_TXEMPTY))
28830581040SÁlvaro Fernández Rojas 			break;
28930581040SÁlvaro Fernández Rojas 	} while (1);
29030581040SÁlvaro Fernández Rojas }
29130581040SÁlvaro Fernández Rojas 
29230581040SÁlvaro Fernández Rojas static inline void _debug_uart_putc(int ch)
29330581040SÁlvaro Fernández Rojas {
29430581040SÁlvaro Fernández Rojas 	void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
29530581040SÁlvaro Fernández Rojas 
29630581040SÁlvaro Fernández Rojas 	wait_xfered(base);
29730581040SÁlvaro Fernández Rojas 	writel_be(ch, base + UART_FIFO_REG);
29830581040SÁlvaro Fernández Rojas 	wait_xfered(base);
29930581040SÁlvaro Fernández Rojas }
30030581040SÁlvaro Fernández Rojas 
30130581040SÁlvaro Fernández Rojas DEBUG_UART_FUNCS
30230581040SÁlvaro Fernández Rojas #endif
303