brintos

brintos / linux-shallow public Read only

0
0
Text · 18.3 KiB · abf7c44 Raw
768 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Sunplus SoC UART driver4 *5 * Author: Hammer Hsieh <hammerh0314@gmail.com>6 *7 * Note1: This driver is 8250-like uart, but are not register compatible.8 *9 * Note2: On some buses, for preventing data incoherence, must do a read10 * for ensure write made it to hardware. In this driver, function startup11 * and shutdown did not do a read but only do a write directly. For what?12 * In Sunplus bus communication between memory bus and peripheral bus with13 * posted write, it will send a specific command after last write command14 * to make sure write done. Then memory bus identify the specific command15 * and send done signal back to master device. After master device received16 * done signal, then proceed next write command. It is no need to do a read17 * before write.18 */19#include <linux/clk.h>20#include <linux/console.h>21#include <linux/interrupt.h>22#include <linux/io.h>23#include <linux/iopoll.h>24#include <linux/module.h>25#include <linux/of.h>26#include <linux/of_platform.h>27#include <linux/platform_device.h>28#include <linux/reset.h>29#include <linux/serial_core.h>30#include <linux/serial_reg.h>31#include <linux/sysrq.h>32#include <linux/tty.h>33#include <linux/tty_flip.h>34#include <asm/irq.h>35 36/* Register offsets */37#define SUP_UART_DATA			0x0038#define SUP_UART_LSR			0x0439#define SUP_UART_MSR			0x0840#define SUP_UART_LCR			0x0C41#define SUP_UART_MCR			0x1042#define SUP_UART_DIV_L			0x1443#define SUP_UART_DIV_H			0x1844#define SUP_UART_ISC			0x1C45#define SUP_UART_TX_RESIDUE		0x2046#define SUP_UART_RX_RESIDUE		0x2447 48/* Line Status Register bits */49#define SUP_UART_LSR_BC			BIT(5) /* break condition status */50#define SUP_UART_LSR_FE			BIT(4) /* frame error status */51#define SUP_UART_LSR_OE			BIT(3) /* overrun error status */52#define SUP_UART_LSR_PE			BIT(2) /* parity error status */53#define SUP_UART_LSR_RX			BIT(1) /* 1: receive fifo not empty */54#define SUP_UART_LSR_TX			BIT(0) /* 1: transmit fifo is not full */55#define SUP_UART_LSR_TX_NOT_FULL	156#define SUP_UART_LSR_BRK_ERROR_BITS	GENMASK(5, 2)57 58/* Line Control Register bits */59#define SUP_UART_LCR_SBC		BIT(5) /* select break condition */60 61/* Modem Control Register bits */62#define SUP_UART_MCR_RI			BIT(3) /* ring indicator */63#define SUP_UART_MCR_DCD		BIT(2) /* data carrier detect */64 65/* Interrupt Status/Control Register bits */66#define SUP_UART_ISC_RXM		BIT(5) /* RX interrupt enable */67#define SUP_UART_ISC_TXM		BIT(4) /* TX interrupt enable */68#define SUP_UART_ISC_RX			BIT(1) /* RX interrupt status */69#define SUP_UART_ISC_TX			BIT(0) /* TX interrupt status */70 71#define SUP_DUMMY_READ			BIT(16) /* drop bytes received on a !CREAD port */72#define SUP_UART_NR			573 74struct sunplus_uart_port {75	struct uart_port port;76	struct clk *clk;77	struct reset_control *rstc;78};79 80static void sp_uart_put_char(struct uart_port *port, unsigned int ch)81{82	writel(ch, port->membase + SUP_UART_DATA);83}84 85static u32 sunplus_tx_buf_not_full(struct uart_port *port)86{87	unsigned int lsr = readl(port->membase + SUP_UART_LSR);88 89	return (lsr & SUP_UART_LSR_TX) ? SUP_UART_LSR_TX_NOT_FULL : 0;90}91 92static unsigned int sunplus_tx_empty(struct uart_port *port)93{94	unsigned int lsr = readl(port->membase + SUP_UART_LSR);95 96	return (lsr & UART_LSR_TEMT) ? TIOCSER_TEMT : 0;97}98 99static void sunplus_set_mctrl(struct uart_port *port, unsigned int mctrl)100{101	unsigned int mcr = readl(port->membase + SUP_UART_MCR);102 103	if (mctrl & TIOCM_DTR)104		mcr |= UART_MCR_DTR;105	else106		mcr &= ~UART_MCR_DTR;107 108	if (mctrl & TIOCM_RTS)109		mcr |= UART_MCR_RTS;110	else111		mcr &= ~UART_MCR_RTS;112 113	if (mctrl & TIOCM_CAR)114		mcr |= SUP_UART_MCR_DCD;115	else116		mcr &= ~SUP_UART_MCR_DCD;117 118	if (mctrl & TIOCM_RI)119		mcr |= SUP_UART_MCR_RI;120	else121		mcr &= ~SUP_UART_MCR_RI;122 123	if (mctrl & TIOCM_LOOP)124		mcr |= UART_MCR_LOOP;125	else126		mcr &= ~UART_MCR_LOOP;127 128	writel(mcr, port->membase + SUP_UART_MCR);129}130 131static unsigned int sunplus_get_mctrl(struct uart_port *port)132{133	unsigned int mcr, ret = 0;134 135	mcr = readl(port->membase + SUP_UART_MCR);136 137	if (mcr & UART_MCR_DTR)138		ret |= TIOCM_DTR;139 140	if (mcr & UART_MCR_RTS)141		ret |= TIOCM_RTS;142 143	if (mcr & SUP_UART_MCR_DCD)144		ret |= TIOCM_CAR;145 146	if (mcr & SUP_UART_MCR_RI)147		ret |= TIOCM_RI;148 149	if (mcr & UART_MCR_LOOP)150		ret |= TIOCM_LOOP;151 152	return ret;153}154 155static void sunplus_stop_tx(struct uart_port *port)156{157	unsigned int isc;158 159	isc = readl(port->membase + SUP_UART_ISC);160	isc &= ~SUP_UART_ISC_TXM;161	writel(isc, port->membase + SUP_UART_ISC);162}163 164static void sunplus_start_tx(struct uart_port *port)165{166	unsigned int isc;167 168	isc = readl(port->membase + SUP_UART_ISC);169	isc |= SUP_UART_ISC_TXM;170	writel(isc, port->membase + SUP_UART_ISC);171}172 173static void sunplus_stop_rx(struct uart_port *port)174{175	unsigned int isc;176 177	isc = readl(port->membase + SUP_UART_ISC);178	isc &= ~SUP_UART_ISC_RXM;179	writel(isc, port->membase + SUP_UART_ISC);180}181 182static void sunplus_break_ctl(struct uart_port *port, int ctl)183{184	unsigned long flags;185	unsigned int lcr;186 187	uart_port_lock_irqsave(port, &flags);188 189	lcr = readl(port->membase + SUP_UART_LCR);190 191	if (ctl)192		lcr |= SUP_UART_LCR_SBC; /* start break */193	else194		lcr &= ~SUP_UART_LCR_SBC; /* stop break */195 196	writel(lcr, port->membase + SUP_UART_LCR);197 198	uart_port_unlock_irqrestore(port, flags);199}200 201static void transmit_chars(struct uart_port *port)202{203	struct tty_port *tport = &port->state->port;204 205	if (port->x_char) {206		sp_uart_put_char(port, port->x_char);207		port->icount.tx++;208		port->x_char = 0;209		return;210	}211 212	if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) {213		sunplus_stop_tx(port);214		return;215	}216 217	do {218		unsigned char ch;219 220		if (!uart_fifo_get(port, &ch))221			break;222 223		sp_uart_put_char(port, ch);224	} while (sunplus_tx_buf_not_full(port));225 226	if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)227		uart_write_wakeup(port);228 229	if (kfifo_is_empty(&tport->xmit_fifo))230		sunplus_stop_tx(port);231}232 233static void receive_chars(struct uart_port *port)234{235	unsigned int lsr = readl(port->membase + SUP_UART_LSR);236	u8 ch, flag;237 238	do {239		ch = readl(port->membase + SUP_UART_DATA);240		flag = TTY_NORMAL;241		port->icount.rx++;242 243		if (unlikely(lsr & SUP_UART_LSR_BRK_ERROR_BITS)) {244			if (lsr & SUP_UART_LSR_BC) {245				lsr &= ~(SUP_UART_LSR_FE | SUP_UART_LSR_PE);246				port->icount.brk++;247				flag = TTY_BREAK;248				if (uart_handle_break(port))249					goto ignore_char;250			} else if (lsr & SUP_UART_LSR_PE) {251				port->icount.parity++;252				flag = TTY_PARITY;253			} else if (lsr & SUP_UART_LSR_FE) {254				port->icount.frame++;255				flag = TTY_FRAME;256			}257 258			if (lsr & SUP_UART_LSR_OE)259				port->icount.overrun++;260		}261 262		if (port->ignore_status_mask & SUP_DUMMY_READ)263			goto ignore_char;264 265		if (uart_prepare_sysrq_char(port, ch))266			goto ignore_char;267 268		uart_insert_char(port, lsr, SUP_UART_LSR_OE, ch, flag);269 270ignore_char:271		lsr = readl(port->membase + SUP_UART_LSR);272	} while (lsr & SUP_UART_LSR_RX);273 274	tty_flip_buffer_push(&port->state->port);275}276 277static irqreturn_t sunplus_uart_irq(int irq, void *args)278{279	struct uart_port *port = args;280	unsigned int isc;281 282	uart_port_lock(port);283 284	isc = readl(port->membase + SUP_UART_ISC);285 286	if (isc & SUP_UART_ISC_RX)287		receive_chars(port);288 289	if (isc & SUP_UART_ISC_TX)290		transmit_chars(port);291 292	uart_unlock_and_check_sysrq(port);293 294	return IRQ_HANDLED;295}296 297static int sunplus_startup(struct uart_port *port)298{299	unsigned long flags;300	unsigned int isc = 0;301	int ret;302 303	ret = request_irq(port->irq, sunplus_uart_irq, 0, "sunplus_uart", port);304	if (ret)305		return ret;306 307	uart_port_lock_irqsave(port, &flags);308	/* isc define Bit[7:4] int setting, Bit[3:0] int status309	 * isc register will clean Bit[3:0] int status after read310	 * only do a write to Bit[7:4] int setting311	 */312	isc |= SUP_UART_ISC_RXM;313	writel(isc, port->membase + SUP_UART_ISC);314	uart_port_unlock_irqrestore(port, flags);315 316	return 0;317}318 319static void sunplus_shutdown(struct uart_port *port)320{321	unsigned long flags;322 323	uart_port_lock_irqsave(port, &flags);324	/* isc define Bit[7:4] int setting, Bit[3:0] int status325	 * isc register will clean Bit[3:0] int status after read326	 * only do a write to Bit[7:4] int setting327	 */328	writel(0, port->membase + SUP_UART_ISC); /* disable all interrupt */329	uart_port_unlock_irqrestore(port, flags);330 331	free_irq(port->irq, port);332}333 334static void sunplus_set_termios(struct uart_port *port,335				struct ktermios *termios,336				const struct ktermios *oldtermios)337{338	u32 ext, div, div_l, div_h, baud, lcr;339	u32 clk = port->uartclk;340	unsigned long flags;341 342	baud = uart_get_baud_rate(port, termios, oldtermios, 0, port->uartclk / 16);343 344	/* baud rate = uartclk / ((16 * divisor + 1) + divisor_ext) */345	clk += baud >> 1;346	div = clk / baud;347	ext = div & 0x0F;348	div = (div >> 4) - 1;349	div_l = (div & 0xFF) | (ext << 12);350	div_h = div >> 8;351 352	switch (termios->c_cflag & CSIZE) {353	case CS5:354		lcr = UART_LCR_WLEN5;355		break;356	case CS6:357		lcr = UART_LCR_WLEN6;358		break;359	case CS7:360		lcr = UART_LCR_WLEN7;361		break;362	default:363		lcr = UART_LCR_WLEN8;364		break;365	}366 367	if (termios->c_cflag & CSTOPB)368		lcr |= UART_LCR_STOP;369 370	if (termios->c_cflag & PARENB) {371		lcr |= UART_LCR_PARITY;372 373		if (!(termios->c_cflag & PARODD))374			lcr |= UART_LCR_EPAR;375	}376 377	uart_port_lock_irqsave(port, &flags);378 379	uart_update_timeout(port, termios->c_cflag, baud);380 381	port->read_status_mask = 0;382	if (termios->c_iflag & INPCK)383		port->read_status_mask |= SUP_UART_LSR_PE | SUP_UART_LSR_FE;384 385	if (termios->c_iflag & (BRKINT | PARMRK))386		port->read_status_mask |= SUP_UART_LSR_BC;387 388	/* Characters to ignore */389	port->ignore_status_mask = 0;390	if (termios->c_iflag & IGNPAR)391		port->ignore_status_mask |= SUP_UART_LSR_FE | SUP_UART_LSR_PE;392 393	if (termios->c_iflag & IGNBRK) {394		port->ignore_status_mask |= SUP_UART_LSR_BC;395 396		if (termios->c_iflag & IGNPAR)397			port->ignore_status_mask |= SUP_UART_LSR_OE;398	}399 400	/* Ignore all characters if CREAD is not set */401	if ((termios->c_cflag & CREAD) == 0) {402		port->ignore_status_mask |= SUP_DUMMY_READ;403		/* flush rx data FIFO */404		writel(0, port->membase + SUP_UART_RX_RESIDUE);405	}406 407	/* Settings for baud rate divisor and lcr */408	writel(div_h, port->membase + SUP_UART_DIV_H);409	writel(div_l, port->membase + SUP_UART_DIV_L);410	writel(lcr, port->membase + SUP_UART_LCR);411 412	uart_port_unlock_irqrestore(port, flags);413}414 415static void sunplus_set_ldisc(struct uart_port *port, struct ktermios *termios)416{417	int new = termios->c_line;418 419	if (new == N_PPS)420		port->flags |= UPF_HARDPPS_CD;421	else422		port->flags &= ~UPF_HARDPPS_CD;423}424 425static const char *sunplus_type(struct uart_port *port)426{427	return port->type == PORT_SUNPLUS ? "sunplus_uart" : NULL;428}429 430static void sunplus_config_port(struct uart_port *port, int type)431{432	if (type & UART_CONFIG_TYPE)433		port->type = PORT_SUNPLUS;434}435 436static int sunplus_verify_port(struct uart_port *port, struct serial_struct *ser)437{438	if (ser->type != PORT_UNKNOWN && ser->type != PORT_SUNPLUS)439		return -EINVAL;440 441	return 0;442}443 444#if defined(CONFIG_SERIAL_SUNPLUS_CONSOLE) || defined(CONFIG_CONSOLE_POLL)445static void wait_for_xmitr(struct uart_port *port)446{447	unsigned int val;448	int ret;449 450	/* Wait while FIFO is full or timeout */451	ret = readl_poll_timeout_atomic(port->membase + SUP_UART_LSR, val,452					(val & SUP_UART_LSR_TX), 1, 10000);453 454	if (ret == -ETIMEDOUT) {455		dev_err(port->dev, "Timeout waiting while UART TX FULL\n");456		return;457	}458}459#endif460 461#ifdef CONFIG_CONSOLE_POLL462static void sunplus_poll_put_char(struct uart_port *port, unsigned char data)463{464	wait_for_xmitr(port);465	sp_uart_put_char(port, data);466}467 468static int sunplus_poll_get_char(struct uart_port *port)469{470	unsigned int lsr = readl(port->membase + SUP_UART_LSR);471 472	if (!(lsr & SUP_UART_LSR_RX))473		return NO_POLL_CHAR;474 475	return readl(port->membase + SUP_UART_DATA);476}477#endif478 479static const struct uart_ops sunplus_uart_ops = {480	.tx_empty	= sunplus_tx_empty,481	.set_mctrl	= sunplus_set_mctrl,482	.get_mctrl	= sunplus_get_mctrl,483	.stop_tx	= sunplus_stop_tx,484	.start_tx	= sunplus_start_tx,485	.stop_rx	= sunplus_stop_rx,486	.break_ctl	= sunplus_break_ctl,487	.startup	= sunplus_startup,488	.shutdown	= sunplus_shutdown,489	.set_termios	= sunplus_set_termios,490	.set_ldisc	= sunplus_set_ldisc,491	.type		= sunplus_type,492	.config_port	= sunplus_config_port,493	.verify_port	= sunplus_verify_port,494#ifdef CONFIG_CONSOLE_POLL495	.poll_put_char	= sunplus_poll_put_char,496	.poll_get_char	= sunplus_poll_get_char,497#endif498};499 500#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE501static struct sunplus_uart_port *sunplus_console_ports[SUP_UART_NR];502 503static void sunplus_uart_console_putchar(struct uart_port *port,504					 unsigned char ch)505{506	wait_for_xmitr(port);507	sp_uart_put_char(port, ch);508}509 510static void sunplus_console_write(struct console *co,511				  const char *s,512				  unsigned int count)513{514	unsigned long flags;515	int locked = 1;516 517	if (oops_in_progress)518		locked = uart_port_trylock_irqsave(&sunplus_console_ports[co->index]->port, &flags);519	else520		uart_port_lock_irqsave(&sunplus_console_ports[co->index]->port, &flags);521 522	uart_console_write(&sunplus_console_ports[co->index]->port, s, count,523			   sunplus_uart_console_putchar);524 525	if (locked)526		uart_port_unlock_irqrestore(&sunplus_console_ports[co->index]->port, flags);527}528 529static int __init sunplus_console_setup(struct console *co, char *options)530{531	struct sunplus_uart_port *sup;532	int baud = 115200;533	int bits = 8;534	int parity = 'n';535	int flow = 'n';536 537	if (co->index < 0 || co->index >= SUP_UART_NR)538		return -EINVAL;539 540	sup = sunplus_console_ports[co->index];541	if (!sup)542		return -ENODEV;543 544	if (options)545		uart_parse_options(options, &baud, &parity, &bits, &flow);546 547	return uart_set_options(&sup->port, co, baud, parity, bits, flow);548}549 550static struct uart_driver sunplus_uart_driver;551static struct console sunplus_uart_console = {552	.name		= "ttySUP",553	.write		= sunplus_console_write,554	.device		= uart_console_device,555	.setup		= sunplus_console_setup,556	.flags		= CON_PRINTBUFFER,557	.index		= -1,558	.data		= &sunplus_uart_driver559};560 561#define	SERIAL_SUNPLUS_CONSOLE	(&sunplus_uart_console)562#else563#define	SERIAL_SUNPLUS_CONSOLE	NULL564#endif565 566static struct uart_driver sunplus_uart_driver = {567	.owner		= THIS_MODULE,568	.driver_name	= "sunplus_uart",569	.dev_name	= "ttySUP",570	.major		= TTY_MAJOR,571	.minor		= 64,572	.nr		= SUP_UART_NR,573	.cons		= SERIAL_SUNPLUS_CONSOLE,574};575 576static void sunplus_uart_disable_unprepare(void *data)577{578	clk_disable_unprepare(data);579}580 581static void sunplus_uart_reset_control_assert(void *data)582{583	reset_control_assert(data);584}585 586static int sunplus_uart_probe(struct platform_device *pdev)587{588	struct sunplus_uart_port *sup;589	struct uart_port *port;590	struct resource *res;591	int ret, irq;592 593	pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");594 595	if (pdev->id < 0 || pdev->id >= SUP_UART_NR)596		return -EINVAL;597 598	sup = devm_kzalloc(&pdev->dev, sizeof(*sup), GFP_KERNEL);599	if (!sup)600		return -ENOMEM;601 602	sup->clk = devm_clk_get_optional(&pdev->dev, NULL);603	if (IS_ERR(sup->clk))604		return dev_err_probe(&pdev->dev, PTR_ERR(sup->clk), "clk not found\n");605 606	ret = clk_prepare_enable(sup->clk);607	if (ret)608		return ret;609 610	ret = devm_add_action_or_reset(&pdev->dev, sunplus_uart_disable_unprepare, sup->clk);611	if (ret)612		return ret;613 614	sup->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);615	if (IS_ERR(sup->rstc))616		return dev_err_probe(&pdev->dev, PTR_ERR(sup->rstc), "rstc not found\n");617 618	port = &sup->port;619 620	port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);621	if (IS_ERR(port->membase))622		return dev_err_probe(&pdev->dev, PTR_ERR(port->membase), "membase not found\n");623 624	irq = platform_get_irq(pdev, 0);625	if (irq < 0)626		return irq;627 628	port->mapbase = res->start;629	port->uartclk = clk_get_rate(sup->clk);630	port->line = pdev->id;631	port->irq = irq;632	port->dev = &pdev->dev;633	port->iotype = UPIO_MEM;634	port->ops = &sunplus_uart_ops;635	port->flags = UPF_BOOT_AUTOCONF;636	port->fifosize = 128;637 638	ret = reset_control_deassert(sup->rstc);639	if (ret)640		return ret;641 642	ret = devm_add_action_or_reset(&pdev->dev, sunplus_uart_reset_control_assert, sup->rstc);643	if (ret)644		return ret;645 646#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE647	sunplus_console_ports[sup->port.line] = sup;648#endif649 650	platform_set_drvdata(pdev, &sup->port);651 652	ret = uart_add_one_port(&sunplus_uart_driver, &sup->port);653#ifdef CONFIG_SERIAL_SUNPLUS_CONSOLE654	if (ret)655		sunplus_console_ports[sup->port.line] = NULL;656#endif657 658	return ret;659}660 661static void sunplus_uart_remove(struct platform_device *pdev)662{663	struct sunplus_uart_port *sup = platform_get_drvdata(pdev);664 665	uart_remove_one_port(&sunplus_uart_driver, &sup->port);666}667 668static int __maybe_unused sunplus_uart_suspend(struct device *dev)669{670	struct sunplus_uart_port *sup = dev_get_drvdata(dev);671 672	if (!uart_console(&sup->port))673		uart_suspend_port(&sunplus_uart_driver, &sup->port);674 675	return 0;676}677 678static int __maybe_unused sunplus_uart_resume(struct device *dev)679{680	struct sunplus_uart_port *sup = dev_get_drvdata(dev);681 682	if (!uart_console(&sup->port))683		uart_resume_port(&sunplus_uart_driver, &sup->port);684 685	return 0;686}687 688static const struct dev_pm_ops sunplus_uart_pm_ops = {689	SET_SYSTEM_SLEEP_PM_OPS(sunplus_uart_suspend, sunplus_uart_resume)690};691 692static const struct of_device_id sp_uart_of_match[] = {693	{ .compatible = "sunplus,sp7021-uart" },694	{}695};696MODULE_DEVICE_TABLE(of, sp_uart_of_match);697 698static struct platform_driver sunplus_uart_platform_driver = {699	.probe		= sunplus_uart_probe,700	.remove_new	= sunplus_uart_remove,701	.driver = {702		.name	= "sunplus_uart",703		.of_match_table = sp_uart_of_match,704		.pm     = &sunplus_uart_pm_ops,705	}706};707 708static int __init sunplus_uart_init(void)709{710	int ret;711 712	ret = uart_register_driver(&sunplus_uart_driver);713	if (ret)714		return ret;715 716	ret = platform_driver_register(&sunplus_uart_platform_driver);717	if (ret)718		uart_unregister_driver(&sunplus_uart_driver);719 720	return ret;721}722module_init(sunplus_uart_init);723 724static void __exit sunplus_uart_exit(void)725{726	platform_driver_unregister(&sunplus_uart_platform_driver);727	uart_unregister_driver(&sunplus_uart_driver);728}729module_exit(sunplus_uart_exit);730 731#ifdef CONFIG_SERIAL_EARLYCON732static void sunplus_uart_putc(struct uart_port *port, unsigned char c)733{734	unsigned int val;735	int ret;736 737	ret = readl_poll_timeout_atomic(port->membase + SUP_UART_LSR, val,738					(val & UART_LSR_TEMT), 1, 10000);739	if (ret)740		return;741 742	writel(c, port->membase + SUP_UART_DATA);743}744 745static void sunplus_uart_early_write(struct console *con, const char *s, unsigned int n)746{747	struct earlycon_device *dev = con->data;748 749	uart_console_write(&dev->port, s, n, sunplus_uart_putc);750}751 752static int __init753sunplus_uart_early_setup(struct earlycon_device *dev, const char *opt)754{755	if (!(dev->port.membase || dev->port.iobase))756		return -ENODEV;757 758	dev->con->write = sunplus_uart_early_write;759 760	return 0;761}762OF_EARLYCON_DECLARE(sunplus_uart, "sunplus,sp7021-uart", sunplus_uart_early_setup);763#endif764 765MODULE_DESCRIPTION("Sunplus UART driver");766MODULE_AUTHOR("Hammer Hsieh <hammerh0314@gmail.com>");767MODULE_LICENSE("GPL v2");768