sunxi: rework target
authorZoltan Herpai <wigyori@uid0.hu>
Thu, 14 Nov 2013 23:12:52 +0000 (23:12 +0000)
committerZoltan Herpai <wigyori@uid0.hu>
Thu, 14 Nov 2013 23:12:52 +0000 (23:12 +0000)
 - update kernel to 3.12
 - add patches for clocks, i2c, usb, sid, rtc
 - support common image for A10/A13/A20
 - add support for a couple boards
 - most drivers are configured into the kernel as of now

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
SVN-Revision: 38811

48 files changed:
target/linux/sunxi/Makefile
target/linux/sunxi/base-files/etc/inittab [new file with mode: 0644]
target/linux/sunxi/base-files/lib/preinit/01_preinit_sunxi.sh [new file with mode: 0644]
target/linux/sunxi/base-files/lib/sunxi.sh [new file with mode: 0644]
target/linux/sunxi/config-3.12 [new file with mode: 0644]
target/linux/sunxi/cortex-a7/profiles/100-generic.mk [deleted file]
target/linux/sunxi/cortex-a7/target.mk [deleted file]
target/linux/sunxi/cortex-a8/profiles/100-generic.mk [deleted file]
target/linux/sunxi/cortex-a8/profiles/110-cubieboard.mk [deleted file]
target/linux/sunxi/cortex-a8/target.mk [deleted file]
target/linux/sunxi/image/Makefile
target/linux/sunxi/patches-3.12/100-clk-sunxi_register_factors.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/101-clk-sunxi_add-gating-pll1.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/102-clk-sunxi_add_pll4.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/103-clk-sunxi_add_pll5-6.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/104-arm-sunxi_add_pll5-6_dts.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/105-clk-sunxi_mod0.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/120-split-dt-for-sun6i-sun7i.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/130-sun7i-enable-i2c-ctrlers.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/131-sun7i-add-i2c-pinmuxing.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/132-add-dt-i2c-for-olinuxino-a20.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/140-add-a31-reset-driver.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/141-add-Kconfig-for-reset.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/142-register-a31-reset.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/143-add-dtsi-for-reset.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/145-fix-reset-for-all-sunxi.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/150-sun4i-add-dt-bindings.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/151-clk-sunxi-add-usbclocks.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/152-sun4i-dt-add-usb-ehci-bindings.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/153-add-sunxi-ehci.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/154-add-ehci-for-a1000.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/155-add-ehci-for-cubieboard-a10.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/156-sun7i-add-dt-bindings-for-usbclocks.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/157-sun7i-add-dt-usb-ehci-bindings.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/158-sun5i-add-dt-bindings-for-usbclocks.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/159-sun5i-add-support-for-usbclocks.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/160-sun5i-dt-add-usb-ehci-bindings.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/161-sun5i-add-dt-ehci-for-a13-olinuxino.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/162-add-dt-ehci-for-a20-olinuxino.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/170-sunxi-sid-initial.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/171-add-dt-sunxi-sid.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/175-sunxi-rtc.patch [new file with mode: 0644]
target/linux/sunxi/patches-3.12/176-add-dt-rtc-for-sun4i-7i.patch [new file with mode: 0644]
target/linux/sunxi/profiles/01-default.mk [new file with mode: 0644]
target/linux/sunxi/profiles/a13-olinuxino.mk [new file with mode: 0644]
target/linux/sunxi/profiles/a20-olinuxino.mk [new file with mode: 0644]
target/linux/sunxi/profiles/cubieboard.mk [new file with mode: 0644]
target/linux/sunxi/profiles/cubieboard2.mk [new file with mode: 0644]

index e60f55036034df2dda9a723ac0e3b5c2600583d9..658de40028a2528fdd9171bbf0da5c82d70e062c 100644 (file)
@@ -4,19 +4,26 @@
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
 #
+
 include $(TOPDIR)/rules.mk
 
 ARCH:=arm
 BOARD:=sunxi
-BOARDNAME:=Allwinner SoC
-FEATURES:=targz
-SUBTARGETS=cortex-a7 cortex-a8
-MAINTAINER:=Luka Perkov <luka@openwrt.org>
+BOARDNAME:=Allwinner A1x/A20/A3x
+FEATURES:=fpu usb ext4 display
+CPU_TYPE:=cortex-a8
+CPU_SUBTYPE:=vfpv3
+MAINTAINER:=Zoltan HERPAI <wigyori@uid0.hu>
 
-LINUX_VERSION:=3.10.18
+LINUX_VERSION:=3.12
+KERNELNAME:="zImage dtbs"
+DEFAULT_PACKAGES += uboot-envtools uboot-sunxi
 
-include $(INCLUDE_DIR)/target.mk
+# A10: Cortex-A8
+# A13: Cortex-A8
+# A20: dual Cortex-A7
+# A31: quad Cortex-A7
 
-KERNELNAME:="zImage dtbs"
+include $(INCLUDE_DIR)/target.mk
 
 $(eval $(call BuildTarget))
diff --git a/target/linux/sunxi/base-files/etc/inittab b/target/linux/sunxi/base-files/etc/inittab
new file mode 100644 (file)
index 0000000..e9de30b
--- /dev/null
@@ -0,0 +1,5 @@
+::sysinit:/etc/init.d/rcS S boot
+::shutdown:/etc/init.d/rcS K shutdown
+tts/0::askfirst:/bin/ash --login
+ttyS0::askfirst:/bin/ash --login
+tty1::askfirst:/bin/ash --login
diff --git a/target/linux/sunxi/base-files/lib/preinit/01_preinit_sunxi.sh b/target/linux/sunxi/base-files/lib/preinit/01_preinit_sunxi.sh
new file mode 100644 (file)
index 0000000..f221dbc
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+do_sunxi() {
+        . /lib/sunxi.sh
+
+        sunxi_board_detect
+}
+
+boot_hook_add preinit_main do_sunxi
diff --git a/target/linux/sunxi/base-files/lib/sunxi.sh b/target/linux/sunxi/base-files/lib/sunxi.sh
new file mode 100644 (file)
index 0000000..adf9f84
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# defaults
+SUNXI_BOARD_NAME="generic sunxi"
+SUNXI_BOARD_MODEL="generic sunxi"
+SUNXI_ENV_DEV=/dev/mmcblk0
+
+#Helper functions 
+get_cmdline_opt() 
+{
+cat /proc/cmdline | awk -F$1= '{print $2}' | awk '{print $1}'
+}
+
+#Since fw_getenv doesn't work with blockdevs let's make a hack
+uboot_getenv() 
+{
+    dd if=$SUNXI_ENV_DEV bs=1024 skip=544 count=128 2>dev/null |\strings|grep $1|cut -d"=" -f2
+}
+
+#Actual routines go below
+sunxi_env_dev()
+{
+    local dev
+    dev=`get_cmdline_opt root|cut -d"p" -f1`
+    SUNXI_ENV_DEV=$dev
+    echo "probing $dev for uboot env data"
+}
+
+sunxi_board_detect() {
+    local board
+    local model
+    sunxi_env_dev
+    [ -e "/tmp/sysinfo/" ] || mkdir -p "/tmp/sysinfo/"
+    board="`uboot_getenv wrt_board`"
+    model="`uboot_getenv wrt_model`"
+    if [ "$board" != "" ]; then
+       SUNXI_BOARD_NAME="$board"
+    fi
+    if [ "$model" != "" ]; then
+       SUNXI_BOARD_MODEL="$model"
+    fi
+    echo "$SUNXI_BOARD_NAME" > /tmp/sysinfo/board_name
+    echo "$SUNXI_BOARD_MODEL" > /tmp/sysinfo/model
+    echo "Detected $SUNXI_BOARD_NAME // $SUNXI_BOARD_MODEL"
+}
diff --git a/target/linux/sunxi/config-3.12 b/target/linux/sunxi/config-3.12
new file mode 100644 (file)
index 0000000..4a3bc4a
--- /dev/null
@@ -0,0 +1,434 @@
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_ARCH_HAS_RESET_CONTROLLER=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+CONFIG_ARCH_MULTI_V6_V7=y
+CONFIG_ARCH_MULTI_V7=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+CONFIG_ARCH_NR_GPIO=288
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+CONFIG_ARCH_SUNXI=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARM=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+# CONFIG_ARM_LPAE is not set
+CONFIG_ARM_NR_BANKS=8
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+CONFIG_ATA=y
+CONFIG_ATAGS=y
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_AUDIT_GENERIC=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_AVERAGE=y
+CONFIG_BINFMT_MISC=y
+CONFIG_BLK_CGROUP=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_BOUNCE=y
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_WEXT is not set
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CGROUP_PERF is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_MANAGER is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLKSRC_OF=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CMDLINE="console=ttyS0,115200 earlyprintk"
+CONFIG_CMDLINE_FORCE=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMPACTION=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CONNECTOR=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_COREDUMP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_CPUSETS=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_UART_8250 is not set
+# CONFIG_DEBUG_UART_PL01X is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DIRECT_IO=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_OF=y
+CONFIG_DNOTIFY=y
+CONFIG_DTC=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_DW_DMAC_CORE is not set
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_EEPROM_SUNXI_SID=y
+CONFIG_ELF_CORE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_EXPERT is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FRAME_WARN=2048
+CONFIG_FREEZER=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_GARP=y
+CONFIG_GENERIC_ACL=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+# CONFIG_HAMRADIO is not set
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_HAVE_BPF_JIT=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SMP=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HW_CONSOLE=y
+CONFIG_HZ_FIXED=0
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_MUX=y
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+CONFIG_I2C_MUX_PINCTRL=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INPUT=y
+# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IPC_NS=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_BOOTP is not set
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_KALLSYMS=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_XZ is not set
+CONFIG_KSM=y
+CONFIG_KTIME_SCALAR=y
+# CONFIG_LBDAF is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_REGULATOR is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_LOG_BUF_SHIFT=19
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_MAC80211=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_HAS_RC=y
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MDIO_BOARDINFO=y
+CONFIG_MDIO_SUN4I=y
+# CONFIG_MEMCG is not set
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_DW=y
+# CONFIG_MMC_DW_EXYNOS is not set
+# CONFIG_MMC_DW_IDMAC is not set
+CONFIG_MMC_DW_PLTFM=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MODULES_USE_ELF_REL=y
+# CONFIG_MTD is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+# CONFIG_MWIFIEX is not set
+CONFIG_NAMESPACES=y
+CONFIG_NEED_DMA_MAP_STATE=y
+# CONFIG_NEON is not set
+# CONFIG_NETPRIO_CGROUP is not set
+# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_NS=y
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_NET_VENDOR_ALLWINNER=y
+# CONFIG_NL80211_TESTMODE is not set
+CONFIG_NLS=y
+CONFIG_NO_HZ=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NR_CPUS=4
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OLD_SIGACTION=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PARTITION_ADVANCED is not set
+# CONFIG_PCI_SYSCALL is not set
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PHYLIB=y
+CONFIG_PID_NS=y
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_PINCTRL_SUNXI=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_RCU=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_PROC_EVENTS=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_PID_CPUSET=y
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_RCU_BOOST is not set
+CONFIG_RCU_CPU_STALL_VERBOSE=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_GZIP=y
+CONFIG_RD_LZ4=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_RD_XZ=y
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+CONFIG_RELAY=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESOURCE_COUNTERS=y
+# CONFIG_RFKILL_REGULATOR is not set
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_SUNXI=y
+CONFIG_SATA_AHCI_PLATFORM=y
+# CONFIG_SATA_RCAR is not set
+CONFIG_SCHED_HRTICK=y
+CONFIG_SCSI=y
+CONFIG_SECURITYFS=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=8
+CONFIG_SERIAL_8250_SYSRQ=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_SERIO_OLPC_APSP is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLUB_DEBUG_ON is not set
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_STAGING is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_SUN4I_EMAC=y
+CONFIG_SUN4I_TIMER=y
+CONFIG_SWP_EMULATE=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_TASK_XACCT=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_UID16=y
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+CONFIG_USB_NET_AX88179_178A=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUNXI_EHCI=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_USBNET=y
+# CONFIG_USER_NS is not set
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_USE_OF=y
+CONFIG_UTS_NS=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_WATCHDOG is not set
+# CONFIG_XEN is not set
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+CONFIG_XPS=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ZBOOT_ROM_TEXT=0
+# CONFIG_ZBUD is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/sunxi/cortex-a7/profiles/100-generic.mk b/target/linux/sunxi/cortex-a7/profiles/100-generic.mk
deleted file mode 100644 (file)
index ca4db9c..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2013 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-define Profile/Generic
-  NAME:=Generic (default)
-  PACKAGES:= \
-       uboot-envtools
-endef
-
-define Profile/Generic/Description
- Package set compatible with most Allwinner A20, A31 and A31s SoC based boards.
-endef
-
-$(eval $(call Profile,Generic))
diff --git a/target/linux/sunxi/cortex-a7/target.mk b/target/linux/sunxi/cortex-a7/target.mk
deleted file mode 100644 (file)
index 1267eef..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Copyright (C) 2013 OpenWrt.org
-#
-
-BOARDNAME:=A20, A31 and A31s
-SUBTARGET:=cortex-a7
-CPU_TYPE:=cortex-a7
-
-define Target/Description
- Allwinner A20, A31 and A31s SoC
-endef
diff --git a/target/linux/sunxi/cortex-a8/profiles/100-generic.mk b/target/linux/sunxi/cortex-a8/profiles/100-generic.mk
deleted file mode 100644 (file)
index 272ec81..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Copyright (C) 2013 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-define Profile/Generic
-  NAME:=Generic (default)
-  PACKAGES:= \
-       uboot-envtools
-endef
-
-define Profile/Generic/Description
- Package set compatible with most Allwinner A10, A10s and A13 SoC based boards.
-endef
-
-$(eval $(call Profile,Generic))
diff --git a/target/linux/sunxi/cortex-a8/profiles/110-cubieboard.mk b/target/linux/sunxi/cortex-a8/profiles/110-cubieboard.mk
deleted file mode 100644 (file)
index a08a53f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Copyright (C) 2013 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-define Profile/CUBIEBOARD
-  NAME:=Cubieboard
-  PACKAGES:= \
-       uboot-envtools
-endef
-
-$(eval $(call Profile,CUBIEBOARD))
diff --git a/target/linux/sunxi/cortex-a8/target.mk b/target/linux/sunxi/cortex-a8/target.mk
deleted file mode 100644 (file)
index 15984a6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Copyright (C) 2013 OpenWrt.org
-#
-
-BOARDNAME:=A10, A10s and A13
-SUBTARGET:=cortex-a8
-CPU_TYPE:=cortex-a8
-
-define Target/Description
- Allwinner A10, A10s and A13 SoC
-endef
index 3a9f64d9af1ef67ce9d54715d882b86027d204a9..2d7a603ad1e6d5f1f5ad46a95ed418448b8e1b08 100644 (file)
@@ -7,21 +7,19 @@
 include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/image.mk
 
-define sanitize_profile_name
-$(shell echo $(PROFILE) | tr '[:upper:]' '[:lower:]' | sed 's/_/-/g')
-endef
-
-define Image/BuildKernel/Template
+BOARDS:= \
+       sun4i-a10-cubieboard \
+       sun5i-a13-olinuxino \
+       sun7i-a20-olinuxino-micro \
+       sun7i-a20-cubieboard2
 
-       $(CP) $(KDIR)/zImage $(BIN_DIR)/$(IMG_PREFIX)-zImage
-       echo -ne '\x00\x00\x00\x00' >> $(BIN_DIR)/$(IMG_PREFIX)-zImage
-       $(call Image/BuildKernel/MkuImage, \
-               none, 0x40008000, 0x40008000, \
-               $(BIN_DIR)/$(IMG_PREFIX)-zImage, \
-               $(BIN_DIR)/$(IMG_PREFIX)-uImage \
-       )
-
- ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),)
+define Image/BuildKernel
+       mkimage -A arm -O linux -T kernel -C none \
+               -a 0x40008000 -e 0x40008000 \
+               -n 'ARM OpenWrt Linux-$(LINUX_VERSION)' \
+               -d $(KDIR)/zImage $(BIN_DIR)/$(IMG_PREFIX)-uImage
+       
+    ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),)
        $(CP) $(KDIR)/zImage-initramfs $(BIN_DIR)/$(IMG_PREFIX)-zImage-initramfs
        echo -ne '\x00\x00\x00\x00' >> $(BIN_DIR)/$(IMG_PREFIX)-zImage-initramfs
        $(call Image/BuildKernel/MkuImage, \
@@ -29,93 +27,15 @@ define Image/BuildKernel/Template
                $(BIN_DIR)/$(IMG_PREFIX)-zImage-initramfs, \
                $(BIN_DIR)/$(IMG_PREFIX)-uImage-initramfs \
        )
- endif
-
- ifneq ($(1),)
-       $(CP) $(LINUX_DIR)/arch/arm/boot/dts/$(1).dtb $(BIN_DIR)/$(IMG_PREFIX)-$(1).dtb
-
-       $(CP) $(KDIR)/zImage $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-zImage
-       cat $(BIN_DIR)/$(IMG_PREFIX)-$(1).dtb >> $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-zImage
-       $(call Image/BuildKernel/MkuImage, \
-               none, 0x40008000, 0x40008000, \
-               $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-zImage, \
-               $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-uImage \
-       )
+    endif
 
-  ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),)
-       $(CP) $(KDIR)/zImage-initramfs $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-zImage-initramfs
-       cat $(BIN_DIR)/$(IMG_PREFIX)-$(1).dtb >> $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-zImage-initramfs
-       $(call Image/BuildKernel/MkuImage, \
-               none, 0x40008000, 0x40008000, \
-               $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-zImage-initramfs, \
-               $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-uImage-initramfs \
+       $(foreach board,$(BOARDS),
+               $(CP) $(LINUX_DIR)/arch/arm/boot/dts/$(board).dtb $(BIN_DIR)/
        )
-  endif
- endif
-endef
-
-define Image/InstallKernel/Template
-
- ifneq ($(CONFIG_TARGET_ROOTFS_INCLUDE_KERNEL),)
-       $(INSTALL_DIR) $(TARGET_DIR)/boot
-   ifneq ($(CONFIG_TARGET_ROOTFS_INCLUDE_UIMAGE),)
-       $(CP) $(BIN_DIR)/$(IMG_PREFIX)-uImage $(TARGET_DIR)/boot/
-       ln -sf $(IMG_PREFIX)-uImage $(TARGET_DIR)/boot/uImage
-   endif
-   ifneq ($(CONFIG_TARGET_ROOTFS_INCLUDE_ZIMAGE),)
-       $(CP) $(BIN_DIR)/$(IMG_PREFIX)-zImage $(TARGET_DIR)/boot/
-       ln -sf $(IMG_PREFIX)-zImage $(TARGET_DIR)/boot/zImage
-   endif
- endif
-
- ifneq ($(CONFIG_TARGET_ROOTFS_INCLUDE_DTB),)
-       $(INSTALL_DIR) $(TARGET_DIR)/boot
-  ifneq ($(1),)
-       $(CP) $(BIN_DIR)/$(IMG_PREFIX)-$(1).dtb $(TARGET_DIR)/boot/
-       ln -sf $(IMG_PREFIX)-$(1).dtb $(TARGET_DIR)/boot/$(1).dtb
-  endif
- endif
-endef
-
-define Image/mkfs/targz
-
-       $(TAR) -czpf $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-rootfs.tar.gz --numeric-owner --owner=0 --group=0 -C $(TARGET_DIR)/ .
-endef
-
-define Image/Build/ubifs
-
- ifneq ($($(PROFILE)_UBIFS_OPTS),)
-       $(CP) $(KDIR)/root.ubifs $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-rootfs.ubifs
- endif
-endef
-
-define Image/Build/ubi
-
- ifneq ($($(PROFILE)_UBI_OPTS),)
-       $(CP) $(KDIR)/root.ubi $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-rootfs.ubi
- endif
-endef
-
-
-Image/BuildKernel/Template/generic=$(call Image/BuildKernel/Template)
-Image/InstallKernel/Template/generic=$(call Image/InstallKernel/Template)
-
-Image/BuildKernel/Template/CUBIEBOARD=$(call Image/BuildKernel/Template,sun4i-a10-cubieboard)
-Image/InstallKernel/Template/CUBIEBOARD=$(call Image/InstallKernel/Template,sun4i-a10-cubieboard)
-
-define Image/BuildKernel
-       $(call Image/BuildKernel/Template/$(PROFILE))
-endef
-
-define Image/InstallKernel
-       $(call Image/InstallKernel/Template/$(PROFILE))
 endef
 
 define Image/Build
-       $(if $(Image/Build/$(1)), \
-               $(call Image/Build/$(1),$(1)), \
-               $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(call sanitize_profile_name)-$(1).img \
-       )
+       $(call Image/Build/$(1),$(1))
 endef
 
 $(eval $(call BuildImage))
diff --git a/target/linux/sunxi/patches-3.12/100-clk-sunxi_register_factors.patch b/target/linux/sunxi/patches-3.12/100-clk-sunxi_register_factors.patch
new file mode 100644 (file)
index 0000000..c949eeb
--- /dev/null
@@ -0,0 +1,220 @@
+From 337d479970b0c8493ee3e8b8d89fb80ee39333a6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Sun, 5 May 2013 21:26:23 -0300
+Subject: [PATCH] clk: sunxi: register factors clocks behind composite
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit reworks factors clock registration to be done behind a
+composite clock. This allows us to additionally add a gate, mux or
+divisors, as it will be needed by some future PLLs.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ drivers/clk/sunxi/clk-factors.c | 63 +--------------------------------------
+ drivers/clk/sunxi/clk-factors.h | 16 +++++-----
+ drivers/clk/sunxi/clk-sunxi.c   | 66 ++++++++++++++++++++++++++++++++++++++---
+ 3 files changed, 72 insertions(+), 73 deletions(-)
+
+diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
+index 88523f9..6e3926c 100644
+--- a/drivers/clk/sunxi/clk-factors.c
++++ b/drivers/clk/sunxi/clk-factors.c
+@@ -30,14 +30,6 @@
+  * parent - fixed parent.  No clk_set_parent support
+  */
+-struct clk_factors {
+-      struct clk_hw hw;
+-      void __iomem *reg;
+-      struct clk_factors_config *config;
+-      void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
+-      spinlock_t *lock;
+-};
+-
+ #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
+ #define SETMASK(len, pos)             (((-1U) >> (31-len))  << (pos))
+@@ -120,61 +112,8 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
+       return 0;
+ }
+-static const struct clk_ops clk_factors_ops = {
++const struct clk_ops clk_factors_ops = {
+       .recalc_rate = clk_factors_recalc_rate,
+       .round_rate = clk_factors_round_rate,
+       .set_rate = clk_factors_set_rate,
+ };
+-
+-/**
+- * clk_register_factors - register a factors clock with
+- * the clock framework
+- * @dev: device registering this clock
+- * @name: name of this clock
+- * @parent_name: name of clock's parent
+- * @flags: framework-specific flags
+- * @reg: register address to adjust factors
+- * @config: shift and width of factors n, k, m and p
+- * @get_factors: function to calculate the factors for a given frequency
+- * @lock: shared register lock for this clock
+- */
+-struct clk *clk_register_factors(struct device *dev, const char *name,
+-                               const char *parent_name,
+-                               unsigned long flags, void __iomem *reg,
+-                               struct clk_factors_config *config,
+-                               void (*get_factors)(u32 *rate, u32 parent,
+-                                                   u8 *n, u8 *k, u8 *m, u8 *p),
+-                               spinlock_t *lock)
+-{
+-      struct clk_factors *factors;
+-      struct clk *clk;
+-      struct clk_init_data init;
+-
+-      /* allocate the factors */
+-      factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+-      if (!factors) {
+-              pr_err("%s: could not allocate factors clk\n", __func__);
+-              return ERR_PTR(-ENOMEM);
+-      }
+-
+-      init.name = name;
+-      init.ops = &clk_factors_ops;
+-      init.flags = flags;
+-      init.parent_names = (parent_name ? &parent_name : NULL);
+-      init.num_parents = (parent_name ? 1 : 0);
+-
+-      /* struct clk_factors assignments */
+-      factors->reg = reg;
+-      factors->config = config;
+-      factors->lock = lock;
+-      factors->hw.init = &init;
+-      factors->get_factors = get_factors;
+-
+-      /* register the clock */
+-      clk = clk_register(dev, &factors->hw);
+-
+-      if (IS_ERR(clk))
+-              kfree(factors);
+-
+-      return clk;
+-}
+diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
+index f49851c..02e1a43 100644
+--- a/drivers/clk/sunxi/clk-factors.h
++++ b/drivers/clk/sunxi/clk-factors.h
+@@ -17,11 +17,13 @@ struct clk_factors_config {
+       u8 pwidth;
+ };
+-struct clk *clk_register_factors(struct device *dev, const char *name,
+-                               const char *parent_name,
+-                               unsigned long flags, void __iomem *reg,
+-                               struct clk_factors_config *config,
+-                               void (*get_factors) (u32 *rate, u32 parent_rate,
+-                                                    u8 *n, u8 *k, u8 *m, u8 *p),
+-                               spinlock_t *lock);
++struct clk_factors {
++      struct clk_hw hw;
++      void __iomem *reg;
++      struct clk_factors_config *config;
++      void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
++      spinlock_t *lock;
++};
++
++extern const struct clk_ops clk_factors_ops;
+ #endif
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 34ee69f..6aed57f 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -256,7 +256,11 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
+  * sunxi_factors_clk_setup() - Setup function for factor clocks
+  */
++#define SUNXI_FACTORS_MUX_MASK 0x3
++
+ struct factors_data {
++      int enable;
++      int mux;
+       struct clk_factors_config *table;
+       void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
+ };
+@@ -307,16 +311,70 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
+                                          struct factors_data *data)
+ {
+       struct clk *clk;
++      struct clk_factors *factors;
++      struct clk_gate *gate;
++      struct clk_mux *mux;
++      struct clk_hw *gate_hw = NULL;
++      struct clk_hw *mux_hw = NULL;
+       const char *clk_name = node->name;
+-      const char *parent;
++      const char *parents[5];
+       void *reg;
++      int i = 0;
+       reg = of_iomap(node, 0);
+-      parent = of_clk_get_parent_name(node, 0);
++      /* if we have a mux, we will have >1 parents */
++      while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
++              i++;
++
++      factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
++      if (!factors)
++              return;
++
++      /* Add a gate if this factor clock can be gated */
++      if (data->enable) {
++              gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
++              if (!gate) {
++                      kfree(factors);
++                      return;
++              }
++
++              /* set up gate properties */
++              gate->reg = reg;
++              gate->bit_idx = data->enable;
++              gate->lock = &clk_lock;
++              gate_hw = &gate->hw;
++      }
+-      clk = clk_register_factors(NULL, clk_name, parent, 0, reg,
+-                                 data->table, data->getter, &clk_lock);
++      /* Add a mux if this factor clock can be muxed */
++      if (data->mux) {
++              mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
++              if (!mux) {
++                      kfree(factors);
++                      kfree(gate);
++                      return;
++              }
++
++              /* set up gate properties */
++              mux->reg = reg;
++              mux->shift = data->mux;
++              mux->mask = SUNXI_FACTORS_MUX_MASK;
++              mux->lock = &clk_lock;
++              mux_hw = &mux->hw;
++      }
++
++      /* set up factors properties */
++      factors->reg = reg;
++      factors->config = data->table;
++      factors->get_factors = data->getter;
++      factors->lock = &clk_lock;
++
++      clk = clk_register_composite(NULL, clk_name,
++                      parents, i,
++                      mux_hw, &clk_mux_ops,
++                      &factors->hw, &clk_factors_ops,
++                      gate_hw, &clk_gate_ops,
++                      i ? 0 : CLK_IS_ROOT);
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/101-clk-sunxi_add-gating-pll1.patch b/target/linux/sunxi/patches-3.12/101-clk-sunxi_add-gating-pll1.patch
new file mode 100644 (file)
index 0000000..00519b8
--- /dev/null
@@ -0,0 +1,51 @@
+From 68557a66b206de79a4556d393d51865407525d52 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Mon, 6 May 2013 09:59:00 -0300
+Subject: [PATCH] clk: sunxi: add gating support to PLL1
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit adds gating support to PLL1 on the clock driver. This makes
+the PLL1 implementation fully compatible with PLL4 as well.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ Documentation/devicetree/bindings/clock/sunxi.txt | 2 +-
+ drivers/clk/sunxi/clk-sunxi.c                     | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
+index 00a5c264..7d9245f 100644
+--- a/Documentation/devicetree/bindings/clock/sunxi.txt
++++ b/Documentation/devicetree/bindings/clock/sunxi.txt
+@@ -7,7 +7,7 @@ This binding uses the common clock binding[1].
+ Required properties:
+ - compatible : shall be one of the following:
+       "allwinner,sun4i-osc-clk" - for a gatable oscillator
+-      "allwinner,sun4i-pll1-clk" - for the main PLL clock
++      "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
+       "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
+       "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
+       "allwinner,sun4i-axi-clk" - for the AXI clock
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 6aed57f..c0b0675 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -293,11 +293,13 @@ struct factors_data {
+ };
+ static const struct factors_data sun4i_pll1_data __initconst = {
++      .enable = 31,
+       .table = &sun4i_pll1_config,
+       .getter = sun4i_get_pll1_factors,
+ };
+ static const struct factors_data sun6i_a31_pll1_data __initconst = {
++      .enable = 31,
+       .table = &sun6i_a31_pll1_config,
+       .getter = sun6i_a31_get_pll1_factors,
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/102-clk-sunxi_add_pll4.patch b/target/linux/sunxi/patches-3.12/102-clk-sunxi_add_pll4.patch
new file mode 100644 (file)
index 0000000..65fb3e6
--- /dev/null
@@ -0,0 +1,94 @@
+From 73bff3c4c33a2bfbddc593fad53c6c58af93bfab Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Mon, 6 May 2013 11:03:41 -0300
+Subject: [PATCH] ARM: sunxi: add PLL4 support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit adds the PLL4 definition to the sun4i, sun5i and sun7i
+device trees. PLL4 is compatible with PLL1.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi  | 7 +++++++
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 7 +++++++
+ arch/arm/boot/dts/sun5i-a13.dtsi  | 7 +++++++
+ arch/arm/boot/dts/sun7i-a20.dtsi  | 7 +++++++
+ 4 files changed, 28 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 319cc6b..a6c1cae 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -66,6 +66,13 @@
+                       clocks = <&osc24M>;
+               };
++              pll4: pll4@01c20018 {
++                      #clock-cells = <0>;
++                      compatible = "allwinner,sun4i-pll1-clk";
++                      reg = <0x01c20018 0x4>;
++                      clocks = <&osc24M>;
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 5247674..c3f4eed 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -63,6 +63,13 @@
+                       clocks = <&osc24M>;
+               };
++              pll4: pll4@01c20018 {
++                      #clock-cells = <0>;
++                      compatible = "allwinner,sun4i-pll1-clk";
++                      reg = <0x01c20018 0x4>;
++                      clocks = <&osc24M>;
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index ce8ef2a..8c4a9c3 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -67,6 +67,13 @@
+                       clocks = <&osc24M>;
+               };
++              pll4: pll4@01c20018 {
++                      #clock-cells = <0>;
++                      compatible = "allwinner,sun4i-pll1-clk";
++                      reg = <0x01c20018 0x4>;
++                      clocks = <&osc24M>;
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 282c775..21bf143 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -62,6 +62,13 @@
+                       clocks = <&osc24M>;
+               };
++              pll4: pll4@01c20018 {
++                      #clock-cells = <0>;
++                      compatible = "allwinner,sun4i-pll1-clk";
++                      reg = <0x01c20018 0x4>;
++                      clocks = <&osc24M>;
++              };
++
+               /*
+                * This is a dummy clock, to be used as placeholder on
+                * other mux clocks when a specific parent clock is not
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/103-clk-sunxi_add_pll5-6.patch b/target/linux/sunxi/patches-3.12/103-clk-sunxi_add_pll5-6.patch
new file mode 100644 (file)
index 0000000..f680a42
--- /dev/null
@@ -0,0 +1,309 @@
+From cad227619badf2a0ff2593d9935fedc84d5ef1ef Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Sun, 26 May 2013 14:23:50 -0300
+Subject: [PATCH] clk: sunxi: add PLL5 and PLL6 support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit implements PLL5 and PLL6 support on the sunxi clock driver.
+These PLLs use a similar factor clock, but differ on their outputs.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ Documentation/devicetree/bindings/clock/sunxi.txt |   2 +
+ drivers/clk/sunxi/clk-sunxi.c                     | 182 +++++++++++++++++++++-
+ 2 files changed, 177 insertions(+), 7 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
+index 7d9245f..773f3ae 100644
+--- a/Documentation/devicetree/bindings/clock/sunxi.txt
++++ b/Documentation/devicetree/bindings/clock/sunxi.txt
+@@ -9,6 +9,8 @@ Required properties:
+       "allwinner,sun4i-osc-clk" - for a gatable oscillator
+       "allwinner,sun4i-pll1-clk" - for the main PLL clock and PLL4
+       "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
++      "allwinner,sun4i-pll5-clk" - for the PLL5 clock
++      "allwinner,sun4i-pll6-clk" - for the PLL6 clock
+       "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
+       "allwinner,sun4i-axi-clk" - for the AXI clock
+       "allwinner,sun4i-axi-gates-clk" - for the AXI gates
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index c0b0675..6947ba9 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -210,6 +210,40 @@ static void sun6i_a31_get_pll1_factors(u32 *freq, u32 parent_rate,
+ }
+ /**
++ * sun4i_get_pll5_factors() - calculates n, k factors for PLL5
++ * PLL5 rate is calculated as follows
++ * rate = parent_rate * n * (k + 1)
++ * parent_rate is always 24Mhz
++ */
++
++static void sun4i_get_pll5_factors(u32 *freq, u32 parent_rate,
++                                 u8 *n, u8 *k, u8 *m, u8 *p)
++{
++      u8 div;
++
++      /* Normalize value to a 24M multiple */
++      div = *freq / 24000000;
++      *freq = 24000000 * div;
++
++      /* we were called to round the frequency, we can now return */
++      if (n == NULL)
++              return;
++
++      if (div < 31)
++              *k = 0;
++      else if (div / 2 < 31)
++              *k = 1;
++      else if (div / 3 < 31)
++              *k = 2;
++      else
++              *k = 3;
++
++      *n = DIV_ROUND_UP(div, (*k+1));
++}
++
++
++
++/**
+  * sun4i_get_apb1_factors() - calculates m, p factors for APB1
+  * APB1 rate is calculated as follows
+  * rate = (parent_rate >> p) / (m + 1);
+@@ -285,6 +319,13 @@ struct factors_data {
+       .mwidth = 2,
+ };
++static struct clk_factors_config sun4i_pll5_config = {
++      .nshift = 8,
++      .nwidth = 5,
++      .kshift = 4,
++      .kwidth = 2,
++};
++
+ static struct clk_factors_config sun4i_apb1_config = {
+       .mshift = 0,
+       .mwidth = 5,
+@@ -304,13 +345,19 @@ struct factors_data {
+       .getter = sun6i_a31_get_pll1_factors,
+ };
++static const struct factors_data sun4i_pll5_data __initconst = {
++      .enable = 31,
++      .table = &sun4i_pll5_config,
++      .getter = sun4i_get_pll5_factors,
++};
++
+ static const struct factors_data sun4i_apb1_data __initconst = {
+       .table = &sun4i_apb1_config,
+       .getter = sun4i_get_apb1_factors,
+ };
+-static void __init sunxi_factors_clk_setup(struct device_node *node,
+-                                         struct factors_data *data)
++static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
++                                              const struct factors_data *data)
+ {
+       struct clk *clk;
+       struct clk_factors *factors;
+@@ -321,6 +368,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
+       const char *clk_name = node->name;
+       const char *parents[5];
+       void *reg;
++      unsigned long flags;
+       int i = 0;
+       reg = of_iomap(node, 0);
+@@ -331,14 +379,14 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
+       factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+       if (!factors)
+-              return;
++              return NULL;
+       /* Add a gate if this factor clock can be gated */
+       if (data->enable) {
+               gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+               if (!gate) {
+                       kfree(factors);
+-                      return;
++                      return NULL;
+               }
+               /* set up gate properties */
+@@ -354,7 +402,7 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
+               if (!mux) {
+                       kfree(factors);
+                       kfree(gate);
+-                      return;
++                      return NULL;
+               }
+               /* set up gate properties */
+@@ -371,17 +419,21 @@ static void __init sunxi_factors_clk_setup(struct device_node *node,
+       factors->get_factors = data->getter;
+       factors->lock = &clk_lock;
++      /* We should not disable pll5, it powers the RAM */
++      flags = !strcmp("pll5", clk_name) ? CLK_IGNORE_UNUSED : 0;
++
+       clk = clk_register_composite(NULL, clk_name,
+                       parents, i,
+                       mux_hw, &clk_mux_ops,
+                       &factors->hw, &clk_factors_ops,
+-                      gate_hw, &clk_gate_ops,
+-                      i ? 0 : CLK_IS_ROOT);
++                      gate_hw, &clk_gate_ops, flags);
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               clk_register_clkdev(clk, clk_name, NULL);
+       }
++
++      return clk;
+ }
+@@ -616,6 +668,112 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
+       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ }
++
++
++/**
++ * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
++ */
++
++#define SUNXI_DIVS_MAX_QTY    2
++#define SUNXI_DIVISOR_WIDTH   2
++
++struct divs_data {
++      const struct factors_data *factors; /* data for the factor clock */
++      struct {
++              u8 fixed; /* is it a fixed divisor? if not... */
++              struct clk_div_table *table; /* is it a table based divisor? */
++              u8 shift; /* otherwise it's a normal divisor with this shift */
++              u8 pow;   /* is it power-of-two based? */
++      } div[SUNXI_DIVS_MAX_QTY];
++};
++
++static struct clk_div_table pll6_sata_table[] = {
++      { .val = 0, .div = 6, },
++      { .val = 1, .div = 12, },
++      { .val = 2, .div = 18, },
++      { .val = 3, .div = 24, },
++      { } /* sentinel */
++};
++
++static const struct divs_data pll5_divs_data __initconst = {
++      .factors = &sun4i_pll5_data,
++      .div = {
++              { .shift = 0, .pow = 0, }, /* M, DDR */
++              { .shift = 16, .pow = 1, }, /* P, other */
++      }
++};
++
++static const struct divs_data pll6_divs_data __initconst = {
++      .factors = &sun4i_pll5_data,
++      .div = {
++              { .shift = 0, .table = pll6_sata_table }, /* M, SATA */
++              { .fixed = 2 }, /* P, other */
++      }
++};
++
++static void __init sunxi_divs_clk_setup(struct device_node *node,
++                                      struct divs_data *data)
++{
++      struct clk_onecell_data *clk_data;
++      const char *parent  = node->name;
++      const char *clk_name;
++      struct clk **clks, *pclk;
++      void *reg;
++      int i = 0;
++      int flags, clkflags;
++
++      /* Set up factor clock that we will be dividing */
++      pclk = sunxi_factors_clk_setup(node, data->factors);
++
++      reg = of_iomap(node, 0);
++
++      clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
++      if (!clk_data)
++              return;
++      clks = kzalloc(SUNXI_DIVS_MAX_QTY * sizeof(struct clk *), GFP_KERNEL);
++      if (!clks) {
++              kfree(clk_data);
++              return;
++      }
++      clk_data->clks = clks;
++
++      /* It's not a good idea to have automatic reparenting changing
++       * our RAM clock! */
++      clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
++
++      for (i = 0; i < SUNXI_DIVS_MAX_QTY; i++) {
++              if (of_property_read_string_index(node, "clock-output-names",
++                                                i, &clk_name) != 0)
++                      break;
++
++              if (data->div[i].fixed) {
++                      clks[i] = clk_register_fixed_factor(NULL, clk_name,
++                                              parent, clkflags,
++                                              1, data->div[i].fixed);
++              } else {
++                      flags = data->div[i].pow ? CLK_DIVIDER_POWER_OF_TWO : 0;
++                      clks[i] = clk_register_divider_table(NULL, clk_name,
++                                              parent, clkflags, reg,
++                                              data->div[i].shift,
++                                              SUNXI_DIVISOR_WIDTH, flags,
++                                              data->div[i].table, &clk_lock);
++              }
++
++              WARN_ON(IS_ERR(clk_data->clks[i]));
++              clk_register_clkdev(clks[i], clk_name, NULL);
++      }
++
++      /* The last clock available on the getter is the parent */
++      clks[i++] = pclk;
++
++      /* Adjust to the real max */
++      clk_data->clk_num = i;
++
++      of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
++}
++
++
++
+ /* Matches for factors clocks */
+ static const struct of_device_id clk_factors_match[] __initconst = {
+       {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
+@@ -633,6 +791,13 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
+       {}
+ };
++/* Matches for divided outputs */
++static const struct of_device_id clk_divs_match[] __initconst = {
++      {.compatible = "allwinner,sun4i-pll5-clk", .data = &pll5_divs_data,},
++      {.compatible = "allwinner,sun4i-pll6-clk", .data = &pll6_divs_data,},
++      {}
++};
++
+ /* Matches for mux clocks */
+ static const struct of_device_id clk_mux_match[] __initconst = {
+       {.compatible = "allwinner,sun4i-cpu-clk", .data = &sun4i_cpu_mux_data,},
+@@ -688,6 +853,9 @@ void __init sunxi_init_clocks(void)
+       /* Register divider clocks */
+       of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
++      /* Register divided output clocks */
++      of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
++
+       /* Register mux clocks */
+       of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/104-arm-sunxi_add_pll5-6_dts.patch b/target/linux/sunxi/patches-3.12/104-arm-sunxi_add_pll5-6_dts.patch
new file mode 100644 (file)
index 0000000..bd92212
--- /dev/null
@@ -0,0 +1,197 @@
+From 4f40ad1587e9435a2085703fa2a7d7c9245306b2 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Sun, 26 May 2013 14:08:59 -0300
+Subject: [PATCH] ARM: sunxi: add PLL5 and PLL6 support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit adds PLL5 and PLL6 nodes to the sun4i, sun5i and sun7i
+device trees.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi  | 19 +++++++++++++++++--
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 19 +++++++++++++++++--
+ arch/arm/boot/dts/sun5i-a13.dtsi  | 19 +++++++++++++++++--
+ arch/arm/boot/dts/sun7i-a20.dtsi  | 28 ++++++++++++++++------------
+ 4 files changed, 67 insertions(+), 18 deletions(-)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index a6c1cae..5e2fc45 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -73,6 +73,22 @@
+                       clocks = <&osc24M>;
+               };
++              pll5: pll5@01c20020 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll5-clk";
++                      reg = <0x01c20020 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll5_ddr", "pll5_other";
++              };
++
++              pll6: pll6@01c20028 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll6-clk";
++                      reg = <0x01c20028 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll6_sata", "pll6_other", "pll6";
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+@@ -138,12 +154,11 @@
+                               "apb0_ir1", "apb0_keypad";
+               };
+-              /* dummy is pll62 */
+               apb1_mux: apb1_mux@01c20058 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-apb1-mux-clk";
+                       reg = <0x01c20058 0x4>;
+-                      clocks = <&osc24M>, <&dummy>, <&osc32k>;
++                      clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+               };
+               apb1: apb1@01c20058 {
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index c3f4eed..b29412a 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -70,6 +70,22 @@
+                       clocks = <&osc24M>;
+               };
++              pll5: pll5@01c20020 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll5-clk";
++                      reg = <0x01c20020 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll5_ddr", "pll5_other";
++              };
++
++              pll6: pll6@01c20028 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll6-clk";
++                      reg = <0x01c20028 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll6_sata", "pll6_other", "pll6";
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+@@ -130,12 +146,11 @@
+                               "apb0_ir", "apb0_keypad";
+               };
+-              /* dummy is pll62 */
+               apb1_mux: apb1_mux@01c20058 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-apb1-mux-clk";
+                       reg = <0x01c20058 0x4>;
+-                      clocks = <&osc24M>, <&dummy>, <&osc32k>;
++                      clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+               };
+               apb1: apb1@01c20058 {
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 8c4a9c3..cded3c7 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -74,6 +74,22 @@
+                       clocks = <&osc24M>;
+               };
++              pll5: pll5@01c20020 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll5-clk";
++                      reg = <0x01c20020 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll5_ddr", "pll5_other";
++              };
++
++              pll6: pll6@01c20028 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll6-clk";
++                      reg = <0x01c20028 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll6_sata", "pll6_other", "pll6";
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+@@ -132,12 +148,11 @@
+                       clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir";
+               };
+-              /* dummy is pll6 */
+               apb1_mux: apb1_mux@01c20058 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-apb1-mux-clk";
+                       reg = <0x01c20058 0x4>;
+-                      clocks = <&osc24M>, <&dummy>, <&osc32k>;
++                      clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+               };
+               apb1: apb1@01c20058 {
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 21bf143..2e39ed9 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -69,23 +69,27 @@
+                       clocks = <&osc24M>;
+               };
+-              /*
+-               * This is a dummy clock, to be used as placeholder on
+-               * other mux clocks when a specific parent clock is not
+-               * yet implemented. It should be dropped when the driver
+-               * is complete.
+-               */
+-              pll6: pll6 {
+-                      #clock-cells = <0>;
+-                      compatible = "fixed-clock";
+-                      clock-frequency = <0>;
++              pll5: pll5@01c20020 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll5-clk";
++                      reg = <0x01c20020 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll5_ddr", "pll5_other";
++              };
++
++              pll6: pll6@01c20028 {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun4i-pll6-clk";
++                      reg = <0x01c20028 0x4>;
++                      clocks = <&osc24M>;
++                      clock-output-names = "pll6_sata", "pll6_other", "pll6";
+               };
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-cpu-clk";
+                       reg = <0x01c20054 0x4>;
+-                      clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6>;
++                      clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll6 1>;
+               };
+               axi: axi@01c20054 {
+@@ -144,7 +148,7 @@
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-apb1-mux-clk";
+                       reg = <0x01c20058 0x4>;
+-                      clocks = <&osc24M>, <&pll6>, <&osc32k>;
++                      clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
+               };
+               apb1: apb1@01c20058 {
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/105-clk-sunxi_mod0.patch b/target/linux/sunxi/patches-3.12/105-clk-sunxi_mod0.patch
new file mode 100644 (file)
index 0000000..bbb8057
--- /dev/null
@@ -0,0 +1,121 @@
+From 3473e6acea4bd01ba2b334628970390207f9f4fd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <emilio@elopez.com.ar>
+Date: Tue, 21 May 2013 21:25:05 -0300
+Subject: [PATCH] clk: sunxi: mod0 support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit implements support for the "module 0" type of clocks, as
+used by MMC, IR, NAND, SATA and other components.
+
+Signed-off-by: Emilio López <emilio@elopez.com.ar>
+---
+ Documentation/devicetree/bindings/clock/sunxi.txt |  1 +
+ drivers/clk/sunxi/clk-sunxi.c                     | 57 +++++++++++++++++++++++
+ 2 files changed, 58 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
+index 773f3ae..ff3f61c 100644
+--- a/Documentation/devicetree/bindings/clock/sunxi.txt
++++ b/Documentation/devicetree/bindings/clock/sunxi.txt
+@@ -35,6 +35,7 @@ Required properties:
+       "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
+       "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
+       "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
++      "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
+ Required properties for all clocks:
+ - reg : shall be the control register address for the clock.
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 6947ba9..96c01b2 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -287,6 +287,47 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
+ /**
++ * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
++ * MMC rate is calculated as follows
++ * rate = (parent_rate >> p) / (m + 1);
++ */
++
++static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
++                                 u8 *n, u8 *k, u8 *m, u8 *p)
++{
++      u8 div, calcm, calcp;
++
++      /* These clocks can only divide, so we will never be able to achieve
++       * frequencies higher than the parent frequency */
++      if (*freq > parent_rate)
++              *freq = parent_rate;
++
++      div = parent_rate / *freq;
++
++      if (div < 16)
++              calcp = 0;
++      else if (div / 2 < 16)
++              calcp = 1;
++      else if (div / 4 < 16)
++              calcp = 2;
++      else
++              calcp = 3;
++
++      calcm = DIV_ROUND_UP(div, 1 << calcp);
++
++      *freq = (parent_rate >> calcp) / calcm;
++
++      /* we were called to round the frequency, we can now return */
++      if (n == NULL)
++              return;
++
++      *m = calcm - 1;
++      *p = calcp;
++}
++
++
++
++/**
+  * sunxi_factors_clk_setup() - Setup function for factor clocks
+  */
+@@ -333,6 +374,14 @@ struct factors_data {
+       .pwidth = 2,
+ };
++/* user manual says "n" but it's really "p" */
++static struct clk_factors_config sun4i_mod0_config = {
++      .mshift = 0,
++      .mwidth = 4,
++      .pshift = 16,
++      .pwidth = 2,
++};
++
+ static const struct factors_data sun4i_pll1_data __initconst = {
+       .enable = 31,
+       .table = &sun4i_pll1_config,
+@@ -356,6 +405,13 @@ struct factors_data {
+       .getter = sun4i_get_apb1_factors,
+ };
++static const struct factors_data sun4i_mod0_data __initconst = {
++      .enable = 31,
++      .mux = 24,
++      .table = &sun4i_mod0_config,
++      .getter = sun4i_get_mod0_factors,
++};
++
+ static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
+                                               const struct factors_data *data)
+ {
+@@ -779,6 +835,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
+       {.compatible = "allwinner,sun4i-pll1-clk", .data = &sun4i_pll1_data,},
+       {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
+       {.compatible = "allwinner,sun4i-apb1-clk", .data = &sun4i_apb1_data,},
++      {.compatible = "allwinner,sun4i-mod0-clk", .data = &sun4i_mod0_data,},
+       {}
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/120-split-dt-for-sun6i-sun7i.patch b/target/linux/sunxi/patches-3.12/120-split-dt-for-sun6i-sun7i.patch
new file mode 100644 (file)
index 0000000..439f7d9
--- /dev/null
@@ -0,0 +1,56 @@
+From eac8f640c624e83ef2ae267efc0769e086a64059 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sun, 11 Aug 2013 14:35:08 +0200
+Subject: [PATCH] ARM: sunxi: Split out the DT machines for sun6i and sun7i
+
+The A20 and A31 SMP code have a different way of bringing up a new core.
+This will prevent us from using the same set of smp_operations for the
+two SoCs family.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/mach-sunxi/sunxi.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
+index e79fb34..e0641dd 100644
+--- a/arch/arm/mach-sunxi/sunxi.c
++++ b/arch/arm/mach-sunxi/sunxi.c
+@@ -133,8 +133,6 @@ static void __init sunxi_dt_init(void)
+       "allwinner,sun4i-a10",
+       "allwinner,sun5i-a10s",
+       "allwinner,sun5i-a13",
+-      "allwinner,sun6i-a31",
+-      "allwinner,sun7i-a20",
+       NULL,
+ };
+@@ -143,3 +141,25 @@ static void __init sunxi_dt_init(void)
+       .init_time      = sunxi_timer_init,
+       .dt_compat      = sunxi_board_dt_compat,
+ MACHINE_END
++
++static const char * const sun6i_board_dt_compat[] = {
++      "allwinner,sun6i-a31",
++      NULL,
++};
++
++DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family")
++      .init_machine   = sunxi_dt_init,
++      .init_time      = sunxi_timer_init,
++      .dt_compat      = sun6i_board_dt_compat,
++MACHINE_END
++
++static const char * const sun7i_board_dt_compat[] = {
++      "allwinner,sun7i-a20",
++      NULL,
++};
++
++DT_MACHINE_START(SUN7I_DT, "Allwinner sun7i (A20) Family")
++      .init_machine   = sunxi_dt_init,
++      .init_time      = sunxi_timer_init,
++      .dt_compat      = sun7i_board_dt_compat,
++MACHINE_END
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/130-sun7i-enable-i2c-ctrlers.patch b/target/linux/sunxi/patches-3.12/130-sun7i-enable-i2c-ctrlers.patch
new file mode 100644 (file)
index 0000000..ef761a6
--- /dev/null
@@ -0,0 +1,73 @@
+From 220d6c860e0c7853aea6509ea2b5a44463c9af8b Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 31 Aug 2013 23:07:24 +0200
+Subject: [PATCH] ARM: sun7i: Enable the I2C controllers
+
+The Allwinner A20 shares the same I2C controller than the one that could
+be found on earlier SoCs from Allwinner. There is only a few more of
+these controllers. Add all of them in the DTSI.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 45 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 45 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 2e39ed9..0d0ee15 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -340,6 +340,51 @@
+                       status = "disabled";
+               };
++              i2c0: i2c@01c2ac00 {
++                      compatible = "allwinner,sun4i-i2c";
++                      reg = <0x01c2ac00 0x400>;
++                      interrupts = <0 7 1>;
++                      clocks = <&apb1_gates 0>;
++                      clock-frequency = <100000>;
++                      status = "disabled";
++              };
++
++              i2c1: i2c@01c2b000 {
++                      compatible = "allwinner,sun4i-i2c";
++                      reg = <0x01c2b000 0x400>;
++                      interrupts = <0 8 1>;
++                      clocks = <&apb1_gates 1>;
++                      clock-frequency = <100000>;
++                      status = "disabled";
++              };
++
++              i2c2: i2c@01c2b400 {
++                      compatible = "allwinner,sun4i-i2c";
++                      reg = <0x01c2b400 0x400>;
++                      interrupts = <0 9 1>;
++                      clocks = <&apb1_gates 2>;
++                      clock-frequency = <100000>;
++                      status = "disabled";
++              };
++
++              i2c3: i2c@01c2b800 {
++                      compatible = "allwinner,sun4i-i2c";
++                      reg = <0x01c2b800 0x400>;
++                      interrupts = <0 88 1>;
++                      clocks = <&apb1_gates 3>;
++                      clock-frequency = <100000>;
++                      status = "disabled";
++              };
++
++              i2c4: i2c@01c2bc00 {
++                      compatible = "allwinner,sun4i-i2c";
++                      reg = <0x01c2bc00 0x400>;
++                      interrupts = <0 89 1>;
++                      clocks = <&apb1_gates 15>;
++                      clock-frequency = <100000>;
++                      status = "disabled";
++              };
++
+               gic: interrupt-controller@01c81000 {
+                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       reg = <0x01c81000 0x1000>,
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/131-sun7i-add-i2c-pinmuxing.patch b/target/linux/sunxi/patches-3.12/131-sun7i-add-i2c-pinmuxing.patch
new file mode 100644 (file)
index 0000000..951059f
--- /dev/null
@@ -0,0 +1,49 @@
+From 1baebecc2892567373f5f9c3650d21496125af18 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 31 Aug 2013 23:08:49 +0200
+Subject: [PATCH] ARM: sun7i: Add the pin muxing options for the I2C
+ controllers
+
+The A20 boards we currently have share the same pins for the i2c
+controllers they share. Add them to the DTSI.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 0d0ee15..a6cd039 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -226,6 +226,27 @@
+                               allwinner,pull = <0>;
+                       };
++                      i2c0_pins_a: i2c0@0 {
++                              allwinner,pins = "PB0", "PB1";
++                              allwinner,function = "i2c0";
++                              allwinner,drive = <0>;
++                              allwinner,pull = <0>;
++                      };
++
++                      i2c1_pins_a: i2c1@0 {
++                              allwinner,pins = "PB18", "PB19";
++                              allwinner,function = "i2c1";
++                              allwinner,drive = <0>;
++                              allwinner,pull = <0>;
++                      };
++
++                      i2c2_pins_a: i2c2@0 {
++                              allwinner,pins = "PB20", "PB21";
++                              allwinner,function = "i2c2";
++                              allwinner,drive = <0>;
++                              allwinner,pull = <0>;
++                      };
++
+                       emac_pins_a: emac0@0 {
+                               allwinner,pins = "PA0", "PA1", "PA2",
+                                               "PA3", "PA4", "PA5", "PA6",
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/132-add-dt-i2c-for-olinuxino-a20.patch b/target/linux/sunxi/patches-3.12/132-add-dt-i2c-for-olinuxino-a20.patch
new file mode 100644 (file)
index 0000000..c1f3b70
--- /dev/null
@@ -0,0 +1,45 @@
+From 45cfefedb2886fac4a7f18c1720310ea9792ea4c Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 31 Aug 2013 23:14:19 +0200
+Subject: [PATCH] ARM: sun7i: olinuxino-micro: Enable the I2C controllers
+
+The A20-olinuxino-micro uses the first three I2C controllers found on
+the A20. Enable them in the DT.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index 9e77855..ead3013 100644
+--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+@@ -60,6 +60,24 @@
+                       pinctrl-0 = <&uart7_pins_a>;
+                       status = "okay";
+               };
++
++              i2c0: i2c@01c2ac00 {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c0_pins_a>;
++                      status = "okay";
++              };
++
++              i2c1: i2c@01c2b000 {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c1_pins_a>;
++                      status = "okay";
++              };
++
++              i2c2: i2c@01c2b400 {
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&i2c2_pins_a>;
++                      status = "okay";
++              };
+       };
+       leds {
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/140-add-a31-reset-driver.patch b/target/linux/sunxi/patches-3.12/140-add-a31-reset-driver.patch
new file mode 100644 (file)
index 0000000..3d48a5f
--- /dev/null
@@ -0,0 +1,189 @@
+From d8d7a5805579db687fdfdfda4125b43d6a50e616 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Tue, 24 Sep 2013 11:07:43 +0300
+Subject: [PATCH] reset: Add Allwinner A31 Reset Controller Driver
+
+The Allwinner A31 has an IP maintaining a few other IPs in the SoC in
+reset by default. Among these IPs are the High Speed Timers, hence why
+we can't use the regular driver construct, and need to call the
+registering function directly during machine initialisation.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ drivers/reset/Makefile      |   1 +
+ drivers/reset/reset-sunxi.c | 156 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 157 insertions(+)
+ create mode 100644 drivers/reset/reset-sunxi.c
+
+diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
+index 1e2d83f..f216b74 100644
+--- a/drivers/reset/Makefile
++++ b/drivers/reset/Makefile
+@@ -1 +1,2 @@
+ obj-$(CONFIG_RESET_CONTROLLER) += core.o
++obj-$(CONFIG_ARCH_SUNXI) += reset-sun6i.o
+diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
+new file mode 100644
+index 0000000..5bbd59a
+--- /dev/null
++++ b/drivers/reset/reset-sunxi.c
+@@ -0,0 +1,156 @@
++/*
++ * Allwinner SoCs Reset Controller driver
++ *
++ * Copyright 2013 Maxime Ripard
++ *
++ * Maxime Ripard <maxime.ripard@free-electrons.com>
++ *
++ * 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.
++ */
++
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/reset-controller.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++
++struct sunxi_reset_data {
++      void __iomem                            *membase;
++      struct reset_controller_dev             rcdev;
++};
++
++static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
++                            unsigned long id)
++{
++      struct sunxi_reset_data *data = container_of(rcdev,
++                                                   struct sunxi_reset_data,
++                                                   rcdev);
++      int bank = id / BITS_PER_LONG;
++      int offset = id % BITS_PER_LONG;
++      u32 reg = readl(data->membase + (bank * 4));
++
++      writel(reg & ~BIT(offset), data->membase + (bank * 4));
++
++      return 0;
++}
++
++static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
++                              unsigned long id)
++{
++      struct sunxi_reset_data *data = container_of(rcdev,
++                                                   struct sunxi_reset_data,
++                                                   rcdev);
++      int bank = id / BITS_PER_LONG;
++      int offset = id % BITS_PER_LONG;
++      u32 reg = readl(data->membase + (bank * 4));
++
++      writel(reg | BIT(offset), data->membase + (bank * 4));
++
++      return 0;
++}
++
++static struct reset_control_ops sunxi_reset_ops = {
++      .assert         = sunxi_reset_assert,
++      .deassert       = sunxi_reset_deassert,
++};
++
++static int sunxi_reset_init(struct device_node *np)
++{
++      struct sunxi_reset_data *data;
++      struct resource res;
++      resource_size_t size;
++      int ret;
++
++      data = kzalloc(sizeof(*data), GFP_KERNEL);
++      if (!data)
++              return -ENOMEM;
++
++      ret = of_address_to_resource(np, 0, &res);
++      if (ret)
++              goto err_alloc;
++
++      size = resource_size(&res);
++      data->membase = ioremap(res.start, size);
++      if (!data->membase) {
++              ret = -ENOMEM;
++              goto err_alloc;
++      }
++
++      data->rcdev.owner = THIS_MODULE;
++      data->rcdev.nr_resets = size * 32;
++      data->rcdev.ops = &sunxi_reset_ops;
++      data->rcdev.of_node = np;
++      reset_controller_register(&data->rcdev);
++
++      return 0;
++
++err_alloc:
++      kfree(data);
++      return ret;
++};
++
++/*
++ * These are the reset controller we need to initialize early on in
++ * our system, before we can even think of using a regular device
++ * driver for it.
++ */
++static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = {
++      { .compatible = "allwinner,sun6i-a31-ahb1-reset", },
++      { /* sentinel */ },
++};
++
++void __init sun6i_reset_init(void)
++{
++      struct device_node *np;
++
++      for_each_matching_node(np, sunxi_early_reset_dt_ids)
++              sunxi_reset_init(np);
++}
++
++/*
++ * And these are the controllers we can register through the regular
++ * device model.
++ */
++static const struct of_device_id sunxi_reset_dt_ids[] = {
++       { .compatible = "allwinner,sun4i-clock-reset", },
++       { /* sentinel */ },
++};
++MODULE_DEVICE_TABLE(of, sunxi_reset_dt_ids);
++
++static int sunxi_reset_probe(struct platform_device *pdev)
++{
++      return sunxi_reset_init(pdev->dev.of_node);
++}
++
++static int sunxi_reset_remove(struct platform_device *pdev)
++{
++      struct sunxi_reset_data *data = platform_get_drvdata(pdev);
++
++      reset_controller_unregister(&data->rcdev);
++      iounmap(data->membase);
++      kfree(data);
++
++      return 0;
++}
++
++static struct platform_driver sunxi_reset_driver = {
++      .probe  = sunxi_reset_probe,
++      .remove = sunxi_reset_remove,
++      .driver = {
++              .name           = "sunxi-reset",
++              .owner          = THIS_MODULE,
++              .of_match_table = sunxi_reset_dt_ids,
++      },
++};
++module_platform_driver(sunxi_reset_driver);
++
++MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
++MODULE_DESCRIPTION("Allwinner SoCs Reset Controller Driver");
++MODULE_LICENSE("GPL");
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/141-add-Kconfig-for-reset.patch b/target/linux/sunxi/patches-3.12/141-add-Kconfig-for-reset.patch
new file mode 100644 (file)
index 0000000..394b9c7
--- /dev/null
@@ -0,0 +1,27 @@
+From 6bf236bb67dfabd0434df47ff1247b1310d4ccf5 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Tue, 24 Sep 2013 11:09:55 +0300
+Subject: [PATCH] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER
+
+The A31 has a reset controller, and we have to select this option to
+have access to the reset controller framework.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/mach-sunxi/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
+index bce0d42..547004c 100644
+--- a/arch/arm/mach-sunxi/Kconfig
++++ b/arch/arm/mach-sunxi/Kconfig
+@@ -1,5 +1,6 @@
+ config ARCH_SUNXI
+       bool "Allwinner A1X SOCs" if ARCH_MULTI_V7
++      select ARCH_HAS_RESET_CONTROLLER
+       select ARCH_REQUIRE_GPIOLIB
+       select ARM_GIC
+       select CLKSRC_MMIO
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/142-register-a31-reset.patch b/target/linux/sunxi/patches-3.12/142-register-a31-reset.patch
new file mode 100644 (file)
index 0000000..4853647
--- /dev/null
@@ -0,0 +1,41 @@
+From ba9cb86c174603252ee5b5f2b277dab46a99cf02 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Sat, 5 Oct 2013 14:53:48 +0200
+Subject: [PATCH] ARM: sunxi: Register the A31 reset IP in init_time
+
+The A31 has a reset IP that maintains a few other IPs in reset by
+default. Among these IPs are the UARTs, and most notably the timers. We
+thus need to register the reset driver before initializing the timers so
+that the reset timer can use the reset framework.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/mach-sunxi/sunxi.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
+index f184f6c..2e79736 100644
+--- a/arch/arm/mach-sunxi/sunxi.c
++++ b/arch/arm/mach-sunxi/sunxi.c
+@@ -142,9 +142,17 @@ static void __init sunxi_dt_init(void)
+       NULL,
+ };
++extern void __init sun6i_reset_init(void);
++static void __init sun6i_timer_init(void)
++{
++      sunxi_init_clocks();
++      sun6i_reset_init();
++      clocksource_of_init();
++}
++
+ DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family")
+       .init_machine   = sunxi_dt_init,
+-      .init_time      = sunxi_timer_init,
++      .init_time      = sun6i_timer_init,
+       .dt_compat      = sun6i_board_dt_compat,
+       .restart        = sun6i_restart,
+ MACHINE_END
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/143-add-dtsi-for-reset.patch b/target/linux/sunxi/patches-3.12/143-add-dtsi-for-reset.patch
new file mode 100644 (file)
index 0000000..62ade36
--- /dev/null
@@ -0,0 +1,94 @@
+From 2a906d06b21968803ce504348864908ad1ed66ac Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Tue, 24 Sep 2013 11:10:41 +0300
+Subject: [PATCH] ARM: sun6i: Add the reset controller to the DTSI
+
+The A31 has a reset controller IP that maintains a few other IPs in
+reset, among which we can find the UARTs, high speed timers or the I2C.
+Now that we have support for them, add the reset controllers to the DTSI.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ arch/arm/boot/dts/sun6i-a31.dtsi | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
+index c1751a6..c7e0658 100644
+--- a/arch/arm/boot/dts/sun6i-a31.dtsi
++++ b/arch/arm/boot/dts/sun6i-a31.dtsi
+@@ -209,6 +209,24 @@
+                       };
+               };
++              ahb1_rst: reset@01c202c0 {
++                      #reset-cells = <1>;
++                      compatible = "allwinner,sun6i-a31-ahb1-reset";
++                      reg = <0x01c202c0 0xc>;
++              };
++
++              apb1_rst: reset@01c202d0 {
++                      #reset-cells = <1>;
++                      compatible = "allwinner,sun4i-clock-reset";
++                      reg = <0x01c202d0 0x4>;
++              };
++
++              apb2_rst: reset@01c202d8 {
++                      #reset-cells = <1>;
++                      compatible = "allwinner,sun4i-clock-reset";
++                      reg = <0x01c202d8 0x4>;
++              };
++
+               timer@01c20c00 {
+                       compatible = "allwinner,sun4i-timer";
+                       reg = <0x01c20c00 0xa0>;
+@@ -232,6 +250,7 @@
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb2_gates 16>;
++                      resets = <&apb2_rst 16>;
+                       status = "disabled";
+               };
+@@ -242,6 +261,7 @@
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb2_gates 17>;
++                      resets = <&apb2_rst 17>;
+                       status = "disabled";
+               };
+@@ -252,6 +272,7 @@
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb2_gates 18>;
++                      resets = <&apb2_rst 18>;
+                       status = "disabled";
+               };
+@@ -262,6 +283,7 @@
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb2_gates 19>;
++                      resets = <&apb2_rst 19>;
+                       status = "disabled";
+               };
+@@ -272,6 +294,7 @@
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb2_gates 20>;
++                      resets = <&apb2_rst 20>;
+                       status = "disabled";
+               };
+@@ -282,6 +305,7 @@
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb2_gates 21>;
++                      resets = <&apb2_rst 21>;
+                       status = "disabled";
+               };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/145-fix-reset-for-all-sunxi.patch b/target/linux/sunxi/patches-3.12/145-fix-reset-for-all-sunxi.patch
new file mode 100644 (file)
index 0000000..130bf04
--- /dev/null
@@ -0,0 +1,20 @@
+From ab2f1e0056db0e5a0717981546a69d5b81439661 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Sun, 20 Oct 2013 22:59:01 +0200
+Subject: [PATCH] reset: Fix mpripard's reset patch
+
+---
+ drivers/reset/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
+index f216b74..cc29832 100644
+--- a/drivers/reset/Makefile
++++ b/drivers/reset/Makefile
+@@ -1,2 +1,2 @@
+ obj-$(CONFIG_RESET_CONTROLLER) += core.o
+-obj-$(CONFIG_ARCH_SUNXI) += reset-sun6i.o
++obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/150-sun4i-add-dt-bindings.patch b/target/linux/sunxi/patches-3.12/150-sun4i-add-dt-bindings.patch
new file mode 100644 (file)
index 0000000..3bc6769
--- /dev/null
@@ -0,0 +1,31 @@
+From 378dab1f11d0386e26363517922dc086227aa6c5 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Thu, 19 Sep 2013 21:58:47 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add bindings for USB clocks
+
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 5e2fc45..3033684 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -89,6 +89,14 @@
+                       clock-output-names = "pll6_sata", "pll6_other", "pll6";
+               };
++              usb:usb@0x01c200cc {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun47i-usb-gates-clk";
++                      reg = <0x01c200cc 0x4>;
++                      clocks = <&pll6 1>;
++                      clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/151-clk-sunxi-add-usbclocks.patch b/target/linux/sunxi/patches-3.12/151-clk-sunxi-add-usbclocks.patch
new file mode 100644 (file)
index 0000000..2fb52f1
--- /dev/null
@@ -0,0 +1,35 @@
+From 43c2d3189567342f68ec192f2eeab6ae4c4d1ddf Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Thu, 19 Sep 2013 21:59:32 +0200
+Subject: [PATCH] clk: sunxi: Add support for USB clocks
+
+---
+ drivers/clk/sunxi/clk-sunxi.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index 96c01b2..cbe1516 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -619,6 +619,10 @@ struct gates_data {
+       .mask = {0x7F77FFF, 0x14FB3F},
+ };
++static const struct gates_data sun47i_usb_gates_data __initconst = {
++      .mask = {0x1C0},
++};
++
+ static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
+       .mask = {0x147667e7, 0x185915},
+ };
+@@ -867,6 +871,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
+ static const struct of_device_id clk_gates_match[] __initconst = {
+       {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
+       {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
++      {.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,},
+       {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
+       {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
+       {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/152-sun4i-dt-add-usb-ehci-bindings.patch b/target/linux/sunxi/patches-3.12/152-sun4i-dt-add-usb-ehci-bindings.patch
new file mode 100644 (file)
index 0000000..0a46d06
--- /dev/null
@@ -0,0 +1,62 @@
+From 90bc2022b61dcfd4d785416ee3aabc2157bfd57a Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Wed, 18 Sep 2013 00:30:04 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add USB EHCI bindings
+
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 3033684..6c05264 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -15,6 +15,11 @@
+ / {
+       interrupt-parent = <&intc>;
++      aliases {
++              ehci1 = &ehci0;
++              ehci2 = &ehci1;
++      };
++
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+@@ -407,5 +412,33 @@
+                       clock-frequency = <100000>;
+                       status = "disabled";
+               };
++
++              usb_rst: reset@0x01c200cc {
++                      #reset-cells = <1>;
++                      compatible = "allwinner,sun4i-clock-reset";
++                      reg = <0x01c200cc 0x4>;
++              };
++
++              ehci0: ehci0@0x01c14000 {
++                      compatible = "allwinner,sunxi-ehci";
++                      reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
++                      interrupts = <39>;
++                      resets = <&usb_rst 1>;
++                      reset-names = "ehci_reset";
++                      clocks = <&usb 8>, <&ahb_gates 1>;
++                      clock-names = "usb_phy", "ahb_ehci";
++                      status = "disabled";
++              };
++
++              ehci1: ehci1@0x01c1c000 {
++                      compatible = "allwinner,sunxi-ehci";
++                      reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>;
++                      interrupts = <40>;
++                      resets = <&usb_rst 2>;
++                      reset-names = "ehci_reset";
++                      clocks = <&usb 8>, <&ahb_gates 3>;
++                      clock-names = "usb_phy", "ahb_ehci";
++                      status = "disabled";
++              };
+       };
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/153-add-sunxi-ehci.patch b/target/linux/sunxi/patches-3.12/153-add-sunxi-ehci.patch
new file mode 100644 (file)
index 0000000..8a78c2d
--- /dev/null
@@ -0,0 +1,499 @@
+From b84d49247eb062672a56ce15f1c08f792099de97 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Wed, 18 Sep 2013 21:45:03 +0200
+Subject: [PATCH] ARM: sunxi: usb: Add Allwinner sunXi EHCI driver
+
+---
+ drivers/usb/host/Kconfig      |   9 +
+ drivers/usb/host/Makefile     |   1 +
+ drivers/usb/host/ehci-sunxi.c | 446 ++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 456 insertions(+)
+ create mode 100644 drivers/usb/host/ehci-sunxi.c
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index b3f20d7..ecc2745 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -274,6 +274,15 @@ config USB_OCTEON_EHCI
+         USB 2.0 device support.  All CN6XXX based chips with USB are
+         supported.
++config USB_SUNXI_EHCI
++      tristate "Allwinner sunXi EHCI support"
++      depends on ARCH_SUNXI
++      default n
++      help
++        Enable support for the Allwinner sunXi on-chip EHCI
++        controller. It is needed for high-speed (480Mbit/sec)
++        USB 2.0 device support.
++
+ endif # USB_EHCI_HCD
+ config USB_OXU210HP_HCD
+diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
+index 50b0041..d2e2c8c 100644
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -38,6 +38,7 @@ obj-$(CONFIG_USB_EHCI_S5P)   += ehci-s5p.o
+ obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
+ obj-$(CONFIG_USB_EHCI_MSM)    += ehci-msm.o
+ obj-$(CONFIG_USB_EHCI_TEGRA)  += ehci-tegra.o
++obj-$(CONFIG_USB_SUNXI_EHCI)  += ehci-sunxi.o
+ obj-$(CONFIG_USB_OXU210HP_HCD)        += oxu210hp-hcd.o
+ obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
+diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c
+new file mode 100644
+index 0000000..e7e15cc
+--- /dev/null
++++ b/drivers/usb/host/ehci-sunxi.c
+@@ -0,0 +1,446 @@
++/*
++ * Copyright (C) 2013 Roman Byshko
++ *
++ * Roman Byshko <rbyshko@gmail.com>
++ *
++ * Based on code from
++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2.  This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#include <linux/bitops.h>
++#include <linux/clk.h>
++#include <linux/dma-mapping.h>
++#include <linux/io.h>
++#include <linux/irq.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/reset.h>
++#include <linux/usb.h>
++#include <linux/usb/hcd.h>
++
++#include "ehci.h"
++
++#define DRV_DESC      "Allwinner sunXi EHCI driver"
++#define DRV_NAME      "sunxi-ehci"
++
++#define SUNXI_USB_PASSBY_EN   1
++
++#define SUNXI_EHCI_AHB_ICHR8_EN               BIT(10)
++#define SUNXI_EHCI_AHB_INCR4_BURST_EN BIT(9)
++#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN BIT(8)
++#define SUNXI_EHCI_ULPI_BYPASS_EN     BIT(0)
++
++struct sunxi_ehci_hcd {
++      struct clk *phy_clk;
++      struct clk *ahb_ehci_clk;
++      struct reset_control *reset;
++      struct regulator *vbus_reg;
++      void __iomem *csr;
++      void __iomem *pmuirq;
++      int irq;
++      int id;
++};
++
++
++static void usb_phy_write(struct sunxi_ehci_hcd *sunxi_ehci,u32 addr, u32 data, u32 len)
++{
++      u32 j = 0;
++      u32 temp = 0;
++      u32 usbc_bit = 0;
++      void __iomem *dest = sunxi_ehci->csr;
++
++      usbc_bit = BIT(sunxi_ehci->id << 1);
++
++      for (j = 0; j < len; j++) {
++              temp = readl(dest);
++
++              /* clear the address portion */
++              temp &= ~(0xff << 8);
++
++              /* set the address */
++              temp |= ((addr + j) << 8);
++              writel(temp, dest);
++
++              /* set the data bit and clear usbc bit*/
++              temp = readb(dest);
++              if (data & 0x1)
++                      temp |= BIT(7);
++              else
++                      temp &= ~BIT(7);
++              temp &= ~usbc_bit;
++              writeb(temp, dest);
++
++              /* flip usbc_bit */
++              __set_bit(usbc_bit, dest);
++              __clear_bit(usbc_bit, dest);
++
++              data >>= 1;
++      }
++}
++
++/* FIXME: should this function be protected by a lock?
++ * ehci1 and ehci0 could call it concurrently with same csr.
++ */
++static void sunxi_usb_phy_init(struct sunxi_ehci_hcd *sunxi_ehci)
++{
++      /* The following comments are machine
++       * translated from Chinese, you have been warned!
++       */
++
++      /* adjust PHY's magnitude and rate */
++      usb_phy_write(sunxi_ehci, 0x20, 0x14, 5);
++
++      /* threshold adjustment disconnect */
++      usb_phy_write(sunxi_ehci, 0x2a, 3, 2);
++
++      return;
++}
++
++static void sunxi_usb_passby(struct sunxi_ehci_hcd *sunxi_ehci, int enable)
++{
++      unsigned long reg_value = 0;
++      unsigned long bits = 0;
++      static DEFINE_SPINLOCK(lock);
++      unsigned long flags = 0;
++      void __iomem *addr = sunxi_ehci->pmuirq;
++
++      bits = SUNXI_EHCI_AHB_ICHR8_EN |
++              SUNXI_EHCI_AHB_INCR4_BURST_EN |
++              SUNXI_EHCI_AHB_INCRX_ALIGN_EN |
++              SUNXI_EHCI_ULPI_BYPASS_EN;
++
++      spin_lock_irqsave(&lock, flags);
++
++      reg_value = readl(addr);
++
++      if (enable)
++              reg_value |= bits;
++      else
++              reg_value &= ~bits;
++
++      writel(reg_value, addr);
++
++      spin_unlock_irqrestore(&lock, flags);
++
++      return;
++}
++
++static void sunxi_ehci_disable(struct sunxi_ehci_hcd *sunxi_ehci)
++{
++      regulator_disable(sunxi_ehci->vbus_reg);
++
++      sunxi_usb_passby(sunxi_ehci, !SUNXI_USB_PASSBY_EN);
++
++      clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk);
++      clk_disable_unprepare(sunxi_ehci->phy_clk);
++
++      reset_control_assert(sunxi_ehci->reset);
++}
++
++static int sunxi_ehci_enable(struct sunxi_ehci_hcd *sunxi_ehci)
++{
++      int ret;
++
++      ret = clk_prepare_enable(sunxi_ehci->phy_clk);
++      if (ret)
++              return ret;
++
++      ret = reset_control_deassert(sunxi_ehci->reset);
++      if (ret)
++              goto fail1;
++
++      ret = clk_prepare_enable(sunxi_ehci->ahb_ehci_clk);
++      if (ret)
++              goto fail2;
++
++      sunxi_usb_phy_init(sunxi_ehci);
++
++      sunxi_usb_passby(sunxi_ehci, SUNXI_USB_PASSBY_EN);
++
++      ret = regulator_enable(sunxi_ehci->vbus_reg);
++      if (ret)
++              goto fail3;
++
++      return 0;
++
++fail3:
++      clk_disable_unprepare(sunxi_ehci->ahb_ehci_clk);
++fail2:
++      reset_control_assert(sunxi_ehci->reset);
++fail1:
++      clk_disable_unprepare(sunxi_ehci->phy_clk);
++
++      return ret;
++}
++
++#ifdef CONFIG_PM
++static int sunxi_ehci_suspend(struct device *dev)
++{
++      struct sunxi_ehci_hcd *sunxi_ehci = NULL;
++      struct usb_hcd *hcd = dev_get_drvdata(dev);
++      int ret;
++
++      bool do_wakeup = device_may_wakeup(dev);
++
++      ret = ehci_suspend(hcd, do_wakeup);
++
++      sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
++
++      sunxi_ehci_disable(sunxi_ehci);
++
++      return ret;
++}
++
++static int sunxi_ehci_resume(struct device *dev)
++{
++      struct sunxi_ehci_hcd *sunxi_ehci = NULL;
++      struct usb_hcd *hcd = dev_get_drvdata(dev);
++      int ret;
++
++      sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
++
++      ret = sunxi_ehci_enable(sunxi_ehci);
++      if (ret)
++              return ret;
++
++      return ehci_resume(hcd, false);
++}
++
++
++static const struct dev_pm_ops sunxi_ehci_pmops = {
++      .suspend        = sunxi_ehci_suspend,
++      .resume         = sunxi_ehci_resume,
++};
++
++#define SUNXI_EHCI_PMOPS (&sunxi_ehci_pmops)
++#else /* !CONFIG_PM */
++#define SUNXI_EHCI_PMOPS NULL
++#endif /* CONFIG_PM */
++
++static const struct ehci_driver_overrides sunxi_overrides __initconst = {
++      .reset =        NULL,
++      .extra_priv_size        = sizeof(struct sunxi_ehci_hcd),
++};
++
++/* FIXME: Should there be two instances of hc_driver,
++ * or one is enough to handle two EHCI controllers? */
++static struct hc_driver __read_mostly sunxi_ehci_hc_driver;
++
++static int sunxi_ehci_init(struct platform_device *pdev, struct usb_hcd *hcd,
++                         struct sunxi_ehci_hcd *sunxi_ehci)
++{
++      void __iomem *ehci_regs = NULL;
++      struct resource *res = NULL;
++
++      sunxi_ehci->vbus_reg = devm_regulator_get(&pdev->dev, "vbus");
++      if (IS_ERR(sunxi_ehci->vbus_reg)) {
++              if (PTR_ERR(sunxi_ehci->vbus_reg) == -EPROBE_DEFER)
++                      return -EPROBE_DEFER;
++
++              dev_info(&pdev->dev, "no USB VBUS power supply found\n");
++      }
++
++      sunxi_ehci->id = of_alias_get_id(pdev->dev.of_node, "ehci");
++      if (sunxi_ehci->id < 0)
++              return sunxi_ehci->id;
++
++      /* FIXME: should res be freed on some failure? */
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!res) {
++              dev_err(&pdev->dev, "failed to get I/O memory\n");
++              return -ENXIO;
++      }
++      ehci_regs = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(ehci_regs))
++              return PTR_ERR(ehci_regs);
++
++      hcd->rsrc_start = res->start;
++      hcd->rsrc_len = resource_size(res);
++      hcd->regs = ehci_regs;
++      hcd_to_ehci(hcd)->caps = ehci_regs;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++      if (!res) {
++              dev_err(&pdev->dev, "failed to get I/O memory\n");
++              return -ENXIO;
++      }
++      sunxi_ehci->pmuirq = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(sunxi_ehci->pmuirq))
++              return PTR_ERR(sunxi_ehci->pmuirq);
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
++      if (!res) {
++              dev_err(&pdev->dev, "failed to get I/O memory\n");
++              return -ENXIO;
++      }
++
++      /* FIXME: this one byte needs to be shared between both EHCIs,
++       * that is why ioremap instead of devm_ioremap_resource,
++       * memory is not unmaped back for now.
++       */
++      sunxi_ehci->csr = ioremap(res->start, resource_size(res));
++      if (IS_ERR(sunxi_ehci->csr)) {
++              dev_err(&pdev->dev, "failed to remap memory\n");
++              return PTR_ERR(sunxi_ehci->csr);
++      }
++
++      sunxi_ehci->irq = platform_get_irq(pdev, 0);
++      if (!sunxi_ehci->irq) {
++              dev_err(&pdev->dev, "failed to get IRQ\n");
++              return -ENODEV;
++      }
++
++      sunxi_ehci->phy_clk = devm_clk_get(&pdev->dev, "usb_phy");
++      if (IS_ERR(sunxi_ehci->phy_clk)) {
++              dev_err(&pdev->dev, "failed to get usb_phy clock\n");
++              return PTR_ERR(sunxi_ehci->phy_clk);
++      }
++      sunxi_ehci->ahb_ehci_clk = devm_clk_get(&pdev->dev, "ahb_ehci");
++      if (IS_ERR(sunxi_ehci->ahb_ehci_clk)) {
++              dev_err(&pdev->dev, "failed to get ahb_ehci clock\n");
++              return PTR_ERR(sunxi_ehci->ahb_ehci_clk);
++      }
++
++      sunxi_ehci->reset = reset_control_get(&pdev->dev, "ehci_reset");
++      if (IS_ERR(sunxi_ehci->reset))
++      {
++              dev_err(&pdev->dev, "failed to get ehci_reset reset line\n");
++              return PTR_ERR(sunxi_ehci->reset);
++      }
++
++      return 0;
++}
++
++static int sunxi_ehci_probe(struct platform_device *pdev)
++{
++      struct sunxi_ehci_hcd *sunxi_ehci = NULL;
++      struct usb_hcd *hcd = NULL;
++      int ret;
++
++      if (pdev->num_resources != 4) {
++              dev_err(&pdev->dev, "invalid number of resources: %i\n",
++                     pdev->num_resources);
++              return -ENODEV;
++      }
++
++      if (pdev->resource[0].flags != IORESOURCE_MEM
++                      || pdev->resource[1].flags != IORESOURCE_MEM
++                      || pdev->resource[2].flags != IORESOURCE_MEM
++                      || pdev->resource[3].flags != IORESOURCE_IRQ) {
++              dev_err(&pdev->dev, "invalid resource type\n");
++              return -ENODEV;
++      }
++
++      if (!pdev->dev.dma_mask)
++              pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
++      if (!pdev->dev.coherent_dma_mask)
++              pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
++
++      hcd = usb_create_hcd(&sunxi_ehci_hc_driver, &pdev->dev,
++                           dev_name(&pdev->dev));
++      if (!hcd) {
++              dev_err(&pdev->dev, "unable to create HCD\n");
++              return -ENOMEM;
++      }
++
++      platform_set_drvdata(pdev, hcd);
++
++      sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
++      ret = sunxi_ehci_init(pdev, hcd, sunxi_ehci);
++      if (ret)
++              goto fail1;
++
++      ret = sunxi_ehci_enable(sunxi_ehci);
++      if (ret)
++              goto fail1;
++
++      ret = usb_add_hcd(hcd, sunxi_ehci->irq, IRQF_SHARED | IRQF_DISABLED);
++      if (ret) {
++              dev_err(&pdev->dev, "failed to add USB HCD\n");
++              goto fail2;
++      }
++
++      return 0;
++
++fail2:
++      sunxi_ehci_disable(sunxi_ehci);
++
++fail1:
++      usb_put_hcd(hcd);
++      return ret;
++}
++
++static int sunxi_ehci_remove(struct platform_device *pdev)
++{
++      struct usb_hcd *hcd = platform_get_drvdata(pdev);
++      struct sunxi_ehci_hcd *sunxi_ehci = NULL;
++
++      sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
++
++      usb_remove_hcd(hcd);
++
++      sunxi_ehci_disable(sunxi_ehci);
++
++      usb_put_hcd(hcd);
++
++      return 0;
++}
++
++static void sunxi_ehci_shutdown(struct platform_device *pdev)
++{
++      struct usb_hcd *hcd = platform_get_drvdata(pdev);
++      struct sunxi_ehci_hcd *sunxi_ehci = NULL;
++
++      sunxi_ehci = (struct sunxi_ehci_hcd *)hcd_to_ehci(hcd)->priv;
++
++      usb_hcd_platform_shutdown(pdev);
++
++      sunxi_ehci_disable(sunxi_ehci);
++}
++
++static const struct of_device_id ehci_of_match[] = {
++      {.compatible = "allwinner,sunxi-ehci"},
++      {},
++};
++
++static struct platform_driver ehci_sunxi_driver = {
++      .driver = {
++              .of_match_table = ehci_of_match,
++              .name = DRV_NAME,
++              .pm = SUNXI_EHCI_PMOPS,
++      },
++      .probe = sunxi_ehci_probe,
++      .remove = sunxi_ehci_remove,
++      .shutdown = sunxi_ehci_shutdown,
++};
++
++static int __init sunxi_ehci_init_module(void)
++{
++      if (usb_disabled())
++              return -ENODEV;
++
++      pr_info(DRV_NAME ": " DRV_DESC "\n");
++
++      ehci_init_driver(&sunxi_ehci_hc_driver, &sunxi_overrides);
++
++      return platform_driver_register(&ehci_sunxi_driver);
++}
++module_init(sunxi_ehci_init_module);
++
++static void __exit sunxi_ehci_exit_module(void)
++{
++      platform_driver_unregister(&ehci_sunxi_driver);
++}
++module_exit(sunxi_ehci_exit_module);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:" DRV_NAME);
++MODULE_DEVICE_TABLE(of, ehci_of_match);
++MODULE_AUTHOR("Roman Byshko <rbyshko@gmail.com>");
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/154-add-ehci-for-a1000.patch b/target/linux/sunxi/patches-3.12/154-add-ehci-for-a1000.patch
new file mode 100644 (file)
index 0000000..dee5b1b
--- /dev/null
@@ -0,0 +1,82 @@
+From bc8138b4218307a8f25076ec5c8c1eae1e5e8d78 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Wed, 18 Sep 2013 00:30:40 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to the Mele A1000
+
+---
+ arch/arm/boot/dts/sun4i-a10-a1000.dts | 46 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 46 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+index eb4d73b..68c705d 100644
+--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
+@@ -53,6 +53,20 @@
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
++
++                      usb1_vbus_pin: usb1_vbus_pin@0 {
++                                      allwinner,pins = "PH6";
++                                      allwinner,function = "gpio_out";
++                                      allwinner,drive = <0>;
++                                      allwinner,pull = <2>;
++                      };
++
++                      usb2_vbus_pin: usb2_vbus_pin@0 {
++                                      allwinner,pins = "PH3";
++                                      allwinner,function = "gpio_out";
++                                      allwinner,drive = <0>;
++                                      allwinner,pull = <2>;
++                      };
+               };
+               uart0: serial@01c28000 {
+@@ -66,6 +80,16 @@
+                       pinctrl-0 = <&i2c0_pins_a>;
+                       status = "okay";
+               };
++
++              ehci0: ehci0@0x01c14000 {
++                      vbus-supply = <&reg_usb1_vbus>;
++                      status = "okay";
++              };
++
++              ehci1: ehci1@0x01c1c000 {
++                      vbus-supply = <&reg_usb2_vbus>;
++                      status = "okay";
++              };
+       };
+       leds {
+@@ -97,5 +121,27 @@
+                       enable-active-high;
+                       gpio = <&pio 7 15 0>;
+               };
++
++              reg_usb1_vbus: usb1-vbus {
++                      compatible = "regulator-fixed";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&usb1_vbus_pin>;
++                      regulator-name = "usb1-vbus";
++                      regulator-min-microvolt = <3300000>;
++                      regulator-max-microvolt = <3300000>;
++                      enable-active-high;
++                      gpio = <&pio 7 6 0>;
++              };
++
++              reg_usb2_vbus: usb2-vbus {
++                      compatible = "regulator-fixed";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&usb2_vbus_pin>;
++                      regulator-name = "usb2-vbus";
++                      regulator-min-microvolt = <3300000>;
++                      regulator-max-microvolt = <3300000>;
++                      enable-active-high;
++                      gpio = <&pio 7 3 0>;
++              };
+       };
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/155-add-ehci-for-cubieboard-a10.patch b/target/linux/sunxi/patches-3.12/155-add-ehci-for-cubieboard-a10.patch
new file mode 100644 (file)
index 0000000..2cb98ae
--- /dev/null
@@ -0,0 +1,85 @@
+From bf96cf461ca2d36e962a4acf83f6f779a05c7df3 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Wed, 18 Sep 2013 22:45:06 +0200
+Subject: [PATCH] ARM: sun4i: dt: Add EHCI bindings to Cubieboard-A10
+
+---
+ arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 50 ++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+index 425a7db..eb6c3c1 100644
+--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+@@ -49,6 +49,20 @@
+                               allwinner,drive = <1>;
+                               allwinner,pull = <0>;
+                       };
++
++                      usb1_vbus_pin: usb1_vbus_pin@0 {
++                                      allwinner,pins = "PH6";
++                                      allwinner,function = "gpio_out";
++                                      allwinner,drive = <0>;
++                                      allwinner,pull = <2>;
++                      };
++
++                      usb2_vbus_pin: usb2_vbus_pin@0 {
++                                      allwinner,pins = "PH3";
++                                      allwinner,function = "gpio_out";
++                                      allwinner,drive = <0>;
++                                      allwinner,pull = <2>;
++                      };
+               };
+               uart0: serial@01c28000 {
+@@ -68,6 +82,16 @@
+                       pinctrl-0 = <&i2c1_pins_a>;
+                       status = "okay";
+               };
++
++              ehci0: ehci0@0x01c14000 {
++                              vbus-supply = <&reg_usb1_vbus>;
++                              status = "okay";
++              };
++
++              ehci1: ehci1@0x01c1c000 {
++                              vbus-supply = <&reg_usb2_vbus>;
++                              status = "okay";
++              };
+       };
+       leds {
+@@ -86,4 +110,30 @@
+                       linux,default-trigger = "heartbeat";
+               };
+       };
++
++      regulators {
++              compatible = "simple-bus";
++
++              reg_usb1_vbus: usb1-vbus {
++                      compatible = "regulator-fixed";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&usb1_vbus_pin>;
++                      regulator-name = "usb1-vbus";
++                      regulator-min-microvolt = <3300000>;
++                      regulator-max-microvolt = <3300000>;
++                      enable-active-high;
++                      gpio = <&pio 7 6 0>;
++              };
++
++              reg_usb2_vbus: usb2-vbus {
++                      compatible = "regulator-fixed";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&usb2_vbus_pin>;
++                      regulator-name = "usb2-vbus";
++                      regulator-min-microvolt = <3300000>;
++                      regulator-max-microvolt = <3300000>;
++                      enable-active-high;
++                      gpio = <&pio 7 3 0>;
++              };
++      };
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/156-sun7i-add-dt-bindings-for-usbclocks.patch b/target/linux/sunxi/patches-3.12/156-sun7i-add-dt-bindings-for-usbclocks.patch
new file mode 100644 (file)
index 0000000..5dfbc5e
--- /dev/null
@@ -0,0 +1,31 @@
+From 336d23a348d6595cac9a282616e983dddb7c7600 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Thu, 19 Sep 2013 21:24:20 +0200
+Subject: [PATCH] ARM: sun7i: dt: Add bindings for USB clocks
+
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 81e6e74..4fe484c 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -85,6 +85,14 @@
+                       clock-output-names = "pll6_sata", "pll6_other", "pll6";
+               };
++              usb:usb@0x01c200cc {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun47i-usb-gates-clk";
++                      reg = <0x01c200cc 0x4>;
++                      clocks = <&pll6 1>;
++                      clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy";
++              };
++
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-cpu-clk";
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/157-sun7i-add-dt-usb-ehci-bindings.patch b/target/linux/sunxi/patches-3.12/157-sun7i-add-dt-usb-ehci-bindings.patch
new file mode 100644 (file)
index 0000000..db7905f
--- /dev/null
@@ -0,0 +1,62 @@
+From b434c5aa38e2db0fff9fa39c6e47cc9d13afe8e1 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Thu, 19 Sep 2013 21:36:10 +0200
+Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings
+
+---
+ arch/arm/boot/dts/sun7i-a20.dtsi | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index 4fe484c..b4e4a5a 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -16,6 +16,11 @@
+ / {
+       interrupt-parent = <&gic>;
++      aliases {
++              ehci1 = &ehci0;
++              ehci2 = &ehci1;
++      };
++
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+@@ -434,5 +439,33 @@
+                       #interrupt-cells = <3>;
+                       interrupts = <1 9 0xf04>;
+               };
++
++              usb_rst: reset@0x01c200cc {
++                      #reset-cells = <1>;
++                      compatible = "allwinner,sun4i-clock-reset";
++                      reg = <0x01c200cc 0x4>;
++              };
++
++              ehci0: ehci0@0x01c14000 {
++                      compatible = "allwinner,sunxi-ehci";
++                      reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
++                      interrupts = <0 39 1>;
++                      resets = <&usb_rst 1>;
++                      reset-names = "ehci_reset";
++                      clocks = <&usb 8>, <&ahb_gates 1>;
++                      clock-names = "usb_phy", "ahb_ehci";
++                      status = "disabled";
++              };
++
++              ehci1: ehci1@0x01c1c000 {
++                      compatible = "allwinner,sunxi-ehci";
++                      reg = <0x01c1c000 0x400 0x01c1c800 0x4 0x01c13404 0x4>;
++                      interrupts = <0 40 1>;
++                      resets = <&usb_rst 2>;
++                      reset-names = "ehci_reset";
++                      clocks = <&usb 8>, <&ahb_gates 3>;
++                      clock-names = "usb_phy", "ahb_ehci";
++                      status = "disabled";
++              };
+       };
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/158-sun5i-add-dt-bindings-for-usbclocks.patch b/target/linux/sunxi/patches-3.12/158-sun5i-add-dt-bindings-for-usbclocks.patch
new file mode 100644 (file)
index 0000000..a8dd56e
--- /dev/null
@@ -0,0 +1,31 @@
+From f4eb27ab7c9893a65fd414451459899cdd6334a7 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Tue, 24 Sep 2013 20:02:39 +0200
+Subject: [PATCH] ARM: sun5i: dt: Add bindings for USB Host clocks
+
+---
+ arch/arm/boot/dts/sun5i-a13.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index 9ac706a..aad270c 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -90,6 +90,14 @@
+                       clock-output-names = "pll6_sata", "pll6_other", "pll6";
+               };
++              usb:usb@0x01c200cc {
++                      #clock-cells = <1>;
++                      compatible = "allwinner,sun5i-usb-gates-clk";
++                      reg = <0x01c200cc 0x4>;
++                      clocks = <&pll6 1>;
++                      clock-output-names = "usb_ohci0", "usb_phy";
++              };
++
+               /* dummy is 200M */
+               cpu: cpu@01c20054 {
+                       #clock-cells = <0>;
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/159-sun5i-add-support-for-usbclocks.patch b/target/linux/sunxi/patches-3.12/159-sun5i-add-support-for-usbclocks.patch
new file mode 100644 (file)
index 0000000..c9445a2
--- /dev/null
@@ -0,0 +1,35 @@
+From aaf8700dfa1b19bbb994e2996bd293190c0cefbd Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Sun, 6 Oct 2013 14:04:50 +0200
+Subject: [PATCH] clk: sun5i: Add support for USB clocks
+
+---
+ drivers/clk/sunxi/clk-sunxi.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
+index cbe1516..f9b8b18 100644
+--- a/drivers/clk/sunxi/clk-sunxi.c
++++ b/drivers/clk/sunxi/clk-sunxi.c
+@@ -623,6 +623,10 @@ struct gates_data {
+       .mask = {0x1C0},
+ };
++static const struct gates_data sun5i_usb_gates_data __initconst = {
++       .mask = {0x140},
++};
++
+ static const struct gates_data sun5i_a10s_ahb_gates_data __initconst = {
+       .mask = {0x147667e7, 0x185915},
+ };
+@@ -874,6 +878,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
+       {.compatible = "allwinner,sun47i-usb-gates-clk", .data = &sun47i_usb_gates_data,},
+       {.compatible = "allwinner,sun5i-a10s-ahb-gates-clk", .data = &sun5i_a10s_ahb_gates_data,},
+       {.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
++      {.compatible = "allwinner,sun5i-usb-gates-clk", .data = &sun5i_usb_gates_data,},
+       {.compatible = "allwinner,sun6i-a31-ahb1-gates-clk", .data = &sun6i_a31_ahb1_gates_data,},
+       {.compatible = "allwinner,sun7i-a20-ahb-gates-clk", .data = &sun7i_a20_ahb_gates_data,},
+       {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/160-sun5i-dt-add-usb-ehci-bindings.patch b/target/linux/sunxi/patches-3.12/160-sun5i-dt-add-usb-ehci-bindings.patch
new file mode 100644 (file)
index 0000000..70e54d5
--- /dev/null
@@ -0,0 +1,50 @@
+From d3f751a7afe959d53c2b9e71a25921aeb38e0837 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Tue, 24 Sep 2013 20:03:40 +0200
+Subject: [PATCH] ARM: sun5i: dt: Add USB EHCI bindings
+
+---
+ arch/arm/boot/dts/sun5i-a13.dtsi | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index aad270c..a271a2d 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -16,6 +16,10 @@
+ / {
+       interrupt-parent = <&intc>;
++      aliases {
++              ehci1 = &ehci0;
++      };
++
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+@@ -310,5 +314,22 @@
+                       interrupts = <82>, <83>;
+                       clocks = <&ahb_gates 28>;
+               };
++
++              usb_rst: reset@0x01c200cc {
++                      #reset-cells = <1>;
++                      compatible = "allwinner,sun4i-clock-reset";
++                      reg = <0x01c200cc 0x4>;
++              };
++
++              ehci0: ehci0@0x01c14000 {
++                      compatible = "allwinner,sunxi-ehci";
++                      reg = <0x01c14000 0x400 0x01c14800 0x4 0x01c13404 0x4>;
++                      interrupts = <39>;
++                      resets = <&usb_rst 1>;
++                      reset-names = "ehci_reset";
++                      clocks = <&usb 8>, <&ahb_gates 1>;
++                      clock-names = "usb_phy", "ahb_ehci";
++                      status = "disabled";
++              };
+       };
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/161-sun5i-add-dt-ehci-for-a13-olinuxino.patch b/target/linux/sunxi/patches-3.12/161-sun5i-add-dt-ehci-for-a13-olinuxino.patch
new file mode 100644 (file)
index 0000000..362d85b
--- /dev/null
@@ -0,0 +1,62 @@
+From 0944583d288e594d10ed0015b3d45839c70f8931 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Tue, 24 Sep 2013 20:07:53 +0200
+Subject: [PATCH] ARM: sun5i: dt: Add EHCI bindings to A13-Olinuxino
+
+---
+ arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+index 9e508dc..e30b89f 100644
+--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
++++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+@@ -30,6 +30,13 @@
+                               allwinner,drive = <1>;
+                               allwinner,pull = <0>;
+                       };
++
++                      usb1_vbus_pin: usb1_vbus_pin@0 {
++                              allwinner,pins = "PG11";
++                              allwinner,function = "gpio_out";
++                              allwinner,drive = <0>;
++                              allwinner,pull = <2>;
++                      };
+               };
+               uart1: serial@01c28400 {
+@@ -55,6 +62,11 @@
+                       pinctrl-0 = <&i2c2_pins_a>;
+                       status = "okay";
+               };
++
++              ehci0: ehci0@0x01c14000 {
++                      vbus-supply = <&reg_usb1_vbus>;
++                      status = "okay";
++              };
+       };
+       leds {
+@@ -67,4 +79,19 @@
+                       default-state = "on";
+               };
+       };
++
++      regulators {
++              compatible = "simple-bus";
++
++              reg_usb1_vbus: usb1-vbus {
++                      compatible = "regulator-fixed";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&usb1_vbus_pin>;
++                      regulator-name = "usb1-vbus";
++                      regulator-min-microvolt = <3300000>;
++                      regulator-max-microvolt = <3300000>;
++                      enable-active-high;
++                      gpio = <&pio 6 11 0>;
++              };
++      };
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/162-add-dt-ehci-for-a20-olinuxino.patch b/target/linux/sunxi/patches-3.12/162-add-dt-ehci-for-a20-olinuxino.patch
new file mode 100644 (file)
index 0000000..40706d2
--- /dev/null
@@ -0,0 +1,84 @@
+From 630ccdf33652f8e35b8c84e939d5a86fad9612e2 Mon Sep 17 00:00:00 2001
+From: arokux <arokux@gmail.com>
+Date: Thu, 19 Sep 2013 21:50:21 +0200
+Subject: [PATCH] ARM: sun7i: dt: Add USB EHCI bindings for A20-Olinuxino
+
+---
+ arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 49 +++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+index ead3013..e6b1e26 100644
+--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+@@ -41,6 +41,20 @@
+                               allwinner,drive = <1>;
+                               allwinner,pull = <0>;
+                       };
++
++                      usb1_vbus_pin: usb1_vbus_pin@0 {
++                                      allwinner,pins = "PH6";
++                                      allwinner,function = "gpio_out";
++                                      allwinner,drive = <0>;
++                                      allwinner,pull = <2>;
++                      };
++
++                      usb2_vbus_pin: usb2_vbus_pin@0 {
++                                      allwinner,pins = "PH3";
++                                      allwinner,function = "gpio_out";
++                                      allwinner,drive = <0>;
++                                      allwinner,pull = <2>;
++                      };
+               };
+               uart0: serial@01c28000 {
+@@ -76,6 +90,15 @@
+               i2c2: i2c@01c2b400 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c2_pins_a>;
++              };
++
++              ehci0: ehci0@0x01c14000 {
++                      vbus-supply = <&reg_usb1_vbus>;
++                      status = "okay";
++              };
++
++              ehci1: ehci1@0x01c1c000 {
++                      vbus-supply = <&reg_usb2_vbus>;
+                       status = "okay";
+               };
+       };
+@@ -91,4 +114,30 @@
+                       default-state = "on";
+               };
+       };
++
++      regulators {
++              compatible = "simple-bus";
++
++              reg_usb1_vbus: usb1-vbus {
++                      compatible = "regulator-fixed";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&usb1_vbus_pin>;
++                      regulator-name = "usb1-vbus";
++                      regulator-min-microvolt = <3300000>;
++                      regulator-max-microvolt = <3300000>;
++                      enable-active-high;
++                      gpio = <&pio 7 6 0>;
++              };
++
++              reg_usb2_vbus: usb2-vbus {
++                      compatible = "regulator-fixed";
++                      pinctrl-names = "default";
++                      pinctrl-0 = <&usb2_vbus_pin>;
++                      regulator-name = "usb2-vbus";
++                      regulator-min-microvolt = <3300000>;
++                      regulator-max-microvolt = <3300000>;
++                      enable-active-high;
++                      gpio = <&pio 7 3 0>;
++              };
++      };
+ };
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/170-sunxi-sid-initial.patch b/target/linux/sunxi/patches-3.12/170-sunxi-sid-initial.patch
new file mode 100644 (file)
index 0000000..8407b2f
--- /dev/null
@@ -0,0 +1,290 @@
+From 1d4b3ab562fa87e2c7f05cf92af1ff4b6cd42581 Mon Sep 17 00:00:00 2001
+From: Oliver Schinagl <oliver@schinagl.nl>
+Date: Tue, 3 Sep 2013 12:33:27 +0200
+Subject: [PATCH] ARM: sunxi: Initial support for Allwinner's Security ID fuses
+
+Allwinner has electric fuses (efuse) on their line of chips. This driver
+reads those fuses, seeds the kernel entropy and exports them as a sysfs
+node.
+
+These fuses are most likely to be programmed at the factory, encoding
+things like Chip ID, some sort of serial number, etc. and appear to be
+reasonably unique.
+While in theory, these should be writeable by the user, it will probably
+be inconvenient to do so. Allwinner recommends that a certain input pin,
+labeled 'efuse_vddq', be connected to GND. To write these fuses however,
+a 2.5 V programming voltage needs to be applied to this pin.
+
+Even so, they can still be used to generate a board-unique mac from,
+board unique RSA key and seed the kernel RNG.
+
+On sun7i additional storage is available, this is initially used for an
+UEFI BOOT key, Secure JTAG key, HDMI-HDCP key and vendor specific keys.
+
+Currently supported are the following known chips:
+Allwinner sun4i (A10)
+Allwinner sun5i (A10s, A13)
+Allwinner sun7i (A20)
+
+Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
+---
+ Documentation/ABI/testing/sysfs-driver-sunxi-sid   |  22 +++
+ .../bindings/misc/allwinner,sunxi-sid.txt          |  17 +++
+ drivers/misc/eeprom/Kconfig                        |  13 ++
+ drivers/misc/eeprom/Makefile                       |   1 +
+ drivers/misc/eeprom/sunxi_sid.c                    | 158 +++++++++++++++++++++
+ 5 files changed, 211 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-driver-sunxi-sid
+ create mode 100644 Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+ create mode 100644 drivers/misc/eeprom/sunxi_sid.c
+
+diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
+new file mode 100644
+index 0000000..ffb9536
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
+@@ -0,0 +1,22 @@
++What:         /sys/devices/*/<our-device>/eeprom
++Date:         August 2013
++Contact:      Oliver Schinagl <oliver@schinagl.nl>
++Description:  read-only access to the SID (Security-ID) on current
++              A-series SoC's from Allwinner. Currently supports A10, A10s, A13
++              and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
++              whereas the newer A20 SoC exposes 512 bytes split into sections.
++              Besides the 16 bytes of SID, there's also an SJTAG area,
++              HDMI-HDCP key and some custom keys. Below a quick overview, for
++              details see the user manual:
++              0x000  128 bit root-key (sun[457]i)
++              0x010  128 bit boot-key (sun7i)
++              0x020   64 bit security-jtag-key (sun7i)
++              0x028   16 bit key configuration (sun7i)
++              0x02b   16 bit custom-vendor-key (sun7i)
++              0x02c  320 bit low general key (sun7i)
++              0x040   32 bit read-control access (sun7i)
++              0x064  224 bit low general key (sun7i)
++              0x080 2304 bit HDCP-key (sun7i)
++              0x1a0  768 bit high general key (sun7i)
++Users:                any user space application which wants to read the SID on
++              Allwinner's A-series of CPU's.
+diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+new file mode 100644
+index 0000000..68ba372
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+@@ -0,0 +1,17 @@
++Allwinner sunxi-sid
++
++Required properties:
++- compatible: "allwinner,sun4i-sid" or "allwinner,sun7i-a20-sid".
++- reg: Should contain registers location and length
++
++Example for sun4i:
++      sid@01c23800 {
++              compatible = "allwinner,sun4i-sid";
++              reg = <0x01c23800 0x10>
++      };
++
++Example for sun7i:
++      sid@01c23800 {
++              compatible = "allwinner,sun7i-a20-sid";
++              reg = <0x01c23800 0x200>
++      };
+diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
+index 04f2e1f..9536852f 100644
+--- a/drivers/misc/eeprom/Kconfig
++++ b/drivers/misc/eeprom/Kconfig
+@@ -96,4 +96,17 @@ config EEPROM_DIGSY_MTC_CFG
+         If unsure, say N.
++config EEPROM_SUNXI_SID
++      tristate "Allwinner sunxi security ID support"
++      depends on ARCH_SUNXI && SYSFS
++      help
++        This is a driver for the 'security ID' available on various Allwinner
++        devices.
++
++        Due to the potential risks involved with changing e-fuses,
++        this driver is read-only.
++
++        This driver can also be built as a module. If so, the module
++        will be called sunxi_sid.
++
+ endmenu
+diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
+index fc1e81d..9507aec 100644
+--- a/drivers/misc/eeprom/Makefile
++++ b/drivers/misc/eeprom/Makefile
+@@ -4,4 +4,5 @@ obj-$(CONFIG_EEPROM_LEGACY)    += eeprom.o
+ obj-$(CONFIG_EEPROM_MAX6875)  += max6875.o
+ obj-$(CONFIG_EEPROM_93CX6)    += eeprom_93cx6.o
+ obj-$(CONFIG_EEPROM_93XX46)   += eeprom_93xx46.o
++obj-$(CONFIG_EEPROM_SUNXI_SID)        += sunxi_sid.o
+ obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
+diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
+new file mode 100644
+index 0000000..9c34e57
+--- /dev/null
++++ b/drivers/misc/eeprom/sunxi_sid.c
+@@ -0,0 +1,158 @@
++/*
++ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
++ * http://www.linux-sunxi.org
++ *
++ * 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.
++ *
++ * This driver exposes the Allwinner security ID, efuses exported in byte-
++ * sized chunks.
++ */
++
++#include <linux/compiler.h>
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/export.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/kobject.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/random.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/sysfs.h>
++#include <linux/types.h>
++
++#define DRV_NAME "sunxi-sid"
++
++struct sunxi_sid_data {
++      void __iomem *reg_base;
++      unsigned int keysize;
++};
++
++/* We read the entire key, due to a 32 bit read alignment requirement. Since we
++ * want to return the requested byte, this results in somewhat slower code and
++ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
++ * only very rarely probed, this is not really an issue.
++ */
++static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
++                            const unsigned int offset)
++{
++      u32 sid_key;
++
++      if (offset >= sid_data->keysize)
++              return 0;
++
++      sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
++      sid_key >>= (offset % 4) * 8;
++
++      return sid_key; /* Only return the last byte */
++}
++
++static ssize_t sid_read(struct file *fd, struct kobject *kobj,
++                      struct bin_attribute *attr, char *buf,
++                      loff_t pos, size_t size)
++{
++      struct platform_device *pdev;
++      struct sunxi_sid_data *sid_data;
++      int i;
++
++      pdev = to_platform_device(kobj_to_dev(kobj));
++      sid_data = platform_get_drvdata(pdev);
++
++      if (pos < 0 || pos >= sid_data->keysize)
++              return 0;
++      if (size > sid_data->keysize - pos)
++              size = sid_data->keysize - pos;
++
++      for (i = 0; i < size; i++)
++              buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
++
++      return i;
++}
++
++static struct bin_attribute sid_bin_attr = {
++      .attr = { .name = "eeprom", .mode = S_IRUGO, },
++      .read = sid_read,
++};
++
++static int sunxi_sid_remove(struct platform_device *pdev)
++{
++      device_remove_bin_file(&pdev->dev, &sid_bin_attr);
++      dev_dbg(&pdev->dev, "driver unloaded\n");
++
++      return 0;
++}
++
++static const struct of_device_id sunxi_sid_of_match[] = {
++      { .compatible = "allwinner,sun4i-sid", .data = (void *)16},
++      { .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
++      {/* sentinel */},
++};
++MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
++
++static int sunxi_sid_probe(struct platform_device *pdev)
++{
++      struct sunxi_sid_data *sid_data;
++      struct resource *res;
++      const struct of_device_id *of_dev_id;
++      u8 *entropy;
++      unsigned int i;
++
++      sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
++                              GFP_KERNEL);
++      if (!sid_data)
++              return -ENOMEM;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(sid_data->reg_base))
++              return PTR_ERR(sid_data->reg_base);
++
++      of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
++      if (!of_dev_id)
++              return -ENODEV;
++      sid_data->keysize = (int)of_dev_id->data;
++
++      platform_set_drvdata(pdev, sid_data);
++
++      sid_bin_attr.size = sid_data->keysize;
++      if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
++              return -ENODEV;
++
++      entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
++      for (i = 0; i < sid_data->keysize; i++)
++              entropy[i] = sunxi_sid_read_byte(sid_data, i);
++      add_device_randomness(entropy, sid_data->keysize);
++      kfree(entropy);
++
++      dev_dbg(&pdev->dev, "loaded\n");
++
++      return 0;
++}
++
++static struct platform_driver sunxi_sid_driver = {
++      .probe = sunxi_sid_probe,
++      .remove = sunxi_sid_remove,
++      .driver = {
++              .name = DRV_NAME,
++              .owner = THIS_MODULE,
++              .of_match_table = sunxi_sid_of_match,
++      },
++};
++module_platform_driver(sunxi_sid_driver);
++
++MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
++MODULE_DESCRIPTION("Allwinner sunxi security id driver");
++MODULE_LICENSE("GPL");
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/171-add-dt-sunxi-sid.patch b/target/linux/sunxi/patches-3.12/171-add-dt-sunxi-sid.patch
new file mode 100644 (file)
index 0000000..55a654f
--- /dev/null
@@ -0,0 +1,84 @@
+From 3c6625e46113e600fb83468c9a963a10c5cebedc Mon Sep 17 00:00:00 2001
+From: Oliver Schinagl <oliver@schinagl.nl>
+Date: Tue, 3 Sep 2013 12:33:28 +0200
+Subject: [PATCH] ARM: sunxi: dt: Add sunxi-sid to dts for sun4i, sun5i and
+ sun7i
+
+This patch shall add support for the sunxi-sid driver to the device
+tree for A10, A10s, A13 and A20.
+
+Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi  | 5 +++++
+ arch/arm/boot/dts/sun5i-a10s.dtsi | 5 +++++
+ arch/arm/boot/dts/sun5i-a13.dtsi  | 5 +++++
+ arch/arm/boot/dts/sun7i-a20.dtsi  | 5 +++++
+ 4 files changed, 20 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index c32770a..319cc6b 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -266,6 +266,11 @@
+                       reg = <0x01c20c90 0x10>;
+               };
++              sid: eeprom@01c23800 {
++                      compatible = "allwinner,sun4i-sid";
++                      reg = <0x01c23800 0x10>;
++              };
++
+               uart0: serial@01c28000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28000 0x400>;
+diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
+index 3b4a057..5247674 100644
+--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
+@@ -255,6 +255,11 @@
+                       reg = <0x01c20c90 0x10>;
+               };
++              sid: eeprom@01c23800 {
++                      compatible = "allwinner,sun4i-sid";
++                      reg = <0x01c23800 0x10>;
++              };
++
+               uart0: serial@01c28000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28000 0x400>;
+diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
+index f6091dc..ce8ef2a 100644
+--- a/arch/arm/boot/dts/sun5i-a13.dtsi
++++ b/arch/arm/boot/dts/sun5i-a13.dtsi
+@@ -222,6 +222,11 @@
+                       reg = <0x01c20c90 0x10>;
+               };
++              sid: eeprom@01c23800 {
++                      compatible = "allwinner,sun4i-sid";
++                      reg = <0x01c23800 0x10>;
++              };
++
+               uart1: serial@01c28400 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28400 0x400>;
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index b939d30..e46cfed 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -265,6 +265,11 @@
+                       reg = <0x01c20c90 0x10>;
+               };
++              sid: eeprom@01c23800 {
++                      compatible = "allwinner,sun7i-a20-sid";
++                      reg = <0x01c23800 0x200>;
++              };
++
+               uart0: serial@01c28000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28000 0x400>;
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/175-sunxi-rtc.patch b/target/linux/sunxi/patches-3.12/175-sunxi-rtc.patch
new file mode 100644 (file)
index 0000000..615658a
--- /dev/null
@@ -0,0 +1,542 @@
+From 9b6e3291426efc69d1e8bf257721997f3eeb3009 Mon Sep 17 00:00:00 2001
+From: Carlo Caione <carlo.caione@gmail.com>
+Date: Wed, 16 Oct 2013 20:30:27 +0200
+Subject: [PATCH] ARM: sun4i/sun7i: RTC driver
+
+This patch introduces the driver for the RTC in the Allwinner A10 and
+A20 SoCs.
+
+Signed-off-by: Carlo Caione <carlo.caione@gmail.com>
+---
+ drivers/rtc/Kconfig     |   7 +
+ drivers/rtc/Makefile    |   1 +
+ drivers/rtc/rtc-sunxi.c | 487 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 495 insertions(+)
+ create mode 100644 drivers/rtc/rtc-sunxi.c
+
+diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
+index 9654aa3..ef45e0b 100644
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -1076,6 +1076,13 @@ config RTC_DRV_SUN4V
+         If you say Y here you will get support for the Hypervisor
+         based RTC on SUN4V systems.
++config RTC_DRV_SUNXI
++      tristate "Allwinner sun4i/sun7i RTC"
++      depends on ARCH_SUNXI
++      help
++        If you say Y here you will get support for the RTC found on
++        Allwinner A10/A20.
++
+ config RTC_DRV_STARFIRE
+       bool "Starfire RTC"
+       depends on SPARC64
+diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
+index 2dff3d2..8b52b5a 100644
+--- a/drivers/rtc/Makefile
++++ b/drivers/rtc/Makefile
+@@ -115,6 +115,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE)     += rtc-starfire.o
+ obj-$(CONFIG_RTC_DRV_STK17TA8)        += rtc-stk17ta8.o
+ obj-$(CONFIG_RTC_DRV_STMP)    += rtc-stmp3xxx.o
+ obj-$(CONFIG_RTC_DRV_SUN4V)   += rtc-sun4v.o
++obj-$(CONFIG_RTC_DRV_SUNXI)   += rtc-sunxi.o
+ obj-$(CONFIG_RTC_DRV_TEGRA)   += rtc-tegra.o
+ obj-$(CONFIG_RTC_DRV_TEST)    += rtc-test.o
+ obj-$(CONFIG_RTC_DRV_TILE)    += rtc-tile.o
+diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c
+new file mode 100644
+index 0000000..ccd48ae
+--- /dev/null
++++ b/drivers/rtc/rtc-sunxi.c
+@@ -0,0 +1,487 @@
++/*
++ * An RTC driver for Allwinner A10/A20
++ *
++ * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com>
++ *
++ * 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.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++ */
++
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/rtc.h>
++#include <linux/types.h>
++
++#define SUNXI_LOSC_CTRL                               0x0000
++#define SUNXI_LOSC_CTRL_RTC_HMS_ACC           BIT(8)
++#define SUNXI_LOSC_CTRL_RTC_YMD_ACC           BIT(7)
++
++#define SUNXI_RTC_YMD                         0x0004
++
++#define SUNXI_RTC_HMS                         0x0008
++
++#define SUNXI_ALRM_DHMS                               0x000c
++
++#define SUNXI_ALRM_EN                         0x0014
++#define SUNXI_ALRM_EN_CNT_EN                  BIT(8)
++
++#define SUNXI_ALRM_IRQ_EN                     0x0018
++#define SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN          BIT(0)
++
++#define SUNXI_ALRM_IRQ_STA                    0x001c
++#define SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND               BIT(0)
++
++#define SUNXI_LOSC_CTRL_RTC_ACC \
++      (SUNXI_LOSC_CTRL_RTC_HMS_ACC | SUNXI_LOSC_CTRL_RTC_YMD_ACC)
++
++#define SUNXI_MASK_DH                         0x0000001f
++#define SUNXI_MASK_SM                         0x0000003f
++#define SUNXI_MASK_M                          0x0000000f
++#define SUNXI_MASK_LY                         0x00000001
++#define SUNXI_MASK_D                          0x00000ffe
++#define SUNXI_MASK_M                          0x0000000f
++
++#define SUNXI_GET(x, mask, shift)             (((x) & ((mask) << (shift))) \
++                                                      >> (shift))
++
++#define SUNXI_SET(x, mask, shift)             (((x) & (mask)) << (shift))
++
++/* Get date values */
++#define SUNXI_DATE_GET_DAY_VALUE(x)           SUNXI_GET(x, SUNXI_MASK_DH, 0)
++#define SUNXI_DATE_GET_MON_VALUE(x)           SUNXI_GET(x, SUNXI_MASK_M, 8)
++#define SUNXI_DATE_GET_YEAR_VALUE(x, mask)    SUNXI_GET(x, mask, 16)
++
++/* Get time values */
++#define SUNXI_TIME_GET_SEC_VALUE(x)           SUNXI_GET(x, SUNXI_MASK_SM, 0)
++#define SUNXI_TIME_GET_MIN_VALUE(x)           SUNXI_GET(x, SUNXI_MASK_SM, 8)
++#define SUNXI_TIME_GET_HOUR_VALUE(x)          SUNXI_GET(x, SUNXI_MASK_DH, 16)
++
++/* Get alarm values */
++#define SUNXI_ALRM_GET_SEC_VALUE(x)           SUNXI_GET(x, SUNXI_MASK_SM, 0)
++#define SUNXI_ALRM_GET_MIN_VALUE(x)           SUNXI_GET(x, SUNXI_MASK_SM, 8)
++#define SUNXI_ALRM_GET_HOUR_VALUE(x)          SUNXI_GET(x, SUNXI_MASK_DH, 16)
++
++/* Set date values */
++#define SUNXI_DATE_SET_DAY_VALUE(x)           SUNXI_DATE_GET_DAY_VALUE(x)
++#define SUNXI_DATE_SET_MON_VALUE(x)           SUNXI_SET(x, SUNXI_MASK_M, 8)
++#define SUNXI_DATE_SET_YEAR_VALUE(x, mask)    SUNXI_SET(x, mask, 16)
++#define SUNXI_LEAP_SET_VALUE(x, shift)                SUNXI_SET(x, SUNXI_MASK_LY, shift)
++
++/* Set time values */
++#define SUNXI_TIME_SET_SEC_VALUE(x)           SUNXI_TIME_GET_SEC_VALUE(x)
++#define SUNXI_TIME_SET_MIN_VALUE(x)           SUNXI_SET(x, SUNXI_MASK_SM, 8)
++#define SUNXI_TIME_SET_HOUR_VALUE(x)          SUNXI_SET(x, SUNXI_MASK_DH, 16)
++
++/* set alarm values */
++#define SUNXI_ALRM_SET_SEC_VALUE(x)           SUNXI_ALRM_GET_SEC_VALUE(x)
++#define SUNXI_ALRM_SET_MIN_VALUE(x)           SUNXI_SET(x, SUNXI_MASK_SM, 8)
++#define SUNXI_ALRM_SET_HOUR_VALUE(x)          SUNXI_SET(x, SUNXI_MASK_DH, 16)
++#define SUNXI_ALRM_SET_DAY_VALUE(x)           SUNXI_SET(x, SUNXI_MASK_D, 21)
++
++/* time unit conversions */
++#define SEC_IN_MIN                            60
++#define SEC_IN_HOUR                           (60 * SEC_IN_MIN)
++#define SEC_IN_DAY                            (24 * SEC_IN_HOUR)
++
++struct sunxi_rtc_data_year {
++      unsigned int min;               /* min year allowed */
++      unsigned int max;               /* max year allowed */
++      unsigned int off;               /* data year offset */
++      unsigned int mask;
++      unsigned char leap_shift;       /* bit shift to get the leap year */
++};
++
++static struct sunxi_rtc_data_year data_year_param[] = {
++      [0] = {
++              .min            = 1970,
++              .max            = 2100,
++              .off            = 0,
++              .mask           = 0x000000ff,
++              .leap_shift     = 24,
++      },
++      [1] = {
++              .min            = 2010,
++              .max            = 2073,
++              .off            = 110,
++              .mask           = 0x0000003f,
++              .leap_shift     = 22,
++      },
++};
++
++struct sunxi_rtc_dev {
++      struct rtc_device *rtc;
++      struct device *dev;
++      struct sunxi_rtc_data_year *data_year;
++      void __iomem *base;
++      int irq;
++};
++
++static irqreturn_t sunxi_rtc_alarmirq(int irq, void *id)
++{
++      struct sunxi_rtc_dev *chip = (struct sunxi_rtc_dev *) id;
++      u32 val;
++
++      val = readl(chip->base + SUNXI_ALRM_IRQ_STA);
++
++      if (val & SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND) {
++              val |= SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND;
++              writel(val, chip->base + SUNXI_ALRM_IRQ_STA);
++
++              rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
++
++              return IRQ_HANDLED;
++      }
++
++      return IRQ_NONE;
++}
++
++static void sunxi_rtc_setaie(int to, struct sunxi_rtc_dev *chip)
++{
++      u32 alarm_val = 0;
++      u32 alarm_irq_val = 0;
++
++      if (to) {
++              alarm_val = readl(chip->base + SUNXI_ALRM_EN);
++              alarm_val |= SUNXI_ALRM_EN_CNT_EN;
++
++              alarm_irq_val = readl(chip->base + SUNXI_ALRM_IRQ_EN);
++              alarm_irq_val |= SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN;
++      } else {
++              writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND,
++                              chip->base + SUNXI_ALRM_IRQ_STA);
++      }
++
++      writel(alarm_val, chip->base + SUNXI_ALRM_EN);
++      writel(alarm_irq_val, chip->base + SUNXI_ALRM_IRQ_EN);
++}
++
++static int sunxi_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++      struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
++      struct rtc_time *alrm_tm = &alrm->time;
++      u32 alarm;
++      u32 alarm_en;
++      u32 date;
++
++      alarm = readl(chip->base + SUNXI_ALRM_DHMS);
++      date = readl(chip->base + SUNXI_RTC_YMD);
++
++      alrm_tm->tm_sec = SUNXI_ALRM_GET_SEC_VALUE(alarm);
++      alrm_tm->tm_min = SUNXI_ALRM_GET_MIN_VALUE(alarm);
++      alrm_tm->tm_hour = SUNXI_ALRM_GET_HOUR_VALUE(alarm);
++
++      alrm_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date);
++      alrm_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date);
++      alrm_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date,
++                      chip->data_year->mask);
++
++      alrm_tm->tm_year += chip->data_year->off;
++      alrm_tm->tm_mon -= 1;
++
++      alarm_en = readl(chip->base + SUNXI_ALRM_IRQ_EN);
++      if (alarm_en & SUNXI_ALRM_EN_CNT_EN)
++              alrm->enabled = 1;
++
++      return 0;
++}
++
++static int sunxi_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
++{
++      struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
++      u32 date, time;
++      int t;
++
++      /* read again if the system was mid-updated
++       */
++      for (t = 0; t < 2; t++) {
++              date = readl(chip->base + SUNXI_RTC_YMD);
++              time = readl(chip->base + SUNXI_RTC_HMS);
++
++              rtc_tm->tm_sec  = SUNXI_TIME_GET_SEC_VALUE(time);
++              rtc_tm->tm_min  = SUNXI_TIME_GET_MIN_VALUE(time);
++              rtc_tm->tm_hour = SUNXI_TIME_GET_HOUR_VALUE(time);
++
++              rtc_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date);
++              rtc_tm->tm_mon  = SUNXI_DATE_GET_MON_VALUE(date);
++              rtc_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date,
++                              chip->data_year->mask);
++
++              if (rtc_tm->tm_sec == 0)
++                      msleep(500);
++              else
++                      break;
++      }
++
++      rtc_tm->tm_year += chip->data_year->off;
++      rtc_tm->tm_mon  -= 1;
++
++      return rtc_valid_tm(rtc_tm);
++}
++
++static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
++{
++      struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
++      struct rtc_time *alrm_tm = &alrm->time;
++      struct rtc_time tm_now;
++      u32 alarm = 0;
++      unsigned long time_now = 0;
++      unsigned long time_set = 0;
++      unsigned long time_gap = 0;
++      unsigned long time_gap_day = 0;
++      unsigned long time_gap_hour = 0;
++      unsigned long time_gap_min = 0;
++      int ret = 0;
++
++      ret = sunxi_rtc_gettime(dev, &tm_now);
++      if (ret < 0) {
++              dev_err(dev, "Error in getting time\n");
++              return -EINVAL;
++      }
++
++      rtc_tm_to_time(alrm_tm, &time_set);
++      rtc_tm_to_time(&tm_now, &time_now);
++      if (time_set <= time_now) {
++              dev_err(dev, "Date to set in the past\n");
++              return -EINVAL;
++      }
++
++      time_gap = time_set - time_now;
++      time_gap_day = time_gap / SEC_IN_DAY;
++      time_gap -= time_gap_day * SEC_IN_DAY;
++      time_gap_hour = time_gap / SEC_IN_HOUR;
++      time_gap -= time_gap_hour * SEC_IN_HOUR;
++      time_gap_min = time_gap / SEC_IN_MIN;
++      time_gap -= time_gap_min * SEC_IN_MIN;
++
++      if (time_gap_day > 255) {
++              dev_err(dev, "Day must be in the range 0 - 255\n");
++              return -EINVAL;
++      }
++
++      sunxi_rtc_setaie(0, chip);
++      writel(0, chip->base + SUNXI_ALRM_DHMS);
++      usleep_range(100, 300);
++
++      alarm = SUNXI_ALRM_SET_SEC_VALUE(time_gap) |
++              SUNXI_ALRM_SET_MIN_VALUE(time_gap_min) |
++              SUNXI_ALRM_SET_HOUR_VALUE(time_gap_hour) |
++              SUNXI_ALRM_SET_DAY_VALUE(time_gap_day);
++      writel(alarm, chip->base + SUNXI_ALRM_DHMS);
++
++      writel(0, chip->base + SUNXI_ALRM_IRQ_EN);
++      writel(SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN, chip->base + SUNXI_ALRM_IRQ_EN);
++
++      sunxi_rtc_setaie(alrm->enabled, chip);
++
++      return 0;
++}
++
++static int sunxi_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
++{
++      struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
++      u32 date = 0;
++      u32 time = 0;
++      int year;
++      int t;
++
++      year = rtc_tm->tm_year + 1900;
++      if (year < chip->data_year->min || year > chip->data_year->max) {
++              dev_err(dev, "rtc only supports year in range %d - %d\n",
++                              chip->data_year->min, chip->data_year->max);
++              return -EINVAL;
++      }
++
++      rtc_tm->tm_year -= chip->data_year->off;
++      rtc_tm->tm_mon += 1;
++
++      date = SUNXI_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
++              SUNXI_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
++              SUNXI_DATE_SET_YEAR_VALUE(rtc_tm->tm_year,
++                              chip->data_year->mask);
++
++      if (is_leap_year(year))
++              date |= SUNXI_LEAP_SET_VALUE(1, chip->data_year->leap_shift);
++
++      time = SUNXI_TIME_SET_SEC_VALUE(rtc_tm->tm_sec)  |
++              SUNXI_TIME_SET_MIN_VALUE(rtc_tm->tm_min)  |
++              SUNXI_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour);
++
++      writel(0, chip->base + SUNXI_RTC_HMS);
++      writel(0, chip->base + SUNXI_RTC_YMD);
++
++      writel(time, chip->base + SUNXI_RTC_HMS);
++
++      /* After writing the RCT HH-MM-SS register, the
++       * SUNXI_LOSC_CTRL_RTC_HMS_ACC bit is set and it will be cleared until
++       * the real writing operation is finished
++       */
++      for (t = 0; t < 3; t++) {
++              if ((readl(chip->base + SUNXI_LOSC_CTRL) &
++                      SUNXI_LOSC_CTRL_RTC_HMS_ACC) && --t)
++                      break;
++              else
++                      msleep(50);
++      }
++      if (t == 0) {
++              dev_err(dev, "Failed to set rtc time.\n");
++              return -1;
++      }
++
++      writel(date, chip->base + SUNXI_RTC_YMD);
++
++      /* After writing the RCT YY-MM-DD register, the
++       * SUNXI_LOSC_CTRL_RTC_YMD_ACC bit is set and it will be cleared until
++       * the real writing operation is finished
++       */
++      for (t = 0; t < 3; t++) {
++              if ((readl(chip->base + SUNXI_LOSC_CTRL) &
++                      SUNXI_LOSC_CTRL_RTC_YMD_ACC) && --t)
++                      break;
++              else
++                      msleep(50);
++      }
++      if (t == 0) {
++              dev_err(dev, "Failed to set rtc date.\n");
++              return -1;
++      }
++
++      /* wait about 70us to make sure the the time is really written into
++       * target */
++      usleep_range(70, 100);
++
++      return 0;
++}
++
++static int sunxi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
++{
++      struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
++
++      if (!enabled)
++              sunxi_rtc_setaie(enabled, chip);
++
++      return 0;
++}
++
++static const struct rtc_class_ops sunxi_rtc_ops = {
++      .read_time              = sunxi_rtc_gettime,
++      .set_time               = sunxi_rtc_settime,
++      .read_alarm             = sunxi_rtc_getalarm,
++      .set_alarm              = sunxi_rtc_setalarm,
++      .alarm_irq_enable       = sunxi_rtc_alarm_irq_enable
++};
++
++static const struct of_device_id sunxi_rtc_dt_ids[] = {
++      { .compatible = "allwinner,sun4i-rtc", .data = &data_year_param[0] },
++      { .compatible = "allwinner,sun7i-a20-rtc", .data = &data_year_param[1] },
++      { /* sentinel */ },
++};
++MODULE_DEVICE_TABLE(of, sunxi_rtc_dt_ids);
++
++
++static int sunxi_rtc_probe(struct platform_device *pdev)
++{
++      struct sunxi_rtc_dev *chip;
++      struct resource *res;
++      const struct of_device_id *of_id;
++      int ret;
++
++      chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
++      if (!chip)
++              return -ENOMEM;
++
++      platform_set_drvdata(pdev, chip);
++      chip->dev = &pdev->dev;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      chip->base = devm_ioremap_resource(&pdev->dev, res);
++      if (IS_ERR(chip->base))
++              return PTR_ERR(chip->base);
++
++      chip->irq = platform_get_irq(pdev, 0);
++      if (chip->irq < 0) {
++              dev_err(&pdev->dev, "No IRQ resource\n");
++              return chip->irq;
++      }
++      ret = devm_request_irq(&pdev->dev, chip->irq, sunxi_rtc_alarmirq,
++                      0, dev_name(&pdev->dev), chip);
++      if (ret) {
++              dev_err(&pdev->dev, "Could not request IRQ\n");
++              return ret;
++      }
++
++      of_id = of_match_device(sunxi_rtc_dt_ids, &pdev->dev);
++      if (!of_id) {
++              dev_err(&pdev->dev, "Unable to setup RTC data\n");
++              return -ENODEV;
++      }
++      chip->data_year = (struct sunxi_rtc_data_year *) of_id->data;
++
++      /* clear the alarm count value */
++      writel(0, chip->base + SUNXI_ALRM_DHMS);
++
++      /* disable alarm, not generate irq pending */
++      writel(0, chip->base + SUNXI_ALRM_EN);
++
++      /* disable alarm week/cnt irq, unset to cpu */
++      writel(0, chip->base + SUNXI_ALRM_IRQ_EN);
++
++      /* clear alarm week/cnt irq pending */
++      writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + SUNXI_ALRM_IRQ_STA);
++
++      chip->rtc = rtc_device_register("rtc-sunxi", &pdev->dev,
++                      &sunxi_rtc_ops, THIS_MODULE);
++      if (IS_ERR(chip->rtc)) {
++              dev_err(&pdev->dev, "unable to register device\n");
++              return PTR_ERR(chip->rtc);
++      }
++
++      dev_info(&pdev->dev, "RTC enabled\n");
++
++      return 0;
++}
++
++static int sunxi_rtc_remove(struct platform_device *pdev)
++{
++      struct sunxi_rtc_dev *chip = platform_get_drvdata(pdev);
++
++      rtc_device_unregister(chip->rtc);
++
++      return 0;
++}
++
++static struct platform_driver sunxi_rtc_driver = {
++      .probe          = sunxi_rtc_probe,
++      .remove         = sunxi_rtc_remove,
++      .driver         = {
++              .name           = "sunxi-rtc",
++              .owner          = THIS_MODULE,
++              .of_match_table = sunxi_rtc_dt_ids,
++      },
++};
++
++module_platform_driver(sunxi_rtc_driver);
++
++MODULE_DESCRIPTION("sunxi RTC driver");
++MODULE_AUTHOR("Carlo Caione <carlo.caione@gmail.com>");
++MODULE_LICENSE("GPL");
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/patches-3.12/176-add-dt-rtc-for-sun4i-7i.patch b/target/linux/sunxi/patches-3.12/176-add-dt-rtc-for-sun4i-7i.patch
new file mode 100644 (file)
index 0000000..3c23c74
--- /dev/null
@@ -0,0 +1,50 @@
+From 40a111b1ce47fabcff14a3bff131a4d118ada257 Mon Sep 17 00:00:00 2001
+From: Carlo Caione <carlo.caione@gmail.com>
+Date: Wed, 16 Oct 2013 20:30:26 +0200
+Subject: [PATCH] ARM: dts: sun4i/sun7i: add RTC node
+
+Add the RTC node to DTS for Allwinner A10 and Allwinner A20.
+
+Signed-off-by: Carlo Caione <carlo.caione@gmail.com>
+---
+ arch/arm/boot/dts/sun4i-a10.dtsi | 6 ++++++
+ arch/arm/boot/dts/sun7i-a20.dtsi | 6 ++++++
+ 2 files changed, 12 insertions(+)
+
+diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
+index 084fef9..04819a7 100644
+--- a/arch/arm/boot/dts/sun4i-a10.dtsi
++++ b/arch/arm/boot/dts/sun4i-a10.dtsi
+@@ -393,6 +393,12 @@
+                       reg = <0x01c20c90 0x10>;
+               };
++              rtc: rtc@01c20d00 {
++                      compatible = "allwinner,sun4i-rtc";
++                      reg = <0x01c20d00 0x20>;
++                      interrupts = <24>;
++              };
++
+               sid: eeprom@01c23800 {
+                       compatible = "allwinner,sun4i-sid";
+                       reg = <0x01c23800 0x10>;
+diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
+index fe6cf18..b92e17b 100644
+--- a/arch/arm/boot/dts/sun7i-a20.dtsi
++++ b/arch/arm/boot/dts/sun7i-a20.dtsi
+@@ -381,6 +381,12 @@
+                       reg = <0x01c20c90 0x10>;
+               };
++              rtc: rtc@01c20d00 {
++                      compatible = "allwinner,sun7i-a20-rtc";
++                      reg = <0x01c20d00 0x20>;
++                      interrupts = <0 24 1>;
++              };
++
+               sid: eeprom@01c23800 {
+                       compatible = "allwinner,sun7i-a20-sid";
+                       reg = <0x01c23800 0x200>;
+-- 
+1.8.4
+
diff --git a/target/linux/sunxi/profiles/01-default.mk b/target/linux/sunxi/profiles/01-default.mk
new file mode 100644 (file)
index 0000000..7d83440
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Default
+  NAME:=Default package set
+  PACKAGES += uboot-sunxi-A13-OLinuXino
+endef
+
+define Profile/Default/Description
+       Default package set compatible with most boards.
+endef
+$(eval $(call Profile,Default))
+
diff --git a/target/linux/sunxi/profiles/a13-olinuxino.mk b/target/linux/sunxi/profiles/a13-olinuxino.mk
new file mode 100644 (file)
index 0000000..821bc56
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/A13_OLinuXino
+       NAME:=A13 OLinuXino
+       PACKAGES:=\
+               uboot-sunxi-A13-OLinuXino
+endef
+
+define Profile/A13_OLinuXino/Description
+       Package set optimized for the Olimex A13 OLinuXino
+endef
+
+$(eval $(call Profile,A13_OLinuXino))
diff --git a/target/linux/sunxi/profiles/a20-olinuxino.mk b/target/linux/sunxi/profiles/a20-olinuxino.mk
new file mode 100644 (file)
index 0000000..583885a
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/A20-OLinuXino_MICRO
+       NAME:=A20 OLinuXino Micro
+       PACKAGES:=\
+               uboot-sunxi-A20-OLinuXino_MICRO
+endef
+
+define Profile/A20-OLinuXino_MICRO/Description
+       Package set optimized for the Olimex A20 OLinuXino micro
+endef
+
+$(eval $(call Profile,A20-OLinuXino_MICRO))
diff --git a/target/linux/sunxi/profiles/cubieboard.mk b/target/linux/sunxi/profiles/cubieboard.mk
new file mode 100644 (file)
index 0000000..2015453
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Cubieboard
+       NAME:=Cubieboard
+       PACKAGES:=\
+               uboot-sunxi-Cubieboard
+endef
+
+define Profile/Cubieboard/Description
+       Package set optimized for the Cubieboard
+endef
+
+$(eval $(call Profile,Cubieboard))
diff --git a/target/linux/sunxi/profiles/cubieboard2.mk b/target/linux/sunxi/profiles/cubieboard2.mk
new file mode 100644 (file)
index 0000000..66c0f43
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Cubieboard2
+       NAME:=Cubieboard2
+       PACKAGES:=\
+               uboot-sunxi-Cubieboard2
+endef
+
+define Profile/Cubieboard2/Description
+       Package set optimized for the Cubieboard2
+endef
+
+$(eval $(call Profile,Cubieboard2))