mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
add rk29 serial and console
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -38,8 +38,17 @@
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#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)
|
||||
|
||||
117
arch/arm/mach-rk29/devices.c
Normal file
117
arch/arm/mach-rk29/devices.c
Normal file
@@ -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 <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/rk29_iomap.h>
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
25
arch/arm/mach-rk29/devices.h
Normal file
25
arch/arm/mach-rk29/devices.h
Normal file
@@ -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
|
||||
19
arch/arm/mach-rk29/include/mach/gpio.h
Normal file
19
arch/arm/mach-rk29/include/mach/gpio.h
Normal file
@@ -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
|
||||
57
arch/arm/mach-rk29/include/mach/iomux.h
Normal file
57
arch/arm/mach-rk29/include/mach/iomux.h
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
33
arch/arm/mach-rk29/iomux.c
Normal file
33
arch/arm/mach-rk29/iomux.c
Normal file
@@ -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 <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <mach/rk29_iomap.h>
|
||||
#include <mach/iomux.h>
|
||||
|
||||
|
||||
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)
|
||||
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
710
drivers/serial/rk29_serial.c
Normal file
710
drivers/serial/rk29_serial.c
Normal file
@@ -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 <linux/hrtimer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/board.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
/*
|
||||
* <20>жϷ<D0B6><CFB7>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA>
|
||||
*<2A><><EFBFBD><EFBFBD>FIFO<46><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FIFO<46>ػ<EFBFBD>FIFO<46><4F><EFBFBD><EFBFBD>
|
||||
*/
|
||||
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<><31><EFBFBD><EFBFBD>
|
||||
}else{
|
||||
return (0);///0:<3A>ǿ<EFBFBD>
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
/*<2A><><EFBFBD><EFBFBD>uart0Ӳ<30><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
||||
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");
|
||||
|
||||
|
||||
@@ -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 <linux/compiler.h>
|
||||
|
||||
Reference in New Issue
Block a user