From: 黄涛 Date: Fri, 22 Nov 2013 11:24:41 +0000 (+0800) Subject: rk3188: add initial support X-Git-Tag: firefly_0821_release~6481 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b4fae167a91f8f9d36bbc0912c8de381af4fad4c;p=firefly-linux-kernel-4.4.55.git rk3188: add initial support --- diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2092322106d0..eb0523897d6c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -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" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index a640f09ec842..31508289061d 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -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 diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 4b5ff1e590dd..3a2d49cd94cf 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -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 diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 00baf9f5766a..6bc6af57eef8 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -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 index 000000000000..5960e1007c51 --- /dev/null +++ b/arch/arm/boot/dts/rk3188-tb.dts @@ -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 index 000000000000..96a23224d76d --- /dev/null +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -0,0 +1,137 @@ +#include + +#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: 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 = ; + }; + + timer@20038000 { + compatible = "rockchip,timer"; + reg = <0x20038000 0x20>; + interrupts = ; + }; + + timer@20038020 { + compatible = "rockchip,timer"; + reg = <0x20038020 0x20>; + interrupts = ; + }; + + timer@20038060 { + compatible = "rockchip,timer"; + reg = <0x20038060 0x20>; + interrupts = ; + }; + + timer@20038080 { + compatible = "rockchip,timer"; + reg = <0x20038080 0x20>; + interrupts = ; + }; + + uart0: serial@10124000 { + compatible = "snps,dw-apb-uart"; + reg = <0x10124000 0x100>; + interrupts = ; + clock-frequency = <24000000>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart1: serial@10126000 { + compatible = "snps,dw-apb-uart"; + reg = <0x10126000 0x100>; + interrupts = ; + clock-frequency = <24000000>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart2: serial@20064000 { + compatible = "snps,dw-apb-uart"; + reg = <0x20064000 0x100>; + interrupts = ; + clock-frequency = <24000000>; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + + uart3: serial@20068000 { + compatible = "snps,dw-apb-uart"; + reg = <0x20068000 0x100>; + interrupts = ; + 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 index 000000000000..9b7a62119cac --- /dev/null +++ b/arch/arm/configs/rockchip_defconfig @@ -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 index 000000000000..72f8a2675580 --- /dev/null +++ b/arch/arm/include/debug/rockchip.S @@ -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 index 000000000000..d01134d0e65f --- /dev/null +++ b/arch/arm/mach-rockchip/Kconfig @@ -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 index 000000000000..82e794e7d9df --- /dev/null +++ b/arch/arm/mach-rockchip/Makefile @@ -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 index 000000000000..ce70ab4e085c --- /dev/null +++ b/arch/arm/mach-rockchip/core.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 ROCKCHIP, Inc. + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * 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 index 000000000000..34ab408bf571 --- /dev/null +++ b/arch/arm/mach-rockchip/headsmp.S @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 ROCKCHIP, Inc. + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * 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 +#include + +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 index 000000000000..25b51506d631 --- /dev/null +++ b/arch/arm/mach-rockchip/platsmp.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2013 ROCKCHIP, Inc. + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 index 000000000000..d96ee44b3b98 --- /dev/null +++ b/arch/arm/mach-rockchip/rockchip.c @@ -0,0 +1,62 @@ +/* + * Device Tree support for Rockchip SoCs + * + * Copyright (C) 2013 ROCKCHIP, Inc. + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 8d979c72aa94..e32018e410cc 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -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 index 000000000000..8c5291fa0e47 --- /dev/null +++ b/drivers/clocksource/rockchip_timer.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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);