18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
38c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
48c2ecf20Sopenharmony_ci * for more details.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2009 Lemote, Inc.
98c2ecf20Sopenharmony_ci * Author: Yan hua (yanhua@lemote.com)
108c2ecf20Sopenharmony_ci * Author: Wu Zhangjin (wuzhangjin@gmail.com)
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/io.h>
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/serial_8250.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <asm/bootinfo.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <loongson.h>
208c2ecf20Sopenharmony_ci#include <machine.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define PORT(int, clk)			\
238c2ecf20Sopenharmony_ci{								\
248c2ecf20Sopenharmony_ci	.irq		= int,					\
258c2ecf20Sopenharmony_ci	.uartclk	= clk,					\
268c2ecf20Sopenharmony_ci	.iotype		= UPIO_PORT,				\
278c2ecf20Sopenharmony_ci	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
288c2ecf20Sopenharmony_ci	.regshift	= 0,					\
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define PORT_M(int, clk)				\
328c2ecf20Sopenharmony_ci{								\
338c2ecf20Sopenharmony_ci	.irq		= MIPS_CPU_IRQ_BASE + (int),		\
348c2ecf20Sopenharmony_ci	.uartclk	= clk,					\
358c2ecf20Sopenharmony_ci	.iotype		= UPIO_MEM,				\
368c2ecf20Sopenharmony_ci	.membase	= (void __iomem *)NULL,			\
378c2ecf20Sopenharmony_ci	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
388c2ecf20Sopenharmony_ci	.regshift	= 0,					\
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic struct plat_serial8250_port uart8250_data[MACH_LOONGSON_END + 1] = {
428c2ecf20Sopenharmony_ci	[MACH_LOONGSON_UNKNOWN]	= {},
438c2ecf20Sopenharmony_ci	[MACH_LEMOTE_FL2E]	= PORT(4, 1843200),
448c2ecf20Sopenharmony_ci	[MACH_LEMOTE_FL2F]	= PORT(3, 1843200),
458c2ecf20Sopenharmony_ci	[MACH_LEMOTE_ML2F7]	= PORT_M(3, 3686400),
468c2ecf20Sopenharmony_ci	[MACH_LEMOTE_YL2F89]	= PORT_M(3, 3686400),
478c2ecf20Sopenharmony_ci	[MACH_DEXXON_GDIUM2F10]	= PORT_M(3, 3686400),
488c2ecf20Sopenharmony_ci	[MACH_LEMOTE_NAS]	= PORT_M(3, 3686400),
498c2ecf20Sopenharmony_ci	[MACH_LEMOTE_LL2F]	= PORT(3, 1843200),
508c2ecf20Sopenharmony_ci	[MACH_LOONGSON_END]	= {},
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic struct platform_device uart8250_device = {
548c2ecf20Sopenharmony_ci	.name = "serial8250",
558c2ecf20Sopenharmony_ci	.id = PLAT8250_DEV_PLATFORM,
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic int __init serial_init(void)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	unsigned char iotype;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	iotype = uart8250_data[mips_machtype].iotype;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	if (UPIO_MEM == iotype) {
658c2ecf20Sopenharmony_ci		uart8250_data[mips_machtype].mapbase =
668c2ecf20Sopenharmony_ci			loongson_uart_base;
678c2ecf20Sopenharmony_ci		uart8250_data[mips_machtype].membase =
688c2ecf20Sopenharmony_ci			(void __iomem *)_loongson_uart_base;
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci	else if (UPIO_PORT == iotype)
718c2ecf20Sopenharmony_ci		uart8250_data[mips_machtype].iobase =
728c2ecf20Sopenharmony_ci			loongson_uart_base - LOONGSON_PCIIO_BASE;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	memset(&uart8250_data[mips_machtype + 1], 0,
758c2ecf20Sopenharmony_ci			sizeof(struct plat_serial8250_port));
768c2ecf20Sopenharmony_ci	uart8250_device.dev.platform_data = &uart8250_data[mips_machtype];
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return platform_device_register(&uart8250_device);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_cimodule_init(serial_init);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic void __exit serial_exit(void)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	platform_device_unregister(&uart8250_device);
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_cimodule_exit(serial_exit);
87