From 2d6ca34280be06dfe38c26cf23539a1cd293a9f7 Mon Sep 17 00:00:00 2001 From: lhh Date: Fri, 22 Oct 2010 21:58:23 +0800 Subject: [PATCH] add rk29 serial and console --- arch/arm/configs/rk29_sdk_defconfig | 106 ++- arch/arm/mach-rk29/Makefile | 2 +- arch/arm/mach-rk29/board-rk29sdk.c | 11 +- arch/arm/mach-rk29/devices.c | 117 +++ arch/arm/mach-rk29/devices.h | 25 + arch/arm/mach-rk29/include/mach/gpio.h | 19 + arch/arm/mach-rk29/include/mach/iomux.h | 57 ++ arch/arm/mach-rk29/include/mach/rk29_iomap.h | 1 + arch/arm/mach-rk29/io.c | 1 + arch/arm/mach-rk29/iomux.c | 33 + arch/arm/mach-rk29/timer.c | 37 +- drivers/serial/Kconfig | 26 +- drivers/serial/Makefile | 2 +- drivers/serial/rk29_serial.c | 710 +++++++++++++++++++ include/linux/serial_core.h | 3 +- 15 files changed, 1089 insertions(+), 61 deletions(-) create mode 100644 arch/arm/mach-rk29/devices.c create mode 100644 arch/arm/mach-rk29/devices.h create mode 100644 arch/arm/mach-rk29/include/mach/gpio.h create mode 100644 arch/arm/mach-rk29/include/mach/iomux.h create mode 100644 arch/arm/mach-rk29/iomux.c create mode 100644 drivers/serial/rk29_serial.c diff --git a/arch/arm/configs/rk29_sdk_defconfig b/arch/arm/configs/rk29_sdk_defconfig index 3687c8f75a86..b124bcd616aa 100644 --- a/arch/arm/configs/rk29_sdk_defconfig +++ b/arch/arm/configs/rk29_sdk_defconfig @@ -67,10 +67,16 @@ CONFIG_RESOURCE_COUNTERS=y # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y +CONFIG_INITRAMFS_SOURCE="../initramfs" +CONFIG_INITRAMFS_ROOT_UID=0 +CONFIG_INITRAMFS_ROOT_GID=0 +# CONFIG_RD_GZIP is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +CONFIG_INITRAMFS_COMPRESSION_NONE=y +# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set +# CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set +# CONFIG_INITRAMFS_COMPRESSION_LZMA is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -322,13 +328,50 @@ CONFIG_NET=y # # Networking options # -# CONFIG_PACKET is not set -# CONFIG_UNIX is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set -# CONFIG_INET is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set CONFIG_ANDROID_PARANOID_NETWORK=y # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_NET_DSA is not set @@ -339,6 +382,7 @@ CONFIG_ANDROID_PARANOID_NETWORK=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set +# CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set # CONFIG_IEEE802154 is not set @@ -353,6 +397,7 @@ CONFIG_ANDROID_PARANOID_NETWORK=y # CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set # CONFIG_WIRELESS is not set # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set @@ -414,6 +459,7 @@ CONFIG_HAVE_IDE=y # CONFIG_MD is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set @@ -490,20 +536,21 @@ CONFIG_DEVKMEM=y # # Non-8250 serial port support # +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_RK29=y +# CONFIG_UART0_RK29 is not set +CONFIG_UART1_RK29=y +# CONFIG_UART2_RK29 is not set +# CONFIG_UART3_RK29 is not set +CONFIG_SERIAL_RK29_CONSOLE=y CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -CONFIG_R3964=y -CONFIG_RAW_DRIVER=y -CONFIG_MAX_RAW_DEVS=256 +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set # CONFIG_DCC_TTY is not set # CONFIG_I2C is not set @@ -585,9 +632,16 @@ CONFIG_STAGING=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y # CONFIG_ANDROID_LOGGER is not set -# CONFIG_ANDROID_RAM_CONSOLE is not set +CONFIG_ANDROID_RAM_CONSOLE=y +CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y +CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y +CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE=128 +CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE=16 +CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE=8 +CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d +# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set # CONFIG_ANDROID_TIMED_OUTPUT is not set -# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set +CONFIG_ANDROID_LOW_MEMORY_KILLER=y # # Qualcomm MSM Camera And Video @@ -710,6 +764,13 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -756,6 +817,7 @@ CONFIG_NLS_ISO8859_15=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set # # Kernel hacking @@ -822,8 +884,7 @@ CONFIG_ARM_UNWIND=y # CONFIG_DEBUG_USER is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_LL is not set # # Security options @@ -943,8 +1004,9 @@ CONFIG_CRC16=y CONFIG_CRC32=y # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_DECOMPRESS_GZIP=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y diff --git a/arch/arm/mach-rk29/Makefile b/arch/arm/mach-rk29/Makefile index ad969989dba7..e9fb9849bdf7 100644 --- a/arch/arm/mach-rk29/Makefile +++ b/arch/arm/mach-rk29/Makefile @@ -1,2 +1,2 @@ -obj-y += timer.o io.o +obj-y += timer.o io.o devices.o iomux.o obj-$(CONFIG_MACH_RK29SDK) += board-rk29sdk.o diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index 231e1327e1a1..234f7415f23e 100644 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -38,8 +38,17 @@ #include #include +#include "devices.h" + extern struct sys_timer rk29_timer; +static struct platform_device *devices[] __initdata = { +#ifdef CONFIG_UART1_RK29 + &rk29_device_uart1, +#endif + +}; + static void __init rk29_gic_init_irq(void) { gic_dist_init(0, (void __iomem *)RK29_GICPERI_BASE, 32); @@ -54,7 +63,7 @@ static void __init machine_rk29_init_irq(void) } static void __init machine_rk29_board_init(void) { - + platform_add_devices(devices, ARRAY_SIZE(devices)); } static void __init machine_rk29_mapio(void) diff --git a/arch/arm/mach-rk29/devices.c b/arch/arm/mach-rk29/devices.c new file mode 100644 index 000000000000..940f651cd4de --- /dev/null +++ b/arch/arm/mach-rk29/devices.c @@ -0,0 +1,117 @@ +/* arch/arm/mach-rk29/devices.c + * + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include + + +/* + * rk29 4 uarts device + */ +#ifdef CONFIG_UART0_RK29 +static struct resource resources_uart0[] = { + { + .start = IRQ_UART0, + .end = IRQ_UART0, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK29_UART0_PHYS, + .end = RK29_UART0_PHYS + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, +}; +#endif +#ifdef CONFIG_UART1_RK29 +static struct resource resources_uart1[] = { + { + .start = IRQ_UART1, + .end = IRQ_UART1, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK29_UART1_PHYS, + .end = RK29_UART1_PHYS + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, +}; +#endif +#ifdef CONFIG_UART2_RK29 +static struct resource resources_uart2[] = { + { + .start = IRQ_UART2, + .end = IRQ_UART2, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK29_UART2_PHYS, + .end = RK29_UART2_PHYS + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, +}; +#endif +#ifdef CONFIG_UART3_RK29 +static struct resource resources_uart3[] = { + { + .start = IRQ_UART3, + .end = IRQ_UART3, + .flags = IORESOURCE_IRQ, + }, + { + .start = RK29_UART3_PHYS, + .end = RK29_UART3_PHYS + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, +}; +#endif +#ifdef CONFIG_UART0_RK29 +struct platform_device rk29_device_uart0 = { + .name = "rk29_serial", + .id = 0, + .num_resources = ARRAY_SIZE(resources_uart0), + .resource = resources_uart0, + .dev = { + .platform_data = &rk2818_serial0_platdata, + }, +}; +#endif +#ifdef CONFIG_UART1_RK29 +struct platform_device rk29_device_uart1 = { + .name = "rk29_serial", + .id = 1, + .num_resources = ARRAY_SIZE(resources_uart1), + .resource = resources_uart1, +}; +#endif +#ifdef CONFIG_UART2_RK29 +struct platform_device rk29_device_uart2 = { + .name = "rk29_serial", + .id = 2, + .num_resources = ARRAY_SIZE(resources_uart2), + .resource = resources_uart2, +}; +#endif +#ifdef CONFIG_UART3_RK29 +struct platform_device rk29_device_uart3 = { + .name = "rk29_serial", + .id = 3, + .num_resources = ARRAY_SIZE(resources_uart3), + .resource = resources_uart3, +}; +#endif \ No newline at end of file diff --git a/arch/arm/mach-rk29/devices.h b/arch/arm/mach-rk29/devices.h new file mode 100644 index 000000000000..44766c99c214 --- /dev/null +++ b/arch/arm/mach-rk29/devices.h @@ -0,0 +1,25 @@ +/* /arch/arm/mach-rk29/devices.h + * + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ARCH_ARM_MACH_RK29_DEVICES_H +#define __ARCH_ARM_MACH_RK29_DEVICES_H + + +extern struct platform_device rk29_device_uart0; +extern struct platform_device rk29_device_uart1; +extern struct platform_device rk29_device_uart2; +extern struct platform_device rk29_device_uart3; + +#endif \ No newline at end of file diff --git a/arch/arm/mach-rk29/include/mach/gpio.h b/arch/arm/mach-rk29/include/mach/gpio.h new file mode 100644 index 000000000000..23263b155d6c --- /dev/null +++ b/arch/arm/mach-rk29/include/mach/gpio.h @@ -0,0 +1,19 @@ +/* arch/arm/mach-rk29/include/mach/gpio.h + * + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __ARCH_ARM_MACH_RK29_GPIO_H +#define __ARCH_ARM_MACH_RK29_GPIO_H + + +#endif diff --git a/arch/arm/mach-rk29/include/mach/iomux.h b/arch/arm/mach-rk29/include/mach/iomux.h new file mode 100644 index 000000000000..9b8d0e78e75d --- /dev/null +++ b/arch/arm/mach-rk29/include/mach/iomux.h @@ -0,0 +1,57 @@ +/* + * arch/arm/mach-rk29/include/mach/iomux.h + * + *Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __RK29_IOMUX_H__ +#define __RK29_IOMUX_H__ + +#include "rk29_iomap.h" + +#define RK29_IOMUX_GPIO0L_CON RK29_GRF_BASE+0x48 +#define RK29_IOMUX_GPIO0H_CON RK29_GRF_BASE+0x4c +#define RK29_IOMUX_GPIO1L_CON RK29_GRF_BASE+0x50 +#define RK29_IOMUX_GPIO1H_CON RK29_GRF_BASE+0x54 +#define RK29_IOMUX_GPIO2L_CON RK29_GRF_BASE+0x58 +#define RK29_IOMUX_GPIO2H_CON RK29_GRF_BASE+0x5c +#define RK29_IOMUX_GPIO3L_CON RK29_GRF_BASE+0x60 +#define RK29_IOMUX_GPIO3H_CON RK29_GRF_BASE+0x64 +#define RK29_IOMUX_GPIO4L_CON RK29_GRF_BASE+0x68 +#define RK29_IOMUX_GPIO4H_CON RK29_GRF_BASE+0x6c +#define RK29_IOMUX_GPIO5L_CON RK29_GRF_BASE+0x70 +#define RK29_IOMUX_GPIO5H_CON RK29_GRF_BASE+0x74 + + +#define MUX_CFG(desc,reg,off,interl,mux_mode,bflags) \ +{ \ + .name = desc, \ + .offset = off, \ + .interleave = interl, \ + .mux_reg = RK29_IOMUX_##reg##_CON, \ + .mode = mux_mode, \ + .premode = mux_mode, \ + .flags = bflags, \ +}, + +struct mux_config { + char *name; + const unsigned int offset; + unsigned int mode; + unsigned int premode; + const unsigned int mux_reg; + const unsigned int interleave; + unsigned int flags; +}; + + +#endif \ No newline at end of file diff --git a/arch/arm/mach-rk29/include/mach/rk29_iomap.h b/arch/arm/mach-rk29/include/mach/rk29_iomap.h index c38977d1d299..49c90cc63450 100644 --- a/arch/arm/mach-rk29/include/mach/rk29_iomap.h +++ b/arch/arm/mach-rk29/include/mach/rk29_iomap.h @@ -103,6 +103,7 @@ #define RK29_CRU_SIZE SZ_16K #define RK29_PMU_PHYS 0x20004000 #define RK29_PMU_SIZE SZ_16K +#define RK29_GRF_BASE (RK29_ADDR_BASE1+0x8000) #define RK29_GRF_PHYS 0x20008000 #define RK29_GRF_SIZE SZ_16K #define RK29_RTC_PHYS 0x2000C000 diff --git a/arch/arm/mach-rk29/io.c b/arch/arm/mach-rk29/io.c index 8fd8840c44b5..d8db9973e8c4 100644 --- a/arch/arm/mach-rk29/io.c +++ b/arch/arm/mach-rk29/io.c @@ -36,6 +36,7 @@ static struct map_desc rk29_io_desc[] __initdata = { RK29_DEVICE(TIMER1), RK29_DEVICE(DDRC), RK29_DEVICE(UART1), + RK29_DEVICE(GRF), }; void __init rk29_map_common_io(void) diff --git a/arch/arm/mach-rk29/iomux.c b/arch/arm/mach-rk29/iomux.c new file mode 100644 index 000000000000..5000c548b1e6 --- /dev/null +++ b/arch/arm/mach-rk29/iomux.c @@ -0,0 +1,33 @@ +/* + * arch/arm/mach-rk29/iomux.c + * + *Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include +#include + + +static struct mux_config rk29_muxs[] = { +/* + * description mux mode mux mux + * reg offset inter mode + */ +//MUX_CFG(GPIOE_I2C0_SEL_NAME, GPIO0L, 30, 2, 0, DEFAULT) + +}; \ No newline at end of file diff --git a/arch/arm/mach-rk29/timer.c b/arch/arm/mach-rk29/timer.c index 4826186b82e4..5f3d4364184e 100644 --- a/arch/arm/mach-rk29/timer.c +++ b/arch/arm/mach-rk29/timer.c @@ -56,19 +56,12 @@ #define TIMER_CLKSRC_NAME "timer1" //static struct clk *timer_clk; -static volatile unsigned long timer_mult; /* timer count = cycle * timer_mult */ -void rk29_timer_update_mult(void) -{ - //if (timer_clk) - // timer_mult = clk_get_rate(timer_clk) / 1000000; - timer_mult = 24000000 / 1000000; -} static int rk29_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { RK_TIMER_DISABLE(TIMER_CLKEVT); - RK_TIMER_SETCOUNT(TIMER_CLKEVT, cycles * timer_mult); + RK_TIMER_SETCOUNT(TIMER_CLKEVT, cycles ); RK_TIMER_ENABLE(TIMER_CLKEVT); return 0; @@ -117,41 +110,17 @@ static struct irqaction rk29_timer_clockevent_irq = { .dev_id = &rk29_timer_clockevent, }; -static int rk29_timer_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) -{ - if (val == CPUFREQ_POSTCHANGE) { - rk29_timer_update_mult(); - } - - return 0; -} - -static struct notifier_block rk29_timer_cpufreq_notifier_block = { - .notifier_call = rk29_timer_cpufreq_notifier, - .priority = 0x7ffffff, -}; - -static __init int rk29_timer_init_cpufreq(void) -{ - cpufreq_register_notifier(&rk29_timer_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - return 0; -} - -arch_initcall_sync(rk29_timer_init_cpufreq); - static __init int rk29_timer_init_clockevent(void) { struct clock_event_device *ce = &rk29_timer_clockevent; //timer_clk = clk_get(NULL, "timer"); - rk29_timer_update_mult(); - RK_TIMER_DISABLE(TIMER_CLKEVT); setup_irq(rk29_timer_clockevent_irq.irq, &rk29_timer_clockevent_irq); - ce->mult = div_sc(1000000, NSEC_PER_SEC, ce->shift); - ce->max_delta_ns = clockevent_delta2ns(0xFFFFFFFFUL / 256, ce); // max pclk < 256MHz + ce->mult = div_sc(24000000, NSEC_PER_SEC, ce->shift); + ce->max_delta_ns = clockevent_delta2ns(0xFFFFFFFFUL, ce); // max pclk < 256MHz ce->min_delta_ns = clockevent_delta2ns(1, ce) + 1; ce->cpumask = cpumask_of(0); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 040967f243a1..326b5c9f6171 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -1502,6 +1502,30 @@ config SERIAL_RK2818_CONSOLE bool "Rockchip rk2818 serial console support" depends on SERIAL_RK2818=y select SERIAL_CORE_CONSOLE + +config SERIAL_RK29 + bool "RockChip rk29 serial port support" + depends on ARM && ARCH_RK29 + select SERIAL_CORE + +config UART0_RK29 + bool "RockChip rk29 serial port 0 support" + depends on SERIAL_RK29 + +config UART1_RK29 + bool "RockChip rk29 serial port 1 support" + depends on SERIAL_RK29 + +config UART2_RK29 + bool "RockChip rk29 serial port 2 support" + depends on SERIAL_RK29 + +config UART3_RK29 + bool "RockChip rk29 serial port 3 support" + depends on SERIAL_RK29 - +config SERIAL_RK29_CONSOLE + bool "Rockchip rk29 serial console support" + depends on SERIAL_RK29=y + select SERIAL_CORE_CONSOLE endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 10e42a48d962..5e8f87950019 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -81,5 +81,5 @@ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_RK2818) += rk2818_serial.o - +obj-$(CONFIG_SERIAL_RK29) += rk29_serial.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o diff --git a/drivers/serial/rk29_serial.c b/drivers/serial/rk29_serial.c new file mode 100644 index 000000000000..0fd57bfd70ad --- /dev/null +++ b/drivers/serial/rk29_serial.c @@ -0,0 +1,710 @@ +/* + * drivers/serial/rk29_serial.c - driver for rk29 serial device and console + * + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#if defined(CONFIG_SERIAL_RK29_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk2818_serial.h" + +/* + * We wrap our port structure around the generic uart_port. + */ +struct rk29_port { + struct uart_port uart; + char name[16]; + struct clk *clk; + unsigned int imr; +}; + +#define UART_TO_RK29(uart_port) ((struct rk29_port *) uart_port) +#define RK29_SERIAL_MAJOR TTY_MAJOR +#define RK29_SERIAL_MINOR 64 + + +static inline void rk29_uart_write(struct uart_port *port, unsigned int val, + unsigned int off) +{ + __raw_writel(val, port->membase + off); +} + +static inline unsigned int rk29_uart_read(struct uart_port *port, unsigned int off) +{ + return __raw_readl(port->membase + off); +} + +static int rk29_set_baud_rate(struct uart_port *port, unsigned int baud) +{ + unsigned int uartTemp; + + rk29_uart_write(port,rk29_uart_read(port,UART_LCR) | LCR_DLA_EN,UART_LCR); + uartTemp = port->uartclk / (16 * baud); + rk29_uart_write(port,uartTemp & 0xff,UART_DLL); + rk29_uart_write(port,(uartTemp>>8) & 0xff,UART_DLH); + rk29_uart_write(port,rk29_uart_read(port,UART_LCR) & (~LCR_DLA_EN),UART_LCR); + return baud; +} + +/* + * ÅжϷ¢ËÍ»º³åÇøÊÇ·ñΪ¿Õ + *ÏÈÒÔFIFO´ò¿ª×ö£¬ºóÃæ¿ÉÒÔ×ö³ÉFIFO¹Ø»òFIFO¿ª¡£ + */ +static u_int rk29_serial_tx_empty(struct uart_port *port) +{ + while(!(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY)) + cpu_relax(); + if(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY) + { + return (1);///1£º¿Õ + }else{ + return (0);///0:·Ç¿Õ + } +} + +/* + * Power / Clock management. + */ +static void rk29_serial_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + struct rk29_port *rk29_port = UART_TO_RK29(port); + + switch (state) { + case 0: + /* + * Enable the peripheral clock for this serial port. + * This is called on uart_open() or a resume event. + */ + //clk_enable(rk29_port->clk); + break; + case 3: + /* + * Disable the peripheral clock for this serial port. + * This is called on uart_close() or a suspend event. + */ + //clk_disable(rk29_port->clk); + break; + default: + printk(KERN_ERR "rk29_serial: unknown pm %d\n", state); + } +} + +/* + * Return string describing the specified port + */ +static const char *rk29_serial_type(struct uart_port *port) +{ + return (port->type == PORT_RK29) ? "RK29_SERIAL" : NULL; +} + +static void rk29_serial_enable_ms(struct uart_port *port) +{ + #ifdef DEBUG_LHH + printk("Enter::%s\n",__FUNCTION__); + #endif +} + +/* no modem control lines */ +static unsigned int rk29_serial_get_mctrl(struct uart_port *port) +{ + unsigned int result = 0; + unsigned int status; + + status = rk29_uart_read(port,UART_MSR); + if (status & UART_MSR_URCTS) + { + result = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; + printk("UART_GET_MSR:0x%x\n",result); + }else{ + result = TIOCM_CAR | TIOCM_DSR; + printk("UART_GET_MSR:0x%x\n",result); + } + return result; +} + +static void rk29_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + #ifdef DEBUG_LHH + printk("Enter::%s\n",__FUNCTION__); + #endif +} + +/* + * Stop transmitting. + */ +static void rk29_serial_stop_tx(struct uart_port *port) +{ + #ifdef DEBUG_LHH + printk("Enter::%s\n",__FUNCTION__); + #endif +} + +/* + * Start transmitting. + */ +static void rk29_serial_start_tx(struct uart_port *port) +{ + struct circ_buf *xmit = &port->state->xmit; + while(!(uart_circ_empty(xmit))) + { + while (!(rk29_uart_read(port,UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL)){ + rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE|UART_IER_SEND_EMPTY_INT_ENABLE,UART_IER); + return; + } + rk29_uart_write(port,xmit->buf[xmit->tail],UART_THR); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } + if((uart_circ_empty(xmit))) + rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +/* + * Stop receiving - port is in process of being closed. + */ +static void rk29_serial_stop_rx(struct uart_port *port) +{ + #ifdef DEBUG_LHH + printk("Enter::%s\n",__FUNCTION__); + #endif +} + +/* + * Control the transmission of a break signal + */ +static void rk29_serial_break_ctl(struct uart_port *port, int break_state) +{ + unsigned int temp; + temp = rk29_uart_read(port,UART_LCR); + if (break_state != 0) + temp = temp & (~BREAK_CONTROL_BIT);/* start break */ + else + temp = temp | BREAK_CONTROL_BIT; /* stop break */ + rk29_uart_write(port,temp,UART_LCR); +} + + +/* + * Characters received (called from interrupt handler) + */ +static void rk29_rx_chars(struct uart_port *port) +{ + unsigned int ch, flag; + while((rk29_uart_read(port,UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY) + { + u32 lsr = rk29_uart_read(port, UART_LSR); + ch = rk29_uart_read(port,UART_RBR); + flag = TTY_NORMAL; + port->icount.rx++; + if (lsr & UART_BREAK_INT_BIT) { + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } + if (uart_handle_sysrq_char(port, ch)) + { + continue; + } + uart_insert_char(port, 0, 0, ch, flag); + } + tty_flip_buffer_push(port->state->port.tty); + +} + +/* + * Interrupt handler + */ +static irqreturn_t rk29_uart_interrupt(int irq, void *dev_id) +{ + struct uart_port *port = dev_id; + unsigned int status, pending; + + status = rk29_uart_read(port,UART_IIR); + pending = status & 0x0f; + if((pending == UART_IIR_RECV_AVAILABLE) || (pending == UART_IIR_CHAR_TIMEOUT)) + rk29_rx_chars(port); + if(pending == UART_IIR_THR_EMPTY) + rk29_serial_start_tx(port); + return IRQ_HANDLED; +} + +/* + * Disable the port + */ +static void rk29_serial_shutdown(struct uart_port *port) +{ + struct rk29_port *rk29_port = UART_TO_RK29(port); + rk29_uart_write(port,0x00,UART_IER); + //clk_disable(rk29_port->clk); + free_irq(port->irq, port); +} +/* + * Perform initialization and enable port for reception + */ +static int rk29_serial_startup(struct uart_port *port) +{ + struct rk29_port *rk29_port = UART_TO_RK29(port); + struct tty_struct *tty = port->state->port.tty; + int retval; + + retval = request_irq(port->irq,rk29_uart_interrupt,IRQF_SHARED, + tty ? tty->name : "rk29_serial",port); + if(retval) + { + printk("\nrk29_serial_startup err \n"); + rk29_serial_shutdown(port); + return retval; + } + //clk_enable(rk29_port->clk); + rk29_uart_write(port,0xf1,UART_FCR); + rk29_uart_write(port,0x01,UART_SFE);///enable fifo + rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); //enable uart recevice IRQ + return 0; +} + +/* + * Change the port parameters + */ +static void rk29_serial_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + unsigned long flags; + unsigned int mode, baud; + unsigned int umcon,fcr; + /* Get current mode register */ + mode = rk29_uart_read(port,UART_LCR) & (BREAK_CONTROL_BIT | EVEN_PARITY_SELECT | PARITY_ENABLED + | ONE_HALF_OR_TWO_BIT | UART_DATABIT_MASK); + + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); + /* byte size */ + switch (termios->c_cflag & CSIZE) { + case CS5: + mode |= LCR_WLS_5; + break; + case CS6: + mode |= LCR_WLS_6; + break; + case CS7: + mode |= LCR_WLS_7; + break; + default: + mode |= LCR_WLS_8; + break; + } + + /* stop bits */ + if (termios->c_cflag & CSTOPB) + mode |= ONE_STOP_BIT; + + /* parity */ + if (termios->c_cflag & PARENB) + { + mode |= PARITY_ENABLED; + if (termios->c_cflag & PARODD) + mode |= ODD_PARITY; + else + mode |= EVEN_PARITY; + } + spin_lock_irqsave(&port->lock, flags); + if(termios->c_cflag & CRTSCTS) + { + /*¿ªÆôuart0Ó²¼þÁ÷¿Ø*/ + printk("start CRTSCTS control and baudrate is %d\n",baud); + umcon=rk29_uart_read(port,UART_MCR); + printk("UART_GET_MCR umcon=0x%x\n",umcon); + umcon |= UART_MCR_AFCEN; + umcon |= UART_MCR_URRTS; + umcon &=~UART_SIR_ENABLE; + rk29_uart_write(port,umcon,UART_MCR); + printk("UART_GET_MCR umcon=0x%x\n",umcon); + fcr=rk29_uart_read(port,UART_FCR); + printk("UART_GET_MCR fcr=0x%x\n",fcr); + fcr |= UART_FCR_FIFO_ENABLE; + rk29_uart_write(port,fcr,UART_FCR); + printk("UART_GET_MCR fcr=0x%x\n",fcr); + } + mode = mode | LCR_DLA_EN; + while(rk29_uart_read(port,UART_USR)&UART_USR_BUSY) + cpu_relax(); + rk29_uart_write(port,mode,UART_LCR); + baud = rk29_set_baud_rate(port, baud); + uart_update_timeout(port, termios->c_cflag, baud); + spin_unlock_irqrestore(&port->lock, flags); +} + + +static void rk29_serial_release_port(struct uart_port *port) +{ + struct platform_device *pdev = to_platform_device(port->dev); + struct resource *resource; + resource_size_t size; + + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!resource)) + return; + size = resource->end - resource->start + 1; + + release_mem_region(port->mapbase, size); + iounmap(port->membase); + port->membase = NULL; +} + +static int rk29_serial_request_port(struct uart_port *port) +{ + struct platform_device *pdev = to_platform_device(port->dev); + struct resource *resource; + resource_size_t size; + + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!resource)) + return -ENXIO; + size = resource->end - resource->start + 1; + + if (unlikely(!request_mem_region(port->mapbase, size, "rk29_serial"))) + return -EBUSY; + + port->membase = ioremap(port->mapbase, size); + if (!port->membase) { + release_mem_region(port->mapbase, size); + return -EBUSY; + } + + return 0; +} + +/* + * Configure/autoconfigure the port. + */ +static void rk29_serial_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + port->type = PORT_RK29; + rk29_serial_request_port(port); + } +} + +/* + * Verify the new serial_struct (for TIOCSSERIAL). + */ +static int rk29_serial_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if (ser->type != PORT_UNKNOWN && ser->type != PORT_RK29) + ret = -EINVAL; + if (port->irq != ser->irq) + ret = -EINVAL; + if (ser->io_type != SERIAL_IO_MEM) + ret = -EINVAL; + if (port->uartclk / 16 != ser->baud_base) + ret = -EINVAL; + if ((void *)port->mapbase != ser->iomem_base) + ret = -EINVAL; + if (port->iobase != ser->port) + ret = -EINVAL; + if (ser->hub6 != 0) + ret = -EINVAL; + return ret; +} + +#ifdef CONFIG_CONSOLE_POLL +/* + * Console polling routines for writing and reading from the uart while + * in an interrupt or debug context. + */ + +static int rk29_serial_poll_get_char(struct uart_port *port) +{ + while (!((rk29_uart_read(port, UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY)) + barrier(); + return rk29_uart_read(port, UART_RBR); +} + +static void rk29_serial_poll_put_char(struct uart_port *port, unsigned char c) +{ + while (!(rk29_uart_read(port, UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL)) + barrier(); + rk29_uart_write(port, c, UART_THR); +} +#endif /* CONFIG_CONSOLE_POLL */ + +static struct uart_ops rk29_uart_pops = { + .tx_empty = rk29_serial_tx_empty, + .set_mctrl = rk29_serial_set_mctrl, + .get_mctrl = rk29_serial_get_mctrl, + .stop_tx = rk29_serial_stop_tx, + .start_tx = rk29_serial_start_tx, + .stop_rx = rk29_serial_stop_rx, + .enable_ms = rk29_serial_enable_ms, + .break_ctl = rk29_serial_break_ctl, + .startup = rk29_serial_startup, + .shutdown = rk29_serial_shutdown, + .set_termios = rk29_serial_set_termios, + .type = rk29_serial_type, + .release_port = rk29_serial_release_port, + .request_port = rk29_serial_request_port, + .config_port = rk29_serial_config_port, + .verify_port = rk29_serial_verify_port, + .pm = rk29_serial_pm, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = rk29_serial_poll_get_char, + .poll_put_char = rk29_serial_poll_put_char, +#endif +}; + + +static struct rk29_port rk29_uart_ports[] = { + { + .uart = { + .iotype = UPIO_MEM, + .ops = &rk29_uart_pops, + .flags = UPF_BOOT_AUTOCONF, + .fifosize = 32, + .line = 0, + }, + }, + { + .uart = { + .iotype = UPIO_MEM, + .ops = &rk29_uart_pops, + .flags = UPF_BOOT_AUTOCONF, + .fifosize = 32, + .line = 1, + }, + }, + { + .uart = { + .iotype = UPIO_MEM, + .ops = &rk29_uart_pops, + .flags = UPF_BOOT_AUTOCONF, + .fifosize = 32, + .line = 2, + }, + }, + { + .uart = { + .iotype = UPIO_MEM, + .ops = &rk29_uart_pops, + .flags = UPF_BOOT_AUTOCONF, + .fifosize = 32, + .line = 3, + }, + }, +}; + +#define UART_NR ARRAY_SIZE(rk29_uart_ports) + +static inline struct uart_port *get_port_from_line(unsigned int line) +{ + return &rk29_uart_ports[line].uart; +} + +#ifdef CONFIG_SERIAL_RK29_CONSOLE +static void rk29_console_putchar(struct uart_port *port, int ch) +{ + while (!(rk29_uart_read(port,UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL)) + cpu_relax(); + rk29_uart_write(port,ch,UART_THR); +} + +/* + * Interrupts are disabled on entering + */ +static void rk29_console_write(struct console *co, const char *s, u_int count) +{ + struct uart_port *port; + struct rk29_port *rk29_port; + + BUG_ON(co->index < 0 || co->index >= UART_NR); + + port = get_port_from_line(co->index); + rk29_port = UART_TO_RK29(port); + + spin_lock(&port->lock); + uart_console_write(port, s, count, rk29_console_putchar); + spin_unlock(&port->lock); +} + +static int __init rk29_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud, flow, bits, parity; + + if (unlikely(co->index >= UART_NR || co->index < 0)) + return -ENXIO; + + port = get_port_from_line(co->index); + + if (unlikely(!port->membase)) + return -ENXIO; + + port->cons = co; + + //rk29_init_clock(port); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + bits = 8; + parity = 'n'; + flow = 'n'; + rk29_uart_write(port,rk29_uart_read(port,UART_LCR) | LCR_WLS_8 | PARITY_DISABLED | ONE_STOP_BIT,UART_LCR); /* 8N1 */ + if (baud < 300 || baud > 115200) + baud = 115200; + rk29_set_baud_rate(port, baud); + + printk(KERN_INFO "rk29_serial: console setup on port %d\n", port->line); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct uart_driver rk29_uart_driver; + +static struct console rk29_console = { + .name = "ttyS", + .write = rk29_console_write, + .device = uart_console_device, + .setup = rk29_console_setup, + .flags = CON_PRINTBUFFER, + .index = 1, + .data = &rk29_uart_driver, +}; + +#define RK29_CONSOLE (&rk29_console) + +#else +#define RK29_CONSOLE NULL +#endif + +static struct uart_driver rk29_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "rk29_serial", + .dev_name = "ttyS", + .nr = UART_NR, + .cons = RK29_CONSOLE, + .major = RK29_SERIAL_MAJOR, + .minor = RK29_SERIAL_MINOR, +}; + +static int __devinit rk29_serial_probe(struct platform_device *pdev) +{ + struct rk29_port *rk29_port; + struct resource *resource; + struct uart_port *port; + //struct rk29_serial_platform_data *pdata = pdev->dev.platform_data; + + if (unlikely(pdev->id < 0 || pdev->id >= UART_NR)) + return -ENXIO; + + printk(KERN_INFO "rk29_serial: detected port %d\n", pdev->id); + + //if (pdata && pdata->io_init) + //pdata->io_init(); + + port = get_port_from_line(pdev->id); + port->dev = &pdev->dev; + rk29_port = UART_TO_RK29(port); + + ///rk29_port->clk = clk_get(&pdev->dev, "uart"); + if (unlikely(IS_ERR(rk29_port->clk))) + return PTR_ERR(rk29_port->clk); + port->uartclk = 24000000; ///clk_get_rate(rk29_port->clk); + + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!resource)) + return -ENXIO; + port->mapbase = resource->start; + + port->irq = platform_get_irq(pdev, 0); + if (unlikely(port->irq < 0)) + return -ENXIO; + + platform_set_drvdata(pdev, port); + + return uart_add_one_port(&rk29_uart_driver, port); +} + +static int __devexit rk29_serial_remove(struct platform_device *pdev) +{ + struct rk29_port *rk29_port = platform_get_drvdata(pdev); + + ///clk_put(rk29_port->clk); + + return 0; +} + +static struct platform_driver rk29_platform_driver = { + .remove = rk29_serial_remove, + .driver = { + .name = "rk29_serial", + .owner = THIS_MODULE, + }, +}; + +static int __init rk29_serial_init(void) +{ + int ret; + ret = uart_register_driver(&rk29_uart_driver); + if (unlikely(ret)) + return ret; + + ret = platform_driver_probe(&rk29_platform_driver, rk29_serial_probe); + if (unlikely(ret)) + uart_unregister_driver(&rk29_uart_driver); + + printk(KERN_INFO "rk29_serial: driver initialized\n"); + + return ret; +} + +static void __exit rk29_serial_exit(void) +{ + #ifdef CONFIG_SERIAL_RK29_CONSOLE + unregister_console(&rk29_console); + #endif + platform_driver_unregister(&rk29_platform_driver); + uart_unregister_driver(&rk29_uart_driver); +} + +/* + * While this can be a module, if builtin it's most likely the console + * So let's leave module_exit but move module_init to an earlier place + */ +arch_initcall(rk29_serial_init); +module_exit(rk29_serial_exit); + +MODULE_AUTHOR("lhh lhh@rock-chips.com"); +MODULE_DESCRIPTION("Rockchip rk29 Serial port driver"); +MODULE_LICENSE("GPL"); + + diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 1f9fa0e1561b..8bdb2548ae3d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -179,8 +179,9 @@ /* BCM63xx family SoCs */ #define PORT_BCM63XX 89 -#define PORT_RK2818 90 +#define PORT_RK2818 90 +#define PORT_RK29 90 #ifdef __KERNEL__ #include -- 2.34.1