rk3188: add initial support
author黄涛 <huangtao@rock-chips.com>
Fri, 22 Nov 2013 11:24:41 +0000 (19:24 +0800)
committer黄涛 <huangtao@rock-chips.com>
Fri, 22 Nov 2013 11:24:41 +0000 (19:24 +0800)
16 files changed:
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/rk3188-tb.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3188.dtsi [new file with mode: 0644]
arch/arm/configs/rockchip_defconfig [new file with mode: 0644]
arch/arm/include/debug/rockchip.S [new file with mode: 0644]
arch/arm/mach-rockchip/Kconfig [new file with mode: 0644]
arch/arm/mach-rockchip/Makefile [new file with mode: 0644]
arch/arm/mach-rockchip/core.h [new file with mode: 0644]
arch/arm/mach-rockchip/headsmp.S [new file with mode: 0644]
arch/arm/mach-rockchip/platsmp.c [new file with mode: 0644]
arch/arm/mach-rockchip/rockchip.c [new file with mode: 0644]
drivers/clocksource/Makefile
drivers/clocksource/rockchip_timer.c [new file with mode: 0644]

index 2092322106d0731422cb089e8031d65046b39cf7..eb0523897d6c97bd7a633a6485d613e32208fdea 100644 (file)
@@ -982,6 +982,8 @@ source "arch/arm/mach-mmp/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
 
+source "arch/arm/mach-rockchip/Kconfig"
+
 source "arch/arm/mach-sa1100/Kconfig"
 
 source "arch/arm/plat-samsung/Kconfig"
index a640f09ec84294cb1c2610c4fa73265637696734..31508289061dee0fba9468a95346a7ee8f6d8dcc 100644 (file)
@@ -374,6 +374,13 @@ choice
                  their output to the standard serial port on the RealView
                  PB1176 platform.
 
+       config DEBUG_ROCKCHIP_UART
+               depends on ARCH_ROCKCHIP
+               bool "Use UART on Rockchip SoCs"
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 on Rockchip SoCs.
+
        config DEBUG_S3C_UART0
                depends on PLAT_SAMSUNG
                select DEBUG_EXYNOS_UART if ARCH_EXYNOS
@@ -660,6 +667,7 @@ config DEBUG_LL_INCLUDE
        default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
        default "debug/pxa.S" if DEBUG_PXA_UART1 || DEBUG_MMP_UART2 || \
                                 DEBUG_MMP_UART3
+       default "debug/rockchip.S" if DEBUG_ROCKCHIP_UART
        default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
        default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
        default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
index 4b5ff1e590ddc08011fe6402ab2a76e0f3d98bed..3a2d49cd94cf7aba1f733f98743b440aabe57f9b 100644 (file)
@@ -173,6 +173,7 @@ machine-$(CONFIG_ARCH_PICOXCELL)    += picoxcell
 machine-$(CONFIG_ARCH_PRIMA2)          += prima2
 machine-$(CONFIG_ARCH_PXA)             += pxa
 machine-$(CONFIG_ARCH_REALVIEW)                += realview
+machine-$(CONFIG_ARCH_ROCKCHIP)                += rockchip
 machine-$(CONFIG_ARCH_RPC)             += rpc
 machine-$(CONFIG_ARCH_S3C24XX)         += s3c24xx
 machine-$(CONFIG_ARCH_S3C64XX)         += s3c64xx
index 00baf9f5766aebf2c01221e7b9a317a7e024d4c0..6bc6af57eef8bf9e7e5d5305f2dd19f8c39ea092 100644 (file)
@@ -155,6 +155,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
        am335x-bone.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3188-tb.dtb
 dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
        hrefprev60.dtb \
        hrefv60plus.dtb \
diff --git a/arch/arm/boot/dts/rk3188-tb.dts b/arch/arm/boot/dts/rk3188-tb.dts
new file mode 100644 (file)
index 0000000..5960e10
--- /dev/null
@@ -0,0 +1,26 @@
+/dts-v1/;
+
+#include "rk3188.dtsi"
+
+/ {
+       memory {
+               device_type = "memory";
+               reg = <0x60000000 0x80000000>;
+       };
+
+       chosen {
+               bootargs ="console=ttyS1,115200 androidboot.console=ttyS1";
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
new file mode 100644 (file)
index 0000000..96a2322
--- /dev/null
@@ -0,0 +1,137 @@
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
+
+/ {
+       compatible = "rockchip,rk3188";
+       interrupt-parent = <&gic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <1>;
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <2>;
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <3>;
+               };
+       };
+
+       twd-wdt@1013c620 {
+               compatible = "arm,cortex-a9-twd-wdt";
+               reg = <0x1013c620 0x20>;
+               interrupts = <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       gic: interrupt-controller@1013d000 {
+               compatible = "arm,cortex-a9-gic";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x1013d000 0x1000>,
+                     <0x1013c100 0x0100>;
+       };
+
+       L2: cache-controller@10138000 {
+               compatible = "arm,pl310-cache";
+               reg = <0x10138000 0x1000>;
+               cache-unified;
+               cache-level = <2>;
+               arm,tag-latency = <1 1 1>;
+               arm,data-latency = <2 3 1>;
+       };
+
+       sram@10080000 {
+               compatible = "rockchip,sram";
+               reg = <0x10080000 0x8000>;
+       };
+
+       pmu@20004000 {
+               compatible = "rockchip,pmu";
+               reg = <0x20004000 0x4000>;
+       };
+
+       timer@200380a0 {
+               compatible = "rockchip,timer";
+               reg = <0x200380a0 0x20>;
+               interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       timer@20038000 {
+               compatible = "rockchip,timer";
+               reg = <0x20038000 0x20>;
+               interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       timer@20038020 {
+               compatible = "rockchip,timer";
+               reg = <0x20038020 0x20>;
+               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       timer@20038060 {
+               compatible = "rockchip,timer";
+               reg = <0x20038060 0x20>;
+               interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       timer@20038080 {
+               compatible = "rockchip,timer";
+               reg = <0x20038080 0x20>;
+               interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       uart0: serial@10124000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x10124000 0x100>;
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               status = "disabled";
+       };
+
+       uart1: serial@10126000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x10126000 0x100>;
+               interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               status = "disabled";
+       };
+
+       uart2: serial@20064000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x20064000 0x100>;
+               interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               status = "disabled";
+       };
+
+       uart3: serial@20068000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x20068000 0x100>;
+               interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <24000000>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               status = "disabled";
+       };
+};
diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig
new file mode 100644 (file)
index 0000000..9b7a621
--- /dev/null
@@ -0,0 +1,427 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_LOG_BUF_SHIFT=19
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
+# CONFIG_UID16 is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_JUMP_LABEL=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_ROCKCHIP=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_753970=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_COREDUMP is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_SUSPEND_TIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_NF_NAT_IPV4=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_RFKILL=y
+CONFIG_CMA=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_UID_STAT=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_RTL8152=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_CDC_EEM=y
+CONFIG_USB_NET_CDC_MBIM=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_CX82310_ETH=y
+CONFIG_USB_NET_KALMIA=y
+CONFIG_USB_NET_QMI_WWAN=y
+CONFIG_USB_HSO=y
+CONFIG_USB_NET_INT51X1=y
+CONFIG_USB_IPHETH=y
+CONFIG_USB_SIERRA_NET=y
+CONFIG_WIFI_CONTROL_FUNC=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=5
+CONFIG_SERIAL_8250_RUNTIME_UARTS=5
+CONFIG_SERIAL_8250_DW=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_SPI=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_THERMAL=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_APPLEIR=y
+CONFIG_HID_AUREAL=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_HOLTEK=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_ICADE=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LENOVO_TPKBD=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_PS3REMOTE=y
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_STEELSERIES=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THINGM=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_ACM=y
+CONFIG_USB_PRINTER=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_TRANCEVIBRATOR=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_ANDROID=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_SYNC=y
+CONFIG_ION=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_CIFS=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_SCHED_TRACER=y
+CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_SECURITY_SELINUX=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/include/debug/rockchip.S b/arch/arm/include/debug/rockchip.S
new file mode 100644 (file)
index 0000000..72f8a26
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.
+ *
+ */
+
+#define UART_SHIFT 2
+
+       .macro addruart, rp, rv, tmp
+               ldr     \rp, = 0x20064000
+               ldr     \rv, = 0xfed64000
+       .endm
+
+#include "8250_32.S"
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
new file mode 100644 (file)
index 0000000..d01134d
--- /dev/null
@@ -0,0 +1,28 @@
+config ARCH_ROCKCHIP
+       bool "Rockchip SoCs" if ARCH_MULTI_V7
+       select PIE
+       select PINCTRL
+       select PINCTRL_ROCKCHIP
+       select ARCH_REQUIRE_GPIOLIB
+       select ARM_GIC
+       select CACHE_L2X0
+       select HAVE_ARM_SCU if SMP
+       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_SMP
+       select LOCAL_TIMERS if SMP
+       select COMMON_CLK
+       select GENERIC_CLOCKEVENTS
+       select CLKSRC_OF if OF
+       help
+         Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs
+         containing the RK2928, RK30xx and RK31xx series.
+
+if ARCH_ROCKCHIP
+
+config RK_DEBUG_UART
+       int "Debug UART"
+       default 2
+       help
+         Select a UART for debugging. -1 disable.
+
+endif
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
new file mode 100644 (file)
index 0000000..82e794e
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
diff --git a/arch/arm/mach-rockchip/core.h b/arch/arm/mach-rockchip/core.h
new file mode 100644 (file)
index 0000000..ce70ab4
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 ROCKCHIP, Inc.
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 __MACH_CORE_H
+#define __MACH_CORE_H
+
+extern char rockchip_secondary_trampoline;
+extern char rockchip_secondary_trampoline_end;
+
+extern unsigned long rockchip_boot_fn;
+
+extern struct smp_operations rockchip_smp_ops;
+
+#endif
diff --git a/arch/arm/mach-rockchip/headsmp.S b/arch/arm/mach-rockchip/headsmp.S
new file mode 100644 (file)
index 0000000..34ab408
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 ROCKCHIP, Inc.
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/linkage.h>
+#include <linux/init.h>
+
+ENTRY(rockchip_secondary_trampoline)
+       ldr     pc, 1f
+ENDPROC(rockchip_secondary_trampoline)
+
+       .globl  rockchip_boot_fn
+rockchip_boot_fn:
+1:     .space  4
+
+ENTRY(rockchip_secondary_trampoline_end)
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
new file mode 100644 (file)
index 0000000..25b5150
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2013 ROCKCHIP, Inc.
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
+#include <asm/mach/map.h>
+
+#include "core.h"
+
+#define SCU_CTRL               0x00
+#define   SCU_STANDBY_EN       (1 << 5)
+
+static int ncores;
+
+/*
+ * temporary PMU handling
+ */
+
+#define PMU_PWRDN_CON          0x08
+#define PMU_PWRDN_ST           0x0c
+
+static void __iomem *pmu_base_addr;
+
+extern void secondary_startup(void);
+extern void v7_invalidate_l1(void);
+static void __naked rockchip_a9_secondary_startup(void)
+{
+       v7_invalidate_l1();
+       secondary_startup();
+}
+
+static inline bool pmu_power_domain_is_on(int pd)
+{
+       return !(readl_relaxed(pmu_base_addr + PMU_PWRDN_ST) & BIT(pd));
+}
+
+static void pmu_set_power_domain(int pd, bool on)
+{
+       u32 val = readl_relaxed(pmu_base_addr + PMU_PWRDN_CON);
+       if (on)
+               val &= ~BIT(pd);
+       else
+               val |=  BIT(pd);
+       writel(val, pmu_base_addr + PMU_PWRDN_CON);
+
+       while (pmu_power_domain_is_on(pd) != on) { }
+}
+
+/*
+ * Handling of CPU cores
+ */
+
+static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
+                                            struct task_struct *idle)
+{
+       if (cpu >= ncores) {
+               pr_err("%s: cpu %d outside maximum number of cpus %d\n",
+                                                       __func__, cpu, ncores);
+               return -EINVAL;
+       }
+
+       /* start the core */
+       pmu_set_power_domain(0 + cpu, true);
+
+       return 0;
+}
+
+/**
+ * rockchip_smp_prepare_sram - populate necessary sram block
+ * Starting cores execute the code residing at the start of the on-chip sram
+ * after power-on. Therefore make sure, this sram region is reserved and
+ * big enough. After this check, copy the trampoline code that directs the
+ * core to the real startup code in ram into the sram-region.
+ */
+static int __init rockchip_smp_prepare_sram(void)
+{
+       void __iomem *sram_base_addr;
+       unsigned int trampoline_sz = &rockchip_secondary_trampoline_end -
+                                           &rockchip_secondary_trampoline;
+
+       sram_base_addr = ioremap_nocache(0, trampoline_sz);
+       if (!sram_base_addr) {
+               pr_err("%s: could not map sram\n", __func__);
+               BUG();
+       }
+
+       /* set the boot function for the sram code */
+       if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
+               rockchip_boot_fn = virt_to_phys(rockchip_a9_secondary_startup);
+       else
+               rockchip_boot_fn = virt_to_phys(secondary_startup);
+
+       /* copy the trampoline to sram, that runs during startup of the core */
+       memcpy(sram_base_addr, &rockchip_secondary_trampoline, trampoline_sz);
+
+       iounmap(sram_base_addr);
+
+       return 0;
+}
+
+static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
+{
+       void __iomem *scu_base_addr = NULL;
+       struct device_node *node;
+       unsigned int i, cpu;
+
+       if (scu_a9_has_base())
+               scu_base_addr = ioremap(scu_a9_get_base(), 0x100);
+
+       if (!scu_base_addr) {
+               pr_err("%s: could not map scu registers\n", __func__);
+               BUG();
+       }
+
+       if (rockchip_smp_prepare_sram())
+               return;
+
+       node = of_find_compatible_node(NULL, NULL, "rockchip,pmu");
+       if (!node) {
+               pr_err("%s: could not find sram dt node\n", __func__);
+               return;
+       }
+
+       pmu_base_addr = of_iomap(node, 0);
+
+       /*
+        * While the number of cpus is gathered from dt, also get the number
+        * of cores from the scu to verify this value when booting the cores.
+        */
+       ncores = scu_get_core_count(scu_base_addr);
+
+       writel_relaxed(readl_relaxed(scu_base_addr + SCU_CTRL) | SCU_STANDBY_EN, scu_base_addr + SCU_CTRL);
+       scu_enable(scu_base_addr);
+
+       cpu = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 0);
+       /* Make sure that all cores except myself are really off */
+       for (i = 0; i < ncores; i++) {
+               if (i == cpu)
+                       continue;
+               pmu_set_power_domain(i, false);
+       }
+
+       iounmap(scu_base_addr);
+}
+
+struct smp_operations rockchip_smp_ops __initdata = {
+       .smp_prepare_cpus       = rockchip_smp_prepare_cpus,
+       .smp_boot_secondary     = rockchip_boot_secondary,
+};
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
new file mode 100644 (file)
index 0000000..d96ee44
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Device Tree support for Rockchip SoCs
+ *
+ * Copyright (C) 2013 ROCKCHIP, Inc.
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <linux/irqchip.h>
+#include <linux/dw_apb_timer.h>
+#include <linux/clk-provider.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "core.h"
+
+static void __init rockchip_dt_map_io(void)
+{
+       preset_lpj = 11996091ULL / 2;
+       debug_ll_io_init();
+}
+
+static void __init rockchip_timer_init(void)
+{
+       of_clk_init(NULL);
+       clocksource_of_init();
+}
+
+static void __init rockchip_dt_init(void)
+{
+       l2x0_of_init(0, ~0UL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const rockchip_board_dt_compat[] = {
+       "rockchip,rk2928",
+       "rockchip,rk3066a",
+       "rockchip,rk3066b",
+       "rockchip,rk3188",
+       NULL,
+};
+
+DT_MACHINE_START(ROCKCHIP_DT, "Rockchip SoC (Flattened Device Tree)")
+       .smp            = smp_ops(rockchip_smp_ops),
+       .map_io         = rockchip_dt_map_io,
+       .init_machine   = rockchip_dt_init,
+       .init_time      = rockchip_timer_init,
+       .dt_compat      = rockchip_board_dt_compat,
+MACHINE_END
index 8d979c72aa946a97a19c940a23133b762f6d33d8..e32018e410cccc15e548d151f66c95490d2a5b0b 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_CLKBLD_I8253)    += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)      += mmio.o
 obj-$(CONFIG_DW_APB_TIMER)     += dw_apb_timer.o
 obj-$(CONFIG_DW_APB_TIMER_OF)  += dw_apb_timer_of.o
+obj-$(CONFIG_ARCH_ROCKCHIP)    += rockchip_timer.o
 obj-$(CONFIG_CLKSRC_NOMADIK_MTU)       += nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)      += clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)      += time-armada-370-xp.o
diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
new file mode 100644 (file)
index 0000000..8c5291f
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2013 ROCKCHIP, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/percpu.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <asm/localtimer.h>
+#include <asm/sched_clock.h>
+
+#define TIMER_NAME "rk_timer"
+
+#define TIMER_LOAD_COUNT0               0x00
+#define TIMER_LOAD_COUNT1               0x04
+#define TIMER_CURRENT_VALUE0            0x08
+#define TIMER_CURRENT_VALUE1            0x0c
+#define TIMER_CONTROL_REG               0x10
+#define TIMER_INT_STATUS                0x18
+
+#define TIMER_DISABLE                   (0 << 0)
+#define TIMER_ENABLE                    (1 << 0)
+#define TIMER_MODE_FREE_RUNNING         (0 << 1)
+#define TIMER_MODE_USER_DEFINED_COUNT   (1 << 1)
+#define TIMER_INT_MASK                  (0 << 2)
+#define TIMER_INT_UNMASK                (1 << 2)
+
+struct cs_timer {
+       void __iomem *base;
+       struct clk *clk;
+       struct clk *pclk;
+};
+
+struct ce_timer {
+       void __iomem *base;
+       struct clk *clk;
+       struct clk *pclk;
+       struct irqaction irq;
+       char name[16];
+};
+
+static struct cs_timer cs_timer;
+static DEFINE_PER_CPU(struct ce_timer, ce_timer);
+
+static inline void rk_timer_disable(void __iomem *base)
+{
+       writel_relaxed(TIMER_DISABLE, base + TIMER_CONTROL_REG);
+       dsb();
+}
+
+static inline void rk_timer_enable(void __iomem *base, u32 flags)
+{
+       writel_relaxed(TIMER_ENABLE | flags, base + TIMER_CONTROL_REG);
+       dsb();
+}
+
+static inline u32 rk_timer_read_current_value(void __iomem *base)
+{
+       return readl_relaxed(base + TIMER_CURRENT_VALUE0);
+}
+
+static inline u32 rk_timer_read_current_value64(void __iomem *base)
+{
+       u32 upper, lower;
+
+       do {
+               upper = readl_relaxed(base + TIMER_CURRENT_VALUE1);
+               lower = readl_relaxed(base + TIMER_CURRENT_VALUE0);
+       } while (upper != readl_relaxed(base + TIMER_CURRENT_VALUE1));
+
+       return ((u64) upper << 32) + lower;
+}
+
+static int rk_timer_set_next_event(unsigned long cycles, struct clock_event_device *ce)
+{
+       void __iomem *base = __get_cpu_var(ce_timer).base;
+
+       rk_timer_disable(base);
+       writel_relaxed(cycles, base + TIMER_LOAD_COUNT0);
+       writel_relaxed(0, base + TIMER_LOAD_COUNT1);
+       dsb();
+       rk_timer_enable(base, TIMER_MODE_USER_DEFINED_COUNT | TIMER_INT_UNMASK);
+       return 0;
+}
+
+static void rk_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
+{
+       struct ce_timer *timer = &__get_cpu_var(ce_timer);
+       void __iomem *base = timer->base;
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               rk_timer_disable(base);
+               writel_relaxed(24000000 / HZ - 1, base + TIMER_LOAD_COUNT0);
+               dsb();
+               rk_timer_enable(base, TIMER_MODE_FREE_RUNNING | TIMER_INT_UNMASK);
+       case CLOCK_EVT_MODE_RESUME:
+       case CLOCK_EVT_MODE_ONESHOT:
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               rk_timer_disable(base);
+               break;
+       }
+}
+
+static irqreturn_t rk_timer_clockevent_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *ce = dev_id;
+       struct ce_timer *timer = &__get_cpu_var(ce_timer);
+       void __iomem *base = timer->base;
+
+       /* clear interrupt */
+       writel_relaxed(1, base + TIMER_INT_STATUS);
+       if (ce->mode == CLOCK_EVT_MODE_ONESHOT) {
+               writel_relaxed(TIMER_DISABLE, base + TIMER_CONTROL_REG);
+       }
+       dsb();
+
+       ce->event_handler(ce);
+
+       return IRQ_HANDLED;
+}
+
+static __cpuinit int rk_timer_init_clockevent(struct clock_event_device *ce, unsigned int cpu)
+{
+       struct ce_timer *timer = &per_cpu(ce_timer, cpu);
+       struct irqaction *irq = &timer->irq;
+       void __iomem *base = timer->base;
+
+       if (!base)
+               return 0;
+
+       ce->name = timer->name;
+       ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+       ce->set_next_event = rk_timer_set_next_event;
+       ce->set_mode = rk_timer_set_mode;
+       ce->irq = irq->irq;
+       ce->cpumask = cpumask_of(cpu);
+
+       writel_relaxed(1, base + TIMER_INT_STATUS);
+       rk_timer_disable(base);
+
+       irq->dev_id = ce;
+       irq_set_affinity(irq->irq, cpumask_of(cpu));
+       setup_irq(irq->irq, irq);
+
+       clockevents_config_and_register(ce, 24000000, 0xF, 0xFFFFFFFF);
+
+       return 0;
+}
+
+static int __cpuinit rk_local_timer_setup(struct clock_event_device *ce)
+{
+       ce->rating = 450;
+       return rk_timer_init_clockevent(ce, smp_processor_id());
+}
+
+static void rk_local_timer_stop(struct clock_event_device *ce)
+{
+       ce->set_mode(CLOCK_EVT_MODE_UNUSED, ce);
+       remove_irq(ce->irq, &per_cpu(ce_timer, smp_processor_id()).irq);
+}
+
+static struct local_timer_ops rk_local_timer_ops __cpuinitdata = {
+       .setup  = rk_local_timer_setup,
+       .stop   = rk_local_timer_stop,
+};
+
+static cycle_t rk_timer_read(struct clocksource *cs)
+{
+       return ~rk_timer_read_current_value64(cs_timer.base);
+}
+
+static struct clocksource rk_timer_clocksource = {
+       .name   = TIMER_NAME,
+       .rating = 200,
+       .read   = rk_timer_read,
+       .mask   = CLOCKSOURCE_MASK(64),
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init rk_timer_init_clocksource(struct device_node *np)
+{
+       void __iomem *base;
+       struct clocksource *cs = &rk_timer_clocksource;
+
+       base = of_iomap(np, 0);
+       cs_timer.base = base;
+
+       rk_timer_disable(base);
+       writel_relaxed(0xFFFFFFFF, base + TIMER_LOAD_COUNT0);
+       writel_relaxed(0xFFFFFFFF, base + TIMER_LOAD_COUNT1);
+       dsb();
+       rk_timer_enable(base, TIMER_MODE_FREE_RUNNING | TIMER_INT_MASK);
+       clocksource_register_hz(cs, 24000000);
+}
+
+static u32 rockchip_read_sched_clock(void)
+{
+       return ~rk_timer_read_current_value(cs_timer.base);
+}
+
+static void __init rk_timer_init_ce_timer(struct device_node *np, unsigned int cpu)
+{
+       struct ce_timer *timer = &per_cpu(ce_timer, cpu);
+       struct irqaction *irq = &timer->irq;
+
+       timer->base = of_iomap(np, 0);
+       snprintf(timer->name, sizeof(timer->name), TIMER_NAME "%d", cpu);
+       irq->irq = irq_of_parse_and_map(np, 0);
+       irq->name = timer->name;
+       irq->flags = IRQF_TIMER | IRQF_NOBALANCING;
+       irq->handler = rk_timer_clockevent_interrupt;
+}
+
+static int num_called;
+static void __init rk_timer_init(struct device_node *np)
+{
+       switch (num_called) {
+       case 0:
+               rk_timer_init_clocksource(np);
+               setup_sched_clock(rockchip_read_sched_clock, 32, 24000000);
+               local_timer_register(&rk_local_timer_ops);
+               break;
+       default:
+               rk_timer_init_ce_timer(np, num_called - 1);
+               break;
+       }
+
+       num_called++;
+}
+CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,timer", rk_timer_init);