summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Luebbe <jlu@pengutronix.de>2012-11-22 11:58:36 +0100
committerJan Luebbe <jlu@pengutronix.de>2012-11-22 12:46:51 +0100
commitce6e38fa64f60a7554546f39b7f462574719e484 (patch)
tree3e13722641d21ea0e6f4e752ed46b2dc7042c315
parent25f57ac7c79468e9a2d3e4ae7473a75a7dd74d05 (diff)
downloadplatform-pengutronix-beagleboneti-ce6e38fa64f60a7554546f39b7f462574719e484.tar.gz
platform-pengutronix-beagleboneti-ce6e38fa64f60a7554546f39b7f462574719e484.tar.xz
kernel: switch to mainline-based patch stack
Thanks to Koen Kooi for maintaining the patch stack. Also update to PTXdist master. Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
-rw-r--r--config/images/boot-mlo-vfat.config1
-rw-r--r--kernelconfig3890
-rw-r--r--patches/linux-3.7-rc6/0000-linux-master.patch503
-rw-r--r--patches/linux-3.7-rc6/0001-video-st7735fb-add-st7735-framebuffer-driver.patch800
-rw-r--r--patches/linux-3.7-rc6/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch41
-rw-r--r--patches/linux-3.7-rc6/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch94
-rw-r--r--patches/linux-3.7-rc6/0004-of-Add-generic-device-tree-DMA-helpers.patch533
-rw-r--r--patches/linux-3.7-rc6/0005-of-dma-fix-build-break-for-CONFIG_OF.patch54
-rw-r--r--patches/linux-3.7-rc6/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch69
-rw-r--r--patches/linux-3.7-rc6/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch24
-rw-r--r--patches/linux-3.7-rc6/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch144
-rw-r--r--patches/linux-3.7-rc6/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch4048
-rw-r--r--patches/linux-3.7-rc6/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch69
-rw-r--r--patches/linux-3.7-rc6/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch633
-rw-r--r--patches/linux-3.7-rc6/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch128
-rw-r--r--patches/linux-3.7-rc6/0013-dmaengine-edma-enable-build-for-AM33XX.patch25
-rw-r--r--patches/linux-3.7-rc6/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch71
-rw-r--r--patches/linux-3.7-rc6/0015-ARM-dts-add-AM33XX-EDMA-support.patch55
-rw-r--r--patches/linux-3.7-rc6/0016-dmaengine-add-dma_request_slave_channel_compat.patch42
-rw-r--r--patches/linux-3.7-rc6/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch45
-rw-r--r--patches/linux-3.7-rc6/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch39
-rw-r--r--patches/linux-3.7-rc6/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch55
-rw-r--r--patches/linux-3.7-rc6/0020-ARM-dts-add-AM33XX-MMC-support.patch91
-rw-r--r--patches/linux-3.7-rc6/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch119
-rw-r--r--patches/linux-3.7-rc6/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch56
-rw-r--r--patches/linux-3.7-rc6/0023-ARM-dts-add-AM33XX-SPI-support.patch124
-rw-r--r--patches/linux-3.7-rc6/0024-Documentation-bindings-add-spansion.patch22
-rw-r--r--patches/linux-3.7-rc6/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch44
-rw-r--r--patches/linux-3.7-rc6/0026-misc-add-gpevt-driver.patch219
-rw-r--r--patches/linux-3.7-rc6/0027-ARM-dts-add-BeagleBone-gpevt-support.patch50
-rw-r--r--patches/linux-3.7-rc6/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch235
-rw-r--r--patches/linux-3.7-rc6/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch2001
-rw-r--r--patches/linux-3.7-rc6/0030-misc-gpevt-null-terminate-the-of_match_table.patch22
-rw-r--r--patches/linux-3.7-rc6/0031-proposed-probe-fix-works-for-me-on-evm.patch43
-rw-r--r--patches/linux-3.7-rc6/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch80
-rw-r--r--patches/linux-3.7-rc6/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch35
-rw-r--r--patches/linux-3.7-rc6/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch87
-rw-r--r--patches/linux-3.7-rc6/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch109
-rw-r--r--patches/linux-3.7-rc6/0038-i2c-pinctrl-ify-i2c-omap.c.patch46
-rw-r--r--patches/linux-3.7-rc6/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch70
-rw-r--r--patches/linux-3.7-rc6/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch29
-rw-r--r--patches/linux-3.7-rc6/0041-beaglebone-add-a-cpu-led-trigger.patch22
-rw-r--r--patches/linux-3.7-rc6/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch79
-rw-r--r--patches/linux-3.7-rc6/0045-input-TSC-ti_tscadc-Correct-register-usage.patch226
-rw-r--r--patches/linux-3.7-rc6/0046-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch138
-rw-r--r--patches/linux-3.7-rc6/0047-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch67
-rw-r--r--patches/linux-3.7-rc6/0048-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch37
-rw-r--r--patches/linux-3.7-rc6/0049-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch1174
-rw-r--r--patches/linux-3.7-rc6/0050-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch453
-rw-r--r--patches/linux-3.7-rc6/0051-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch571
-rw-r--r--patches/linux-3.7-rc6/0052-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch420
-rw-r--r--patches/linux-3.7-rc6/0053-input-ti_am335x_tsc-Make-steps-enable-configurable.patch74
-rw-r--r--patches/linux-3.7-rc6/0054-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch329
-rw-r--r--patches/linux-3.7-rc6/0055-input-ti_am335x_tsc-Add-variance-filters.patch75
-rw-r--r--patches/linux-3.7-rc6/0056-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch183
-rw-r--r--patches/linux-3.7-rc6/0057-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch184
-rw-r--r--patches/linux-3.7-rc6/0059-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch165
-rw-r--r--patches/linux-3.7-rc6/0060-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch68
-rw-r--r--patches/linux-3.7-rc6/0061-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch120
-rw-r--r--patches/linux-3.7-rc6/0062-Control-module-EHRPWM-clk-enabling.patch43
-rw-r--r--patches/linux-3.7-rc6/0063-pwm-pwm-tiecap-Enable-clock-gating.patch102
-rw-r--r--patches/linux-3.7-rc6/0064-PWM-ti-ehrpwm-fix-up-merge-conflict.patch22
-rw-r--r--patches/linux-3.7-rc6/0065-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch370
-rw-r--r--patches/linux-3.7-rc6/0066-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch84
-rw-r--r--patches/linux-3.7-rc6/0067-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch122
-rw-r--r--patches/linux-3.7-rc6/0069-pinctrl-pinctrl-single-must-be-initialized-early.patch35
-rw-r--r--patches/linux-3.7-rc6/0070-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch94
-rw-r--r--patches/linux-3.7-rc6/0071-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch107
-rw-r--r--patches/linux-3.7-rc6/0072-beaglebone-fix-backlight-entry-in-DT.patch29
-rw-r--r--patches/linux-3.7-rc6/0074-Shut-up-musb.patch24
-rw-r--r--patches/linux-3.7-rc6/0075-musb-Fix-crashes-and-other-weirdness.patch46
-rw-r--r--patches/linux-3.7-rc6/0076-musb-revert-parts-of-032ec49f.patch371
-rw-r--r--patches/linux-3.7-rc6/0077-usb-musb-dsps-get-the-PHY-using-phandle-api.patch55
-rw-r--r--patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch204
-rw-r--r--patches/linux-3.7-rc6/0079-usb-otg-nop-add-dt-support.patch48
-rw-r--r--patches/linux-3.7-rc6/0080-usb-musb-dsps-add-phy-control-logic-to-glue.patch275
-rw-r--r--patches/linux-3.7-rc6/0081-usb-musb-dsps-enable-phy-control-for-am335x.patch58
-rw-r--r--patches/linux-3.7-rc6/0082-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch45
-rw-r--r--patches/linux-3.7-rc6/0084-omap2-clk-Add-missing-lcdc-clock-definition.patch40
-rw-r--r--patches/linux-3.7-rc6/0085-da8xx-Allow-use-by-am33xx-based-devices.patch23
-rw-r--r--patches/linux-3.7-rc6/0086-da8xx-Fix-revision-check-on-the-da8xx-driver.patch22
-rw-r--r--patches/linux-3.7-rc6/0087-da8xx-De-constify-members-in-the-platform-config.patch29
-rw-r--r--patches/linux-3.7-rc6/0088-da8xx-Add-standard-panel-definition.patch36
-rw-r--r--patches/linux-3.7-rc6/0089-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch34
-rw-r--r--patches/linux-3.7-rc6/0090-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch35
-rw-r--r--patches/linux-3.7-rc6/0092-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch117
-rw-r--r--patches/linux-3.7-rc6/0093-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch38
-rw-r--r--patches/linux-3.7-rc6/0094-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch23
-rw-r--r--patches/linux-3.7-rc6/0096-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch25
-rw-r--r--patches/linux-3.7-rc6/0098-f2fs-add-document.patch438
-rw-r--r--patches/linux-3.7-rc6/0099-f2fs-add-on-disk-layout.patch383
-rw-r--r--patches/linux-3.7-rc6/0100-f2fs-add-superblock-and-major-in-memory-structure.patch1962
-rw-r--r--patches/linux-3.7-rc6/0101-f2fs-add-super-block-operations.patch612
-rw-r--r--patches/linux-3.7-rc6/0102-f2fs-add-checkpoint-operations.patch834
-rw-r--r--patches/linux-3.7-rc6/0103-f2fs-add-node-operations.patch1824
-rw-r--r--patches/linux-3.7-rc6/0104-f2fs-add-segment-operations.patch1843
-rw-r--r--patches/linux-3.7-rc6/0105-f2fs-add-file-operations.patch661
-rw-r--r--patches/linux-3.7-rc6/0106-f2fs-add-address-space-operations-for-data.patch724
-rw-r--r--patches/linux-3.7-rc6/0107-f2fs-add-core-inode-operations.patch282
-rw-r--r--patches/linux-3.7-rc6/0108-f2fs-add-inode-operations-for-special-inodes.patch514
-rw-r--r--patches/linux-3.7-rc6/0109-f2fs-add-core-directory-operations.patch782
-rw-r--r--patches/linux-3.7-rc6/0110-f2fs-add-xattr-and-acl-functionalities.patch1102
-rw-r--r--patches/linux-3.7-rc6/0111-f2fs-add-garbage-collection-functions.patch1395
-rw-r--r--patches/linux-3.7-rc6/0112-f2fs-add-recovery-routines-for-roll-forward.patch411
-rw-r--r--patches/linux-3.7-rc6/0113-f2fs-update-Kconfig-and-Makefile.patch115
-rw-r--r--patches/linux-3.7-rc6/0114-f2fs-gc.h-make-should_do_checkpoint-inline.patch26
-rw-r--r--patches/linux-3.7-rc6/0115-f2fs-move-statistics-code-into-one-file.patch967
-rw-r--r--patches/linux-3.7-rc6/0116-f2fs-move-proc-files-to-debugfs.patch449
-rw-r--r--patches/linux-3.7-rc6/0117-f2fs-compile-fix.patch22
-rw-r--r--patches/linux-3.7-rc6/0119-i2c-EEPROM-Export-memory-accessor.patch89
-rw-r--r--patches/linux-3.7-rc6/0120-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch71
-rw-r--r--patches/linux-3.7-rc6/0121-gpio-keys-Pinctrl-fy.patch40
-rw-r--r--patches/linux-3.7-rc6/0122-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch195
-rw-r--r--patches/linux-3.7-rc6/0123-pwm-export-of_pwm_request.patch67
-rw-r--r--patches/linux-3.7-rc6/0124-i2c-Export-capability-to-probe-devices.patch65
-rw-r--r--patches/linux-3.7-rc6/0125-pwm-backlight-Pinctrl-fy.patch37
-rw-r--r--patches/linux-3.7-rc6/0126-spi-Export-OF-interfaces-for-capebus-use.patch119
-rw-r--r--patches/linux-3.7-rc6/0127-w1-gpio-Pinctrl-fy.patch36
-rw-r--r--patches/linux-3.7-rc6/0128-w1-gpio-Simplify-get-rid-of-defines.patch141
-rw-r--r--patches/linux-3.7-rc6/0129-arm-dt-Enable-DT-proc-updates.patch22
-rw-r--r--patches/linux-3.7-rc6/0130-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch57
-rw-r--r--patches/linux-3.7-rc6/0131-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch501
-rw-r--r--patches/linux-3.7-rc6/0132-beaglebone-enable-emmc-for-bonelt.patch49
-rw-r--r--patches/linux-3.7-rc6/0133-capebus-Core-capebus-support.patch1383
-rw-r--r--patches/linux-3.7-rc6/0134-capebus-Add-beaglebone-board-support.patch1955
-rw-r--r--patches/linux-3.7-rc6/0135-capebus-Beaglebone-generic-board.patch135
-rw-r--r--patches/linux-3.7-rc6/0136-capebus-Add-beaglebone-geiger-cape.patch546
-rw-r--r--patches/linux-3.7-rc6/0137-capebus-Beaglebone-capebus-DT-update.patch745
-rw-r--r--patches/linux-3.7-rc6/0138-beaglebone-Update-default-config-for-capebus.patch3909
-rw-r--r--patches/linux-3.7-rc6/0139-capebus-Geiger-Cape-config-bugfixs.patch27
-rw-r--r--patches/linux-3.7-rc6/series128
-rw-r--r--platformconfig24
132 files changed, 47464 insertions, 9 deletions
diff --git a/config/images/boot-mlo-vfat.config b/config/images/boot-mlo-vfat.config
index 3b5f9b5..6a52246 100644
--- a/config/images/boot-mlo-vfat.config
+++ b/config/images/boot-mlo-vfat.config
@@ -3,6 +3,7 @@ image @IMAGE@ {
file MLO { image = "MLO"}
file barebox.bin { image = "barebox-image" }
file barebox.env { image = "barebox-default-environment" }
+ file oftree { image = "am335x-bone.dtb" }
file uImage { image = "linuximage" }
}
name = boot-mlo
diff --git a/kernelconfig b/kernelconfig
new file mode 100644
index 0000000..72894d1
--- /dev/null
+++ b/kernelconfig
@@ -0,0 +1,3890 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.7.0-rc6 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_NEED_MACH_GPIO_H=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_SPARSE_IRQ=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_RCU_FANOUT=32
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_CGROUP_PERF is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_CFS_BANDWIDTH is not set
+# CONFIG_RT_GROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_HAVE_UID16=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_JUMP_LABEL is not set
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_GENERIC_KERNEL_THREAD=y
+CONFIG_GENERIC_KERNEL_EXECVE=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PADATA=y
+CONFIG_ASN1=m
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM2835 is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_ARCH_ZYNQ is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+
+#
+# TI OMAP Common Features
+#
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2PLUS=y
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
+CONFIG_OMAP_32K_TIMER_HZ=512
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_PM_NOOP=y
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# TI OMAP2/3/4 Specific Features
+#
+CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
+CONFIG_SOC_HAS_OMAP2_SDRC=y
+# CONFIG_SOC_HAS_REALTIME_COUNTER is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
+# CONFIG_SOC_OMAP5 is not set
+CONFIG_SOC_OMAP3430=y
+# CONFIG_SOC_TI81XX is not set
+CONFIG_SOC_AM33XX=y
+CONFIG_OMAP_PACKAGE_CBB=y
+CONFIG_OMAP_PACKAGE_CBL=y
+CONFIG_OMAP_PACKAGE_CBS=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_DEVKIT8000 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP3530_LV_SOM is not set
+# CONFIG_MACH_OMAP3_TORPEDO is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3517EVM is not set
+# CONFIG_MACH_CRANEBOARD is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_TOUCHBOOK is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RM680 is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+# CONFIG_MACH_OMAP_ZOOM3 is not set
+# CONFIG_MACH_CM_T35 is not set
+# CONFIG_MACH_CM_T3517 is not set
+CONFIG_MACH_IGEP0020=y
+# CONFIG_MACH_IGEP0030 is not set
+# CONFIG_MACH_SBC3530 is not set
+# CONFIG_MACH_OMAP_3630SDP is not set
+# CONFIG_MACH_OMAP_4430SDP is not set
+CONFIG_MACH_OMAP4_PANDA=y
+# CONFIG_OMAP3_EMU is not set
+# CONFIG_OMAP3_SDRC_AC_TIMING is not set
+# CONFIG_OMAP4_ERRATA_I688 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_ARM_VIRT_EXT is not set
+CONFIG_SWP_EMULATE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_CACHE_L2X0=y
+CONFIG_CACHE_PL310=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARM_NR_BANKS=8
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_742230 is not set
+# CONFIG_ARM_ERRATA_742231 is not set
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_727915=y
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_751472 is not set
+# CONFIG_PL310_ERRATA_753970 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+# CONFIG_ARM_ERRATA_764369 is not set
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+CONFIG_ARM_GIC=y
+CONFIG_TI_PRIV_EDMA=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_ARM_CPU_TOPOLOGY=y
+# CONFIG_SCHED_MC is not set
+# CONFIG_SCHED_SMT is not set
+CONFIG_HAVE_ARM_SCU=y
+# CONFIG_ARM_ARCH_TIMER is not set
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+CONFIG_LOCAL_TIMERS=y
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=512
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_GENERIC_CPUFREQ_CPU0=y
+
+#
+# ARM CPU frequency scaling drivers
+#
+# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_COREDUMP is not set
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_PM_SLEEP_DEBUG=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_HAS_OPP=y
+CONFIG_PM_OPP=y
+CONFIG_PM_CLK=y
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_UDP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+# CONFIG_NETFILTER_XT_MARK is not set
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ECN=m
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_HL=m
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_IPV6 is not set
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+# CONFIG_IP_VS_PROTO_TCP is not set
+# CONFIG_IP_VS_PROTO_UDP is not set
+# CONFIG_IP_VS_PROTO_AH_ESP is not set
+# CONFIG_IP_VS_PROTO_ESP is not set
+# CONFIG_IP_VS_PROTO_AH is not set
+# CONFIG_IP_VS_PROTO_SCTP is not set
+
+#
+# IPVS scheduler
+#
+# CONFIG_IP_VS_RR is not set
+# CONFIG_IP_VS_WRR is not set
+# CONFIG_IP_VS_LC is not set
+# CONFIG_IP_VS_WLC is not set
+# CONFIG_IP_VS_LBLC is not set
+# CONFIG_IP_VS_LBLCR is not set
+# CONFIG_IP_VS_DH is not set
+# CONFIG_IP_VS_SH is not set
+# CONFIG_IP_VS_SED is not set
+# CONFIG_IP_VS_NQ is not set
+
+#
+# IPVS SH scheduler
+#
+CONFIG_IP_VS_SH_TAB_BITS=8
+
+#
+# IPVS application helper
+#
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV6 is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+# CONFIG_L2TP_V3 is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+CONFIG_NET_DSA=m
+# CONFIG_NET_DSA_TAG_DSA is not set
+# CONFIG_NET_DSA_TAG_EDSA is not set
+# CONFIG_NET_DSA_TAG_TRAILER is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_PHONET=m
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFB is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+CONFIG_NET_SCH_CODEL=y
+CONFIG_NET_SCH_FQ_CODEL=y
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+CONFIG_NET_CLS_CGROUP=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_BLA=y
+# CONFIG_BATMAN_ADV_DEBUG is not set
+CONFIG_OPENVSWITCH=m
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+CONFIG_NETPRIO_CGROUP=m
+CONFIG_BQL=y
+CONFIG_BPF_JIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+
+#
+# CAN Device Drivers
+#
+# CONFIG_CAN_VCAN is not set
+# CONFIG_CAN_SLCAN is not set
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_TI_HECC=m
+CONFIG_CAN_MCP251X=m
+# CONFIG_CAN_SJA1000 is not set
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+# CONFIG_CAN_CC770 is not set
+
+#
+# CAN USB interfaces
+#
+CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB2=m
+CONFIG_CAN_PEAK_USB=m
+# CONFIG_CAN_SOFTING is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+# CONFIG_IRNET is not set
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+# CONFIG_BT_WILINK is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEBUGFS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_REGULATOR=m
+CONFIG_RFKILL_GPIO=m
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+CONFIG_CEPH_LIB=m
+# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
+# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
+CONFIG_NFC=m
+CONFIG_NFC_NCI=m
+CONFIG_NFC_HCI=m
+CONFIG_NFC_SHDLC=y
+# CONFIG_NFC_LLCP is not set
+
+#
+# Near Field Communication (NFC) devices
+#
+CONFIG_PN544_HCI_NFC=m
+CONFIG_NFC_PN533=m
+# CONFIG_NFC_WILINK is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=m
+CONFIG_REGMAP_MMIO=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+# CONFIG_CMA is not set
+
+#
+# Bus devices
+#
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_OMAP_INTERCONNECT=y
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PHYSMAP_OF is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+# CONFIG_MTD_NAND_OMAP_BCH is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+CONFIG_MTD_UBI_FASTMAP=y
+# CONFIG_MTD_UBI_GLUEBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+
+#
+# Device Tree and Open Firmware support
+#
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_OF_SELFTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+CONFIG_BMP085=y
+CONFIG_BMP085_I2C=m
+# CONFIG_BMP085_SPI is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_GPEVT is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=y
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+CONFIG_TI_ST=m
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_VIRTIO=m
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_DM is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_MII=y
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+CONFIG_VXLAN=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_VIRTIO_NET=m
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+CONFIG_NET_VENDOR_CIRRUS=y
+# CONFIG_CS89x0 is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_FARADAY=y
+# CONFIG_FTMAC100 is not set
+# CONFIG_FTGMAC100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+CONFIG_NET_VENDOR_MICREL=y
+CONFIG_KS8842=m
+CONFIG_KS8851=y
+CONFIG_KS8851_MLL=y
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_AX88796 is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_VENDOR_SMSC=y
+CONFIG_SMC91X=y
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_SMSC911X_ARCH_HOOKS is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_TI=y
+CONFIG_TI_DAVINCI_EMAC=y
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_TI_DAVINCI_CPDMA=y
+CONFIG_TI_CPSW=y
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_AT803X_PHY=y
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_MDIO_BUS_MUX=m
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+CONFIG_MDIO_BUS_MUX_MMIOREG=m
+# CONFIG_MICREL_KS8995MA is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+CONFIG_USB_NET_SMSC95XX=y
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_QMI_WWAN is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_CDC_PHONET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMFMAC is not set
+# CONFIG_HOSTAP is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_SPI is not set
+CONFIG_LIBERTAS_DEBUG=y
+# CONFIG_LIBERTAS_MESH is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_WL_TI is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+CONFIG_INPUT_MATRIXKMAP=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_EGALAX is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_ILI210X is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MMS114=m
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+# CONFIG_INPUT_TWL4030_VIBRA is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_EM is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_HVC_DRIVER=y
+# CONFIG_HVC_DCC is not set
+CONFIG_VIRTIO_CONSOLE=m
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_ATMEL is not set
+CONFIG_HW_RANDOM_VIRTIO=m
+# CONFIG_HW_RANDOM_EXYNOS is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_OMAP24XX=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+CONFIG_SPI_SC18IS602=m
+CONFIG_SPI_XCOMM=m
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+CONFIG_PINCTRL_SINGLE=y
+# CONFIG_PINCTRL_SAMSUNG is not set
+# CONFIG_PINCTRL_EXYNOS4 is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_EM is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+CONFIG_GPIO_TWL4030=y
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_DS1WM=m
+CONFIG_W1_MASTER_GPIO=y
+CONFIG_HDQ_MASTER_OMAP=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=y
+CONFIG_W1_SLAVE_SMEM=y
+CONFIG_W1_SLAVE_DS2408=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_DS2780=m
+CONFIG_W1_SLAVE_DS2781=m
+CONFIG_W1_SLAVE_DS28E04=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+CONFIG_GENERIC_ADC_BATTERY=m
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_ISP1704 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_TWL4030 is not set
+# CONFIG_CHARGER_LP8727 is not set
+CONFIG_CHARGER_GPIO=m
+# CONFIG_CHARGER_MANAGER is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7314 is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+CONFIG_SENSORS_ADT7410=m
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+CONFIG_SENSORS_GPIO_FAN=m
+CONFIG_SENSORS_HIH6130=m
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+CONFIG_SENSORS_MAX197=m
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+CONFIG_SENSORS_SHT21=m
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_SCH5627 is not set
+# CONFIG_SENSORS_SCH5636 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_THMC50 is not set
+CONFIG_SENSORS_TMP102=m
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_CPU_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MPCORE_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL4030_WATCHDOG=y
+# CONFIG_MAX63XX_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+CONFIG_MFD_TI_AM335X_TSCADC=y
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+CONFIG_MFD_TPS65217=y
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_MADC is not set
+CONFIG_TWL4030_POWER=y
+# CONFIG_MFD_TWL4030_AUDIO is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+CONFIG_MFD_WL1273_CORE=m
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_PALMAS is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_GPIO is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_FAN53555 is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_LP872X is not set
+# CONFIG_REGULATOR_TPS62360 is not set
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
+CONFIG_REGULATOR_TPS65217=y
+# CONFIG_REGULATOR_TPS6524X is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_V4L2=m
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEOBUF2_CORE=m
+CONFIG_VIDEOBUF2_MEMOPS=m
+CONFIG_VIDEOBUF2_DMA_CONTIG=m
+CONFIG_VIDEOBUF2_VMALLOC=m
+CONFIG_DVB_CORE=m
+CONFIG_DVB_NET=y
+CONFIG_DVB_MAX_ADAPTERS=8
+CONFIG_DVB_DYNAMIC_MINORS=y
+
+#
+# Media drivers
+#
+CONFIG_RC_CORE=m
+CONFIG_RC_MAP=m
+CONFIG_RC_DECODERS=y
+CONFIG_LIRC=m
+CONFIG_IR_LIRC_CODEC=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_RC5_SZ_DECODER=m
+CONFIG_IR_SANYO_DECODER=m
+CONFIG_IR_MCE_KBD_DECODER=m
+CONFIG_RC_DEVICES=y
+CONFIG_RC_ATI_REMOTE=m
+CONFIG_IR_IMON=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_REDRAT3=m
+CONFIG_IR_STREAMZAP=m
+CONFIG_IR_IGUANA=m
+CONFIG_IR_TTUSBIR=m
+CONFIG_IR_RX51=m
+CONFIG_RC_LOOPBACK=m
+CONFIG_IR_GPIO_CIR=m
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_JL2005BCD=m
+CONFIG_USB_GSPCA_KINECT=m
+CONFIG_USB_GSPCA_KONICA=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_NW80X=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SE401=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TOPRO=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_VICAM=m
+CONFIG_USB_GSPCA_XIRLINK_CIT=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+CONFIG_VIDEO_CPIA2=m
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_USB_SN9C102=m
+
+#
+# Analog TV USB devices
+#
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_STK1160=m
+CONFIG_VIDEO_STK1160_AC97=y
+
+#
+# Analog/digital TV USB devices
+#
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_RC=y
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_TM6000=m
+CONFIG_VIDEO_TM6000_ALSA=m
+CONFIG_VIDEO_TM6000_DVB=m
+
+#
+# Digital TV USB devices
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_PCTV452E=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_FRIIO=m
+CONFIG_DVB_USB_AZ6027=m
+CONFIG_DVB_USB_TECHNISAT_USB2=m
+CONFIG_DVB_USB_V2=m
+CONFIG_DVB_USB_CYPRESS_FIRMWARE=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_AF9035=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_AZ6007=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_IT913X=m
+CONFIG_DVB_USB_LME2510=m
+CONFIG_DVB_USB_MXL111SF=m
+CONFIG_DVB_USB_RTL28XXU=m
+# CONFIG_SMS_USB_DRV is not set
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_EM28XX_RC=m
+CONFIG_TTPCI_EEPROM=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_VPSS_SYSTEM=m
+CONFIG_VIDEO_VPFE_CAPTURE=m
+CONFIG_VIDEO_DM6446_CCDC=m
+CONFIG_VIDEO_OMAP2_VOUT_VRFB=y
+CONFIG_VIDEO_OMAP2_VOUT=m
+# CONFIG_VIDEO_TIMBERDALE is not set
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
+CONFIG_V4L_TEST_DRIVERS=y
+CONFIG_VIDEO_VIVI=m
+CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_SMS_SDIO_DRV is not set
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_SI470X=y
+CONFIG_USB_SI470X=m
+CONFIG_I2C_SI470X=m
+CONFIG_USB_MR800=m
+CONFIG_USB_DSBR=m
+# CONFIG_RADIO_SHARK is not set
+CONFIG_RADIO_SHARK2=m
+CONFIG_I2C_SI4713=m
+CONFIG_RADIO_SI4713=m
+CONFIG_USB_KEENE=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_WL1273=m
+
+#
+# Texas Instruments WL128x FM driver (ST based)
+#
+CONFIG_RADIO_WL128X=m
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, frontends)
+#
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Audio decoders, processors and mixers
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+CONFIG_VIDEO_MT9V011=m
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Miscelaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# soc_camera sensor drivers
+#
+# CONFIG_SOC_CAMERA_IMX074 is not set
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
+CONFIG_SOC_CAMERA_MT9T112=m
+CONFIG_SOC_CAMERA_MT9V022=m
+# CONFIG_SOC_CAMERA_OV2640 is not set
+# CONFIG_SOC_CAMERA_OV5642 is not set
+# CONFIG_SOC_CAMERA_OV6650 is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_SOC_CAMERA_OV9640 is not set
+# CONFIG_SOC_CAMERA_OV9740 is not set
+# CONFIG_SOC_CAMERA_RJ54N1 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2063=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_XC4000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_MEDIA_TUNER_TDA18218=m
+CONFIG_MEDIA_TUNER_FC0011=m
+CONFIG_MEDIA_TUNER_FC0012=m
+CONFIG_MEDIA_TUNER_FC0013=m
+CONFIG_MEDIA_TUNER_TDA18212=m
+CONFIG_MEDIA_TUNER_E4000=m
+CONFIG_MEDIA_TUNER_FC2580=m
+CONFIG_MEDIA_TUNER_TUA9001=m
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV6110x=m
+
+#
+# Multistandard (cable + terrestrial) frontends
+#
+CONFIG_DVB_DRXK=m
+CONFIG_DVB_TDA18271C2DD=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_TDA10071=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRXD=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+CONFIG_DVB_CXD2820R=m
+CONFIG_DVB_RTL2830=m
+CONFIG_DVB_RTL2832=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_LG2160=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_AU8522_DTV=m
+CONFIG_DVB_AU8522_V4L=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_MB86A20S=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_LNBP22=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_A8293=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_IX2505V=m
+CONFIG_DVB_IT913X_FE=m
+CONFIG_DVB_M88RS2000=m
+CONFIG_DVB_AF9033=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CFB_REV_PIXELS_IN_BYTE=y
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_BOTH_ENDIAN=y
+# CONFIG_FB_BIG_ENDIAN is not set
+# CONFIG_FB_LITTLE_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+# CONFIG_FB_WMT_GE_ROPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+CONFIG_FB_DA8XX=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+CONFIG_FB_ST7735=y
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=m
+CONFIG_OMAP2_VRAM_SIZE=0
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
+CONFIG_OMAP2_DSS_DPI=y
+CONFIG_OMAP2_DSS_RFBI=y
+CONFIG_OMAP2_DSS_VENC=y
+CONFIG_OMAP4_DSS_HDMI=y
+CONFIG_OMAP2_DSS_SDI=y
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
+CONFIG_FB_OMAP2=m
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC_DPI=m
+# CONFIG_PANEL_TFP410 is not set
+# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
+CONFIG_PANEL_SHARP_LS037V7DW01=m
+CONFIG_PANEL_NEC_NL8048HL11_01B=m
+# CONFIG_PANEL_PICODLP is not set
+CONFIG_PANEL_TAAL=m
+CONFIG_PANEL_TPO_TD043MTEA1=m
+CONFIG_PANEL_ACX565AKM=m
+# CONFIG_PANEL_N8X0 is not set
+# CONFIG_EXYNOS_VIDEO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+CONFIG_LCD_ILI9320=y
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+# CONFIG_LCD_S6E63M0 is not set
+# CONFIG_LCD_LD9040 is not set
+# CONFIG_LCD_AMS369FG06 is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PWM=y
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
+CONFIG_BACKLIGHT_LM3630=m
+CONFIG_BACKLIGHT_LM3639=m
+# CONFIG_BACKLIGHT_LP855X is not set
+# CONFIG_BACKLIGHT_PANDORA is not set
+CONFIG_BACKLIGHT_TPS65217=y
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_COMPRESS_OFFLOAD=m
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_6FIRE is not set
+CONFIG_SND_SOC=m
+# CONFIG_SND_DESIGNWARE_I2S is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SND_SIMPLE_CARD is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+CONFIG_UHID=m
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+CONFIG_HID_LENOVO_TPKBD=m
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+CONFIG_HID_PS3REMOTE=m
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_HID_SENSOR_HUB=m
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB_ARCH_HAS_XHCI is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+# CONFIG_USB_MUSB_TUSB6010 is not set
+# CONFIG_USB_MUSB_OMAP2PLUS is not set
+# CONFIG_USB_MUSB_AM35X is not set
+CONFIG_USB_MUSB_DSPS=y
+CONFIG_MUSB_PIO_ONLY=y
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_RENESAS_USBHS is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+CONFIG_USB_UAS=y
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_USB_EZUSB_FX2=m
+
+#
+# USB Physical Layer drivers
+#
+CONFIG_OMAP_USB2=y
+CONFIG_USB_ISP1301=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_MV_UDC is not set
+CONFIG_USB_GADGET_MUSB_HDRC=y
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_G_NCM is not set
+CONFIG_USB_GADGETFS=m
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_CDC_COMPOSITE=m
+# CONFIG_USB_G_NOKIA is not set
+# CONFIG_USB_G_ACM_MS is not set
+# CONFIG_USB_G_MULTI is not set
+CONFIG_USB_G_HID=m
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
+# CONFIG_USB_ULPI is not set
+CONFIG_TWL6030_USB=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+CONFIG_LEDS_LM3642=m
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA9633 is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_REGULATOR is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_RENESAS_TPU is not set
+# CONFIG_LEDS_TCA6507 is not set
+CONFIG_LEDS_LM355x=m
+# CONFIG_LEDS_OT200 is not set
+CONFIG_LEDS_BLINKM=m
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_DS2404=m
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SNVS=m
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_DW_DMAC is not set
+# CONFIG_TIMB_DMA is not set
+CONFIG_TI_EDMA=y
+# CONFIG_DMA_OMAP is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+CONFIG_ASYNC_TX_DMA=y
+CONFIG_DMATEST=m
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
+CONFIG_UIO_PDRV_GENIRQ=y
+CONFIG_VIRTIO=m
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_BALLOON is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HWSPINLOCK=m
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_HWSPINLOCK_OMAP=m
+CONFIG_CLKSRC_MMIO=y
+CONFIG_IOMMU_SUPPORT=y
+CONFIG_OF_IOMMU=y
+# CONFIG_OMAP_IOMMU is not set
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+CONFIG_REMOTEPROC=m
+CONFIG_STE_MODEM_RPROC=m
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_KFIFO_BUF=m
+CONFIG_IIO_TRIGGERED_BUFFER=m
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+
+#
+# Accelerometers
+#
+CONFIG_HID_SENSOR_ACCEL_3D=m
+
+#
+# Analog to digital converters
+#
+CONFIG_AD_SIGMA_DELTA=m
+CONFIG_AD7266=m
+CONFIG_AD7791=m
+CONFIG_AD7476=m
+CONFIG_TI_AM335X_ADC=y
+
+#
+# Amplifiers
+#
+# CONFIG_AD8366 is not set
+
+#
+# Light sensors
+#
+CONFIG_ADJD_S311=m
+CONFIG_VCNL4000=m
+CONFIG_HID_SENSOR_ALS=m
+
+#
+# Frequency Synthesizers DDS/PLL
+#
+
+#
+# Clock Generator/Distribution
+#
+CONFIG_AD9523=m
+
+#
+# Phase-Locked Loop (PLL) frequency synthesizers
+#
+CONFIG_ADF4350=m
+
+#
+# Digital to analog converters
+#
+CONFIG_AD5064=m
+CONFIG_AD5360=m
+CONFIG_AD5380=m
+CONFIG_AD5421=m
+CONFIG_AD5624R_SPI=m
+CONFIG_AD5446=m
+CONFIG_AD5504=m
+CONFIG_AD5755=m
+CONFIG_AD5764=m
+CONFIG_AD5791=m
+CONFIG_AD5686=m
+CONFIG_MAX517=m
+CONFIG_MCP4725=m
+
+#
+# Hid Sensor IIO Common
+#
+CONFIG_HID_SENSOR_IIO_COMMON=m
+CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS=m
+
+#
+# Digital gyroscope sensors
+#
+CONFIG_HID_SENSOR_GYRO_3D=m
+
+#
+# Magnetometer sensors
+#
+CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+CONFIG_PWM=y
+CONFIG_PWM_TIECAP=y
+CONFIG_PWM_TIEHRPWM=y
+# CONFIG_PWM_TWL6030 is not set
+CONFIG_EHRPWM_TEST=m
+
+#
+# CAPEBUS support
+#
+CONFIG_CAPEBUS=y
+CONFIG_CAPEBUS_BONE_CONTROLLER=y
+CONFIG_CAPEBUS_BONE_GENERIC=y
+CONFIG_CAPEBUS_BONE_GEIGER=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
+CONFIG_NILFS2_FS=m
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_STAT_FS=y
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_FS_POSIX_ACL=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_SWAP=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_LKDTM is not set
+CONFIG_NOTIFIER_ERROR_INJECTION=m
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
+CONFIG_PM_NOTIFIER_ERROR_INJECT=m
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_KPROBE_EVENT=y
+CONFIG_PROBE_EVENTS=y
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_ARM_KPROBES_TEST is not set
+# CONFIG_PID_IN_CONTEXTIDR is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_SECURITY_YAMA is not set
+# CONFIG_IMA is not set
+# CONFIG_EVM is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_PCRYPT=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA1_ARM is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_ARM=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
+# CONFIG_CRYPTO_DEV_OMAP_AES is not set
+CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_PUBLIC_KEY_ALGO_RSA=m
+CONFIG_X509_CERTIFICATE_PARSER=m
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+CONFIG_CLZ_TAB=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_MPILIB=m
+CONFIG_OID_REGISTRY=m
diff --git a/patches/linux-3.7-rc6/0000-linux-master.patch b/patches/linux-3.7-rc6/0000-linux-master.patch
new file mode 100644
index 0000000..d0fc85b
--- /dev/null
+++ b/patches/linux-3.7-rc6/0000-linux-master.patch
@@ -0,0 +1,503 @@
+diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
+index 1e6956a..14db93e 100644
+--- a/arch/alpha/kernel/osf_sys.c
++++ b/arch/alpha/kernel/osf_sys.c
+@@ -445,7 +445,7 @@ struct procfs_args {
+ * unhappy with OSF UFS. [CHECKME]
+ */
+ static int
+-osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
++osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags)
+ {
+ int retval;
+ struct cdfs_args tmp;
+@@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
+ }
+
+ static int
+-osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
++osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags)
+ {
+ int retval;
+ struct cdfs_args tmp;
+@@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
+ }
+
+ static int
+-osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
++osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags)
+ {
+ struct procfs_args tmp;
+
+diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
+index 67e489d..2df26b5 100644
+--- a/arch/m68k/include/asm/signal.h
++++ b/arch/m68k/include/asm/signal.h
+@@ -41,7 +41,7 @@ struct k_sigaction {
+ static inline void sigaddset(sigset_t *set, int _sig)
+ {
+ asm ("bfset %0{%1,#1}"
+- : "+od" (*set)
++ : "+o" (*set)
+ : "id" ((_sig - 1) ^ 31)
+ : "cc");
+ }
+@@ -49,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig)
+ static inline void sigdelset(sigset_t *set, int _sig)
+ {
+ asm ("bfclr %0{%1,#1}"
+- : "+od" (*set)
++ : "+o" (*set)
+ : "id" ((_sig - 1) ^ 31)
+ : "cc");
+ }
+@@ -65,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
+ int ret;
+ asm ("bfextu %1{%2,#1},%0"
+ : "=d" (ret)
+- : "od" (*set), "id" ((_sig-1) ^ 31)
++ : "o" (*set), "id" ((_sig-1) ^ 31)
+ : "cc");
+ return ret;
+ }
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index b1ae480..b7078af 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev)
+ return 0;
+ }
+
+-#ifdef CONFIG_PM
++#ifdef CONFIG_PM_SLEEP
+ static int ahci_suspend(struct device *dev)
+ {
+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
+diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
+index fd9ecf7..5b0ba3f 100644
+--- a/drivers/ata/libata-acpi.c
++++ b/drivers/ata/libata-acpi.c
+@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
+ struct acpi_device *acpi_dev;
+ struct acpi_device_power_state *states;
+
+- if (ap->flags & ATA_FLAG_ACPI_SATA)
+- ata_dev = &ap->link.device[sdev->channel];
+- else
++ if (ap->flags & ATA_FLAG_ACPI_SATA) {
++ if (!sata_pmp_attached(ap))
++ ata_dev = &ap->link.device[sdev->id];
++ else
++ ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
++ }
++ else {
+ ata_dev = &ap->link.device[sdev->id];
++ }
+
+ *handle = ata_dev_acpi_handle(ata_dev);
+
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index 3cc7096..f46fbd3 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
+
+ if (xfer_mode == t->mode)
+ return t;
++
++ WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
++ __func__, xfer_mode);
++
+ return NULL;
+ }
+
+diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
+index 26201eb..371fd2c 100644
+--- a/drivers/ata/pata_arasan_cf.c
++++ b/drivers/ata/pata_arasan_cf.c
+@@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev)
+ return ret;
+ }
+
++ ret = clk_set_rate(acdev->clk, 166000000);
++ if (ret) {
++ dev_warn(acdev->host->dev, "clock set rate failed");
++ return ret;
++ }
++
+ spin_lock_irqsave(&acdev->host->lock, flags);
+ /* configure CF interface clock */
+ writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
+@@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev)
+ return 0;
+ }
+
+-#ifdef CONFIG_PM
++#ifdef CONFIG_PM_SLEEP
+ static int arasan_cf_suspend(struct device *dev)
+ {
+ struct ata_host *host = dev_get_drvdata(dev);
+diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
+index 0d7c4c2..400bf1c 100644
+--- a/drivers/ata/sata_highbank.c
++++ b/drivers/ata/sata_highbank.c
+@@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, ahci_of_match);
+
+-static int __init ahci_highbank_probe(struct platform_device *pdev)
++static int __devinit ahci_highbank_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct ahci_host_priv *hpriv;
+@@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev)
+ return 0;
+ }
+
+-#ifdef CONFIG_PM
++#ifdef CONFIG_PM_SLEEP
+ static int ahci_highbank_suspend(struct device *dev)
+ {
+ struct ata_host *host = dev_get_drvdata(dev);
+diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
+index 44a4256..08608de 100644
+--- a/drivers/ata/sata_svw.c
++++ b/drivers/ata/sata_svw.c
+@@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,
+ return 0;
+ }
+
++static int k2_sata_softreset(struct ata_link *link,
++ unsigned int *class, unsigned long deadline)
++{
++ u8 dmactl;
++ void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
++
++ dmactl = readb(mmio + ATA_DMA_CMD);
++
++ /* Clear the start bit */
++ if (dmactl & ATA_DMA_START) {
++ dmactl &= ~ATA_DMA_START;
++ writeb(dmactl, mmio + ATA_DMA_CMD);
++ }
++
++ return ata_sff_softreset(link, class, deadline);
++}
++
++static int k2_sata_hardreset(struct ata_link *link,
++ unsigned int *class, unsigned long deadline)
++{
++ u8 dmactl;
++ void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
++
++ dmactl = readb(mmio + ATA_DMA_CMD);
++
++ /* Clear the start bit */
++ if (dmactl & ATA_DMA_START) {
++ dmactl &= ~ATA_DMA_START;
++ writeb(dmactl, mmio + ATA_DMA_CMD);
++ }
++
++ return sata_sff_hardreset(link, class, deadline);
++}
+
+ static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+@@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {
+
+ static struct ata_port_operations k2_sata_ops = {
+ .inherits = &ata_bmdma_port_ops,
++ .softreset = k2_sata_softreset,
++ .hardreset = k2_sata_hardreset,
+ .sff_tf_load = k2_sata_tf_load,
+ .sff_tf_read = k2_sata_tf_read,
+ .sff_check_status = k2_stat_check_status,
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index f11d8e3..47150f5 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -466,7 +466,7 @@ config GPIO_ADP5588_IRQ
+
+ config GPIO_ADNP
+ tristate "Avionic Design N-bit GPIO expander"
+- depends on I2C && OF
++ depends on I2C && OF_GPIO
+ help
+ This option enables support for N GPIOs found on Avionic Design
+ I2C GPIO expanders. The register space will be extended by powers
+diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
+index 0f42518..ce1c847 100644
+--- a/drivers/gpio/gpio-mcp23s08.c
++++ b/drivers/gpio/gpio-mcp23s08.c
+@@ -77,7 +77,7 @@ struct mcp23s08_driver_data {
+
+ /*----------------------------------------------------------------------*/
+
+-#ifdef CONFIG_I2C
++#if IS_ENABLED(CONFIG_I2C)
+
+ static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
+ {
+@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
+ break;
+ #endif /* CONFIG_SPI_MASTER */
+
+-#ifdef CONFIG_I2C
++#if IS_ENABLED(CONFIG_I2C)
+ case MCP_TYPE_008:
+ mcp->ops = &mcp23008_ops;
+ mcp->chip.ngpio = 8;
+@@ -473,7 +473,7 @@ fail:
+
+ /*----------------------------------------------------------------------*/
+
+-#ifdef CONFIG_I2C
++#if IS_ENABLED(CONFIG_I2C)
+
+ static int __devinit mcp230xx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
+index cf7afb9..be65c04 100644
+--- a/drivers/gpio/gpio-mvebu.c
++++ b/drivers/gpio/gpio-mvebu.c
+@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
+ return mvchip->membase + GPIO_OUT_OFF;
+ }
+
++static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
++{
++ return mvchip->membase + GPIO_BLINK_EN_OFF;
++}
++
+ static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
+ {
+ return mvchip->membase + GPIO_IO_CONF_OFF;
+@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
+ return (u >> pin) & 1;
+ }
+
++static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
++{
++ struct mvebu_gpio_chip *mvchip =
++ container_of(chip, struct mvebu_gpio_chip, chip);
++ unsigned long flags;
++ u32 u;
++
++ spin_lock_irqsave(&mvchip->lock, flags);
++ u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
++ if (value)
++ u |= 1 << pin;
++ else
++ u &= ~(1 << pin);
++ writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
++ spin_unlock_irqrestore(&mvchip->lock, flags);
++}
++
+ static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
+ {
+ struct mvebu_gpio_chip *mvchip =
+@@ -244,6 +266,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+ if (ret)
+ return ret;
+
++ mvebu_gpio_blink(chip, pin, 0);
+ mvebu_gpio_set(chip, pin, value);
+
+ spin_lock_irqsave(&mvchip->lock, flags);
+diff --git a/fs/file.c b/fs/file.c
+index 708d997..7cb71b9 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -685,7 +685,6 @@ void do_close_on_exec(struct files_struct *files)
+ struct fdtable *fdt;
+
+ /* exec unshares first */
+- BUG_ON(atomic_read(&files->count) != 1);
+ spin_lock(&files->file_lock);
+ for (i = 0; ; i++) {
+ unsigned long set;
+diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
+index 721d692..6fcaeb8 100644
+--- a/fs/notify/fanotify/fanotify_user.c
++++ b/fs/notify/fanotify/fanotify_user.c
+@@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
+ if (ret)
+ goto out_close_fd;
+
+- fd_install(fd, f);
++ if (fd != FAN_NOFD)
++ fd_install(fd, f);
+ return fanotify_event_metadata.event_len;
+
+ out_close_fd:
+diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
+index e562dd4..e57e2da 100644
+--- a/fs/xfs/xfs_aops.c
++++ b/fs/xfs/xfs_aops.c
+@@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
+ *
+ * The fix is two passes across the ioend list - one to start writeback on the
+ * buffer_heads, and then submit them for I/O on the second pass.
++ *
++ * If @fail is non-zero, it means that we have a situation where some part of
++ * the submission process has failed after we have marked paged for writeback
++ * and unlocked them. In this situation, we need to fail the ioend chain rather
++ * than submit it to IO. This typically only happens on a filesystem shutdown.
+ */
+ STATIC void
+ xfs_submit_ioend(
+ struct writeback_control *wbc,
+- xfs_ioend_t *ioend)
++ xfs_ioend_t *ioend,
++ int fail)
+ {
+ xfs_ioend_t *head = ioend;
+ xfs_ioend_t *next;
+@@ -506,6 +512,18 @@ xfs_submit_ioend(
+ next = ioend->io_list;
+ bio = NULL;
+
++ /*
++ * If we are failing the IO now, just mark the ioend with an
++ * error and finish it. This will run IO completion immediately
++ * as there is only one reference to the ioend at this point in
++ * time.
++ */
++ if (fail) {
++ ioend->io_error = -fail;
++ xfs_finish_ioend(ioend);
++ continue;
++ }
++
+ for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
+
+ if (!bio) {
+@@ -1060,7 +1078,18 @@ xfs_vm_writepage(
+
+ xfs_start_page_writeback(page, 1, count);
+
+- if (ioend && imap_valid) {
++ /* if there is no IO to be submitted for this page, we are done */
++ if (!ioend)
++ return 0;
++
++ ASSERT(iohead);
++
++ /*
++ * Any errors from this point onwards need tobe reported through the IO
++ * completion path as we have marked the initial page as under writeback
++ * and unlocked it.
++ */
++ if (imap_valid) {
+ xfs_off_t end_index;
+
+ end_index = imap.br_startoff + imap.br_blockcount;
+@@ -1079,20 +1108,15 @@ xfs_vm_writepage(
+ wbc, end_index);
+ }
+
+- if (iohead) {
+- /*
+- * Reserve log space if we might write beyond the on-disk
+- * inode size.
+- */
+- if (ioend->io_type != XFS_IO_UNWRITTEN &&
+- xfs_ioend_is_append(ioend)) {
+- err = xfs_setfilesize_trans_alloc(ioend);
+- if (err)
+- goto error;
+- }
+
+- xfs_submit_ioend(wbc, iohead);
+- }
++ /*
++ * Reserve log space if we might write beyond the on-disk inode size.
++ */
++ err = 0;
++ if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
++ err = xfs_setfilesize_trans_alloc(ioend);
++
++ xfs_submit_ioend(wbc, iohead, err);
+
+ return 0;
+
+diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
+index d330111..70eec18 100644
+--- a/fs/xfs/xfs_attr_leaf.c
++++ b/fs/xfs/xfs_attr_leaf.c
+@@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
+ leaf2 = blk2->bp->b_addr;
+ ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+ ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
++ ASSERT(leaf2->hdr.count == 0);
+ args = state->args;
+
+ trace_xfs_attr_leaf_rebalance(args);
+@@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
+ * I assert that since all callers pass in an empty
+ * second buffer, this code should never execute.
+ */
++ ASSERT(0);
+
+ /*
+ * Figure the total bytes to be added to the destination leaf.
+@@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
+ args->index2 = 0;
+ args->blkno2 = blk2->blkno;
+ } else {
++ /*
++ * On a double leaf split, the original attr location
++ * is already stored in blkno2/index2, so don't
++ * overwrite it overwise we corrupt the tree.
++ */
+ blk2->index = blk1->index
+ - be16_to_cpu(leaf1->hdr.count);
+- args->index = args->index2 = blk2->index;
+- args->blkno = args->blkno2 = blk2->blkno;
++ args->index = blk2->index;
++ args->blkno = blk2->blkno;
++ if (!state->extravalid) {
++ /*
++ * set the new attr location to match the old
++ * one and let the higher level split code
++ * decide where in the leaf to place it.
++ */
++ args->index2 = blk2->index;
++ args->blkno2 = blk2->blkno;
++ }
+ }
+ } else {
+ ASSERT(state->inleaf == 1);
+diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
+index 933b793..4b0b8dd 100644
+--- a/fs/xfs/xfs_buf.c
++++ b/fs/xfs/xfs_buf.c
+@@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io(
+ {
+ xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private;
+
+- xfs_buf_ioerror(bp, -error);
++ /*
++ * don't overwrite existing errors - otherwise we can lose errors on
++ * buffers that require multiple bios to complete.
++ */
++ if (!bp->b_error)
++ xfs_buf_ioerror(bp, -error);
+
+- if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
++ if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+ invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
+
+ _xfs_buf_ioend(bp, 1);
+@@ -1279,6 +1284,11 @@ next_chunk:
+ if (size)
+ goto next_chunk;
+ } else {
++ /*
++ * This is guaranteed not to be the last io reference count
++ * because the caller (xfs_buf_iorequest) holds a count itself.
++ */
++ atomic_dec(&bp->b_io_remaining);
+ xfs_buf_ioerror(bp, EIO);
+ bio_put(bio);
+ }
diff --git a/patches/linux-3.7-rc6/0001-video-st7735fb-add-st7735-framebuffer-driver.patch b/patches/linux-3.7-rc6/0001-video-st7735fb-add-st7735-framebuffer-driver.patch
new file mode 100644
index 0000000..70cfb9c
--- /dev/null
+++ b/patches/linux-3.7-rc6/0001-video-st7735fb-add-st7735-framebuffer-driver.patch
@@ -0,0 +1,800 @@
+From f24d7d872ab89aa8aec4ea0bf36c1c612906907b Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Tue, 11 Sep 2012 15:30:10 -0400
+Subject: [PATCH] video: st7735fb: add st7735 framebuffer driver
+
+Add driver for the SPI-connected ST7735 display controller.
+This driver requires that the platform support DT booting.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ .../devicetree/bindings/vendor-prefixes.txt | 2 +
+ drivers/video/Kconfig | 11 +
+ drivers/video/Makefile | 1 +
+ drivers/video/st7735fb.c | 631 ++++++++++++++++++++
+ drivers/video/st7735fb.h | 84 +++
+ 5 files changed, 729 insertions(+)
+ create mode 100644 drivers/video/st7735fb.c
+ create mode 100644 drivers/video/st7735fb.h
+
+diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
+index 9de2b9f..54463a7 100644
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -4,6 +4,7 @@ This isn't an exhaustive list, but you should add new prefixes to it before
+ using them to avoid name-space collisions.
+
+ ad Avionic Design GmbH
++adafruit Adafruit Industries
+ adi Analog Devices, Inc.
+ amcc Applied Micro Circuits Corporation (APM, formally AMCC)
+ apm Applied Micro Circuits Corporation (APM)
+@@ -45,6 +46,7 @@ schindler Schindler
+ sil Silicon Image
+ simtek
+ sirf SiRF Technology, Inc.
++sitronix Sitronix Technology Corp.
+ st STMicroelectronics
+ stericsson ST-Ericsson
+ ti Texas Instruments
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index d08d799..9791d10 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2417,6 +2417,17 @@ config FB_PUV3_UNIGFX
+ Choose this option if you want to use the Unigfx device as a
+ framebuffer device. Without the support of PCI & AGP.
+
++config FB_ST7735
++ tristate "ST7735 framebuffer support"
++ depends on FB && SPI
++ select FB_SYS_FILLRECT
++ select FB_SYS_COPYAREA
++ select FB_SYS_IMAGEBLIT
++ select FB_SYS_FOPS
++ select FB_DEFERRED_IO
++ help
++ Framebuffer support for the ST7735 display controller in SPI mode.
++
+ source "drivers/video/omap/Kconfig"
+ source "drivers/video/omap2/Kconfig"
+ source "drivers/video/exynos/Kconfig"
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 23e948e..0e13296 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -146,6 +146,7 @@ obj-$(CONFIG_FB_MSM) += msm/
+ obj-$(CONFIG_FB_NUC900) += nuc900fb.o
+ obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
+ obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
++obj-$(CONFIG_FB_ST7735) += st7735fb.o
+
+ # Platform or fallback drivers go here
+ obj-$(CONFIG_FB_UVESA) += uvesafb.o
+diff --git a/drivers/video/st7735fb.c b/drivers/video/st7735fb.c
+new file mode 100644
+index 0000000..67c2544
+--- /dev/null
++++ b/drivers/video/st7735fb.c
+@@ -0,0 +1,631 @@
++/*
++ * linux/drivers/video/st7735fb.c -- FB driver for ST7735 LCD controller
++ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
++ *
++ * Copyright (C) 2012, Matt Porter <matt@ohporter.com>
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/fb.h>
++#include <linux/gpio.h>
++#include <linux/spi/spi.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/uaccess.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++
++#include "st7735fb.h"
++
++static struct st7735_function st7735_cfg_script[] = {
++ { ST7735_START, ST7735_START},
++ { ST7735_CMD, ST7735_SWRESET},
++ { ST7735_DELAY, 150},
++ { ST7735_CMD, ST7735_SLPOUT},
++ { ST7735_DELAY, 500},
++ { ST7735_CMD, ST7735_FRMCTR1},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_CMD, ST7735_FRMCTR2},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_CMD, ST7735_FRMCTR3},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_CMD, ST7735_INVCTR},
++ { ST7735_DATA, 0x07},
++ { ST7735_CMD, ST7735_PWCTR1},
++ { ST7735_DATA, 0xa2},
++ { ST7735_DATA, 0x02},
++ { ST7735_DATA, 0x84},
++ { ST7735_CMD, ST7735_PWCTR2},
++ { ST7735_DATA, 0xc5},
++ { ST7735_CMD, ST7735_PWCTR3},
++ { ST7735_DATA, 0x0a},
++ { ST7735_DATA, 0x00},
++ { ST7735_CMD, ST7735_PWCTR4},
++ { ST7735_DATA, 0x8a},
++ { ST7735_DATA, 0x2a},
++ { ST7735_CMD, ST7735_PWCTR5},
++ { ST7735_DATA, 0x8a},
++ { ST7735_DATA, 0xee},
++ { ST7735_CMD, ST7735_VMCTR1},
++ { ST7735_DATA, 0x0e},
++ { ST7735_CMD, ST7735_INVOFF},
++ { ST7735_CMD, ST7735_MADCTL},
++ { ST7735_DATA, 0xc8},
++ { ST7735_CMD, ST7735_COLMOD},
++ { ST7735_DATA, 0x05},
++ { ST7735_CMD, ST7735_CASET},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x7f},
++ { ST7735_CMD, ST7735_RASET},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x9f},
++ { ST7735_CMD, ST7735_GMCTRP1},
++ { ST7735_DATA, 0x02},
++ { ST7735_DATA, 0x1c},
++ { ST7735_DATA, 0x07},
++ { ST7735_DATA, 0x12},
++ { ST7735_DATA, 0x37},
++ { ST7735_DATA, 0x32},
++ { ST7735_DATA, 0x29},
++ { ST7735_DATA, 0x2d},
++ { ST7735_DATA, 0x29},
++ { ST7735_DATA, 0x25},
++ { ST7735_DATA, 0x2b},
++ { ST7735_DATA, 0x39},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x03},
++ { ST7735_DATA, 0x10},
++ { ST7735_CMD, ST7735_GMCTRN1},
++ { ST7735_DATA, 0x03},
++ { ST7735_DATA, 0x1d},
++ { ST7735_DATA, 0x07},
++ { ST7735_DATA, 0x06},
++ { ST7735_DATA, 0x2e},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x29},
++ { ST7735_DATA, 0x2d},
++ { ST7735_DATA, 0x2e},
++ { ST7735_DATA, 0x2e},
++ { ST7735_DATA, 0x37},
++ { ST7735_DATA, 0x3f},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x02},
++ { ST7735_DATA, 0x10},
++ { ST7735_CMD, ST7735_DISPON},
++ { ST7735_DELAY, 100},
++ { ST7735_CMD, ST7735_NORON},
++ { ST7735_DELAY, 10},
++ { ST7735_END, ST7735_END},
++};
++
++static struct fb_fix_screeninfo st7735fb_fix __devinitdata = {
++ .id = "ST7735",
++ .type = FB_TYPE_PACKED_PIXELS,
++ .visual = FB_VISUAL_DIRECTCOLOR,
++ .xpanstep = 0,
++ .ypanstep = 0,
++ .ywrapstep = 0,
++ .line_length = WIDTH*BPP/8,
++ .accel = FB_ACCEL_NONE,
++};
++
++static struct fb_var_screeninfo st7735fb_var __devinitdata = {
++ .xres = WIDTH,
++ .yres = HEIGHT,
++ .xres_virtual = WIDTH,
++ .yres_virtual = HEIGHT,
++ .bits_per_pixel = BPP,
++ .nonstd = 0,
++};
++
++static int st7735_write(struct st7735fb_par *par, u8 data)
++{
++ par->buf[0] = data;
++
++ return spi_write(par->spi, par->buf, 1);
++}
++
++static void st7735_write_data(struct st7735fb_par *par, u8 data)
++{
++ int ret = 0;
++
++ /* Set data mode */
++ gpio_set_value(par->dc, 1);
++
++ ret = st7735_write(par, data);
++ if (ret < 0)
++ pr_err("%s: write data %02x failed with status %d\n",
++ par->info->fix.id, data, ret);
++}
++
++static int st7735_write_data_buf(struct st7735fb_par *par,
++ u8 *txbuf, int size)
++{
++ /* Set data mode */
++ gpio_set_value(par->dc, 1);
++
++ /* Write entire buffer */
++ return spi_write(par->spi, txbuf, size);
++}
++
++static void st7735_write_cmd(struct st7735fb_par *par, u8 data)
++{
++ int ret = 0;
++
++ /* Set command mode */
++ gpio_set_value(par->dc, 0);
++
++ ret = st7735_write(par, data);
++ if (ret < 0)
++ pr_err("%s: write command %02x failed with status %d\n",
++ par->info->fix.id, data, ret);
++}
++
++static void st7735_run_cfg_script(struct st7735fb_par *par)
++{
++ int i = 0;
++ int end_script = 0;
++
++ do {
++ switch (st7735_cfg_script[i].cmd)
++ {
++ case ST7735_START:
++ break;
++ case ST7735_CMD:
++ st7735_write_cmd(par,
++ st7735_cfg_script[i].data & 0xff);
++ break;
++ case ST7735_DATA:
++ st7735_write_data(par,
++ st7735_cfg_script[i].data & 0xff);
++ break;
++ case ST7735_DELAY:
++ mdelay(st7735_cfg_script[i].data);
++ break;
++ case ST7735_END:
++ end_script = 1;
++ }
++ i++;
++ } while (!end_script);
++}
++
++static void st7735_set_addr_win(struct st7735fb_par *par,
++ int xs, int ys, int xe, int ye)
++{
++ st7735_write_cmd(par, ST7735_CASET);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, xs + par->xoff);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, xe + par->xoff);
++ st7735_write_cmd(par, ST7735_RASET);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, ys + par->yoff);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, ye + par->yoff);
++}
++
++static void st7735_reset(struct st7735fb_par *par)
++{
++ /* Reset controller */
++ gpio_set_value(par->rst, 0);
++ udelay(10);
++ gpio_set_value(par->rst, 1);
++ mdelay(120);
++}
++
++static void st7735fb_update_display(struct st7735fb_par *par)
++{
++ int ret = 0;
++ u16 *vmem;
++#ifdef __LITTLE_ENDIAN
++ int i;
++ u16 *vmem16 = (u16 *)par->info->screen_base;
++ vmem = par->ssbuf;
++
++ for (i=0; i<WIDTH*HEIGHT*BPP/8/2; i++)
++ vmem[i] = swab16(vmem16[i]);
++#else
++ vmem = (u16 *)par->info->screen_base;
++#endif
++
++ mutex_lock(&(par->io_lock));
++
++ /* Set row/column data window */
++ st7735_set_addr_win(par, 0, 0, WIDTH-1, HEIGHT-1);
++
++ /* Internal RAM write command */
++ st7735_write_cmd(par, ST7735_RAMWR);
++
++ /* Blast framebuffer to ST7735 internal display RAM */
++ ret = st7735_write_data_buf(par, (u8 *)vmem, WIDTH*HEIGHT*BPP/8);
++ if (ret < 0)
++ pr_err("%s: spi_write failed to update display buffer\n",
++ par->info->fix.id);
++
++ mutex_unlock(&(par->io_lock));
++}
++
++static int st7735fb_init_display(struct st7735fb_par *par)
++{
++ int ret = 0;
++
++ /* Request GPIOs and initialize to default values */
++ ret = gpio_request_one(par->rst, GPIOF_OUT_INIT_HIGH,
++ "ST7735 Reset Pin");
++ if (ret < 0) {
++ pr_err("%s: failed to claim reset pin\n", par->info->fix.id);
++ goto out;
++ }
++ ret = gpio_request_one(par->dc, GPIOF_OUT_INIT_LOW,
++ "ST7735 Data/Command Pin");
++ if (ret < 0) {
++ pr_err("%s: failed to claim data/command pin\n", par->info->fix.id);
++ goto out;
++ }
++
++ st7735_reset(par);
++
++ st7735_run_cfg_script(par);
++
++out:
++ return ret;
++}
++
++static void st7735fb_deferred_io(struct fb_info *info,
++ struct list_head *pagelist)
++{
++ st7735fb_update_display(info->par);
++}
++
++static void st7735fb_update_display_deferred(struct fb_info *info)
++{
++ struct fb_deferred_io *fbdefio = info->fbdefio;
++
++ schedule_delayed_work(&info->deferred_work, fbdefio->delay);
++}
++
++static void st7735fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
++{
++ sys_fillrect(info, rect);
++
++ st7735fb_update_display_deferred(info);
++}
++
++static void st7735fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
++{
++ sys_copyarea(info, area);
++
++ st7735fb_update_display_deferred(info);
++}
++
++static void st7735fb_imageblit(struct fb_info *info, const struct fb_image *image)
++{
++ sys_imageblit(info, image);
++
++ st7735fb_update_display_deferred(info);
++}
++
++static ssize_t st7735fb_write(struct fb_info *info, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ unsigned long p = *ppos;
++ void *dst;
++ int err = 0;
++ unsigned long total_size;
++
++ if (info->state != FBINFO_STATE_RUNNING)
++ return -EPERM;
++
++ total_size = info->fix.smem_len;
++
++ if (p > total_size)
++ return -EFBIG;
++
++ if (count > total_size) {
++ err = -EFBIG;
++ count = total_size;
++ }
++
++ if (count + p > total_size) {
++ if (!err)
++ err = -ENOSPC;
++
++ count = total_size - p;
++ }
++
++ dst = (void __force *) (info->screen_base + p);
++
++ if (copy_from_user(dst, buf, count))
++ err = -EFAULT;
++
++ if (!err)
++ *ppos += count;
++
++ st7735fb_update_display_deferred(info);
++
++ return (err) ? err : count;
++}
++
++static int st7735fb_setcolreg(unsigned regno, unsigned red, unsigned green,
++ unsigned blue, unsigned transp,
++ struct fb_info *info)
++{
++ if (regno >= MAX_PALETTE)
++ return -EINVAL;
++
++ /* RGB565 */
++ ((u32*)(info->pseudo_palette))[regno] =
++ ((red & 0xf800) |
++ ((green & 0xfc00) >> 5) |
++ ((blue & 0xf800) >> 11));
++
++ return 0;
++}
++
++static struct fb_ops st7735fb_ops = {
++ .owner = THIS_MODULE,
++ .fb_read = fb_sys_read,
++ .fb_write = st7735fb_write,
++ .fb_fillrect = st7735fb_fillrect,
++ .fb_copyarea = st7735fb_copyarea,
++ .fb_imageblit = st7735fb_imageblit,
++ .fb_setcolreg = st7735fb_setcolreg,
++};
++
++static struct fb_deferred_io st7735fb_defio = {
++ .delay = HZ/20,
++ .deferred_io = st7735fb_deferred_io,
++};
++
++static const struct spi_device_id st7735fb_device_id[] = {
++ {
++ .name = "tft-lcd-1.8-green",
++ .driver_data = ST7735_AF_TFT18_GREEN,
++ }, {
++ .name = "tft-lcd-1.8-red",
++ .driver_data = ST7735_AF_TFT18_RED,
++ }, {
++ /* sentinel */
++ }
++};
++MODULE_DEVICE_TABLE(spi, st7735fb_device_id);
++
++static const struct of_device_id st7735fb_dt_ids[] = {
++ { .compatible = "adafruit,tft-lcd-1.8-green", .data = (void *) ST7735_AF_TFT18_GREEN, },
++ { .compatible = "adafruit,tft-lcd-1.8-red", .data = (void *) ST7735_AF_TFT18_RED, },
++};
++MODULE_DEVICE_TABLE(of, st7735fb_dt_ids);
++
++static int __devinit st7735fb_probe (struct spi_device *spi)
++{
++ int vmem_size = WIDTH*HEIGHT*BPP/8;
++ u8 *vmem;
++ struct fb_info *info;
++ struct st7735fb_par *par;
++ int retval = -ENOMEM;
++ struct device_node *np = spi->dev.of_node;
++ const struct spi_device_id *spi_id = spi_get_device_id(spi);
++ struct pinctrl *pinctrl;
++
++ if (!spi_id) {
++ dev_err(&spi->dev,
++ "device id not supported!\n");
++ return -EINVAL;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&spi->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&spi->dev,
++ "pins are not configured from the driver\n");
++
++#ifdef __LITTLE_ENDIAN
++ vmem = (u8 *)vmalloc(vmem_size);
++#else
++ vmem = (u8 *)kmalloc(vmem_size, GFP_KERNEL);
++#endif
++ if (!vmem)
++ return retval;
++
++ info = framebuffer_alloc(sizeof(struct st7735fb_par), &spi->dev);
++ if (!info)
++ goto fballoc_fail;
++
++ info->pseudo_palette = kmalloc(sizeof(u32)*MAX_PALETTE, GFP_KERNEL);
++ if (!info->pseudo_palette) {
++ goto palette_fail;
++ }
++
++ info->screen_base = (u8 __force __iomem *)vmem;
++ info->fbops = &st7735fb_ops;
++ info->fix = st7735fb_fix;
++ info->fix.smem_len = vmem_size;
++ info->var = st7735fb_var;
++ /* Choose any packed pixel format as long as it's RGB565 */
++ info->var.red.offset = 11;
++ info->var.red.length = 5;
++ info->var.green.offset = 5;
++ info->var.green.length = 6;
++ info->var.blue.offset = 0;
++ info->var.blue.length = 5;
++ info->var.transp.offset = 0;
++ info->var.transp.length = 0;
++ info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
++
++ info->fbdefio = &st7735fb_defio;
++ fb_deferred_io_init(info);
++
++ retval = fb_alloc_cmap(&info->cmap, MAX_PALETTE, 0);
++ if (retval < 0)
++ goto cmap_fail;
++ info->cmap.len = MAX_PALETTE;
++
++ par = info->par;
++ par->info = info;
++ par->spi = spi;
++
++ mutex_init(&par->io_lock);
++
++ if (spi_id->driver_data == ST7735_AF_TFT18_GREEN) {
++ par->xoff = 2;
++ par->yoff = 1;
++ } else {
++ par->xoff = 0;
++ par->yoff = 0;
++ }
++
++ /* TODO: fix all exit paths for cleanup */
++ par->rst = of_get_named_gpio(np, "st7735-rst", 0);
++ if (par->rst < 0) {
++ printk("failed to find st7735-rst node!\n");
++ return -EINVAL;
++ }
++
++ par->dc = of_get_named_gpio(np, "st7735-dc", 0);
++ if (par->dc < 0) {
++ printk("failed to find st7735-dc node!\n");
++ return -EINVAL;
++ }
++
++ par->buf = kmalloc(1, GFP_KERNEL);
++ if (!par->buf) {
++ retval = -ENOMEM;
++ goto buf_fail;
++ }
++
++#ifdef __LITTLE_ENDIAN
++ /* Allocated swapped shadow buffer */
++ par->ssbuf = kmalloc(vmem_size, GFP_KERNEL);
++ if (!par->ssbuf) {
++ retval = -ENOMEM;
++ goto ssbuf_fail;
++ }
++#endif
++
++ retval = st7735fb_init_display(par);
++ if (retval < 0)
++ goto init_fail;
++
++ retval = register_framebuffer(info);
++ if (retval < 0)
++ goto fbreg_fail;
++
++ spi_set_drvdata(spi, info);
++
++ printk(KERN_INFO
++ "fb%d: %s frame buffer device,\n\tusing %d KiB of video memory\n",
++ info->node, info->fix.id, vmem_size);
++
++ return 0;
++
++
++ spi_set_drvdata(spi, NULL);
++
++fbreg_fail:
++ /* TODO: release gpios on fail */
++ /* TODO: and unwind everything in init */
++
++init_fail:
++#ifdef __LITTLE_ENDIAN
++ kfree(par->ssbuf);
++#endif
++
++ssbuf_fail:
++ kfree(par->buf);
++
++buf_fail:
++ fb_dealloc_cmap(&info->cmap);
++
++cmap_fail:
++ kfree(info->pseudo_palette);
++
++palette_fail:
++ framebuffer_release(info);
++
++fballoc_fail:
++#ifdef __LITTLE_ENDIAN
++ vfree(vmem);
++#else
++ kfree(vmem);
++#endif
++
++ return retval;
++}
++
++static int __devexit st7735fb_remove(struct spi_device *spi)
++{
++ struct fb_info *info = spi_get_drvdata(spi);
++
++ spi_set_drvdata(spi, NULL);
++
++ if (info) {
++ unregister_framebuffer(info);
++ fb_dealloc_cmap(&info->cmap);
++ kfree(info->pseudo_palette);
++ vfree(info->screen_base);
++ framebuffer_release(info);
++ }
++
++ /* TODO: release gpios */
++
++ return 0;
++}
++
++static struct spi_driver st7735fb_driver = {
++ .id_table = st7735fb_device_id,
++ .driver = {
++ .name = "st7735",
++ .owner = THIS_MODULE,
++ .of_match_table = st7735fb_dt_ids,
++ },
++ .probe = st7735fb_probe,
++ .remove = __devexit_p(st7735fb_remove),
++};
++
++static int __init st7735fb_init(void)
++{
++ return spi_register_driver(&st7735fb_driver);
++}
++
++static void __exit st7735fb_exit(void)
++{
++ spi_unregister_driver(&st7735fb_driver);
++}
++
++/* ------------------------------------------------------------------------- */
++
++module_init(st7735fb_init);
++module_exit(st7735fb_exit);
++
++MODULE_DESCRIPTION("FB driver for ST7735 display controller");
++MODULE_AUTHOR("Matt Porter <matt@ohporter.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/st7735fb.h b/drivers/video/st7735fb.h
+new file mode 100644
+index 0000000..0ce5c11
+--- /dev/null
++++ b/drivers/video/st7735fb.h
+@@ -0,0 +1,84 @@
++/*
++ * linux/include/video/st7735fb.h -- FB driver for ST7735 LCD controller
++ *
++ * Copyright (C) 2012, Matt Porter
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#define DRVNAME "st7735fb"
++#define WIDTH 128
++#define HEIGHT 160
++#define BPP 16
++#define MAX_PALETTE 16
++
++/* Supported display modules */
++#define ST7735_AF_TFT18_GREEN 0 /* Adafruit SPI TFT 1.8" - green tab */
++#define ST7735_AF_TFT18_RED 1 /* Adafruit SPI TFT 1.8" - red tab */
++
++/* Init script function */
++struct st7735_function {
++ u16 cmd;
++ u16 data;
++};
++
++/* Init script commands */
++enum st7735_cmd {
++ ST7735_START,
++ ST7735_END,
++ ST7735_CMD,
++ ST7735_DATA,
++ ST7735_DELAY
++};
++
++struct st7735fb_par {
++ struct spi_device *spi;
++ struct fb_info *info;
++ struct mutex io_lock;
++ int xoff;
++ int yoff;
++ int rst;
++ int dc;
++ u16 *ssbuf;
++ u8 *buf;
++};
++
++/* ST7735 Commands */
++#define ST7735_NOP 0x0
++#define ST7735_SWRESET 0x01
++#define ST7735_RDDID 0x04
++#define ST7735_RDDST 0x09
++#define ST7735_SLPIN 0x10
++#define ST7735_SLPOUT 0x11
++#define ST7735_PTLON 0x12
++#define ST7735_NORON 0x13
++#define ST7735_INVOFF 0x20
++#define ST7735_INVON 0x21
++#define ST7735_DISPOFF 0x28
++#define ST7735_DISPON 0x29
++#define ST7735_CASET 0x2A
++#define ST7735_RASET 0x2B
++#define ST7735_RAMWR 0x2C
++#define ST7735_RAMRD 0x2E
++#define ST7735_COLMOD 0x3A
++#define ST7735_MADCTL 0x36
++#define ST7735_FRMCTR1 0xB1
++#define ST7735_FRMCTR2 0xB2
++#define ST7735_FRMCTR3 0xB3
++#define ST7735_INVCTR 0xB4
++#define ST7735_DISSET5 0xB6
++#define ST7735_PWCTR1 0xC0
++#define ST7735_PWCTR2 0xC1
++#define ST7735_PWCTR3 0xC2
++#define ST7735_PWCTR4 0xC3
++#define ST7735_PWCTR5 0xC4
++#define ST7735_VMCTR1 0xC5
++#define ST7735_RDID1 0xDA
++#define ST7735_RDID2 0xDB
++#define ST7735_RDID3 0xDC
++#define ST7735_RDID4 0xDD
++#define ST7735_GMCTRP1 0xE0
++#define ST7735_GMCTRN1 0xE1
++#define ST7735_PWCTR6 0xFC
diff --git a/patches/linux-3.7-rc6/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch b/patches/linux-3.7-rc6/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch
new file mode 100644
index 0000000..d96dd9b
--- /dev/null
+++ b/patches/linux-3.7-rc6/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch
@@ -0,0 +1,41 @@
+From 99ab21ddea0d88d7d60a2210c0aa7c582571fb5b Mon Sep 17 00:00:00 2001
+From: "AnilKumar, Chimata" <anilkumar@ti.com>
+Date: Mon, 15 Oct 2012 12:15:58 +0000
+Subject: [PATCH] regulator: tps65910: fix BUG_ON() shown with vrtc regulator
+
+Fix BUG_ON() error if tps65910 VRTC regulator is used with out
+rdev->desc->volt_table data. Recent changes in regulator core driver
+which add support for "regulator_list_voltage_table" have BUG_ON() if
+regulator descriptor do not voltage table information. This patch adds
+the voltage table information to fix the issue.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ drivers/regulator/tps65910-regulator.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
+index 793adda..1d2dd18 100644
+--- a/drivers/regulator/tps65910-regulator.c
++++ b/drivers/regulator/tps65910-regulator.c
+@@ -38,6 +38,11 @@ static const unsigned int VIO_VSEL_table[] = {
+
+ /* VSEL tables for TPS65910 specific LDOs and dcdc's */
+
++/* supported VRTC voltages in microvolts */
++static const unsigned int VRTC_VSEL_table[] = {
++ 1800000,
++};
++
+ /* supported VDD3 voltages in microvolts */
+ static const unsigned int VDD3_VSEL_table[] = {
+ 5000000,
+@@ -95,6 +100,8 @@ static struct tps_info tps65910_regs[] = {
+ {
+ .name = "vrtc",
+ .vin_name = "vcc7",
++ .n_voltages = ARRAY_SIZE(VRTC_VSEL_table),
++ .voltage_table = VRTC_VSEL_table,
+ .enable_time_us = 2200,
+ },
+ {
diff --git a/patches/linux-3.7-rc6/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch b/patches/linux-3.7-rc6/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
new file mode 100644
index 0000000..78b2693
--- /dev/null
+++ b/patches/linux-3.7-rc6/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
@@ -0,0 +1,94 @@
+From 510f4fd7a8ba825a4b376c27ba86fa5b976fb974 Mon Sep 17 00:00:00 2001
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Fri, 14 Sep 2012 17:41:57 -0500
+Subject: [PATCH] dmaengine: add helper function to request a slave DMA
+ channel
+
+Currently slave DMA channels are requested by calling dma_request_channel()
+and requires DMA clients to pass various filter parameters to obtain the
+appropriate channel.
+
+With device-tree being used by architectures such as arm and the addition of
+device-tree helper functions to extract the relevant DMA client information
+from device-tree, add a new function to request a slave DMA channel using
+device-tree. This function is currently a simple wrapper that calls the
+device-tree of_dma_request_slave_channel() function.
+
+Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
+Cc: Benoit Cousson <b-cousson@ti.com>
+Cc: Stephen Warren <swarren@nvidia.com>
+Cc: Grant Likely <grant.likely@secretlab.ca>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Rob Herring <rob.herring@calxeda.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Vinod Koul <vinod.koul@intel.com>
+Cc: Dan Williams <djbw@fb.com>
+
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Reviewed-by: Stephen Warren <swarren@wwwdotorg.org>
+Acked-by: Rob Herring <rob.herring@calxeda.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ drivers/dma/dmaengine.c | 16 ++++++++++++++++
+ include/linux/dmaengine.h | 6 ++++++
+ 2 files changed, 22 insertions(+)
+
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index a815d44..d37cf95 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -62,6 +62,7 @@
+ #include <linux/rculist.h>
+ #include <linux/idr.h>
+ #include <linux/slab.h>
++#include <linux/of_dma.h>
+
+ static DEFINE_MUTEX(dma_list_mutex);
+ static DEFINE_IDR(dma_idr);
+@@ -546,6 +547,21 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
+ }
+ EXPORT_SYMBOL_GPL(__dma_request_channel);
+
++/**
++ * dma_request_slave_channel - try to allocate an exclusive slave channel
++ * @dev: pointer to client device structure
++ * @name: slave channel name
++ */
++struct dma_chan *dma_request_slave_channel(struct device *dev, char *name)
++{
++ /* If device-tree is present get slave info from here */
++ if (dev->of_node)
++ return of_dma_request_slave_channel(dev->of_node, name);
++
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(dma_request_slave_channel);
++
+ void dma_release_channel(struct dma_chan *chan)
+ {
+ mutex_lock(&dma_list_mutex);
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index d3201e4..8cd0e25 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -974,6 +974,7 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
+ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
+ void dma_issue_pending_all(void);
+ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
++struct dma_chan *dma_request_slave_channel(struct device *dev, char *name);
+ void dma_release_channel(struct dma_chan *chan);
+ #else
+ static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+@@ -988,6 +989,11 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+ {
+ return NULL;
+ }
++static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
++ char *name)
++{
++ return NULL
++}
+ static inline void dma_release_channel(struct dma_chan *chan)
+ {
+ }
diff --git a/patches/linux-3.7-rc6/0004-of-Add-generic-device-tree-DMA-helpers.patch b/patches/linux-3.7-rc6/0004-of-Add-generic-device-tree-DMA-helpers.patch
new file mode 100644
index 0000000..fb08560
--- /dev/null
+++ b/patches/linux-3.7-rc6/0004-of-Add-generic-device-tree-DMA-helpers.patch
@@ -0,0 +1,533 @@
+From 21793273a36ca45c4162f41978a3ec8eb1984c42 Mon Sep 17 00:00:00 2001
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Fri, 14 Sep 2012 17:41:56 -0500
+Subject: [PATCH] of: Add generic device tree DMA helpers
+
+This is based upon the work by Benoit Cousson [1] and Nicolas Ferre [2]
+to add some basic helpers to retrieve a DMA controller device_node and the
+DMA request/channel information.
+
+Aim of DMA helpers
+- The purpose of device-tree is to describe the capabilites of the hardware.
+ Thinking about DMA controllers purely from the context of the hardware to
+ begin with, we can describe a device in terms of a DMA controller as
+ follows ...
+ 1. Number of DMA controllers
+ 2. Number of channels (maybe physical or logical)
+ 3. Mapping of DMA requests signals to DMA controller
+ 4. Number of DMA interrupts
+ 5. Mapping of DMA interrupts to channels
+- With the above in mind the aim of the DT DMA helper functions is to extract
+ the above information from the DT and provide to the appropriate driver.
+ However, due to the vast number of DMA controllers and not all are using a
+ common driver (such as DMA Engine) it has been seen that this is not a
+ trivial task. In previous discussions on this topic the following concerns
+ have been raised ...
+ 1. How does the binding support devices with multiple DMA controllers?
+ 2. How to support both legacy DMA controllers not using DMA Engine as
+ well as those that support DMA Engine.
+ 3. When using with DMA Engine how do we support the various
+ implementations where the opaque filter function parameter differs
+ between implementations?
+ 4. How do we handle DMA channels that are identified with a string
+ versus a integer?
+- Hence the design of the DMA helpers has to accomodate the above or align on
+ an agreement what can be or should be supported.
+
+Design of DMA helpers
+
+1. Registering DMA controllers
+
+ In the case of DMA controllers that are using DMA Engine, requesting a
+ channel is performed by calling the following function.
+
+ struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+ dma_filter_fn filter_fn,
+ void *filter_param);
+
+ The mask variable is used to match a type of the device controller in a list
+ of controllers. The filter_fn and filter_param are used to identify the
+ required dma channel and return a handle to the dma channel of type dma_chan.
+
+ From the examples I have seen, the mask and filter_fn are constant
+ for a given DMA controller and therefore, we can specify these as controller
+ specific data when registering the DMA controller with the device-tree DMA
+ helpers.
+
+ The filter_param variable is of an unknown type and is typically specific
+ to the DMA engine implementation for a given DMA controller. To allow some
+ flexibility in the type and formating of this filter_param we employ an
+ xlate to translate the device-tree binding information into the appropriate
+ format. The xlate function used for a DMA controller can also be specified
+ when registering the DMA controller with the device-tree DMA helpers.
+
+ Based upon the above, a function for registering the DMA controller with the
+ DMA helpers now looks like the below. The data variable is used to pass a
+ pointer to DMA controller specific data used by the xlate function.
+
+ int of_dma_controller_register(struct device_node *np,
+ struct dma_chan *(*of_dma_xlate)
+ (struct of_phandle_args *, struct of_dma *),
+ void *data)
+
+ For example, in the case where DMA engine is used, we define the following
+ structure (that stores the DMA engine capability mask and filter function)
+ and pass this to the data variable in the above function.
+
+ struct of_dma_filter_info {
+ dma_cap_mask_t dma_cap;
+ dma_filter_fn filter_fn;
+ };
+
+2. Representing and requesting channel information
+
+ Please see the dma binding documentation included in this patch for a
+ description of how DMA controllers and client information should be
+ represented with device-tree. For more information on how this binding
+ came about please see [3]. In addition to this, feedback received from
+ the Linux kernel summit showed a consensus (among those who attended) to
+ use a name to identify DMA client information [4].
+
+ A DMA channel can be requested by calling the following function, where name
+ is a required parameter used for identifying a DMA channel. This function
+ has been designed to return a structure of type dma_chan to work with the
+ DMA engine driver. Note that if DMA engine is used then drivers should be
+ using the DMA engine API dma_request_slave_channel() (implemented in part 2
+ of this series, "dmaengine: add helper function to request a slave DMA
+ channel") which will in turn call the below function if device-tree is
+ present. The aim being to have a common DMA engine interface regardless of
+ whether device tree is being used.
+
+ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
+ char *name)
+
+3. Supporting legacy devices not using DMA Engine
+
+ These devices present a problem, as there may not be a uniform way to easily
+ support them with regard to device tree. Ideally, these should be migrated
+ to DMA engine. However, if this is not possible, then they should still be
+ able to use this binding, the only constaint imposed by this implementation
+ is that when requesting a DMA channel via of_dma_request_slave_channel(), it
+ will return a type of dma_chan.
+
+This implementation has been tested on OMAP4430 using the kernel v3.6-rc5. I
+have validated that MMC is working on the PANDA board with this implementation.
+My development branch for testing on OMAP can be found here [5].
+
+v6: - minor corrections in DMA binding documentation
+v5: - minor update to binding documentation
+ - added loop to exhaustively search for a slave channel in the case where
+ there could be alternative channels available
+v4: - revert the removal of xlate function from v3
+ - update the proposed binding format and APIs based upon discussions [3]
+v3: - avoid passing an xlate function and instead pass DMA engine parameters
+ - define number of dma channels and requests in dma-controller node
+v2: - remove of_dma_to_resource API
+ - make property #dma-cells required (no fallback anymore)
+ - another check in of_dma_xlate_onenumbercell() function
+
+[1] http://article.gmane.org/gmane.linux.drivers.devicetree/12022
+[2] http://article.gmane.org/gmane.linux.ports.arm.omap/73622
+[3] http://marc.info/?l=linux-omap&m=133582085008539&w=2
+[4] http://pad.linaro.org/arm-mini-summit-2012
+[5] https://github.com/jonhunter/linux/tree/dev-dt-dma
+
+Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
+Cc: Benoit Cousson <b-cousson@ti.com>
+Cc: Stephen Warren <swarren@nvidia.com>
+Cc: Grant Likely <grant.likely@secretlab.ca>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Rob Herring <rob.herring@calxeda.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Vinod Koul <vinod.koul@intel.com>
+Cc: Dan Williams <djbw@fb.com>
+
+Reviewed-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Reviewed-by: Stephen Warren <swarren@wwwdotorg.org>
+Acked-by: Rob Herring <rob.herring@calxeda.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ Documentation/devicetree/bindings/dma/dma.txt | 81 +++++++++
+ drivers/of/Makefile | 2 +-
+ drivers/of/dma.c | 219 +++++++++++++++++++++++++
+ include/linux/of_dma.h | 45 +++++
+ 4 files changed, 346 insertions(+), 1 deletion(-)
+ create mode 100644 Documentation/devicetree/bindings/dma/dma.txt
+ create mode 100644 drivers/of/dma.c
+ create mode 100644 include/linux/of_dma.h
+
+diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt
+new file mode 100644
+index 0000000..a4f59a5
+--- /dev/null
++++ b/Documentation/devicetree/bindings/dma/dma.txt
+@@ -0,0 +1,81 @@
++* Generic DMA Controller and DMA request bindings
++
++Generic binding to provide a way for a driver using DMA Engine to retrieve the
++DMA request or channel information that goes from a hardware device to a DMA
++controller.
++
++
++* DMA controller
++
++Required property:
++- #dma-cells: Must be at least 1. Used to provide DMA controller
++ specific information. See DMA client binding below for
++ more details.
++
++Optional properties:
++- #dma-channels: Number of DMA channels supported by the controller.
++- #dma-requests: Number of DMA requests signals supported by the
++ controller.
++
++Example:
++
++ dma: dma@48000000 {
++ compatible = "ti,omap-sdma"
++ reg = <0x48000000 0x1000>;
++ interrupts = <0 12 0x4
++ 0 13 0x4
++ 0 14 0x4
++ 0 15 0x4>;
++ #dma-cells = <1>;
++ #dma-channels = <32>;
++ #dma-requests = <127>;
++ };
++
++
++* DMA client
++
++Client drivers should specify the DMA property using a phandle to the controller
++followed by DMA controller specific data.
++
++Required property:
++- dmas: List of one or more DMA specifiers, each consisting of
++ - A phandle pointing to DMA controller node
++ - A number of integer cells, as determined by the
++ #dma-cells property in the node referenced by phandle
++ containing DMA controller specific information. This
++ typically contains a DMA request line number or a
++ channel number, but can contain any data that is used
++ required for configuring a channel.
++- dma-names: Contains one identifier string for each DMA specifier in
++ the dmas property. The specific strings that can be used
++ are defined in the binding of the DMA client device.
++ Multiple DMA specifiers can be used to represent
++ alternatives and in this case the dma-names for those
++ DMA specifiers must be identical (see examples).
++
++Examples:
++
++1. A device with one DMA read channel, one DMA write channel:
++
++ i2c1: i2c@1 {
++ ...
++ dmas = <&dma 2 /* read channel */
++ &dma 3>; /* write channel */
++ dma-names = "rx", "tx"
++ ...
++ };
++
++2. A single read-write channel with three alternative DMA controllers:
++
++ dmas = <&dma1 5
++ &dma2 7
++ &dma3 2>;
++ dma-names = "rx-tx", "rx-tx", "rx-tx"
++
++3. A device with three channels, one of which has two alternatives:
++
++ dmas = <&dma1 2 /* read channel */
++ &dma1 3 /* write channel */
++ &dma2 0 /* error read */
++ &dma3 0>; /* alternative error read */
++ dma-names = "rx", "tx", "error", "error";
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index e027f44..eafa107 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -1,4 +1,4 @@
+-obj-y = base.o
++obj-y = base.o dma.o
+ obj-$(CONFIG_OF_FLATTREE) += fdt.o
+ obj-$(CONFIG_OF_PROMTREE) += pdt.o
+ obj-$(CONFIG_OF_ADDRESS) += address.o
+diff --git a/drivers/of/dma.c b/drivers/of/dma.c
+new file mode 100644
+index 0000000..19ad37c
+--- /dev/null
++++ b/drivers/of/dma.c
+@@ -0,0 +1,219 @@
++/*
++ * Device tree helpers for DMA request / controller
++ *
++ * Based on of_gpio.c
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/rculist.h>
++#include <linux/slab.h>
++#include <linux/of.h>
++#include <linux/of_dma.h>
++
++static LIST_HEAD(of_dma_list);
++
++/**
++ * of_dma_find_controller - Find a DMA controller in DT DMA helpers list
++ * @np: device node of DMA controller
++ */
++static struct of_dma *of_dma_find_controller(struct device_node *np)
++{
++ struct of_dma *ofdma;
++
++ if (list_empty(&of_dma_list)) {
++ pr_err("empty DMA controller list\n");
++ return NULL;
++ }
++
++ list_for_each_entry_rcu(ofdma, &of_dma_list, of_dma_controllers)
++ if (ofdma->of_node == np)
++ return ofdma;
++
++ return NULL;
++}
++
++/**
++ * of_dma_controller_register - Register a DMA controller to DT DMA helpers
++ * @np: device node of DMA controller
++ * @of_dma_xlate: translation function which converts a phandle
++ * arguments list into a dma_chan structure
++ * @data pointer to controller specific data to be used by
++ * translation function
++ *
++ * Returns 0 on success or appropriate errno value on error.
++ *
++ * Allocated memory should be freed with appropriate of_dma_controller_free()
++ * call.
++ */
++int of_dma_controller_register(struct device_node *np,
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *),
++ void *data)
++{
++ struct of_dma *ofdma;
++ int nbcells;
++
++ if (!np || !of_dma_xlate) {
++ pr_err("%s: not enough information provided\n", __func__);
++ return -EINVAL;
++ }
++
++ ofdma = kzalloc(sizeof(*ofdma), GFP_KERNEL);
++ if (!ofdma)
++ return -ENOMEM;
++
++ nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL));
++ if (!nbcells) {
++ pr_err("%s: #dma-cells property is missing or invalid\n",
++ __func__);
++ return -EINVAL;
++ }
++
++ ofdma->of_node = np;
++ ofdma->of_dma_nbcells = nbcells;
++ ofdma->of_dma_xlate = of_dma_xlate;
++ ofdma->of_dma_data = data;
++
++ /* Now queue of_dma controller structure in list */
++ list_add_tail_rcu(&ofdma->of_dma_controllers, &of_dma_list);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(of_dma_controller_register);
++
++/**
++ * of_dma_controller_free - Remove a DMA controller from DT DMA helpers list
++ * @np: device node of DMA controller
++ *
++ * Memory allocated by of_dma_controller_register() is freed here.
++ */
++void of_dma_controller_free(struct device_node *np)
++{
++ struct of_dma *ofdma;
++
++ ofdma = of_dma_find_controller(np);
++ if (ofdma) {
++ list_del_rcu(&ofdma->of_dma_controllers);
++ kfree(ofdma);
++ }
++}
++EXPORT_SYMBOL_GPL(of_dma_controller_free);
++
++/**
++ * of_dma_find_channel - Find a DMA channel by name
++ * @np: device node to look for DMA channels
++ * @name: name of desired channel
++ * @dma_spec: pointer to DMA specifier as found in the device tree
++ *
++ * Find a DMA channel by the name. Returns 0 on success or appropriate
++ * errno value on error.
++ */
++static int of_dma_find_channel(struct device_node *np, char *name,
++ struct of_phandle_args *dma_spec)
++{
++ int count, i;
++ const char *s;
++
++ count = of_property_count_strings(np, "dma-names");
++ if (count < 0)
++ return count;
++
++ for (i = 0; i < count; i++) {
++ if (of_property_read_string_index(np, "dma-names", i, &s))
++ continue;
++
++ if (strcmp(name, s))
++ continue;
++
++ if (!of_parse_phandle_with_args(np, "dmas", "#dma-cells", i,
++ dma_spec))
++ return 0;
++ }
++
++ return -ENODEV;
++}
++
++/**
++ * of_dma_request_slave_channel - Get the DMA slave channel
++ * @np: device node to get DMA request from
++ * @name: name of desired channel
++ *
++ * Returns pointer to appropriate dma channel on success or NULL on error.
++ */
++struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
++ char *name)
++{
++ struct of_phandle_args dma_spec;
++ struct of_dma *ofdma;
++ struct dma_chan *chan;
++ int r;
++
++ if (!np || !name) {
++ pr_err("%s: not enough information provided\n", __func__);
++ return NULL;
++ }
++
++ do {
++ r = of_dma_find_channel(np, name, &dma_spec);
++ if (r) {
++ pr_err("%s: can't find DMA channel\n", np->full_name);
++ return NULL;
++ }
++
++ ofdma = of_dma_find_controller(dma_spec.np);
++ if (!ofdma) {
++ pr_debug("%s: can't find DMA controller %s\n",
++ np->full_name, dma_spec.np->full_name);
++ continue;
++ }
++
++ if (dma_spec.args_count != ofdma->of_dma_nbcells) {
++ pr_debug("%s: wrong #dma-cells for %s\n", np->full_name,
++ dma_spec.np->full_name);
++ continue;
++ }
++
++ chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
++
++ of_node_put(dma_spec.np);
++
++ } while (!chan);
++
++ return chan;
++}
++
++/**
++ * of_dma_simple_xlate - Simple DMA engine translation function
++ * @dma_spec: pointer to DMA specifier as found in the device tree
++ * @of_dma: pointer to DMA controller data
++ *
++ * A simple translation function for devices that use a 32-bit value for the
++ * filter_param when calling the DMA engine dma_request_channel() function.
++ * Note that this translation function requires that #dma-cells is equal to 1
++ * and the argument of the dma specifier is the 32-bit filter_param. Returns
++ * pointer to appropriate dma channel on success or NULL on error.
++ */
++struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
++ struct of_dma *ofdma)
++{
++ int count = dma_spec->args_count;
++ struct of_dma_filter_info *info = ofdma->of_dma_data;
++
++ if (!info || !info->filter_fn)
++ return NULL;
++
++ if (count != 1)
++ return NULL;
++
++ return dma_request_channel(info->dma_cap, info->filter_fn,
++ &dma_spec->args[0]);
++}
++EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
+diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
+new file mode 100644
+index 0000000..337823d
+--- /dev/null
++++ b/include/linux/of_dma.h
+@@ -0,0 +1,45 @@
++/*
++ * OF helpers for DMA request / controller
++ *
++ * Based on of_gpio.h
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __LINUX_OF_DMA_H
++#define __LINUX_OF_DMA_H
++
++#include <linux/of.h>
++#include <linux/dmaengine.h>
++
++struct device_node;
++
++struct of_dma {
++ struct list_head of_dma_controllers;
++ struct device_node *of_node;
++ int of_dma_nbcells;
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *);
++ void *of_dma_data;
++};
++
++struct of_dma_filter_info {
++ dma_cap_mask_t dma_cap;
++ dma_filter_fn filter_fn;
++};
++
++extern int of_dma_controller_register(struct device_node *np,
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *),
++ void *data);
++extern void of_dma_controller_free(struct device_node *np);
++extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
++ char *name);
++extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
++ struct of_dma *ofdma);
++
++#endif /* __LINUX_OF_DMA_H */
diff --git a/patches/linux-3.7-rc6/0005-of-dma-fix-build-break-for-CONFIG_OF.patch b/patches/linux-3.7-rc6/0005-of-dma-fix-build-break-for-CONFIG_OF.patch
new file mode 100644
index 0000000..1801a9c
--- /dev/null
+++ b/patches/linux-3.7-rc6/0005-of-dma-fix-build-break-for-CONFIG_OF.patch
@@ -0,0 +1,54 @@
+From 7ea168ca4862bc9a803bfd9e1415c1b71f6349e0 Mon Sep 17 00:00:00 2001
+From: Vinod Koul <vinod.koul@linux.intel.com>
+Date: Tue, 25 Sep 2012 09:57:36 +0530
+Subject: [PATCH] of: dma- fix build break for !CONFIG_OF
+
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ include/linux/of_dma.h | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
+index 337823d..67158dd 100644
+--- a/include/linux/of_dma.h
++++ b/include/linux/of_dma.h
+@@ -32,6 +32,7 @@ struct of_dma_filter_info {
+ dma_filter_fn filter_fn;
+ };
+
++#ifdef CONFIG_OF
+ extern int of_dma_controller_register(struct device_node *np,
+ struct dma_chan *(*of_dma_xlate)
+ (struct of_phandle_args *, struct of_dma *),
+@@ -41,5 +42,31 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
+ char *name);
+ extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma);
++#else
++static int of_dma_controller_register(struct device_node *np,
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *),
++ void *data)
++{
++ return -ENODEV;
++}
++
++static void of_dma_controller_free(struct device_node *np)
++{
++}
++
++static struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
++ char *name)
++{
++ return NULL;
++}
++
++static struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
++ struct of_dma *ofdma)
++{
++ return NULL;
++}
++
++#endif
+
+ #endif /* __LINUX_OF_DMA_H */
diff --git a/patches/linux-3.7-rc6/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch b/patches/linux-3.7-rc6/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch
new file mode 100644
index 0000000..a92573f
--- /dev/null
+++ b/patches/linux-3.7-rc6/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch
@@ -0,0 +1,69 @@
+From b455947ab768efeaca48e47746206b830f13b04a Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 19 Sep 2012 10:49:48 -0400
+Subject: [PATCH] of: dma: fix typos in generic dma binding definition
+
+Some semicolons were left out in the examples.
+
+The #dma-channels and #dma-requests properties have a prefix
+that is, by convention, reserved for cell size properties.
+Rename those properties to dma-channels and dma-requests.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ Documentation/devicetree/bindings/dma/dma.txt | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt
+index a4f59a5..8f504e6 100644
+--- a/Documentation/devicetree/bindings/dma/dma.txt
++++ b/Documentation/devicetree/bindings/dma/dma.txt
+@@ -13,22 +13,22 @@ Required property:
+ more details.
+
+ Optional properties:
+-- #dma-channels: Number of DMA channels supported by the controller.
+-- #dma-requests: Number of DMA requests signals supported by the
++- dma-channels: Number of DMA channels supported by the controller.
++- dma-requests: Number of DMA requests signals supported by the
+ controller.
+
+ Example:
+
+ dma: dma@48000000 {
+- compatible = "ti,omap-sdma"
++ compatible = "ti,omap-sdma";
+ reg = <0x48000000 0x1000>;
+ interrupts = <0 12 0x4
+ 0 13 0x4
+ 0 14 0x4
+ 0 15 0x4>;
+ #dma-cells = <1>;
+- #dma-channels = <32>;
+- #dma-requests = <127>;
++ dma-channels = <32>;
++ dma-requests = <127>;
+ };
+
+
+@@ -61,7 +61,7 @@ Examples:
+ ...
+ dmas = <&dma 2 /* read channel */
+ &dma 3>; /* write channel */
+- dma-names = "rx", "tx"
++ dma-names = "rx", "tx";
+ ...
+ };
+
+@@ -70,7 +70,7 @@ Examples:
+ dmas = <&dma1 5
+ &dma2 7
+ &dma3 2>;
+- dma-names = "rx-tx", "rx-tx", "rx-tx"
++ dma-names = "rx-tx", "rx-tx", "rx-tx";
+
+ 3. A device with three channels, one of which has two alternatives:
+
diff --git a/patches/linux-3.7-rc6/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch b/patches/linux-3.7-rc6/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
new file mode 100644
index 0000000..e49b823
--- /dev/null
+++ b/patches/linux-3.7-rc6/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
@@ -0,0 +1,24 @@
+From ae2d9b7b36e62046f28b0b9092e68fcc1f84a96a Mon Sep 17 00:00:00 2001
+From: Vinod Koul <vinod.koul@linux.intel.com>
+Date: Tue, 25 Sep 2012 16:18:55 +0530
+Subject: [PATCH] dmaengine: fix build failure due to missing semi-colon
+
+Reported-by: Fengguang Wu <fengguang.wu@intel.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ include/linux/dmaengine.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index 8cd0e25..c88f302 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -992,7 +992,7 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+ static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
+ char *name)
+ {
+- return NULL
++ return NULL;
+ }
+ static inline void dma_release_channel(struct dma_chan *chan)
+ {
diff --git a/patches/linux-3.7-rc6/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch b/patches/linux-3.7-rc6/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
new file mode 100644
index 0000000..41e012f
--- /dev/null
+++ b/patches/linux-3.7-rc6/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
@@ -0,0 +1,144 @@
+From 10e28276286e519e3be5d9ffb783bf77d48fc3ed Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Tue, 18 Sep 2012 18:57:15 +0000
+Subject: [PATCH] dmaengine: edma: fix slave config dependency on direction
+
+The edma_slave_config() implementation depends on the
+direction field such that it will not properly configure
+a slave channel when called without direction set.
+
+This fixes the implementation so that the slave config
+is copied as is and prep_slave_sg() handles the
+direction dependent handling. spi-omap2-mcspi and
+omap_hsmmc both expose this bug as they configure the
+slave channel config from a common path with an unconfigured
+direction field.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/dma/edma.c | 55 ++++++++++++++++++++++++++--------------------------
+ 1 file changed, 27 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index 05aea3c..fdcf079 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -69,9 +69,7 @@ struct edma_chan {
+ int ch_num;
+ bool alloced;
+ int slot[EDMA_MAX_SLOTS];
+- dma_addr_t addr;
+- int addr_width;
+- int maxburst;
++ struct dma_slave_config cfg;
+ };
+
+ struct edma_cc {
+@@ -178,29 +176,14 @@ static int edma_terminate_all(struct edma_chan *echan)
+ return 0;
+ }
+
+-
+ static int edma_slave_config(struct edma_chan *echan,
+- struct dma_slave_config *config)
++ struct dma_slave_config *cfg)
+ {
+- if ((config->src_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+- (config->dst_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
++ if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
++ cfg->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
+ return -EINVAL;
+
+- if (config->direction == DMA_MEM_TO_DEV) {
+- if (config->dst_addr)
+- echan->addr = config->dst_addr;
+- if (config->dst_addr_width)
+- echan->addr_width = config->dst_addr_width;
+- if (config->dst_maxburst)
+- echan->maxburst = config->dst_maxburst;
+- } else if (config->direction == DMA_DEV_TO_MEM) {
+- if (config->src_addr)
+- echan->addr = config->src_addr;
+- if (config->src_addr_width)
+- echan->addr_width = config->src_addr_width;
+- if (config->src_maxburst)
+- echan->maxburst = config->src_maxburst;
+- }
++ memcpy(&echan->cfg, cfg, sizeof(echan->cfg));
+
+ return 0;
+ }
+@@ -235,6 +218,9 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ struct edma_chan *echan = to_edma_chan(chan);
+ struct device *dev = chan->device->dev;
+ struct edma_desc *edesc;
++ dma_addr_t dev_addr;
++ enum dma_slave_buswidth dev_width;
++ u32 burst;
+ struct scatterlist *sg;
+ int i;
+ int acnt, bcnt, ccnt, src, dst, cidx;
+@@ -243,7 +229,20 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ if (unlikely(!echan || !sgl || !sg_len))
+ return NULL;
+
+- if (echan->addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
++ if (direction == DMA_DEV_TO_MEM) {
++ dev_addr = echan->cfg.src_addr;
++ dev_width = echan->cfg.src_addr_width;
++ burst = echan->cfg.src_maxburst;
++ } else if (direction == DMA_MEM_TO_DEV) {
++ dev_addr = echan->cfg.dst_addr;
++ dev_width = echan->cfg.dst_addr_width;
++ burst = echan->cfg.dst_maxburst;
++ } else {
++ dev_err(dev, "%s: bad direction?\n", __func__);
++ return NULL;
++ }
++
++ if (dev_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
+ dev_err(dev, "Undefined slave buswidth\n");
+ return NULL;
+ }
+@@ -275,14 +274,14 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ }
+ }
+
+- acnt = echan->addr_width;
++ acnt = dev_width;
+
+ /*
+ * If the maxburst is equal to the fifo width, use
+ * A-synced transfers. This allows for large contiguous
+ * buffer transfers using only one PaRAM set.
+ */
+- if (echan->maxburst == 1) {
++ if (burst == 1) {
+ edesc->absync = false;
+ ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1);
+ bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1);
+@@ -302,7 +301,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ */
+ } else {
+ edesc->absync = true;
+- bcnt = echan->maxburst;
++ bcnt = burst;
+ ccnt = sg_dma_len(sg) / (acnt * bcnt);
+ if (ccnt > (SZ_64K - 1)) {
+ dev_err(dev, "Exceeded max SG segment size\n");
+@@ -313,13 +312,13 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+
+ if (direction == DMA_MEM_TO_DEV) {
+ src = sg_dma_address(sg);
+- dst = echan->addr;
++ dst = dev_addr;
+ src_bidx = acnt;
+ src_cidx = cidx;
+ dst_bidx = 0;
+ dst_cidx = 0;
+ } else {
+- src = echan->addr;
++ src = dev_addr;
+ dst = sg_dma_address(sg);
+ src_bidx = 0;
+ src_cidx = 0;
diff --git a/patches/linux-3.7-rc6/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch b/patches/linux-3.7-rc6/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
new file mode 100644
index 0000000..f766eb2
--- /dev/null
+++ b/patches/linux-3.7-rc6/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
@@ -0,0 +1,4048 @@
+From 11d28a7c4cf53a9d5eff3d01ff5f7a2436d29790 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 22 Aug 2012 09:24:24 -0400
+Subject: [PATCH] ARM: davinci: move private EDMA API to arm/common
+
+Move mach-davinci/dma.c to common/edma.c so it can be used
+by OMAP (specifically AM33xx) as well. This just moves the
+private EDMA API but does not support OMAP.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/Kconfig | 1 +
+ arch/arm/common/Kconfig | 3 +
+ arch/arm/common/Makefile | 1 +
+ arch/arm/common/edma.c | 1588 +++++++++++++++++++++++++++
+ arch/arm/mach-davinci/Makefile | 2 +-
+ arch/arm/mach-davinci/board-tnetv107x-evm.c | 2 +-
+ arch/arm/mach-davinci/davinci.h | 2 +-
+ arch/arm/mach-davinci/devices-tnetv107x.c | 2 +-
+ arch/arm/mach-davinci/devices.c | 7 +-
+ arch/arm/mach-davinci/dm355.c | 2 +-
+ arch/arm/mach-davinci/dm365.c | 2 +-
+ arch/arm/mach-davinci/dm644x.c | 2 +-
+ arch/arm/mach-davinci/dm646x.c | 2 +-
+ arch/arm/mach-davinci/dma.c | 1588 ---------------------------
+ arch/arm/mach-davinci/include/mach/da8xx.h | 2 +-
+ arch/arm/mach-davinci/include/mach/edma.h | 267 -----
+ arch/arm/plat-omap/Kconfig | 1 +
+ drivers/dma/edma.c | 2 +-
+ drivers/mmc/host/davinci_mmc.c | 1 +
+ include/linux/mfd/davinci_voicecodec.h | 3 +-
+ include/linux/platform_data/edma.h | 198 ++++
+ include/linux/platform_data/spi-davinci.h | 2 +-
+ sound/soc/davinci/davinci-evm.c | 1 +
+ sound/soc/davinci/davinci-pcm.c | 1 +
+ sound/soc/davinci/davinci-pcm.h | 2 +-
+ sound/soc/davinci/davinci-sffsdr.c | 6 +-
+ 26 files changed, 1815 insertions(+), 1875 deletions(-)
+ create mode 100644 arch/arm/common/edma.c
+ delete mode 100644 arch/arm/mach-davinci/dma.c
+ delete mode 100644 arch/arm/mach-davinci/include/mach/edma.h
+ create mode 100644 include/linux/platform_data/edma.h
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index ade7e92..6737b69 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -924,6 +924,7 @@ config ARCH_DAVINCI
+ select GENERIC_IRQ_CHIP
+ select HAVE_IDE
+ select NEED_MACH_GPIO_H
++ select TI_PRIV_EDMA
+ select ZONE_DMA
+ help
+ Support for TI's DaVinci platform.
+diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
+index 45ceeb0..9e32d0d 100644
+--- a/arch/arm/common/Kconfig
++++ b/arch/arm/common/Kconfig
+@@ -40,3 +40,6 @@ config SHARP_PARAM
+
+ config SHARP_SCOOP
+ bool
++
++config TI_PRIV_EDMA
++ bool
+diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
+index e8a4e58..d09a39b 100644
+--- a/arch/arm/common/Makefile
++++ b/arch/arm/common/Makefile
+@@ -13,3 +13,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
+ obj-$(CONFIG_SHARP_SCOOP) += scoop.o
+ obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
+ obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
++obj-$(CONFIG_TI_PRIV_EDMA) += edma.o
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+new file mode 100644
+index 0000000..4411087
+--- /dev/null
++++ b/arch/arm/common/edma.c
+@@ -0,0 +1,1588 @@
++/*
++ * EDMA3 support for DaVinci
++ *
++ * Copyright (C) 2006-2009 Texas Instruments.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++
++#include <linux/platform_data/edma.h>
++
++/* Offsets matching "struct edmacc_param" */
++#define PARM_OPT 0x00
++#define PARM_SRC 0x04
++#define PARM_A_B_CNT 0x08
++#define PARM_DST 0x0c
++#define PARM_SRC_DST_BIDX 0x10
++#define PARM_LINK_BCNTRLD 0x14
++#define PARM_SRC_DST_CIDX 0x18
++#define PARM_CCNT 0x1c
++
++#define PARM_SIZE 0x20
++
++/* Offsets for EDMA CC global channel registers and their shadows */
++#define SH_ER 0x00 /* 64 bits */
++#define SH_ECR 0x08 /* 64 bits */
++#define SH_ESR 0x10 /* 64 bits */
++#define SH_CER 0x18 /* 64 bits */
++#define SH_EER 0x20 /* 64 bits */
++#define SH_EECR 0x28 /* 64 bits */
++#define SH_EESR 0x30 /* 64 bits */
++#define SH_SER 0x38 /* 64 bits */
++#define SH_SECR 0x40 /* 64 bits */
++#define SH_IER 0x50 /* 64 bits */
++#define SH_IECR 0x58 /* 64 bits */
++#define SH_IESR 0x60 /* 64 bits */
++#define SH_IPR 0x68 /* 64 bits */
++#define SH_ICR 0x70 /* 64 bits */
++#define SH_IEVAL 0x78
++#define SH_QER 0x80
++#define SH_QEER 0x84
++#define SH_QEECR 0x88
++#define SH_QEESR 0x8c
++#define SH_QSER 0x90
++#define SH_QSECR 0x94
++#define SH_SIZE 0x200
++
++/* Offsets for EDMA CC global registers */
++#define EDMA_REV 0x0000
++#define EDMA_CCCFG 0x0004
++#define EDMA_QCHMAP 0x0200 /* 8 registers */
++#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */
++#define EDMA_QDMAQNUM 0x0260
++#define EDMA_QUETCMAP 0x0280
++#define EDMA_QUEPRI 0x0284
++#define EDMA_EMR 0x0300 /* 64 bits */
++#define EDMA_EMCR 0x0308 /* 64 bits */
++#define EDMA_QEMR 0x0310
++#define EDMA_QEMCR 0x0314
++#define EDMA_CCERR 0x0318
++#define EDMA_CCERRCLR 0x031c
++#define EDMA_EEVAL 0x0320
++#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/
++#define EDMA_QRAE 0x0380 /* 4 registers */
++#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */
++#define EDMA_QSTAT 0x0600 /* 2 registers */
++#define EDMA_QWMTHRA 0x0620
++#define EDMA_QWMTHRB 0x0624
++#define EDMA_CCSTAT 0x0640
++
++#define EDMA_M 0x1000 /* global channel registers */
++#define EDMA_ECR 0x1008
++#define EDMA_ECRH 0x100C
++#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */
++#define EDMA_PARM 0x4000 /* 128 param entries */
++
++#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
++
++#define EDMA_DCHMAP 0x0100 /* 64 registers */
++#define CHMAP_EXIST BIT(24)
++
++#define EDMA_MAX_DMACH 64
++#define EDMA_MAX_PARAMENTRY 512
++
++/*****************************************************************************/
++
++static void __iomem *edmacc_regs_base[EDMA_MAX_CC];
++
++static inline unsigned int edma_read(unsigned ctlr, int offset)
++{
++ return (unsigned int)__raw_readl(edmacc_regs_base[ctlr] + offset);
++}
++
++static inline void edma_write(unsigned ctlr, int offset, int val)
++{
++ __raw_writel(val, edmacc_regs_base[ctlr] + offset);
++}
++static inline void edma_modify(unsigned ctlr, int offset, unsigned and,
++ unsigned or)
++{
++ unsigned val = edma_read(ctlr, offset);
++ val &= and;
++ val |= or;
++ edma_write(ctlr, offset, val);
++}
++static inline void edma_and(unsigned ctlr, int offset, unsigned and)
++{
++ unsigned val = edma_read(ctlr, offset);
++ val &= and;
++ edma_write(ctlr, offset, val);
++}
++static inline void edma_or(unsigned ctlr, int offset, unsigned or)
++{
++ unsigned val = edma_read(ctlr, offset);
++ val |= or;
++ edma_write(ctlr, offset, val);
++}
++static inline unsigned int edma_read_array(unsigned ctlr, int offset, int i)
++{
++ return edma_read(ctlr, offset + (i << 2));
++}
++static inline void edma_write_array(unsigned ctlr, int offset, int i,
++ unsigned val)
++{
++ edma_write(ctlr, offset + (i << 2), val);
++}
++static inline void edma_modify_array(unsigned ctlr, int offset, int i,
++ unsigned and, unsigned or)
++{
++ edma_modify(ctlr, offset + (i << 2), and, or);
++}
++static inline void edma_or_array(unsigned ctlr, int offset, int i, unsigned or)
++{
++ edma_or(ctlr, offset + (i << 2), or);
++}
++static inline void edma_or_array2(unsigned ctlr, int offset, int i, int j,
++ unsigned or)
++{
++ edma_or(ctlr, offset + ((i*2 + j) << 2), or);
++}
++static inline void edma_write_array2(unsigned ctlr, int offset, int i, int j,
++ unsigned val)
++{
++ edma_write(ctlr, offset + ((i*2 + j) << 2), val);
++}
++static inline unsigned int edma_shadow0_read(unsigned ctlr, int offset)
++{
++ return edma_read(ctlr, EDMA_SHADOW0 + offset);
++}
++static inline unsigned int edma_shadow0_read_array(unsigned ctlr, int offset,
++ int i)
++{
++ return edma_read(ctlr, EDMA_SHADOW0 + offset + (i << 2));
++}
++static inline void edma_shadow0_write(unsigned ctlr, int offset, unsigned val)
++{
++ edma_write(ctlr, EDMA_SHADOW0 + offset, val);
++}
++static inline void edma_shadow0_write_array(unsigned ctlr, int offset, int i,
++ unsigned val)
++{
++ edma_write(ctlr, EDMA_SHADOW0 + offset + (i << 2), val);
++}
++static inline unsigned int edma_parm_read(unsigned ctlr, int offset,
++ int param_no)
++{
++ return edma_read(ctlr, EDMA_PARM + offset + (param_no << 5));
++}
++static inline void edma_parm_write(unsigned ctlr, int offset, int param_no,
++ unsigned val)
++{
++ edma_write(ctlr, EDMA_PARM + offset + (param_no << 5), val);
++}
++static inline void edma_parm_modify(unsigned ctlr, int offset, int param_no,
++ unsigned and, unsigned or)
++{
++ edma_modify(ctlr, EDMA_PARM + offset + (param_no << 5), and, or);
++}
++static inline void edma_parm_and(unsigned ctlr, int offset, int param_no,
++ unsigned and)
++{
++ edma_and(ctlr, EDMA_PARM + offset + (param_no << 5), and);
++}
++static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
++ unsigned or)
++{
++ edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
++}
++
++static inline void set_bits(int offset, int len, unsigned long *p)
++{
++ for (; len > 0; len--)
++ set_bit(offset + (len - 1), p);
++}
++
++static inline void clear_bits(int offset, int len, unsigned long *p)
++{
++ for (; len > 0; len--)
++ clear_bit(offset + (len - 1), p);
++}
++
++/*****************************************************************************/
++
++/* actual number of DMA channels and slots on this silicon */
++struct edma {
++ /* how many dma resources of each type */
++ unsigned num_channels;
++ unsigned num_region;
++ unsigned num_slots;
++ unsigned num_tc;
++ unsigned num_cc;
++ enum dma_event_q default_queue;
++
++ /* list of channels with no even trigger; terminated by "-1" */
++ const s8 *noevent;
++
++ /* The edma_inuse bit for each PaRAM slot is clear unless the
++ * channel is in use ... by ARM or DSP, for QDMA, or whatever.
++ */
++ DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
++
++ /* The edma_unused bit for each channel is clear unless
++ * it is not being used on this platform. It uses a bit
++ * of SOC-specific initialization code.
++ */
++ DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
++
++ unsigned irq_res_start;
++ unsigned irq_res_end;
++
++ struct dma_interrupt_data {
++ void (*callback)(unsigned channel, unsigned short ch_status,
++ void *data);
++ void *data;
++ } intr_data[EDMA_MAX_DMACH];
++};
++
++static struct edma *edma_cc[EDMA_MAX_CC];
++static int arch_num_cc;
++
++/* dummy param set used to (re)initialize parameter RAM slots */
++static const struct edmacc_param dummy_paramset = {
++ .link_bcntrld = 0xffff,
++ .ccnt = 1,
++};
++
++/*****************************************************************************/
++
++static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
++ enum dma_event_q queue_no)
++{
++ int bit = (ch_no & 0x7) * 4;
++
++ /* default to low priority queue */
++ if (queue_no == EVENTQ_DEFAULT)
++ queue_no = edma_cc[ctlr]->default_queue;
++
++ queue_no &= 7;
++ edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3),
++ ~(0x7 << bit), queue_no << bit);
++}
++
++static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
++{
++ int bit = queue_no * 4;
++ edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
++}
++
++static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
++ int priority)
++{
++ int bit = queue_no * 4;
++ edma_modify(ctlr, EDMA_QUEPRI, ~(0x7 << bit),
++ ((priority & 0x7) << bit));
++}
++
++/**
++ * map_dmach_param - Maps channel number to param entry number
++ *
++ * This maps the dma channel number to param entry numberter. In
++ * other words using the DMA channel mapping registers a param entry
++ * can be mapped to any channel
++ *
++ * Callers are responsible for ensuring the channel mapping logic is
++ * included in that particular EDMA variant (Eg : dm646x)
++ *
++ */
++static void __init map_dmach_param(unsigned ctlr)
++{
++ int i;
++ for (i = 0; i < EDMA_MAX_DMACH; i++)
++ edma_write_array(ctlr, EDMA_DCHMAP , i , (i << 5));
++}
++
++static inline void
++setup_dma_interrupt(unsigned lch,
++ void (*callback)(unsigned channel, u16 ch_status, void *data),
++ void *data)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(lch);
++ lch = EDMA_CHAN_SLOT(lch);
++
++ if (!callback)
++ edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5,
++ BIT(lch & 0x1f));
++
++ edma_cc[ctlr]->intr_data[lch].callback = callback;
++ edma_cc[ctlr]->intr_data[lch].data = data;
++
++ if (callback) {
++ edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5,
++ BIT(lch & 0x1f));
++ edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5,
++ BIT(lch & 0x1f));
++ }
++}
++
++static int irq2ctlr(int irq)
++{
++ if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end)
++ return 0;
++ else if (irq >= edma_cc[1]->irq_res_start &&
++ irq <= edma_cc[1]->irq_res_end)
++ return 1;
++
++ return -1;
++}
++
++/******************************************************************************
++ *
++ * DMA interrupt handler
++ *
++ *****************************************************************************/
++static irqreturn_t dma_irq_handler(int irq, void *data)
++{
++ int ctlr;
++ u32 sh_ier;
++ u32 sh_ipr;
++ u32 bank;
++
++ ctlr = irq2ctlr(irq);
++ if (ctlr < 0)
++ return IRQ_NONE;
++
++ dev_dbg(data, "dma_irq_handler\n");
++
++ sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
++ if (!sh_ipr) {
++ sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
++ if (!sh_ipr)
++ return IRQ_NONE;
++ sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
++ bank = 1;
++ } else {
++ sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
++ bank = 0;
++ }
++
++ do {
++ u32 slot;
++ u32 channel;
++
++ dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
++
++ slot = __ffs(sh_ipr);
++ sh_ipr &= ~(BIT(slot));
++
++ if (sh_ier & BIT(slot)) {
++ channel = (bank << 5) | slot;
++ /* Clear the corresponding IPR bits */
++ edma_shadow0_write_array(ctlr, SH_ICR, bank,
++ BIT(slot));
++ if (edma_cc[ctlr]->intr_data[channel].callback)
++ edma_cc[ctlr]->intr_data[channel].callback(
++ channel, DMA_COMPLETE,
++ edma_cc[ctlr]->intr_data[channel].data);
++ }
++ } while (sh_ipr);
++
++ edma_shadow0_write(ctlr, SH_IEVAL, 1);
++ return IRQ_HANDLED;
++}
++
++/******************************************************************************
++ *
++ * DMA error interrupt handler
++ *
++ *****************************************************************************/
++static irqreturn_t dma_ccerr_handler(int irq, void *data)
++{
++ int i;
++ int ctlr;
++ unsigned int cnt = 0;
++
++ ctlr = irq2ctlr(irq);
++ if (ctlr < 0)
++ return IRQ_NONE;
++
++ dev_dbg(data, "dma_ccerr_handler\n");
++
++ if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
++ (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
++ (edma_read(ctlr, EDMA_QEMR) == 0) &&
++ (edma_read(ctlr, EDMA_CCERR) == 0))
++ return IRQ_NONE;
++
++ while (1) {
++ int j = -1;
++ if (edma_read_array(ctlr, EDMA_EMR, 0))
++ j = 0;
++ else if (edma_read_array(ctlr, EDMA_EMR, 1))
++ j = 1;
++ if (j >= 0) {
++ dev_dbg(data, "EMR%d %08x\n", j,
++ edma_read_array(ctlr, EDMA_EMR, j));
++ for (i = 0; i < 32; i++) {
++ int k = (j << 5) + i;
++ if (edma_read_array(ctlr, EDMA_EMR, j) &
++ BIT(i)) {
++ /* Clear the corresponding EMR bits */
++ edma_write_array(ctlr, EDMA_EMCR, j,
++ BIT(i));
++ /* Clear any SER */
++ edma_shadow0_write_array(ctlr, SH_SECR,
++ j, BIT(i));
++ if (edma_cc[ctlr]->intr_data[k].
++ callback) {
++ edma_cc[ctlr]->intr_data[k].
++ callback(k,
++ DMA_CC_ERROR,
++ edma_cc[ctlr]->intr_data
++ [k].data);
++ }
++ }
++ }
++ } else if (edma_read(ctlr, EDMA_QEMR)) {
++ dev_dbg(data, "QEMR %02x\n",
++ edma_read(ctlr, EDMA_QEMR));
++ for (i = 0; i < 8; i++) {
++ if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) {
++ /* Clear the corresponding IPR bits */
++ edma_write(ctlr, EDMA_QEMCR, BIT(i));
++ edma_shadow0_write(ctlr, SH_QSECR,
++ BIT(i));
++
++ /* NOTE: not reported!! */
++ }
++ }
++ } else if (edma_read(ctlr, EDMA_CCERR)) {
++ dev_dbg(data, "CCERR %08x\n",
++ edma_read(ctlr, EDMA_CCERR));
++ /* FIXME: CCERR.BIT(16) ignored! much better
++ * to just write CCERRCLR with CCERR value...
++ */
++ for (i = 0; i < 8; i++) {
++ if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) {
++ /* Clear the corresponding IPR bits */
++ edma_write(ctlr, EDMA_CCERRCLR, BIT(i));
++
++ /* NOTE: not reported!! */
++ }
++ }
++ }
++ if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
++ (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
++ (edma_read(ctlr, EDMA_QEMR) == 0) &&
++ (edma_read(ctlr, EDMA_CCERR) == 0))
++ break;
++ cnt++;
++ if (cnt > 10)
++ break;
++ }
++ edma_write(ctlr, EDMA_EEVAL, 1);
++ return IRQ_HANDLED;
++}
++
++/******************************************************************************
++ *
++ * Transfer controller error interrupt handlers
++ *
++ *****************************************************************************/
++
++#define tc_errs_handled false /* disabled as long as they're NOPs */
++
++static irqreturn_t dma_tc0err_handler(int irq, void *data)
++{
++ dev_dbg(data, "dma_tc0err_handler\n");
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t dma_tc1err_handler(int irq, void *data)
++{
++ dev_dbg(data, "dma_tc1err_handler\n");
++ return IRQ_HANDLED;
++}
++
++static int reserve_contiguous_slots(int ctlr, unsigned int id,
++ unsigned int num_slots,
++ unsigned int start_slot)
++{
++ int i, j;
++ unsigned int count = num_slots;
++ int stop_slot = start_slot;
++ DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY);
++
++ for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) {
++ j = EDMA_CHAN_SLOT(i);
++ if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) {
++ /* Record our current beginning slot */
++ if (count == num_slots)
++ stop_slot = i;
++
++ count--;
++ set_bit(j, tmp_inuse);
++
++ if (count == 0)
++ break;
++ } else {
++ clear_bit(j, tmp_inuse);
++
++ if (id == EDMA_CONT_PARAMS_FIXED_EXACT) {
++ stop_slot = i;
++ break;
++ } else {
++ count = num_slots;
++ }
++ }
++ }
++
++ /*
++ * We have to clear any bits that we set
++ * if we run out parameter RAM slots, i.e we do find a set
++ * of contiguous parameter RAM slots but do not find the exact number
++ * requested as we may reach the total number of parameter RAM slots
++ */
++ if (i == edma_cc[ctlr]->num_slots)
++ stop_slot = i;
++
++ j = start_slot;
++ for_each_set_bit_from(j, tmp_inuse, stop_slot)
++ clear_bit(j, edma_cc[ctlr]->edma_inuse);
++
++ if (count)
++ return -EBUSY;
++
++ for (j = i - num_slots + 1; j <= i; ++j)
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j),
++ &dummy_paramset, PARM_SIZE);
++
++ return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
++}
++
++static int prepare_unused_channel_list(struct device *dev, void *data)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ int i, ctlr;
++
++ for (i = 0; i < pdev->num_resources; i++) {
++ if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
++ (int)pdev->resource[i].start >= 0) {
++ ctlr = EDMA_CTLR(pdev->resource[i].start);
++ clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
++ edma_cc[ctlr]->edma_unused);
++ }
++ }
++
++ return 0;
++}
++
++/*-----------------------------------------------------------------------*/
++
++static bool unused_chan_list_done;
++
++/* Resource alloc/free: dma channels, parameter RAM slots */
++
++/**
++ * edma_alloc_channel - allocate DMA channel and paired parameter RAM
++ * @channel: specific channel to allocate; negative for "any unmapped channel"
++ * @callback: optional; to be issued on DMA completion or errors
++ * @data: passed to callback
++ * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
++ * Controller (TC) executes requests using this channel. Use
++ * EVENTQ_DEFAULT unless you really need a high priority queue.
++ *
++ * This allocates a DMA channel and its associated parameter RAM slot.
++ * The parameter RAM is initialized to hold a dummy transfer.
++ *
++ * Normal use is to pass a specific channel number as @channel, to make
++ * use of hardware events mapped to that channel. When the channel will
++ * be used only for software triggering or event chaining, channels not
++ * mapped to hardware events (or mapped to unused events) are preferable.
++ *
++ * DMA transfers start from a channel using edma_start(), or by
++ * chaining. When the transfer described in that channel's parameter RAM
++ * slot completes, that slot's data may be reloaded through a link.
++ *
++ * DMA errors are only reported to the @callback associated with the
++ * channel driving that transfer, but transfer completion callbacks can
++ * be sent to another channel under control of the TCC field in
++ * the option word of the transfer's parameter RAM set. Drivers must not
++ * use DMA transfer completion callbacks for channels they did not allocate.
++ * (The same applies to TCC codes used in transfer chaining.)
++ *
++ * Returns the number of the channel, else negative errno.
++ */
++int edma_alloc_channel(int channel,
++ void (*callback)(unsigned channel, u16 ch_status, void *data),
++ void *data,
++ enum dma_event_q eventq_no)
++{
++ unsigned i, done = 0, ctlr = 0;
++ int ret = 0;
++
++ if (!unused_chan_list_done) {
++ /*
++ * Scan all the platform devices to find out the EDMA channels
++ * used and clear them in the unused list, making the rest
++ * available for ARM usage.
++ */
++ ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
++ prepare_unused_channel_list);
++ if (ret < 0)
++ return ret;
++
++ unused_chan_list_done = true;
++ }
++
++ if (channel >= 0) {
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++ }
++
++ if (channel < 0) {
++ for (i = 0; i < arch_num_cc; i++) {
++ channel = 0;
++ for (;;) {
++ channel = find_next_bit(edma_cc[i]->edma_unused,
++ edma_cc[i]->num_channels,
++ channel);
++ if (channel == edma_cc[i]->num_channels)
++ break;
++ if (!test_and_set_bit(channel,
++ edma_cc[i]->edma_inuse)) {
++ done = 1;
++ ctlr = i;
++ break;
++ }
++ channel++;
++ }
++ if (done)
++ break;
++ }
++ if (!done)
++ return -ENOMEM;
++ } else if (channel >= edma_cc[ctlr]->num_channels) {
++ return -EINVAL;
++ } else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) {
++ return -EBUSY;
++ }
++
++ /* ensure access through shadow region 0 */
++ edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
++
++ /* ensure no events are pending */
++ edma_stop(EDMA_CTLR_CHAN(ctlr, channel));
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
++ &dummy_paramset, PARM_SIZE);
++
++ if (callback)
++ setup_dma_interrupt(EDMA_CTLR_CHAN(ctlr, channel),
++ callback, data);
++
++ map_dmach_queue(ctlr, channel, eventq_no);
++
++ return EDMA_CTLR_CHAN(ctlr, channel);
++}
++EXPORT_SYMBOL(edma_alloc_channel);
++
++
++/**
++ * edma_free_channel - deallocate DMA channel
++ * @channel: dma channel returned from edma_alloc_channel()
++ *
++ * This deallocates the DMA channel and associated parameter RAM slot
++ * allocated by edma_alloc_channel().
++ *
++ * Callers are responsible for ensuring the channel is inactive, and
++ * will not be reactivated by linking, chaining, or software calls to
++ * edma_start().
++ */
++void edma_free_channel(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel >= edma_cc[ctlr]->num_channels)
++ return;
++
++ setup_dma_interrupt(channel, NULL, NULL);
++ /* REVISIT should probably take out of shadow region 0 */
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
++ &dummy_paramset, PARM_SIZE);
++ clear_bit(channel, edma_cc[ctlr]->edma_inuse);
++}
++EXPORT_SYMBOL(edma_free_channel);
++
++/**
++ * edma_alloc_slot - allocate DMA parameter RAM
++ * @slot: specific slot to allocate; negative for "any unused slot"
++ *
++ * This allocates a parameter RAM slot, initializing it to hold a
++ * dummy transfer. Slots allocated using this routine have not been
++ * mapped to a hardware DMA channel, and will normally be used by
++ * linking to them from a slot associated with a DMA channel.
++ *
++ * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
++ * slots may be allocated on behalf of DSP firmware.
++ *
++ * Returns the number of the slot, else negative errno.
++ */
++int edma_alloc_slot(unsigned ctlr, int slot)
++{
++ if (slot >= 0)
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < 0) {
++ slot = edma_cc[ctlr]->num_channels;
++ for (;;) {
++ slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse,
++ edma_cc[ctlr]->num_slots, slot);
++ if (slot == edma_cc[ctlr]->num_slots)
++ return -ENOMEM;
++ if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse))
++ break;
++ }
++ } else if (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots) {
++ return -EINVAL;
++ } else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) {
++ return -EBUSY;
++ }
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
++ &dummy_paramset, PARM_SIZE);
++
++ return EDMA_CTLR_CHAN(ctlr, slot);
++}
++EXPORT_SYMBOL(edma_alloc_slot);
++
++/**
++ * edma_free_slot - deallocate DMA parameter RAM
++ * @slot: parameter RAM slot returned from edma_alloc_slot()
++ *
++ * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
++ * Callers are responsible for ensuring the slot is inactive, and will
++ * not be activated.
++ */
++void edma_free_slot(unsigned slot)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots)
++ return;
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
++ &dummy_paramset, PARM_SIZE);
++ clear_bit(slot, edma_cc[ctlr]->edma_inuse);
++}
++EXPORT_SYMBOL(edma_free_slot);
++
++
++/**
++ * edma_alloc_cont_slots- alloc contiguous parameter RAM slots
++ * The API will return the starting point of a set of
++ * contiguous parameter RAM slots that have been requested
++ *
++ * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT
++ * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
++ * @count: number of contiguous Paramter RAM slots
++ * @slot - the start value of Parameter RAM slot that should be passed if id
++ * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
++ *
++ * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of
++ * contiguous Parameter RAM slots from parameter RAM 64 in the case of
++ * DaVinci SOCs and 32 in the case of DA8xx SOCs.
++ *
++ * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a
++ * set of contiguous parameter RAM slots from the "slot" that is passed as an
++ * argument to the API.
++ *
++ * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries
++ * starts looking for a set of contiguous parameter RAMs from the "slot"
++ * that is passed as an argument to the API. On failure the API will try to
++ * find a set of contiguous Parameter RAM slots from the remaining Parameter
++ * RAM slots
++ */
++int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count)
++{
++ /*
++ * The start slot requested should be greater than
++ * the number of channels and lesser than the total number
++ * of slots
++ */
++ if ((id != EDMA_CONT_PARAMS_ANY) &&
++ (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots))
++ return -EINVAL;
++
++ /*
++ * The number of parameter RAM slots requested cannot be less than 1
++ * and cannot be more than the number of slots minus the number of
++ * channels
++ */
++ if (count < 1 || count >
++ (edma_cc[ctlr]->num_slots - edma_cc[ctlr]->num_channels))
++ return -EINVAL;
++
++ switch (id) {
++ case EDMA_CONT_PARAMS_ANY:
++ return reserve_contiguous_slots(ctlr, id, count,
++ edma_cc[ctlr]->num_channels);
++ case EDMA_CONT_PARAMS_FIXED_EXACT:
++ case EDMA_CONT_PARAMS_FIXED_NOT_EXACT:
++ return reserve_contiguous_slots(ctlr, id, count, slot);
++ default:
++ return -EINVAL;
++ }
++
++}
++EXPORT_SYMBOL(edma_alloc_cont_slots);
++
++/**
++ * edma_free_cont_slots - deallocate DMA parameter RAM slots
++ * @slot: first parameter RAM of a set of parameter RAM slots to be freed
++ * @count: the number of contiguous parameter RAM slots to be freed
++ *
++ * This deallocates the parameter RAM slots allocated by
++ * edma_alloc_cont_slots.
++ * Callers/applications need to keep track of sets of contiguous
++ * parameter RAM slots that have been allocated using the edma_alloc_cont_slots
++ * API.
++ * Callers are responsible for ensuring the slots are inactive, and will
++ * not be activated.
++ */
++int edma_free_cont_slots(unsigned slot, int count)
++{
++ unsigned ctlr, slot_to_free;
++ int i;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots ||
++ count < 1)
++ return -EINVAL;
++
++ for (i = slot; i < slot + count; ++i) {
++ ctlr = EDMA_CTLR(i);
++ slot_to_free = EDMA_CHAN_SLOT(i);
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free),
++ &dummy_paramset, PARM_SIZE);
++ clear_bit(slot_to_free, edma_cc[ctlr]->edma_inuse);
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(edma_free_cont_slots);
++
++/*-----------------------------------------------------------------------*/
++
++/* Parameter RAM operations (i) -- read/write partial slots */
++
++/**
++ * edma_set_src - set initial DMA source address in parameter RAM slot
++ * @slot: parameter RAM slot being configured
++ * @src_port: physical address of source (memory, controller FIFO, etc)
++ * @addressMode: INCR, except in very rare cases
++ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
++ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
++ *
++ * Note that the source address is modified during the DMA transfer
++ * according to edma_set_src_index().
++ */
++void edma_set_src(unsigned slot, dma_addr_t src_port,
++ enum address_mode mode, enum fifo_width width)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
++
++ if (mode) {
++ /* set SAM and program FWID */
++ i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
++ } else {
++ /* clear SAM */
++ i &= ~SAM;
++ }
++ edma_parm_write(ctlr, PARM_OPT, slot, i);
++
++ /* set the source port address
++ in source register of param structure */
++ edma_parm_write(ctlr, PARM_SRC, slot, src_port);
++ }
++}
++EXPORT_SYMBOL(edma_set_src);
++
++/**
++ * edma_set_dest - set initial DMA destination address in parameter RAM slot
++ * @slot: parameter RAM slot being configured
++ * @dest_port: physical address of destination (memory, controller FIFO, etc)
++ * @addressMode: INCR, except in very rare cases
++ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
++ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
++ *
++ * Note that the destination address is modified during the DMA transfer
++ * according to edma_set_dest_index().
++ */
++void edma_set_dest(unsigned slot, dma_addr_t dest_port,
++ enum address_mode mode, enum fifo_width width)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
++
++ if (mode) {
++ /* set DAM and program FWID */
++ i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
++ } else {
++ /* clear DAM */
++ i &= ~DAM;
++ }
++ edma_parm_write(ctlr, PARM_OPT, slot, i);
++ /* set the destination port address
++ in dest register of param structure */
++ edma_parm_write(ctlr, PARM_DST, slot, dest_port);
++ }
++}
++EXPORT_SYMBOL(edma_set_dest);
++
++/**
++ * edma_get_position - returns the current transfer points
++ * @slot: parameter RAM slot being examined
++ * @src: pointer to source port position
++ * @dst: pointer to destination port position
++ *
++ * Returns current source and destination addresses for a particular
++ * parameter RAM slot. Its channel should not be active when this is called.
++ */
++void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
++{
++ struct edmacc_param temp;
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp);
++ if (src != NULL)
++ *src = temp.src;
++ if (dst != NULL)
++ *dst = temp.dst;
++}
++EXPORT_SYMBOL(edma_get_position);
++
++/**
++ * edma_set_src_index - configure DMA source address indexing
++ * @slot: parameter RAM slot being configured
++ * @src_bidx: byte offset between source arrays in a frame
++ * @src_cidx: byte offset between source frames in a block
++ *
++ * Offsets are specified to support either contiguous or discontiguous
++ * memory transfers, or repeated access to a hardware register, as needed.
++ * When accessing hardware registers, both offsets are normally zero.
++ */
++void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
++ 0xffff0000, src_bidx);
++ edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
++ 0xffff0000, src_cidx);
++ }
++}
++EXPORT_SYMBOL(edma_set_src_index);
++
++/**
++ * edma_set_dest_index - configure DMA destination address indexing
++ * @slot: parameter RAM slot being configured
++ * @dest_bidx: byte offset between destination arrays in a frame
++ * @dest_cidx: byte offset between destination frames in a block
++ *
++ * Offsets are specified to support either contiguous or discontiguous
++ * memory transfers, or repeated access to a hardware register, as needed.
++ * When accessing hardware registers, both offsets are normally zero.
++ */
++void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
++ 0x0000ffff, dest_bidx << 16);
++ edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
++ 0x0000ffff, dest_cidx << 16);
++ }
++}
++EXPORT_SYMBOL(edma_set_dest_index);
++
++/**
++ * edma_set_transfer_params - configure DMA transfer parameters
++ * @slot: parameter RAM slot being configured
++ * @acnt: how many bytes per array (at least one)
++ * @bcnt: how many arrays per frame (at least one)
++ * @ccnt: how many frames per block (at least one)
++ * @bcnt_rld: used only for A-Synchronized transfers; this specifies
++ * the value to reload into bcnt when it decrements to zero
++ * @sync_mode: ASYNC or ABSYNC
++ *
++ * See the EDMA3 documentation to understand how to configure and link
++ * transfers using the fields in PaRAM slots. If you are not doing it
++ * all at once with edma_write_slot(), you will use this routine
++ * plus two calls each for source and destination, setting the initial
++ * address and saying how to index that address.
++ *
++ * An example of an A-Synchronized transfer is a serial link using a
++ * single word shift register. In that case, @acnt would be equal to
++ * that word size; the serial controller issues a DMA synchronization
++ * event to transfer each word, and memory access by the DMA transfer
++ * controller will be word-at-a-time.
++ *
++ * An example of an AB-Synchronized transfer is a device using a FIFO.
++ * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
++ * The controller with the FIFO issues DMA synchronization events when
++ * the FIFO threshold is reached, and the DMA transfer controller will
++ * transfer one frame to (or from) the FIFO. It will probably use
++ * efficient burst modes to access memory.
++ */
++void edma_set_transfer_params(unsigned slot,
++ u16 acnt, u16 bcnt, u16 ccnt,
++ u16 bcnt_rld, enum sync_dimension sync_mode)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ edma_parm_modify(ctlr, PARM_LINK_BCNTRLD, slot,
++ 0x0000ffff, bcnt_rld << 16);
++ if (sync_mode == ASYNC)
++ edma_parm_and(ctlr, PARM_OPT, slot, ~SYNCDIM);
++ else
++ edma_parm_or(ctlr, PARM_OPT, slot, SYNCDIM);
++ /* Set the acount, bcount, ccount registers */
++ edma_parm_write(ctlr, PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
++ edma_parm_write(ctlr, PARM_CCNT, slot, ccnt);
++ }
++}
++EXPORT_SYMBOL(edma_set_transfer_params);
++
++/**
++ * edma_link - link one parameter RAM slot to another
++ * @from: parameter RAM slot originating the link
++ * @to: parameter RAM slot which is the link target
++ *
++ * The originating slot should not be part of any active DMA transfer.
++ */
++void edma_link(unsigned from, unsigned to)
++{
++ unsigned ctlr_from, ctlr_to;
++
++ ctlr_from = EDMA_CTLR(from);
++ from = EDMA_CHAN_SLOT(from);
++ ctlr_to = EDMA_CTLR(to);
++ to = EDMA_CHAN_SLOT(to);
++
++ if (from >= edma_cc[ctlr_from]->num_slots)
++ return;
++ if (to >= edma_cc[ctlr_to]->num_slots)
++ return;
++ edma_parm_modify(ctlr_from, PARM_LINK_BCNTRLD, from, 0xffff0000,
++ PARM_OFFSET(to));
++}
++EXPORT_SYMBOL(edma_link);
++
++/**
++ * edma_unlink - cut link from one parameter RAM slot
++ * @from: parameter RAM slot originating the link
++ *
++ * The originating slot should not be part of any active DMA transfer.
++ * Its link is set to 0xffff.
++ */
++void edma_unlink(unsigned from)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(from);
++ from = EDMA_CHAN_SLOT(from);
++
++ if (from >= edma_cc[ctlr]->num_slots)
++ return;
++ edma_parm_or(ctlr, PARM_LINK_BCNTRLD, from, 0xffff);
++}
++EXPORT_SYMBOL(edma_unlink);
++
++/*-----------------------------------------------------------------------*/
++
++/* Parameter RAM operations (ii) -- read/write whole parameter sets */
++
++/**
++ * edma_write_slot - write parameter RAM data for slot
++ * @slot: number of parameter RAM slot being modified
++ * @param: data to be written into parameter RAM slot
++ *
++ * Use this to assign all parameters of a transfer at once. This
++ * allows more efficient setup of transfers than issuing multiple
++ * calls to set up those parameters in small pieces, and provides
++ * complete control over all transfer options.
++ */
++void edma_write_slot(unsigned slot, const struct edmacc_param *param)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot >= edma_cc[ctlr]->num_slots)
++ return;
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), param,
++ PARM_SIZE);
++}
++EXPORT_SYMBOL(edma_write_slot);
++
++/**
++ * edma_read_slot - read parameter RAM data from slot
++ * @slot: number of parameter RAM slot being copied
++ * @param: where to store copy of parameter RAM data
++ *
++ * Use this to read data from a parameter RAM slot, perhaps to
++ * save them as a template for later reuse.
++ */
++void edma_read_slot(unsigned slot, struct edmacc_param *param)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot >= edma_cc[ctlr]->num_slots)
++ return;
++ memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
++ PARM_SIZE);
++}
++EXPORT_SYMBOL(edma_read_slot);
++
++/*-----------------------------------------------------------------------*/
++
++/* Various EDMA channel control operations */
++
++/**
++ * edma_pause - pause dma on a channel
++ * @channel: on which edma_start() has been called
++ *
++ * This temporarily disables EDMA hardware events on the specified channel,
++ * preventing them from triggering new transfers on its behalf
++ */
++void edma_pause(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ unsigned int mask = BIT(channel & 0x1f);
++
++ edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask);
++ }
++}
++EXPORT_SYMBOL(edma_pause);
++
++/**
++ * edma_resume - resumes dma on a paused channel
++ * @channel: on which edma_pause() has been called
++ *
++ * This re-enables EDMA hardware events on the specified channel.
++ */
++void edma_resume(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ unsigned int mask = BIT(channel & 0x1f);
++
++ edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask);
++ }
++}
++EXPORT_SYMBOL(edma_resume);
++
++/**
++ * edma_start - start dma on a channel
++ * @channel: channel being activated
++ *
++ * Channels with event associations will be triggered by their hardware
++ * events, and channels without such associations will be triggered by
++ * software. (At this writing there is no interface for using software
++ * triggers except with channels that don't support hardware triggers.)
++ *
++ * Returns zero on success, else negative errno.
++ */
++int edma_start(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ int j = channel >> 5;
++ unsigned int mask = BIT(channel & 0x1f);
++
++ /* EDMA channels without event association */
++ if (test_bit(channel, edma_cc[ctlr]->edma_unused)) {
++ pr_debug("EDMA: ESR%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_ESR, j));
++ edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
++ return 0;
++ }
++
++ /* EDMA channel with event association */
++ pr_debug("EDMA: ER%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_ER, j));
++ /* Clear any pending event or error */
++ edma_write_array(ctlr, EDMA_ECR, j, mask);
++ edma_write_array(ctlr, EDMA_EMCR, j, mask);
++ /* Clear any SER */
++ edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
++ edma_shadow0_write_array(ctlr, SH_EESR, j, mask);
++ pr_debug("EDMA: EER%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_EER, j));
++ return 0;
++ }
++
++ return -EINVAL;
++}
++EXPORT_SYMBOL(edma_start);
++
++/**
++ * edma_stop - stops dma on the channel passed
++ * @channel: channel being deactivated
++ *
++ * When @lch is a channel, any active transfer is paused and
++ * all pending hardware events are cleared. The current transfer
++ * may not be resumed, and the channel's Parameter RAM should be
++ * reinitialized before being reused.
++ */
++void edma_stop(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ int j = channel >> 5;
++ unsigned int mask = BIT(channel & 0x1f);
++
++ edma_shadow0_write_array(ctlr, SH_EECR, j, mask);
++ edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
++ edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
++ edma_write_array(ctlr, EDMA_EMCR, j, mask);
++
++ pr_debug("EDMA: EER%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_EER, j));
++
++ /* REVISIT: consider guarding against inappropriate event
++ * chaining by overwriting with dummy_paramset.
++ */
++ }
++}
++EXPORT_SYMBOL(edma_stop);
++
++/******************************************************************************
++ *
++ * It cleans ParamEntry qand bring back EDMA to initial state if media has
++ * been removed before EDMA has finished.It is usedful for removable media.
++ * Arguments:
++ * ch_no - channel no
++ *
++ * Return: zero on success, or corresponding error no on failure
++ *
++ * FIXME this should not be needed ... edma_stop() should suffice.
++ *
++ *****************************************************************************/
++
++void edma_clean_channel(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ int j = (channel >> 5);
++ unsigned int mask = BIT(channel & 0x1f);
++
++ pr_debug("EDMA: EMR%d %08x\n", j,
++ edma_read_array(ctlr, EDMA_EMR, j));
++ edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
++ /* Clear the corresponding EMR bits */
++ edma_write_array(ctlr, EDMA_EMCR, j, mask);
++ /* Clear any SER */
++ edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
++ edma_write(ctlr, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
++ }
++}
++EXPORT_SYMBOL(edma_clean_channel);
++
++/*
++ * edma_clear_event - clear an outstanding event on the DMA channel
++ * Arguments:
++ * channel - channel number
++ */
++void edma_clear_event(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel >= edma_cc[ctlr]->num_channels)
++ return;
++ if (channel < 32)
++ edma_write(ctlr, EDMA_ECR, BIT(channel));
++ else
++ edma_write(ctlr, EDMA_ECRH, BIT(channel - 32));
++}
++EXPORT_SYMBOL(edma_clear_event);
++
++/*-----------------------------------------------------------------------*/
++
++static int __init edma_probe(struct platform_device *pdev)
++{
++ struct edma_soc_info **info = pdev->dev.platform_data;
++ const s8 (*queue_priority_mapping)[2];
++ const s8 (*queue_tc_mapping)[2];
++ int i, j, off, ln, found = 0;
++ int status = -1;
++ const s16 (*rsv_chans)[2];
++ const s16 (*rsv_slots)[2];
++ int irq[EDMA_MAX_CC] = {0, 0};
++ int err_irq[EDMA_MAX_CC] = {0, 0};
++ struct resource *r[EDMA_MAX_CC] = {NULL};
++ resource_size_t len[EDMA_MAX_CC];
++ char res_name[10];
++ char irq_name[10];
++
++ if (!info)
++ return -ENODEV;
++
++ for (j = 0; j < EDMA_MAX_CC; j++) {
++ sprintf(res_name, "edma_cc%d", j);
++ r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ res_name);
++ if (!r[j] || !info[j]) {
++ if (found)
++ break;
++ else
++ return -ENODEV;
++ } else {
++ found = 1;
++ }
++
++ len[j] = resource_size(r[j]);
++
++ r[j] = request_mem_region(r[j]->start, len[j],
++ dev_name(&pdev->dev));
++ if (!r[j]) {
++ status = -EBUSY;
++ goto fail1;
++ }
++
++ edmacc_regs_base[j] = ioremap(r[j]->start, len[j]);
++ if (!edmacc_regs_base[j]) {
++ status = -EBUSY;
++ goto fail1;
++ }
++
++ edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
++ if (!edma_cc[j]) {
++ status = -ENOMEM;
++ goto fail1;
++ }
++
++ edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
++ EDMA_MAX_DMACH);
++ edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
++ EDMA_MAX_PARAMENTRY);
++ edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
++ EDMA_MAX_CC);
++
++ edma_cc[j]->default_queue = info[j]->default_queue;
++
++ dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
++ edmacc_regs_base[j]);
++
++ for (i = 0; i < edma_cc[j]->num_slots; i++)
++ memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
++ &dummy_paramset, PARM_SIZE);
++
++ /* Mark all channels as unused */
++ memset(edma_cc[j]->edma_unused, 0xff,
++ sizeof(edma_cc[j]->edma_unused));
++
++ if (info[j]->rsv) {
++
++ /* Clear the reserved channels in unused list */
++ rsv_chans = info[j]->rsv->rsv_chans;
++ if (rsv_chans) {
++ for (i = 0; rsv_chans[i][0] != -1; i++) {
++ off = rsv_chans[i][0];
++ ln = rsv_chans[i][1];
++ clear_bits(off, ln,
++ edma_cc[j]->edma_unused);
++ }
++ }
++
++ /* Set the reserved slots in inuse list */
++ rsv_slots = info[j]->rsv->rsv_slots;
++ if (rsv_slots) {
++ for (i = 0; rsv_slots[i][0] != -1; i++) {
++ off = rsv_slots[i][0];
++ ln = rsv_slots[i][1];
++ set_bits(off, ln,
++ edma_cc[j]->edma_inuse);
++ }
++ }
++ }
++
++ sprintf(irq_name, "edma%d", j);
++ irq[j] = platform_get_irq_byname(pdev, irq_name);
++ edma_cc[j]->irq_res_start = irq[j];
++ status = request_irq(irq[j], dma_irq_handler, 0, "edma",
++ &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
++ irq[j], status);
++ goto fail;
++ }
++
++ sprintf(irq_name, "edma%d_err", j);
++ err_irq[j] = platform_get_irq_byname(pdev, irq_name);
++ edma_cc[j]->irq_res_end = err_irq[j];
++ status = request_irq(err_irq[j], dma_ccerr_handler, 0,
++ "edma_error", &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
++ err_irq[j], status);
++ goto fail;
++ }
++
++ for (i = 0; i < edma_cc[j]->num_channels; i++)
++ map_dmach_queue(j, i, info[j]->default_queue);
++
++ queue_tc_mapping = info[j]->queue_tc_mapping;
++ queue_priority_mapping = info[j]->queue_priority_mapping;
++
++ /* Event queue to TC mapping */
++ for (i = 0; queue_tc_mapping[i][0] != -1; i++)
++ map_queue_tc(j, queue_tc_mapping[i][0],
++ queue_tc_mapping[i][1]);
++
++ /* Event queue priority mapping */
++ for (i = 0; queue_priority_mapping[i][0] != -1; i++)
++ assign_priority_to_queue(j,
++ queue_priority_mapping[i][0],
++ queue_priority_mapping[i][1]);
++
++ /* Map the channel to param entry if channel mapping logic
++ * exist
++ */
++ if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
++ map_dmach_param(j);
++
++ for (i = 0; i < info[j]->n_region; i++) {
++ edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
++ edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
++ edma_write_array(j, EDMA_QRAE, i, 0x0);
++ }
++ arch_num_cc++;
++ }
++
++ if (tc_errs_handled) {
++ status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
++ "edma_tc0", &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
++ IRQ_TCERRINT0, status);
++ return status;
++ }
++ status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
++ "edma_tc1", &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
++ IRQ_TCERRINT, status);
++ return status;
++ }
++ }
++
++ return 0;
++
++fail:
++ for (i = 0; i < EDMA_MAX_CC; i++) {
++ if (err_irq[i])
++ free_irq(err_irq[i], &pdev->dev);
++ if (irq[i])
++ free_irq(irq[i], &pdev->dev);
++ }
++fail1:
++ for (i = 0; i < EDMA_MAX_CC; i++) {
++ if (r[i])
++ release_mem_region(r[i]->start, len[i]);
++ if (edmacc_regs_base[i])
++ iounmap(edmacc_regs_base[i]);
++ kfree(edma_cc[i]);
++ }
++ return status;
++}
++
++
++static struct platform_driver edma_driver = {
++ .driver.name = "edma",
++};
++
++static int __init edma_init(void)
++{
++ return platform_driver_probe(&edma_driver, edma_probe);
++}
++arch_initcall(edma_init);
++
+diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
+index 2227eff..97c639e 100644
+--- a/arch/arm/mach-davinci/Makefile
++++ b/arch/arm/mach-davinci/Makefile
+@@ -5,7 +5,7 @@
+
+ # Common objects
+ obj-y := time.o clock.o serial.o psc.o \
+- dma.o usb.o common.o sram.o aemif.o
++ usb.o common.o sram.o aemif.o
+
+ obj-$(CONFIG_DAVINCI_MUX) += mux.o
+
+diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
+index be30997..86f55ba 100644
+--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
++++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
+@@ -26,12 +26,12 @@
+ #include <linux/input.h>
+ #include <linux/input/matrix_keypad.h>
+ #include <linux/spi/spi.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach-types.h>
+
+ #include <mach/irqs.h>
+-#include <mach/edma.h>
+ #include <mach/mux.h>
+ #include <mach/cp_intc.h>
+ #include <mach/tnetv107x.h>
+diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
+index 12d544b..d26a6bc 100644
+--- a/arch/arm/mach-davinci/davinci.h
++++ b/arch/arm/mach-davinci/davinci.h
+@@ -23,9 +23,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/spi/spi.h>
+ #include <linux/platform_data/davinci_asp.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/platform_data/keyscan-davinci.h>
+ #include <mach/hardware.h>
+-#include <mach/edma.h>
+
+ #include <media/davinci/vpfe_capture.h>
+ #include <media/davinci/vpif_types.h>
+diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
+index 29b17f7..59efd7f 100644
+--- a/arch/arm/mach-davinci/devices-tnetv107x.c
++++ b/arch/arm/mach-davinci/devices-tnetv107x.c
+@@ -18,10 +18,10 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/clk.h>
+ #include <linux/slab.h>
++#include <linux/platform_data/edma.h>
+
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+-#include <mach/edma.h>
+ #include <mach/tnetv107x.h>
+
+ #include "clock.h"
+diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
+index 4c48a36..f45d591 100644
+--- a/arch/arm/mach-davinci/devices.c
++++ b/arch/arm/mach-davinci/devices.c
+@@ -19,9 +19,10 @@
+ #include <mach/irqs.h>
+ #include <mach/cputype.h>
+ #include <mach/mux.h>
+-#include <mach/edma.h>
+ #include <linux/platform_data/mmc-davinci.h>
+ #include <mach/time.h>
++#include <linux/platform_data/edma.h>
++
+
+ #include "davinci.h"
+ #include "clock.h"
+@@ -141,10 +142,10 @@ static struct resource mmcsd0_resources[] = {
+ },
+ /* DMA channels: RX, then TX */
+ {
+- .start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCRXEVT),
++ .start = EDMA_CTLR_CHAN(0, 26),
+ .flags = IORESOURCE_DMA,
+ }, {
+- .start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCTXEVT),
++ .start = EDMA_CTLR_CHAN(0, 27),
+ .flags = IORESOURCE_DMA,
+ },
+ };
+diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
+index a255434..b165c27 100644
+--- a/arch/arm/mach-davinci/dm355.c
++++ b/arch/arm/mach-davinci/dm355.c
+@@ -19,7 +19,6 @@
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+ #include <mach/irqs.h>
+@@ -28,6 +27,7 @@
+ #include <mach/common.h>
+ #include <linux/platform_data/spi-davinci.h>
+ #include <mach/gpio-davinci.h>
++#include <linux/platform_data/edma.h>
+
+ #include "davinci.h"
+ #include "clock.h"
+diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
+index b680c83..a611716 100644
+--- a/arch/arm/mach-davinci/dm365.c
++++ b/arch/arm/mach-davinci/dm365.c
+@@ -18,11 +18,11 @@
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/spi/spi.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+ #include <mach/irqs.h>
+diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
+index cd0c8b1..90f5639 100644
+--- a/arch/arm/mach-davinci/dm644x.c
++++ b/arch/arm/mach-davinci/dm644x.c
+@@ -12,11 +12,11 @@
+ #include <linux/clk.h>
+ #include <linux/serial_8250.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/irqs.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
+index 97c0f8e..08f9dab 100644
+--- a/arch/arm/mach-davinci/dm646x.c
++++ b/arch/arm/mach-davinci/dm646x.c
+@@ -13,11 +13,11 @@
+ #include <linux/clk.h>
+ #include <linux/serial_8250.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/irqs.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
+deleted file mode 100644
+index a685e97..0000000
+--- a/arch/arm/mach-davinci/dma.c
++++ /dev/null
+@@ -1,1588 +0,0 @@
+-/*
+- * EDMA3 support for DaVinci
+- *
+- * Copyright (C) 2006-2009 Texas Instruments.
+- *
+- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/interrupt.h>
+-#include <linux/platform_device.h>
+-#include <linux/io.h>
+-#include <linux/slab.h>
+-
+-#include <mach/edma.h>
+-
+-/* Offsets matching "struct edmacc_param" */
+-#define PARM_OPT 0x00
+-#define PARM_SRC 0x04
+-#define PARM_A_B_CNT 0x08
+-#define PARM_DST 0x0c
+-#define PARM_SRC_DST_BIDX 0x10
+-#define PARM_LINK_BCNTRLD 0x14
+-#define PARM_SRC_DST_CIDX 0x18
+-#define PARM_CCNT 0x1c
+-
+-#define PARM_SIZE 0x20
+-
+-/* Offsets for EDMA CC global channel registers and their shadows */
+-#define SH_ER 0x00 /* 64 bits */
+-#define SH_ECR 0x08 /* 64 bits */
+-#define SH_ESR 0x10 /* 64 bits */
+-#define SH_CER 0x18 /* 64 bits */
+-#define SH_EER 0x20 /* 64 bits */
+-#define SH_EECR 0x28 /* 64 bits */
+-#define SH_EESR 0x30 /* 64 bits */
+-#define SH_SER 0x38 /* 64 bits */
+-#define SH_SECR 0x40 /* 64 bits */
+-#define SH_IER 0x50 /* 64 bits */
+-#define SH_IECR 0x58 /* 64 bits */
+-#define SH_IESR 0x60 /* 64 bits */
+-#define SH_IPR 0x68 /* 64 bits */
+-#define SH_ICR 0x70 /* 64 bits */
+-#define SH_IEVAL 0x78
+-#define SH_QER 0x80
+-#define SH_QEER 0x84
+-#define SH_QEECR 0x88
+-#define SH_QEESR 0x8c
+-#define SH_QSER 0x90
+-#define SH_QSECR 0x94
+-#define SH_SIZE 0x200
+-
+-/* Offsets for EDMA CC global registers */
+-#define EDMA_REV 0x0000
+-#define EDMA_CCCFG 0x0004
+-#define EDMA_QCHMAP 0x0200 /* 8 registers */
+-#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */
+-#define EDMA_QDMAQNUM 0x0260
+-#define EDMA_QUETCMAP 0x0280
+-#define EDMA_QUEPRI 0x0284
+-#define EDMA_EMR 0x0300 /* 64 bits */
+-#define EDMA_EMCR 0x0308 /* 64 bits */
+-#define EDMA_QEMR 0x0310
+-#define EDMA_QEMCR 0x0314
+-#define EDMA_CCERR 0x0318
+-#define EDMA_CCERRCLR 0x031c
+-#define EDMA_EEVAL 0x0320
+-#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/
+-#define EDMA_QRAE 0x0380 /* 4 registers */
+-#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */
+-#define EDMA_QSTAT 0x0600 /* 2 registers */
+-#define EDMA_QWMTHRA 0x0620
+-#define EDMA_QWMTHRB 0x0624
+-#define EDMA_CCSTAT 0x0640
+-
+-#define EDMA_M 0x1000 /* global channel registers */
+-#define EDMA_ECR 0x1008
+-#define EDMA_ECRH 0x100C
+-#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */
+-#define EDMA_PARM 0x4000 /* 128 param entries */
+-
+-#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
+-
+-#define EDMA_DCHMAP 0x0100 /* 64 registers */
+-#define CHMAP_EXIST BIT(24)
+-
+-#define EDMA_MAX_DMACH 64
+-#define EDMA_MAX_PARAMENTRY 512
+-
+-/*****************************************************************************/
+-
+-static void __iomem *edmacc_regs_base[EDMA_MAX_CC];
+-
+-static inline unsigned int edma_read(unsigned ctlr, int offset)
+-{
+- return (unsigned int)__raw_readl(edmacc_regs_base[ctlr] + offset);
+-}
+-
+-static inline void edma_write(unsigned ctlr, int offset, int val)
+-{
+- __raw_writel(val, edmacc_regs_base[ctlr] + offset);
+-}
+-static inline void edma_modify(unsigned ctlr, int offset, unsigned and,
+- unsigned or)
+-{
+- unsigned val = edma_read(ctlr, offset);
+- val &= and;
+- val |= or;
+- edma_write(ctlr, offset, val);
+-}
+-static inline void edma_and(unsigned ctlr, int offset, unsigned and)
+-{
+- unsigned val = edma_read(ctlr, offset);
+- val &= and;
+- edma_write(ctlr, offset, val);
+-}
+-static inline void edma_or(unsigned ctlr, int offset, unsigned or)
+-{
+- unsigned val = edma_read(ctlr, offset);
+- val |= or;
+- edma_write(ctlr, offset, val);
+-}
+-static inline unsigned int edma_read_array(unsigned ctlr, int offset, int i)
+-{
+- return edma_read(ctlr, offset + (i << 2));
+-}
+-static inline void edma_write_array(unsigned ctlr, int offset, int i,
+- unsigned val)
+-{
+- edma_write(ctlr, offset + (i << 2), val);
+-}
+-static inline void edma_modify_array(unsigned ctlr, int offset, int i,
+- unsigned and, unsigned or)
+-{
+- edma_modify(ctlr, offset + (i << 2), and, or);
+-}
+-static inline void edma_or_array(unsigned ctlr, int offset, int i, unsigned or)
+-{
+- edma_or(ctlr, offset + (i << 2), or);
+-}
+-static inline void edma_or_array2(unsigned ctlr, int offset, int i, int j,
+- unsigned or)
+-{
+- edma_or(ctlr, offset + ((i*2 + j) << 2), or);
+-}
+-static inline void edma_write_array2(unsigned ctlr, int offset, int i, int j,
+- unsigned val)
+-{
+- edma_write(ctlr, offset + ((i*2 + j) << 2), val);
+-}
+-static inline unsigned int edma_shadow0_read(unsigned ctlr, int offset)
+-{
+- return edma_read(ctlr, EDMA_SHADOW0 + offset);
+-}
+-static inline unsigned int edma_shadow0_read_array(unsigned ctlr, int offset,
+- int i)
+-{
+- return edma_read(ctlr, EDMA_SHADOW0 + offset + (i << 2));
+-}
+-static inline void edma_shadow0_write(unsigned ctlr, int offset, unsigned val)
+-{
+- edma_write(ctlr, EDMA_SHADOW0 + offset, val);
+-}
+-static inline void edma_shadow0_write_array(unsigned ctlr, int offset, int i,
+- unsigned val)
+-{
+- edma_write(ctlr, EDMA_SHADOW0 + offset + (i << 2), val);
+-}
+-static inline unsigned int edma_parm_read(unsigned ctlr, int offset,
+- int param_no)
+-{
+- return edma_read(ctlr, EDMA_PARM + offset + (param_no << 5));
+-}
+-static inline void edma_parm_write(unsigned ctlr, int offset, int param_no,
+- unsigned val)
+-{
+- edma_write(ctlr, EDMA_PARM + offset + (param_no << 5), val);
+-}
+-static inline void edma_parm_modify(unsigned ctlr, int offset, int param_no,
+- unsigned and, unsigned or)
+-{
+- edma_modify(ctlr, EDMA_PARM + offset + (param_no << 5), and, or);
+-}
+-static inline void edma_parm_and(unsigned ctlr, int offset, int param_no,
+- unsigned and)
+-{
+- edma_and(ctlr, EDMA_PARM + offset + (param_no << 5), and);
+-}
+-static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
+- unsigned or)
+-{
+- edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
+-}
+-
+-static inline void set_bits(int offset, int len, unsigned long *p)
+-{
+- for (; len > 0; len--)
+- set_bit(offset + (len - 1), p);
+-}
+-
+-static inline void clear_bits(int offset, int len, unsigned long *p)
+-{
+- for (; len > 0; len--)
+- clear_bit(offset + (len - 1), p);
+-}
+-
+-/*****************************************************************************/
+-
+-/* actual number of DMA channels and slots on this silicon */
+-struct edma {
+- /* how many dma resources of each type */
+- unsigned num_channels;
+- unsigned num_region;
+- unsigned num_slots;
+- unsigned num_tc;
+- unsigned num_cc;
+- enum dma_event_q default_queue;
+-
+- /* list of channels with no even trigger; terminated by "-1" */
+- const s8 *noevent;
+-
+- /* The edma_inuse bit for each PaRAM slot is clear unless the
+- * channel is in use ... by ARM or DSP, for QDMA, or whatever.
+- */
+- DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
+-
+- /* The edma_unused bit for each channel is clear unless
+- * it is not being used on this platform. It uses a bit
+- * of SOC-specific initialization code.
+- */
+- DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
+-
+- unsigned irq_res_start;
+- unsigned irq_res_end;
+-
+- struct dma_interrupt_data {
+- void (*callback)(unsigned channel, unsigned short ch_status,
+- void *data);
+- void *data;
+- } intr_data[EDMA_MAX_DMACH];
+-};
+-
+-static struct edma *edma_cc[EDMA_MAX_CC];
+-static int arch_num_cc;
+-
+-/* dummy param set used to (re)initialize parameter RAM slots */
+-static const struct edmacc_param dummy_paramset = {
+- .link_bcntrld = 0xffff,
+- .ccnt = 1,
+-};
+-
+-/*****************************************************************************/
+-
+-static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
+- enum dma_event_q queue_no)
+-{
+- int bit = (ch_no & 0x7) * 4;
+-
+- /* default to low priority queue */
+- if (queue_no == EVENTQ_DEFAULT)
+- queue_no = edma_cc[ctlr]->default_queue;
+-
+- queue_no &= 7;
+- edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3),
+- ~(0x7 << bit), queue_no << bit);
+-}
+-
+-static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
+-{
+- int bit = queue_no * 4;
+- edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
+-}
+-
+-static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
+- int priority)
+-{
+- int bit = queue_no * 4;
+- edma_modify(ctlr, EDMA_QUEPRI, ~(0x7 << bit),
+- ((priority & 0x7) << bit));
+-}
+-
+-/**
+- * map_dmach_param - Maps channel number to param entry number
+- *
+- * This maps the dma channel number to param entry numberter. In
+- * other words using the DMA channel mapping registers a param entry
+- * can be mapped to any channel
+- *
+- * Callers are responsible for ensuring the channel mapping logic is
+- * included in that particular EDMA variant (Eg : dm646x)
+- *
+- */
+-static void __init map_dmach_param(unsigned ctlr)
+-{
+- int i;
+- for (i = 0; i < EDMA_MAX_DMACH; i++)
+- edma_write_array(ctlr, EDMA_DCHMAP , i , (i << 5));
+-}
+-
+-static inline void
+-setup_dma_interrupt(unsigned lch,
+- void (*callback)(unsigned channel, u16 ch_status, void *data),
+- void *data)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(lch);
+- lch = EDMA_CHAN_SLOT(lch);
+-
+- if (!callback)
+- edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5,
+- BIT(lch & 0x1f));
+-
+- edma_cc[ctlr]->intr_data[lch].callback = callback;
+- edma_cc[ctlr]->intr_data[lch].data = data;
+-
+- if (callback) {
+- edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5,
+- BIT(lch & 0x1f));
+- edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5,
+- BIT(lch & 0x1f));
+- }
+-}
+-
+-static int irq2ctlr(int irq)
+-{
+- if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end)
+- return 0;
+- else if (irq >= edma_cc[1]->irq_res_start &&
+- irq <= edma_cc[1]->irq_res_end)
+- return 1;
+-
+- return -1;
+-}
+-
+-/******************************************************************************
+- *
+- * DMA interrupt handler
+- *
+- *****************************************************************************/
+-static irqreturn_t dma_irq_handler(int irq, void *data)
+-{
+- int ctlr;
+- u32 sh_ier;
+- u32 sh_ipr;
+- u32 bank;
+-
+- ctlr = irq2ctlr(irq);
+- if (ctlr < 0)
+- return IRQ_NONE;
+-
+- dev_dbg(data, "dma_irq_handler\n");
+-
+- sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
+- if (!sh_ipr) {
+- sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
+- if (!sh_ipr)
+- return IRQ_NONE;
+- sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
+- bank = 1;
+- } else {
+- sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
+- bank = 0;
+- }
+-
+- do {
+- u32 slot;
+- u32 channel;
+-
+- dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
+-
+- slot = __ffs(sh_ipr);
+- sh_ipr &= ~(BIT(slot));
+-
+- if (sh_ier & BIT(slot)) {
+- channel = (bank << 5) | slot;
+- /* Clear the corresponding IPR bits */
+- edma_shadow0_write_array(ctlr, SH_ICR, bank,
+- BIT(slot));
+- if (edma_cc[ctlr]->intr_data[channel].callback)
+- edma_cc[ctlr]->intr_data[channel].callback(
+- channel, DMA_COMPLETE,
+- edma_cc[ctlr]->intr_data[channel].data);
+- }
+- } while (sh_ipr);
+-
+- edma_shadow0_write(ctlr, SH_IEVAL, 1);
+- return IRQ_HANDLED;
+-}
+-
+-/******************************************************************************
+- *
+- * DMA error interrupt handler
+- *
+- *****************************************************************************/
+-static irqreturn_t dma_ccerr_handler(int irq, void *data)
+-{
+- int i;
+- int ctlr;
+- unsigned int cnt = 0;
+-
+- ctlr = irq2ctlr(irq);
+- if (ctlr < 0)
+- return IRQ_NONE;
+-
+- dev_dbg(data, "dma_ccerr_handler\n");
+-
+- if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
+- (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
+- (edma_read(ctlr, EDMA_QEMR) == 0) &&
+- (edma_read(ctlr, EDMA_CCERR) == 0))
+- return IRQ_NONE;
+-
+- while (1) {
+- int j = -1;
+- if (edma_read_array(ctlr, EDMA_EMR, 0))
+- j = 0;
+- else if (edma_read_array(ctlr, EDMA_EMR, 1))
+- j = 1;
+- if (j >= 0) {
+- dev_dbg(data, "EMR%d %08x\n", j,
+- edma_read_array(ctlr, EDMA_EMR, j));
+- for (i = 0; i < 32; i++) {
+- int k = (j << 5) + i;
+- if (edma_read_array(ctlr, EDMA_EMR, j) &
+- BIT(i)) {
+- /* Clear the corresponding EMR bits */
+- edma_write_array(ctlr, EDMA_EMCR, j,
+- BIT(i));
+- /* Clear any SER */
+- edma_shadow0_write_array(ctlr, SH_SECR,
+- j, BIT(i));
+- if (edma_cc[ctlr]->intr_data[k].
+- callback) {
+- edma_cc[ctlr]->intr_data[k].
+- callback(k,
+- DMA_CC_ERROR,
+- edma_cc[ctlr]->intr_data
+- [k].data);
+- }
+- }
+- }
+- } else if (edma_read(ctlr, EDMA_QEMR)) {
+- dev_dbg(data, "QEMR %02x\n",
+- edma_read(ctlr, EDMA_QEMR));
+- for (i = 0; i < 8; i++) {
+- if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) {
+- /* Clear the corresponding IPR bits */
+- edma_write(ctlr, EDMA_QEMCR, BIT(i));
+- edma_shadow0_write(ctlr, SH_QSECR,
+- BIT(i));
+-
+- /* NOTE: not reported!! */
+- }
+- }
+- } else if (edma_read(ctlr, EDMA_CCERR)) {
+- dev_dbg(data, "CCERR %08x\n",
+- edma_read(ctlr, EDMA_CCERR));
+- /* FIXME: CCERR.BIT(16) ignored! much better
+- * to just write CCERRCLR with CCERR value...
+- */
+- for (i = 0; i < 8; i++) {
+- if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) {
+- /* Clear the corresponding IPR bits */
+- edma_write(ctlr, EDMA_CCERRCLR, BIT(i));
+-
+- /* NOTE: not reported!! */
+- }
+- }
+- }
+- if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
+- (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
+- (edma_read(ctlr, EDMA_QEMR) == 0) &&
+- (edma_read(ctlr, EDMA_CCERR) == 0))
+- break;
+- cnt++;
+- if (cnt > 10)
+- break;
+- }
+- edma_write(ctlr, EDMA_EEVAL, 1);
+- return IRQ_HANDLED;
+-}
+-
+-/******************************************************************************
+- *
+- * Transfer controller error interrupt handlers
+- *
+- *****************************************************************************/
+-
+-#define tc_errs_handled false /* disabled as long as they're NOPs */
+-
+-static irqreturn_t dma_tc0err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc0err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t dma_tc1err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc1err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+-static int reserve_contiguous_slots(int ctlr, unsigned int id,
+- unsigned int num_slots,
+- unsigned int start_slot)
+-{
+- int i, j;
+- unsigned int count = num_slots;
+- int stop_slot = start_slot;
+- DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY);
+-
+- for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) {
+- j = EDMA_CHAN_SLOT(i);
+- if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) {
+- /* Record our current beginning slot */
+- if (count == num_slots)
+- stop_slot = i;
+-
+- count--;
+- set_bit(j, tmp_inuse);
+-
+- if (count == 0)
+- break;
+- } else {
+- clear_bit(j, tmp_inuse);
+-
+- if (id == EDMA_CONT_PARAMS_FIXED_EXACT) {
+- stop_slot = i;
+- break;
+- } else {
+- count = num_slots;
+- }
+- }
+- }
+-
+- /*
+- * We have to clear any bits that we set
+- * if we run out parameter RAM slots, i.e we do find a set
+- * of contiguous parameter RAM slots but do not find the exact number
+- * requested as we may reach the total number of parameter RAM slots
+- */
+- if (i == edma_cc[ctlr]->num_slots)
+- stop_slot = i;
+-
+- j = start_slot;
+- for_each_set_bit_from(j, tmp_inuse, stop_slot)
+- clear_bit(j, edma_cc[ctlr]->edma_inuse);
+-
+- if (count)
+- return -EBUSY;
+-
+- for (j = i - num_slots + 1; j <= i; ++j)
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j),
+- &dummy_paramset, PARM_SIZE);
+-
+- return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
+-}
+-
+-static int prepare_unused_channel_list(struct device *dev, void *data)
+-{
+- struct platform_device *pdev = to_platform_device(dev);
+- int i, ctlr;
+-
+- for (i = 0; i < pdev->num_resources; i++) {
+- if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
+- (int)pdev->resource[i].start >= 0) {
+- ctlr = EDMA_CTLR(pdev->resource[i].start);
+- clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
+- edma_cc[ctlr]->edma_unused);
+- }
+- }
+-
+- return 0;
+-}
+-
+-/*-----------------------------------------------------------------------*/
+-
+-static bool unused_chan_list_done;
+-
+-/* Resource alloc/free: dma channels, parameter RAM slots */
+-
+-/**
+- * edma_alloc_channel - allocate DMA channel and paired parameter RAM
+- * @channel: specific channel to allocate; negative for "any unmapped channel"
+- * @callback: optional; to be issued on DMA completion or errors
+- * @data: passed to callback
+- * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
+- * Controller (TC) executes requests using this channel. Use
+- * EVENTQ_DEFAULT unless you really need a high priority queue.
+- *
+- * This allocates a DMA channel and its associated parameter RAM slot.
+- * The parameter RAM is initialized to hold a dummy transfer.
+- *
+- * Normal use is to pass a specific channel number as @channel, to make
+- * use of hardware events mapped to that channel. When the channel will
+- * be used only for software triggering or event chaining, channels not
+- * mapped to hardware events (or mapped to unused events) are preferable.
+- *
+- * DMA transfers start from a channel using edma_start(), or by
+- * chaining. When the transfer described in that channel's parameter RAM
+- * slot completes, that slot's data may be reloaded through a link.
+- *
+- * DMA errors are only reported to the @callback associated with the
+- * channel driving that transfer, but transfer completion callbacks can
+- * be sent to another channel under control of the TCC field in
+- * the option word of the transfer's parameter RAM set. Drivers must not
+- * use DMA transfer completion callbacks for channels they did not allocate.
+- * (The same applies to TCC codes used in transfer chaining.)
+- *
+- * Returns the number of the channel, else negative errno.
+- */
+-int edma_alloc_channel(int channel,
+- void (*callback)(unsigned channel, u16 ch_status, void *data),
+- void *data,
+- enum dma_event_q eventq_no)
+-{
+- unsigned i, done = 0, ctlr = 0;
+- int ret = 0;
+-
+- if (!unused_chan_list_done) {
+- /*
+- * Scan all the platform devices to find out the EDMA channels
+- * used and clear them in the unused list, making the rest
+- * available for ARM usage.
+- */
+- ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
+- prepare_unused_channel_list);
+- if (ret < 0)
+- return ret;
+-
+- unused_chan_list_done = true;
+- }
+-
+- if (channel >= 0) {
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+- }
+-
+- if (channel < 0) {
+- for (i = 0; i < arch_num_cc; i++) {
+- channel = 0;
+- for (;;) {
+- channel = find_next_bit(edma_cc[i]->edma_unused,
+- edma_cc[i]->num_channels,
+- channel);
+- if (channel == edma_cc[i]->num_channels)
+- break;
+- if (!test_and_set_bit(channel,
+- edma_cc[i]->edma_inuse)) {
+- done = 1;
+- ctlr = i;
+- break;
+- }
+- channel++;
+- }
+- if (done)
+- break;
+- }
+- if (!done)
+- return -ENOMEM;
+- } else if (channel >= edma_cc[ctlr]->num_channels) {
+- return -EINVAL;
+- } else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) {
+- return -EBUSY;
+- }
+-
+- /* ensure access through shadow region 0 */
+- edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
+-
+- /* ensure no events are pending */
+- edma_stop(EDMA_CTLR_CHAN(ctlr, channel));
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
+- &dummy_paramset, PARM_SIZE);
+-
+- if (callback)
+- setup_dma_interrupt(EDMA_CTLR_CHAN(ctlr, channel),
+- callback, data);
+-
+- map_dmach_queue(ctlr, channel, eventq_no);
+-
+- return EDMA_CTLR_CHAN(ctlr, channel);
+-}
+-EXPORT_SYMBOL(edma_alloc_channel);
+-
+-
+-/**
+- * edma_free_channel - deallocate DMA channel
+- * @channel: dma channel returned from edma_alloc_channel()
+- *
+- * This deallocates the DMA channel and associated parameter RAM slot
+- * allocated by edma_alloc_channel().
+- *
+- * Callers are responsible for ensuring the channel is inactive, and
+- * will not be reactivated by linking, chaining, or software calls to
+- * edma_start().
+- */
+-void edma_free_channel(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel >= edma_cc[ctlr]->num_channels)
+- return;
+-
+- setup_dma_interrupt(channel, NULL, NULL);
+- /* REVISIT should probably take out of shadow region 0 */
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
+- &dummy_paramset, PARM_SIZE);
+- clear_bit(channel, edma_cc[ctlr]->edma_inuse);
+-}
+-EXPORT_SYMBOL(edma_free_channel);
+-
+-/**
+- * edma_alloc_slot - allocate DMA parameter RAM
+- * @slot: specific slot to allocate; negative for "any unused slot"
+- *
+- * This allocates a parameter RAM slot, initializing it to hold a
+- * dummy transfer. Slots allocated using this routine have not been
+- * mapped to a hardware DMA channel, and will normally be used by
+- * linking to them from a slot associated with a DMA channel.
+- *
+- * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
+- * slots may be allocated on behalf of DSP firmware.
+- *
+- * Returns the number of the slot, else negative errno.
+- */
+-int edma_alloc_slot(unsigned ctlr, int slot)
+-{
+- if (slot >= 0)
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < 0) {
+- slot = edma_cc[ctlr]->num_channels;
+- for (;;) {
+- slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse,
+- edma_cc[ctlr]->num_slots, slot);
+- if (slot == edma_cc[ctlr]->num_slots)
+- return -ENOMEM;
+- if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse))
+- break;
+- }
+- } else if (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots) {
+- return -EINVAL;
+- } else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) {
+- return -EBUSY;
+- }
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+- &dummy_paramset, PARM_SIZE);
+-
+- return EDMA_CTLR_CHAN(ctlr, slot);
+-}
+-EXPORT_SYMBOL(edma_alloc_slot);
+-
+-/**
+- * edma_free_slot - deallocate DMA parameter RAM
+- * @slot: parameter RAM slot returned from edma_alloc_slot()
+- *
+- * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
+- * Callers are responsible for ensuring the slot is inactive, and will
+- * not be activated.
+- */
+-void edma_free_slot(unsigned slot)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots)
+- return;
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+- &dummy_paramset, PARM_SIZE);
+- clear_bit(slot, edma_cc[ctlr]->edma_inuse);
+-}
+-EXPORT_SYMBOL(edma_free_slot);
+-
+-
+-/**
+- * edma_alloc_cont_slots- alloc contiguous parameter RAM slots
+- * The API will return the starting point of a set of
+- * contiguous parameter RAM slots that have been requested
+- *
+- * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT
+- * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+- * @count: number of contiguous Paramter RAM slots
+- * @slot - the start value of Parameter RAM slot that should be passed if id
+- * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+- *
+- * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of
+- * contiguous Parameter RAM slots from parameter RAM 64 in the case of
+- * DaVinci SOCs and 32 in the case of DA8xx SOCs.
+- *
+- * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a
+- * set of contiguous parameter RAM slots from the "slot" that is passed as an
+- * argument to the API.
+- *
+- * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries
+- * starts looking for a set of contiguous parameter RAMs from the "slot"
+- * that is passed as an argument to the API. On failure the API will try to
+- * find a set of contiguous Parameter RAM slots from the remaining Parameter
+- * RAM slots
+- */
+-int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count)
+-{
+- /*
+- * The start slot requested should be greater than
+- * the number of channels and lesser than the total number
+- * of slots
+- */
+- if ((id != EDMA_CONT_PARAMS_ANY) &&
+- (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots))
+- return -EINVAL;
+-
+- /*
+- * The number of parameter RAM slots requested cannot be less than 1
+- * and cannot be more than the number of slots minus the number of
+- * channels
+- */
+- if (count < 1 || count >
+- (edma_cc[ctlr]->num_slots - edma_cc[ctlr]->num_channels))
+- return -EINVAL;
+-
+- switch (id) {
+- case EDMA_CONT_PARAMS_ANY:
+- return reserve_contiguous_slots(ctlr, id, count,
+- edma_cc[ctlr]->num_channels);
+- case EDMA_CONT_PARAMS_FIXED_EXACT:
+- case EDMA_CONT_PARAMS_FIXED_NOT_EXACT:
+- return reserve_contiguous_slots(ctlr, id, count, slot);
+- default:
+- return -EINVAL;
+- }
+-
+-}
+-EXPORT_SYMBOL(edma_alloc_cont_slots);
+-
+-/**
+- * edma_free_cont_slots - deallocate DMA parameter RAM slots
+- * @slot: first parameter RAM of a set of parameter RAM slots to be freed
+- * @count: the number of contiguous parameter RAM slots to be freed
+- *
+- * This deallocates the parameter RAM slots allocated by
+- * edma_alloc_cont_slots.
+- * Callers/applications need to keep track of sets of contiguous
+- * parameter RAM slots that have been allocated using the edma_alloc_cont_slots
+- * API.
+- * Callers are responsible for ensuring the slots are inactive, and will
+- * not be activated.
+- */
+-int edma_free_cont_slots(unsigned slot, int count)
+-{
+- unsigned ctlr, slot_to_free;
+- int i;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots ||
+- count < 1)
+- return -EINVAL;
+-
+- for (i = slot; i < slot + count; ++i) {
+- ctlr = EDMA_CTLR(i);
+- slot_to_free = EDMA_CHAN_SLOT(i);
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free),
+- &dummy_paramset, PARM_SIZE);
+- clear_bit(slot_to_free, edma_cc[ctlr]->edma_inuse);
+- }
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(edma_free_cont_slots);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-/* Parameter RAM operations (i) -- read/write partial slots */
+-
+-/**
+- * edma_set_src - set initial DMA source address in parameter RAM slot
+- * @slot: parameter RAM slot being configured
+- * @src_port: physical address of source (memory, controller FIFO, etc)
+- * @addressMode: INCR, except in very rare cases
+- * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+- * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+- *
+- * Note that the source address is modified during the DMA transfer
+- * according to edma_set_src_index().
+- */
+-void edma_set_src(unsigned slot, dma_addr_t src_port,
+- enum address_mode mode, enum fifo_width width)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
+-
+- if (mode) {
+- /* set SAM and program FWID */
+- i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
+- } else {
+- /* clear SAM */
+- i &= ~SAM;
+- }
+- edma_parm_write(ctlr, PARM_OPT, slot, i);
+-
+- /* set the source port address
+- in source register of param structure */
+- edma_parm_write(ctlr, PARM_SRC, slot, src_port);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_src);
+-
+-/**
+- * edma_set_dest - set initial DMA destination address in parameter RAM slot
+- * @slot: parameter RAM slot being configured
+- * @dest_port: physical address of destination (memory, controller FIFO, etc)
+- * @addressMode: INCR, except in very rare cases
+- * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+- * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+- *
+- * Note that the destination address is modified during the DMA transfer
+- * according to edma_set_dest_index().
+- */
+-void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+- enum address_mode mode, enum fifo_width width)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
+-
+- if (mode) {
+- /* set DAM and program FWID */
+- i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
+- } else {
+- /* clear DAM */
+- i &= ~DAM;
+- }
+- edma_parm_write(ctlr, PARM_OPT, slot, i);
+- /* set the destination port address
+- in dest register of param structure */
+- edma_parm_write(ctlr, PARM_DST, slot, dest_port);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_dest);
+-
+-/**
+- * edma_get_position - returns the current transfer points
+- * @slot: parameter RAM slot being examined
+- * @src: pointer to source port position
+- * @dst: pointer to destination port position
+- *
+- * Returns current source and destination addresses for a particular
+- * parameter RAM slot. Its channel should not be active when this is called.
+- */
+-void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
+-{
+- struct edmacc_param temp;
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp);
+- if (src != NULL)
+- *src = temp.src;
+- if (dst != NULL)
+- *dst = temp.dst;
+-}
+-EXPORT_SYMBOL(edma_get_position);
+-
+-/**
+- * edma_set_src_index - configure DMA source address indexing
+- * @slot: parameter RAM slot being configured
+- * @src_bidx: byte offset between source arrays in a frame
+- * @src_cidx: byte offset between source frames in a block
+- *
+- * Offsets are specified to support either contiguous or discontiguous
+- * memory transfers, or repeated access to a hardware register, as needed.
+- * When accessing hardware registers, both offsets are normally zero.
+- */
+-void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
+- 0xffff0000, src_bidx);
+- edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
+- 0xffff0000, src_cidx);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_src_index);
+-
+-/**
+- * edma_set_dest_index - configure DMA destination address indexing
+- * @slot: parameter RAM slot being configured
+- * @dest_bidx: byte offset between destination arrays in a frame
+- * @dest_cidx: byte offset between destination frames in a block
+- *
+- * Offsets are specified to support either contiguous or discontiguous
+- * memory transfers, or repeated access to a hardware register, as needed.
+- * When accessing hardware registers, both offsets are normally zero.
+- */
+-void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
+- 0x0000ffff, dest_bidx << 16);
+- edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
+- 0x0000ffff, dest_cidx << 16);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_dest_index);
+-
+-/**
+- * edma_set_transfer_params - configure DMA transfer parameters
+- * @slot: parameter RAM slot being configured
+- * @acnt: how many bytes per array (at least one)
+- * @bcnt: how many arrays per frame (at least one)
+- * @ccnt: how many frames per block (at least one)
+- * @bcnt_rld: used only for A-Synchronized transfers; this specifies
+- * the value to reload into bcnt when it decrements to zero
+- * @sync_mode: ASYNC or ABSYNC
+- *
+- * See the EDMA3 documentation to understand how to configure and link
+- * transfers using the fields in PaRAM slots. If you are not doing it
+- * all at once with edma_write_slot(), you will use this routine
+- * plus two calls each for source and destination, setting the initial
+- * address and saying how to index that address.
+- *
+- * An example of an A-Synchronized transfer is a serial link using a
+- * single word shift register. In that case, @acnt would be equal to
+- * that word size; the serial controller issues a DMA synchronization
+- * event to transfer each word, and memory access by the DMA transfer
+- * controller will be word-at-a-time.
+- *
+- * An example of an AB-Synchronized transfer is a device using a FIFO.
+- * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
+- * The controller with the FIFO issues DMA synchronization events when
+- * the FIFO threshold is reached, and the DMA transfer controller will
+- * transfer one frame to (or from) the FIFO. It will probably use
+- * efficient burst modes to access memory.
+- */
+-void edma_set_transfer_params(unsigned slot,
+- u16 acnt, u16 bcnt, u16 ccnt,
+- u16 bcnt_rld, enum sync_dimension sync_mode)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- edma_parm_modify(ctlr, PARM_LINK_BCNTRLD, slot,
+- 0x0000ffff, bcnt_rld << 16);
+- if (sync_mode == ASYNC)
+- edma_parm_and(ctlr, PARM_OPT, slot, ~SYNCDIM);
+- else
+- edma_parm_or(ctlr, PARM_OPT, slot, SYNCDIM);
+- /* Set the acount, bcount, ccount registers */
+- edma_parm_write(ctlr, PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
+- edma_parm_write(ctlr, PARM_CCNT, slot, ccnt);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_transfer_params);
+-
+-/**
+- * edma_link - link one parameter RAM slot to another
+- * @from: parameter RAM slot originating the link
+- * @to: parameter RAM slot which is the link target
+- *
+- * The originating slot should not be part of any active DMA transfer.
+- */
+-void edma_link(unsigned from, unsigned to)
+-{
+- unsigned ctlr_from, ctlr_to;
+-
+- ctlr_from = EDMA_CTLR(from);
+- from = EDMA_CHAN_SLOT(from);
+- ctlr_to = EDMA_CTLR(to);
+- to = EDMA_CHAN_SLOT(to);
+-
+- if (from >= edma_cc[ctlr_from]->num_slots)
+- return;
+- if (to >= edma_cc[ctlr_to]->num_slots)
+- return;
+- edma_parm_modify(ctlr_from, PARM_LINK_BCNTRLD, from, 0xffff0000,
+- PARM_OFFSET(to));
+-}
+-EXPORT_SYMBOL(edma_link);
+-
+-/**
+- * edma_unlink - cut link from one parameter RAM slot
+- * @from: parameter RAM slot originating the link
+- *
+- * The originating slot should not be part of any active DMA transfer.
+- * Its link is set to 0xffff.
+- */
+-void edma_unlink(unsigned from)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(from);
+- from = EDMA_CHAN_SLOT(from);
+-
+- if (from >= edma_cc[ctlr]->num_slots)
+- return;
+- edma_parm_or(ctlr, PARM_LINK_BCNTRLD, from, 0xffff);
+-}
+-EXPORT_SYMBOL(edma_unlink);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-/* Parameter RAM operations (ii) -- read/write whole parameter sets */
+-
+-/**
+- * edma_write_slot - write parameter RAM data for slot
+- * @slot: number of parameter RAM slot being modified
+- * @param: data to be written into parameter RAM slot
+- *
+- * Use this to assign all parameters of a transfer at once. This
+- * allows more efficient setup of transfers than issuing multiple
+- * calls to set up those parameters in small pieces, and provides
+- * complete control over all transfer options.
+- */
+-void edma_write_slot(unsigned slot, const struct edmacc_param *param)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot >= edma_cc[ctlr]->num_slots)
+- return;
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), param,
+- PARM_SIZE);
+-}
+-EXPORT_SYMBOL(edma_write_slot);
+-
+-/**
+- * edma_read_slot - read parameter RAM data from slot
+- * @slot: number of parameter RAM slot being copied
+- * @param: where to store copy of parameter RAM data
+- *
+- * Use this to read data from a parameter RAM slot, perhaps to
+- * save them as a template for later reuse.
+- */
+-void edma_read_slot(unsigned slot, struct edmacc_param *param)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot >= edma_cc[ctlr]->num_slots)
+- return;
+- memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+- PARM_SIZE);
+-}
+-EXPORT_SYMBOL(edma_read_slot);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-/* Various EDMA channel control operations */
+-
+-/**
+- * edma_pause - pause dma on a channel
+- * @channel: on which edma_start() has been called
+- *
+- * This temporarily disables EDMA hardware events on the specified channel,
+- * preventing them from triggering new transfers on its behalf
+- */
+-void edma_pause(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask);
+- }
+-}
+-EXPORT_SYMBOL(edma_pause);
+-
+-/**
+- * edma_resume - resumes dma on a paused channel
+- * @channel: on which edma_pause() has been called
+- *
+- * This re-enables EDMA hardware events on the specified channel.
+- */
+-void edma_resume(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask);
+- }
+-}
+-EXPORT_SYMBOL(edma_resume);
+-
+-/**
+- * edma_start - start dma on a channel
+- * @channel: channel being activated
+- *
+- * Channels with event associations will be triggered by their hardware
+- * events, and channels without such associations will be triggered by
+- * software. (At this writing there is no interface for using software
+- * triggers except with channels that don't support hardware triggers.)
+- *
+- * Returns zero on success, else negative errno.
+- */
+-int edma_start(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- int j = channel >> 5;
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- /* EDMA channels without event association */
+- if (test_bit(channel, edma_cc[ctlr]->edma_unused)) {
+- pr_debug("EDMA: ESR%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_ESR, j));
+- edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
+- return 0;
+- }
+-
+- /* EDMA channel with event association */
+- pr_debug("EDMA: ER%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_ER, j));
+- /* Clear any pending event or error */
+- edma_write_array(ctlr, EDMA_ECR, j, mask);
+- edma_write_array(ctlr, EDMA_EMCR, j, mask);
+- /* Clear any SER */
+- edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+- edma_shadow0_write_array(ctlr, SH_EESR, j, mask);
+- pr_debug("EDMA: EER%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_EER, j));
+- return 0;
+- }
+-
+- return -EINVAL;
+-}
+-EXPORT_SYMBOL(edma_start);
+-
+-/**
+- * edma_stop - stops dma on the channel passed
+- * @channel: channel being deactivated
+- *
+- * When @lch is a channel, any active transfer is paused and
+- * all pending hardware events are cleared. The current transfer
+- * may not be resumed, and the channel's Parameter RAM should be
+- * reinitialized before being reused.
+- */
+-void edma_stop(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- int j = channel >> 5;
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- edma_shadow0_write_array(ctlr, SH_EECR, j, mask);
+- edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
+- edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+- edma_write_array(ctlr, EDMA_EMCR, j, mask);
+-
+- pr_debug("EDMA: EER%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_EER, j));
+-
+- /* REVISIT: consider guarding against inappropriate event
+- * chaining by overwriting with dummy_paramset.
+- */
+- }
+-}
+-EXPORT_SYMBOL(edma_stop);
+-
+-/******************************************************************************
+- *
+- * It cleans ParamEntry qand bring back EDMA to initial state if media has
+- * been removed before EDMA has finished.It is usedful for removable media.
+- * Arguments:
+- * ch_no - channel no
+- *
+- * Return: zero on success, or corresponding error no on failure
+- *
+- * FIXME this should not be needed ... edma_stop() should suffice.
+- *
+- *****************************************************************************/
+-
+-void edma_clean_channel(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- int j = (channel >> 5);
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- pr_debug("EDMA: EMR%d %08x\n", j,
+- edma_read_array(ctlr, EDMA_EMR, j));
+- edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
+- /* Clear the corresponding EMR bits */
+- edma_write_array(ctlr, EDMA_EMCR, j, mask);
+- /* Clear any SER */
+- edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+- edma_write(ctlr, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
+- }
+-}
+-EXPORT_SYMBOL(edma_clean_channel);
+-
+-/*
+- * edma_clear_event - clear an outstanding event on the DMA channel
+- * Arguments:
+- * channel - channel number
+- */
+-void edma_clear_event(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel >= edma_cc[ctlr]->num_channels)
+- return;
+- if (channel < 32)
+- edma_write(ctlr, EDMA_ECR, BIT(channel));
+- else
+- edma_write(ctlr, EDMA_ECRH, BIT(channel - 32));
+-}
+-EXPORT_SYMBOL(edma_clear_event);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-static int __init edma_probe(struct platform_device *pdev)
+-{
+- struct edma_soc_info **info = pdev->dev.platform_data;
+- const s8 (*queue_priority_mapping)[2];
+- const s8 (*queue_tc_mapping)[2];
+- int i, j, off, ln, found = 0;
+- int status = -1;
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
+- int irq[EDMA_MAX_CC] = {0, 0};
+- int err_irq[EDMA_MAX_CC] = {0, 0};
+- struct resource *r[EDMA_MAX_CC] = {NULL};
+- resource_size_t len[EDMA_MAX_CC];
+- char res_name[10];
+- char irq_name[10];
+-
+- if (!info)
+- return -ENODEV;
+-
+- for (j = 0; j < EDMA_MAX_CC; j++) {
+- sprintf(res_name, "edma_cc%d", j);
+- r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+- res_name);
+- if (!r[j] || !info[j]) {
+- if (found)
+- break;
+- else
+- return -ENODEV;
+- } else {
+- found = 1;
+- }
+-
+- len[j] = resource_size(r[j]);
+-
+- r[j] = request_mem_region(r[j]->start, len[j],
+- dev_name(&pdev->dev));
+- if (!r[j]) {
+- status = -EBUSY;
+- goto fail1;
+- }
+-
+- edmacc_regs_base[j] = ioremap(r[j]->start, len[j]);
+- if (!edmacc_regs_base[j]) {
+- status = -EBUSY;
+- goto fail1;
+- }
+-
+- edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
+- if (!edma_cc[j]) {
+- status = -ENOMEM;
+- goto fail1;
+- }
+-
+- edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
+- EDMA_MAX_DMACH);
+- edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
+- EDMA_MAX_PARAMENTRY);
+- edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
+- EDMA_MAX_CC);
+-
+- edma_cc[j]->default_queue = info[j]->default_queue;
+-
+- dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
+- edmacc_regs_base[j]);
+-
+- for (i = 0; i < edma_cc[j]->num_slots; i++)
+- memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
+- &dummy_paramset, PARM_SIZE);
+-
+- /* Mark all channels as unused */
+- memset(edma_cc[j]->edma_unused, 0xff,
+- sizeof(edma_cc[j]->edma_unused));
+-
+- if (info[j]->rsv) {
+-
+- /* Clear the reserved channels in unused list */
+- rsv_chans = info[j]->rsv->rsv_chans;
+- if (rsv_chans) {
+- for (i = 0; rsv_chans[i][0] != -1; i++) {
+- off = rsv_chans[i][0];
+- ln = rsv_chans[i][1];
+- clear_bits(off, ln,
+- edma_cc[j]->edma_unused);
+- }
+- }
+-
+- /* Set the reserved slots in inuse list */
+- rsv_slots = info[j]->rsv->rsv_slots;
+- if (rsv_slots) {
+- for (i = 0; rsv_slots[i][0] != -1; i++) {
+- off = rsv_slots[i][0];
+- ln = rsv_slots[i][1];
+- set_bits(off, ln,
+- edma_cc[j]->edma_inuse);
+- }
+- }
+- }
+-
+- sprintf(irq_name, "edma%d", j);
+- irq[j] = platform_get_irq_byname(pdev, irq_name);
+- edma_cc[j]->irq_res_start = irq[j];
+- status = request_irq(irq[j], dma_irq_handler, 0, "edma",
+- &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- irq[j], status);
+- goto fail;
+- }
+-
+- sprintf(irq_name, "edma%d_err", j);
+- err_irq[j] = platform_get_irq_byname(pdev, irq_name);
+- edma_cc[j]->irq_res_end = err_irq[j];
+- status = request_irq(err_irq[j], dma_ccerr_handler, 0,
+- "edma_error", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- err_irq[j], status);
+- goto fail;
+- }
+-
+- for (i = 0; i < edma_cc[j]->num_channels; i++)
+- map_dmach_queue(j, i, info[j]->default_queue);
+-
+- queue_tc_mapping = info[j]->queue_tc_mapping;
+- queue_priority_mapping = info[j]->queue_priority_mapping;
+-
+- /* Event queue to TC mapping */
+- for (i = 0; queue_tc_mapping[i][0] != -1; i++)
+- map_queue_tc(j, queue_tc_mapping[i][0],
+- queue_tc_mapping[i][1]);
+-
+- /* Event queue priority mapping */
+- for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+- assign_priority_to_queue(j,
+- queue_priority_mapping[i][0],
+- queue_priority_mapping[i][1]);
+-
+- /* Map the channel to param entry if channel mapping logic
+- * exist
+- */
+- if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
+- map_dmach_param(j);
+-
+- for (i = 0; i < info[j]->n_region; i++) {
+- edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
+- edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
+- edma_write_array(j, EDMA_QRAE, i, 0x0);
+- }
+- arch_num_cc++;
+- }
+-
+- if (tc_errs_handled) {
+- status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
+- "edma_tc0", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- IRQ_TCERRINT0, status);
+- return status;
+- }
+- status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
+- "edma_tc1", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
+- IRQ_TCERRINT, status);
+- return status;
+- }
+- }
+-
+- return 0;
+-
+-fail:
+- for (i = 0; i < EDMA_MAX_CC; i++) {
+- if (err_irq[i])
+- free_irq(err_irq[i], &pdev->dev);
+- if (irq[i])
+- free_irq(irq[i], &pdev->dev);
+- }
+-fail1:
+- for (i = 0; i < EDMA_MAX_CC; i++) {
+- if (r[i])
+- release_mem_region(r[i]->start, len[i]);
+- if (edmacc_regs_base[i])
+- iounmap(edmacc_regs_base[i]);
+- kfree(edma_cc[i]);
+- }
+- return status;
+-}
+-
+-
+-static struct platform_driver edma_driver = {
+- .driver.name = "edma",
+-};
+-
+-static int __init edma_init(void)
+-{
+- return platform_driver_probe(&edma_driver, edma_probe);
+-}
+-arch_initcall(edma_init);
+-
+diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
+index aaccdc4..4380691 100644
+--- a/arch/arm/mach-davinci/include/mach/da8xx.h
++++ b/arch/arm/mach-davinci/include/mach/da8xx.h
+@@ -20,8 +20,8 @@
+ #include <linux/videodev2.h>
+
+ #include <mach/serial.h>
+-#include <mach/edma.h>
+ #include <mach/pm.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/platform_data/i2c-davinci.h>
+ #include <linux/platform_data/mmc-davinci.h>
+ #include <linux/platform_data/usb-davinci.h>
+diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
+deleted file mode 100644
+index 7e84c90..0000000
+--- a/arch/arm/mach-davinci/include/mach/edma.h
++++ /dev/null
+@@ -1,267 +0,0 @@
+-/*
+- * TI DAVINCI dma definitions
+- *
+- * Copyright (C) 2006-2009 Texas Instruments.
+- *
+- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- * 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.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-/*
+- * This EDMA3 programming framework exposes two basic kinds of resource:
+- *
+- * Channel Triggers transfers, usually from a hardware event but
+- * also manually or by "chaining" from DMA completions.
+- * Each channel is coupled to a Parameter RAM (PaRAM) slot.
+- *
+- * Slot Each PaRAM slot holds a DMA transfer descriptor (PaRAM
+- * "set"), source and destination addresses, a link to a
+- * next PaRAM slot (if any), options for the transfer, and
+- * instructions for updating those addresses. There are
+- * more than twice as many slots as event channels.
+- *
+- * Each PaRAM set describes a sequence of transfers, either for one large
+- * buffer or for several discontiguous smaller buffers. An EDMA transfer
+- * is driven only from a channel, which performs the transfers specified
+- * in its PaRAM slot until there are no more transfers. When that last
+- * transfer completes, the "link" field may be used to reload the channel's
+- * PaRAM slot with a new transfer descriptor.
+- *
+- * The EDMA Channel Controller (CC) maps requests from channels into physical
+- * Transfer Controller (TC) requests when the channel triggers (by hardware
+- * or software events, or by chaining). The two physical DMA channels provided
+- * by the TCs are thus shared by many logical channels.
+- *
+- * DaVinci hardware also has a "QDMA" mechanism which is not currently
+- * supported through this interface. (DSP firmware uses it though.)
+- */
+-
+-#ifndef EDMA_H_
+-#define EDMA_H_
+-
+-/* PaRAM slots are laid out like this */
+-struct edmacc_param {
+- unsigned int opt;
+- unsigned int src;
+- unsigned int a_b_cnt;
+- unsigned int dst;
+- unsigned int src_dst_bidx;
+- unsigned int link_bcntrld;
+- unsigned int src_dst_cidx;
+- unsigned int ccnt;
+-};
+-
+-#define CCINT0_INTERRUPT 16
+-#define CCERRINT_INTERRUPT 17
+-#define TCERRINT0_INTERRUPT 18
+-#define TCERRINT1_INTERRUPT 19
+-
+-/* fields in edmacc_param.opt */
+-#define SAM BIT(0)
+-#define DAM BIT(1)
+-#define SYNCDIM BIT(2)
+-#define STATIC BIT(3)
+-#define EDMA_FWID (0x07 << 8)
+-#define TCCMODE BIT(11)
+-#define EDMA_TCC(t) ((t) << 12)
+-#define TCINTEN BIT(20)
+-#define ITCINTEN BIT(21)
+-#define TCCHEN BIT(22)
+-#define ITCCHEN BIT(23)
+-
+-#define TRWORD (0x7<<2)
+-#define PAENTRY (0x1ff<<5)
+-
+-/* Drivers should avoid using these symbolic names for dm644x
+- * channels, and use platform_device IORESOURCE_DMA resources
+- * instead. (Other DaVinci chips have different peripherals
+- * and thus have different DMA channel mappings.)
+- */
+-#define DAVINCI_DMA_MCBSP_TX 2
+-#define DAVINCI_DMA_MCBSP_RX 3
+-#define DAVINCI_DMA_VPSS_HIST 4
+-#define DAVINCI_DMA_VPSS_H3A 5
+-#define DAVINCI_DMA_VPSS_PRVU 6
+-#define DAVINCI_DMA_VPSS_RSZ 7
+-#define DAVINCI_DMA_IMCOP_IMXINT 8
+-#define DAVINCI_DMA_IMCOP_VLCDINT 9
+-#define DAVINCI_DMA_IMCO_PASQINT 10
+-#define DAVINCI_DMA_IMCOP_DSQINT 11
+-#define DAVINCI_DMA_SPI_SPIX 16
+-#define DAVINCI_DMA_SPI_SPIR 17
+-#define DAVINCI_DMA_UART0_URXEVT0 18
+-#define DAVINCI_DMA_UART0_UTXEVT0 19
+-#define DAVINCI_DMA_UART1_URXEVT1 20
+-#define DAVINCI_DMA_UART1_UTXEVT1 21
+-#define DAVINCI_DMA_UART2_URXEVT2 22
+-#define DAVINCI_DMA_UART2_UTXEVT2 23
+-#define DAVINCI_DMA_MEMSTK_MSEVT 24
+-#define DAVINCI_DMA_MMCRXEVT 26
+-#define DAVINCI_DMA_MMCTXEVT 27
+-#define DAVINCI_DMA_I2C_ICREVT 28
+-#define DAVINCI_DMA_I2C_ICXEVT 29
+-#define DAVINCI_DMA_GPIO_GPINT0 32
+-#define DAVINCI_DMA_GPIO_GPINT1 33
+-#define DAVINCI_DMA_GPIO_GPINT2 34
+-#define DAVINCI_DMA_GPIO_GPINT3 35
+-#define DAVINCI_DMA_GPIO_GPINT4 36
+-#define DAVINCI_DMA_GPIO_GPINT5 37
+-#define DAVINCI_DMA_GPIO_GPINT6 38
+-#define DAVINCI_DMA_GPIO_GPINT7 39
+-#define DAVINCI_DMA_GPIO_GPBNKINT0 40
+-#define DAVINCI_DMA_GPIO_GPBNKINT1 41
+-#define DAVINCI_DMA_GPIO_GPBNKINT2 42
+-#define DAVINCI_DMA_GPIO_GPBNKINT3 43
+-#define DAVINCI_DMA_GPIO_GPBNKINT4 44
+-#define DAVINCI_DMA_TIMER0_TINT0 48
+-#define DAVINCI_DMA_TIMER1_TINT1 49
+-#define DAVINCI_DMA_TIMER2_TINT2 50
+-#define DAVINCI_DMA_TIMER3_TINT3 51
+-#define DAVINCI_DMA_PWM0 52
+-#define DAVINCI_DMA_PWM1 53
+-#define DAVINCI_DMA_PWM2 54
+-
+-/* DA830 specific EDMA3 information */
+-#define EDMA_DA830_NUM_DMACH 32
+-#define EDMA_DA830_NUM_TCC 32
+-#define EDMA_DA830_NUM_PARAMENTRY 128
+-#define EDMA_DA830_NUM_EVQUE 2
+-#define EDMA_DA830_NUM_TC 2
+-#define EDMA_DA830_CHMAP_EXIST 0
+-#define EDMA_DA830_NUM_REGIONS 4
+-#define DA830_DMACH2EVENT_MAP0 0x000FC03Fu
+-#define DA830_DMACH2EVENT_MAP1 0x00000000u
+-#define DA830_EDMA_ARM_OWN 0x30FFCCFFu
+-
+-/*ch_status paramater of callback function possible values*/
+-#define DMA_COMPLETE 1
+-#define DMA_CC_ERROR 2
+-#define DMA_TC1_ERROR 3
+-#define DMA_TC2_ERROR 4
+-
+-enum address_mode {
+- INCR = 0,
+- FIFO = 1
+-};
+-
+-enum fifo_width {
+- W8BIT = 0,
+- W16BIT = 1,
+- W32BIT = 2,
+- W64BIT = 3,
+- W128BIT = 4,
+- W256BIT = 5
+-};
+-
+-enum dma_event_q {
+- EVENTQ_0 = 0,
+- EVENTQ_1 = 1,
+- EVENTQ_2 = 2,
+- EVENTQ_3 = 3,
+- EVENTQ_DEFAULT = -1
+-};
+-
+-enum sync_dimension {
+- ASYNC = 0,
+- ABSYNC = 1
+-};
+-
+-#define EDMA_CTLR_CHAN(ctlr, chan) (((ctlr) << 16) | (chan))
+-#define EDMA_CTLR(i) ((i) >> 16)
+-#define EDMA_CHAN_SLOT(i) ((i) & 0xffff)
+-
+-#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */
+-#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */
+-#define EDMA_CONT_PARAMS_ANY 1001
+-#define EDMA_CONT_PARAMS_FIXED_EXACT 1002
+-#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
+-
+-#define EDMA_MAX_CC 2
+-
+-/* alloc/free DMA channels and their dedicated parameter RAM slots */
+-int edma_alloc_channel(int channel,
+- void (*callback)(unsigned channel, u16 ch_status, void *data),
+- void *data, enum dma_event_q);
+-void edma_free_channel(unsigned channel);
+-
+-/* alloc/free parameter RAM slots */
+-int edma_alloc_slot(unsigned ctlr, int slot);
+-void edma_free_slot(unsigned slot);
+-
+-/* alloc/free a set of contiguous parameter RAM slots */
+-int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count);
+-int edma_free_cont_slots(unsigned slot, int count);
+-
+-/* calls that operate on part of a parameter RAM slot */
+-void edma_set_src(unsigned slot, dma_addr_t src_port,
+- enum address_mode mode, enum fifo_width);
+-void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+- enum address_mode mode, enum fifo_width);
+-void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
+-void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
+-void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
+-void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
+- u16 bcnt_rld, enum sync_dimension sync_mode);
+-void edma_link(unsigned from, unsigned to);
+-void edma_unlink(unsigned from);
+-
+-/* calls that operate on an entire parameter RAM slot */
+-void edma_write_slot(unsigned slot, const struct edmacc_param *params);
+-void edma_read_slot(unsigned slot, struct edmacc_param *params);
+-
+-/* channel control operations */
+-int edma_start(unsigned channel);
+-void edma_stop(unsigned channel);
+-void edma_clean_channel(unsigned channel);
+-void edma_clear_event(unsigned channel);
+-void edma_pause(unsigned channel);
+-void edma_resume(unsigned channel);
+-
+-struct edma_rsv_info {
+-
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
+-};
+-
+-/* platform_data for EDMA driver */
+-struct edma_soc_info {
+-
+- /* how many dma resources of each type */
+- unsigned n_channel;
+- unsigned n_region;
+- unsigned n_slot;
+- unsigned n_tc;
+- unsigned n_cc;
+- /*
+- * Default queue is expected to be a low-priority queue.
+- * This way, long transfers on the default queue started
+- * by the codec engine will not cause audio defects.
+- */
+- enum dma_event_q default_queue;
+-
+- /* Resource reservation for other cores */
+- struct edma_rsv_info *rsv;
+-
+- const s8 (*queue_tc_mapping)[2];
+- const s8 (*queue_priority_mapping)[2];
+-};
+-
+-#endif
+diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
+index 82fcb20..74ce024 100644
+--- a/arch/arm/plat-omap/Kconfig
++++ b/arch/arm/plat-omap/Kconfig
+@@ -29,6 +29,7 @@ config ARCH_OMAP2PLUS
+ select PINCTRL
+ select PROC_DEVICETREE if PROC_FS
+ select SPARSE_IRQ
++ select TI_PRIV_EDMA
+ select USE_OF
+ help
+ "Systems based on OMAP2, OMAP3, OMAP4 or OMAP5"
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index fdcf079..47ba7bf 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -24,7 +24,7 @@
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ #include "dmaengine.h"
+ #include "virt-dma.h"
+diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
+index 2063677..f5d46ea 100644
+--- a/drivers/mmc/host/davinci_mmc.c
++++ b/drivers/mmc/host/davinci_mmc.c
+@@ -35,6 +35,7 @@
+ #include <linux/edma.h>
+ #include <linux/mmc/mmc.h>
+
++#include <linux/platform_data/edma.h>
+ #include <linux/platform_data/mmc-davinci.h>
+
+ /*
+diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h
+index 0ab6132..7dd6524 100644
+--- a/include/linux/mfd/davinci_voicecodec.h
++++ b/include/linux/mfd/davinci_voicecodec.h
+@@ -26,8 +26,7 @@
+ #include <linux/kernel.h>
+ #include <linux/platform_device.h>
+ #include <linux/mfd/core.h>
+-
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ /*
+ * Register values.
+diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
+new file mode 100644
+index 0000000..7396f0b3
+--- /dev/null
++++ b/include/linux/platform_data/edma.h
+@@ -0,0 +1,198 @@
++/*
++ * TI DAVINCI dma definitions
++ *
++ * Copyright (C) 2006-2009 Texas Instruments.
++ *
++ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * This EDMA3 programming framework exposes two basic kinds of resource:
++ *
++ * Channel Triggers transfers, usually from a hardware event but
++ * also manually or by "chaining" from DMA completions.
++ * Each channel is coupled to a Parameter RAM (PaRAM) slot.
++ *
++ * Slot Each PaRAM slot holds a DMA transfer descriptor (PaRAM
++ * "set"), source and destination addresses, a link to a
++ * next PaRAM slot (if any), options for the transfer, and
++ * instructions for updating those addresses. There are
++ * more than twice as many slots as event channels.
++ *
++ * Each PaRAM set describes a sequence of transfers, either for one large
++ * buffer or for several discontiguous smaller buffers. An EDMA transfer
++ * is driven only from a channel, which performs the transfers specified
++ * in its PaRAM slot until there are no more transfers. When that last
++ * transfer completes, the "link" field may be used to reload the channel's
++ * PaRAM slot with a new transfer descriptor.
++ *
++ * The EDMA Channel Controller (CC) maps requests from channels into physical
++ * Transfer Controller (TC) requests when the channel triggers (by hardware
++ * or software events, or by chaining). The two physical DMA channels provided
++ * by the TCs are thus shared by many logical channels.
++ *
++ * DaVinci hardware also has a "QDMA" mechanism which is not currently
++ * supported through this interface. (DSP firmware uses it though.)
++ */
++
++#ifndef EDMA_H_
++#define EDMA_H_
++
++/* PaRAM slots are laid out like this */
++struct edmacc_param {
++ unsigned int opt;
++ unsigned int src;
++ unsigned int a_b_cnt;
++ unsigned int dst;
++ unsigned int src_dst_bidx;
++ unsigned int link_bcntrld;
++ unsigned int src_dst_cidx;
++ unsigned int ccnt;
++};
++
++/* fields in edmacc_param.opt */
++#define SAM BIT(0)
++#define DAM BIT(1)
++#define SYNCDIM BIT(2)
++#define STATIC BIT(3)
++#define EDMA_FWID (0x07 << 8)
++#define TCCMODE BIT(11)
++#define EDMA_TCC(t) ((t) << 12)
++#define TCINTEN BIT(20)
++#define ITCINTEN BIT(21)
++#define TCCHEN BIT(22)
++#define ITCCHEN BIT(23)
++
++/*ch_status paramater of callback function possible values*/
++#define DMA_COMPLETE 1
++#define DMA_CC_ERROR 2
++#define DMA_TC1_ERROR 3
++#define DMA_TC2_ERROR 4
++
++enum address_mode {
++ INCR = 0,
++ FIFO = 1
++};
++
++enum fifo_width {
++ W8BIT = 0,
++ W16BIT = 1,
++ W32BIT = 2,
++ W64BIT = 3,
++ W128BIT = 4,
++ W256BIT = 5
++};
++
++enum dma_event_q {
++ EVENTQ_0 = 0,
++ EVENTQ_1 = 1,
++ EVENTQ_2 = 2,
++ EVENTQ_3 = 3,
++ EVENTQ_DEFAULT = -1
++};
++
++enum sync_dimension {
++ ASYNC = 0,
++ ABSYNC = 1
++};
++
++#define EDMA_CTLR_CHAN(ctlr, chan) (((ctlr) << 16) | (chan))
++#define EDMA_CTLR(i) ((i) >> 16)
++#define EDMA_CHAN_SLOT(i) ((i) & 0xffff)
++
++#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */
++#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */
++#define EDMA_CONT_PARAMS_ANY 1001
++#define EDMA_CONT_PARAMS_FIXED_EXACT 1002
++#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
++
++#define EDMA_MAX_CC 2
++
++/* alloc/free DMA channels and their dedicated parameter RAM slots */
++int edma_alloc_channel(int channel,
++ void (*callback)(unsigned channel, u16 ch_status, void *data),
++ void *data, enum dma_event_q);
++void edma_free_channel(unsigned channel);
++
++/* alloc/free parameter RAM slots */
++int edma_alloc_slot(unsigned ctlr, int slot);
++void edma_free_slot(unsigned slot);
++
++/* alloc/free a set of contiguous parameter RAM slots */
++int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count);
++int edma_free_cont_slots(unsigned slot, int count);
++
++/* calls that operate on part of a parameter RAM slot */
++void edma_set_src(unsigned slot, dma_addr_t src_port,
++ enum address_mode mode, enum fifo_width);
++void edma_set_dest(unsigned slot, dma_addr_t dest_port,
++ enum address_mode mode, enum fifo_width);
++void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
++void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
++void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
++void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
++ u16 bcnt_rld, enum sync_dimension sync_mode);
++void edma_link(unsigned from, unsigned to);
++void edma_unlink(unsigned from);
++
++/* calls that operate on an entire parameter RAM slot */
++void edma_write_slot(unsigned slot, const struct edmacc_param *params);
++void edma_read_slot(unsigned slot, struct edmacc_param *params);
++
++/* channel control operations */
++int edma_start(unsigned channel);
++void edma_stop(unsigned channel);
++void edma_clean_channel(unsigned channel);
++void edma_clear_event(unsigned channel);
++void edma_pause(unsigned channel);
++void edma_resume(unsigned channel);
++
++struct edma_rsv_info {
++
++ const s16 (*rsv_chans)[2];
++ const s16 (*rsv_slots)[2];
++};
++
++/* platform_data for EDMA driver */
++struct edma_soc_info {
++
++ /* how many dma resources of each type */
++ unsigned n_channel;
++ unsigned n_region;
++ unsigned n_slot;
++ unsigned n_tc;
++ unsigned n_cc;
++ /*
++ * Default queue is expected to be a low-priority queue.
++ * This way, long transfers on the default queue started
++ * by the codec engine will not cause audio defects.
++ */
++ enum dma_event_q default_queue;
++
++ /* Resource reservation for other cores */
++ struct edma_rsv_info *rsv;
++
++ const s8 (*queue_tc_mapping)[2];
++ const s8 (*queue_priority_mapping)[2];
++};
++
++#endif
+diff --git a/include/linux/platform_data/spi-davinci.h b/include/linux/platform_data/spi-davinci.h
+index 7af305b..8dc2fa47 100644
+--- a/include/linux/platform_data/spi-davinci.h
++++ b/include/linux/platform_data/spi-davinci.h
+@@ -19,7 +19,7 @@
+ #ifndef __ARCH_ARM_DAVINCI_SPI_H
+ #define __ARCH_ARM_DAVINCI_SPI_H
+
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ #define SPI_INTERN_CS 0xFF
+
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+index 6fac5af..44365d5 100644
+--- a/sound/soc/davinci/davinci-evm.c
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -14,6 +14,7 @@
+ #include <linux/timer.h>
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/i2c.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
+index 93ea3bf..c9d1b7a 100644
+--- a/sound/soc/davinci/davinci-pcm.c
++++ b/sound/soc/davinci/davinci-pcm.c
+@@ -16,6 +16,7 @@
+ #include <linux/slab.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/kernel.h>
++#include <linux/platform_data/edma.h>
+
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
+index fc4d01c..deab6c3 100644
+--- a/sound/soc/davinci/davinci-pcm.h
++++ b/sound/soc/davinci/davinci-pcm.h
+@@ -13,7 +13,7 @@
+ #define _DAVINCI_PCM_H
+
+ #include <linux/platform_data/davinci_asp.h>
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ struct davinci_pcm_dma_params {
+ int channel; /* sync dma channel ID */
+diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
+index 5be65aa..5345e63 100644
+--- a/sound/soc/davinci/davinci-sffsdr.c
++++ b/sound/soc/davinci/davinci-sffsdr.c
+@@ -17,6 +17,7 @@
+ #include <linux/timer.h>
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/gpio.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+@@ -28,7 +29,6 @@
+ #include <asm/plat-sffsdr/sffsdr-fpga.h>
+ #endif
+
+-#include <mach/edma.h>
+
+ #include "../codecs/pcm3008.h"
+ #include "davinci-pcm.h"
+@@ -123,8 +123,8 @@ static struct resource sffsdr_snd_resources[] = {
+ };
+
+ static struct evm_snd_platform_data sffsdr_snd_data = {
+- .tx_dma_ch = DAVINCI_DMA_MCBSP_TX,
+- .rx_dma_ch = DAVINCI_DMA_MCBSP_RX,
++ .tx_dma_ch = 2,
++ .rx_dma_ch = 3,
+ };
+
+ static struct platform_device *sffsdr_snd_device;
diff --git a/patches/linux-3.7-rc6/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch b/patches/linux-3.7-rc6/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch
new file mode 100644
index 0000000..f05c02a
--- /dev/null
+++ b/patches/linux-3.7-rc6/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch
@@ -0,0 +1,69 @@
+From 9b14772219c6edaf900645ad688abf8591f6c6a7 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 22 Aug 2012 09:31:49 -0400
+Subject: [PATCH] ARM: edma: remove unused transfer controller handlers
+
+Fix build on OMAP, the irqs are undefined on AM33xx.
+These error interrupt handlers were hardcoded as disabled
+so since they are unused code, simply remove them.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 37 -------------------------------------
+ 1 file changed, 37 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index 4411087..a3d189d 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -494,26 +494,6 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data)
+ return IRQ_HANDLED;
+ }
+
+-/******************************************************************************
+- *
+- * Transfer controller error interrupt handlers
+- *
+- *****************************************************************************/
+-
+-#define tc_errs_handled false /* disabled as long as they're NOPs */
+-
+-static irqreturn_t dma_tc0err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc0err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t dma_tc1err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc1err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+ static int reserve_contiguous_slots(int ctlr, unsigned int id,
+ unsigned int num_slots,
+ unsigned int start_slot)
+@@ -1538,23 +1518,6 @@ static int __init edma_probe(struct platform_device *pdev)
+ arch_num_cc++;
+ }
+
+- if (tc_errs_handled) {
+- status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
+- "edma_tc0", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- IRQ_TCERRINT0, status);
+- return status;
+- }
+- status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
+- "edma_tc1", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
+- IRQ_TCERRINT, status);
+- return status;
+- }
+- }
+-
+ return 0;
+
+ fail:
diff --git a/patches/linux-3.7-rc6/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch b/patches/linux-3.7-rc6/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch
new file mode 100644
index 0000000..e197daf
--- /dev/null
+++ b/patches/linux-3.7-rc6/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch
@@ -0,0 +1,633 @@
+From 98622c01c7b234d869066035776c906feff18a53 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 6 Sep 2012 17:40:42 -0400
+Subject: [PATCH] ARM: edma: add DT and runtime PM support for AM33XX
+
+Adds support for parsing the TI EDMA DT data into the required
+EDMA private API platform data.
+
+Calls runtime PM API only in the DT case in order to unidle the
+associated hwmods on AM33XX.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 255 +++++++++++++++++++++++++--
+ arch/arm/mach-davinci/board-da830-evm.c | 4 +-
+ arch/arm/mach-davinci/board-da850-evm.c | 8 +-
+ arch/arm/mach-davinci/board-dm646x-evm.c | 4 +-
+ arch/arm/mach-davinci/board-omapl138-hawk.c | 8 +-
+ arch/arm/mach-davinci/devices-da8xx.c | 8 +-
+ arch/arm/mach-davinci/devices-tnetv107x.c | 4 +-
+ arch/arm/mach-davinci/dm355.c | 4 +-
+ arch/arm/mach-davinci/dm365.c | 4 +-
+ arch/arm/mach-davinci/dm644x.c | 4 +-
+ arch/arm/mach-davinci/dm646x.c | 4 +-
+ include/linux/platform_data/edma.h | 8 +-
+ 12 files changed, 272 insertions(+), 43 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index a3d189d..6d2a590 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -24,6 +24,13 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/slab.h>
++#include <linux/edma.h>
++#include <linux/err.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/of_dma.h>
++#include <linux/of_irq.h>
++#include <linux/pm_runtime.h>
+
+ #include <linux/platform_data/edma.h>
+
+@@ -1366,31 +1373,237 @@ void edma_clear_event(unsigned channel)
+ EXPORT_SYMBOL(edma_clear_event);
+
+ /*-----------------------------------------------------------------------*/
++static int edma_of_read_u32_to_s8_array(const struct device_node *np,
++ const char *propname, s8 *out_values,
++ size_t sz)
++{
++ struct property *prop = of_find_property(np, propname, NULL);
++ const __be32 *val;
++
++ if (!prop)
++ return -EINVAL;
++ if (!prop->value)
++ return -ENODATA;
++ if ((sz * sizeof(u32)) > prop->length)
++ return -EOVERFLOW;
++
++ val = prop->value;
++
++ while (sz--)
++ *out_values++ = (s8)(be32_to_cpup(val++) & 0xff);
++
++ /* Terminate it */
++ *out_values++ = -1;
++ *out_values++ = -1;
++
++ return 0;
++}
++
++static int edma_of_read_u32_to_s16_array(const struct device_node *np,
++ const char *propname, s16 *out_values,
++ size_t sz)
++{
++ struct property *prop = of_find_property(np, propname, NULL);
++ const __be32 *val;
++
++ if (!prop)
++ return -EINVAL;
++ if (!prop->value)
++ return -ENODATA;
++ if ((sz * sizeof(u32)) > prop->length)
++ return -EOVERFLOW;
++
++ val = prop->value;
++
++ while (sz--)
++ *out_values++ = (s16)(be32_to_cpup(val++) & 0xffff);
++
++ /* Terminate it */
++ *out_values++ = -1;
++ *out_values++ = -1;
++
++ return 0;
++}
++
++static int edma_of_parse_dt(struct device *dev,
++ struct device_node *node,
++ struct edma_soc_info *pdata)
++{
++ int ret = 0;
++ u32 value;
++ struct property *prop;
++ size_t sz;
++ struct edma_rsv_info *rsv_info;
++ s16 (*rsv_chans)[2], (*rsv_slots)[2];
++ s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
++
++ ret = of_property_read_u32(node, "dma-channels", &value);
++ if (ret < 0)
++ return ret;
++ pdata->n_channel = value;
++
++ ret = of_property_read_u32(node, "ti,edma-regions", &value);
++ if (ret < 0)
++ return ret;
++ pdata->n_region = value;
++
++ ret = of_property_read_u32(node, "ti,edma-slots", &value);
++ if (ret < 0)
++ return ret;
++ pdata->n_slot = value;
++
++ pdata->n_cc = 1;
++ /* This is unused */
++ pdata->n_tc = 3;
++
++ rsv_info =
++ devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL);
++ if (!rsv_info)
++ return -ENOMEM;
++ pdata->rsv = rsv_info;
++
++ /* Build the reserved channel/slots arrays */
++ prop = of_find_property(node, "ti,edma-reserved-channels", &sz);
++ if (prop) {
++ rsv_chans = devm_kzalloc(dev,
++ sz/sizeof(s16) + 2*sizeof(s16),
++ GFP_KERNEL);
++ if (!rsv_chans)
++ return -ENOMEM;
++ pdata->rsv->rsv_chans = rsv_chans;
++
++ ret = edma_of_read_u32_to_s16_array(node,
++ "ti,edma-reserved-channels",
++ (s16 *)rsv_chans,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++ }
++
++ prop = of_find_property(node, "ti,edma-reserved-slots", &sz);
++ if (prop) {
++ rsv_slots = devm_kzalloc(dev,
++ sz/sizeof(s16) + 2*sizeof(s16),
++ GFP_KERNEL);
++ if (!rsv_slots)
++ return -ENOMEM;
++ pdata->rsv->rsv_slots = rsv_slots;
++
++ ret = edma_of_read_u32_to_s16_array(node,
++ "ti,edma-reserved-slots",
++ (s16 *)rsv_slots,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++ }
++
++ prop = of_find_property(node, "ti,edma-queue-tc-map", &sz);
++ if (!prop)
++ return -EINVAL;
++
++ queue_tc_map = devm_kzalloc(dev,
++ sz/sizeof(s8) + 2*sizeof(s8),
++ GFP_KERNEL);
++ if (!queue_tc_map)
++ return -ENOMEM;
++ pdata->queue_tc_mapping = queue_tc_map;
++
++ ret = edma_of_read_u32_to_s8_array(node,
++ "ti,edma-queue-tc-map",
++ (s8 *)queue_tc_map,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++
++ prop = of_find_property(node, "ti,edma-queue-priority-map", &sz);
++ if (!prop)
++ return -EINVAL;
++
++ queue_priority_map = devm_kzalloc(dev,
++ sz/sizeof(s8) + 2*sizeof(s8),
++ GFP_KERNEL);
++ if (!queue_priority_map)
++ return -ENOMEM;
++ pdata->queue_priority_mapping = queue_priority_map;
++
++ ret = edma_of_read_u32_to_s8_array(node,
++ "ti,edma-queue-tc-map",
++ (s8 *)queue_priority_map,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++
++ ret = of_property_read_u32(node, "ti,edma-default-queue", &value);
++ if (ret < 0)
++ return ret;
++ pdata->default_queue = value;
++
++ return ret;
++}
++
++static struct of_dma_filter_info edma_filter_info = {
++ .filter_fn = edma_filter_fn,
++};
+
+ static int __init edma_probe(struct platform_device *pdev)
+ {
+ struct edma_soc_info **info = pdev->dev.platform_data;
+- const s8 (*queue_priority_mapping)[2];
+- const s8 (*queue_tc_mapping)[2];
++ s8 (*queue_priority_mapping)[2];
++ s8 (*queue_tc_mapping)[2];
+ int i, j, off, ln, found = 0;
+ int status = -1;
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
++ s16 (*rsv_chans)[2];
++ s16 (*rsv_slots)[2];
+ int irq[EDMA_MAX_CC] = {0, 0};
+ int err_irq[EDMA_MAX_CC] = {0, 0};
+- struct resource *r[EDMA_MAX_CC] = {NULL};
++ struct resource *r[EDMA_MAX_CC] = {NULL, NULL};
++ struct resource res[EDMA_MAX_CC];
+ resource_size_t len[EDMA_MAX_CC];
+ char res_name[10];
+ char irq_name[10];
++ struct device_node *node = pdev->dev.of_node;
++ struct device *dev = &pdev->dev;
++ struct edma_soc_info *pdata;
++ int ret;
++
++ if (node) {
++ pdata = devm_kzalloc(dev,
++ sizeof(struct edma_soc_info),
++ GFP_KERNEL);
++ edma_of_parse_dt(dev, node, pdata);
++ info = &pdata;
++ dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
++ of_dma_controller_register(dev->of_node,
++ of_dma_simple_xlate,
++ &edma_filter_info);
++ pm_runtime_enable(dev);
++ ret = pm_runtime_get_sync(dev);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(dev, "pm_runtime_get_sync() failed\n");
++ return ret;
++ }
++ }
+
+ if (!info)
+ return -ENODEV;
+
+ for (j = 0; j < EDMA_MAX_CC; j++) {
+- sprintf(res_name, "edma_cc%d", j);
+- r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ if (!info[j]) {
++ if (!found)
++ return -ENODEV;
++ break;
++ }
++ if (node) {
++ ret = of_address_to_resource(node, j, &res[j]);
++ if (!IS_ERR_VALUE(ret))
++ r[j] = &res[j];
++ } else {
++ sprintf(res_name, "edma_cc%d", j);
++ r[j] = platform_get_resource_byname(pdev,
++ IORESOURCE_MEM,
+ res_name);
+- if (!r[j] || !info[j]) {
++ }
++ if (!r[j]) {
+ if (found)
+ break;
+ else
+@@ -1465,8 +1678,12 @@ static int __init edma_probe(struct platform_device *pdev)
+ }
+ }
+
+- sprintf(irq_name, "edma%d", j);
+- irq[j] = platform_get_irq_byname(pdev, irq_name);
++ if (node)
++ irq[j] = irq_of_parse_and_map(node, 0);
++ else {
++ sprintf(irq_name, "edma%d", j);
++ irq[j] = platform_get_irq_byname(pdev, irq_name);
++ }
+ edma_cc[j]->irq_res_start = irq[j];
+ status = request_irq(irq[j], dma_irq_handler, 0, "edma",
+ &pdev->dev);
+@@ -1476,8 +1693,12 @@ static int __init edma_probe(struct platform_device *pdev)
+ goto fail;
+ }
+
+- sprintf(irq_name, "edma%d_err", j);
+- err_irq[j] = platform_get_irq_byname(pdev, irq_name);
++ if (node)
++ err_irq[j] = irq_of_parse_and_map(node, 2);
++ else {
++ sprintf(irq_name, "edma%d_err", j);
++ err_irq[j] = platform_get_irq_byname(pdev, irq_name);
++ }
+ edma_cc[j]->irq_res_end = err_irq[j];
+ status = request_irq(err_irq[j], dma_ccerr_handler, 0,
+ "edma_error", &pdev->dev);
+@@ -1538,9 +1759,17 @@ fail1:
+ return status;
+ }
+
++static const struct of_device_id edma_of_ids[] = {
++ { .compatible = "ti,edma3", },
++ {}
++};
+
+ static struct platform_driver edma_driver = {
+- .driver.name = "edma",
++ .driver = {
++ .name = "edma",
++ .of_match_table = edma_of_ids,
++ },
++ .probe = edma_probe,
+ };
+
+ static int __init edma_init(void)
+diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
+index 95b5e10..ffcbec1 100644
+--- a/arch/arm/mach-davinci/board-da830-evm.c
++++ b/arch/arm/mach-davinci/board-da830-evm.c
+@@ -512,7 +512,7 @@ static struct davinci_i2c_platform_data da830_evm_i2c_0_pdata = {
+ * example: Timer, GPIO, UART events etc) on da830/omap-l137 EVM, hence
+ * they are being reserved for codecs on the DSP side.
+ */
+-static const s16 da830_dma_rsv_chans[][2] = {
++static s16 da830_dma_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 8, 2},
+ {12, 2},
+@@ -521,7 +521,7 @@ static const s16 da830_dma_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da830_dma_rsv_slots[][2] = {
++static s16 da830_dma_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 8, 2},
+ {12, 2},
+diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
+index 32ee3f8..f207965 100644
+--- a/arch/arm/mach-davinci/board-da850-evm.c
++++ b/arch/arm/mach-davinci/board-da850-evm.c
+@@ -1097,7 +1097,7 @@ device_initcall(da850_evm_config_emac);
+ * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM, hence
+ * they are being reserved for codecs on the DSP side.
+ */
+-static const s16 da850_dma0_rsv_chans[][2] = {
++static s16 da850_dma0_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -1105,7 +1105,7 @@ static const s16 da850_dma0_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma0_rsv_slots[][2] = {
++static s16 da850_dma0_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -1113,14 +1113,14 @@ static const s16 da850_dma0_rsv_slots[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_chans[][2] = {
++static s16 da850_dma1_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 2},
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_slots[][2] = {
++static s16 da850_dma1_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 90},
+diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
+index 1dbf85b..6c5b814 100644
+--- a/arch/arm/mach-davinci/board-dm646x-evm.c
++++ b/arch/arm/mach-davinci/board-dm646x-evm.c
+@@ -764,7 +764,7 @@ static struct davinci_uart_config uart_config __initdata = {
+ * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
+ * reserved for codecs on the DSP side.
+ */
+-static const s16 dm646x_dma_rsv_chans[][2] = {
++static s16 dm646x_dma_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 0, 4},
+ {13, 3},
+@@ -774,7 +774,7 @@ static const s16 dm646x_dma_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 dm646x_dma_rsv_slots[][2] = {
++static s16 dm646x_dma_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 0, 4},
+ {13, 3},
+diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
+index dc1208e..09c34f8 100644
+--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
++++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
+@@ -70,7 +70,7 @@ static __init void omapl138_hawk_config_emac(void)
+ * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM/Hawkboard,
+ * hence they are being reserved for codecs on the DSP side.
+ */
+-static const s16 da850_dma0_rsv_chans[][2] = {
++static s16 da850_dma0_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -78,7 +78,7 @@ static const s16 da850_dma0_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma0_rsv_slots[][2] = {
++static s16 da850_dma0_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -86,14 +86,14 @@ static const s16 da850_dma0_rsv_slots[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_chans[][2] = {
++static s16 da850_dma1_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 2},
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_slots[][2] = {
++static s16 da850_dma1_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 90},
+diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
+index bd2f72b..1f9c6ff 100644
+--- a/arch/arm/mach-davinci/devices-da8xx.c
++++ b/arch/arm/mach-davinci/devices-da8xx.c
+@@ -103,27 +103,27 @@ struct platform_device da8xx_serial_device = {
+ },
+ };
+
+-static const s8 da8xx_queue_tc_mapping[][2] = {
++static s8 da8xx_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+ {1, 1},
+ {-1, -1}
+ };
+
+-static const s8 da8xx_queue_priority_mapping[][2] = {
++static s8 da8xx_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+ {1, 7},
+ {-1, -1}
+ };
+
+-static const s8 da850_queue_tc_mapping[][2] = {
++static s8 da850_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+ {-1, -1}
+ };
+
+-static const s8 da850_queue_priority_mapping[][2] = {
++static s8 da850_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+ {-1, -1}
+diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
+index 59efd7f..d2453c9 100644
+--- a/arch/arm/mach-davinci/devices-tnetv107x.c
++++ b/arch/arm/mach-davinci/devices-tnetv107x.c
+@@ -58,14 +58,14 @@
+ #define TNETV107X_DMACH_SDIO1_RX 28
+ #define TNETV107X_DMACH_SDIO1_TX 29
+
+-static const s8 edma_tc_mapping[][2] = {
++static s8 edma_tc_mapping[][2] = {
+ /* event queue no TC no */
+ { 0, 0 },
+ { 1, 1 },
+ { -1, -1 }
+ };
+
+-static const s8 edma_priority_mapping[][2] = {
++static s8 edma_priority_mapping[][2] = {
+ /* event queue no Prio */
+ { 0, 3 },
+ { 1, 7 },
+diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
+index b165c27..cdefef3 100644
+--- a/arch/arm/mach-davinci/dm355.c
++++ b/arch/arm/mach-davinci/dm355.c
+@@ -567,7 +567,7 @@ static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+
+ /*----------------------------------------------------------------------*/
+
+-static const s8
++static s8
+ queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -575,7 +575,7 @@ queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
+index a611716..801e162 100644
+--- a/arch/arm/mach-davinci/dm365.c
++++ b/arch/arm/mach-davinci/dm365.c
+@@ -822,7 +822,7 @@ static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ };
+
+ /* Four Transfer Controllers on DM365 */
+-static const s8
++static s8
+ dm365_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -832,7 +832,7 @@ dm365_queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ dm365_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 7},
+diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
+index 90f5639..4799fd9 100644
+--- a/arch/arm/mach-davinci/dm644x.c
++++ b/arch/arm/mach-davinci/dm644x.c
+@@ -497,7 +497,7 @@ static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+
+ /*----------------------------------------------------------------------*/
+
+-static const s8
++static s8
+ queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -505,7 +505,7 @@ queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
+index 08f9dab..b4a4da6 100644
+--- a/arch/arm/mach-davinci/dm646x.c
++++ b/arch/arm/mach-davinci/dm646x.c
+@@ -531,7 +531,7 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ /*----------------------------------------------------------------------*/
+
+ /* Four Transfer Controllers on DM646x */
+-static const s8
++static s8
+ dm646x_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -541,7 +541,7 @@ dm646x_queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ dm646x_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 4},
+diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
+index 7396f0b3..b20b586 100644
+--- a/include/linux/platform_data/edma.h
++++ b/include/linux/platform_data/edma.h
+@@ -168,8 +168,8 @@ void edma_resume(unsigned channel);
+
+ struct edma_rsv_info {
+
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
++ s16 (*rsv_chans)[2];
++ s16 (*rsv_slots)[2];
+ };
+
+ /* platform_data for EDMA driver */
+@@ -191,8 +191,8 @@ struct edma_soc_info {
+ /* Resource reservation for other cores */
+ struct edma_rsv_info *rsv;
+
+- const s8 (*queue_tc_mapping)[2];
+- const s8 (*queue_priority_mapping)[2];
++ s8 (*queue_tc_mapping)[2];
++ s8 (*queue_priority_mapping)[2];
+ };
+
+ #endif
diff --git a/patches/linux-3.7-rc6/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch b/patches/linux-3.7-rc6/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch
new file mode 100644
index 0000000..87ee271
--- /dev/null
+++ b/patches/linux-3.7-rc6/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch
@@ -0,0 +1,128 @@
+From 824b8ee82f35528d0ab1a6cf66973694a694100c Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 16:13:17 -0400
+Subject: [PATCH] ARM: edma: add AM33XX crossbar event support
+
+Adds support for the per-EDMA channel event mux. This is required
+for any peripherals using DMA crossbar mapped events.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 63 +++++++++++++++++++++++++++++++++++-
+ include/linux/platform_data/edma.h | 1 +
+ 2 files changed, 63 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index 6d2a590..b761b7a 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -1425,6 +1425,53 @@ static int edma_of_read_u32_to_s16_array(const struct device_node *np,
+ return 0;
+ }
+
++static int edma_xbar_event_map(struct device *dev,
++ struct device_node *node,
++ struct edma_soc_info *pdata, int len)
++{
++ int ret = 0;
++ int i;
++ struct resource res;
++ void *xbar;
++ s16 (*xbar_chans)[2];
++ u32 shift, offset, mux;
++
++ xbar_chans = devm_kzalloc(dev,
++ len/sizeof(s16) + 2*sizeof(s16),
++ GFP_KERNEL);
++ if (!xbar_chans)
++ return -ENOMEM;
++
++ ret = of_address_to_resource(node, 1, &res);
++ if (IS_ERR_VALUE(ret))
++ return -EIO;
++
++ xbar = devm_ioremap(dev, res.start, resource_size(&res));
++ if (!xbar)
++ return -EIO;
++
++ ret = edma_of_read_u32_to_s16_array(node,
++ "ti,edma-xbar-event-map",
++ (s16 *)xbar_chans,
++ len/sizeof(u32));
++ if (IS_ERR_VALUE(ret))
++ return -EIO;
++
++ for (i = 0; xbar_chans[i][0] != -1; i++) {
++ shift = (xbar_chans[i][1] % 4) * 8;
++ offset = xbar_chans[i][1] >> 2;
++ offset <<= 2;
++ mux = __raw_readl((void *)((u32)xbar + offset));
++ mux &= (~(0xff << shift));
++ mux |= (xbar_chans[i][0] << shift);
++ __raw_writel(mux, (void *)((u32)xbar + offset));
++ }
++
++ pdata->xbar_chans = xbar_chans;
++
++ return 0;
++}
++
+ static int edma_of_parse_dt(struct device *dev,
+ struct device_node *node,
+ struct edma_soc_info *pdata)
+@@ -1453,7 +1500,6 @@ static int edma_of_parse_dt(struct device *dev,
+ pdata->n_slot = value;
+
+ pdata->n_cc = 1;
+- /* This is unused */
+ pdata->n_tc = 3;
+
+ rsv_info =
+@@ -1538,6 +1584,10 @@ static int edma_of_parse_dt(struct device *dev,
+ return ret;
+ pdata->default_queue = value;
+
++ prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
++ if (prop)
++ ret = edma_xbar_event_map(dev, node, pdata, sz);
++
+ return ret;
+ }
+
+@@ -1554,6 +1604,7 @@ static int __init edma_probe(struct platform_device *pdev)
+ int status = -1;
+ s16 (*rsv_chans)[2];
+ s16 (*rsv_slots)[2];
++ s16 (*xbar_chans)[2];
+ int irq[EDMA_MAX_CC] = {0, 0};
+ int err_irq[EDMA_MAX_CC] = {0, 0};
+ struct resource *r[EDMA_MAX_CC] = {NULL, NULL};
+@@ -1678,6 +1729,16 @@ static int __init edma_probe(struct platform_device *pdev)
+ }
+ }
+
++ /* Clear the xbar mapped channels in unused list */
++ xbar_chans = info[j]->xbar_chans;
++ if (xbar_chans) {
++ for (i = 0; xbar_chans[i][1] != -1; i++) {
++ off = xbar_chans[i][1];
++ clear_bits(off, 1,
++ edma_cc[j]->edma_unused);
++ }
++ }
++
+ if (node)
+ irq[j] = irq_of_parse_and_map(node, 0);
+ else {
+diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
+index b20b586..888a3c6 100644
+--- a/include/linux/platform_data/edma.h
++++ b/include/linux/platform_data/edma.h
+@@ -191,6 +191,7 @@ struct edma_soc_info {
+ /* Resource reservation for other cores */
+ struct edma_rsv_info *rsv;
+
++ s16 (*xbar_chans)[2];
+ s8 (*queue_tc_mapping)[2];
+ s8 (*queue_priority_mapping)[2];
+ };
diff --git a/patches/linux-3.7-rc6/0013-dmaengine-edma-enable-build-for-AM33XX.patch b/patches/linux-3.7-rc6/0013-dmaengine-edma-enable-build-for-AM33XX.patch
new file mode 100644
index 0000000..7e7fe48
--- /dev/null
+++ b/patches/linux-3.7-rc6/0013-dmaengine-edma-enable-build-for-AM33XX.patch
@@ -0,0 +1,25 @@
+From b0668c88fe5e7a8df4d1c8944673c2af2065d350 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 6 Sep 2012 17:42:35 -0400
+Subject: [PATCH] dmaengine: edma: enable build for AM33XX
+
+Enable TI EDMA option on OMAP.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/dma/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index d4c1218..20ef955 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -221,7 +221,7 @@ config SIRF_DMA
+
+ config TI_EDMA
+ tristate "TI EDMA support"
+- depends on ARCH_DAVINCI
++ depends on ARCH_DAVINCI || ARCH_OMAP
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ default n
diff --git a/patches/linux-3.7-rc6/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch b/patches/linux-3.7-rc6/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
new file mode 100644
index 0000000..83a5c93
--- /dev/null
+++ b/patches/linux-3.7-rc6/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
@@ -0,0 +1,71 @@
+From 406954740157c140ce175107e437d15f5d74a1ba Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 07:46:04 -0400
+Subject: [PATCH] dmaengine: edma: Add TI EDMA device tree binding
+
+The binding definition is based on the generic DMA controller
+binding.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ Documentation/devicetree/bindings/dma/ti-edma.txt | 51 +++++++++++++++++++++
+ 1 file changed, 51 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/dma/ti-edma.txt
+
+diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt
+new file mode 100644
+index 0000000..3344345
+--- /dev/null
++++ b/Documentation/devicetree/bindings/dma/ti-edma.txt
+@@ -0,0 +1,51 @@
++TI EDMA
++
++Required properties:
++- compatible : "ti,edma3"
++- ti,hwmods: Name of the hwmods associated to the EDMA
++- ti,edma-regions: Number of regions
++- ti,edma-slots: Number of slots
++- ti,edma-queue-tc-map: List of transfer control to queue mappings
++- ti,edma-queue-priority-map: List of queue priority mappings
++- ti,edma-default-queue: Default queue value
++
++Optional properties:
++- ti,edma-reserved-channels: List of reserved channel regions
++- ti,edma-reserved-slots: List of reserved slot regions
++- ti,edma-xbar-event-map: Crossbar event to channel map
++
++Example:
++
++edma: edma@49000000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x49000000 0x10000>;
++ interrupt-parent = <&intc>;
++ interrupts = <12 13 14>;
++ compatible = "ti,edma3";
++ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
++ #dma-cells = <1>;
++ dma-channels = <64>;
++ ti,edma-regions = <4>;
++ ti,edma-slots = <256>;
++ ti,edma-reserved-channels = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8>;
++ ti,edma-reserved-slots = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8
++ 64 127>;
++ ti,edma-queue-tc-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-queue-priority-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-default-queue = <0>;
++ ti,edma-xbar-event-map = <1 12
++ 2 13>;
++};
diff --git a/patches/linux-3.7-rc6/0015-ARM-dts-add-AM33XX-EDMA-support.patch b/patches/linux-3.7-rc6/0015-ARM-dts-add-AM33XX-EDMA-support.patch
new file mode 100644
index 0000000..85a10ac
--- /dev/null
+++ b/patches/linux-3.7-rc6/0015-ARM-dts-add-AM33XX-EDMA-support.patch
@@ -0,0 +1,55 @@
+From 0a343eb46473df01ad66d7975f4b17ee8a0ba833 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 10 Oct 2012 10:01:33 -0400
+Subject: [PATCH] ARM: dts: add AM33XX EDMA support
+
+Adds AM33XX EDMA support to the am33xx.dtsi as documented in
+Documentation/devicetree/bindings/dma/ti-edma.txt
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index bb31bff..ab9c78f 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -62,6 +62,37 @@
+ reg = <0x48200000 0x1000>;
+ };
+
++ edma: edma@49000000 {
++ compatible = "ti,edma3";
++ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
++ reg = <0x49000000 0x10000>,
++ <0x44e10f90 0x10>;
++ interrupt-parent = <&intc>;
++ interrupts = <12 13 14>;
++ #dma-cells = <1>;
++ dma-channels = <64>;
++ ti,edma-regions = <4>;
++ ti,edma-slots = <256>;
++ ti,edma-reserved-channels = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8>;
++ ti,edma-reserved-slots = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8
++ 64 127>;
++ ti,edma-queue-tc-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-queue-priority-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-default-queue = <0>;
++ };
++
+ gpio1: gpio@44e07000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio1";
diff --git a/patches/linux-3.7-rc6/0016-dmaengine-add-dma_request_slave_channel_compat.patch b/patches/linux-3.7-rc6/0016-dmaengine-add-dma_request_slave_channel_compat.patch
new file mode 100644
index 0000000..cc70c89
--- /dev/null
+++ b/patches/linux-3.7-rc6/0016-dmaengine-add-dma_request_slave_channel_compat.patch
@@ -0,0 +1,42 @@
+From 4b29b8fc42201109ebfe6dc14e5b778f33f8331f Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 11 Oct 2012 12:58:44 -0400
+Subject: [PATCH] dmaengine: add dma_request_slave_channel_compat()
+
+Adds a dma_request_slave_channel_compat() wrapper which accepts
+both the arguments from dma_request_channel() and
+dma_request_slave_channel(). Based on whether the driver is
+instantiated via DT, the appropriate channel request call will be
+made.
+
+This allows for a much cleaner migration of drivers to the
+dmaengine DT API as platforms continue to be mixed between those
+that boot using DT and those that do not.
+
+Suggested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ include/linux/dmaengine.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index c88f302..11d9e25 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -1007,6 +1007,16 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
+ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
+ struct dma_chan *net_dma_find_channel(void);
+ #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
++static inline struct dma_chan
++*dma_request_slave_channel_compat(dma_cap_mask_t mask, dma_filter_fn fn,
++ void *fn_param, struct device *dev,
++ char *name)
++{
++ if (dev->of_node)
++ return dma_request_slave_channel(dev, name);
++ else
++ return dma_request_channel(mask, fn, fn_param);
++}
+
+ /* --- Helper iov-locking functions --- */
+
diff --git a/patches/linux-3.7-rc6/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch b/patches/linux-3.7-rc6/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
new file mode 100644
index 0000000..60efa50
--- /dev/null
+++ b/patches/linux-3.7-rc6/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
@@ -0,0 +1,45 @@
+From eac7b54ca639d29ca6e2bdf421aa609b6a17ca0f Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 6 Sep 2012 17:47:21 -0400
+Subject: [PATCH] mmc: omap_hsmmc: convert to
+ dma_request_slave_channel_compat()
+
+Convert dmaengine channel requests to use
+dma_request_slave_channel_compat(). This supports the DT case of
+platforms requiring channel selection from either the OMAP DMA or
+the EDMA engine. AM33xx only boots from DT and is the only user
+implementing EDMA so in the !DT case we can default to the OMAP DMA
+filter.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index fedd258..f74141e 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1871,14 +1871,20 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+- host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req);
++ host->rx_chan =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &rx_req, &pdev->dev, "rx");
++
+ if (!host->rx_chan) {
+ dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req);
+ ret = -ENXIO;
+ goto err_irq;
+ }
+
+- host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req);
++ host->tx_chan =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &tx_req, &pdev->dev, "tx");
++
+ if (!host->tx_chan) {
+ dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req);
+ ret = -ENXIO;
diff --git a/patches/linux-3.7-rc6/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch b/patches/linux-3.7-rc6/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch
new file mode 100644
index 0000000..36ab8ae
--- /dev/null
+++ b/patches/linux-3.7-rc6/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch
@@ -0,0 +1,39 @@
+From f64e173af16724e4dbdc727821ae060a3fab459e Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 08:55:41 -0400
+Subject: [PATCH] mmc: omap_hsmmc: limit max_segs with the EDMA DMAC
+
+The EDMA DMAC has a hardware limitation that prevents supporting
+scatter gather lists with any number of segments. Since the EDMA
+DMA Engine driver sets the maximum segments to 16, we do the
+same.
+
+TODO: this will be replaced once the DMA Engine API supports an
+API to query the DMAC's segment size limit.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index f74141e..4fe62b0 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1833,6 +1833,16 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ * as we want. */
+ mmc->max_segs = 1024;
+
++ /* Eventually we should get our max_segs limitation for EDMA by
++ * querying the dmaengine API */
++ if (pdev->dev.of_node) {
++ struct device_node *parent = pdev->dev.of_node->parent;
++ struct device_node *node;
++ node = of_find_node_by_name(parent, "edma");
++ if (node)
++ mmc->max_segs = 16;
++ }
++
+ mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
+ mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
+ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
diff --git a/patches/linux-3.7-rc6/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch b/patches/linux-3.7-rc6/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
new file mode 100644
index 0000000..e01d8fe
--- /dev/null
+++ b/patches/linux-3.7-rc6/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
@@ -0,0 +1,55 @@
+From fc9e3599817da4fb14ed9e9bb876cb4dc901a47c Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 07:47:47 -0400
+Subject: [PATCH] mmc: omap_hsmmc: add generic DMA request support to the DT
+ binding
+
+The binding definition is based on the generic DMA request binding.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 25 +++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+index be76a23..d1b8932 100644
+--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
++++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+@@ -19,8 +19,28 @@ ti,dual-volt: boolean, supports dual voltage cards
+ "supply-name" examples are "vmmc", "vmmc_aux" etc
+ ti,non-removable: non-removable slot (like eMMC)
+ ti,needs-special-reset: Requires a special softreset sequence
++dmas: DMA controller phandle and DMA request value ordered pair
++One tx and one rx pair is required.
++dma-names: DMA request names. These strings correspond 1:1 with
++the ordered pairs in dmas. The RX request must be "rx" and the
++TX request must be "tx".
++
++Examples:
++
++[hwmod populated DMA resources]
++
++ mmc1: mmc@0x4809c000 {
++ compatible = "ti,omap4-hsmmc";
++ reg = <0x4809c000 0x400>;
++ ti,hwmods = "mmc1";
++ ti,dual-volt;
++ bus-width = <4>;
++ vmmc-supply = <&vmmc>; /* phandle to regulator node */
++ ti,non-removable;
++ };
++
++[generic DMA request binding]
+
+-Example:
+ mmc1: mmc@0x4809c000 {
+ compatible = "ti,omap4-hsmmc";
+ reg = <0x4809c000 0x400>;
+@@ -29,4 +49,7 @@ Example:
+ bus-width = <4>;
+ vmmc-supply = <&vmmc>; /* phandle to regulator node */
+ ti,non-removable;
++ dmas = <&edma 24
++ &edma 25>;
++ dma-names = "tx", "rx";
+ };
diff --git a/patches/linux-3.7-rc6/0020-ARM-dts-add-AM33XX-MMC-support.patch b/patches/linux-3.7-rc6/0020-ARM-dts-add-AM33XX-MMC-support.patch
new file mode 100644
index 0000000..9a2423c
--- /dev/null
+++ b/patches/linux-3.7-rc6/0020-ARM-dts-add-AM33XX-MMC-support.patch
@@ -0,0 +1,91 @@
+From 2eafee121ee4f7c3175da0fc3415c8c79474beee Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 10 Oct 2012 15:14:03 -0400
+Subject: [PATCH] ARM: dts: add AM33XX MMC support
+
+Adds AM33XX MMC support for am335x-bone and am335x-evm.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 6 ++++++
+ arch/arm/boot/dts/am335x-evm.dts | 6 ++++++
+ arch/arm/boot/dts/am33xx.dtsi | 27 +++++++++++++++++++++++++++
+ 3 files changed, 39 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index c634f87..5510979 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -70,6 +70,8 @@
+ };
+
+ ldo3_reg: regulator@5 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+@@ -78,3 +80,7 @@
+ };
+ };
+ };
++
++&mmc1 {
++ vmmc-supply = <&ldo3_reg>;
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 185d632..d63fce8 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -114,7 +114,13 @@
+ };
+
+ vmmc_reg: regulator@12 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
++
++&mmc1 {
++ vmmc-supply = <&vmmc_reg>;
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index ab9c78f..26a6af7 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -234,6 +234,33 @@
+ status = "disabled";
+ };
+
++ mmc1: mmc@48060000 {
++ compatible = "ti,omap3-hsmmc";
++ ti,hwmods = "mmc1";
++ ti,dual-volt;
++ ti,needs-special-reset;
++ dmas = <&edma 24
++ &edma 25>;
++ dma-names = "tx", "rx";
++ };
++
++ mmc2: mmc@481d8000 {
++ compatible = "ti,omap3-hsmmc";
++ ti,hwmods = "mmc2";
++ ti,needs-special-reset;
++ dmas = <&edma 2
++ &edma 3>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ mmc3: mmc@47810000 {
++ compatible = "ti,omap3-hsmmc";
++ ti,hwmods = "mmc3";
++ ti,needs-special-reset;
++ status = "disabled";
++ };
++
+ wdt2: wdt@44e35000 {
+ compatible = "ti,omap3-wdt";
+ ti,hwmods = "wd_timer2";
diff --git a/patches/linux-3.7-rc6/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch b/patches/linux-3.7-rc6/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
new file mode 100644
index 0000000..1636f82
--- /dev/null
+++ b/patches/linux-3.7-rc6/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
@@ -0,0 +1,119 @@
+From 588d993abc0c750ebe9a9547ead82d07e74127ad Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 00:37:54 -0400
+Subject: [PATCH] spi: omap2-mcspi: convert to
+ dma_request_slave_channel_compat()
+
+Convert dmaengine channel requests to use
+dma_request_slave_channel_compat(). This supports the DT case of
+platforms requiring channel selection from either the OMAP DMA or
+the EDMA engine. AM33xx only boots from DT and is the only user
+implementing EDMA so in the !DT case we can default to the OMAP DMA
+filter.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/spi/spi-omap2-mcspi.c | 65 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 45 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
+index 3542fdc..793ae8c 100644
+--- a/drivers/spi/spi-omap2-mcspi.c
++++ b/drivers/spi/spi-omap2-mcspi.c
+@@ -103,6 +103,9 @@ struct omap2_mcspi_dma {
+
+ struct completion dma_tx_completion;
+ struct completion dma_rx_completion;
++
++ char dma_rx_ch_name[14];
++ char dma_tx_ch_name[14];
+ };
+
+ /* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+@@ -819,14 +822,23 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ sig = mcspi_dma->dma_rx_sync_dev;
+- mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
++
++ mcspi_dma->dma_rx =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &sig, &master->dev,
++ mcspi_dma->dma_rx_ch_name);
++
+ if (!mcspi_dma->dma_rx) {
+ dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n");
+ return -EAGAIN;
+ }
+
+ sig = mcspi_dma->dma_tx_sync_dev;
+- mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
++ mcspi_dma->dma_tx =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &sig, &master->dev,
++ mcspi_dma->dma_tx_ch_name);
++
+ if (!mcspi_dma->dma_tx) {
+ dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n");
+ dma_release_channel(mcspi_dma->dma_rx);
+@@ -1217,29 +1229,42 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
+ goto free_master;
+
+ for (i = 0; i < master->num_chipselect; i++) {
+- char dma_ch_name[14];
++ char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name;
++ char *dma_tx_ch_name = mcspi->dma_channels[i].dma_tx_ch_name;
+ struct resource *dma_res;
+
+- sprintf(dma_ch_name, "rx%d", i);
+- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+- dma_ch_name);
+- if (!dma_res) {
+- dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
+- status = -ENODEV;
+- break;
+- }
++ sprintf(dma_rx_ch_name, "rx%d", i);
++ if (!pdev->dev.of_node) {
++ dma_res =
++ platform_get_resource_byname(pdev,
++ IORESOURCE_DMA,
++ dma_rx_ch_name);
++ if (!dma_res) {
++ dev_dbg(&pdev->dev,
++ "cannot get DMA RX channel\n");
++ status = -ENODEV;
++ break;
++ }
+
+- mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
+- sprintf(dma_ch_name, "tx%d", i);
+- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+- dma_ch_name);
+- if (!dma_res) {
+- dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
+- status = -ENODEV;
+- break;
++ mcspi->dma_channels[i].dma_rx_sync_dev =
++ dma_res->start;
+ }
++ sprintf(dma_tx_ch_name, "tx%d", i);
++ if (!pdev->dev.of_node) {
++ dma_res =
++ platform_get_resource_byname(pdev,
++ IORESOURCE_DMA,
++ dma_tx_ch_name);
++ if (!dma_res) {
++ dev_dbg(&pdev->dev,
++ "cannot get DMA TX channel\n");
++ status = -ENODEV;
++ break;
++ }
+
+- mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
++ mcspi->dma_channels[i].dma_tx_sync_dev =
++ dma_res->start;
++ }
+ }
+
+ if (status < 0)
diff --git a/patches/linux-3.7-rc6/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch b/patches/linux-3.7-rc6/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
new file mode 100644
index 0000000..1f52e69
--- /dev/null
+++ b/patches/linux-3.7-rc6/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
@@ -0,0 +1,56 @@
+From b51a573d3fa257c4dad23baf9d9ffe8aea220b11 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 09:21:16 -0400
+Subject: [PATCH] spi: omap2-mcspi: add generic DMA request support to the DT
+ binding
+
+The binding definition is based on the generic DMA request binding.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ Documentation/devicetree/bindings/spi/omap-spi.txt | 27 +++++++++++++++++++-
+ 1 file changed, 26 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/spi/omap-spi.txt b/Documentation/devicetree/bindings/spi/omap-spi.txt
+index 81df374..11aff04 100644
+--- a/Documentation/devicetree/bindings/spi/omap-spi.txt
++++ b/Documentation/devicetree/bindings/spi/omap-spi.txt
+@@ -7,8 +7,18 @@ Required properties:
+ - ti,spi-num-cs : Number of chipselect supported by the instance.
+ - ti,hwmods: Name of the hwmod associated to the McSPI
+
++Optional properties:
++- dmas: List of DMA controller phandle and DMA request ordered
++ pairs. One tx and one rx pair is required for each chip
++ select.
++- dma-names: List of DMA request names. These strings correspond
++ 1:1 with the ordered pairs in dmas. The string naming is
++ to be "rxN" and "txN" for RX and TX requests,
++ respectively, where N equals the chip select number.
+
+-Example:
++Examples:
++
++[hwmod populated DMA resources]
+
+ mcspi1: mcspi@1 {
+ #address-cells = <1>;
+@@ -18,3 +28,18 @@ mcspi1: mcspi@1 {
+ ti,spi-num-cs = <4>;
+ };
+
++[generic DMA request binding]
++
++mcspi1: mcspi@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "ti,omap4-mcspi";
++ ti,hwmods = "mcspi1";
++ ti,spi-num-cs = <2>;
++ dmas = <&edma 42
++ &edma 43
++ &edma 44
++ &edma 45>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
++};
++
diff --git a/patches/linux-3.7-rc6/0023-ARM-dts-add-AM33XX-SPI-support.patch b/patches/linux-3.7-rc6/0023-ARM-dts-add-AM33XX-SPI-support.patch
new file mode 100644
index 0000000..8388d26
--- /dev/null
+++ b/patches/linux-3.7-rc6/0023-ARM-dts-add-AM33XX-SPI-support.patch
@@ -0,0 +1,124 @@
+From 3fa0e6f705cc2725d267ed19b0c76541e9d7a96b Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 11 Oct 2012 08:51:46 -0400
+Subject: [PATCH] ARM: dts: add AM33XX SPI support
+
+Adds AM33XX SPI support for am335x-bone and am335x-evm.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 17 +++++++++++++++
+ arch/arm/boot/dts/am335x-evm.dts | 9 ++++++++
+ arch/arm/boot/dts/am33xx.dtsi | 43 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 69 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 5510979..23edfd8 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -18,6 +18,17 @@
+ reg = <0x80000000 0x10000000>; /* 256 MB */
+ };
+
++ am3358_pinmux: pinmux@44e10800 {
++ spi1_pins: pinmux_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x13 /* mcasp0_aclkx.spi1_sclk, OUTPUT_PULLUP | MODE3 */
++ 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
++ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
++ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
++ >;
++ };
++ };
++
+ ocp {
+ uart1: serial@44e09000 {
+ status = "okay";
+@@ -84,3 +95,9 @@
+ &mmc1 {
+ vmmc-supply = <&ldo3_reg>;
+ };
++
++&spi1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi1_pins>;
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index d63fce8..8d5f660 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -124,3 +124,12 @@
+ &mmc1 {
+ vmmc-supply = <&vmmc_reg>;
+ };
++
++&spi0 {
++ status = "okay";
++ spi-flash@0 {
++ compatible = "spansion,s25fl064k", "m25p80";
++ spi-max-frequency = <24000000>;
++ reg = <0>;
++ };
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 26a6af7..063ecea 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -40,6 +40,15 @@
+ };
+ };
+
++ am3358_pinmux: pinmux@44e10800 {
++ compatible = "pinctrl-single";
++ reg = <0x44e10800 0x0238>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ pinctrl-single,register-width = <32>;
++ pinctrl-single,function-mask = <0x7f>;
++ };
++
+ /*
+ * XXX: Use a flat representation of the AM33XX interconnect.
+ * The real AM33XX interconnect network is quite complex.Since
+@@ -261,6 +270,40 @@
+ status = "disabled";
+ };
+
++ spi0: spi@48030000 {
++ compatible = "ti,omap4-mcspi";
++ ti,hwmods = "spi0";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x48030000 0x400>;
++ interrupt-parent = <&intc>;
++ interrupt = <65>;
++ dmas = <&edma 16
++ &edma 17
++ &edma 18
++ &edma 19>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
++ ti,spi-num-cs = <2>;
++ status = "disabled";
++ };
++
++ spi1: spi@481a0000 {
++ compatible = "ti,omap4-mcspi";
++ ti,hwmods = "spi1";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x481a0000 0x400>;
++ interrupt-parent = <&intc>;
++ interrupt = <125>;
++ dmas = <&edma 42
++ &edma 43
++ &edma 44
++ &edma 45>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
++ ti,spi-num-cs = <2>;
++ status = "disabled";
++ };
++
+ wdt2: wdt@44e35000 {
+ compatible = "ti,omap3-wdt";
+ ti,hwmods = "wd_timer2";
diff --git a/patches/linux-3.7-rc6/0024-Documentation-bindings-add-spansion.patch b/patches/linux-3.7-rc6/0024-Documentation-bindings-add-spansion.patch
new file mode 100644
index 0000000..8287397
--- /dev/null
+++ b/patches/linux-3.7-rc6/0024-Documentation-bindings-add-spansion.patch
@@ -0,0 +1,22 @@
+From edd68fd797edcb247d1bcfc8f9a6dd843af35843 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 17:12:09 -0400
+Subject: [PATCH] Documentation: bindings: add spansion
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
+index 54463a7..261b6d5 100644
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -47,6 +47,7 @@ sil Silicon Image
+ simtek
+ sirf SiRF Technology, Inc.
+ sitronix Sitronix Technology Corp.
++spansion Spansion, Inc.
+ st STMicroelectronics
+ stericsson ST-Ericsson
+ ti Texas Instruments
diff --git a/patches/linux-3.7-rc6/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch b/patches/linux-3.7-rc6/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
new file mode 100644
index 0000000..a31b2a9
--- /dev/null
+++ b/patches/linux-3.7-rc6/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
@@ -0,0 +1,44 @@
+From 03118b0a0ad5e5249b94d87f68c1f4694155b78a Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 11 Oct 2012 08:52:54 -0400
+Subject: [PATCH] ARM: dts: add BeagleBone Adafruit 1.8 LCD support
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 23edfd8..290408c 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -27,6 +27,12 @@
+ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+ >;
+ };
++ lcd_pins: pinmux_lcd_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -100,4 +106,16 @@
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ pinctrl-names = "default";
++ pinctrl-0 = <&lcd_pins>;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
+ };
diff --git a/patches/linux-3.7-rc6/0026-misc-add-gpevt-driver.patch b/patches/linux-3.7-rc6/0026-misc-add-gpevt-driver.patch
new file mode 100644
index 0000000..41df270
--- /dev/null
+++ b/patches/linux-3.7-rc6/0026-misc-add-gpevt-driver.patch
@@ -0,0 +1,219 @@
+From 041c51572bd5c7eb9e2f581e223fd4cfa4921656 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 10:48:22 -0400
+Subject: [PATCH] misc: add gpevt driver
+
+Simply amazing...'nuff said.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/misc/Kconfig | 6 ++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/gpevt.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 179 insertions(+)
+ create mode 100644 drivers/misc/gpevt.c
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index b151b7c..cd43cbd 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -499,6 +499,12 @@ config USB_SWITCH_FSA9480
+ stereo and mono audio, video, microphone and UART data to use
+ a common connector port.
+
++config GPEVT
++ tristate "Amazing GPIO DMA Event Test Driver(tm)"
++ depends on TI_EDMA
++ help
++ Simply amazing!
++
+ source "drivers/misc/c2port/Kconfig"
+ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 2129377..661d093 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -49,3 +49,4 @@ obj-y += carma/
+ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+ obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
+ obj-$(CONFIG_INTEL_MEI) += mei/
++obj-$(CONFIG_GPEVT) += gpevt.o
+diff --git a/drivers/misc/gpevt.c b/drivers/misc/gpevt.c
+new file mode 100644
+index 0000000..4fe256c
+--- /dev/null
++++ b/drivers/misc/gpevt.c
+@@ -0,0 +1,172 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmaengine.h>
++#include <linux/gpio.h>
++#include <linux/err.h>
++#include <linux/uaccess.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/platform_device.h>
++
++#define GPEVT_MAGIC 0xdeadbeef
++
++static u32 *dst_fifo;
++static dma_addr_t fifo_addr;
++
++static void gpevt_callback(void *data)
++{
++ struct device *dev = data;
++
++ dma_unmap_single(dev, fifo_addr, 32, DMA_FROM_DEVICE);
++
++ if (*dst_fifo == GPEVT_MAGIC)
++ dev_info(dev, "*** DMA transfer succeeded ***\n");
++ else
++ dev_info(dev, "*** DMA transfer failed ***\n");
++}
++
++static int __devinit gpevt_probe (struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ struct pinctrl *pinctrl;
++ struct dma_chan *chan;
++ struct dma_slave_config cfg;
++ struct dma_async_tx_descriptor *tx;
++ int gpio_evt = 0;
++ int ret;
++ u32 *src_buf;
++ struct scatterlist sg;
++
++ src_buf = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
++ if (!src_buf) {
++ dev_err(&pdev->dev, "failed to allocate src buffer\n");
++ return -ENOMEM;
++ }
++
++ dst_fifo = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
++ if (!dst_fifo) {
++ dev_err(&pdev->dev, "failed to allocate dst fifo\n");
++ return -ENOMEM;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ gpio_evt = of_get_named_gpio(np, "gpio-evt", 0);
++ if (gpio_evt < 0) {
++ dev_err(&pdev->dev, "failed to find gpio event signal!\n");
++ return -EINVAL;
++ }
++
++ ret = devm_gpio_request_one(&pdev->dev, gpio_evt,
++ GPIOF_IN, "GPIO Event Pin");
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to claim gpio-evt pin\n");
++ return ret;
++ }
++
++ ret = request_irq(gpio_to_irq(gpio_evt), no_action,
++ IRQ_TYPE_EDGE_FALLING, "gpevt", &pdev->dev);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to request falling edge irq/event\n");
++ return ret;
++ }
++
++ chan = dma_request_slave_channel(&pdev->dev, "gpioevt");
++ if (!chan) {
++ dev_err(&pdev->dev, "no gpio channel for gpevt\n");
++ return -EAGAIN;
++ }
++
++ fifo_addr = dma_map_single(&pdev->dev, dst_fifo, 32, DMA_FROM_DEVICE);
++ if (!fifo_addr) {
++ dev_err(&pdev->dev, "could not map dst fifo\n");
++ return -EIO;
++ }
++ cfg.dst_addr = fifo_addr;
++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ cfg.dst_maxburst = 1;
++
++ ret = dmaengine_slave_config(chan, &cfg);
++ if (ret)
++ return ret;
++
++ *src_buf = GPEVT_MAGIC;
++ sg_init_table(&sg, 1);
++ sg_dma_address(&sg) = dma_map_single(&pdev->dev, src_buf, 32, DMA_TO_DEVICE);
++ sg_dma_len(&sg) = 4;
++
++ tx = dmaengine_prep_slave_sg(chan, &sg, 1, DMA_MEM_TO_DEV,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ if (!tx) {
++ dev_err(&pdev->dev, "prep_slave_sg() failed\n");
++ return -EIO;
++ }
++
++ tx->callback = gpevt_callback;
++ tx->callback_param = &pdev->dev;
++ dmaengine_submit(tx);
++
++ dma_async_issue_pending(chan);
++
++ dev_info(&pdev->dev, "Amazing GPIO DMA Event Test Driver(tm) engaged\n");
++
++ return 0;
++}
++
++static int __devexit gpevt_remove(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static const struct of_device_id gpevt_dt_ids[] = {
++ { .compatible = "gpevt", .data = (void *) NULL, },
++};
++MODULE_DEVICE_TABLE(of, gpevt_dt_ids);
++
++static struct platform_driver gpevt_driver = {
++ .driver = {
++ .name = "gpevt",
++ .owner = THIS_MODULE,
++ .of_match_table = gpevt_dt_ids,
++ },
++ .probe = gpevt_probe,
++ .remove = __devexit_p(gpevt_remove),
++};
++
++static int __init gpevt_init(void)
++{
++ return platform_driver_register(&gpevt_driver);
++}
++
++static void __exit gpevt_exit(void)
++{
++ platform_driver_unregister(&gpevt_driver);
++}
++
++/* ------------------------------------------------------------------------- */
++
++module_init(gpevt_init);
++module_exit(gpevt_exit);
++
++MODULE_DESCRIPTION("Amazing GPIO DMA Event Test Driver(tm)");
++MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.7-rc6/0027-ARM-dts-add-BeagleBone-gpevt-support.patch b/patches/linux-3.7-rc6/0027-ARM-dts-add-BeagleBone-gpevt-support.patch
new file mode 100644
index 0000000..48f0f4b
--- /dev/null
+++ b/patches/linux-3.7-rc6/0027-ARM-dts-add-BeagleBone-gpevt-support.patch
@@ -0,0 +1,50 @@
+From de9cf3f43a2bc994e0c1f4d21c8b0ff63eb3dfda Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 17:12:45 -0400
+Subject: [PATCH] ARM: dts: add BeagleBone gpevt support
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 290408c..2ad3914 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -33,6 +33,11 @@
+ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++ gpevt_pins: pinmux_gpevt_pins {
++ pinctrl-single,pins = <
++ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -49,6 +54,15 @@
+ };
+
+ };
++
++ gpevt {
++ compatible = "gpevt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpevt_pins>;
++ dmas = <&edma 12>;
++ dma-names = "gpioevt";
++ gpio-evt = <&gpio3 2 0>;
++ };
+ };
+ };
+
+@@ -119,3 +133,7 @@
+ st7735-dc = <&gpio4 21 0>;
+ };
+ };
++
++&edma {
++ ti,edma-xbar-event-map = <32 12>;
++};
diff --git a/patches/linux-3.7-rc6/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch b/patches/linux-3.7-rc6/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch
new file mode 100644
index 0000000..6f69da0
--- /dev/null
+++ b/patches/linux-3.7-rc6/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch
@@ -0,0 +1,235 @@
+From 21a9326ab1c0c135deee4490c2a5f8a07140c318 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Fri, 12 Oct 2012 16:52:55 -0400
+Subject: [PATCH] ARM: configs: working AM33XX edma dmaengine defconfig
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/configs/omap2plus_defconfig | 68 ++++++++++++++++++++--------------
+ 1 file changed, 40 insertions(+), 28 deletions(-)
+
+diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
+index 6230304..89e1c58 100644
+--- a/arch/arm/configs/omap2plus_defconfig
++++ b/arch/arm/configs/omap2plus_defconfig
+@@ -1,14 +1,15 @@
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_SYSVIPC=y
+ CONFIG_POSIX_MQUEUE=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
+ CONFIG_BSD_PROCESS_ACCT=y
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=16
++CONFIG_CGROUPS=y
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_EXPERT=y
+-# CONFIG_SYSCTL_SYSCALL is not set
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+ CONFIG_SLAB=y
+ CONFIG_PROFILING=y
+ CONFIG_OPROFILE=y
+@@ -20,19 +21,20 @@ CONFIG_MODULE_FORCE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+ # CONFIG_BLK_DEV_BSG is not set
++CONFIG_PARTITION_ADVANCED=y
+ CONFIG_ARCH_OMAP=y
+ CONFIG_OMAP_RESET_CLOCKS=y
+ CONFIG_OMAP_MUX_DEBUG=y
++CONFIG_SOC_OMAP5=y
+ CONFIG_ARM_THUMBEE=y
+ CONFIG_ARM_ERRATA_411920=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+ CONFIG_SMP=y
+ CONFIG_NR_CPUS=2
+-CONFIG_LEDS=y
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
++CONFIG_ARM_APPENDED_DTB=y
++CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO0,115200"
++CONFIG_CMDLINE_FORCE=y
+ CONFIG_KEXEC=y
+ CONFIG_FPE_NWFPE=y
+ CONFIG_BINFMT_MISC=y
+@@ -52,18 +54,24 @@ CONFIG_IP_PNP_RARP=y
+ # CONFIG_INET_LRO is not set
+ # CONFIG_IPV6 is not set
+ CONFIG_NETFILTER=y
+-CONFIG_BT=m
++CONFIG_BT=y
+ CONFIG_BT_HCIUART=m
+ CONFIG_BT_HCIUART_H4=y
+ CONFIG_BT_HCIUART_BCSP=y
+ CONFIG_BT_HCIUART_LL=y
+ CONFIG_BT_HCIBCM203X=m
+ CONFIG_BT_HCIBPA10X=m
+-CONFIG_CFG80211=m
+-CONFIG_MAC80211=m
++CONFIG_CFG80211=y
++CONFIG_NL80211_TESTMODE=y
++CONFIG_CFG80211_DEBUGFS=y
++CONFIG_CFG80211_WEXT=y
++CONFIG_LIB80211=y
++CONFIG_MAC80211=y
+ CONFIG_MAC80211_RC_PID=y
+ CONFIG_MAC80211_RC_DEFAULT_PID=y
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
+ CONFIG_CONNECTOR=y
+ CONFIG_MTD=y
+ CONFIG_MTD_CMDLINE_PARTS=y
+@@ -72,6 +80,7 @@ CONFIG_MTD_BLOCK=y
+ CONFIG_MTD_OOPS=y
+ CONFIG_MTD_CFI=y
+ CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_M25P80=y
+ CONFIG_MTD_NAND=y
+ CONFIG_MTD_NAND_OMAP2=y
+ CONFIG_MTD_ONENAND=y
+@@ -81,28 +90,27 @@ CONFIG_MTD_UBI=y
+ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_SIZE=16384
++CONFIG_GPEVT=y
+ CONFIG_SCSI=y
+ CONFIG_BLK_DEV_SD=y
+ CONFIG_SCSI_MULTI_LUN=y
+ CONFIG_SCSI_SCAN_ASYNC=y
+ CONFIG_MD=y
+ CONFIG_NETDEVICES=y
+-CONFIG_SMSC_PHY=y
+-CONFIG_NET_ETHERNET=y
+-CONFIG_SMC91X=y
+-CONFIG_SMSC911X=y
+ CONFIG_KS8851=y
+ CONFIG_KS8851_MLL=y
+-CONFIG_LIBERTAS=m
+-CONFIG_LIBERTAS_USB=m
+-CONFIG_LIBERTAS_SDIO=m
+-CONFIG_LIBERTAS_DEBUG=y
++CONFIG_SMC91X=y
++CONFIG_SMSC911X=y
++CONFIG_SMSC_PHY=y
+ CONFIG_USB_USBNET=y
+ CONFIG_USB_NET_SMSC95XX=y
+ CONFIG_USB_ALI_M5632=y
+ CONFIG_USB_AN2720=y
+ CONFIG_USB_EPSON2888=y
+ CONFIG_USB_KC2190=y
++CONFIG_WL_TI=y
++CONFIG_WL12XX=y
++CONFIG_WLCORE_SDIO=y
+ CONFIG_INPUT_JOYDEV=y
+ CONFIG_INPUT_EVDEV=y
+ CONFIG_KEYBOARD_GPIO=y
+@@ -123,23 +131,29 @@ CONFIG_HW_RANDOM=y
+ CONFIG_I2C_CHARDEV=y
+ CONFIG_SPI=y
+ CONFIG_SPI_OMAP24XX=y
++CONFIG_DEBUG_PINCTRL=y
+ CONFIG_PINCTRL_SINGLE=y
+ CONFIG_DEBUG_GPIO=y
+ CONFIG_GPIO_SYSFS=y
++CONFIG_GPIO_GENERIC_PLATFORM=y
+ CONFIG_GPIO_TWL4030=y
+ CONFIG_W1=y
+ CONFIG_POWER_SUPPLY=y
+ CONFIG_WATCHDOG=y
+ CONFIG_OMAP_WATCHDOG=y
+ CONFIG_TWL4030_WATCHDOG=y
+-CONFIG_REGULATOR_TWL4030=y
++CONFIG_MFD_TPS65217=y
++CONFIG_MFD_TPS65910=y
+ CONFIG_REGULATOR_TPS65023=y
+ CONFIG_REGULATOR_TPS6507X=y
++CONFIG_REGULATOR_TPS65217=y
++CONFIG_REGULATOR_TPS65910=y
++CONFIG_REGULATOR_TWL4030=y
+ CONFIG_FB=y
+ CONFIG_FIRMWARE_EDID=y
+ CONFIG_FB_MODE_HELPERS=y
+ CONFIG_FB_TILEBLITTING=y
+-CONFIG_FB_OMAP_LCD_VGA=y
++CONFIG_FB_ST7735=y
+ CONFIG_OMAP2_DSS=m
+ CONFIG_OMAP2_DSS_RFBI=y
+ CONFIG_OMAP2_DSS_SDI=y
+@@ -154,7 +168,6 @@ CONFIG_PANEL_ACX565AKM=m
+ CONFIG_BACKLIGHT_LCD_SUPPORT=y
+ CONFIG_LCD_CLASS_DEVICE=y
+ CONFIG_LCD_PLATFORM=y
+-CONFIG_DISPLAY_SUPPORT=y
+ CONFIG_FRAMEBUFFER_CONSOLE=y
+ CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+ CONFIG_FONTS=y
+@@ -174,12 +187,10 @@ CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
+ CONFIG_USB=y
+ CONFIG_USB_DEBUG=y
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+-CONFIG_USB_DEVICEFS=y
+ CONFIG_USB_SUSPEND=y
+ CONFIG_USB_MON=y
+ CONFIG_USB_WDM=y
+ CONFIG_USB_STORAGE=y
+-CONFIG_USB_LIBUSUAL=y
+ CONFIG_USB_TEST=y
+ CONFIG_USB_GADGET=y
+ CONFIG_USB_GADGET_DEBUG=y
+@@ -192,9 +203,13 @@ CONFIG_SDIO_UART=y
+ CONFIG_MMC_OMAP=y
+ CONFIG_MMC_OMAP_HS=y
+ CONFIG_RTC_CLASS=y
++# CONFIG_RTC_INTF_SYSFS is not set
++# CONFIG_RTC_INTF_PROC is not set
++# CONFIG_RTC_INTF_DEV is not set
+ CONFIG_RTC_DRV_TWL92330=y
+ CONFIG_RTC_DRV_TWL4030=y
+ CONFIG_DMADEVICES=y
++CONFIG_TI_EDMA=y
+ CONFIG_DMA_OMAP=y
+ CONFIG_EXT2_FS=y
+ CONFIG_EXT3_FS=y
+@@ -202,6 +217,7 @@ CONFIG_EXT3_FS=y
+ CONFIG_EXT4_FS=y
+ CONFIG_QUOTA=y
+ CONFIG_QFMT_V2=y
++CONFIG_AUTOFS4_FS=y
+ CONFIG_MSDOS_FS=y
+ CONFIG_VFAT_FS=y
+ CONFIG_TMPFS=y
+@@ -214,23 +230,20 @@ CONFIG_JFFS2_RUBIN=y
+ CONFIG_UBIFS_FS=y
+ CONFIG_CRAMFS=y
+ CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+ CONFIG_NFS_V3_ACL=y
+ CONFIG_NFS_V4=y
+ CONFIG_ROOT_NFS=y
+-CONFIG_PARTITION_ADVANCED=y
+ CONFIG_NLS_CODEPAGE_437=y
+ CONFIG_NLS_ISO8859_1=y
+ CONFIG_PRINTK_TIME=y
+ CONFIG_MAGIC_SYSRQ=y
+-CONFIG_DEBUG_KERNEL=y
+ CONFIG_SCHEDSTATS=y
+ CONFIG_TIMER_STATS=y
+ CONFIG_PROVE_LOCKING=y
+-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+ # CONFIG_DEBUG_BUGVERBOSE is not set
+ CONFIG_DEBUG_INFO=y
+-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++CONFIG_DEBUG_LL=y
++CONFIG_EARLY_PRINTK=y
+ CONFIG_SECURITY=y
+ CONFIG_CRYPTO_MICHAEL_MIC=y
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
+@@ -239,4 +252,3 @@ CONFIG_CRC_T10DIF=y
+ CONFIG_CRC_ITU_T=y
+ CONFIG_CRC7=y
+ CONFIG_LIBCRC32C=y
+-CONFIG_SOC_OMAP5=y
diff --git a/patches/linux-3.7-rc6/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch b/patches/linux-3.7-rc6/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch
new file mode 100644
index 0000000..b30da0c
--- /dev/null
+++ b/patches/linux-3.7-rc6/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch
@@ -0,0 +1,2001 @@
+From 3e2a5b5bd5dc697a3c060f6527f22543be1be880 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Mon, 15 Oct 2012 10:17:43 -0400
+Subject: [PATCH] ARM: configs: working da850 edma dmaengine defconfig
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/configs/da8xx_omapl_defconfig | 1878 +++++++++++++++++++++++++++++++-
+ 1 file changed, 1857 insertions(+), 21 deletions(-)
+
+diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig
+index 88ccde0..571445f 100644
+--- a/arch/arm/configs/da8xx_omapl_defconfig
++++ b/arch/arm/configs/da8xx_omapl_defconfig
+@@ -1,129 +1,1965 @@
++#
++# Automatically generated file; DO NOT EDIT.
++# Linux/arm 3.7.0-rc1 Kernel Configuration
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_HAVE_PROC_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_ARCH_HAS_CPUFREQ=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_NEED_DMA_MAP_STATE=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_ARM_PATCH_PHYS_VIRT=y
++CONFIG_NEED_MACH_GPIO_H=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_HAVE_IRQ_WORK=y
++
++#
++# General setup
++#
+ CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_CROSS_COMPILE=""
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_HAVE_KERNEL_GZIP=y
++CONFIG_HAVE_KERNEL_LZMA=y
++CONFIG_HAVE_KERNEL_XZ=y
++CONFIG_HAVE_KERNEL_LZO=y
++CONFIG_KERNEL_GZIP=y
++# CONFIG_KERNEL_LZMA is not set
++# CONFIG_KERNEL_XZ is not set
++# CONFIG_KERNEL_LZO is not set
++CONFIG_DEFAULT_HOSTNAME="(none)"
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
+ CONFIG_POSIX_MQUEUE=y
++CONFIG_POSIX_MQUEUE_SYSCTL=y
++# CONFIG_FHANDLE is not set
++# CONFIG_AUDIT is not set
++CONFIG_HAVE_GENERIC_HARDIRQS=y
++
++#
++# IRQ subsystem
++#
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_IRQ_SHOW=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_CHIP=y
++CONFIG_IRQ_DOMAIN=y
++# CONFIG_IRQ_DOMAIN_DEBUG is not set
++CONFIG_KTIME_SCALAR=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++
++#
++# Timers subsystem
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++
++#
++# CPU/Task time and stats accounting
++#
++CONFIG_TICK_CPU_ACCOUNTING=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_TINY_PREEMPT_RCU=y
++CONFIG_PREEMPT_RCU=y
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_RCU_BOOST is not set
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++# CONFIG_CHECKPOINT_RESTORE is not set
++# CONFIG_NAMESPACES is not set
++# CONFIG_SCHED_AUTOGROUP is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
+ CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
++# CONFIG_RD_XZ is not set
++# CONFIG_RD_LZO is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
+ CONFIG_EXPERT=y
++CONFIG_HAVE_UID16=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++# CONFIG_EMBEDDED is not set
++CONFIG_HAVE_PERF_EVENTS=y
++CONFIG_PERF_USE_VMALLOC=y
++
++#
++# Kernel Performance Events And Counters
++#
++# CONFIG_PERF_EVENTS is not set
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++# CONFIG_JUMP_LABEL is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_ARCH_TRACEHOOK=y
++CONFIG_HAVE_DMA_ATTRS=y
++CONFIG_HAVE_DMA_CONTIGUOUS=y
++CONFIG_GENERIC_SMP_IDLE_THREAD=y
++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
++CONFIG_HAVE_CLK=y
++CONFIG_HAVE_DMA_API_DEBUG=y
++CONFIG_HAVE_ARCH_JUMP_LABEL=y
++CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
++CONFIG_GENERIC_KERNEL_THREAD=y
++CONFIG_GENERIC_KERNEL_EXECVE=y
++CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
++CONFIG_MODULES_USE_ELF_REL=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_GCOV_KERNEL is not set
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
+ CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODULE_FORCE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_MODULE_SIG is not set
++CONFIG_BLOCK=y
++CONFIG_LBDAF=y
+ # CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_BSGLIB is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
+ # CONFIG_IOSCHED_DEADLINE is not set
+ # CONFIG_IOSCHED_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_UNINLINE_SPIN_UNLOCK=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_MMU=y
++# CONFIG_ARCH_MULTIPLATFORM is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_BCM2835 is not set
++# CONFIG_ARCH_CNS3XXX is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
++# CONFIG_ARCH_SIRF is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_MXS is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_DOVE is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_W90X900 is not set
++# CONFIG_ARCH_LPC32XX is not set
++# CONFIG_ARCH_TEGRA is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_SHMOBILE is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C24XX is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_S5P64X0 is not set
++# CONFIG_ARCH_S5PC100 is not set
++# CONFIG_ARCH_S5PV210 is not set
++# CONFIG_ARCH_EXYNOS is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_U300 is not set
++# CONFIG_ARCH_U8500 is not set
++# CONFIG_ARCH_NOMADIK is not set
++# CONFIG_PLAT_SPEAR is not set
+ CONFIG_ARCH_DAVINCI=y
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VT8500 is not set
++# CONFIG_ARCH_ZYNQ is not set
++CONFIG_CP_INTC=y
++
++#
++# TI DaVinci Implementations
++#
++
++#
++# DaVinci Core Type
++#
++# CONFIG_ARCH_DAVINCI_DM644x is not set
++# CONFIG_ARCH_DAVINCI_DM355 is not set
++# CONFIG_ARCH_DAVINCI_DM646x is not set
+ CONFIG_ARCH_DAVINCI_DA830=y
+ CONFIG_ARCH_DAVINCI_DA850=y
++CONFIG_ARCH_DAVINCI_DA8XX=y
++# CONFIG_ARCH_DAVINCI_DM365 is not set
++# CONFIG_ARCH_DAVINCI_TNETV107X is not set
++
++#
++# DaVinci Board Type
++#
++CONFIG_MACH_DAVINCI_DA830_EVM=y
++CONFIG_DA830_UI_LCD=y
++# CONFIG_DA830_UI_NAND is not set
++CONFIG_MACH_DAVINCI_DA850_EVM=y
++CONFIG_DA850_UI_NONE=y
++# CONFIG_DA850_UI_RMII is not set
++# CONFIG_DA850_UI_SD_VIDEO_PORT is not set
++# CONFIG_DA850_WL12XX is not set
++CONFIG_GPIO_PCA953X=y
++CONFIG_KEYBOARD_GPIO_POLLED=y
+ CONFIG_MACH_MITYOMAPL138=y
+ CONFIG_MACH_OMAPL138_HAWKBOARD=y
++CONFIG_DAVINCI_MUX=y
++# CONFIG_DAVINCI_MUX_DEBUG is not set
++# CONFIG_DAVINCI_MUX_WARNINGS is not set
+ CONFIG_DAVINCI_RESET_CLOCKS=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_LEGACY=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++CONFIG_CPU_USE_DOMAINS=y
++
++#
++# Processor Features
++#
++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++CONFIG_CPU_DCACHE_WRITETHROUGH=y
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_CACHE_L2X0 is not set
++CONFIG_ARM_L1_CACHE_SHIFT=5
++CONFIG_ARM_NR_BANKS=8
++CONFIG_TI_PRIV_EDMA=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++CONFIG_ARCH_NR_GPIO=0
++# CONFIG_PREEMPT_NONE is not set
++# CONFIG_PREEMPT_VOLUNTARY is not set
+ CONFIG_PREEMPT=y
++CONFIG_PREEMPT_COUNT=y
++CONFIG_HZ=100
+ CONFIG_AEABI=y
+ # CONFIG_OABI_COMPAT is not set
+-CONFIG_LEDS=y
++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_HAVE_ARCH_PFN_VALID=y
++# CONFIG_HIGHMEM is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_HAVE_MEMBLOCK=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=999999
++CONFIG_COMPACTION=y
++CONFIG_MIGRATION=y
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_KSM is not set
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
++CONFIG_CROSS_MEMORY_ATTACH=y
++CONFIG_NEED_PER_CPU_KM=y
++# CONFIG_CLEANCACHE is not set
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
++# CONFIG_SECCOMP is not set
++# CONFIG_CC_STACKPROTECTOR is not set
++
++#
++# Boot options
++#
++# CONFIG_USE_OF is not set
++CONFIG_ATAGS=y
++# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++# CONFIG_CRASH_DUMP is not set
++# CONFIG_AUTO_ZRELADDR is not set
++
++#
++# CPU Power Management
++#
++
++#
++# CPU Frequency scaling
++#
+ CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++CONFIG_CPU_FREQ_STAT=y
++# CONFIG_CPU_FREQ_STAT_DETAILS is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+ CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+ CONFIG_CPU_FREQ_GOV_PERFORMANCE=m
+ CONFIG_CPU_FREQ_GOV_POWERSAVE=m
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
+ CONFIG_CPU_FREQ_GOV_ONDEMAND=m
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
++
++#
++# ARM CPU frequency scaling drivers
++#
++# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
+ CONFIG_CPU_IDLE=y
++CONFIG_CPU_IDLE_GOV_LADDER=y
++CONFIG_CPU_IDLE_GOV_MENU=y
++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++CONFIG_COREDUMP=y
++
++#
++# Power management options
++#
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++CONFIG_PM_SLEEP=y
++# CONFIG_PM_AUTOSLEEP is not set
++# CONFIG_PM_WAKELOCKS is not set
++# CONFIG_PM_RUNTIME is not set
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++# CONFIG_APM_EMULATION is not set
++CONFIG_PM_CLK=y
++CONFIG_CPU_PM=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_ARM_CPU_SUSPEND=y
+ CONFIG_NET=y
++
++#
++# Networking options
++#
+ CONFIG_PACKET=y
++# CONFIG_PACKET_DIAG is not set
+ CONFIG_UNIX=y
++# CONFIG_UNIX_DIAG is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
+ CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
+ CONFIG_IP_PNP=y
+ CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE_DEMUX is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_NET_IPVTI is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
+ # CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_INET_UDP_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++# CONFIG_IPV6_SIT_6RD is not set
++CONFIG_IPV6_NDISC_NODETYPE=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_GRE is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+ CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_ACCT is not set
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_XTABLES is not set
++# CONFIG_IP_VS is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV4 is not set
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++
++#
++# IPv6: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV6 is not set
++# CONFIG_IP6_NF_IPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_RDS is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_L2TP is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_PHONET is not set
++# CONFIG_IEEE802154 is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++# CONFIG_BATMAN_ADV is not set
++# CONFIG_OPENVSWITCH is not set
++CONFIG_BQL=y
++# CONFIG_BPF_JIT is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++# CONFIG_LIB80211 is not set
++
++#
++# CFG80211 needs to be enabled for MAC80211
++#
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_RFKILL_REGULATOR is not set
++# CONFIG_NET_9P is not set
++# CONFIG_CAIF is not set
++# CONFIG_CEPH_LIB is not set
++# CONFIG_NFC is not set
++CONFIG_HAVE_BPF_JIT=y
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++# CONFIG_DEVTMPFS is not set
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_GENERIC_CPU_DEVICES is not set
++CONFIG_REGMAP=y
++CONFIG_REGMAP_I2C=y
++CONFIG_REGMAP_SPI=y
++# CONFIG_DMA_SHARED_BUFFER is not set
++# CONFIG_CMA is not set
++
++#
++# Bus devices
++#
++# CONFIG_OMAP_OCP2SCP is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_TESTS is not set
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++# CONFIG_MTD_BLKDEVS is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_SM_FTL is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++# CONFIG_MTD_CFI is not set
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++CONFIG_MTD_M25P80=y
++CONFIG_M25PXX_USE_FAST_READ=y
++# CONFIG_MTD_SST25L is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOCG3 is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
+ CONFIG_BLK_DEV_LOOP=m
++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++
++#
++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
++#
++# CONFIG_BLK_DEV_NBD is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=1
+ CONFIG_BLK_DEV_RAM_SIZE=32768
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MG_DISK is not set
++# CONFIG_BLK_DEV_RBD is not set
++
++#
++# Misc devices
++#
++# CONFIG_SENSORS_LIS3LV02D is not set
++# CONFIG_AD525X_DPOT is not set
++# CONFIG_ATMEL_PWM is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_APDS9802ALS is not set
++# CONFIG_ISL29003 is not set
++# CONFIG_ISL29020 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_SENSORS_BH1780 is not set
++# CONFIG_SENSORS_BH1770 is not set
++# CONFIG_SENSORS_APDS990X is not set
++# CONFIG_HMC6352 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_TI_DAC7512 is not set
++# CONFIG_BMP085_I2C is not set
++# CONFIG_BMP085_SPI is not set
++# CONFIG_USB_SWITCH_FSA9480 is not set
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
+ CONFIG_EEPROM_AT24=y
++# CONFIG_EEPROM_AT25 is not set
++# CONFIG_EEPROM_LEGACY is not set
++# CONFIG_EEPROM_MAX6875 is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_EEPROM_93XX46 is not set
++
++#
++# Texas Instruments shared transport line discipline
++#
++# CONFIG_TI_ST is not set
++# CONFIG_SENSORS_LIS3_SPI is not set
++# CONFIG_SENSORS_LIS3_I2C is not set
++
++#
++# Altera FPGA firmware download module
++#
++# CONFIG_ALTERA_STAPL is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI_MOD=m
++# CONFIG_RAID_ATTRS is not set
+ CONFIG_SCSI=m
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
+ CONFIG_BLK_DEV_SD=m
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_ISCSI_BOOT_SYSFS is not set
++# CONFIG_LIBFC is not set
++# CONFIG_LIBFCOE is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_TARGET_CORE is not set
+ CONFIG_NETDEVICES=y
+-CONFIG_TUN=m
+-CONFIG_LXT_PHY=y
+-CONFIG_LSI_ET1011C_PHY=y
+-CONFIG_NET_ETHERNET=y
++CONFIG_NET_CORE=y
++# CONFIG_BONDING is not set
++# CONFIG_DUMMY is not set
++# CONFIG_EQUALIZER is not set
+ CONFIG_MII=y
+-CONFIG_TI_DAVINCI_EMAC=y
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
++# CONFIG_NET_TEAM is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_VXLAN is not set
+ CONFIG_NETCONSOLE=y
++CONFIG_NETPOLL=y
+ CONFIG_NETPOLL_TRAP=y
++CONFIG_NET_POLL_CONTROLLER=y
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++
++#
++# CAIF transport drivers
++#
++CONFIG_ETHERNET=y
++CONFIG_NET_VENDOR_BROADCOM=y
++# CONFIG_B44 is not set
++# CONFIG_NET_CALXEDA_XGMAC is not set
++CONFIG_NET_VENDOR_CHELSIO=y
++CONFIG_NET_VENDOR_CIRRUS=y
++# CONFIG_CS89x0 is not set
++# CONFIG_DM9000 is not set
++# CONFIG_DNET is not set
++CONFIG_NET_VENDOR_FARADAY=y
++# CONFIG_FTMAC100 is not set
++# CONFIG_FTGMAC100 is not set
++CONFIG_NET_VENDOR_INTEL=y
++CONFIG_NET_VENDOR_I825XX=y
++CONFIG_NET_VENDOR_MARVELL=y
++CONFIG_NET_VENDOR_MICREL=y
++# CONFIG_KS8842 is not set
++# CONFIG_KS8851 is not set
++# CONFIG_KS8851_MLL is not set
++CONFIG_NET_VENDOR_MICROCHIP=y
++# CONFIG_ENC28J60 is not set
++CONFIG_NET_VENDOR_NATSEMI=y
++CONFIG_NET_VENDOR_8390=y
++# CONFIG_AX88796 is not set
++# CONFIG_ETHOC is not set
++CONFIG_NET_VENDOR_SEEQ=y
++# CONFIG_SEEQ8005 is not set
++CONFIG_NET_VENDOR_SMSC=y
++# CONFIG_SMC91X is not set
++# CONFIG_SMC911X is not set
++# CONFIG_SMSC911X is not set
++CONFIG_NET_VENDOR_STMICRO=y
++# CONFIG_STMMAC_ETH is not set
++CONFIG_NET_VENDOR_TI=y
++CONFIG_TI_DAVINCI_EMAC=y
++CONFIG_TI_DAVINCI_MDIO=y
++CONFIG_TI_DAVINCI_CPDMA=y
++# CONFIG_TI_CPSW is not set
++CONFIG_NET_VENDOR_WIZNET=y
++# CONFIG_WIZNET_W5100 is not set
++# CONFIG_WIZNET_W5300 is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_AMD_PHY is not set
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++CONFIG_LXT_PHY=y
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++# CONFIG_SMSC_PHY is not set
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_BCM87XX_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_NATIONAL_PHY is not set
++# CONFIG_STE10XP is not set
++CONFIG_LSI_ET1011C_PHY=y
++# CONFIG_MICREL_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++# CONFIG_MICREL_KS8995MA is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++CONFIG_WLAN=y
++# CONFIG_HOSTAP is not set
++# CONFIG_WL_TI is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++# CONFIG_WAN is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++CONFIG_INPUT_POLLDEV=y
++# CONFIG_INPUT_SPARSEKMAP is not set
++# CONFIG_INPUT_MATRIXKMAP is not set
++
++#
++# Userland interfaces
++#
+ CONFIG_INPUT_MOUSEDEV=m
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
+ CONFIG_INPUT_EVDEV=m
+ CONFIG_INPUT_EVBUG=m
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ADP5588 is not set
++# CONFIG_KEYBOARD_ADP5589 is not set
+ CONFIG_KEYBOARD_ATKBD=m
++# CONFIG_KEYBOARD_QT1070 is not set
++# CONFIG_KEYBOARD_QT2160 is not set
++# CONFIG_KEYBOARD_LKKBD is not set
+ CONFIG_KEYBOARD_GPIO=y
++# CONFIG_KEYBOARD_TCA6416 is not set
++# CONFIG_KEYBOARD_TCA8418 is not set
++# CONFIG_KEYBOARD_MATRIX is not set
++# CONFIG_KEYBOARD_LM8333 is not set
++# CONFIG_KEYBOARD_MAX7359 is not set
++# CONFIG_KEYBOARD_MCS is not set
++# CONFIG_KEYBOARD_MPR121 is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_KEYBOARD_SAMSUNG is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_OMAP4 is not set
+ CONFIG_KEYBOARD_XTKBD=m
+ # CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_ADS7846 is not set
++# CONFIG_TOUCHSCREEN_AD7877 is not set
++# CONFIG_TOUCHSCREEN_AD7879 is not set
++# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
++# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
++# CONFIG_TOUCHSCREEN_BU21013 is not set
++# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
++# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
++# CONFIG_TOUCHSCREEN_DYNAPRO is not set
++# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
++# CONFIG_TOUCHSCREEN_EETI is not set
++# CONFIG_TOUCHSCREEN_EGALAX is not set
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_ILI210X is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
++# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
++# CONFIG_TOUCHSCREEN_MAX11801 is not set
++# CONFIG_TOUCHSCREEN_MCS5000 is not set
++# CONFIG_TOUCHSCREEN_MMS114 is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_INEXIO is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_PIXCIR is not set
++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
++# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
++# CONFIG_TOUCHSCREEN_TSC2005 is not set
++# CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_TOUCHSCREEN_W90X900 is not set
++# CONFIG_TOUCHSCREEN_ST1232 is not set
++# CONFIG_TOUCHSCREEN_TPS6507X is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
+ CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_SERIO_ALTERA_PS2 is not set
++# CONFIG_SERIO_PS2MULT is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
+ # CONFIG_VT_CONSOLE is not set
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_N_GSM is not set
++# CONFIG_TRACE_SINK is not set
++CONFIG_DEVKMEM=y
++
++#
++# Serial drivers
++#
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+ CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_SERIAL_8250_EXTENDED is not set
++# CONFIG_SERIAL_8250_EM is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_MAX3100 is not set
++# CONFIG_SERIAL_MAX310X is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_SCCNXP is not set
++# CONFIG_SERIAL_TIMBERDALE is not set
++# CONFIG_SERIAL_ALTERA_JTAGUART is not set
++# CONFIG_SERIAL_ALTERA_UART is not set
++# CONFIG_SERIAL_IFX6X60 is not set
++# CONFIG_SERIAL_XILINX_PS_UART is not set
++# CONFIG_TTY_PRINTK is not set
++# CONFIG_HVC_DCC is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
++# CONFIG_HW_RANDOM_ATMEL is not set
++# CONFIG_HW_RANDOM_EXYNOS is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_COMPAT=y
+ CONFIG_I2C_CHARDEV=y
++# CONFIG_I2C_MUX is not set
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
+ CONFIG_I2C_DAVINCI=y
++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_PXA_PCI is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_XILINX is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_ALTERA is not set
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_DAVINCI=y
++# CONFIG_SPI_GPIO is not set
++# CONFIG_SPI_OC_TINY is not set
++# CONFIG_SPI_PXA2XX_PCI is not set
++# CONFIG_SPI_SC18IS602 is not set
++# CONFIG_SPI_XCOMM is not set
++# CONFIG_SPI_XILINX is not set
++# CONFIG_SPI_DESIGNWARE is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_HSI is not set
++
++#
++# PPS support
++#
++# CONFIG_PPS is not set
++
++#
++# PPS generators support
++#
++
++#
++# PTP clock support
++#
++
++#
++# Enable Device Drivers -> PPS to see the PTP clock options.
++#
++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++# CONFIG_DEBUG_GPIO is not set
++# CONFIG_GPIO_SYSFS is not set
++
++#
++# Memory mapped GPIO drivers:
++#
++# CONFIG_GPIO_GENERIC_PLATFORM is not set
++# CONFIG_GPIO_EM is not set
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX7300 is not set
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X_IRQ is not set
++CONFIG_GPIO_PCF857X=y
++# CONFIG_GPIO_SX150X is not set
++# CONFIG_GPIO_ADP5588 is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_GPIO_MC33880 is not set
++# CONFIG_GPIO_74X164 is not set
++
++#
++# AC97 GPIO expanders:
++#
++
++#
++# MODULbus GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_POWER_AVS is not set
+ # CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
+ CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_CORE is not set
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_DW_WATCHDOG is not set
++# CONFIG_DAVINCI_WATCHDOG is not set
++# CONFIG_MAX63XX_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++CONFIG_BCMA_POSSIBLE=y
++
++#
++# Broadcom specific AMBA
++#
++# CONFIG_BCMA is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_88PM860X is not set
++# CONFIG_MFD_88PM800 is not set
++# CONFIG_MFD_88PM805 is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_HTC_I2CPLD is not set
++# CONFIG_MFD_LM3533 is not set
++# CONFIG_TPS6105X is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_TPS6507X is not set
++# CONFIG_MFD_TPS65217 is not set
++# CONFIG_MFD_TPS6586X is not set
++# CONFIG_MFD_TPS65910 is not set
++# CONFIG_MFD_TPS65912_I2C is not set
++# CONFIG_MFD_TPS65912_SPI is not set
++# CONFIG_TWL4030_CORE is not set
++# CONFIG_TWL6040_CORE is not set
++# CONFIG_MFD_STMPE is not set
++# CONFIG_MFD_TC3589X is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_T7L66XB is not set
++# CONFIG_MFD_SMSC is not set
++# CONFIG_MFD_TC6387XB is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_DA9052_SPI is not set
++# CONFIG_MFD_DA9052_I2C is not set
++# CONFIG_MFD_DA9055 is not set
++# CONFIG_PMIC_ADP5520 is not set
++# CONFIG_MFD_LP8788 is not set
++# CONFIG_MFD_MAX77686 is not set
++# CONFIG_MFD_MAX77693 is not set
++# CONFIG_MFD_MAX8907 is not set
++# CONFIG_MFD_MAX8925 is not set
++# CONFIG_MFD_MAX8997 is not set
++# CONFIG_MFD_MAX8998 is not set
++# CONFIG_MFD_SEC_CORE is not set
++# CONFIG_MFD_ARIZONA_I2C is not set
++# CONFIG_MFD_ARIZONA_SPI is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM831X_I2C is not set
++# CONFIG_MFD_WM831X_SPI is not set
++# CONFIG_MFD_WM8350_I2C is not set
++# CONFIG_MFD_WM8994 is not set
++# CONFIG_MFD_PCF50633 is not set
++# CONFIG_MFD_MC13XXX_SPI is not set
++# CONFIG_MFD_MC13XXX_I2C is not set
++# CONFIG_ABX500_CORE is not set
++# CONFIG_EZX_PCAP is not set
++# CONFIG_MFD_WL1273_CORE is not set
++# CONFIG_MFD_TPS65090 is not set
++# CONFIG_MFD_AAT2870_CORE is not set
++# CONFIG_MFD_RC5T583 is not set
++# CONFIG_MFD_PALMAS is not set
+ CONFIG_REGULATOR=y
++# CONFIG_REGULATOR_DEBUG is not set
+ CONFIG_REGULATOR_DUMMY=y
++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
++# CONFIG_REGULATOR_GPIO is not set
++# CONFIG_REGULATOR_AD5398 is not set
++# CONFIG_REGULATOR_FAN53555 is not set
++# CONFIG_REGULATOR_ISL6271A is not set
++# CONFIG_REGULATOR_MAX1586 is not set
++# CONFIG_REGULATOR_MAX8649 is not set
++# CONFIG_REGULATOR_MAX8660 is not set
++# CONFIG_REGULATOR_MAX8952 is not set
++# CONFIG_REGULATOR_LP3971 is not set
++# CONFIG_REGULATOR_LP3972 is not set
++# CONFIG_REGULATOR_LP872X is not set
++# CONFIG_REGULATOR_TPS62360 is not set
++# CONFIG_REGULATOR_TPS65023 is not set
+ CONFIG_REGULATOR_TPS6507X=y
++# CONFIG_REGULATOR_TPS6524X is not set
++# CONFIG_MEDIA_SUPPORT is not set
++
++#
++# Graphics support
++#
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++CONFIG_FB_CFB_REV_PIXELS_IN_BYTE=y
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_WMT_GE_ROPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
+ CONFIG_FB_DA8XX=y
+-# CONFIG_VGA_CONSOLE is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_BROADSHEET is not set
++# CONFIG_FB_AUO_K190X is not set
++# CONFIG_FB_ST7735 is not set
++# CONFIG_EXYNOS_VIDEO is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_DUMMY_CONSOLE=y
+ CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++# CONFIG_FONTS is not set
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
+ CONFIG_LOGO=y
+-CONFIG_SOUND=m
+-CONFIG_SND=m
+-CONFIG_SND_SOC=m
+-CONFIG_SND_DAVINCI_SOC=m
+-# CONFIG_HID_SUPPORT is not set
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++CONFIG_SOUND=y
++# CONFIG_SOUND_OSS_CORE is not set
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++CONFIG_SND_COMPRESS_OFFLOAD=y
++CONFIG_SND_JACK=y
++# CONFIG_SND_SEQUENCER is not set
++# CONFIG_SND_MIXER_OSS is not set
++# CONFIG_SND_PCM_OSS is not set
++# CONFIG_SND_HRTIMER is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++# CONFIG_SND_RAWMIDI_SEQ is not set
++# CONFIG_SND_OPL3_LIB_SEQ is not set
++# CONFIG_SND_OPL4_LIB_SEQ is not set
++# CONFIG_SND_SBAWE_SEQ is not set
++# CONFIG_SND_EMU10K1_SEQ is not set
++CONFIG_SND_DRIVERS=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_ALOOP is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++CONFIG_SND_ARM=y
++CONFIG_SND_SPI=y
++CONFIG_SND_SOC=y
++CONFIG_SND_DAVINCI_SOC=y
++CONFIG_SND_DAVINCI_SOC_MCASP=y
++# CONFIG_SND_DA830_SOC_EVM is not set
++CONFIG_SND_DA850_SOC_EVM=y
++# CONFIG_SND_DESIGNWARE_I2S is not set
++CONFIG_SND_SOC_I2C_AND_SPI=y
++# CONFIG_SND_SOC_ALL_CODECS is not set
++CONFIG_SND_SOC_TLV320AIC3X=y
++# CONFIG_SND_SIMPLE_CARD is not set
++# CONFIG_SOUND_PRIME is not set
++
++#
++# HID support
++#
++CONFIG_HID=y
++# CONFIG_HIDRAW is not set
++# CONFIG_UHID is not set
++CONFIG_HID_GENERIC=y
++
++#
++# Special HID drivers
++#
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB_ARCH_HAS_XHCI is not set
+ # CONFIG_USB_SUPPORT is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++CONFIG_MMC_UNSAFE_RESUME=y
++# CONFIG_MMC_CLKGATE is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_MINORS=8
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_SDHCI is not set
++# CONFIG_MMC_SDHCI_PXAV3 is not set
++# CONFIG_MMC_SDHCI_PXAV2 is not set
++CONFIG_MMC_DAVINCI=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_MMC_DW is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_DS3232 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_ISL12022 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_BQ32K is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++# CONFIG_RTC_DRV_RX8025 is not set
++# CONFIG_RTC_DRV_EM3027 is not set
++# CONFIG_RTC_DRV_RV3029C2 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T93 is not set
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++# CONFIG_RTC_DRV_PCF2123 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_MSM6242 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_RP5C01 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++# CONFIG_RTC_DRV_DS2404 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_OMAP=y
++CONFIG_DMADEVICES=y
++# CONFIG_DMADEVICES_DEBUG is not set
++
++#
++# DMA Devices
++#
++# CONFIG_DW_DMAC is not set
++# CONFIG_TIMB_DMA is not set
++CONFIG_TI_EDMA=y
++CONFIG_DMA_ENGINE=y
++CONFIG_DMA_VIRTUAL_CHANNELS=y
++
++#
++# DMA Clients
++#
++# CONFIG_NET_DMA is not set
++# CONFIG_ASYNC_TX_DMA is not set
++# CONFIG_DMATEST is not set
++# CONFIG_AUXDISPLAY is not set
++CONFIG_UIO=y
++# CONFIG_UIO_PDRV is not set
++# CONFIG_UIO_PDRV_GENIRQ is not set
++CONFIG_UIO_PRUSS=y
++
++#
++# Virtio drivers
++#
++# CONFIG_VIRTIO_MMIO is not set
++
++#
++# Microsoft Hyper-V guest support
++#
++# CONFIG_STAGING is not set
++CONFIG_CLKDEV_LOOKUP=y
++
++#
++# Hardware Spinlock drivers
++#
++CONFIG_IOMMU_SUPPORT=y
++
++#
++# Remoteproc drivers (EXPERIMENTAL)
++#
++# CONFIG_STE_MODEM_RPROC is not set
++
++#
++# Rpmsg drivers (EXPERIMENTAL)
++#
++# CONFIG_VIRT_DRIVERS is not set
++# CONFIG_PM_DEVFREQ is not set
++# CONFIG_EXTCON is not set
++# CONFIG_MEMORY is not set
++# CONFIG_IIO is not set
++# CONFIG_PWM is not set
++
++#
++# File systems
++#
+ CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
+ CONFIG_EXT3_FS=y
++CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
+ CONFIG_XFS_FS=m
+-CONFIG_INOTIFY=y
++# CONFIG_XFS_QUOTA is not set
++# CONFIG_XFS_POSIX_ACL is not set
++# CONFIG_XFS_RT is not set
++# CONFIG_XFS_DEBUG is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++# CONFIG_NILFS2_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++CONFIG_EXPORTFS=m
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_FANOTIFY is not set
++# CONFIG_QUOTA is not set
++# CONFIG_QUOTACTL is not set
+ CONFIG_AUTOFS4_FS=m
++# CONFIG_FUSE_FS is not set
++
++#
++# Caches
++#
++# CONFIG_FSCACHE is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
+ CONFIG_MSDOS_FS=y
+ CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS2_FS is not set
++# CONFIG_LOGFS is not set
+ CONFIG_CRAMFS=y
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
+ CONFIG_MINIX_FS=m
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX6FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_PSTORE is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
++CONFIG_NFS_V2=y
+ CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_SWAP is not set
+ CONFIG_ROOT_NFS=y
+ CONFIG_NFSD=m
+ CONFIG_NFSD_V3=y
+-CONFIG_SMB_FS=m
+-CONFIG_PARTITION_ADVANCED=y
++# CONFIG_NFSD_V3_ACL is not set
++# CONFIG_NFSD_V4 is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_DEBUG is not set
++# CONFIG_CEPH_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
+ CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
+ CONFIG_NLS_ASCII=m
+ CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_MAC_ROMAN is not set
++# CONFIG_NLS_MAC_CELTIC is not set
++# CONFIG_NLS_MAC_CENTEURO is not set
++# CONFIG_NLS_MAC_CROATIAN is not set
++# CONFIG_NLS_MAC_CYRILLIC is not set
++# CONFIG_NLS_MAC_GAELIC is not set
++# CONFIG_NLS_MAC_GREEK is not set
++# CONFIG_NLS_MAC_ICELAND is not set
++# CONFIG_NLS_MAC_INUIT is not set
++# CONFIG_NLS_MAC_ROMANIAN is not set
++# CONFIG_NLS_MAC_TURKISH is not set
+ CONFIG_NLS_UTF8=m
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_STRIP_ASM_SYMS is not set
++# CONFIG_READABLE_ASM is not set
++# CONFIG_UNUSED_SYMBOLS is not set
+ CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_SECTION_MISMATCH is not set
+ CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_LOCKUP_DETECTOR is not set
++# CONFIG_PANIC_ON_OOPS is not set
++CONFIG_PANIC_ON_OOPS_VALUE=0
++# CONFIG_DETECT_HUNG_TASK is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
+ CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_HAVE_DEBUG_KMEMLEAK=y
++# CONFIG_DEBUG_KMEMLEAK is not set
++CONFIG_DEBUG_PREEMPT=y
+ CONFIG_DEBUG_RT_MUTEXES=y
++CONFIG_DEBUG_PI_LIST=y
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
+ CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_PROVE_RCU_DELAY is not set
++# CONFIG_SPARSE_RCU_POINTER is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_ATOMIC_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
++# CONFIG_DEBUG_MEMORY_INIT is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_TEST_LIST_SORT is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_DEBUG_NOTIFIERS is not set
++# CONFIG_DEBUG_CREDENTIALS is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_RCU_TRACE is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
++# CONFIG_LKDTM is not set
++# CONFIG_NOTIFIER_ERROR_INJECTION is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
++CONFIG_HAVE_DYNAMIC_FTRACE=y
++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
++CONFIG_HAVE_C_RECORDMCOUNT=y
++CONFIG_TRACING_SUPPORT=y
++CONFIG_FTRACE=y
++# CONFIG_FUNCTION_TRACER is not set
++# CONFIG_IRQSOFF_TRACER is not set
++# CONFIG_PREEMPT_TRACER is not set
++# CONFIG_SCHED_TRACER is not set
++# CONFIG_ENABLE_DEFAULT_TRACERS is not set
++# CONFIG_FTRACE_SYSCALLS is not set
++CONFIG_BRANCH_PROFILE_NONE=y
++# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
++# CONFIG_PROFILE_ALL_BRANCHES is not set
++# CONFIG_STACK_TRACER is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_PROBE_EVENTS is not set
++# CONFIG_RBTREE_TEST is not set
++# CONFIG_INTERVAL_TREE_TEST is not set
++# CONFIG_DYNAMIC_DEBUG is not set
++# CONFIG_DMA_API_DEBUG is not set
++# CONFIG_ATOMIC64_SELFTEST is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++# CONFIG_TEST_KSTRTOX is not set
++# CONFIG_STRICT_DEVMEM is not set
++CONFIG_ARM_UNWIND=y
+ CONFIG_DEBUG_USER=y
+-CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_LL is not set
++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY_DMESG_RESTRICT is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++CONFIG_DEFAULT_SECURITY_DAC=y
++CONFIG_DEFAULT_SECURITY=""
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_MANAGER2 is not set
++# CONFIG_CRYPTO_USER is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_VMAC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_GHASH is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA1_ARM is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++CONFIG_CRYPTO_AES=y
++# CONFIG_CRYPTO_AES_ARM is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_ZLIB is not set
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_USER_API_HASH is not set
++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+ # CONFIG_CRYPTO_HW is not set
++# CONFIG_BINARY_PRINTF is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_STRNCPY_FROM_USER=y
++CONFIG_GENERIC_STRNLEN_USER=y
++CONFIG_GENERIC_PCI_IOMAP=y
++CONFIG_GENERIC_IO=y
+ CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
+ CONFIG_CRC_T10DIF=m
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC32_SELFTEST is not set
++CONFIG_CRC32_SLICEBY8=y
++# CONFIG_CRC32_SLICEBY4 is not set
++# CONFIG_CRC32_SARWATE is not set
++# CONFIG_CRC32_BIT is not set
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++# CONFIG_CRC8 is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++# CONFIG_XZ_DEC is not set
++# CONFIG_XZ_DEC_BCJ is not set
++CONFIG_DECOMPRESS_GZIP=y
++CONFIG_GENERIC_ALLOCATOR=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_DQL=y
++CONFIG_NLATTR=y
++CONFIG_GENERIC_ATOMIC64=y
++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
++# CONFIG_AVERAGE is not set
++# CONFIG_CORDIC is not set
++# CONFIG_DDR is not set
diff --git a/patches/linux-3.7-rc6/0030-misc-gpevt-null-terminate-the-of_match_table.patch b/patches/linux-3.7-rc6/0030-misc-gpevt-null-terminate-the-of_match_table.patch
new file mode 100644
index 0000000..5edd618
--- /dev/null
+++ b/patches/linux-3.7-rc6/0030-misc-gpevt-null-terminate-the-of_match_table.patch
@@ -0,0 +1,22 @@
+From 07a646411ade49a270c87332d482f4ac6f0ecfba Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 18 Oct 2012 10:29:57 -0400
+Subject: [PATCH] misc: gpevt: null terminate the of_match_table
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/misc/gpevt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/misc/gpevt.c b/drivers/misc/gpevt.c
+index 4fe256c..c0cc1a2 100644
+--- a/drivers/misc/gpevt.c
++++ b/drivers/misc/gpevt.c
+@@ -139,6 +139,7 @@ static int __devexit gpevt_remove(struct platform_device *pdev)
+
+ static const struct of_device_id gpevt_dt_ids[] = {
+ { .compatible = "gpevt", .data = (void *) NULL, },
++ { },
+ };
+ MODULE_DEVICE_TABLE(of, gpevt_dt_ids);
+
diff --git a/patches/linux-3.7-rc6/0031-proposed-probe-fix-works-for-me-on-evm.patch b/patches/linux-3.7-rc6/0031-proposed-probe-fix-works-for-me-on-evm.patch
new file mode 100644
index 0000000..db77068
--- /dev/null
+++ b/patches/linux-3.7-rc6/0031-proposed-probe-fix-works-for-me-on-evm.patch
@@ -0,0 +1,43 @@
+From 93ae8a949f58bbd1d8c77baf116c5db2654d11c6 Mon Sep 17 00:00:00 2001
+From: Matt Porter <mporter@ti.com>
+Date: Fri, 19 Oct 2012 11:24:40 -0400
+Subject: [PATCH] proposed probe fix - works for me on evm
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index b761b7a..6ed394f 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -1598,6 +1598,8 @@ static struct of_dma_filter_info edma_filter_info = {
+ static int __init edma_probe(struct platform_device *pdev)
+ {
+ struct edma_soc_info **info = pdev->dev.platform_data;
++ struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL, NULL};
++ struct edma_soc_info tmpinfo;
+ s8 (*queue_priority_mapping)[2];
+ s8 (*queue_tc_mapping)[2];
+ int i, j, off, ln, found = 0;
+@@ -1614,15 +1616,13 @@ static int __init edma_probe(struct platform_device *pdev)
+ char irq_name[10];
+ struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+- struct edma_soc_info *pdata;
+ int ret;
+
+ if (node) {
+- pdata = devm_kzalloc(dev,
+- sizeof(struct edma_soc_info),
+- GFP_KERNEL);
+- edma_of_parse_dt(dev, node, pdata);
+- info = &pdata;
++ info = ninfo;
++ edma_of_parse_dt(dev, node, &tmpinfo);
++ info[0] = &tmpinfo;
++
+ dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
+ of_dma_controller_register(dev->of_node,
+ of_dma_simple_xlate,
diff --git a/patches/linux-3.7-rc6/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch b/patches/linux-3.7-rc6/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch
new file mode 100644
index 0000000..37d6082
--- /dev/null
+++ b/patches/linux-3.7-rc6/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch
@@ -0,0 +1,80 @@
+From 8889710c8dc2c6e67fec6124bb2c397bac5ae43d Mon Sep 17 00:00:00 2001
+From: Mugunthan V N <mugunthanvnm@ti.com>
+Date: Tue, 5 Jun 2012 13:18:01 +0530
+Subject: [PATCH] ARM: OMAP3+: hwmod: Add AM33XX HWMOD data for davinci_mdio
+
+This patch adds minimal hwmod support for davinci mdio driver. This patch
+requires rework on parent child relation between cpsw and davinci mdio
+hwmod data to support runtime PM.
+
+Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 34 ++++++++++++++++++++++++++--
+ 1 file changed, 32 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index 59d5c1c..f96bbc0 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -650,8 +650,7 @@ static struct omap_hwmod_class_sysconfig am33xx_cpgmac_sysc = {
+ .rev_offs = 0x0,
+ .sysc_offs = 0x8,
+ .syss_offs = 0x4,
+- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+- SYSS_HAS_RESET_STATUS),
++ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE |
+ MSTANDBY_NO),
+ .sysc_fields = &omap_hwmod_sysc_type3,
+@@ -682,6 +681,8 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
++ HWMOD_INIT_NO_RESET | HWMOD_INIT_NO_IDLE),
+ };
+
+ /*
+@@ -2510,6 +2511,34 @@ static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
+ { }
+ };
+
++/* mdio class */
++static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
++ .name = "davinci_mdio",
++};
++
++struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
++ {
++ .pa_start = 0x4A101000,
++ .pa_end = 0x4A101000 + SZ_256 - 1,
++ .flags = ADDR_MAP_ON_INIT,
++ },
++ { }
++};
++
++static struct omap_hwmod am33xx_mdio_hwmod = {
++ .name = "davinci_mdio",
++ .class = &am33xx_mdio_hwmod_class,
++ .clkdm_name = "cpsw_125mhz_clkdm",
++ .main_clk = "cpsw_125mhz_gclk",
++};
++
++struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
++ .master = &am33xx_cpgmac0_hwmod,
++ .slave = &am33xx_mdio_hwmod,
++ .addr = am33xx_mdio_addr_space,
++ .user = OCP_USER_MPU,
++};
++
+ static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
+ .master = &am33xx_l4_ls_hwmod,
+ .slave = &am33xx_elm_hwmod,
+@@ -3371,6 +3400,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l3_main__tptc2,
+ &am33xx_l3_s__usbss,
+ &am33xx_l4_hs__cpgmac0,
++ &am33xx_cpgmac0__mdio,
+ NULL,
+ };
+
diff --git a/patches/linux-3.7-rc6/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch b/patches/linux-3.7-rc6/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch
new file mode 100644
index 0000000..a15b51d
--- /dev/null
+++ b/patches/linux-3.7-rc6/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch
@@ -0,0 +1,35 @@
+From 009cf7834fb1707dd687934131d70750d037c376 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Mon, 3 Sep 2012 21:14:52 +0530
+Subject: [PATCH] net: davinci_mdio: Fix type mistake in calling runtime-pm
+ api
+
+By mistake (most likely a copy-paste), instead of pm_runtime_get_sync()
+api, driver is calling pm_runtime_put_sync() api in resume callback
+function. The bug was introduced by commit id (ae2c07aaf74:
+davinci_mdio: runtime PM support).
+
+Now, the reason why it didn't impact functionality is, the patch has
+been tested on AM335x-EVM and BeagleBone platform while submitting;
+and in case of AM335x the MDIO driver doesn't control the module
+enable/disable part, which is handled by CPSW driver.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+Cc: Mugunthan V N <mugunthanvnm@ti.com>
+---
+ drivers/net/ethernet/ti/davinci_mdio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
+index 51a96db..ae74280 100644
+--- a/drivers/net/ethernet/ti/davinci_mdio.c
++++ b/drivers/net/ethernet/ti/davinci_mdio.c
+@@ -465,7 +465,7 @@ static int davinci_mdio_resume(struct device *dev)
+ u32 ctrl;
+
+ spin_lock(&data->lock);
+- pm_runtime_put_sync(data->dev);
++ pm_runtime_get_sync(data->dev);
+
+ /* restart the scan state machine */
+ ctrl = __raw_readl(&data->regs->control);
diff --git a/patches/linux-3.7-rc6/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch b/patches/linux-3.7-rc6/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch
new file mode 100644
index 0000000..47f1029
--- /dev/null
+++ b/patches/linux-3.7-rc6/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch
@@ -0,0 +1,87 @@
+From a96742d124907b9056fadaa90590331b93ca25dc Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Mon, 3 Sep 2012 21:25:38 +0530
+Subject: [PATCH] net: cpsw: Add parent<->child relation support between cpsw
+ and mdio
+
+CPGMAC SubSystem consist of various sub-modules, like, mdio, cpdma,
+cpsw, etc... These sub-modules are also used in some of Davinci family
+of devices. Now based on requirement, use-case and available technology
+nodes the integration of these sub-modules varies across devices.
+
+So coming back to Linux net driver, currently separate and independent
+platform devices & drivers for CPSW and MDIO is implemented. In case of
+Davinci they both has separate control, from resources perspective,
+like clock.
+
+In case of AM33XX, the resources are shared and only one register
+bit-field is provided to control module/clock enable/disable, makes it
+difficult to handle common resource.
+
+So the solution here implemented in this patch is,
+
+Create parent<->child relationship between both the drivers, making
+CPSW as a parent and MDIO as its child and enumerate all the child nodes
+under cpsw module.
+Both the drivers will function exactly the way it was operating before,
+including runtime-pm functionality. No change is required in MDIO driver
+(for that matter to any child driver).
+
+As this is only supported during DT boot, the parent<->child relationship
+is created and populated in DT execution flow. The only required change
+is inside DTS file, making MDIO as a child to CPSW node.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+Cc: Mugunthan V N <mugunthanvnm@ti.com>
+---
+ drivers/net/ethernet/ti/cpsw.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
+index df55e24..fb1a692 100644
+--- a/drivers/net/ethernet/ti/cpsw.c
++++ b/drivers/net/ethernet/ti/cpsw.c
+@@ -827,7 +827,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
+ }
+ data->mac_control = prop;
+
+- for_each_child_of_node(node, slave_node) {
++ for_each_node_by_name(slave_node, "slave") {
+ struct cpsw_slave_data *slave_data = data->slave_data + i;
+ const char *phy_id = NULL;
+ const void *mac_addr = NULL;
+@@ -862,6 +862,14 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
+ i++;
+ }
+
++ /*
++ * Populate all the child nodes here...
++ */
++ ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
++ /* We do not want to force this, as in some cases may not have child */
++ if (ret)
++ pr_warn("Doesn't have any child node\n");
++
+ return 0;
+
+ error_ret:
+@@ -895,6 +903,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
+ priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
+ priv->rx_packet_max = max(rx_packet_max, 128);
+
++ /*
++ * This may be required here for child devices.
++ */
++ pm_runtime_enable(&pdev->dev);
++
+ if (cpsw_probe_dt(&priv->data, pdev)) {
+ pr_err("cpsw: platform data missing\n");
+ ret = -ENODEV;
+@@ -921,7 +934,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
+ for (i = 0; i < data->slaves; i++)
+ priv->slaves[i].slave_num = i;
+
+- pm_runtime_enable(&pdev->dev);
+ priv->clk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR(priv->clk)) {
+ dev_err(&pdev->dev, "fck is not found\n");
diff --git a/patches/linux-3.7-rc6/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch b/patches/linux-3.7-rc6/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch
new file mode 100644
index 0000000..a61d47c
--- /dev/null
+++ b/patches/linux-3.7-rc6/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch
@@ -0,0 +1,109 @@
+From bd5fdad1c484959dadf1daf6b1d433b9e1653390 Mon Sep 17 00:00:00 2001
+From: Mugunthan V N <mugunthanvnm@ti.com>
+Date: Sun, 29 Jul 2012 20:56:29 +0530
+Subject: [PATCH] arm/dts: am33xx: Add cpsw and mdio module nodes for AM33XX
+
+Add CPSW and MDIO related device tree data for AM33XX.
+Also enable them into board/evm dts files by providing
+respective phy-id.
+
+Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 8 ++++++
+ arch/arm/boot/dts/am335x-evm.dts | 8 ++++++
+ arch/arm/boot/dts/am33xx.dtsi | 50 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 66 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 2ad3914..47c17e8 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -137,3 +137,11 @@
+ &edma {
+ ti,edma-xbar-event-map = <32 12>;
+ };
++
++&cpsw_emac0 {
++ phy_id = "4a101000.mdio:00";
++};
++
++&cpsw_emac1 {
++ phy_id = "4a101000.mdio:01";
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 8d5f660..23d1e26 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -133,3 +133,11 @@
+ reg = <0>;
+ };
+ };
++
++&cpsw_emac0 {
++ phy_id = "4a101000.mdio:00";
++};
++
++&cpsw_emac1 {
++ phy_id = "4a101000.mdio:01";
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 063ecea..a6bfd9b 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -311,5 +311,55 @@
+ interrupt-parent = <&intc>;
+ interrupts = <91>;
+ };
++
++ mac: ethernet@4A100000 {
++ compatible = "ti,cpsw";
++ ti,hwmods = "cpgmac0";
++ cpdma_channels = <8>;
++ host_port_no = <0>;
++ cpdma_reg_ofs = <0x800>;
++ cpdma_sram_ofs = <0xa00>;
++ ale_reg_ofs = <0xd00>;
++ ale_entries = <1024>;
++ host_port_reg_ofs = <0x108>;
++ hw_stats_reg_ofs = <0x900>;
++ bd_ram_ofs = <0x2000>;
++ bd_ram_size = <0x2000>;
++ no_bd_ram = <0>;
++ rx_descs = <64>;
++ mac_control = <0x20>;
++ slaves = <2>;
++ reg = <0x4a100000 0x800
++ 0x4a101200 0x100
++ 0x4a101000 0x100>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ interrupt-parent = <&intc>;
++ /* c0_rx_thresh_pend c0_rx_pend c0_tx_pend c0_misc_pend*/
++ interrupts = <40 41 42 43>;
++ ranges;
++ cpsw_emac0: slave@0 {
++ slave_reg_ofs = <0x208>;
++ sliver_reg_ofs = <0xd80>;
++ /* Filled in by U-Boot */
++ mac-address = [ 00 00 00 00 00 00 ];
++ };
++ cpsw_emac1: slave@1 {
++ slave_reg_ofs = <0x308>;
++ sliver_reg_ofs = <0xdc0>;
++ /* Filled in by U-Boot */
++ mac-address = [ 00 00 00 00 00 00 ];
++ };
++
++ davinci_mdio: mdio@4a101000 {
++ compatible = "ti,davinci_mdio";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ ti,hwmods = "davinci_mdio";
++ bus_freq = <1000000>;
++ reg = <0x4a101000 0x100>;
++ };
++
++ };
+ };
+ };
diff --git a/patches/linux-3.7-rc6/0038-i2c-pinctrl-ify-i2c-omap.c.patch b/patches/linux-3.7-rc6/0038-i2c-pinctrl-ify-i2c-omap.c.patch
new file mode 100644
index 0000000..e936d15
--- /dev/null
+++ b/patches/linux-3.7-rc6/0038-i2c-pinctrl-ify-i2c-omap.c.patch
@@ -0,0 +1,46 @@
+From 610430c8c2229f0b70e7f52188ea7dc8c368a6d6 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Sep 2012 17:51:11 +0300
+Subject: [PATCH] i2c: pinctrl-ify i2c-omap.c
+
+Conflicts:
+ drivers/i2c/busses/i2c-omap.c
+---
+ drivers/i2c/busses/i2c-omap.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index db31eae..4c38aa0 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -44,6 +44,8 @@
+ #include <linux/i2c-omap.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/pm_qos.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ /* I2C controller revisions */
+ #define OMAP_I2C_OMAP1_REV_2 0x20
+@@ -1064,6 +1066,7 @@ omap_i2c_probe(struct platform_device *pdev)
+ const struct of_device_id *match;
+ int irq;
+ int r;
++ struct pinctrl *pinctrl;
+
+ /* NOTE: driver uses the static register mapping */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -1202,6 +1205,13 @@ omap_i2c_probe(struct platform_device *pdev)
+
+ of_i2c_register_devices(adap);
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(dev->dev, "unable to select pin group\n");
++
++ dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr,
++ dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
++
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put_autosuspend(dev->dev);
+
diff --git a/patches/linux-3.7-rc6/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch b/patches/linux-3.7-rc6/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
new file mode 100644
index 0000000..5b16009
--- /dev/null
+++ b/patches/linux-3.7-rc6/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
@@ -0,0 +1,70 @@
+From b76bec0181666391a0e7ad495a72865f1f35173d Mon Sep 17 00:00:00 2001
+From: "AnilKumar, Chimata" <anilkumar@ti.com>
+Date: Fri, 31 Aug 2012 09:29:18 +0000
+Subject: [PATCH] arm/dts: AM33XX: Configure pinmuxs for user leds control on
+ Bone
+
+Adds GPIO pinctrl nodes to am3358_pinmux master node to control
+user leds (USR0, USR1, USR2 and USR3) present on BeagleBone.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 38 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 47c17e8..3a089c0 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -38,6 +38,14 @@
+ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
+ >;
+ };
++ userled_pins: pinmux_userled_pins {
++ pinctrl-single,pins = <
++ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
++ 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
++ 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
++ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -45,6 +53,36 @@
+ status = "okay";
+ };
+
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&userled_pins>;
++
++ led0 {
++ label = "beaglebone:green:usr0";
++ gpios = <&gpio2 21 0>;
++ default-state = "off";
++ };
++
++ led1 {
++ label = "beaglebone:green:usr1";
++ gpios = <&gpio2 22 0>;
++ default-state = "off";
++ };
++
++ led2 {
++ label = "beaglebone:green:usr2";
++ gpios = <&gpio2 23 0>;
++ default-state = "off";
++ };
++
++ led3 {
++ label = "beaglebone:green:usr3";
++ gpios = <&gpio2 24 0>;
++ default-state = "off";
++ };
++ };
++
+ i2c1: i2c@44e0b000 {
+ status = "okay";
+ clock-frequency = <400000>;
diff --git a/patches/linux-3.7-rc6/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch b/patches/linux-3.7-rc6/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch
new file mode 100644
index 0000000..c901a64
--- /dev/null
+++ b/patches/linux-3.7-rc6/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch
@@ -0,0 +1,29 @@
+From 1d95712aeeea071a0090699bb863004e5fae01d3 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 5 Sep 2012 09:49:21 +0200
+Subject: [PATCH] beaglebone DT: set default triggers for LEDS
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 3a089c0..63acfb4 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -61,12 +61,14 @@
+ led0 {
+ label = "beaglebone:green:usr0";
+ gpios = <&gpio2 21 0>;
++ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ led1 {
+ label = "beaglebone:green:usr1";
+ gpios = <&gpio2 22 0>;
++ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+
diff --git a/patches/linux-3.7-rc6/0041-beaglebone-add-a-cpu-led-trigger.patch b/patches/linux-3.7-rc6/0041-beaglebone-add-a-cpu-led-trigger.patch
new file mode 100644
index 0000000..e30b5cd
--- /dev/null
+++ b/patches/linux-3.7-rc6/0041-beaglebone-add-a-cpu-led-trigger.patch
@@ -0,0 +1,22 @@
+From 1313bf938b17dca177b11f7317e8b1765c2008b0 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 15 Oct 2012 16:53:28 +0200
+Subject: [PATCH] beaglebone: add a cpu led trigger
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 63acfb4..147bc01 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -75,6 +75,7 @@
+ led2 {
+ label = "beaglebone:green:usr2";
+ gpios = <&gpio2 23 0>;
++ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+
diff --git a/patches/linux-3.7-rc6/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch b/patches/linux-3.7-rc6/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch
new file mode 100644
index 0000000..6977708
--- /dev/null
+++ b/patches/linux-3.7-rc6/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch
@@ -0,0 +1,79 @@
+From 6983ddebcd85a68ce206f513adea0edd80e22052 Mon Sep 17 00:00:00 2001
+From: "AnilKumar, Chimata" <anilkumar@ti.com>
+Date: Fri, 31 Aug 2012 09:37:20 +0000
+Subject: [PATCH] arm/dts: AM33XX: Add device tree OPP table
+
+Add DT OPP table for AM33XX family of devices. This data is
+decoded by OF with of_init_opp_table() helper function.
+
+Also adds cpu0 supply name to the corresponding dts files.
+cpu0-supply name is used by cpufreq-cpu0 driver to get the
+regulator pointer for voltage modifications.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 6 ++++++
+ arch/arm/boot/dts/am335x-evm.dts | 6 ++++++
+ arch/arm/boot/dts/am33xx.dtsi | 15 +++++++++++++++
+ 3 files changed, 27 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 147bc01..87686e9 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -13,6 +13,12 @@
+ model = "TI AM335x BeagleBone";
+ compatible = "ti,am335x-bone", "ti,am33xx";
+
++ cpus {
++ cpu@0 {
++ cpu0-supply = <&dcdc2_reg>;
++ };
++ };
++
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>; /* 256 MB */
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 23d1e26..43e23a8 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -13,6 +13,12 @@
+ model = "TI AM335x EVM";
+ compatible = "ti,am335x-evm", "ti,am33xx";
+
++ cpus {
++ cpu@0 {
++ cpu0-supply = <&vdd1_reg>;
++ };
++ };
++
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>; /* 256 MB */
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index a6bfd9b..9755276 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -25,6 +25,21 @@
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a8";
++
++ /*
++ * To consider voltage drop between PMIC and SoC,
++ * tolerance value is reduced to 2% from 4% and
++ * voltage value is increased as a precaution.
++ */
++ operating-points = <
++ /* kHz uV */
++ 720000 1285000
++ 600000 1225000
++ 500000 1125000
++ 275000 1125000
++ >;
++ voltage-tolerance = <2>; /* 2 percentage */
++ clock-latency = <300000>; /* From omap-cpufreq driver */
+ };
+ };
+
diff --git a/patches/linux-3.7-rc6/0045-input-TSC-ti_tscadc-Correct-register-usage.patch b/patches/linux-3.7-rc6/0045-input-TSC-ti_tscadc-Correct-register-usage.patch
new file mode 100644
index 0000000..5046ca3
--- /dev/null
+++ b/patches/linux-3.7-rc6/0045-input-TSC-ti_tscadc-Correct-register-usage.patch
@@ -0,0 +1,226 @@
+From 26a11407fe194a39a80f8a36964d23f03ef61f7e Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:38 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Correct register usage
+
+This patch cleans up the wrong register definitions
+and usage for touchscreen controller.
+Bit masks were not defined earlier.
+
+For ex: consider a register define as:
+write(xyz, ABC)
+ABC is expected to be written to register bits 0-11.
+Here we see that value written is as expected, but this write
+is also affecting all the remaining bits of xyz.
+The remaining bits hold the default value as 0 and the write
+also sets it to zero. Hence wrong usage were not causing user
+visible bugs.
+Due to these reasons it was difficult to follow when
+compared with TRM.
+
+Unused definitions are also removed.
+Since there is change in some naming convention because of
+all the above mentioned reasons, the same has been
+updated throughout the code.
+Bit declarations are grouped to increase readability.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 128 +++++++++++++++++++++------------
+ 1 file changed, 82 insertions(+), 46 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index d229c74..d198cab 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -52,43 +52,79 @@
+
+ /* Register Bitfields */
+ #define IRQWKUP_ENB BIT(0)
+-#define STPENB_STEPENB 0x7FFF
++
++/* Step Enable */
++#define STEPENB_MASK (0x1FFFF << 0)
++#define STEPENB(val) (val << 0)
++#define STPENB_STEPENB STEPENB(0x7FFF)
++
++/* IRQ enable */
+ #define IRQENB_FIFO1THRES BIT(5)
+ #define IRQENB_PENUP BIT(9)
+-#define STEPCONFIG_MODE_HWSYNC 0x2
+-#define STEPCONFIG_SAMPLES_AVG (1 << 4)
+-#define STEPCONFIG_XPP (1 << 5)
+-#define STEPCONFIG_XNN (1 << 6)
+-#define STEPCONFIG_YPP (1 << 7)
+-#define STEPCONFIG_YNN (1 << 8)
+-#define STEPCONFIG_XNP (1 << 9)
+-#define STEPCONFIG_YPN (1 << 10)
+-#define STEPCONFIG_INM (1 << 18)
+-#define STEPCONFIG_INP (1 << 20)
+-#define STEPCONFIG_INP_5 (1 << 21)
+-#define STEPCONFIG_FIFO1 (1 << 26)
+-#define STEPCONFIG_OPENDLY 0xff
+-#define STEPCONFIG_Z1 (3 << 19)
+-#define STEPIDLE_INP (1 << 22)
+-#define STEPCHARGE_RFP (1 << 12)
+-#define STEPCHARGE_INM (1 << 15)
+-#define STEPCHARGE_INP (1 << 19)
+-#define STEPCHARGE_RFM (1 << 23)
+-#define STEPCHARGE_DELAY 0x1
+-#define CNTRLREG_TSCSSENB (1 << 0)
+-#define CNTRLREG_STEPID (1 << 1)
+-#define CNTRLREG_STEPCONFIGWRT (1 << 2)
+-#define CNTRLREG_4WIRE (1 << 5)
+-#define CNTRLREG_5WIRE (1 << 6)
+-#define CNTRLREG_8WIRE (3 << 5)
+-#define CNTRLREG_TSCENB (1 << 7)
+-#define ADCFSM_STEPID 0x10
+
++/* Step Configuration */
++#define STEPCONFIG_MODE_MASK (3 << 0)
++#define STEPCONFIG_MODE(val) (val << 0)
++#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
++#define STEPCONFIG_AVG_MASK (7 << 2)
++#define STEPCONFIG_AVG(val) (val << 2)
++#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
++#define STEPCONFIG_XPP BIT(5)
++#define STEPCONFIG_XNN BIT(6)
++#define STEPCONFIG_YPP BIT(7)
++#define STEPCONFIG_YNN BIT(8)
++#define STEPCONFIG_XNP BIT(9)
++#define STEPCONFIG_YPN BIT(10)
++#define STEPCONFIG_INM_MASK (0xF << 15)
++#define STEPCONFIG_INM(val) (val << 15)
++#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
++#define STEPCONFIG_INP_MASK (0xF << 19)
++#define STEPCONFIG_INP(val) (val << 19)
++#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
++#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
++#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
++#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
++#define STEPCONFIG_FIFO1 BIT(26)
++
++/* Delay register */
++#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
++#define STEPDELAY_OPEN(val) (val << 0)
++#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
++
++/* Charge Config */
++#define STEPCHARGE_RFP_MASK (7 << 12)
++#define STEPCHARGE_RFP(val) (val << 12)
++#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
++#define STEPCHARGE_INM_MASK (0xF << 15)
++#define STEPCHARGE_INM(val) (val << 15)
++#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
++#define STEPCHARGE_INP_MASK (0xF << 19)
++#define STEPCHARGE_INP(val) (val << 19)
++#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
++#define STEPCHARGE_RFM_MASK (3 << 23)
++#define STEPCHARGE_RFM(val) (val << 23)
++#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
++
++/* Charge delay */
++#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
++#define CHARGEDLY_OPEN(val) (val << 0)
++#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
++
++/* Control register */
++#define CNTRLREG_TSCSSENB BIT(0)
++#define CNTRLREG_STEPID BIT(1)
++#define CNTRLREG_STEPCONFIGWRT BIT(2)
++#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
++#define CNTRLREG_AFE_CTRL(val) (val << 5)
++#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
++#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
++#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
++#define CNTRLREG_TSCENB BIT(7)
++
++#define ADCFSM_STEPID 0x10
+ #define SEQ_SETTLE 275
+ #define ADC_CLK 3000000
+ #define MAX_12BIT ((1 << 12) - 1)
+-#define TSCADC_DELTA_X 15
+-#define TSCADC_DELTA_Y 15
+
+ struct tscadc {
+ struct input_dev *input;
+@@ -119,18 +155,18 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ /* Configure the Step registers */
+
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP;
++ STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+ switch (ts_dev->wires) {
+ case 4:
+- config |= STEPCONFIG_INP | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+ break;
+ case 5:
+ config |= STEPCONFIG_YNN |
+- STEPCONFIG_INP_5 | STEPCONFIG_XNN |
++ STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+ STEPCONFIG_YPP;
+ break;
+ case 8:
+- config |= STEPCONFIG_INP | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+ break;
+ }
+
+@@ -141,14 +177,14 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+
+ config = 0;
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN |
+- STEPCONFIG_INM | STEPCONFIG_FIFO1;
++ STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
++ STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+ switch (ts_dev->wires) {
+ case 4:
+ config |= STEPCONFIG_YPP;
+ break;
+ case 5:
+- config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 |
++ config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
+ STEPCONFIG_XNP | STEPCONFIG_YPN;
+ break;
+ case 8:
+@@ -164,21 +200,21 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ config = 0;
+ /* Charge step configuration */
+ config = STEPCONFIG_XPP | STEPCONFIG_YNN |
+- STEPCHARGE_RFP | STEPCHARGE_RFM |
+- STEPCHARGE_INM | STEPCHARGE_INP;
++ STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
++ STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+
+ tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
+- tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY);
++ tscadc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+
+ config = 0;
+ /* Configure to calculate pressure */
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP |
+- STEPCONFIG_XNN | STEPCONFIG_INM;
++ STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
++ STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+ tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
+ tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
+
+- config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1;
++ config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+ tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
+ tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
+
+@@ -190,8 +226,8 @@ static void tscadc_idle_config(struct tscadc *ts_config)
+ unsigned int idleconfig;
+
+ idleconfig = STEPCONFIG_YNN |
+- STEPCONFIG_INM |
+- STEPCONFIG_YPN | STEPIDLE_INP;
++ STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
+ tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
+ }
+
diff --git a/patches/linux-3.7-rc6/0046-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch b/patches/linux-3.7-rc6/0046-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch
new file mode 100644
index 0000000..bf40198
--- /dev/null
+++ b/patches/linux-3.7-rc6/0046-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch
@@ -0,0 +1,138 @@
+From b932cb2194e4e7ffc21e5c19b56d2b018ef88f5a Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:39 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Add Step configuration as platform
+ data
+
+There are 16 programmable Step Configuration
+registers which are used by the sequencer.
+Program the Steps in order to configure a channel
+input to be sampled. If the same step is applied
+several times, the coordinate values read are more
+accurate.
+Hence we provide the user an option of how many steps
+should be configured.
+
+For ex: If this value is assigned as 4, This means that
+4 steps are applied to read x co-ordinate and 4 steps to read
+y co-ordinate. Furtheron the interrupt handler already
+holds code to use delta filter and report the best value
+out of these values to the input sub-system.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 25 +++++++++++++------------
+ include/linux/input/ti_tscadc.h | 6 ++++++
+ 2 files changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index d198cab..c1bd8e5 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -41,10 +41,6 @@
+ #define REG_CHARGEDELAY 0x060
+ #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+ #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+-#define REG_STEPCONFIG13 0x0C4
+-#define REG_STEPDELAY13 0x0C8
+-#define REG_STEPCONFIG14 0x0CC
+-#define REG_STEPDELAY14 0x0D0
+ #define REG_FIFO0CNT 0xE4
+ #define REG_FIFO1THR 0xF4
+ #define REG_FIFO0 0x100
+@@ -134,6 +130,7 @@ struct tscadc {
+ unsigned int wires;
+ unsigned int x_plate_resistance;
+ bool pen_down;
++ int steps_to_configure;
+ };
+
+ static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
+@@ -150,9 +147,10 @@ static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
+ static void tscadc_step_config(struct tscadc *ts_dev)
+ {
+ unsigned int config;
+- int i;
++ int i, total_steps;
+
+ /* Configure the Step registers */
++ total_steps = 2 * ts_dev->steps_to_configure;
+
+ config = STEPCONFIG_MODE_HWSYNC |
+ STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+@@ -170,7 +168,7 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ break;
+ }
+
+- for (i = 1; i < 7; i++) {
++ for (i = 1; i <= ts_dev->steps_to_configure; i++) {
+ tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+@@ -192,7 +190,7 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ break;
+ }
+
+- for (i = 7; i < 13; i++) {
++ for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
+ tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+@@ -211,12 +209,14 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ config = STEPCONFIG_MODE_HWSYNC |
+ STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+ STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+- tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
+- tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
++ tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
++ tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
++ STEPCONFIG_OPENDLY);
+
+ config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+- tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
+- tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
++ tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
++ tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
++ STEPCONFIG_OPENDLY);
+
+ tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+ }
+@@ -379,6 +379,7 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
+ ts_dev->irq = irq;
+ ts_dev->wires = pdata->wires;
+ ts_dev->x_plate_resistance = pdata->x_plate_resistance;
++ ts_dev->steps_to_configure = pdata->steps_to_configure;
+
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (!res) {
+@@ -447,7 +448,7 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
+ tscadc_idle_config(ts_dev);
+ tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+ tscadc_step_config(ts_dev);
+- tscadc_writel(ts_dev, REG_FIFO1THR, 6);
++ tscadc_writel(ts_dev, REG_FIFO1THR, ts_dev->steps_to_configure);
+
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(ts_dev, REG_CTRL, ctrl);
+diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
+index b10a527..ad442a3 100644
+--- a/include/linux/input/ti_tscadc.h
++++ b/include/linux/input/ti_tscadc.h
+@@ -7,11 +7,17 @@
+ * i.e. 4/5/8 wire touchscreen support
+ * on the platform.
+ * @x_plate_resistance: X plate resistance.
++ * @steps_to_configure: The sequencer supports a total of
++ * 16 programmable steps.
++ * A step configured to read a single
++ * co-ordinate value, can be applied
++ * more number of times for better results.
+ */
+
+ struct tsc_data {
+ int wires;
+ int x_plate_resistance;
++ int steps_to_configure;
+ };
+
+ #endif
diff --git a/patches/linux-3.7-rc6/0047-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch b/patches/linux-3.7-rc6/0047-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch
new file mode 100644
index 0000000..e61ea48
--- /dev/null
+++ b/patches/linux-3.7-rc6/0047-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch
@@ -0,0 +1,67 @@
+From ac7eef064eb1619eaf030e9f36e784230a8d7baa Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:40 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: set FIFO0 threshold Interrupt
+
+Code currently uses FIFO1 threshold interrupt.
+since this is a MFD, Dedicating FIFO0 to touchscreen
+and making way for other devices to use FIFO1 as well.
+The FIFO can be shared between 2 devices but since the
+interrupt used is threshold interrupt on FIFO1, we would
+end up having wrong interrupts. Hence changing the same.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index c1bd8e5..2cc19b0 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -42,6 +42,7 @@
+ #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+ #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+ #define REG_FIFO0CNT 0xE4
++#define REG_FIFO0THR 0xE8
+ #define REG_FIFO1THR 0xF4
+ #define REG_FIFO0 0x100
+ #define REG_FIFO1 0x200
+@@ -55,6 +56,7 @@
+ #define STPENB_STEPENB STEPENB(0x7FFF)
+
+ /* IRQ enable */
++#define IRQENB_FIFO0THRES BIT(2)
+ #define IRQENB_FIFO1THRES BIT(5)
+ #define IRQENB_PENUP BIT(9)
+
+@@ -277,7 +279,7 @@ static irqreturn_t tscadc_irq(int irq, void *dev)
+ unsigned int fsm;
+
+ status = tscadc_readl(ts_dev, REG_IRQSTATUS);
+- if (status & IRQENB_FIFO1THRES) {
++ if (status & IRQENB_FIFO0THRES) {
+ tscadc_read_coordinates(ts_dev, &x, &y);
+
+ z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
+@@ -303,7 +305,7 @@ static irqreturn_t tscadc_irq(int irq, void *dev)
+ input_sync(input_dev);
+ }
+ }
+- irqclr |= IRQENB_FIFO1THRES;
++ irqclr |= IRQENB_FIFO0THRES;
+ }
+
+ /*
+@@ -446,9 +448,9 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
+ tscadc_writel(ts_dev, REG_CTRL, ctrl);
+
+ tscadc_idle_config(ts_dev);
+- tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
++ tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+ tscadc_step_config(ts_dev);
+- tscadc_writel(ts_dev, REG_FIFO1THR, ts_dev->steps_to_configure);
++ tscadc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(ts_dev, REG_CTRL, ctrl);
diff --git a/patches/linux-3.7-rc6/0048-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch b/patches/linux-3.7-rc6/0048-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch
new file mode 100644
index 0000000..ab04b48
--- /dev/null
+++ b/patches/linux-3.7-rc6/0048-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch
@@ -0,0 +1,37 @@
+From e1c5c484bc32790c868f8de1300780b950d4514d Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:41 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Remove definition of End Of Interrupt
+ register
+
+The touchscreen IP uses level sensitive interrupts rather
+than edge sensitive interrupts and therefore the is no need
+to use the EOI register to have the module re-strobe the
+interrupt line if there pending interrupts exist.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index 2cc19b0..ec0a442 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -27,7 +27,6 @@
+ #include <linux/input/ti_tscadc.h>
+ #include <linux/delay.h>
+
+-#define REG_IRQEOI 0x020
+ #define REG_RAWIRQSTATUS 0x024
+ #define REG_IRQSTATUS 0x028
+ #define REG_IRQENABLE 0x02C
+@@ -330,8 +329,6 @@ static irqreturn_t tscadc_irq(int irq, void *dev)
+ }
+
+ tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+- /* check pending interrupts */
+- tscadc_writel(ts_dev, REG_IRQEOI, 0x0);
+
+ tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+ return IRQ_HANDLED;
diff --git a/patches/linux-3.7-rc6/0049-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch b/patches/linux-3.7-rc6/0049-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch
new file mode 100644
index 0000000..0b482cd
--- /dev/null
+++ b/patches/linux-3.7-rc6/0049-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch
@@ -0,0 +1,1174 @@
+From 0f0fedfede0d4c004f4612e4725b311b7bdcb061 Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:42 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Rename the existing touchscreen
+ driver
+
+Make way for addition of MFD driver.
+The existing touchsreen driver is a MFD client.
+For better readability we rename the file to
+indicate its functionality as only touchscreen.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/Kconfig | 4 +-
+ drivers/input/touchscreen/Makefile | 2 +-
+ drivers/input/touchscreen/ti_am335x_tsc.c | 522 +++++++++++++++++++++++++++++
+ drivers/input/touchscreen/ti_tscadc.c | 522 -----------------------------
+ include/linux/input/ti_am335x_tsc.h | 23 ++
+ include/linux/input/ti_tscadc.h | 23 --
+ 6 files changed, 548 insertions(+), 548 deletions(-)
+ create mode 100644 drivers/input/touchscreen/ti_am335x_tsc.c
+ delete mode 100644 drivers/input/touchscreen/ti_tscadc.c
+ create mode 100644 include/linux/input/ti_am335x_tsc.h
+ delete mode 100644 include/linux/input/ti_tscadc.h
+
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index f7668b2..d31dc5f 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -529,7 +529,7 @@ config TOUCHSCREEN_TOUCHWIN
+ To compile this driver as a module, choose M here: the
+ module will be called touchwin.
+
+-config TOUCHSCREEN_TI_TSCADC
++config TOUCHSCREEN_TI_AM335X_TSC
+ tristate "TI Touchscreen Interface"
+ depends on ARCH_OMAP2PLUS
+ help
+@@ -539,7 +539,7 @@ config TOUCHSCREEN_TI_TSCADC
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+- module will be called ti_tscadc.
++ module will be called ti_am335x_tsc.
+
+ config TOUCHSCREEN_ATMEL_TSADCC
+ tristate "Atmel Touchscreen Interface"
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 178eb12..7c4c78e 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -52,7 +52,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
+ obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
+-obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o
++obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
+ obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+new file mode 100644
+index 0000000..462950a
+--- /dev/null
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -0,0 +1,522 @@
++/*
++ * TI Touch Screen driver
++ *
++ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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 version 2.
++ *
++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
++ * kind, whether express or implied; without even the implied warranty
++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/input.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/delay.h>
++
++#define REG_RAWIRQSTATUS 0x024
++#define REG_IRQSTATUS 0x028
++#define REG_IRQENABLE 0x02C
++#define REG_IRQWAKEUP 0x034
++#define REG_CTRL 0x040
++#define REG_ADCFSM 0x044
++#define REG_CLKDIV 0x04C
++#define REG_SE 0x054
++#define REG_IDLECONFIG 0x058
++#define REG_CHARGECONFIG 0x05C
++#define REG_CHARGEDELAY 0x060
++#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
++#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
++#define REG_FIFO0CNT 0xE4
++#define REG_FIFO0THR 0xE8
++#define REG_FIFO1THR 0xF4
++#define REG_FIFO0 0x100
++#define REG_FIFO1 0x200
++
++/* Register Bitfields */
++#define IRQWKUP_ENB BIT(0)
++
++/* Step Enable */
++#define STEPENB_MASK (0x1FFFF << 0)
++#define STEPENB(val) (val << 0)
++#define STPENB_STEPENB STEPENB(0x7FFF)
++
++/* IRQ enable */
++#define IRQENB_FIFO0THRES BIT(2)
++#define IRQENB_FIFO1THRES BIT(5)
++#define IRQENB_PENUP BIT(9)
++
++/* Step Configuration */
++#define STEPCONFIG_MODE_MASK (3 << 0)
++#define STEPCONFIG_MODE(val) (val << 0)
++#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
++#define STEPCONFIG_AVG_MASK (7 << 2)
++#define STEPCONFIG_AVG(val) (val << 2)
++#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
++#define STEPCONFIG_XPP BIT(5)
++#define STEPCONFIG_XNN BIT(6)
++#define STEPCONFIG_YPP BIT(7)
++#define STEPCONFIG_YNN BIT(8)
++#define STEPCONFIG_XNP BIT(9)
++#define STEPCONFIG_YPN BIT(10)
++#define STEPCONFIG_INM_MASK (0xF << 15)
++#define STEPCONFIG_INM(val) (val << 15)
++#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
++#define STEPCONFIG_INP_MASK (0xF << 19)
++#define STEPCONFIG_INP(val) (val << 19)
++#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
++#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
++#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
++#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
++#define STEPCONFIG_FIFO1 BIT(26)
++
++/* Delay register */
++#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
++#define STEPDELAY_OPEN(val) (val << 0)
++#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
++
++/* Charge Config */
++#define STEPCHARGE_RFP_MASK (7 << 12)
++#define STEPCHARGE_RFP(val) (val << 12)
++#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
++#define STEPCHARGE_INM_MASK (0xF << 15)
++#define STEPCHARGE_INM(val) (val << 15)
++#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
++#define STEPCHARGE_INP_MASK (0xF << 19)
++#define STEPCHARGE_INP(val) (val << 19)
++#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
++#define STEPCHARGE_RFM_MASK (3 << 23)
++#define STEPCHARGE_RFM(val) (val << 23)
++#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
++
++/* Charge delay */
++#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
++#define CHARGEDLY_OPEN(val) (val << 0)
++#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
++
++/* Control register */
++#define CNTRLREG_TSCSSENB BIT(0)
++#define CNTRLREG_STEPID BIT(1)
++#define CNTRLREG_STEPCONFIGWRT BIT(2)
++#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
++#define CNTRLREG_AFE_CTRL(val) (val << 5)
++#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
++#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
++#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
++#define CNTRLREG_TSCENB BIT(7)
++
++#define ADCFSM_STEPID 0x10
++#define SEQ_SETTLE 275
++#define ADC_CLK 3000000
++#define MAX_12BIT ((1 << 12) - 1)
++
++struct titsc {
++ struct input_dev *input;
++ struct clk *tsc_ick;
++ void __iomem *tsc_base;
++ unsigned int irq;
++ unsigned int wires;
++ unsigned int x_plate_resistance;
++ bool pen_down;
++ int steps_to_configure;
++};
++
++static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
++{
++ return readl(ts->tsc_base + reg);
++}
++
++static void titsc_writel(struct titsc *tsc, unsigned int reg,
++ unsigned int val)
++{
++ writel(val, tsc->tsc_base + reg);
++}
++
++static void titsc_step_config(struct titsc *ts_dev)
++{
++ unsigned int config;
++ int i, total_steps;
++
++ /* Configure the Step registers */
++ total_steps = 2 * ts_dev->steps_to_configure;
++
++ config = STEPCONFIG_MODE_HWSYNC |
++ STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
++ switch (ts_dev->wires) {
++ case 4:
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ break;
++ case 5:
++ config |= STEPCONFIG_YNN |
++ STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
++ STEPCONFIG_YPP;
++ break;
++ case 8:
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ break;
++ }
++
++ for (i = 1; i <= ts_dev->steps_to_configure; i++) {
++ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
++ }
++
++ config = 0;
++ config = STEPCONFIG_MODE_HWSYNC |
++ STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
++ STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
++ switch (ts_dev->wires) {
++ case 4:
++ config |= STEPCONFIG_YPP;
++ break;
++ case 5:
++ config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
++ STEPCONFIG_XNP | STEPCONFIG_YPN;
++ break;
++ case 8:
++ config |= STEPCONFIG_YPP;
++ break;
++ }
++
++ for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
++ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
++ }
++
++ config = 0;
++ /* Charge step configuration */
++ config = STEPCONFIG_XPP | STEPCONFIG_YNN |
++ STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
++ STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
++
++ titsc_writel(ts_dev, REG_CHARGECONFIG, config);
++ titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
++
++ config = 0;
++ /* Configure to calculate pressure */
++ config = STEPCONFIG_MODE_HWSYNC |
++ STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
++ STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
++ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
++ STEPCONFIG_OPENDLY);
++
++ config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
++ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
++ STEPCONFIG_OPENDLY);
++
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
++}
++
++static void titsc_idle_config(struct titsc *ts_config)
++{
++ unsigned int idleconfig;
++
++ idleconfig = STEPCONFIG_YNN |
++ STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
++ titsc_writel(ts_config, REG_IDLECONFIG, idleconfig);
++}
++
++static void titsc_read_coordinates(struct titsc *ts_dev,
++ unsigned int *x, unsigned int *y)
++{
++ unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
++ unsigned int prev_val_x = ~0, prev_val_y = ~0;
++ unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
++ unsigned int read, diff;
++ unsigned int i;
++
++ /*
++ * Delta filter is used to remove large variations in sampled
++ * values from ADC. The filter tries to predict where the next
++ * coordinate could be. This is done by taking a previous
++ * coordinate and subtracting it form current one. Further the
++ * algorithm compares the difference with that of a present value,
++ * if true the value is reported to the sub system.
++ */
++ for (i = 0; i < fifocount - 1; i++) {
++ read = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
++ diff = abs(read - prev_val_x);
++ if (diff < prev_diff_x) {
++ prev_diff_x = diff;
++ *x = read;
++ }
++ prev_val_x = read;
++
++ read = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
++ diff = abs(read - prev_val_y);
++ if (diff < prev_diff_y) {
++ prev_diff_y = diff;
++ *y = read;
++ }
++ prev_val_y = read;
++ }
++}
++
++static irqreturn_t titsc_irq(int irq, void *dev)
++{
++ struct titsc *ts_dev = dev;
++ struct input_dev *input_dev = ts_dev->input;
++ unsigned int status, irqclr = 0;
++ unsigned int x = 0, y = 0;
++ unsigned int z1, z2, z;
++ unsigned int fsm;
++
++ status = titsc_readl(ts_dev, REG_IRQSTATUS);
++ if (status & IRQENB_FIFO0THRES) {
++ titsc_read_coordinates(ts_dev, &x, &y);
++
++ z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
++ z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
++
++ if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
++ /*
++ * Calculate pressure using formula
++ * Resistance(touch) = x plate resistance *
++ * x postion/4096 * ((z2 / z1) - 1)
++ */
++ z = z2 - z1;
++ z *= x;
++ z *= ts_dev->x_plate_resistance;
++ z /= z1;
++ z = (z + 2047) >> 12;
++
++ if (z <= MAX_12BIT) {
++ input_report_abs(input_dev, ABS_X, x);
++ input_report_abs(input_dev, ABS_Y, y);
++ input_report_abs(input_dev, ABS_PRESSURE, z);
++ input_report_key(input_dev, BTN_TOUCH, 1);
++ input_sync(input_dev);
++ }
++ }
++ irqclr |= IRQENB_FIFO0THRES;
++ }
++
++ /*
++ * Time for sequencer to settle, to read
++ * correct state of the sequencer.
++ */
++ udelay(SEQ_SETTLE);
++
++ status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
++ if (status & IRQENB_PENUP) {
++ /* Pen up event */
++ fsm = titsc_readl(ts_dev, REG_ADCFSM);
++ if (fsm == ADCFSM_STEPID) {
++ ts_dev->pen_down = false;
++ input_report_key(input_dev, BTN_TOUCH, 0);
++ input_report_abs(input_dev, ABS_PRESSURE, 0);
++ input_sync(input_dev);
++ } else {
++ ts_dev->pen_down = true;
++ }
++ irqclr |= IRQENB_PENUP;
++ }
++
++ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
++
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
++ return IRQ_HANDLED;
++}
++
++/*
++ * The functions for inserting/removing driver as a module.
++ */
++
++static int __devinit titsc_probe(struct platform_device *pdev)
++{
++ const struct tsc_data *pdata = pdev->dev.platform_data;
++ struct resource *res;
++ struct titsc *ts_dev;
++ struct input_dev *input_dev;
++ struct clk *clk;
++ int err;
++ int clk_value, ctrl, irq;
++
++ if (!pdata) {
++ dev_err(&pdev->dev, "missing platform data.\n");
++ return -EINVAL;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource defined.\n");
++ return -EINVAL;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "no irq ID is specified.\n");
++ return -EINVAL;
++ }
++
++ /* Allocate memory for device */
++ ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!ts_dev || !input_dev) {
++ dev_err(&pdev->dev, "failed to allocate memory.\n");
++ err = -ENOMEM;
++ goto err_free_mem;
++ }
++
++ ts_dev->input = input_dev;
++ ts_dev->irq = irq;
++ ts_dev->wires = pdata->wires;
++ ts_dev->x_plate_resistance = pdata->x_plate_resistance;
++ ts_dev->steps_to_configure = pdata->steps_to_configure;
++
++ res = request_mem_region(res->start, resource_size(res), pdev->name);
++ if (!res) {
++ dev_err(&pdev->dev, "failed to reserve registers.\n");
++ err = -EBUSY;
++ goto err_free_mem;
++ }
++
++ ts_dev->tsc_base = ioremap(res->start, resource_size(res));
++ if (!ts_dev->tsc_base) {
++ dev_err(&pdev->dev, "failed to map registers.\n");
++ err = -ENOMEM;
++ goto err_release_mem_region;
++ }
++
++ err = request_irq(ts_dev->irq, titsc_irq,
++ 0, pdev->dev.driver->name, ts_dev);
++ if (err) {
++ dev_err(&pdev->dev, "failed to allocate irq.\n");
++ goto err_unmap_regs;
++ }
++
++ ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
++ if (IS_ERR(ts_dev->tsc_ick)) {
++ dev_err(&pdev->dev, "failed to get TSC ick\n");
++ goto err_free_irq;
++ }
++ clk_enable(ts_dev->tsc_ick);
++
++ clk = clk_get(&pdev->dev, "adc_tsc_fck");
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "failed to get TSC fck\n");
++ err = PTR_ERR(clk);
++ goto err_disable_clk;
++ }
++
++ clk_value = clk_get_rate(clk) / ADC_CLK;
++ clk_put(clk);
++
++ if (clk_value < 7) {
++ dev_err(&pdev->dev, "clock input less than min clock requirement\n");
++ goto err_disable_clk;
++ }
++ /* CLKDIV needs to be configured to the value minus 1 */
++ titsc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
++
++ /* Enable wake-up of the SoC using touchscreen */
++ titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
++
++ ctrl = CNTRLREG_STEPCONFIGWRT |
++ CNTRLREG_TSCENB |
++ CNTRLREG_STEPID;
++ switch (ts_dev->wires) {
++ case 4:
++ ctrl |= CNTRLREG_4WIRE;
++ break;
++ case 5:
++ ctrl |= CNTRLREG_5WIRE;
++ break;
++ case 8:
++ ctrl |= CNTRLREG_8WIRE;
++ break;
++ }
++ titsc_writel(ts_dev, REG_CTRL, ctrl);
++
++ titsc_idle_config(ts_dev);
++ titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
++ titsc_step_config(ts_dev);
++ titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
++
++ ctrl |= CNTRLREG_TSCSSENB;
++ titsc_writel(ts_dev, REG_CTRL, ctrl);
++
++ input_dev->name = "ti-tsc-adc";
++ input_dev->dev.parent = &pdev->dev;
++
++ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
++ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
++
++ input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
++ input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
++ input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
++
++ /* register to the input system */
++ err = input_register_device(input_dev);
++ if (err)
++ goto err_disable_clk;
++
++ platform_set_drvdata(pdev, ts_dev);
++ return 0;
++
++err_disable_clk:
++ clk_disable(ts_dev->tsc_ick);
++ clk_put(ts_dev->tsc_ick);
++err_free_irq:
++ free_irq(ts_dev->irq, ts_dev);
++err_unmap_regs:
++ iounmap(ts_dev->tsc_base);
++err_release_mem_region:
++ release_mem_region(res->start, resource_size(res));
++err_free_mem:
++ input_free_device(input_dev);
++ kfree(ts_dev);
++ return err;
++}
++
++static int __devexit titsc_remove(struct platform_device *pdev)
++{
++ struct titsc *ts_dev = platform_get_drvdata(pdev);
++ struct resource *res;
++
++ free_irq(ts_dev->irq, ts_dev);
++
++ input_unregister_device(ts_dev->input);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ iounmap(ts_dev->tsc_base);
++ release_mem_region(res->start, resource_size(res));
++
++ clk_disable(ts_dev->tsc_ick);
++ clk_put(ts_dev->tsc_ick);
++
++ kfree(ts_dev);
++
++ platform_set_drvdata(pdev, NULL);
++ return 0;
++}
++
++static struct platform_driver ti_tsc_driver = {
++ .probe = titsc_probe,
++ .remove = __devexit_p(titsc_remove),
++ .driver = {
++ .name = "tsc",
++ .owner = THIS_MODULE,
++ },
++};
++module_platform_driver(ti_tsc_driver);
++
++MODULE_DESCRIPTION("TI touchscreen controller driver");
++MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+deleted file mode 100644
+index ec0a442..0000000
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ /dev/null
+@@ -1,522 +0,0 @@
+-/*
+- * TI Touch Screen driver
+- *
+- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.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 version 2.
+- *
+- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+- * kind, whether express or implied; without even the implied warranty
+- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- */
+-
+-
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/err.h>
+-#include <linux/module.h>
+-#include <linux/input.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/clk.h>
+-#include <linux/platform_device.h>
+-#include <linux/io.h>
+-#include <linux/input/ti_tscadc.h>
+-#include <linux/delay.h>
+-
+-#define REG_RAWIRQSTATUS 0x024
+-#define REG_IRQSTATUS 0x028
+-#define REG_IRQENABLE 0x02C
+-#define REG_IRQWAKEUP 0x034
+-#define REG_CTRL 0x040
+-#define REG_ADCFSM 0x044
+-#define REG_CLKDIV 0x04C
+-#define REG_SE 0x054
+-#define REG_IDLECONFIG 0x058
+-#define REG_CHARGECONFIG 0x05C
+-#define REG_CHARGEDELAY 0x060
+-#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+-#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+-#define REG_FIFO0CNT 0xE4
+-#define REG_FIFO0THR 0xE8
+-#define REG_FIFO1THR 0xF4
+-#define REG_FIFO0 0x100
+-#define REG_FIFO1 0x200
+-
+-/* Register Bitfields */
+-#define IRQWKUP_ENB BIT(0)
+-
+-/* Step Enable */
+-#define STEPENB_MASK (0x1FFFF << 0)
+-#define STEPENB(val) (val << 0)
+-#define STPENB_STEPENB STEPENB(0x7FFF)
+-
+-/* IRQ enable */
+-#define IRQENB_FIFO0THRES BIT(2)
+-#define IRQENB_FIFO1THRES BIT(5)
+-#define IRQENB_PENUP BIT(9)
+-
+-/* Step Configuration */
+-#define STEPCONFIG_MODE_MASK (3 << 0)
+-#define STEPCONFIG_MODE(val) (val << 0)
+-#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
+-#define STEPCONFIG_AVG_MASK (7 << 2)
+-#define STEPCONFIG_AVG(val) (val << 2)
+-#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
+-#define STEPCONFIG_XPP BIT(5)
+-#define STEPCONFIG_XNN BIT(6)
+-#define STEPCONFIG_YPP BIT(7)
+-#define STEPCONFIG_YNN BIT(8)
+-#define STEPCONFIG_XNP BIT(9)
+-#define STEPCONFIG_YPN BIT(10)
+-#define STEPCONFIG_INM_MASK (0xF << 15)
+-#define STEPCONFIG_INM(val) (val << 15)
+-#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
+-#define STEPCONFIG_INP_MASK (0xF << 19)
+-#define STEPCONFIG_INP(val) (val << 19)
+-#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
+-#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
+-#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
+-#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
+-#define STEPCONFIG_FIFO1 BIT(26)
+-
+-/* Delay register */
+-#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
+-#define STEPDELAY_OPEN(val) (val << 0)
+-#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
+-
+-/* Charge Config */
+-#define STEPCHARGE_RFP_MASK (7 << 12)
+-#define STEPCHARGE_RFP(val) (val << 12)
+-#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
+-#define STEPCHARGE_INM_MASK (0xF << 15)
+-#define STEPCHARGE_INM(val) (val << 15)
+-#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
+-#define STEPCHARGE_INP_MASK (0xF << 19)
+-#define STEPCHARGE_INP(val) (val << 19)
+-#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
+-#define STEPCHARGE_RFM_MASK (3 << 23)
+-#define STEPCHARGE_RFM(val) (val << 23)
+-#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
+-
+-/* Charge delay */
+-#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
+-#define CHARGEDLY_OPEN(val) (val << 0)
+-#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
+-
+-/* Control register */
+-#define CNTRLREG_TSCSSENB BIT(0)
+-#define CNTRLREG_STEPID BIT(1)
+-#define CNTRLREG_STEPCONFIGWRT BIT(2)
+-#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
+-#define CNTRLREG_AFE_CTRL(val) (val << 5)
+-#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
+-#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
+-#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
+-#define CNTRLREG_TSCENB BIT(7)
+-
+-#define ADCFSM_STEPID 0x10
+-#define SEQ_SETTLE 275
+-#define ADC_CLK 3000000
+-#define MAX_12BIT ((1 << 12) - 1)
+-
+-struct tscadc {
+- struct input_dev *input;
+- struct clk *tsc_ick;
+- void __iomem *tsc_base;
+- unsigned int irq;
+- unsigned int wires;
+- unsigned int x_plate_resistance;
+- bool pen_down;
+- int steps_to_configure;
+-};
+-
+-static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
+-{
+- return readl(ts->tsc_base + reg);
+-}
+-
+-static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
+- unsigned int val)
+-{
+- writel(val, tsc->tsc_base + reg);
+-}
+-
+-static void tscadc_step_config(struct tscadc *ts_dev)
+-{
+- unsigned int config;
+- int i, total_steps;
+-
+- /* Configure the Step registers */
+- total_steps = 2 * ts_dev->steps_to_configure;
+-
+- config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+- switch (ts_dev->wires) {
+- case 4:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+- break;
+- case 5:
+- config |= STEPCONFIG_YNN |
+- STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+- STEPCONFIG_YPP;
+- break;
+- case 8:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+- break;
+- }
+-
+- for (i = 1; i <= ts_dev->steps_to_configure; i++) {
+- tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+- }
+-
+- config = 0;
+- config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
+- STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+- switch (ts_dev->wires) {
+- case 4:
+- config |= STEPCONFIG_YPP;
+- break;
+- case 5:
+- config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
+- STEPCONFIG_XNP | STEPCONFIG_YPN;
+- break;
+- case 8:
+- config |= STEPCONFIG_YPP;
+- break;
+- }
+-
+- for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
+- tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+- }
+-
+- config = 0;
+- /* Charge step configuration */
+- config = STEPCONFIG_XPP | STEPCONFIG_YNN |
+- STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
+- STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+-
+- tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
+- tscadc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+-
+- config = 0;
+- /* Configure to calculate pressure */
+- config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+- STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+- tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
+- STEPCONFIG_OPENDLY);
+-
+- config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+- tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+- STEPCONFIG_OPENDLY);
+-
+- tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+-}
+-
+-static void tscadc_idle_config(struct tscadc *ts_config)
+-{
+- unsigned int idleconfig;
+-
+- idleconfig = STEPCONFIG_YNN |
+- STEPCONFIG_INM_ADCREFM |
+- STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
+- tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
+-}
+-
+-static void tscadc_read_coordinates(struct tscadc *ts_dev,
+- unsigned int *x, unsigned int *y)
+-{
+- unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT);
+- unsigned int prev_val_x = ~0, prev_val_y = ~0;
+- unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
+- unsigned int read, diff;
+- unsigned int i;
+-
+- /*
+- * Delta filter is used to remove large variations in sampled
+- * values from ADC. The filter tries to predict where the next
+- * coordinate could be. This is done by taking a previous
+- * coordinate and subtracting it form current one. Further the
+- * algorithm compares the difference with that of a present value,
+- * if true the value is reported to the sub system.
+- */
+- for (i = 0; i < fifocount - 1; i++) {
+- read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
+- diff = abs(read - prev_val_x);
+- if (diff < prev_diff_x) {
+- prev_diff_x = diff;
+- *x = read;
+- }
+- prev_val_x = read;
+-
+- read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
+- diff = abs(read - prev_val_y);
+- if (diff < prev_diff_y) {
+- prev_diff_y = diff;
+- *y = read;
+- }
+- prev_val_y = read;
+- }
+-}
+-
+-static irqreturn_t tscadc_irq(int irq, void *dev)
+-{
+- struct tscadc *ts_dev = dev;
+- struct input_dev *input_dev = ts_dev->input;
+- unsigned int status, irqclr = 0;
+- unsigned int x = 0, y = 0;
+- unsigned int z1, z2, z;
+- unsigned int fsm;
+-
+- status = tscadc_readl(ts_dev, REG_IRQSTATUS);
+- if (status & IRQENB_FIFO0THRES) {
+- tscadc_read_coordinates(ts_dev, &x, &y);
+-
+- z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
+- z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
+-
+- if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
+- /*
+- * Calculate pressure using formula
+- * Resistance(touch) = x plate resistance *
+- * x postion/4096 * ((z2 / z1) - 1)
+- */
+- z = z2 - z1;
+- z *= x;
+- z *= ts_dev->x_plate_resistance;
+- z /= z1;
+- z = (z + 2047) >> 12;
+-
+- if (z <= MAX_12BIT) {
+- input_report_abs(input_dev, ABS_X, x);
+- input_report_abs(input_dev, ABS_Y, y);
+- input_report_abs(input_dev, ABS_PRESSURE, z);
+- input_report_key(input_dev, BTN_TOUCH, 1);
+- input_sync(input_dev);
+- }
+- }
+- irqclr |= IRQENB_FIFO0THRES;
+- }
+-
+- /*
+- * Time for sequencer to settle, to read
+- * correct state of the sequencer.
+- */
+- udelay(SEQ_SETTLE);
+-
+- status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS);
+- if (status & IRQENB_PENUP) {
+- /* Pen up event */
+- fsm = tscadc_readl(ts_dev, REG_ADCFSM);
+- if (fsm == ADCFSM_STEPID) {
+- ts_dev->pen_down = false;
+- input_report_key(input_dev, BTN_TOUCH, 0);
+- input_report_abs(input_dev, ABS_PRESSURE, 0);
+- input_sync(input_dev);
+- } else {
+- ts_dev->pen_down = true;
+- }
+- irqclr |= IRQENB_PENUP;
+- }
+-
+- tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+-
+- tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+- return IRQ_HANDLED;
+-}
+-
+-/*
+- * The functions for inserting/removing driver as a module.
+- */
+-
+-static int __devinit tscadc_probe(struct platform_device *pdev)
+-{
+- const struct tsc_data *pdata = pdev->dev.platform_data;
+- struct resource *res;
+- struct tscadc *ts_dev;
+- struct input_dev *input_dev;
+- struct clk *clk;
+- int err;
+- int clk_value, ctrl, irq;
+-
+- if (!pdata) {
+- dev_err(&pdev->dev, "missing platform data.\n");
+- return -EINVAL;
+- }
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- dev_err(&pdev->dev, "no memory resource defined.\n");
+- return -EINVAL;
+- }
+-
+- irq = platform_get_irq(pdev, 0);
+- if (irq < 0) {
+- dev_err(&pdev->dev, "no irq ID is specified.\n");
+- return -EINVAL;
+- }
+-
+- /* Allocate memory for device */
+- ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL);
+- input_dev = input_allocate_device();
+- if (!ts_dev || !input_dev) {
+- dev_err(&pdev->dev, "failed to allocate memory.\n");
+- err = -ENOMEM;
+- goto err_free_mem;
+- }
+-
+- ts_dev->input = input_dev;
+- ts_dev->irq = irq;
+- ts_dev->wires = pdata->wires;
+- ts_dev->x_plate_resistance = pdata->x_plate_resistance;
+- ts_dev->steps_to_configure = pdata->steps_to_configure;
+-
+- res = request_mem_region(res->start, resource_size(res), pdev->name);
+- if (!res) {
+- dev_err(&pdev->dev, "failed to reserve registers.\n");
+- err = -EBUSY;
+- goto err_free_mem;
+- }
+-
+- ts_dev->tsc_base = ioremap(res->start, resource_size(res));
+- if (!ts_dev->tsc_base) {
+- dev_err(&pdev->dev, "failed to map registers.\n");
+- err = -ENOMEM;
+- goto err_release_mem_region;
+- }
+-
+- err = request_irq(ts_dev->irq, tscadc_irq,
+- 0, pdev->dev.driver->name, ts_dev);
+- if (err) {
+- dev_err(&pdev->dev, "failed to allocate irq.\n");
+- goto err_unmap_regs;
+- }
+-
+- ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
+- if (IS_ERR(ts_dev->tsc_ick)) {
+- dev_err(&pdev->dev, "failed to get TSC ick\n");
+- goto err_free_irq;
+- }
+- clk_enable(ts_dev->tsc_ick);
+-
+- clk = clk_get(&pdev->dev, "adc_tsc_fck");
+- if (IS_ERR(clk)) {
+- dev_err(&pdev->dev, "failed to get TSC fck\n");
+- err = PTR_ERR(clk);
+- goto err_disable_clk;
+- }
+-
+- clk_value = clk_get_rate(clk) / ADC_CLK;
+- clk_put(clk);
+-
+- if (clk_value < 7) {
+- dev_err(&pdev->dev, "clock input less than min clock requirement\n");
+- goto err_disable_clk;
+- }
+- /* CLKDIV needs to be configured to the value minus 1 */
+- tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
+-
+- /* Enable wake-up of the SoC using touchscreen */
+- tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
+-
+- ctrl = CNTRLREG_STEPCONFIGWRT |
+- CNTRLREG_TSCENB |
+- CNTRLREG_STEPID;
+- switch (ts_dev->wires) {
+- case 4:
+- ctrl |= CNTRLREG_4WIRE;
+- break;
+- case 5:
+- ctrl |= CNTRLREG_5WIRE;
+- break;
+- case 8:
+- ctrl |= CNTRLREG_8WIRE;
+- break;
+- }
+- tscadc_writel(ts_dev, REG_CTRL, ctrl);
+-
+- tscadc_idle_config(ts_dev);
+- tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+- tscadc_step_config(ts_dev);
+- tscadc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+-
+- ctrl |= CNTRLREG_TSCSSENB;
+- tscadc_writel(ts_dev, REG_CTRL, ctrl);
+-
+- input_dev->name = "ti-tsc-adc";
+- input_dev->dev.parent = &pdev->dev;
+-
+- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+-
+- input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
+- input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
+- input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
+-
+- /* register to the input system */
+- err = input_register_device(input_dev);
+- if (err)
+- goto err_disable_clk;
+-
+- platform_set_drvdata(pdev, ts_dev);
+- return 0;
+-
+-err_disable_clk:
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
+-err_free_irq:
+- free_irq(ts_dev->irq, ts_dev);
+-err_unmap_regs:
+- iounmap(ts_dev->tsc_base);
+-err_release_mem_region:
+- release_mem_region(res->start, resource_size(res));
+-err_free_mem:
+- input_free_device(input_dev);
+- kfree(ts_dev);
+- return err;
+-}
+-
+-static int __devexit tscadc_remove(struct platform_device *pdev)
+-{
+- struct tscadc *ts_dev = platform_get_drvdata(pdev);
+- struct resource *res;
+-
+- free_irq(ts_dev->irq, ts_dev);
+-
+- input_unregister_device(ts_dev->input);
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- iounmap(ts_dev->tsc_base);
+- release_mem_region(res->start, resource_size(res));
+-
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
+-
+- kfree(ts_dev);
+-
+- platform_set_drvdata(pdev, NULL);
+- return 0;
+-}
+-
+-static struct platform_driver ti_tsc_driver = {
+- .probe = tscadc_probe,
+- .remove = __devexit_p(tscadc_remove),
+- .driver = {
+- .name = "tsc",
+- .owner = THIS_MODULE,
+- },
+-};
+-module_platform_driver(ti_tsc_driver);
+-
+-MODULE_DESCRIPTION("TI touchscreen controller driver");
+-MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
+-MODULE_LICENSE("GPL");
+diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
+new file mode 100644
+index 0000000..49269a2
+--- /dev/null
++++ b/include/linux/input/ti_am335x_tsc.h
+@@ -0,0 +1,23 @@
++#ifndef __LINUX_TI_AM335X_TSC_H
++#define __LINUX_TI_AM335X_TSC_H
++
++/**
++ * struct tsc_data Touchscreen wire configuration
++ * @wires: Wires refer to application modes
++ * i.e. 4/5/8 wire touchscreen support
++ * on the platform.
++ * @x_plate_resistance: X plate resistance.
++ * @steps_to_configure: The sequencer supports a total of
++ * 16 programmable steps.
++ * A step configured to read a single
++ * co-ordinate value, can be applied
++ * more number of times for better results.
++ */
++
++struct tsc_data {
++ int wires;
++ int x_plate_resistance;
++ int steps_to_configure;
++};
++
++#endif
+diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
+deleted file mode 100644
+index ad442a3..0000000
+--- a/include/linux/input/ti_tscadc.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-#ifndef __LINUX_TI_TSCADC_H
+-#define __LINUX_TI_TSCADC_H
+-
+-/**
+- * struct tsc_data Touchscreen wire configuration
+- * @wires: Wires refer to application modes
+- * i.e. 4/5/8 wire touchscreen support
+- * on the platform.
+- * @x_plate_resistance: X plate resistance.
+- * @steps_to_configure: The sequencer supports a total of
+- * 16 programmable steps.
+- * A step configured to read a single
+- * co-ordinate value, can be applied
+- * more number of times for better results.
+- */
+-
+-struct tsc_data {
+- int wires;
+- int x_plate_resistance;
+- int steps_to_configure;
+-};
+-
+-#endif
diff --git a/patches/linux-3.7-rc6/0050-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch b/patches/linux-3.7-rc6/0050-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch
new file mode 100644
index 0000000..7bade04
--- /dev/null
+++ b/patches/linux-3.7-rc6/0050-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch
@@ -0,0 +1,453 @@
+From f0239cfc7dffbfe1409dfb670899cb188ed257a1 Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:43 +0000
+Subject: [PATCH] MFD: ti_tscadc: Add support for TI's TSC/ADC MFDevice
+
+Add the mfd core driver which supports touchscreen
+and ADC.
+With this patch we are only adding infrastructure to
+support the MFD clients.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/mfd/Kconfig | 11 ++
+ drivers/mfd/Makefile | 1 +
+ drivers/mfd/ti_am335x_tscadc.c | 250 ++++++++++++++++++++++++++++++++++
+ include/linux/mfd/ti_am335x_tscadc.h | 137 +++++++++++++++++++
+ 4 files changed, 399 insertions(+)
+ create mode 100644 drivers/mfd/ti_am335x_tscadc.c
+ create mode 100644 include/linux/mfd/ti_am335x_tscadc.h
+
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index acab3ef..9bba7f7 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -94,6 +94,17 @@ config MFD_TI_SSP
+ To compile this driver as a module, choose M here: the
+ module will be called ti-ssp.
+
++config MFD_TI_AM335X_TSCADC
++ tristate "TI ADC / Touch Screen chip support"
++ select MFD_CORE
++ select REGMAP
++ select REGMAP_MMIO
++ help
++ If you say yes here you get support for Texas Instruments series
++ of Touch Screen /ADC chips.
++ To compile this driver as a module, choose M here: the
++ module will be called ti_am335x_tscadc.
++
+ config HTC_EGPIO
+ bool "HTC EGPIO support"
+ depends on GENERIC_HARDIRQS && GPIOLIB && ARM
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index d8ccb63..442c17e 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -16,6 +16,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
+ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
+ obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
+ obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o
++obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o
+
+ obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o
+ obj-$(CONFIG_MFD_STMPE) += stmpe.o
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+new file mode 100644
+index 0000000..14df67b
+--- /dev/null
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -0,0 +1,250 @@
++/*
++ * TI Touch Screen / ADC MFD driver
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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 version 2.
++ *
++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
++ * kind, whether express or implied; without even the implied warranty
++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/regmap.h>
++#include <linux/mfd/core.h>
++#include <linux/pm_runtime.h>
++
++#include <linux/mfd/ti_am335x_tscadc.h>
++
++static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
++{
++ unsigned int val;
++
++ regmap_read(tsadc->regmap_tscadc, reg, &val);
++ return val;
++}
++
++static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg,
++ unsigned int val)
++{
++ regmap_write(tsadc->regmap_tscadc, reg, val);
++}
++
++static const struct regmap_config tscadc_regmap_config = {
++ .name = "ti_tscadc",
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++};
++
++static void tscadc_idle_config(struct ti_tscadc_dev *config)
++{
++ unsigned int idleconfig;
++
++ idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN;
++
++ tscadc_writel(config, REG_IDLECONFIG, idleconfig);
++}
++
++static int __devinit ti_tscadc_probe(struct platform_device *pdev)
++{
++ struct ti_tscadc_dev *tscadc;
++ struct resource *res;
++ struct clk *clk;
++ struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
++ int irq;
++ int err, ctrl;
++ int clk_value, clock_rate;
++
++ if (!pdata) {
++ dev_err(&pdev->dev, "Could not find platform data\n");
++ return -EINVAL;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource defined.\n");
++ return -EINVAL;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "no irq ID is specified.\n");
++ return -EINVAL;
++ }
++
++ /* Allocate memory for device */
++ tscadc = devm_kzalloc(&pdev->dev,
++ sizeof(struct ti_tscadc_dev), GFP_KERNEL);
++ if (!tscadc) {
++ dev_err(&pdev->dev, "failed to allocate memory.\n");
++ return -ENOMEM;
++ }
++ tscadc->dev = &pdev->dev;
++ tscadc->irq = irq;
++
++ res = devm_request_mem_region(&pdev->dev,
++ res->start, resource_size(res), pdev->name);
++ if (!res) {
++ dev_err(&pdev->dev, "failed to reserve registers.\n");
++ err = -EBUSY;
++ goto err;
++ }
++
++ tscadc->tscadc_base = devm_ioremap(&pdev->dev,
++ res->start, resource_size(res));
++ if (!tscadc->tscadc_base) {
++ dev_err(&pdev->dev, "failed to map registers.\n");
++ err = -ENOMEM;
++ goto err;
++ }
++
++ tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
++ tscadc->tscadc_base, &tscadc_regmap_config);
++ if (IS_ERR(tscadc->regmap_tscadc)) {
++ dev_err(&pdev->dev, "regmap init failed\n");
++ err = PTR_ERR(tscadc->regmap_tscadc);
++ goto err;
++ }
++
++ pm_runtime_enable(&pdev->dev);
++ pm_runtime_get_sync(&pdev->dev);
++
++ /*
++ * The TSC_ADC_Subsystem has 2 clock domains
++ * OCP_CLK and ADC_CLK.
++ * The ADC clock is expected to run at target of 3MHz,
++ * and expected to capture 12-bit data at a rate of 200 KSPS.
++ * The TSC_ADC_SS controller design assumes the OCP clock is
++ * at least 6x faster than the ADC clock.
++ */
++ clk = clk_get(&pdev->dev, "adc_tsc_fck");
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "failed to get TSC fck\n");
++ err = PTR_ERR(clk);
++ goto err_disable_clk;
++ }
++ clock_rate = clk_get_rate(clk);
++ clk_put(clk);
++ clk_value = clock_rate / ADC_CLK;
++ if (clk_value < MAX_CLK_DIV) {
++ dev_err(&pdev->dev, "clock input less than min clock requirement\n");
++ err = -EINVAL;
++ goto err_disable_clk;
++ }
++ /* TSCADC_CLKDIV needs to be configured to the value minus 1 */
++ clk_value = clk_value - 1;
++ tscadc_writel(tscadc, REG_CLKDIV, clk_value);
++
++ /* Set the control register bits */
++ ctrl = CNTRLREG_STEPCONFIGWRT |
++ CNTRLREG_TSCENB |
++ CNTRLREG_STEPID |
++ CNTRLREG_4WIRE;
++ tscadc_writel(tscadc, REG_CTRL, ctrl);
++
++ /* Set register bits for Idle Config Mode */
++ tscadc_idle_config(tscadc);
++
++ /* Enable the TSC module enable bit */
++ ctrl = tscadc_readl(tscadc, REG_CTRL);
++ ctrl |= CNTRLREG_TSCSSENB;
++ tscadc_writel(tscadc, REG_CTRL, ctrl);
++
++ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
++ TSCADC_CELLS, NULL, 0, NULL);
++ if (err < 0)
++ goto err_disable_clk;
++
++ device_init_wakeup(&pdev->dev, true);
++ platform_set_drvdata(pdev, tscadc);
++
++ return 0;
++
++err_disable_clk:
++ pm_runtime_put_sync(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++err:
++ return err;
++}
++
++static int __devexit ti_tscadc_remove(struct platform_device *pdev)
++{
++ struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev);
++
++ tscadc_writel(tscadc, REG_SE, 0x00);
++
++ pm_runtime_put_sync(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++
++ mfd_remove_devices(tscadc->dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int tscadc_suspend(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev);
++
++ tscadc_writel(tscadc_dev, REG_SE, 0x00);
++ pm_runtime_put_sync(dev);
++
++ return 0;
++}
++
++static int tscadc_resume(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev);
++ unsigned int restore, ctrl;
++
++ pm_runtime_get_sync(dev);
++
++ /* context restore */
++ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB |
++ CNTRLREG_STEPID | CNTRLREG_4WIRE;
++ tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
++ tscadc_idle_config(tscadc_dev);
++ tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB);
++ restore = tscadc_readl(tscadc_dev, REG_CTRL);
++ tscadc_writel(tscadc_dev, REG_CTRL,
++ (restore | CNTRLREG_TSCSSENB));
++
++ return 0;
++}
++
++static const struct dev_pm_ops tscadc_pm_ops = {
++ .suspend = tscadc_suspend,
++ .resume = tscadc_resume,
++};
++#define TSCADC_PM_OPS (&tscadc_pm_ops)
++#else
++#define TSCADC_PM_OPS NULL
++#endif
++
++static struct platform_driver ti_tscadc_driver = {
++ .driver = {
++ .name = "ti_tscadc",
++ .owner = THIS_MODULE,
++ .pm = TSCADC_PM_OPS,
++ },
++ .probe = ti_tscadc_probe,
++ .remove = __devexit_p(ti_tscadc_remove),
++
++};
++
++module_platform_driver(ti_tscadc_driver);
++
++MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
++MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+new file mode 100644
+index 0000000..b7232b1
+--- /dev/null
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -0,0 +1,137 @@
++#ifndef __LINUX_TI_AM335X_TSCADC_MFD_H
++#define __LINUX_TI_AM335X_TSCADC_MFD_H
++
++/*
++ * TI Touch Screen / ADC MFD driver
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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 version 2.
++ *
++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
++ * kind, whether express or implied; without even the implied warranty
++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/mfd/core.h>
++
++#define REG_RAWIRQSTATUS 0x024
++#define REG_IRQSTATUS 0x028
++#define REG_IRQENABLE 0x02C
++#define REG_IRQCLR 0x030
++#define REG_IRQWAKEUP 0x034
++#define REG_CTRL 0x040
++#define REG_ADCFSM 0x044
++#define REG_CLKDIV 0x04C
++#define REG_SE 0x054
++#define REG_IDLECONFIG 0x058
++#define REG_CHARGECONFIG 0x05C
++#define REG_CHARGEDELAY 0x060
++#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
++#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
++#define REG_FIFO0CNT 0xE4
++#define REG_FIFO0THR 0xE8
++#define REG_FIFO1CNT 0xF0
++#define REG_FIFO1THR 0xF4
++#define REG_FIFO0 0x100
++#define REG_FIFO1 0x200
++
++/* Register Bitfields */
++/* IRQ wakeup enable */
++#define IRQWKUP_ENB BIT(0)
++
++/* Step Enable */
++#define STEPENB_MASK (0x1FFFF << 0)
++#define STEPENB(val) ((val) << 0)
++#define STPENB_STEPENB STEPENB(0x1FFFF)
++
++/* IRQ enable */
++#define IRQENB_HW_PEN BIT(0)
++#define IRQENB_FIFO0THRES BIT(2)
++#define IRQENB_FIFO1THRES BIT(5)
++#define IRQENB_PENUP BIT(9)
++
++/* Step Configuration */
++#define STEPCONFIG_MODE_MASK (3 << 0)
++#define STEPCONFIG_MODE(val) ((val) << 0)
++#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
++#define STEPCONFIG_AVG_MASK (7 << 2)
++#define STEPCONFIG_AVG(val) ((val) << 2)
++#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
++#define STEPCONFIG_XPP BIT(5)
++#define STEPCONFIG_XNN BIT(6)
++#define STEPCONFIG_YPP BIT(7)
++#define STEPCONFIG_YNN BIT(8)
++#define STEPCONFIG_XNP BIT(9)
++#define STEPCONFIG_YPN BIT(10)
++#define STEPCONFIG_INM_MASK (0xF << 15)
++#define STEPCONFIG_INM(val) ((val) << 15)
++#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
++#define STEPCONFIG_INP_MASK (0xF << 19)
++#define STEPCONFIG_INP(val) ((val) << 19)
++#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
++#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
++#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
++#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
++#define STEPCONFIG_FIFO1 BIT(26)
++
++/* Delay register */
++#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
++#define STEPDELAY_OPEN(val) ((val) << 0)
++#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
++#define STEPDELAY_SAMPLE_MASK (0xFF << 24)
++#define STEPDELAY_SAMPLE(val) ((val) << 24)
++#define STEPCONFIG_SAMPLEDLY STEPDELAY_SAMPLE(0)
++
++/* Charge Config */
++#define STEPCHARGE_RFP_MASK (7 << 12)
++#define STEPCHARGE_RFP(val) ((val) << 12)
++#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
++#define STEPCHARGE_INM_MASK (0xF << 15)
++#define STEPCHARGE_INM(val) ((val) << 15)
++#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
++#define STEPCHARGE_INP_MASK (0xF << 19)
++#define STEPCHARGE_INP(val) ((val) << 19)
++#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
++#define STEPCHARGE_RFM_MASK (3 << 23)
++#define STEPCHARGE_RFM(val) ((val) << 23)
++#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
++
++/* Charge delay */
++#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
++#define CHARGEDLY_OPEN(val) ((val) << 0)
++#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
++
++/* Control register */
++#define CNTRLREG_TSCSSENB BIT(0)
++#define CNTRLREG_STEPID BIT(1)
++#define CNTRLREG_STEPCONFIGWRT BIT(2)
++#define CNTRLREG_POWERDOWN BIT(4)
++#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
++#define CNTRLREG_AFE_CTRL(val) ((val) << 5)
++#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
++#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
++#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
++#define CNTRLREG_TSCENB BIT(7)
++
++#define ADC_CLK 3000000
++#define MAX_CLK_DIV 7
++
++#define TSCADC_CELLS 0
++
++struct mfd_tscadc_board {
++ struct tsc_data *tsc_init;
++};
++
++struct ti_tscadc_dev {
++ struct device *dev;
++ struct regmap *regmap_tscadc;
++ void __iomem *tscadc_base;
++ int irq;
++ struct mfd_cell cells[TSCADC_CELLS];
++};
++
++#endif
diff --git a/patches/linux-3.7-rc6/0051-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch b/patches/linux-3.7-rc6/0051-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch
new file mode 100644
index 0000000..11bdb5f
--- /dev/null
+++ b/patches/linux-3.7-rc6/0051-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch
@@ -0,0 +1,571 @@
+From 0191d4a7838cc6c437d8811ec630e26f10abe116 Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:44 +0000
+Subject: [PATCH] input: TSC: ti_tsc: Convert TSC into a MFDevice
+
+This patch converts touchscreen into a MFD client.
+All the register definitions, clock initialization,
+etc has been moved to MFD core driver.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/Kconfig | 2 +-
+ drivers/input/touchscreen/ti_am335x_tsc.c | 318 +++++++++--------------------
+ drivers/mfd/ti_am335x_tscadc.c | 11 +
+ include/linux/mfd/ti_am335x_tscadc.h | 10 +-
+ 4 files changed, 118 insertions(+), 223 deletions(-)
+
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index d31dc5f..0c45cad 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -531,7 +531,7 @@ config TOUCHSCREEN_TOUCHWIN
+
+ config TOUCHSCREEN_TI_AM335X_TSC
+ tristate "TI Touchscreen Interface"
+- depends on ARCH_OMAP2PLUS
++ depends on MFD_TI_AM335X_TSCADC
+ help
+ Say Y here if you have 4/5/8 wire touchscreen controller
+ to be connected to the ADC controller on your TI AM335x SoC.
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 462950a..7a18a8a 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -27,106 +27,15 @@
+ #include <linux/input/ti_am335x_tsc.h>
+ #include <linux/delay.h>
+
+-#define REG_RAWIRQSTATUS 0x024
+-#define REG_IRQSTATUS 0x028
+-#define REG_IRQENABLE 0x02C
+-#define REG_IRQWAKEUP 0x034
+-#define REG_CTRL 0x040
+-#define REG_ADCFSM 0x044
+-#define REG_CLKDIV 0x04C
+-#define REG_SE 0x054
+-#define REG_IDLECONFIG 0x058
+-#define REG_CHARGECONFIG 0x05C
+-#define REG_CHARGEDELAY 0x060
+-#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+-#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+-#define REG_FIFO0CNT 0xE4
+-#define REG_FIFO0THR 0xE8
+-#define REG_FIFO1THR 0xF4
+-#define REG_FIFO0 0x100
+-#define REG_FIFO1 0x200
+-
+-/* Register Bitfields */
+-#define IRQWKUP_ENB BIT(0)
+-
+-/* Step Enable */
+-#define STEPENB_MASK (0x1FFFF << 0)
+-#define STEPENB(val) (val << 0)
+-#define STPENB_STEPENB STEPENB(0x7FFF)
+-
+-/* IRQ enable */
+-#define IRQENB_FIFO0THRES BIT(2)
+-#define IRQENB_FIFO1THRES BIT(5)
+-#define IRQENB_PENUP BIT(9)
+-
+-/* Step Configuration */
+-#define STEPCONFIG_MODE_MASK (3 << 0)
+-#define STEPCONFIG_MODE(val) (val << 0)
+-#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
+-#define STEPCONFIG_AVG_MASK (7 << 2)
+-#define STEPCONFIG_AVG(val) (val << 2)
+-#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
+-#define STEPCONFIG_XPP BIT(5)
+-#define STEPCONFIG_XNN BIT(6)
+-#define STEPCONFIG_YPP BIT(7)
+-#define STEPCONFIG_YNN BIT(8)
+-#define STEPCONFIG_XNP BIT(9)
+-#define STEPCONFIG_YPN BIT(10)
+-#define STEPCONFIG_INM_MASK (0xF << 15)
+-#define STEPCONFIG_INM(val) (val << 15)
+-#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
+-#define STEPCONFIG_INP_MASK (0xF << 19)
+-#define STEPCONFIG_INP(val) (val << 19)
+-#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
+-#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
+-#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
+-#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
+-#define STEPCONFIG_FIFO1 BIT(26)
+-
+-/* Delay register */
+-#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
+-#define STEPDELAY_OPEN(val) (val << 0)
+-#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
+-
+-/* Charge Config */
+-#define STEPCHARGE_RFP_MASK (7 << 12)
+-#define STEPCHARGE_RFP(val) (val << 12)
+-#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
+-#define STEPCHARGE_INM_MASK (0xF << 15)
+-#define STEPCHARGE_INM(val) (val << 15)
+-#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
+-#define STEPCHARGE_INP_MASK (0xF << 19)
+-#define STEPCHARGE_INP(val) (val << 19)
+-#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
+-#define STEPCHARGE_RFM_MASK (3 << 23)
+-#define STEPCHARGE_RFM(val) (val << 23)
+-#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
+-
+-/* Charge delay */
+-#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
+-#define CHARGEDLY_OPEN(val) (val << 0)
+-#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
+-
+-/* Control register */
+-#define CNTRLREG_TSCSSENB BIT(0)
+-#define CNTRLREG_STEPID BIT(1)
+-#define CNTRLREG_STEPCONFIGWRT BIT(2)
+-#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
+-#define CNTRLREG_AFE_CTRL(val) (val << 5)
+-#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
+-#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
+-#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
+-#define CNTRLREG_TSCENB BIT(7)
++#include <linux/mfd/ti_am335x_tscadc.h>
+
+ #define ADCFSM_STEPID 0x10
+ #define SEQ_SETTLE 275
+-#define ADC_CLK 3000000
+ #define MAX_12BIT ((1 << 12) - 1)
+
+ struct titsc {
+ struct input_dev *input;
+- struct clk *tsc_ick;
+- void __iomem *tsc_base;
++ struct ti_tscadc_dev *mfd_tscadc;
+ unsigned int irq;
+ unsigned int wires;
+ unsigned int x_plate_resistance;
+@@ -136,13 +45,13 @@ struct titsc {
+
+ static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+ {
+- return readl(ts->tsc_base + reg);
++ return readl(ts->mfd_tscadc->tscadc_base + reg);
+ }
+
+ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ unsigned int val)
+ {
+- writel(val, tsc->tsc_base + reg);
++ writel(val, tsc->mfd_tscadc->tscadc_base + reg);
+ }
+
+ static void titsc_step_config(struct titsc *ts_dev)
+@@ -219,17 +128,7 @@ static void titsc_step_config(struct titsc *ts_dev)
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+ STEPCONFIG_OPENDLY);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+-}
+-
+-static void titsc_idle_config(struct titsc *ts_config)
+-{
+- unsigned int idleconfig;
+-
+- idleconfig = STEPCONFIG_YNN |
+- STEPCONFIG_INM_ADCREFM |
+- STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
+- titsc_writel(ts_config, REG_IDLECONFIG, idleconfig);
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+ }
+
+ static void titsc_read_coordinates(struct titsc *ts_dev,
+@@ -239,7 +138,7 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
+ unsigned int prev_val_x = ~0, prev_val_y = ~0;
+ unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
+ unsigned int read, diff;
+- unsigned int i;
++ unsigned int i, channel;
+
+ /*
+ * Delta filter is used to remove large variations in sampled
+@@ -250,21 +149,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
+ * if true the value is reported to the sub system.
+ */
+ for (i = 0; i < fifocount - 1; i++) {
+- read = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
+- diff = abs(read - prev_val_x);
+- if (diff < prev_diff_x) {
+- prev_diff_x = diff;
+- *x = read;
++ read = titsc_readl(ts_dev, REG_FIFO0);
++ channel = read & 0xf0000;
++ channel = channel >> 0x10;
++ if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
++ read &= 0xfff;
++ diff = abs(read - prev_val_x);
++ if (diff < prev_diff_x) {
++ prev_diff_x = diff;
++ *x = read;
++ }
++ prev_val_x = read;
+ }
+- prev_val_x = read;
+
+- read = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
+- diff = abs(read - prev_val_y);
+- if (diff < prev_diff_y) {
+- prev_diff_y = diff;
+- *y = read;
++ read = titsc_readl(ts_dev, REG_FIFO1);
++ channel = read & 0xf0000;
++ channel = channel >> 0x10;
++ if ((channel >= ts_dev->steps_to_configure) &&
++ (channel < (2 * ts_dev->steps_to_configure - 1))) {
++ read &= 0xfff;
++ diff = abs(read - prev_val_y);
++ if (diff < prev_diff_y) {
++ prev_diff_y = diff;
++ *y = read;
++ }
++ prev_val_y = read;
+ }
+- prev_val_y = read;
+ }
+ }
+
+@@ -276,6 +186,8 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ unsigned int x = 0, y = 0;
+ unsigned int z1, z2, z;
+ unsigned int fsm;
++ unsigned int fifo1count, fifo0count;
++ int i;
+
+ status = titsc_readl(ts_dev, REG_IRQSTATUS);
+ if (status & IRQENB_FIFO0THRES) {
+@@ -284,6 +196,14 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
+ z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
+
++ fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
++ for (i = 0; i < fifo1count; i++)
++ titsc_readl(ts_dev, REG_FIFO1);
++
++ fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
++ for (i = 0; i < fifo0count; i++)
++ titsc_readl(ts_dev, REG_FIFO0);
++
+ if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
+ /*
+ * Calculate pressure using formula
+@@ -330,7 +250,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+
+ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+ return IRQ_HANDLED;
+ }
+
+@@ -340,28 +260,16 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+
+ static int __devinit titsc_probe(struct platform_device *pdev)
+ {
+- const struct tsc_data *pdata = pdev->dev.platform_data;
+- struct resource *res;
+ struct titsc *ts_dev;
+ struct input_dev *input_dev;
+- struct clk *clk;
++ struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
++ struct mfd_tscadc_board *pdata;
+ int err;
+- int clk_value, ctrl, irq;
+
+- if (!pdata) {
+- dev_err(&pdev->dev, "missing platform data.\n");
+- return -EINVAL;
+- }
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- dev_err(&pdev->dev, "no memory resource defined.\n");
+- return -EINVAL;
+- }
++ pdata = tscadc_dev->dev->platform_data;
+
+- irq = platform_get_irq(pdev, 0);
+- if (irq < 0) {
+- dev_err(&pdev->dev, "no irq ID is specified.\n");
++ if (!pdata) {
++ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+
+@@ -374,85 +282,26 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ goto err_free_mem;
+ }
+
++ tscadc_dev->tsc = ts_dev;
++ ts_dev->mfd_tscadc = tscadc_dev;
+ ts_dev->input = input_dev;
+- ts_dev->irq = irq;
+- ts_dev->wires = pdata->wires;
+- ts_dev->x_plate_resistance = pdata->x_plate_resistance;
+- ts_dev->steps_to_configure = pdata->steps_to_configure;
+-
+- res = request_mem_region(res->start, resource_size(res), pdev->name);
+- if (!res) {
+- dev_err(&pdev->dev, "failed to reserve registers.\n");
+- err = -EBUSY;
+- goto err_free_mem;
+- }
+-
+- ts_dev->tsc_base = ioremap(res->start, resource_size(res));
+- if (!ts_dev->tsc_base) {
+- dev_err(&pdev->dev, "failed to map registers.\n");
+- err = -ENOMEM;
+- goto err_release_mem_region;
+- }
++ ts_dev->irq = tscadc_dev->irq;
++ ts_dev->wires = pdata->tsc_init->wires;
++ ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
++ ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
+
+ err = request_irq(ts_dev->irq, titsc_irq,
+ 0, pdev->dev.driver->name, ts_dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to allocate irq.\n");
+- goto err_unmap_regs;
+- }
+-
+- ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
+- if (IS_ERR(ts_dev->tsc_ick)) {
+- dev_err(&pdev->dev, "failed to get TSC ick\n");
+- goto err_free_irq;
+- }
+- clk_enable(ts_dev->tsc_ick);
+-
+- clk = clk_get(&pdev->dev, "adc_tsc_fck");
+- if (IS_ERR(clk)) {
+- dev_err(&pdev->dev, "failed to get TSC fck\n");
+- err = PTR_ERR(clk);
+- goto err_disable_clk;
+- }
+-
+- clk_value = clk_get_rate(clk) / ADC_CLK;
+- clk_put(clk);
+-
+- if (clk_value < 7) {
+- dev_err(&pdev->dev, "clock input less than min clock requirement\n");
+- goto err_disable_clk;
+- }
+- /* CLKDIV needs to be configured to the value minus 1 */
+- titsc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
+-
+- /* Enable wake-up of the SoC using touchscreen */
+- titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
+-
+- ctrl = CNTRLREG_STEPCONFIGWRT |
+- CNTRLREG_TSCENB |
+- CNTRLREG_STEPID;
+- switch (ts_dev->wires) {
+- case 4:
+- ctrl |= CNTRLREG_4WIRE;
+- break;
+- case 5:
+- ctrl |= CNTRLREG_5WIRE;
+- break;
+- case 8:
+- ctrl |= CNTRLREG_8WIRE;
+- break;
++ goto err_free_mem;
+ }
+- titsc_writel(ts_dev, REG_CTRL, ctrl);
+
+- titsc_idle_config(ts_dev);
+ titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+
+- ctrl |= CNTRLREG_TSCSSENB;
+- titsc_writel(ts_dev, REG_CTRL, ctrl);
+-
+- input_dev->name = "ti-tsc-adc";
++ input_dev->name = "ti-tsc";
+ input_dev->dev.parent = &pdev->dev;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+@@ -465,20 +314,13 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ /* register to the input system */
+ err = input_register_device(input_dev);
+ if (err)
+- goto err_disable_clk;
++ goto err_free_irq;
+
+ platform_set_drvdata(pdev, ts_dev);
+ return 0;
+
+-err_disable_clk:
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
+ err_free_irq:
+ free_irq(ts_dev->irq, ts_dev);
+-err_unmap_regs:
+- iounmap(ts_dev->tsc_base);
+-err_release_mem_region:
+- release_mem_region(res->start, resource_size(res));
+ err_free_mem:
+ input_free_device(input_dev);
+ kfree(ts_dev);
+@@ -487,32 +329,66 @@ err_free_mem:
+
+ static int __devexit titsc_remove(struct platform_device *pdev)
+ {
+- struct titsc *ts_dev = platform_get_drvdata(pdev);
+- struct resource *res;
++ struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
++ struct titsc *ts_dev = tscadc_dev->tsc;
+
+ free_irq(ts_dev->irq, ts_dev);
+
+ input_unregister_device(ts_dev->input);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- iounmap(ts_dev->tsc_base);
+- release_mem_region(res->start, resource_size(res));
++ platform_set_drvdata(pdev, NULL);
++ kfree(ts_dev);
++ return 0;
++}
+
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
++#ifdef CONFIG_PM
++static int titsc_suspend(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
++ struct titsc *ts_dev = tscadc_dev->tsc;
++ unsigned int idle;
++
++ if (device_may_wakeup(tscadc_dev->dev)) {
++ idle = titsc_readl(ts_dev, REG_IRQENABLE);
++ titsc_writel(ts_dev, REG_IRQENABLE,
++ (idle | IRQENB_HW_PEN));
++ titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
++ }
++ return 0;
++}
+
+- kfree(ts_dev);
++static int titsc_resume(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
++ struct titsc *ts_dev = tscadc_dev->tsc;
+
+- platform_set_drvdata(pdev, NULL);
++ if (device_may_wakeup(tscadc_dev->dev)) {
++ titsc_writel(ts_dev, REG_IRQWAKEUP,
++ 0x00);
++ titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
++ }
++ titsc_step_config(ts_dev);
++ titsc_writel(ts_dev, REG_FIFO0THR,
++ ts_dev->steps_to_configure);
+ return 0;
+ }
+
++static const struct dev_pm_ops titsc_pm_ops = {
++ .suspend = titsc_suspend,
++ .resume = titsc_resume,
++};
++#define TITSC_PM_OPS (&titsc_pm_ops)
++#else
++#define TITSC_PM_OPS NULL
++#endif
++
+ static struct platform_driver ti_tsc_driver = {
+ .probe = titsc_probe,
+ .remove = __devexit_p(titsc_remove),
+ .driver = {
+ .name = "tsc",
+ .owner = THIS_MODULE,
++ .pm = TITSC_PM_OPS,
+ },
+ };
+ module_platform_driver(ti_tsc_driver);
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index 14df67b..d812be4 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -24,6 +24,7 @@
+ #include <linux/pm_runtime.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
++#include <linux/input/ti_am335x_tsc.h>
+
+ static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
+ {
+@@ -62,15 +63,19 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ struct resource *res;
+ struct clk *clk;
+ struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
++ struct mfd_cell *cell;
+ int irq;
+ int err, ctrl;
+ int clk_value, clock_rate;
++ int tsc_wires;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+
++ tsc_wires = pdata->tsc_init->wires;
++
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no memory resource defined.\n");
+@@ -161,6 +166,12 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(tscadc, REG_CTRL, ctrl);
+
++ /* TSC Cell */
++ cell = &tscadc->cells[TSC_CELL];
++ cell->name = "tsc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++
+ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+ TSCADC_CELLS, NULL, 0, NULL);
+ if (err < 0)
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index b7232b1..fc18b2e 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -47,6 +47,7 @@
+ #define STEPENB_MASK (0x1FFFF << 0)
+ #define STEPENB(val) ((val) << 0)
+ #define STPENB_STEPENB STEPENB(0x1FFFF)
++#define STPENB_STEPENB_TC STEPENB(0x1FFF)
+
+ /* IRQ enable */
+ #define IRQENB_HW_PEN BIT(0)
+@@ -120,7 +121,11 @@
+ #define ADC_CLK 3000000
+ #define MAX_CLK_DIV 7
+
+-#define TSCADC_CELLS 0
++#define TSCADC_CELLS 1
++
++enum tscadc_cells {
++ TSC_CELL,
++};
+
+ struct mfd_tscadc_board {
+ struct tsc_data *tsc_init;
+@@ -132,6 +137,9 @@ struct ti_tscadc_dev {
+ void __iomem *tscadc_base;
+ int irq;
+ struct mfd_cell cells[TSCADC_CELLS];
++
++ /* tsc device */
++ struct titsc *tsc;
+ };
+
+ #endif
diff --git a/patches/linux-3.7-rc6/0052-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch b/patches/linux-3.7-rc6/0052-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch
new file mode 100644
index 0000000..55e3b66
--- /dev/null
+++ b/patches/linux-3.7-rc6/0052-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch
@@ -0,0 +1,420 @@
+From 1c87d22d7a5671164abd42a6478cf536a3637fee Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:45 +0000
+Subject: [PATCH] IIO : ADC: tiadc: Add support of TI's ADC driver
+
+This patch adds support for TI's ADC driver.
+This is a multifunctional device.
+Analog input lines are provided on which
+voltage measurements can be carried out.
+You can have upto 8 input lines.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Acked-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/adc/Kconfig | 7 +
+ drivers/iio/adc/Makefile | 1 +
+ drivers/iio/adc/ti_am335x_adc.c | 260 +++++++++++++++++++++++++++
+ drivers/mfd/ti_am335x_tscadc.c | 18 +-
+ include/linux/mfd/ti_am335x_tscadc.h | 9 +-
+ include/linux/platform_data/ti_am335x_adc.h | 14 ++
+ 6 files changed, 307 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/iio/adc/ti_am335x_adc.c
+ create mode 100644 include/linux/platform_data/ti_am335x_adc.h
+
+diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
+index 4927581..1401ed1 100644
+--- a/drivers/iio/adc/Kconfig
++++ b/drivers/iio/adc/Kconfig
+@@ -60,4 +60,11 @@ config LP8788_ADC
+ help
+ Say yes here to build support for TI LP8788 ADC.
+
++config TI_AM335X_ADC
++ tristate "TI's ADC driver"
++ depends on MFD_TI_AM335X_TSCADC
++ help
++ Say yes here to build support for Texas Instruments ADC
++ driver which is also a MFD client.
++
+ endmenu
+diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
+index 900995d..4410a90 100644
+--- a/drivers/iio/adc/Makefile
++++ b/drivers/iio/adc/Makefile
+@@ -8,3 +8,4 @@ obj-$(CONFIG_AD7476) += ad7476.o
+ obj-$(CONFIG_AD7791) += ad7791.o
+ obj-$(CONFIG_AT91_ADC) += at91_adc.o
+ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
++obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+new file mode 100644
+index 0000000..02a43c8
+--- /dev/null
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -0,0 +1,260 @@
++/*
++ * TI ADC MFD driver
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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 version 2.
++ *
++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
++ * kind, whether express or implied; without even the implied warranty
++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/iio/iio.h>
++
++#include <linux/mfd/ti_am335x_tscadc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++
++struct tiadc_device {
++ struct ti_tscadc_dev *mfd_tscadc;
++ int channels;
++};
++
++static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
++{
++ return readl(adc->mfd_tscadc->tscadc_base + reg);
++}
++
++static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
++ unsigned int val)
++{
++ writel(val, adc->mfd_tscadc->tscadc_base + reg);
++}
++
++static void tiadc_step_config(struct tiadc_device *adc_dev)
++{
++ unsigned int stepconfig;
++ int i, channels = 0, steps;
++
++ /*
++ * There are 16 configurable steps and 8 analog input
++ * lines available which are shared between Touchscreen and ADC.
++ *
++ * Steps backwards i.e. from 16 towards 0 are used by ADC
++ * depending on number of input lines needed.
++ * Channel would represent which analog input
++ * needs to be given to ADC to digitalize data.
++ */
++
++ steps = TOTAL_STEPS - adc_dev->channels;
++ channels = TOTAL_CHANNELS - adc_dev->channels;
++
++ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
++
++ for (i = (steps + 1); i <= TOTAL_STEPS; i++) {
++ tiadc_writel(adc_dev, REG_STEPCONFIG(i),
++ stepconfig | STEPCONFIG_INP(channels));
++ tiadc_writel(adc_dev, REG_STEPDELAY(i),
++ STEPCONFIG_OPENDLY);
++ channels++;
++ }
++ tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
++}
++
++static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
++{
++ struct iio_chan_spec *chan_array;
++ int i;
++
++ indio_dev->num_channels = channels;
++ chan_array = kcalloc(indio_dev->num_channels,
++ sizeof(struct iio_chan_spec), GFP_KERNEL);
++
++ if (chan_array == NULL)
++ return -ENOMEM;
++
++ for (i = 0; i < (indio_dev->num_channels); i++) {
++ struct iio_chan_spec *chan = chan_array + i;
++ chan->type = IIO_VOLTAGE;
++ chan->indexed = 1;
++ chan->channel = i;
++ chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
++ }
++
++ indio_dev->channels = chan_array;
++
++ return indio_dev->num_channels;
++}
++
++static void tiadc_channels_remove(struct iio_dev *indio_dev)
++{
++ kfree(indio_dev->channels);
++}
++
++static int tiadc_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan,
++ int *val, int *val2, long mask)
++{
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
++ int i;
++ unsigned int fifo1count, readx1;
++
++ /*
++ * When the sub-system is first enabled,
++ * the sequencer will always start with the
++ * lowest step (1) and continue until step (16).
++ * For ex: If we have enabled 4 ADC channels and
++ * currently use only 1 out of them, the
++ * sequencer still configures all the 4 steps,
++ * leading to 3 unwanted data.
++ * Hence we need to flush out this data.
++ */
++
++ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
++ for (i = 0; i < fifo1count; i++) {
++ readx1 = tiadc_readl(adc_dev, REG_FIFO1);
++ if (i == chan->channel)
++ *val = readx1 & 0xfff;
++ }
++ tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
++
++ return IIO_VAL_INT;
++}
++
++static const struct iio_info tiadc_info = {
++ .read_raw = &tiadc_read_raw,
++};
++
++static int __devinit tiadc_probe(struct platform_device *pdev)
++{
++ struct iio_dev *indio_dev;
++ struct tiadc_device *adc_dev;
++ struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
++ struct mfd_tscadc_board *pdata;
++ int err;
++
++ pdata = tscadc_dev->dev->platform_data;
++ if (!pdata || !pdata->adc_init) {
++ dev_err(&pdev->dev, "Could not find platform data\n");
++ return -EINVAL;
++ }
++
++ indio_dev = iio_device_alloc(sizeof(struct tiadc_device));
++ if (indio_dev == NULL) {
++ dev_err(&pdev->dev, "failed to allocate iio device\n");
++ err = -ENOMEM;
++ goto err_ret;
++ }
++ adc_dev = iio_priv(indio_dev);
++
++ adc_dev->mfd_tscadc = tscadc_dev;
++ adc_dev->channels = pdata->adc_init->adc_channels;
++
++ indio_dev->dev.parent = &pdev->dev;
++ indio_dev->name = dev_name(&pdev->dev);
++ indio_dev->modes = INDIO_DIRECT_MODE;
++ indio_dev->info = &tiadc_info;
++
++ tiadc_step_config(adc_dev);
++
++ err = tiadc_channel_init(indio_dev, adc_dev->channels);
++ if (err < 0)
++ goto err_free_device;
++
++ err = iio_device_register(indio_dev);
++ if (err)
++ goto err_free_channels;
++
++ platform_set_drvdata(pdev, indio_dev);
++
++ return 0;
++
++err_free_channels:
++ tiadc_channels_remove(indio_dev);
++err_free_device:
++ iio_device_free(indio_dev);
++err_ret:
++ return err;
++}
++
++static int __devexit tiadc_remove(struct platform_device *pdev)
++{
++ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
++
++ iio_device_unregister(indio_dev);
++ tiadc_channels_remove(indio_dev);
++
++ iio_device_free(indio_dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int tiadc_suspend(struct device *dev)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
++ struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
++ unsigned int idle;
++
++ if (!device_may_wakeup(tscadc_dev->dev)) {
++ idle = tiadc_readl(adc_dev, REG_CTRL);
++ idle &= ~(CNTRLREG_TSCSSENB);
++ tiadc_writel(adc_dev, REG_CTRL, (idle |
++ CNTRLREG_POWERDOWN));
++ }
++
++ return 0;
++}
++
++static int tiadc_resume(struct device *dev)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
++ unsigned int restore;
++
++ /* Make sure ADC is powered up */
++ restore = tiadc_readl(adc_dev, REG_CTRL);
++ restore &= ~(CNTRLREG_POWERDOWN);
++ tiadc_writel(adc_dev, REG_CTRL, restore);
++
++ tiadc_step_config(adc_dev);
++
++ return 0;
++}
++
++static const struct dev_pm_ops tiadc_pm_ops = {
++ .suspend = tiadc_suspend,
++ .resume = tiadc_resume,
++};
++#define TIADC_PM_OPS (&tiadc_pm_ops)
++#else
++#define TIADC_PM_OPS NULL
++#endif
++
++static struct platform_driver tiadc_driver = {
++ .driver = {
++ .name = "tiadc",
++ .owner = THIS_MODULE,
++ .pm = TIADC_PM_OPS,
++ },
++ .probe = tiadc_probe,
++ .remove = __devexit_p(tiadc_remove),
++};
++
++module_platform_driver(tiadc_driver);
++
++MODULE_DESCRIPTION("TI ADC controller driver");
++MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index d812be4..e947dd8 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -25,6 +25,7 @@
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
+
+ static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
+ {
+@@ -67,14 +68,23 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ int irq;
+ int err, ctrl;
+ int clk_value, clock_rate;
+- int tsc_wires;
++ int tsc_wires, adc_channels = 0, total_channels;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+
++ if (pdata->adc_init)
++ adc_channels = pdata->adc_init->adc_channels;
++
+ tsc_wires = pdata->tsc_init->wires;
++ total_channels = tsc_wires + adc_channels;
++
++ if (total_channels > 8) {
++ dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
++ return -EINVAL;
++ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+@@ -172,6 +182,12 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ cell->platform_data = tscadc;
+ cell->pdata_size = sizeof(*tscadc);
+
++ /* ADC Cell */
++ cell = &tscadc->cells[ADC_CELL];
++ cell->name = "tiadc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++
+ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+ TSCADC_CELLS, NULL, 0, NULL);
+ if (err < 0)
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index fc18b2e..c79ad5d 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -120,15 +120,19 @@
+
+ #define ADC_CLK 3000000
+ #define MAX_CLK_DIV 7
++#define TOTAL_STEPS 16
++#define TOTAL_CHANNELS 8
+
+-#define TSCADC_CELLS 1
++#define TSCADC_CELLS 2
+
+ enum tscadc_cells {
+ TSC_CELL,
++ ADC_CELL,
+ };
+
+ struct mfd_tscadc_board {
+ struct tsc_data *tsc_init;
++ struct adc_data *adc_init;
+ };
+
+ struct ti_tscadc_dev {
+@@ -140,6 +144,9 @@ struct ti_tscadc_dev {
+
+ /* tsc device */
+ struct titsc *tsc;
++
++ /* adc device */
++ struct adc_device *adc;
+ };
+
+ #endif
+diff --git a/include/linux/platform_data/ti_am335x_adc.h b/include/linux/platform_data/ti_am335x_adc.h
+new file mode 100644
+index 0000000..e41d583
+--- /dev/null
++++ b/include/linux/platform_data/ti_am335x_adc.h
+@@ -0,0 +1,14 @@
++#ifndef __LINUX_TI_AM335X_ADC_H
++#define __LINUX_TI_AM335X_ADC_H
++
++/**
++ * struct adc_data ADC Input information
++ * @adc_channels: Number of analog inputs
++ * available for ADC.
++ */
++
++struct adc_data {
++ unsigned int adc_channels;
++};
++
++#endif
diff --git a/patches/linux-3.7-rc6/0053-input-ti_am335x_tsc-Make-steps-enable-configurable.patch b/patches/linux-3.7-rc6/0053-input-ti_am335x_tsc-Make-steps-enable-configurable.patch
new file mode 100644
index 0000000..cc791d4
--- /dev/null
+++ b/patches/linux-3.7-rc6/0053-input-ti_am335x_tsc-Make-steps-enable-configurable.patch
@@ -0,0 +1,74 @@
+From c2e4f935c7eb7e48e81eee2f11582ea686e9199a Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Mon, 22 Oct 2012 10:15:16 +0000
+Subject: [PATCH] input: ti_am335x_tsc: Make steps enable configurable
+
+Current code has hard coded value written to
+step enable bits. Now the bits are updated based
+on how many steps are needed to be configured got
+from platform data.
+
+The user needs to take care not to exceed
+the count more than 16. While using ADC and TSC
+one should take care to set this parameter correctly.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 10 ++++++++--
+ include/linux/mfd/ti_am335x_tscadc.h | 1 -
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 7a18a8a..4369224 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -39,6 +39,7 @@ struct titsc {
+ unsigned int irq;
+ unsigned int wires;
+ unsigned int x_plate_resistance;
++ unsigned int enable_bits;
+ bool pen_down;
+ int steps_to_configure;
+ };
+@@ -57,6 +58,7 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ static void titsc_step_config(struct titsc *ts_dev)
+ {
+ unsigned int config;
++ unsigned int stepenable = 0;
+ int i, total_steps;
+
+ /* Configure the Step registers */
+@@ -128,7 +130,11 @@ static void titsc_step_config(struct titsc *ts_dev)
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+ STEPCONFIG_OPENDLY);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
++ for (i = 0; i <= (total_steps + 2); i++)
++ stepenable |= 1 << i;
++ ts_dev->enable_bits = stepenable;
++
++ titsc_writel(ts_dev, REG_SE, ts_dev->enable_bits);
+ }
+
+ static void titsc_read_coordinates(struct titsc *ts_dev,
+@@ -250,7 +256,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+
+ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
++ titsc_writel(ts_dev, REG_SE, ts_dev->enable_bits);
+ return IRQ_HANDLED;
+ }
+
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index c79ad5d..23e4f33 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -47,7 +47,6 @@
+ #define STEPENB_MASK (0x1FFFF << 0)
+ #define STEPENB(val) ((val) << 0)
+ #define STPENB_STEPENB STEPENB(0x1FFFF)
+-#define STPENB_STEPENB_TC STEPENB(0x1FFF)
+
+ /* IRQ enable */
+ #define IRQENB_HW_PEN BIT(0)
diff --git a/patches/linux-3.7-rc6/0054-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch b/patches/linux-3.7-rc6/0054-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch
new file mode 100644
index 0000000..0f7105a
--- /dev/null
+++ b/patches/linux-3.7-rc6/0054-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch
@@ -0,0 +1,329 @@
+From 27f22a592f264d221ecd8ddc1dc8f7d49ea4108a Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Mon, 22 Oct 2012 10:15:17 +0000
+Subject: [PATCH] input: ti_am335x_tsc: Order of TSC wires connect, made
+ configurable
+
+The driver expected touchscreen wires(XP,XN,YP,YN)
+to be connected in a particular order.
+Making changes to accept this as platform data.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 156 ++++++++++++++++++++++++++---
+ include/linux/input/ti_am335x_tsc.h | 12 +++
+ include/linux/mfd/ti_am335x_tscadc.h | 10 +-
+ 3 files changed, 159 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 4369224..6a817a8 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -33,6 +33,17 @@
+ #define SEQ_SETTLE 275
+ #define MAX_12BIT ((1 << 12) - 1)
+
++/*
++ * Refer to function regbit_map() to
++ * map the values in the matrix.
++ */
++static int config[4][4] = {
++ {1, 0, 1, 0},
++ {2, 3, 2, 3},
++ {4, 5, 4, 5},
++ {0, 6, 0, 6}
++};
++
+ struct titsc {
+ struct input_dev *input;
+ struct ti_tscadc_dev *mfd_tscadc;
+@@ -42,6 +53,9 @@ struct titsc {
+ unsigned int enable_bits;
+ bool pen_down;
+ int steps_to_configure;
++ int config_inp[20];
++ int bit_xp, bit_xn, bit_yp, bit_yn;
++ int inp_xp, inp_xn, inp_yp, inp_yn;
+ };
+
+ static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+@@ -55,6 +69,107 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ writel(val, tsc->mfd_tscadc->tscadc_base + reg);
+ }
+
++/*
++ * Each of the analog lines are mapped
++ * with one or two register bits,
++ * which can be either pulled high/low
++ * depending on the value to be read.
++ */
++static int regbit_map(int val)
++{
++ int map_bits = 0;
++
++ switch (val) {
++ case 1:
++ map_bits = XPP;
++ break;
++ case 2:
++ map_bits = XNP;
++ break;
++ case 3:
++ map_bits = XNN;
++ break;
++ case 4:
++ map_bits = YPP;
++ break;
++ case 5:
++ map_bits = YPN;
++ break;
++ case 6:
++ map_bits = YNN;
++ break;
++ }
++
++ return map_bits;
++}
++
++static int titsc_config_wires(struct titsc *ts_dev)
++{
++ int analog_line[10], wire_order[10];
++ int i, temp_bits, err;
++
++ for (i = 0; i < 4; i++) {
++ /*
++ * Get the order in which TSC wires are attached
++ * w.r.t. each of the analog input lines on the EVM.
++ */
++ analog_line[i] = ts_dev->config_inp[i] & 0xF0;
++ analog_line[i] = analog_line[i] >> 4;
++
++ wire_order[i] = ts_dev->config_inp[i] & 0x0F;
++ }
++
++ for (i = 0; i < 4; i++) {
++ switch (wire_order[i]) {
++ case 0:
++ temp_bits = config[analog_line[i]][0];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_xp = regbit_map(temp_bits);
++ ts_dev->inp_xp = analog_line[i];
++ break;
++ }
++ case 1:
++ temp_bits = config[analog_line[i]][1];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_xn = regbit_map(temp_bits);
++ ts_dev->inp_xn = analog_line[i];
++ break;
++ }
++ case 2:
++ temp_bits = config[analog_line[i]][2];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_yp = regbit_map(temp_bits);
++ ts_dev->inp_yp = analog_line[i];
++ break;
++ }
++ case 3:
++ temp_bits = config[analog_line[i]][3];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_yn = regbit_map(temp_bits);
++ ts_dev->inp_yn = analog_line[i];
++ break;
++ }
++ }
++ }
++
++ return 0;
++
++ret:
++ return err;
++}
++
+ static void titsc_step_config(struct titsc *ts_dev)
+ {
+ unsigned int config;
+@@ -65,18 +180,18 @@ static void titsc_step_config(struct titsc *ts_dev)
+ total_steps = 2 * ts_dev->steps_to_configure;
+
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
++ STEPCONFIG_AVG_16 | ts_dev->bit_xp;
+ switch (ts_dev->wires) {
+ case 4:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
+ break;
+ case 5:
+- config |= STEPCONFIG_YNN |
+- STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+- STEPCONFIG_YPP;
++ config |= ts_dev->bit_yn |
++ STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
++ ts_dev->bit_yp;
+ break;
+ case 8:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
+ break;
+ }
+
+@@ -87,18 +202,18 @@ static void titsc_step_config(struct titsc *ts_dev)
+
+ config = 0;
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
++ STEPCONFIG_AVG_16 | ts_dev->bit_yn |
+ STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+ switch (ts_dev->wires) {
+ case 4:
+- config |= STEPCONFIG_YPP;
++ config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
+ break;
+ case 5:
+- config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
+- STEPCONFIG_XNP | STEPCONFIG_YPN;
++ config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
++ ts_dev->bit_xn | ts_dev->bit_yp;
+ break;
+ case 8:
+- config |= STEPCONFIG_YPP;
++ config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
+ break;
+ }
+
+@@ -109,9 +224,9 @@ static void titsc_step_config(struct titsc *ts_dev)
+
+ config = 0;
+ /* Charge step configuration */
+- config = STEPCONFIG_XPP | STEPCONFIG_YNN |
++ config = ts_dev->bit_xp | ts_dev->bit_yn |
+ STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
+- STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
++ STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
+
+ titsc_writel(ts_dev, REG_CHARGECONFIG, config);
+ titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+@@ -119,13 +234,14 @@ static void titsc_step_config(struct titsc *ts_dev)
+ config = 0;
+ /* Configure to calculate pressure */
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+- STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
++ STEPCONFIG_AVG_16 | ts_dev->bit_yp |
++ ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_INP(ts_dev->inp_xp);
+ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
+ STEPCONFIG_OPENDLY);
+
+- config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
++ config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1;
+ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+ STEPCONFIG_OPENDLY);
+@@ -295,6 +411,8 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ ts_dev->wires = pdata->tsc_init->wires;
+ ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
+ ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
++ memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
++ sizeof(pdata->tsc_init->wire_config));
+
+ err = request_irq(ts_dev->irq, titsc_irq,
+ 0, pdev->dev.driver->name, ts_dev);
+@@ -304,6 +422,11 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ }
+
+ titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
++ err = titsc_config_wires(ts_dev);
++ if (err) {
++ dev_err(&pdev->dev, "wrong i/p wire configuration\n");
++ goto err_free_irq;
++ }
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+
+@@ -373,6 +496,7 @@ static int titsc_resume(struct device *dev)
+ 0x00);
+ titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
+ }
++ titsc_config_wires(ts_dev);
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR,
+ ts_dev->steps_to_configure);
+diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
+index 49269a2..6a66b4d 100644
+--- a/include/linux/input/ti_am335x_tsc.h
++++ b/include/linux/input/ti_am335x_tsc.h
+@@ -12,12 +12,24 @@
+ * A step configured to read a single
+ * co-ordinate value, can be applied
+ * more number of times for better results.
++ * @wire_config: Different EVM's could have a different order
++ * for connecting wires on touchscreen.
++ * We need to provide an 8 bit number where in
++ * the 1st four bits represent the analog lines
++ * and the next 4 bits represent positive/
++ * negative terminal on that input line.
++ * Notations to represent the input lines and
++ * terminals resoectively is as follows:
++ * AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
++ * XP = 0, XN = 1, YP = 2, YN = 3.
++ *
+ */
+
+ struct tsc_data {
+ int wires;
+ int x_plate_resistance;
+ int steps_to_configure;
++ int wire_config[10];
+ };
+
+ #endif
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index 23e4f33..9624fea 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -72,8 +72,6 @@
+ #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
+ #define STEPCONFIG_INP_MASK (0xF << 19)
+ #define STEPCONFIG_INP(val) ((val) << 19)
+-#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
+-#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
+ #define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
+ #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
+ #define STEPCONFIG_FIFO1 BIT(26)
+@@ -95,7 +93,6 @@
+ #define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
+ #define STEPCHARGE_INP_MASK (0xF << 19)
+ #define STEPCHARGE_INP(val) ((val) << 19)
+-#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
+ #define STEPCHARGE_RFM_MASK (3 << 23)
+ #define STEPCHARGE_RFM(val) ((val) << 23)
+ #define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
+@@ -117,6 +114,13 @@
+ #define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
+ #define CNTRLREG_TSCENB BIT(7)
+
++#define XPP STEPCONFIG_XPP
++#define XNP STEPCONFIG_XNP
++#define XNN STEPCONFIG_XNN
++#define YPP STEPCONFIG_YPP
++#define YPN STEPCONFIG_YPN
++#define YNN STEPCONFIG_YNN
++
+ #define ADC_CLK 3000000
+ #define MAX_CLK_DIV 7
+ #define TOTAL_STEPS 16
diff --git a/patches/linux-3.7-rc6/0055-input-ti_am335x_tsc-Add-variance-filters.patch b/patches/linux-3.7-rc6/0055-input-ti_am335x_tsc-Add-variance-filters.patch
new file mode 100644
index 0000000..4be6c7d
--- /dev/null
+++ b/patches/linux-3.7-rc6/0055-input-ti_am335x_tsc-Add-variance-filters.patch
@@ -0,0 +1,75 @@
+From 18d663634d89727e277e5055af890bbfa13eeffc Mon Sep 17 00:00:00 2001
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Mon, 22 Oct 2012 10:15:18 +0000
+Subject: [PATCH] input: ti_am335x_tsc: Add variance filters
+
+Only fine tuning variance present in tslib utility
+does not help in removing all the wanted ADC noise.
+This logic of filtering is necessary to get this
+touchscreen to work finely.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 6a817a8..7a26810 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -32,6 +32,8 @@
+ #define ADCFSM_STEPID 0x10
+ #define SEQ_SETTLE 275
+ #define MAX_12BIT ((1 << 12) - 1)
++#define TSCADC_DELTA_X 15
++#define TSCADC_DELTA_Y 15
+
+ /*
+ * Refer to function regbit_map() to
+@@ -51,6 +53,8 @@ struct titsc {
+ unsigned int wires;
+ unsigned int x_plate_resistance;
+ unsigned int enable_bits;
++ unsigned int bckup_x;
++ unsigned int bckup_y;
+ bool pen_down;
+ int steps_to_configure;
+ int config_inp[20];
+@@ -309,12 +313,18 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ unsigned int z1, z2, z;
+ unsigned int fsm;
+ unsigned int fifo1count, fifo0count;
++ unsigned int diffx = 0, diffy = 0;
+ int i;
+
+ status = titsc_readl(ts_dev, REG_IRQSTATUS);
+ if (status & IRQENB_FIFO0THRES) {
+ titsc_read_coordinates(ts_dev, &x, &y);
+
++ diffx = abs(x - (ts_dev->bckup_x));
++ diffy = abs(y - (ts_dev->bckup_y));
++ ts_dev->bckup_x = x;
++ ts_dev->bckup_y = y;
++
+ z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
+ z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
+
+@@ -338,7 +348,8 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ z /= z1;
+ z = (z + 2047) >> 12;
+
+- if (z <= MAX_12BIT) {
++ if ((diffx < TSCADC_DELTA_X) &&
++ (diffy < TSCADC_DELTA_Y) && (z <= MAX_12BIT)) {
+ input_report_abs(input_dev, ABS_X, x);
+ input_report_abs(input_dev, ABS_Y, y);
+ input_report_abs(input_dev, ABS_PRESSURE, z);
+@@ -361,6 +372,8 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ fsm = titsc_readl(ts_dev, REG_ADCFSM);
+ if (fsm == ADCFSM_STEPID) {
+ ts_dev->pen_down = false;
++ ts_dev->bckup_x = 0;
++ ts_dev->bckup_y = 0;
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_report_abs(input_dev, ABS_PRESSURE, 0);
+ input_sync(input_dev);
diff --git a/patches/linux-3.7-rc6/0056-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch b/patches/linux-3.7-rc6/0056-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch
new file mode 100644
index 0000000..d0ebf97
--- /dev/null
+++ b/patches/linux-3.7-rc6/0056-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch
@@ -0,0 +1,183 @@
+From 8f4be87c38d30e43f4e83fd104a64e642589f9b2 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:37:24 +0300
+Subject: [PATCH] ti_tscadc: Update with IIO map interface & deal with partial
+ activation
+
+Add an IIO map interface that consumers can use.
+While we're here fix the mfd device in the case where a subdevice
+might not be activated.
+---
+ drivers/iio/adc/ti_am335x_adc.c | 53 ++++++++++++++++++++++++++++------
+ drivers/mfd/ti_am335x_tscadc.c | 30 +++++++++++++------
+ include/linux/mfd/ti_am335x_tscadc.h | 8 ++---
+ 3 files changed, 68 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index 02a43c8..d48fd79 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -20,8 +20,9 @@
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
+-#include <linux/io.h>
+ #include <linux/iio/iio.h>
++#include <linux/iio/machine.h>
++#include <linux/iio/driver.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/platform_data/ti_am335x_adc.h>
+@@ -29,6 +30,8 @@
+ struct tiadc_device {
+ struct ti_tscadc_dev *mfd_tscadc;
+ int channels;
++ char *buf;
++ struct iio_map *map;
+ };
+
+ static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
+@@ -75,25 +78,57 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+ {
+ struct iio_chan_spec *chan_array;
+- int i;
+-
+- indio_dev->num_channels = channels;
+- chan_array = kcalloc(indio_dev->num_channels,
+- sizeof(struct iio_chan_spec), GFP_KERNEL);
++ struct iio_chan_spec *chan;
++ char *s;
++ int i, len, size, ret;
+
++ size = indio_dev->num_channels * (sizeof(struct iio_chan_spec) + 6);
++ chan_array = kzalloc(size, GFP_KERNEL);
+ if (chan_array == NULL)
+ return -ENOMEM;
+
+- for (i = 0; i < (indio_dev->num_channels); i++) {
+- struct iio_chan_spec *chan = chan_array + i;
++ /* buffer space is after the array */
++ s = (char *)(chan_array + indio_dev->num_channels);
++ chan = chan_array;
++ for (i = 0; i < indio_dev->num_channels; i++, chan++, s += len + 1) {
++
++ len = sprintf(s, "AIN%d", i);
++
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+ chan->channel = i;
+- chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
++ chan->datasheet_name = s;
++ chan->scan_type.sign = 'u';
++ chan->scan_type.realbits = 12;
++ chan->scan_type.storagebits = 32;
++ chan->scan_type.shift = 0;
+ }
+
+ indio_dev->channels = chan_array;
+
++ size = (indio_dev->num_channels + 1) * sizeof(struct iio_map);
++ adc_dev->map = kzalloc(size, GFP_KERNEL);
++ if (adc_dev->map == NULL) {
++ kfree(chan_array);
++ return -ENOMEM;
++ }
++
++ for (i = 0; i < indio_dev->num_channels; i++) {
++ adc_dev->map[i].adc_channel_label = chan_array[i].datasheet_name;
++ adc_dev->map[i].consumer_dev_name = "any";
++ adc_dev->map[i].consumer_channel = chan_array[i].datasheet_name;
++ }
++ adc_dev->map[i].adc_channel_label = NULL;
++ adc_dev->map[i].consumer_dev_name = NULL;
++ adc_dev->map[i].consumer_channel = NULL;
++
++ ret = iio_map_array_register(indio_dev, adc_dev->map);
++ if (ret != 0) {
++ kfree(adc_dev->map);
++ kfree(chan_array);
++ return -ENOMEM;
++ }
++
+ return indio_dev->num_channels;
+ }
+
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index e947dd8..cbb8b70c 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -176,26 +176,38 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(tscadc, REG_CTRL, ctrl);
+
++ tscadc->used_cells = 0;
++ tscadc->tsc_cell = -1;
++ tscadc->adc_cell = -1;
++
+ /* TSC Cell */
+- cell = &tscadc->cells[TSC_CELL];
+- cell->name = "tsc";
+- cell->platform_data = tscadc;
+- cell->pdata_size = sizeof(*tscadc);
++ if (tsc_wires > 0) {
++ tscadc->tsc_cell = tscadc->used_cells;
++ cell = &tscadc->cells[tscadc->used_cells++];
++ cell->name = "tsc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++ }
+
+ /* ADC Cell */
+- cell = &tscadc->cells[ADC_CELL];
+- cell->name = "tiadc";
+- cell->platform_data = tscadc;
+- cell->pdata_size = sizeof(*tscadc);
++ if (adc_channels > 0) {
++ tscadc->adc_cell = tscadc->used_cells;
++ cell = &tscadc->cells[tscadc->used_cells++];
++ cell->name = "tiadc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++ }
+
+ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+- TSCADC_CELLS, NULL, 0, NULL);
++ tscadc->used_cells, NULL, 0, NULL);
+ if (err < 0)
+ goto err_disable_clk;
+
+ device_init_wakeup(&pdev->dev, true);
+ platform_set_drvdata(pdev, tscadc);
+
++ dev_info(&pdev->dev, "Initialized OK.\n");
++
+ return 0;
+
+ err_disable_clk:
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index 9624fea..50a245f 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -128,11 +128,6 @@
+
+ #define TSCADC_CELLS 2
+
+-enum tscadc_cells {
+- TSC_CELL,
+- ADC_CELL,
+-};
+-
+ struct mfd_tscadc_board {
+ struct tsc_data *tsc_init;
+ struct adc_data *adc_init;
+@@ -143,6 +138,9 @@ struct ti_tscadc_dev {
+ struct regmap *regmap_tscadc;
+ void __iomem *tscadc_base;
+ int irq;
++ int used_cells; /* 0-2 */
++ int tsc_cell; /* -1 if not used */
++ int adc_cell; /* -1 if not used */
+ struct mfd_cell cells[TSCADC_CELLS];
+
+ /* tsc device */
diff --git a/patches/linux-3.7-rc6/0057-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch b/patches/linux-3.7-rc6/0057-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch
new file mode 100644
index 0000000..645adc4
--- /dev/null
+++ b/patches/linux-3.7-rc6/0057-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch
@@ -0,0 +1,184 @@
+From e2ca20cc059c217cd78963a77189004645de55c7 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 26 Oct 2012 14:01:05 +0300
+Subject: [PATCH] ti_tscadc: Match mfd sub devices to regmap interface
+
+---
+ drivers/iio/adc/ti_am335x_adc.c | 27 +++++++++++++++++++--------
+ drivers/input/touchscreen/ti_am335x_tsc.c | 16 +++++++++++++---
+ drivers/mfd/ti_am335x_tscadc.c | 7 +++++--
+ 3 files changed, 37 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index d48fd79..5f325c1 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -23,7 +23,9 @@
+ #include <linux/iio/iio.h>
+ #include <linux/iio/machine.h>
+ #include <linux/iio/driver.h>
++#include <linux/regmap.h>
+
++#include <linux/io.h>
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/platform_data/ti_am335x_adc.h>
+
+@@ -36,13 +38,17 @@ struct tiadc_device {
+
+ static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
+ {
+- return readl(adc->mfd_tscadc->tscadc_base + reg);
++ unsigned int val;
++
++ val = (unsigned int)-1;
++ regmap_read(adc->mfd_tscadc->regmap_tscadc, reg, &val);
++ return val;
+ }
+
+ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
+ unsigned int val)
+ {
+- writel(val, adc->mfd_tscadc->tscadc_base + reg);
++ regmap_write(adc->mfd_tscadc->regmap_tscadc, reg, val);
+ }
+
+ static void tiadc_step_config(struct tiadc_device *adc_dev)
+@@ -75,22 +81,24 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+ }
+
+-static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
++static int tiadc_channel_init(struct iio_dev *indio_dev,
++ struct tiadc_device *adc_dev)
+ {
+ struct iio_chan_spec *chan_array;
+ struct iio_chan_spec *chan;
+ char *s;
+ int i, len, size, ret;
++ int channels = adc_dev->channels;
+
+- size = indio_dev->num_channels * (sizeof(struct iio_chan_spec) + 6);
++ size = channels * (sizeof(struct iio_chan_spec) + 6);
+ chan_array = kzalloc(size, GFP_KERNEL);
+ if (chan_array == NULL)
+ return -ENOMEM;
+
+ /* buffer space is after the array */
+- s = (char *)(chan_array + indio_dev->num_channels);
++ s = (char *)(chan_array + channels);
+ chan = chan_array;
+- for (i = 0; i < indio_dev->num_channels; i++, chan++, s += len + 1) {
++ for (i = 0; i < channels; i++, chan++, s += len + 1) {
+
+ len = sprintf(s, "AIN%d", i);
+
+@@ -105,8 +113,9 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+ }
+
+ indio_dev->channels = chan_array;
++ indio_dev->num_channels = channels;
+
+- size = (indio_dev->num_channels + 1) * sizeof(struct iio_map);
++ size = (channels + 1) * sizeof(struct iio_map);
+ adc_dev->map = kzalloc(size, GFP_KERNEL);
+ if (adc_dev->map == NULL) {
+ kfree(chan_array);
+@@ -203,7 +212,7 @@ static int __devinit tiadc_probe(struct platform_device *pdev)
+
+ tiadc_step_config(adc_dev);
+
+- err = tiadc_channel_init(indio_dev, adc_dev->channels);
++ err = tiadc_channel_init(indio_dev, adc_dev);
+ if (err < 0)
+ goto err_free_device;
+
+@@ -213,6 +222,8 @@ static int __devinit tiadc_probe(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, indio_dev);
+
++ dev_info(&pdev->dev, "Initialized\n");
++
+ return 0;
+
+ err_free_channels:
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 7a26810..d09e1a7 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -26,6 +26,7 @@
+ #include <linux/io.h>
+ #include <linux/input/ti_am335x_tsc.h>
+ #include <linux/delay.h>
++#include <linux/regmap.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+
+@@ -64,13 +65,17 @@ struct titsc {
+
+ static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+ {
+- return readl(ts->mfd_tscadc->tscadc_base + reg);
++ unsigned int val;
++
++ val = (unsigned int)-1;
++ regmap_read(ts->mfd_tscadc->regmap_tscadc, reg, &val);
++ return val;
+ }
+
+ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ unsigned int val)
+ {
+- writel(val, tsc->mfd_tscadc->tscadc_base + reg);
++ regmap_write(tsc->mfd_tscadc->regmap_tscadc, reg, val);
+ }
+
+ /*
+@@ -455,10 +460,15 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+
+ /* register to the input system */
+ err = input_register_device(input_dev);
+- if (err)
++ if (err) {
++ dev_err(&pdev->dev, "Failed to register input device\n");
+ goto err_free_irq;
++ }
+
+ platform_set_drvdata(pdev, ts_dev);
++
++ dev_info(&pdev->dev, "Initialized OK\n");
++
+ return 0;
+
+ err_free_irq:
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index cbb8b70c..4a7041c 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -31,6 +31,7 @@ static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
+ {
+ unsigned int val;
+
++ val = (unsigned int)-1;
+ regmap_read(tsadc->regmap_tscadc, reg, &val);
+ return val;
+ }
+@@ -68,7 +69,7 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ int irq;
+ int err, ctrl;
+ int clk_value, clock_rate;
+- int tsc_wires, adc_channels = 0, total_channels;
++ int tsc_wires = 0, adc_channels = 0, total_channels;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+@@ -78,7 +79,9 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ if (pdata->adc_init)
+ adc_channels = pdata->adc_init->adc_channels;
+
+- tsc_wires = pdata->tsc_init->wires;
++ if (pdata->tsc_init)
++ tsc_wires = pdata->tsc_init->wires;
++
+ total_channels = tsc_wires + adc_channels;
+
+ if (total_channels > 8) {
diff --git a/patches/linux-3.7-rc6/0059-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch b/patches/linux-3.7-rc6/0059-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch
new file mode 100644
index 0000000..a50a7c1
--- /dev/null
+++ b/patches/linux-3.7-rc6/0059-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch
@@ -0,0 +1,165 @@
+From ef11a2c0cc3cc0c1b8ea1d96a4ead994b0175f02 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 2 Jul 2012 13:51:39 +0530
+Subject: [PATCH] ARM: OMAP3+: hwmod: Corrects resource data for PWM devices.
+
+PWM device has common space + module specific part in AM335x. To access
+module specific part from module drivers, resource regions for PWM
+device rearranged to access module specific part with index 0. This
+helps module re-usability for platforms that didn't have config space
+support like Davinci. Also ADDR_TYPE_RT flag removed for module specific
+part.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 72 ++++++++++++++--------------
+ 1 file changed, 36 insertions(+), 36 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index f96bbc0..b6f78c1 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -2549,17 +2549,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
+ {
+- .pa_start = 0x48300000,
+- .pa_end = 0x48300000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48300200,
+ .pa_end = 0x48300200 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48300000,
++ .pa_end = 0x48300000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2575,17 +2575,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm0 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
+ {
+- .pa_start = 0x48302000,
+- .pa_end = 0x48302000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48302200,
+ .pa_end = 0x48302200 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48302000,
++ .pa_end = 0x48302000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2601,17 +2601,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm1 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
+ {
+- .pa_start = 0x48304000,
+- .pa_end = 0x48304000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48304200,
+ .pa_end = 0x48304200 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48304000,
++ .pa_end = 0x48304000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2627,17 +2627,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm2 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
+ {
+- .pa_start = 0x48300000,
+- .pa_end = 0x48300000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48300100,
+ .pa_end = 0x48300100 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48300000,
++ .pa_end = 0x48300000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2653,17 +2653,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap0 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ecap1_addr_space[] = {
+ {
+- .pa_start = 0x48302000,
+- .pa_end = 0x48302000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48302100,
+ .pa_end = 0x48302100 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48302000,
++ .pa_end = 0x48302000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2679,17 +2679,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap1 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
+ {
+- .pa_start = 0x48304000,
+- .pa_end = 0x48304000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48304100,
+ .pa_end = 0x48304100 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48304000,
++ .pa_end = 0x48304000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
diff --git a/patches/linux-3.7-rc6/0060-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch b/patches/linux-3.7-rc6/0060-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
new file mode 100644
index 0000000..4a6d3c3
--- /dev/null
+++ b/patches/linux-3.7-rc6/0060-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
@@ -0,0 +1,68 @@
+From 9deb78bb727ab7c632f240dc57af845f39e618c8 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 16 Jul 2012 14:59:41 +0530
+Subject: [PATCH] pwm_backlight: Add device tree support for Low Threshold
+ Brightness
+
+Low Threshold Brightness should be configured to have a linear relation
+in brightness scale. This patch adds device tree support for low
+threshold brightness as optional one for pwm_backlight.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ .../bindings/video/backlight/pwm-backlight.txt | 21 ++++++++++++++++++++
+ drivers/video/backlight/pwm_bl.c | 5 +++++
+ 2 files changed, 26 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+index 1e4fc72..689c7d2 100644
+--- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
++++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+@@ -14,6 +14,8 @@ Required properties:
+ Optional properties:
+ - pwm-names: a list of names for the PWM devices specified in the
+ "pwms" property (see PWM binding[0])
++ - low_threshold_brightness: brightness threshold low level. (get linear
++ scales in brightness in low end of brightness levels)
+
+ [0]: Documentation/devicetree/bindings/pwm/pwm.txt
+
+@@ -26,3 +28,22 @@ Example:
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ };
++
++Example for brightness_threshold_level:
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&pwm 0 50000>;
++
++ brightness-levels = <0 4 8 16 32 64 128 255>;
++ default-brightness-level = <6>;
++ low_threshold_brightness = <50>;
++ };
++};
++Note:
++Low threshold support is required to have linear brightness scale from
++0 to max. For some panels, backlight absent on low end of brightness
++scale. So support for Low Threshold been required. So that the scale of
++brightness changed from Low Threshold to Max in scales defined in
++brightness-levels. In this example 20% maximum brightness scale should
++be required to turn on panel backlight.
+diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
+index 069983c..0c91023 100644
+--- a/drivers/video/backlight/pwm_bl.c
++++ b/drivers/video/backlight/pwm_bl.c
+@@ -143,6 +143,11 @@ static int pwm_backlight_parse_dt(struct device *dev,
+
+ data->dft_brightness = value;
+ data->max_brightness--;
++
++ ret = of_property_read_u32(node, "low_threshold_brightness",
++ &value);
++ if (!ret)
++ data->lth_brightness = value;
+ }
+
+ /*
diff --git a/patches/linux-3.7-rc6/0061-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch b/patches/linux-3.7-rc6/0061-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch
new file mode 100644
index 0000000..1bf1097
--- /dev/null
+++ b/patches/linux-3.7-rc6/0061-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch
@@ -0,0 +1,120 @@
+From 6a9abd983cbbd369707b4b7edc3b9b45aa80a4b1 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Fri, 29 Jun 2012 10:52:57 +0530
+Subject: [PATCH] pwm: pwm-tiecap: Add device-tree binding support in APWM
+ driver
+
+Adds support for device-tree binding in ECAP APWM driver and custom
+of_xlate support. In custom of_xlate support, support for configuring
+polarity also been provided. This will provide configuration of ECAP
+APWM polarity from client drivers device-tree.
+Also size of pwm-cells set to 3 to support polarity configuration from
+device tree.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ Documentation/devicetree/bindings/pwm/ecap-pwm.txt | 24 ++++++++++++++
+ drivers/pwm/pwm-tiecap.c | 35 ++++++++++++++++++++
+ 2 files changed, 59 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+
+diff --git a/Documentation/devicetree/bindings/pwm/ecap-pwm.txt b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+new file mode 100644
+index 0000000..fa56534
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+@@ -0,0 +1,24 @@
++TI SOC ECAP based APWM controller
++
++Required properties:
++- compatible : Must be "ti, ecap"
++- ti,hwmods : Must be "ecap<n>", n being the instance number (0-based)
++- #pwm-cells: On ECAP the number of cells used to specify a PWM is 3. The
++ first cell specifies the per-chip index of the PWM to use, the second
++ cell is the period cycle in nanoseconds and the third cell is the
++ polarity of PWM output. Polarity 0 gives normal polarity and 1 gives
++ inversed polarity (inverse duty cycle)
++
++Note: Current implementation will fetch base address, irq and dma
++from omap hwmod data base during device registration.
++Future plan is to migrate hwmod data base contents into device tree
++blob so that, all the required data will be used from device tree dts
++file.
++
++Example:
++
++ ecap0: ecap@0 {
++ compatible = "ti, ecap";
++ ti,hwmods = "ecap0";
++ #pwm-cells = <3>;
++ };
+diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
+index d6d4cf0..d15941c 100644
+--- a/drivers/pwm/pwm-tiecap.c
++++ b/drivers/pwm/pwm-tiecap.c
+@@ -37,6 +37,8 @@
+ #define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6))
+ #define ECCTL2_TSCTR_FREERUN BIT(4)
+
++#define PWM_CELL_SIZE 3
++
+ struct ecap_pwm_chip {
+ struct pwm_chip chip;
+ unsigned int clk_rate;
+@@ -184,6 +186,26 @@ static const struct pwm_ops ecap_pwm_ops = {
+ .owner = THIS_MODULE,
+ };
+
++static struct pwm_device *of_ecap_xlate(struct pwm_chip *chip,
++ const struct of_phandle_args *args)
++{
++ struct pwm_device *pwm;
++
++ if (chip->of_pwm_n_cells < PWM_CELL_SIZE)
++ return ERR_PTR(-EINVAL);
++
++ if (args->args[0] >= chip->npwm)
++ return ERR_PTR(-EINVAL);
++
++ pwm = pwm_request_from_chip(chip, args->args[0], NULL);
++ if (IS_ERR(pwm))
++ return pwm;
++
++ pwm_set_period(pwm, args->args[1]);
++ pwm_set_polarity(pwm, args->args[2]);
++ return pwm;
++}
++
+ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+ {
+ int ret;
+@@ -211,6 +233,8 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+
+ pc->chip.dev = &pdev->dev;
+ pc->chip.ops = &ecap_pwm_ops;
++ pc->chip.of_xlate = of_ecap_xlate;
++ pc->chip.of_pwm_n_cells = PWM_CELL_SIZE;
+ pc->chip.base = -1;
+ pc->chip.npwm = 1;
+
+@@ -244,9 +268,20 @@ static int __devexit ecap_pwm_remove(struct platform_device *pdev)
+ return pwmchip_remove(&pc->chip);
+ }
+
++#if defined(CONFIG_OF)
++static const struct of_device_id omap_ecap_of_match[] = {
++ { .compatible = "ti,ecap" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, omap_ecap_of_match);
++#endif
++
+ static struct platform_driver ecap_pwm_driver = {
+ .driver = {
+ .name = "ecap",
++#if defined(CONFIG_OF)
++ .of_match_table = of_match_ptr(omap_ecap_of_match),
++#endif
+ },
+ .probe = ecap_pwm_probe,
+ .remove = __devexit_p(ecap_pwm_remove),
diff --git a/patches/linux-3.7-rc6/0062-Control-module-EHRPWM-clk-enabling.patch b/patches/linux-3.7-rc6/0062-Control-module-EHRPWM-clk-enabling.patch
new file mode 100644
index 0000000..6ea83fe
--- /dev/null
+++ b/patches/linux-3.7-rc6/0062-Control-module-EHRPWM-clk-enabling.patch
@@ -0,0 +1,43 @@
+From 6f3f226f97712e86991a805aa5e05e8734aa9f21 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 22 May 2012 11:34:58 +0530
+Subject: [PATCH] Control module : EHRPWM clk enabling
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/mach-omap2/devices.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index c72b5a7..9faecb9 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -434,6 +434,20 @@ static void omap_init_mcspi(void)
+ static inline void omap_init_mcspi(void) {}
+ #endif
+
++#include "cm33xx.h"
++
++int __init am33xx_register_ehrpwm(void)
++{
++ void __iomem *iobase;
++ unsigned short regword;
++
++ iobase = AM33XX_CM_REGADDR(0, 0x10664);
++ regword = readw(iobase);
++ regword |= 0x7;
++ writew(regword, iobase);
++ return 0;
++}
++
+ /**
+ * omap_init_rng - bind the RNG hwmod to the RNG omap_device
+ *
+@@ -720,6 +734,7 @@ static int __init omap2_init_devices(void)
+ omap_init_vout();
+ omap_init_ocp2scp();
+
++ am33xx_register_ehrpwm();
+ return 0;
+ }
+ arch_initcall(omap2_init_devices);
diff --git a/patches/linux-3.7-rc6/0063-pwm-pwm-tiecap-Enable-clock-gating.patch b/patches/linux-3.7-rc6/0063-pwm-pwm-tiecap-Enable-clock-gating.patch
new file mode 100644
index 0000000..8adb2c9
--- /dev/null
+++ b/patches/linux-3.7-rc6/0063-pwm-pwm-tiecap-Enable-clock-gating.patch
@@ -0,0 +1,102 @@
+From 33ed8e5aaf8a28e904bf0f3174cfc3a4cb3c5e50 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 24 Jul 2012 14:58:09 +0530
+Subject: [PATCH] pwm: pwm-tiecap: Enable clock gating
+
+In AM335x SOC, clock to PWM modules is gated in common config space.
+This commit adds support for enabling clock gating in the driver and
+leave it enabled if config space node is present.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ Documentation/devicetree/bindings/pwm/ecap-pwm.txt | 12 +++++++
+ drivers/pwm/pwm-tiecap.c | 37 +++++++++++++++++++-
+ 2 files changed, 48 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/pwm/ecap-pwm.txt b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+index fa56534..7d83587 100644
+--- a/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
++++ b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+@@ -9,6 +9,11 @@ Required properties:
+ polarity of PWM output. Polarity 0 gives normal polarity and 1 gives
+ inversed polarity (inverse duty cycle)
+
++Optional properties:
++- has_configspace: Some ECAP hardwares has config space memory region
++ to enable clock gating to individual modules. Adding this as optional
++ properties.
++
+ Note: Current implementation will fetch base address, irq and dma
+ from omap hwmod data base during device registration.
+ Future plan is to migrate hwmod data base contents into device tree
+@@ -22,3 +27,10 @@ Example:
+ ti,hwmods = "ecap0";
+ #pwm-cells = <3>;
+ };
++Example with has_configspace:
++ ecap0: ecap@0 {
++ compatible = "ti, ecap";
++ ti,hwmods = "ecap0";
++ #pwm-cells = <3>;
++ has_configspace = <1>;
++ };
+diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
+index d15941c..5b07707 100644
+--- a/drivers/pwm/pwm-tiecap.c
++++ b/drivers/pwm/pwm-tiecap.c
+@@ -206,12 +206,16 @@ static struct pwm_device *of_ecap_xlate(struct pwm_chip *chip,
+ return pwm;
+ }
+
++#define CLKCONFIG 8
++#define ECAP_CLK_EN 1
+ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+ {
+- int ret;
++ int ret, len;
+ struct resource *r;
+ struct clk *clk;
+ struct ecap_pwm_chip *pc;
++ void __iomem *mmio_base;
++ unsigned long regval;
+
+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc) {
+@@ -255,6 +259,37 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+ }
+
+ pm_runtime_enable(&pdev->dev);
++
++ /*
++ * Some IP's have config space and require special handling of
++ * clock gating from config space. So enabling clock gating
++ * at config space.
++ */
++ if (pdev->dev.of_node && of_find_property(pdev->dev.of_node,
++ "has_configspace", &len)) {
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ if (!r) {
++ pm_runtime_disable(&pdev->dev);
++ dev_err(&pdev->dev, "no memory resource defined\n");
++ return -ENODEV;
++ }
++
++ mmio_base = devm_ioremap(&pdev->dev, r->start,
++ resource_size(r));
++ if (!mmio_base) {
++ pm_runtime_disable(&pdev->dev);
++ dev_err(&pdev->dev, "failed to ioremap() registers\n");
++ return -EADDRNOTAVAIL;
++ }
++
++ pm_runtime_get_sync(&pdev->dev);
++ regval = readw(mmio_base + CLKCONFIG);
++ regval |= ECAP_CLK_EN;
++ writew(regval, mmio_base + CLKCONFIG);
++ pm_runtime_put_sync(&pdev->dev);
++ }
++
+ platform_set_drvdata(pdev, pc);
+ return 0;
+ }
diff --git a/patches/linux-3.7-rc6/0064-PWM-ti-ehrpwm-fix-up-merge-conflict.patch b/patches/linux-3.7-rc6/0064-PWM-ti-ehrpwm-fix-up-merge-conflict.patch
new file mode 100644
index 0000000..c036093
--- /dev/null
+++ b/patches/linux-3.7-rc6/0064-PWM-ti-ehrpwm-fix-up-merge-conflict.patch
@@ -0,0 +1,22 @@
+From f650c07353651edeb2f3b56fc5628ca48e60609d Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 17 Sep 2012 10:34:22 +0200
+Subject: [PATCH] PWM: ti-ehrpwm: fix up merge conflict
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/pwm/pwm-tiehrpwm.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index d3c1dff..288f93e 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -113,6 +113,7 @@ struct ehrpwm_pwm_chip {
+ struct pwm_chip chip;
+ unsigned int clk_rate;
+ void __iomem *mmio_base;
++ unsigned long duty_cycles;
+ unsigned long period_cycles[NUM_PWM_CHANNEL];
+ enum pwm_polarity polarity[NUM_PWM_CHANNEL];
+ };
diff --git a/patches/linux-3.7-rc6/0065-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch b/patches/linux-3.7-rc6/0065-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
new file mode 100644
index 0000000..1036f6d
--- /dev/null
+++ b/patches/linux-3.7-rc6/0065-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
@@ -0,0 +1,370 @@
+From a1655d02663d4cef923a9a75c60fb34f2e35c783 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 17 Jul 2012 21:35:11 +0530
+Subject: [PATCH] pwm: pwm_test: Driver support for PWM module testing
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ drivers/pwm/Kconfig | 11 ++
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/pwm_test.c | 322 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 334 insertions(+)
+ create mode 100644 drivers/pwm/pwm_test.c
+
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index ed81720..f1a0721 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -160,4 +160,15 @@ config PWM_VT8500
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-vt8500.
+
++config EHRPWM_TEST
++ tristate "EHRPWM TEST support"
++ depends on PWM_TIEHRPWM
++
++ help
++ Test driver support for the EHRPWM PWM driver found on AM33XX
++ TI SOC
++
++ To compile this driver as a module, choose M here: the module
++ will be called pwm_ehrpwm.
++
+ endif
+diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
+index acfe482..e2c6277 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -13,3 +13,4 @@ obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
+ obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o
+ obj-$(CONFIG_PWM_TWL6030) += pwm-twl6030.o
+ obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o
++obj-$(CONFIG_EHRPWM_TEST) += pwm_test.o
+diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c
+new file mode 100644
+index 0000000..d9948db
+--- /dev/null
++++ b/drivers/pwm/pwm_test.c
+@@ -0,0 +1,322 @@
++/*
++ * PWM Test driver
++ *
++ * Copyright (C) 2012 Texas Instruments.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pwm.h>
++#include <linux/slab.h>
++#include <linux/io.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/pm_runtime.h>
++
++struct pwm_test {
++ struct pwm_device *pwm;
++ int ret;
++ struct class *pwm_test_class;
++ unsigned long period, duty, run, polarity, config, requested;
++ unsigned long period_s, duty_s, run_s, polarity_s, config_s, requested_s;
++ struct device *dev;
++};
++
++static ssize_t pwm_test_show_duty(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%lu\n", pwm_test->duty);
++}
++
++static ssize_t pwm_test_store_duty(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->duty_s);
++ if (rc)
++ return rc;
++ return count;
++}
++
++static ssize_t pwm_test_show_period(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%lu\n", pwm_test->period);
++}
++
++static ssize_t pwm_test_store_period(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->period_s);
++ if (rc)
++ return rc;
++
++ return count;
++}
++
++static ssize_t pwm_test_show_config(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ if (pwm_test->config)
++ return sprintf(buf, "config Done\n");
++ else
++ return sprintf(buf, "config Failed\n");
++}
++static ssize_t pwm_test_store_config(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ int ret;
++
++ if (pwm_test->duty_s == 0) {
++ ret = pwm_config(pwm_test->pwm, 0, pwm_test->period_s);
++ if (ret) {
++ pwm_test->config = 0;
++ pr_err("operation failed %d\n", ret);
++ pwm_test->duty_s = pwm_test->duty;
++ pwm_test->period_s = pwm_test->period;
++ return ret;
++ }
++ pwm_test->duty = pwm_test->duty_s;
++ pwm_test->period = pwm_test->period_s;
++ pwm_test->config = 1;
++ } else {
++ ret = pwm_config(pwm_test->pwm, pwm_test->duty_s,
++ pwm_test->period_s);
++ if (ret) {
++ pwm_test->config = 0;
++ pr_err("operation failed %d\n", ret);
++ pwm_test->duty_s = pwm_test->duty;
++ pwm_test->period_s = pwm_test->period;
++ return ret;
++ }
++ pwm_test->duty = pwm_test->duty_s;
++ pwm_test->period = pwm_test->period_s;
++ pwm_test->config = 1;
++ }
++ return count;
++}
++
++static ssize_t pwm_test_show_run(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%s\n", pwm_test->run ? "Enabled" : "Disabled");
++}
++
++static ssize_t pwm_test_store_run(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->run_s);
++ if (rc)
++ return rc;
++
++ if (pwm_test->run_s)
++ rc = pwm_enable(pwm_test->pwm);
++ else
++ pwm_disable(pwm_test->pwm);
++
++ if (rc) {
++ pr_err("operation failed %d\n", rc);
++ pwm_test->run_s = pwm_test->run;
++ return rc;
++ }
++
++ pwm_test->run = pwm_test->run_s;
++ return count;
++}
++
++static ssize_t pwm_test_show_polarity(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%s\n",
++ pwm_test->polarity ? "Polarity Inversed" :
++ "Polarity Normal");
++}
++
++static ssize_t pwm_test_store_polarity(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->polarity_s);
++ if (rc)
++ return rc;
++
++ rc = pwm_set_polarity(pwm_test->pwm, pwm_test->polarity_s);
++ if (rc) {
++ pr_err("operation failed %d\n", rc);
++ return rc;
++ }
++
++ pwm_test->polarity = pwm_test->polarity_s;
++ return count;
++}
++
++static ssize_t pwm_test_show_request(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%s\n", pwm_test->requested ? "Requested" : "Freed");
++}
++
++static ssize_t pwm_test_store_request(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->requested_s);
++ if (rc)
++ return rc;
++
++ if (pwm_test->requested_s) {
++ pwm_test->pwm = pwm_get(dev, NULL);
++
++ if (IS_ERR(pwm_test->pwm)) {
++ dev_err(dev, "%s() %d %ld\n", __func__, __LINE__,
++ PTR_ERR(pwm_test->pwm));
++ rc = -EINVAL;
++ }
++ } else {
++ pwm_free(pwm_test->pwm);
++ pwm_test->polarity = 0;
++ pwm_test->run = 0;
++ pwm_test->duty = 0;
++ pwm_test->period = 0;
++ pwm_test->config = 0;
++ pwm_test->polarity_s = 0;
++ pwm_test->run_s = 0;
++ pwm_test->duty_s = 0;
++ pwm_test->period_s = 0;
++ pwm_test->config_s = 0;
++ rc = 0;
++ }
++
++ if (rc) {
++ pr_err("operation failed %d\n", rc);
++ pwm_test->requested_s = pwm_test->requested;
++ return rc;
++ }
++
++ pwm_test->requested = pwm_test->requested_s;
++ return count;
++}
++
++static DEVICE_ATTR(duty, 0644, pwm_test_show_duty, pwm_test_store_duty);
++static DEVICE_ATTR(period, 0644, pwm_test_show_period, pwm_test_store_period);
++static DEVICE_ATTR(polarity, 0644, pwm_test_show_polarity,
++ pwm_test_store_polarity);
++static DEVICE_ATTR(config, 0644 , pwm_test_show_config, pwm_test_store_config);
++static DEVICE_ATTR(run, 0644 , pwm_test_show_run, pwm_test_store_run);
++static DEVICE_ATTR(request, 0644 , pwm_test_show_request, pwm_test_store_request);
++
++static const struct attribute *pwm_attrs[] = {
++ &dev_attr_duty.attr,
++ &dev_attr_period.attr,
++ &dev_attr_config.attr,
++ &dev_attr_run.attr,
++ &dev_attr_request.attr,
++ &dev_attr_polarity.attr,
++ NULL,
++};
++
++static const struct attribute_group pwm_device_attr_group = {
++ .attrs = (struct attribute **) pwm_attrs,
++};
++
++static int __init pwm_test_class_init(struct device *dev)
++{
++ if (sysfs_create_group(&dev->kobj, &pwm_device_attr_group))
++ return 1;
++ return 0;
++}
++
++static int pwm_test_probe(struct platform_device *pdev)
++{
++ struct pwm_test *pwm_test;
++
++ pwm_test = devm_kzalloc(&pdev->dev, sizeof(*pwm_test), GFP_KERNEL);
++
++ if (!pwm_test) {
++ dev_err(&pdev->dev, "memory error\n");
++ return -ENOMEM;
++ }
++
++ if (pwm_test_class_init(&pdev->dev)) {
++ dev_err(&pdev->dev, "sysfs creation failed\n");
++ return -EINVAL;
++ }
++ dev_set_drvdata(&pdev->dev, pwm_test);
++ platform_set_drvdata(pdev, pwm_test);
++ return 0;
++}
++
++static int pwm_test_remove(struct platform_device *pdev)
++{
++ struct pwm_test *pwm_test = platform_get_drvdata(pdev);
++
++ if (!pwm_test->ret) {
++ pwm_config(pwm_test->pwm, 0, 0x1000);
++ pwm_disable(pwm_test->pwm);
++ pr_emerg("PWM Device Disabled %s\n", dev_name(&pdev->dev));
++ }
++ if (pwm_test->requested)
++ pwm_free(pwm_test->pwm);
++
++ pr_emerg("PWM Device Freed %s\n", dev_name(&pdev->dev));
++ pwm_test->run = 0;
++ sysfs_remove_group(&pdev->dev.kobj, &pwm_device_attr_group);
++ return 0;
++}
++
++static struct of_device_id pwm_test_of_match[] = {
++ { .compatible = "pwm_test" },
++ { }
++};
++
++MODULE_DEVICE_TABLE(of, pwm_test_of_match);
++
++static struct platform_driver pwm_test_driver = {
++ .driver = {
++ .name = "pwm_test",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(pwm_test_of_match),
++ },
++ .probe = pwm_test_probe,
++ .remove = pwm_test_remove,
++};
++
++module_platform_driver(pwm_test_driver);
++
++MODULE_DESCRIPTION("pwm_test Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pwm_test");
diff --git a/patches/linux-3.7-rc6/0066-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch b/patches/linux-3.7-rc6/0066-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch
new file mode 100644
index 0000000..a4ff6bd
--- /dev/null
+++ b/patches/linux-3.7-rc6/0066-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch
@@ -0,0 +1,84 @@
+From 335aa3e5347097e0ef7ba046e59d9bb9cffa8a48 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Wed, 11 Jul 2012 11:01:33 +0530
+Subject: [PATCH] arm/dts: DT support for EHRPWM and ECAP device.
+
+Adds DT support for EHRPWM and ECAP APWM device. Also sets size of
+pwm-cells to 3 to support - <PWM instance number>, <PWM period> in
+nano-seconds and <PWM polarity>.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 60 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 60 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 9755276..433065e 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -376,5 +376,65 @@
+ };
+
+ };
++
++ ehrpwm0: ehrpwm@48300200 {
++ compatible = "ti,omap2-ehrpwm";
++ reg = <0x48300200 0x100 0x48300000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <86 58>;
++ ti,hwmods = "ehrpwm0";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ehrpwm1: ehrpwm@48302200 {
++ compatible = "ti,omap2-ehrpwm";
++ reg = <0x48302200 0x100 0x48302000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <87 59>;
++ ti,hwmods = "ehrpwm1";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ehrpwm2: ehrpwm@48304200 {
++ compatible = "ti,omap2-ehrpwm";
++ reg = <0x48304200 0x100 0x48304000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <39 60>;
++ ti,hwmods = "ehrpwm2";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ecap0: ecap@48300100 {
++ compatible = "ti,omap2-ecap";
++ reg = <0x48300100 0x80 0x48300000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <31>;
++ ti,hwmods = "ecap0";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ecap1: ecap@48302100 {
++ compatible = "ti,omap2-ecap";
++ reg = <0x48302100 0x80 0x48302000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <47>;
++ ti,hwmods = "ecap1";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ecap2: ecap@48304100 {
++ compatible = "ti,omap2-ecap";
++ reg = <0x48304100 0x80 0x48304000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <61>;
++ ti,hwmods = "ecap2";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
+ };
+ };
diff --git a/patches/linux-3.7-rc6/0067-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch b/patches/linux-3.7-rc6/0067-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch
new file mode 100644
index 0000000..4da3741
--- /dev/null
+++ b/patches/linux-3.7-rc6/0067-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch
@@ -0,0 +1,122 @@
+From 2d9a549a27aad6c8a87878c3620e1c0812af8da1 Mon Sep 17 00:00:00 2001
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 2 Jul 2012 14:03:53 +0530
+Subject: [PATCH] pwm: pwm-tiehrpwm: Add device-tree binding support EHRPWM
+ driver
+
+Adds device-tree binding support in EHRWPM driver and custom of_xlate
+support. In custom of_xlate support, support for configuring polarity
+also been provided. This will provide configuration of EHRPWM polarity
+from client drivers device-tree.
+Also size of pwm-cells set to 3 to support polarity configuration from
+device tree.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+
+Conflicts:
+ drivers/pwm/pwm-tiehrpwm.c
+---
+ .../devicetree/bindings/pwm/ehrpwm-pwm.txt | 24 ++++++++++++++
+ drivers/pwm/pwm-tiehrpwm.c | 34 ++++++++++++++++++++
+ 2 files changed, 58 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt
+
+diff --git a/Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt b/Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt
+new file mode 100644
+index 0000000..a11543c
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt
+@@ -0,0 +1,24 @@
++TI SOC EHRPWM based PWM controller
++
++Required properties:
++- compatible : Must be "ti, ehrpwm"
++- ti,hwmods : Must be "ehrpwm<n>", n being the instance number (0-based)
++- #pwm-cells: On EHRPWM the number of cells used to specify a PWM is 3. The
++ first cell specifies the per-chip index of the PWM to use, the second
++ cell is the period cycle in nanoseconds and the third cell is the
++ polarity of PWM output. Polarity 0 gives normal polarity and 1 gives
++ inversed polarity (inverse duty cycle)
++
++Note: Current implementation will fetch base address, irq and dma
++from omap hwmod data base during device registration.
++Future plan is to migrate hwmod data base contents into device tree
++blob so that, all the required data will be used from device tree dts
++file.
++
++Example:
++
++ ehrpwm0: ehrpwm@0 {
++ compatible = "ti, ehrpwm";
++ ti,hwmods = "ehrpwm0";
++ #pwm-cells = <3>;
++ };
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index 288f93e..4f1e467 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -108,6 +108,7 @@
+ #define AQCSFRC_CSFA_DISSWFRC (BIT(1) | BIT(0))
+
+ #define NUM_PWM_CHANNEL 2 /* EHRPWM channels */
++#define PWM_CELL_SIZE 3
+
+ struct ehrpwm_pwm_chip {
+ struct pwm_chip chip;
+@@ -393,6 +394,26 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
+ .owner = THIS_MODULE,
+ };
+
++static struct pwm_device *of_ehrpwm_xlate(struct pwm_chip *chip,
++ const struct of_phandle_args *args)
++{
++ struct pwm_device *pwm;
++
++ if (chip->of_pwm_n_cells < PWM_CELL_SIZE)
++ return ERR_PTR(-EINVAL);
++
++ if (args->args[0] >= chip->npwm)
++ return ERR_PTR(-EINVAL);
++
++ pwm = pwm_request_from_chip(chip, args->args[0], NULL);
++ if (IS_ERR(pwm))
++ return pwm;
++
++ pwm_set_period(pwm, args->args[1]);
++ pwm_set_polarity(pwm, args->args[2]);
++ return pwm;
++}
++
+ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
+ {
+ int ret;
+@@ -420,6 +441,8 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
+
+ pc->chip.dev = &pdev->dev;
+ pc->chip.ops = &ehrpwm_pwm_ops;
++ pc->chip.of_xlate = of_ehrpwm_xlate;
++ pc->chip.of_pwm_n_cells = PWM_CELL_SIZE;
+ pc->chip.base = -1;
+ pc->chip.npwm = NUM_PWM_CHANNEL;
+
+@@ -453,9 +476,20 @@ static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)
+ return pwmchip_remove(&pc->chip);
+ }
+
++#if defined(CONFIG_OF)
++static const struct of_device_id omap_ehrpwm_of_match[] = {
++ { .compatible = "ti,omap2-ehrpwm" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, omap_ehrpwm_of_match);
++#endif
++
+ static struct platform_driver ehrpwm_pwm_driver = {
+ .driver = {
+ .name = "ehrpwm",
++#if defined(CONFIG_OF)
++ .of_match_table = of_match_ptr(omap_ehrpwm_of_match),
++#endif
+ },
+ .probe = ehrpwm_pwm_probe,
+ .remove = __devexit_p(ehrpwm_pwm_remove),
diff --git a/patches/linux-3.7-rc6/0069-pinctrl-pinctrl-single-must-be-initialized-early.patch b/patches/linux-3.7-rc6/0069-pinctrl-pinctrl-single-must-be-initialized-early.patch
new file mode 100644
index 0000000..0862d29
--- /dev/null
+++ b/patches/linux-3.7-rc6/0069-pinctrl-pinctrl-single-must-be-initialized-early.patch
@@ -0,0 +1,35 @@
+From 3a0f046cac46f4b1cc0a8e544dba30afcae91f3d Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 15 Sep 2012 12:00:41 +0300
+Subject: [PATCH] pinctrl: pinctrl-single must be initialized early.
+
+When using pinctrl-single to handle i2c initialization, it has
+to be done early. Whether this is the best way to do so, is an
+exercise left to the reader.
+---
+ drivers/pinctrl/pinctrl-single.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
+index 726a729..2b258c3 100644
+--- a/drivers/pinctrl/pinctrl-single.c
++++ b/drivers/pinctrl/pinctrl-single.c
+@@ -1014,7 +1014,17 @@ static struct platform_driver pcs_driver = {
+ },
+ };
+
+-module_platform_driver(pcs_driver);
++static int __init pcs_init(void)
++{
++ return platform_driver_register(&pcs_driver);
++}
++postcore_initcall(pcs_init);
++
++static void __exit pcs_exit(void)
++{
++ platform_driver_unregister(&pcs_driver);
++}
++module_exit(pcs_exit);
+
+ MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+ MODULE_DESCRIPTION("One-register-per-pin type device tree based pinctrl driver");
diff --git a/patches/linux-3.7-rc6/0070-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch b/patches/linux-3.7-rc6/0070-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
new file mode 100644
index 0000000..4472434
--- /dev/null
+++ b/patches/linux-3.7-rc6/0070-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
@@ -0,0 +1,94 @@
+From cc8421dbb5b79561a93b29d4f29959f61471757e Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 15 Sep 2012 12:05:04 +0300
+Subject: [PATCH] Bone DTS working i2c2 (i2c3 in the tree)
+
+---
+ arch/arm/boot/dts/am335x-bone.dts | 60 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 50 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 87686e9..d1c21ba 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -52,6 +52,12 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++ i2c3_pins: pinmux_i2c3_pins {
++ pinctrl-single,pins = <
++ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -92,16 +98,6 @@
+ };
+ };
+
+- i2c1: i2c@44e0b000 {
+- status = "okay";
+- clock-frequency = <400000>;
+-
+- tps: tps@24 {
+- reg = <0x24>;
+- };
+-
+- };
+-
+ gpevt {
+ compatible = "gpevt";
+ pinctrl-names = "default";
+@@ -113,6 +109,50 @@
+ };
+ };
+
++&i2c1 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ tps: tps@24 {
++ reg = <0x24>;
++ };
++
++ baseboard_eeprom: baseboard_eeprom@50 {
++ compatible = "at,24c256";
++ reg = <0x50>;
++ };
++
++};
++
++&i2c3 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c3_pins>;
++
++ clock-frequency = <100000>;
++
++ /* OK, I know these are cape but for now it will do */
++ cape_eeprom_0: cape_eeprom_0@54 {
++ compatible = "at,24c256";
++ reg = <0x54>;
++ };
++
++ cape_eeprom_1: cape_eeprom_1@55 {
++ compatible = "at,24c256";
++ reg = <0x55>;
++ };
++
++ cape_eeprom_2: cape_eeprom_2@56 {
++ compatible = "at,24c256";
++ reg = <0x56>;
++ };
++
++ cape_eeprom_3: cape_eeprom_3@57 {
++ compatible = "at,24c256";
++ reg = <0x57>;
++ };
++};
++
+ /include/ "tps65217.dtsi"
+
+ &tps {
diff --git a/patches/linux-3.7-rc6/0071-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch b/patches/linux-3.7-rc6/0071-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
new file mode 100644
index 0000000..007caf1
--- /dev/null
+++ b/patches/linux-3.7-rc6/0071-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
@@ -0,0 +1,107 @@
+From bd2807f5f8e0cf858f95e7d930de4aec2d753d4c Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 15 Sep 2012 14:49:11 +0300
+Subject: [PATCH] am33xx: Convert I2C from omap to am33xx names
+
+On OMAP the TRM names I2C instances as i2c1, i2c2, etc.
+On the am33xx's it is i2c0, i2c1, etc.
+
+Use am33xx naming everywhere, beside the hwmod name.
+---
+ arch/arm/boot/dts/am335x-bone.dts | 8 ++++----
+ arch/arm/boot/dts/am335x-evm.dts | 2 +-
+ arch/arm/boot/dts/am33xx.dtsi | 12 ++++++------
+ 3 files changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index d1c21ba..1daf1af 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -52,7 +52,7 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
+- i2c3_pins: pinmux_i2c3_pins {
++ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+@@ -109,7 +109,7 @@
+ };
+ };
+
+-&i2c1 {
++&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+@@ -124,10 +124,10 @@
+
+ };
+
+-&i2c3 {
++&i2c2 {
+ status = "okay";
+ pinctrl-names = "default";
+- pinctrl-0 = <&i2c3_pins>;
++ pinctrl-0 = <&i2c2_pins>;
+
+ clock-frequency = <100000>;
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 43e23a8..6032648 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -29,7 +29,7 @@
+ status = "okay";
+ };
+
+- i2c1: i2c@44e0b000 {
++ i2c0: i2c@44e0b000 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 433065e..535a66c 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -225,33 +225,33 @@
+ status = "disabled";
+ };
+
+- i2c1: i2c@44e0b000 {
++ i2c0: i2c@44e0b000 {
+ compatible = "ti,omap4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- ti,hwmods = "i2c1";
++ ti,hwmods = "i2c1"; /* TODO: Fix hwmod */
+ reg = <0x44e0b000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <70>;
+ status = "disabled";
+ };
+
+- i2c2: i2c@4802a000 {
++ i2c1: i2c@4802a000 {
+ compatible = "ti,omap4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- ti,hwmods = "i2c2";
++ ti,hwmods = "i2c2"; /* TODO: Fix hwmod */
+ reg = <0x4802a000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <71>;
+ status = "disabled";
+ };
+
+- i2c3: i2c@4819c000 {
++ i2c2: i2c@4819c000 {
+ compatible = "ti,omap4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- ti,hwmods = "i2c3";
++ ti,hwmods = "i2c3"; /* TODO: Fix hwmod */
+ reg = <0x4819c000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <30>;
diff --git a/patches/linux-3.7-rc6/0072-beaglebone-fix-backlight-entry-in-DT.patch b/patches/linux-3.7-rc6/0072-beaglebone-fix-backlight-entry-in-DT.patch
new file mode 100644
index 0000000..58f62c9
--- /dev/null
+++ b/patches/linux-3.7-rc6/0072-beaglebone-fix-backlight-entry-in-DT.patch
@@ -0,0 +1,29 @@
+From b1eb01e79784564526df857c50491fcd47a124b5 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 18 Sep 2012 11:23:47 +0200
+Subject: [PATCH] beaglebone: fix backlight entry in DT
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 1daf1af..667842d 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -107,6 +107,14 @@
+ gpio-evt = <&gpio3 2 0>;
+ };
+ };
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "st7735fb";
++ brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
++ default-brightness-level = <50>; /* index to the array above */
++ };
+ };
+
+ &i2c0 {
diff --git a/patches/linux-3.7-rc6/0074-Shut-up-musb.patch b/patches/linux-3.7-rc6/0074-Shut-up-musb.patch
new file mode 100644
index 0000000..e533862
--- /dev/null
+++ b/patches/linux-3.7-rc6/0074-Shut-up-musb.patch
@@ -0,0 +1,24 @@
+From f52622777ab0362a9b6abe4a781ea3138285cb91 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 4 Oct 2012 12:02:13 +0300
+Subject: [PATCH] Shut up musb!
+
+---
+ drivers/usb/musb/musb_host.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 3df6a76..f43b55c 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -2432,8 +2432,10 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
+ }
+
+ if (musb->is_active) {
++#if 0
+ WARNING("trying to suspend as %s while active\n",
+ otg_state_string(musb->xceiv->state));
++#endif
+ return -EBUSY;
+ } else
+ return 0;
diff --git a/patches/linux-3.7-rc6/0075-musb-Fix-crashes-and-other-weirdness.patch b/patches/linux-3.7-rc6/0075-musb-Fix-crashes-and-other-weirdness.patch
new file mode 100644
index 0000000..6febda8
--- /dev/null
+++ b/patches/linux-3.7-rc6/0075-musb-Fix-crashes-and-other-weirdness.patch
@@ -0,0 +1,46 @@
+From 51880a937820eeb67105545a7202668c1b2a4663 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 4 Oct 2012 17:53:53 +0300
+Subject: [PATCH] musb: Fix crashes, and other weirdness.
+
+---
+ arch/arm/boot/dts/am33xx.dtsi | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 535a66c..9bb71cb 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -285,6 +285,32 @@
+ status = "disabled";
+ };
+
++ usb0_phy: phy0 {
++ compatible = "nop-xceiv-usb";
++ };
++
++ usb1_phy: phy1 {
++ compatible = "nop-xceiv-usb";
++ };
++
++ usb_otg_hs: usb_otg_hs {
++ compatible = "ti,musb-am33xx";
++ ti,hwmods = "usb_otg_hs";
++ multipoint = <1>;
++ num-eps = <16>;
++ ram-bits = <12>;
++ port0-mode = <3>;
++ port1-mode = <1>;
++ power = <250>;
++ usb0-phy = <&usb0_phy>;
++ usb1-phy = <&usb1_phy>;
++ };
++
++ rtc {
++ compatible = "ti,da830-rtc";
++ ti,hwmods = "rtc";
++ };
++
+ spi0: spi@48030000 {
+ compatible = "ti,omap4-mcspi";
+ ti,hwmods = "spi0";
diff --git a/patches/linux-3.7-rc6/0076-musb-revert-parts-of-032ec49f.patch b/patches/linux-3.7-rc6/0076-musb-revert-parts-of-032ec49f.patch
new file mode 100644
index 0000000..6b3083e
--- /dev/null
+++ b/patches/linux-3.7-rc6/0076-musb-revert-parts-of-032ec49f.patch
@@ -0,0 +1,371 @@
+From 482b626629b125679eab02d90e067e1223201506 Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Wed, 17 Oct 2012 15:34:24 +0200
+Subject: [PATCH] musb: revert parts of 032ec49f
+
+This reverts parts of commit 032ec49f ("usb: musb: drop useless
+board_mode usage") to get USB host mode working again.
+---
+ drivers/usb/musb/musb_core.c | 210 ++++++++++++++++++++++++++++--------------
+ drivers/usb/musb/musb_core.h | 5 +
+ 2 files changed, 144 insertions(+), 71 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index bb56a0e..8621fca 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -681,7 +681,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ musb_g_suspend(musb);
+- musb->is_active = otg->gadget->b_hnp_enable;
++ musb->is_active = is_otg_enabled(musb)
++ && otg->gadget->b_hnp_enable;
+ if (musb->is_active) {
+ musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
+@@ -697,7 +698,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ break;
+ case OTG_STATE_A_HOST:
+ musb->xceiv->state = OTG_STATE_A_SUSPEND;
+- musb->is_active = otg->host->b_hnp_enable;
++ musb->is_active = is_otg_enabled(musb)
++ && otg->host->b_hnp_enable;
+ break;
+ case OTG_STATE_B_HOST:
+ /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
+@@ -785,7 +787,7 @@ b_host:
+ case OTG_STATE_A_SUSPEND:
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ musb_root_disconnect(musb);
+- if (musb->a_wait_bcon != 0)
++ if (musb->a_wait_bcon != 0 && is_otg_enabled(musb))
+ musb_platform_try_idle(musb, jiffies
+ + msecs_to_jiffies(musb->a_wait_bcon));
+ break;
+@@ -961,16 +963,25 @@ void musb_start(struct musb *musb)
+ devctl = musb_readb(regs, MUSB_DEVCTL);
+ devctl &= ~MUSB_DEVCTL_SESSION;
+
+- /* session started after:
+- * (a) ID-grounded irq, host mode;
+- * (b) vbus present/connect IRQ, peripheral mode;
+- * (c) peripheral initiates, using SRP
+- */
+- if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+- musb->is_active = 1;
+- else
++ if (is_otg_enabled(musb)) {
++ /* session started after:
++ * (a) ID-grounded irq, host mode;
++ * (b) vbus present/connect IRQ, peripheral mode;
++ * (c) peripheral initiates, using SRP
++ */
++ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
++ musb->is_active = 1;
++ else
++ devctl |= MUSB_DEVCTL_SESSION;
++
++ } else if (is_host_enabled(musb)) {
++ /* assume ID pin is hard-wired to ground */
+ devctl |= MUSB_DEVCTL_SESSION;
+
++ } else /* peripheral is enabled */ {
++ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
++ musb->is_active = 1;
++ }
+ musb_platform_enable(musb);
+ musb_writeb(regs, MUSB_DEVCTL, devctl);
+ }
+@@ -1034,6 +1045,8 @@ static void musb_shutdown(struct platform_device *pdev)
+ musb_generic_disable(musb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+
++ if (!is_otg_enabled(musb) && is_host_enabled(musb))
++ usb_remove_hcd(musb_to_hcd(musb));
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ musb_platform_exit(musb);
+
+@@ -1891,7 +1904,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ int status;
+ struct musb *musb;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct usb_hcd *hcd;
+
+ /* The driver might handle more features than the board; OK.
+ * Fail when the board needs a feature that's not enabled.
+@@ -1914,6 +1926,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ pm_runtime_enable(musb->controller);
+
+ spin_lock_init(&musb->lock);
++ musb->board_mode = plat->mode;
+ musb->board_set_power = plat->set_power;
+ musb->min_power = plat->min_power;
+ musb->ops = plat->platform_ops;
+@@ -1984,7 +1997,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ goto fail3;
+ }
+ musb->nIrq = nIrq;
+- /* FIXME this handles wakeup irqs wrong */
++/* FIXME this handles wakeup irqs wrong */
+ if (enable_irq_wake(nIrq) == 0) {
+ musb->irq_wake = 1;
+ device_init_wakeup(dev, 1);
+@@ -1993,25 +2006,58 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ }
+
+ /* host side needs more setup */
+- hcd = musb_to_hcd(musb);
+- otg_set_host(musb->xceiv->otg, &hcd->self);
+- hcd->self.otg_port = 1;
+- musb->xceiv->otg->host = &hcd->self;
+- hcd->power_budget = 2 * (plat->power ? : 250);
+-
+- /* program PHY to use external vBus if required */
+- if (plat->extvbus) {
+- u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
+- busctl |= MUSB_ULPI_USE_EXTVBUS;
+- musb_write_ulpi_buscontrol(musb->mregs, busctl);
++ if (is_host_enabled(musb)) {
++ struct usb_hcd *hcd = musb_to_hcd(musb);
++
++ otg_set_host(musb->xceiv->otg, &hcd->self);
++
++ if (is_otg_enabled(musb))
++ hcd->self.otg_port = 1;
++ musb->xceiv->otg->host = &hcd->self;
++ hcd->power_budget = 2 * (plat->power ? : 250);
++
++ /* program PHY to use external vBus if required */
++ if (plat->extvbus) {
++ u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
++ busctl |= MUSB_ULPI_USE_EXTVBUS;
++ musb_write_ulpi_buscontrol(musb->mregs, busctl);
++ }
+ }
+
+- MUSB_DEV_MODE(musb);
+- musb->xceiv->otg->default_a = 0;
+- musb->xceiv->state = OTG_STATE_B_IDLE;
++ /* For the host-only role, we can activate right away.
++ * (We expect the ID pin to be forcibly grounded!!)
++ * Otherwise, wait till the gadget driver hooks up.
++ */
++ if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
++ struct usb_hcd *hcd = musb_to_hcd(musb);
++
++ MUSB_HST_MODE(musb);
++ musb->xceiv->otg->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
++
++ status = usb_add_hcd(musb_to_hcd(musb), 0, 0);
++
++ hcd->self.uses_pio_for_control = 1;
++ dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n",
++ "HOST", status,
++ musb_readb(musb->mregs, MUSB_DEVCTL),
++ (musb_readb(musb->mregs, MUSB_DEVCTL)
++ & MUSB_DEVCTL_BDEVICE
++ ? 'B' : 'A'));
++
++ } else /* peripheral is enabled */ {
++ MUSB_DEV_MODE(musb);
++ musb->xceiv->otg->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
++
++ status = musb_gadget_setup(musb);
+
+- status = musb_gadget_setup(musb);
++ dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n",
++ is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
++ status,
++ musb_readb(musb->mregs, MUSB_DEVCTL));
+
++ }
+ if (status < 0)
+ goto fail3;
+
+@@ -2027,13 +2073,28 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+
+ pm_runtime_put(musb->controller);
+
++ dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
++ ({char *s;
++ switch (musb->board_mode) {
++ case MUSB_HOST: s = "Host"; break;
++ case MUSB_PERIPHERAL: s = "Peripheral"; break;
++ default: s = "OTG"; break;
++ }; s; }),
++ ctrl,
++ (is_dma_capable() && musb->dma_controller)
++ ? "DMA" : "PIO",
++ musb->nIrq);
++
+ return 0;
+
+ fail5:
+ musb_exit_debugfs(musb);
+
+ fail4:
+- musb_gadget_cleanup(musb);
++ if (!is_otg_enabled(musb) && is_host_enabled(musb))
++ usb_remove_hcd(musb_to_hcd(musb));
++ else
++ musb_gadget_cleanup(musb);
+
+ fail3:
+ pm_runtime_put_sync(musb->controller);
+@@ -2116,9 +2177,11 @@ static void musb_save_context(struct musb *musb)
+ void __iomem *musb_base = musb->mregs;
+ void __iomem *epio;
+
+- musb->context.frame = musb_readw(musb_base, MUSB_FRAME);
+- musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
+- musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
++ if (is_host_enabled(musb)) {
++ musb->context.frame = musb_readw(musb_base, MUSB_FRAME);
++ musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
++ musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
++ }
+ musb->context.power = musb_readb(musb_base, MUSB_POWER);
+ musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
+ musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
+@@ -2157,29 +2220,30 @@ static void musb_save_context(struct musb *musb)
+ musb->context.index_regs[i].rxfifosz =
+ musb_read_rxfifosz(musb_base);
+ }
+-
+- musb->context.index_regs[i].txtype =
+- musb_readb(epio, MUSB_TXTYPE);
+- musb->context.index_regs[i].txinterval =
+- musb_readb(epio, MUSB_TXINTERVAL);
+- musb->context.index_regs[i].rxtype =
+- musb_readb(epio, MUSB_RXTYPE);
+- musb->context.index_regs[i].rxinterval =
+- musb_readb(epio, MUSB_RXINTERVAL);
+-
+- musb->context.index_regs[i].txfunaddr =
+- musb_read_txfunaddr(musb_base, i);
+- musb->context.index_regs[i].txhubaddr =
+- musb_read_txhubaddr(musb_base, i);
+- musb->context.index_regs[i].txhubport =
+- musb_read_txhubport(musb_base, i);
+-
+- musb->context.index_regs[i].rxfunaddr =
+- musb_read_rxfunaddr(musb_base, i);
+- musb->context.index_regs[i].rxhubaddr =
+- musb_read_rxhubaddr(musb_base, i);
+- musb->context.index_regs[i].rxhubport =
+- musb_read_rxhubport(musb_base, i);
++ if (is_host_enabled(musb)) {
++ musb->context.index_regs[i].txtype =
++ musb_readb(epio, MUSB_TXTYPE);
++ musb->context.index_regs[i].txinterval =
++ musb_readb(epio, MUSB_TXINTERVAL);
++ musb->context.index_regs[i].rxtype =
++ musb_readb(epio, MUSB_RXTYPE);
++ musb->context.index_regs[i].rxinterval =
++ musb_readb(epio, MUSB_RXINTERVAL);
++
++ musb->context.index_regs[i].txfunaddr =
++ musb_read_txfunaddr(musb_base, i);
++ musb->context.index_regs[i].txhubaddr =
++ musb_read_txhubaddr(musb_base, i);
++ musb->context.index_regs[i].txhubport =
++ musb_read_txhubport(musb_base, i);
++
++ musb->context.index_regs[i].rxfunaddr =
++ musb_read_rxfunaddr(musb_base, i);
++ musb->context.index_regs[i].rxhubaddr =
++ musb_read_rxhubaddr(musb_base, i);
++ musb->context.index_regs[i].rxhubport =
++ musb_read_rxhubport(musb_base, i);
++ }
+ }
+ }
+
+@@ -2190,9 +2254,11 @@ static void musb_restore_context(struct musb *musb)
+ void __iomem *ep_target_regs;
+ void __iomem *epio;
+
+- musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
+- musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
+- musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
++ if (is_host_enabled(musb)) {
++ musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
++ musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
++ musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
++ }
+ musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+ musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
+ musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+@@ -2231,31 +2297,33 @@ static void musb_restore_context(struct musb *musb)
+ musb->context.index_regs[i].rxfifoadd);
+ }
+
+- musb_writeb(epio, MUSB_TXTYPE,
++ if (is_host_enabled(musb)) {
++ musb_writeb(epio, MUSB_TXTYPE,
+ musb->context.index_regs[i].txtype);
+- musb_writeb(epio, MUSB_TXINTERVAL,
++ musb_writeb(epio, MUSB_TXINTERVAL,
+ musb->context.index_regs[i].txinterval);
+- musb_writeb(epio, MUSB_RXTYPE,
++ musb_writeb(epio, MUSB_RXTYPE,
+ musb->context.index_regs[i].rxtype);
+- musb_writeb(epio, MUSB_RXINTERVAL,
++ musb_writeb(epio, MUSB_RXINTERVAL,
+
+- musb->context.index_regs[i].rxinterval);
+- musb_write_txfunaddr(musb_base, i,
++ musb->context.index_regs[i].rxinterval);
++ musb_write_txfunaddr(musb_base, i,
+ musb->context.index_regs[i].txfunaddr);
+- musb_write_txhubaddr(musb_base, i,
++ musb_write_txhubaddr(musb_base, i,
+ musb->context.index_regs[i].txhubaddr);
+- musb_write_txhubport(musb_base, i,
++ musb_write_txhubport(musb_base, i,
+ musb->context.index_regs[i].txhubport);
+
+- ep_target_regs =
+- musb_read_target_reg_base(i, musb_base);
++ ep_target_regs =
++ musb_read_target_reg_base(i, musb_base);
+
+- musb_write_rxfunaddr(ep_target_regs,
++ musb_write_rxfunaddr(ep_target_regs,
+ musb->context.index_regs[i].rxfunaddr);
+- musb_write_rxhubaddr(ep_target_regs,
++ musb_write_rxhubaddr(ep_target_regs,
+ musb->context.index_regs[i].rxhubaddr);
+- musb_write_rxhubport(ep_target_regs,
++ musb_write_rxhubport(ep_target_regs,
+ musb->context.index_regs[i].rxhubport);
++ }
+ }
+ musb_writeb(musb_base, MUSB_INDEX, musb->context.index);
+ }
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index c158aac..290e411 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -71,6 +71,10 @@ struct musb_ep;
+ #include <linux/usb/hcd.h>
+ #include "musb_host.h"
+
++#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST)
++#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL)
++#define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG)
++
+ /* NOTE: otg and peripheral-only state machines start at B_IDLE.
+ * OTG or host-only go to A_IDLE when ID is sensed.
+ */
+@@ -368,6 +372,7 @@ struct musb {
+ u16 epmask;
+ u8 nr_endpoints;
+
++ u8 board_mode; /* enum musb_mode */
+ int (*board_set_power)(int state);
+
+ u8 min_power; /* vbus for periph, in mA/2 */
diff --git a/patches/linux-3.7-rc6/0077-usb-musb-dsps-get-the-PHY-using-phandle-api.patch b/patches/linux-3.7-rc6/0077-usb-musb-dsps-get-the-PHY-using-phandle-api.patch
new file mode 100644
index 0000000..ec0953e
--- /dev/null
+++ b/patches/linux-3.7-rc6/0077-usb-musb-dsps-get-the-PHY-using-phandle-api.patch
@@ -0,0 +1,55 @@
+From f2a9a492881a8eb7b4e9368510e29bcf04e16adb Mon Sep 17 00:00:00 2001
+From: Ravi Babu <ravibabu@ti.com>
+Date: Thu, 2 Aug 2012 16:13:32 +0530
+Subject: [PATCH] usb: musb: dsps: get the PHY using phandle api
+
+AM33xx has two PHY of same type used by each musb controller so
+use phandle of phy nodes to get the phy pointer.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Ravi Babu <ravibabu@ti.com>
+---
+ Documentation/devicetree/bindings/usb/am33xx-usb.txt | 5 +++++
+ drivers/usb/musb/musb_dsps.c | 5 ++++-
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/usb/am33xx-usb.txt b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
+index ca8fa56..e2702df 100644
+--- a/Documentation/devicetree/bindings/usb/am33xx-usb.txt
++++ b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
+@@ -12,3 +12,8 @@ AM33XX MUSB GLUE
+ represents PERIPHERAL.
+ - power : Should be "250". This signifies the controller can supply upto
+ 500mA when operating in host mode.
++ - usb0-phy : phandle for usb0 NOP PHY
++ - usb1-phy : phandle for usb1 NOP PHY
++
++NOP USB PHY
++ - compatible : Should be "nop-xceiv-usb"
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index ff5f112..6a14101 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -367,10 +367,12 @@ static int dsps_musb_init(struct musb *musb)
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev);
++ struct platform_device *parent_pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ struct omap_musb_board_data *data = plat->board_data;
+ void __iomem *reg_base = musb->ctrl_base;
++ char name[10];
+ u32 rev, val;
+ int status;
+
+@@ -378,7 +380,8 @@ static int dsps_musb_init(struct musb *musb)
+ musb->mregs += wrp->musb_core_offset;
+
+ /* Get the NOP PHY */
+- musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
++ sprintf(name, "usb%d-phy", pdev->id);
++ musb->xceiv = devm_usb_get_phy_by_phandle(&parent_pdev->dev, name);
+ if (IS_ERR_OR_NULL(musb->xceiv))
+ return -ENODEV;
+
diff --git a/patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch b/patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch
new file mode 100644
index 0000000..4ef518d
--- /dev/null
+++ b/patches/linux-3.7-rc6/0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch
@@ -0,0 +1,204 @@
+From 5a2e1bc30bd48edd71c3eaef3d5141d6fbe3edb2 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Tue, 10 Jul 2012 14:10:38 +0530
+Subject: [PATCH] drivers: usb: otg: add device tree support to otg library
+
+Adds an API to get usb phy by passing a device node phandle value. Since
+now it's possible to obtain phy by phandle, the checks in usb_add_phy
+for a valid phy type is removed (now it's just a debug message if a user
+tries to add a phy with undefined type).
+This also allows to add multiple phys of same type.
+
+Cc: Richard Zhao <richard.zhao@freescale.com>
+Cc: Marek Vasut <marex@denx.de>
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/otg/otg.c | 95 ++++++++++++++++++++++++++++++++++++++++-------
+ include/linux/usb/otg.h | 32 ++++++++++++++++
+ 2 files changed, 113 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
+index a30c041..ff08b34 100644
+--- a/drivers/usb/otg/otg.c
++++ b/drivers/usb/otg/otg.c
+@@ -14,6 +14,7 @@
+ #include <linux/err.h>
+ #include <linux/device.h>
+ #include <linux/slab.h>
++#include <linux/of.h>
+
+ #include <linux/usb/otg.h>
+
+@@ -35,6 +36,21 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,
+ return ERR_PTR(-ENODEV);
+ }
+
++static struct usb_phy *__of_usb_find_phy(struct list_head *list,
++ struct device_node *node)
++{
++ struct usb_phy *phy;
++
++ list_for_each_entry(phy, list, head) {
++ if (node != phy->dev->of_node)
++ continue;
++
++ return phy;
++ }
++
++ return ERR_PTR(-ENODEV);
++}
++
+ static void devm_usb_phy_release(struct device *dev, void *res)
+ {
+ struct usb_phy *phy = *(struct usb_phy **)res;
+@@ -111,6 +127,65 @@ err0:
+ EXPORT_SYMBOL(usb_get_phy);
+
+ /**
++ * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
++ * @dev - device that requests this phy
++ * @phandle - name of the property holding the phy phandle value
++ *
++ * Returns the phy driver associated with the given phandle value,
++ * after getting a refcount to it; or -ENODEV/NULL if there is no such phy.
++ * While at that, it also associates the device with the phy using
++ * devres. On driver detach, release function is invoked on the devres data,
++ * then, devres data is freed.
++ *
++ * For use by USB host and peripheral drivers.
++ */
++struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle)
++{
++ struct usb_phy *phy = NULL, **ptr;
++ unsigned long flags;
++ struct device_node *node;
++
++ if (!dev->of_node) {
++ dev_dbg(dev, "device does not have a device node entry\n");
++ return ERR_PTR(-EINVAL);
++ }
++
++ ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
++ if (!ptr) {
++ dev_dbg(dev, "failed to allocate memory for devres\n");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ spin_lock_irqsave(&phy_lock, flags);
++
++ node = of_parse_phandle(dev->of_node, phandle, 0);
++ if (!node) {
++ dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
++ dev->of_node->full_name);
++ goto err0;
++ }
++
++ phy = __of_usb_find_phy(&phy_list, node);
++ if (!IS_ERR(phy)) {
++ *ptr = phy;
++ devres_add(dev, ptr);
++ } else {
++ pr_err("unable to find transceiver with phandle %s\n", phandle);
++ devres_free(ptr);
++ goto err0;
++ }
++
++ get_device(phy->dev);
++
++err0:
++ spin_unlock_irqrestore(&phy_lock, flags);
++
++ return phy;
++}
++EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
++
++/**
+ * devm_usb_put_phy - release the USB PHY
+ * @dev - device that wants to release this phy
+ * @phy - the phy returned by devm_usb_get_phy()
+@@ -155,32 +230,24 @@ EXPORT_SYMBOL(usb_put_phy);
+ */
+ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
+ {
+- int ret = 0;
+ unsigned long flags;
+ struct usb_phy *phy;
+
+- if (x->type != USB_PHY_TYPE_UNDEFINED) {
+- dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
+- return -EINVAL;
+- }
++ if (x && x->type != USB_PHY_TYPE_UNDEFINED)
++ dev_dbg(x->dev, "add a phy with undefined type %s\n", x->label);
+
+ spin_lock_irqsave(&phy_lock, flags);
+
+- list_for_each_entry(phy, &phy_list, head) {
+- if (phy->type == type) {
+- ret = -EBUSY;
+- dev_err(x->dev, "transceiver type %s already exists\n",
++ list_for_each_entry(phy, &phy_list, head)
++ if (phy->type == type)
++ dev_dbg(x->dev, "transceiver type %s already exists\n",
+ usb_phy_type_string(type));
+- goto out;
+- }
+- }
+
+ x->type = type;
+ list_add_tail(&x->head, &phy_list);
+
+-out:
+ spin_unlock_irqrestore(&phy_lock, flags);
+- return ret;
++ return 0;
+ }
+ EXPORT_SYMBOL(usb_add_phy);
+
+diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
+index e8a5fe8..bae7599 100644
+--- a/include/linux/usb/otg.h
++++ b/include/linux/usb/otg.h
+@@ -37,8 +37,40 @@ struct usb_otg {
+ };
+
+ #ifdef CONFIG_USB_OTG_UTILS
++extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
++extern struct usb_phy *devm_usb_get_phy(struct device *dev,
++ enum usb_phy_type type);
++extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle);
++extern void usb_put_phy(struct usb_phy *);
++extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
+ extern const char *otg_state_string(enum usb_otg_state state);
+ #else
++static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
++{
++ return NULL;
++}
++
++static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
++ enum usb_phy_type type)
++{
++ return NULL;
++}
++
++extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle)
++{
++ return NULL;
++}
++
++static inline void usb_put_phy(struct usb_phy *x)
++{
++}
++
++static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
++{
++}
++
+ static inline const char *otg_state_string(enum usb_otg_state state)
+ {
+ return NULL;
diff --git a/patches/linux-3.7-rc6/0079-usb-otg-nop-add-dt-support.patch b/patches/linux-3.7-rc6/0079-usb-otg-nop-add-dt-support.patch
new file mode 100644
index 0000000..ac46e10
--- /dev/null
+++ b/patches/linux-3.7-rc6/0079-usb-otg-nop-add-dt-support.patch
@@ -0,0 +1,48 @@
+From fb37c173324d76c12dd1b0e7758f1e2012f6dabf Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Tue, 10 Jul 2012 14:51:53 +0530
+Subject: [PATCH] usb: otg: nop: add dt support
+
+Added device tree support for nop transceiver driver and updated the
+Documentation with device tree binding information for am33xx platform.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Ravi Babu <ravibabu@ti.com>
+---
+ drivers/usb/otg/nop-usb-xceiv.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
+index e52e35e..466a321 100644
+--- a/drivers/usb/otg/nop-usb-xceiv.c
++++ b/drivers/usb/otg/nop-usb-xceiv.c
+@@ -27,6 +27,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/usb/otg.h>
+@@ -154,12 +155,21 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++#ifdef CONFIG_OF
++static const struct of_device_id nop_xceiv_id_table[] = {
++ { .compatible = "nop-xceiv-usb" },
++ {}
++};
++MODULE_DEVICE_TABLE(of, nop_xceiv_id_table);
++#endif
++
+ static struct platform_driver nop_usb_xceiv_driver = {
+ .probe = nop_usb_xceiv_probe,
+ .remove = __devexit_p(nop_usb_xceiv_remove),
+ .driver = {
+ .name = "nop_usb_xceiv",
+ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(nop_xceiv_id_table),
+ },
+ };
+
diff --git a/patches/linux-3.7-rc6/0080-usb-musb-dsps-add-phy-control-logic-to-glue.patch b/patches/linux-3.7-rc6/0080-usb-musb-dsps-add-phy-control-logic-to-glue.patch
new file mode 100644
index 0000000..81953b7
--- /dev/null
+++ b/patches/linux-3.7-rc6/0080-usb-musb-dsps-add-phy-control-logic-to-glue.patch
@@ -0,0 +1,275 @@
+From eca00fad21c1ef2bf0df883fa2c001e2242bfe29 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 5 Jul 2012 14:06:42 +0530
+Subject: [PATCH] usb: musb: dsps: add phy control logic to glue
+
+AM335x uses NOP transceiver driver and need to enable builtin PHY
+by writing into usb_ctrl register available in system control
+module register space. This is being added at musb glue driver
+layer untill a separate system control module driver is available.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ arch/arm/mach-omap2/board-ti8168evm.c | 1 -
+ arch/arm/mach-omap2/omap_phy_internal.c | 35 ------------
+ arch/arm/plat-omap/include/plat/usb.h | 5 +-
+ drivers/usb/musb/musb_dsps.c | 91 +++++++++++++++++++++++++------
+ 4 files changed, 75 insertions(+), 57 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
+index c4f8833..b367d18 100644
+--- a/arch/arm/mach-omap2/board-ti8168evm.c
++++ b/arch/arm/mach-omap2/board-ti8168evm.c
+@@ -23,7 +23,6 @@
+ #include <plat/usb.h>
+
+ static struct omap_musb_board_data musb_board_data = {
+- .set_phy_power = ti81xx_musb_phy_power,
+ .interface_type = MUSB_INTERFACE_ULPI,
+ .mode = MUSB_OTG,
+ .power = 500,
+diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
+index d992db8..db3ada8 100644
+--- a/arch/arm/mach-omap2/omap_phy_internal.c
++++ b/arch/arm/mach-omap2/omap_phy_internal.c
+@@ -118,38 +118,3 @@ void am35x_set_mode(u8 musb_mode)
+
+ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+ }
+-
+-void ti81xx_musb_phy_power(u8 on)
+-{
+- void __iomem *scm_base = NULL;
+- u32 usbphycfg;
+-
+- scm_base = ioremap(TI81XX_SCM_BASE, SZ_2K);
+- if (!scm_base) {
+- pr_err("system control module ioremap failed\n");
+- return;
+- }
+-
+- usbphycfg = __raw_readl(scm_base + USBCTRL0);
+-
+- if (on) {
+- if (cpu_is_ti816x()) {
+- usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
+- usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
+- } else if (cpu_is_ti814x()) {
+- usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
+- | USBPHY_DPINPUT | USBPHY_DMINPUT);
+- usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
+- | USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
+- }
+- } else {
+- if (cpu_is_ti816x())
+- usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
+- else if (cpu_is_ti814x())
+- usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+-
+- }
+- __raw_writel(usbphycfg, scm_base + USBCTRL0);
+-
+- iounmap(scm_base);
+-}
+diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
+index 87ee140..43052e7f 100644
+--- a/arch/arm/plat-omap/include/plat/usb.h
++++ b/arch/arm/plat-omap/include/plat/usb.h
+@@ -101,7 +101,6 @@ extern void am35x_musb_reset(void);
+ extern void am35x_musb_phy_power(u8 on);
+ extern void am35x_musb_clear_irq(void);
+ extern void am35x_set_mode(u8 musb_mode);
+-extern void ti81xx_musb_phy_power(u8 on);
+
+ /* AM35x */
+ /* USB 2.0 PHY Control */
+@@ -126,8 +125,8 @@ extern void ti81xx_musb_phy_power(u8 on);
+ #define CONF2_DATPOL (1 << 1)
+
+ /* TI81XX specific definitions */
+-#define USBCTRL0 0x620
+-#define USBSTAT0 0x624
++#define MUSB_USBSS_REV_816X 0x9
++#define MUSB_USBSS_REV_814X 0xb
+
+ /* TI816X PHY controls bits */
+ #define TI816X_USBPHY0_NORMAL_MODE (1 << 0)
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 6a14101..1151760 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -124,9 +124,46 @@ struct dsps_glue {
+ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
+ struct timer_list timer[2]; /* otg_workaround timer */
+ unsigned long last_timer[2]; /* last timer data for each instance */
++ u32 __iomem *usb_ctrl[2];
++ u8 usbss_rev;
+ };
+
+ /**
++ * musb_dsps_phy_control - phy on/off
++ * @glue: struct dsps_glue *
++ * @id: the id
++ * @on: flag for phy to be switched on or off
++ *
++ * This is to enable the PHY using usb_ctrl register in system control
++ * module space.
++ *
++ * XXX: This function will be removed once we have a seperate driver for
++ * control module
++ */
++static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
++{
++ u32 usbphycfg;
++
++ usbphycfg = __raw_readl(glue->usb_ctrl[id]);
++ if (on) {
++ if (glue->usbss_rev == MUSB_USBSS_REV_816X) {
++ usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
++ usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
++ } else if (glue->usbss_rev == MUSB_USBSS_REV_814X) {
++ usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
++ | USBPHY_DPINPUT | USBPHY_DMINPUT);
++ usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
++ | USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
++ }
++ } else {
++ if (glue->usbss_rev == MUSB_USBSS_REV_816X)
++ usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
++ else if (glue->usbss_rev == MUSB_USBSS_REV_814X)
++ usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
++ }
++ __raw_writel(usbphycfg, glue->usb_ctrl[id]);
++}
++/**
+ * dsps_musb_enable - enable interrupts
+ */
+ static void dsps_musb_enable(struct musb *musb)
+@@ -365,12 +402,10 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
+ static int dsps_musb_init(struct musb *musb)
+ {
+ struct device *dev = musb->controller;
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct platform_device *parent_pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+- struct omap_musb_board_data *data = plat->board_data;
+ void __iomem *reg_base = musb->ctrl_base;
+ char name[10];
+ u32 rev, val;
+@@ -398,8 +433,7 @@ static int dsps_musb_init(struct musb *musb)
+ dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
+
+ /* Start the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(1);
++ musb_dsps_phy_control(glue, pdev->id, 1);
+
+ musb->isr = dsps_interrupt;
+
+@@ -421,16 +455,13 @@ err0:
+ static int dsps_musb_exit(struct musb *musb)
+ {
+ struct device *dev = musb->controller;
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct omap_musb_board_data *data = plat->board_data;
+- struct platform_device *pdev = to_platform_device(dev);
+- struct dsps_glue *glue = dev_get_drvdata(dev->parent);
++ struct platform_device *pdev = to_platform_device(dev->parent);
++ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ del_timer_sync(&glue->timer[pdev->id]);
+
+ /* Shutdown the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(0);
++ musb_dsps_phy_control(glue, pdev->id, 0);
+
+ /* NOP driver needs change if supporting dual instance */
+ usb_put_phy(musb->xceiv);
+@@ -464,6 +495,21 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+ char res_name[11];
+ int ret, musbid;
+
++ /* get memory resource for usb control register */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2 * id + 2);
++ if (!res) {
++ dev_err(dev, "%s get mem resource failed\n", res_name);
++ ret = -ENODEV;
++ goto err0;
++ }
++
++ glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, res);
++ if (glue->usb_ctrl == NULL) {
++ dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id);
++ ret = -ENODEV;
++ goto err0;
++ }
++
+ /* get memory resource */
+ snprintf(res_name, sizeof(res_name), "musb%d", id);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+@@ -579,6 +625,7 @@ static int __devinit dsps_probe(struct platform_device *pdev)
+ const struct dsps_musb_wrapper *wrp;
+ struct dsps_glue *glue;
+ struct resource *iomem;
++ u32 __iomem *usbss;
+ int ret, i;
+
+ match = of_match_node(musb_dsps_of_match, np);
+@@ -605,6 +652,13 @@ static int __devinit dsps_probe(struct platform_device *pdev)
+ goto err1;
+ }
+
++ usbss = devm_request_and_ioremap(&pdev->dev, iomem);
++ if (usbss == NULL) {
++ dev_err(&pdev->dev, "Failed to obtain usbss memory\n");
++ ret = -ENODEV;
++ goto err1;
++ }
++
+ glue->dev = &pdev->dev;
+
+ glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
+@@ -636,6 +690,9 @@ static int __devinit dsps_probe(struct platform_device *pdev)
+ }
+ }
+
++ /* read the usbss revision register */
++ glue->usbss_rev = __raw_readl(usbss);
++
+ return 0;
+
+ err3:
+@@ -669,24 +726,22 @@ static int __devexit dsps_remove(struct platform_device *pdev)
+ #ifdef CONFIG_PM_SLEEP
+ static int dsps_suspend(struct device *dev)
+ {
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct omap_musb_board_data *data = plat->board_data;
++ struct platform_device *pdev = to_platform_device(dev->parent);
++ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ /* Shutdown the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(0);
++ musb_dsps_phy_control(glue, pdev->id, 0);
+
+ return 0;
+ }
+
+ static int dsps_resume(struct device *dev)
+ {
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct omap_musb_board_data *data = plat->board_data;
++ struct platform_device *pdev = to_platform_device(dev->parent);
++ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ /* Start the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(1);
++ musb_dsps_phy_control(glue, pdev->id, 1);
+
+ return 0;
+ }
diff --git a/patches/linux-3.7-rc6/0081-usb-musb-dsps-enable-phy-control-for-am335x.patch b/patches/linux-3.7-rc6/0081-usb-musb-dsps-enable-phy-control-for-am335x.patch
new file mode 100644
index 0000000..3935eb9
--- /dev/null
+++ b/patches/linux-3.7-rc6/0081-usb-musb-dsps-enable-phy-control-for-am335x.patch
@@ -0,0 +1,58 @@
+From 849303a736b86ac5de2570a52ddac5ef9c2290f0 Mon Sep 17 00:00:00 2001
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 5 Jul 2012 14:35:06 +0530
+Subject: [PATCH] usb: musb: dsps: enable phy control for am335x
+
+Enabled the phy control logic for am335x also based on usbss
+revision register.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ arch/arm/plat-omap/include/plat/usb.h | 1 +
+ drivers/usb/musb/musb_dsps.c | 17 +++++++++++------
+ 2 files changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
+index 43052e7f..bb27e88 100644
+--- a/arch/arm/plat-omap/include/plat/usb.h
++++ b/arch/arm/plat-omap/include/plat/usb.h
+@@ -127,6 +127,7 @@ extern void am35x_set_mode(u8 musb_mode);
+ /* TI81XX specific definitions */
+ #define MUSB_USBSS_REV_816X 0x9
+ #define MUSB_USBSS_REV_814X 0xb
++#define MUSB_USBSS_REV_33XX 0xd
+
+ /* TI816X PHY controls bits */
+ #define TI816X_USBPHY0_NORMAL_MODE (1 << 0)
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 1151760..ed3b379 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -149,16 +149,21 @@ static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
+ if (glue->usbss_rev == MUSB_USBSS_REV_816X) {
+ usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
+ usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
+- } else if (glue->usbss_rev == MUSB_USBSS_REV_814X) {
+- usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
+- | USBPHY_DPINPUT | USBPHY_DMINPUT);
+- usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
+- | USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
++ } else if (glue->usbss_rev == MUSB_USBSS_REV_814X ||
++ glue->usbss_rev == MUSB_USBSS_REV_33XX) {
++ usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
++ usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
++ if (glue->usbss_rev == MUSB_USBSS_REV_814X) {
++ usbphycfg &= ~(USBPHY_DPINPUT | USBPHY_DMINPUT);
++ usbphycfg |= USBPHY_DPOPBUFCTL
++ | USBPHY_DMOPBUFCTL;
++ }
+ }
+ } else {
+ if (glue->usbss_rev == MUSB_USBSS_REV_816X)
+ usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
+- else if (glue->usbss_rev == MUSB_USBSS_REV_814X)
++ else if (glue->usbss_rev == MUSB_USBSS_REV_814X ||
++ glue->usbss_rev == MUSB_USBSS_REV_33XX)
+ usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+ }
+ __raw_writel(usbphycfg, glue->usb_ctrl[id]);
diff --git a/patches/linux-3.7-rc6/0082-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch b/patches/linux-3.7-rc6/0082-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch
new file mode 100644
index 0000000..5fd84b3
--- /dev/null
+++ b/patches/linux-3.7-rc6/0082-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch
@@ -0,0 +1,45 @@
+From 23ec7954c2eb161d52ce3df4fac3f7a188319120 Mon Sep 17 00:00:00 2001
+From: Daniel Mack <zonque@gmail.com>
+Date: Wed, 17 Oct 2012 16:39:00 +0200
+Subject: [PATCH] ARM: am33xx: fix mem regions in USB hwmod
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index b6f78c1..2a5032f 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -3310,12 +3310,24 @@ static struct omap_hwmod_addr_space am33xx_usbss_addr_space[] = {
+ .pa_end = 0x47401000 + SZ_2K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+- {
+- .name = "musb1",
+- .pa_start = 0x47401800,
+- .pa_end = 0x47401800 + SZ_2K - 1,
+- .flags = ADDR_TYPE_RT
+- },
++ {
++ .name = "usb_ctrl0",
++ .pa_start = 0x44E10620,
++ .pa_end = 0x44E10620 + SZ_4 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ {
++ .name = "musb1",
++ .pa_start = 0x47401800,
++ .pa_end = 0x47401800 + SZ_2K - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ {
++ .name = "usb_ctrl1",
++ .pa_start = 0x44E10628,
++ .pa_end = 0x44E10628 + SZ_4 - 1,
++ .flags = ADDR_TYPE_RT
++ },
+ { }
+ };
+
diff --git a/patches/linux-3.7-rc6/0084-omap2-clk-Add-missing-lcdc-clock-definition.patch b/patches/linux-3.7-rc6/0084-omap2-clk-Add-missing-lcdc-clock-definition.patch
new file mode 100644
index 0000000..0e85066
--- /dev/null
+++ b/patches/linux-3.7-rc6/0084-omap2-clk-Add-missing-lcdc-clock-definition.patch
@@ -0,0 +1,40 @@
+From 5cb5d4cb5e66b2aab310bb097e23cd7b424c590d Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:12:22 +0300
+Subject: [PATCH] omap2-clk: Add missing lcdc clock definition
+
+Looks like the lcdc clock definition got dropped.
+It is required for the LCD controller to work. Reintroduce.
+---
+ arch/arm/mach-omap2/clock33xx_data.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c
+index 1a45d6b..b7b7995 100644
+--- a/arch/arm/mach-omap2/clock33xx_data.c
++++ b/arch/arm/mach-omap2/clock33xx_data.c
+@@ -867,6 +867,16 @@ static struct clk lcd_gclk = {
+ .recalc = &followparent_recalc,
+ };
+
++static struct clk lcdc_fck = {
++ .name = "lcdc_fck",
++ .clkdm_name = "lcdc_clkdm",
++ .parent = &lcd_gclk,
++ .enable_reg = AM33XX_CM_PER_LCDC_CLKCTRL,
++ .enable_bit = AM33XX_MODULEMODE_SWCTRL,
++ .ops = &clkops_omap2_dflt,
++ .recalc = &followparent_recalc,
++};
++
+ static struct clk mmc_clk = {
+ .name = "mmc_clk",
+ .clkdm_name = "l4ls_clkdm",
+@@ -1075,6 +1085,7 @@ static struct omap_clk am33xx_clks[] = {
+ CLK(NULL, "clkout2_ck", &clkout2_ck, CK_AM33XX),
+ CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX),
+ CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX),
++ CLK("da8xx_lcdc.0", NULL, &lcdc_fck, CK_AM33XX),
+ };
+
+ int __init am33xx_clk_init(void)
diff --git a/patches/linux-3.7-rc6/0085-da8xx-Allow-use-by-am33xx-based-devices.patch b/patches/linux-3.7-rc6/0085-da8xx-Allow-use-by-am33xx-based-devices.patch
new file mode 100644
index 0000000..f796803
--- /dev/null
+++ b/patches/linux-3.7-rc6/0085-da8xx-Allow-use-by-am33xx-based-devices.patch
@@ -0,0 +1,23 @@
+From a7cd16691ffbb0a9e4fe2d9602d51ae57d741753 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:18:37 +0300
+Subject: [PATCH] da8xx: Allow use by am33xx based devices
+
+This driver can be used for AM33xx devices, like the popular beaglebone.
+---
+ drivers/video/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 9791d10..e7868d8 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2202,7 +2202,7 @@ config FB_SH7760
+
+ config FB_DA8XX
+ tristate "DA8xx/OMAP-L1xx Framebuffer support"
+- depends on FB && ARCH_DAVINCI_DA8XX
++ depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
diff --git a/patches/linux-3.7-rc6/0086-da8xx-Fix-revision-check-on-the-da8xx-driver.patch b/patches/linux-3.7-rc6/0086-da8xx-Fix-revision-check-on-the-da8xx-driver.patch
new file mode 100644
index 0000000..72d81c3
--- /dev/null
+++ b/patches/linux-3.7-rc6/0086-da8xx-Fix-revision-check-on-the-da8xx-driver.patch
@@ -0,0 +1,22 @@
+From fab03445e416c75fab4cbe2a46a241445965122f Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:21:05 +0300
+Subject: [PATCH] da8xx: Fix revision check on the da8xx driver
+
+The revision check fails for the beaglebone; Add new revision ID.
+---
+ drivers/video/da8xx-fb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 80665f6..866d804 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1283,6 +1283,7 @@ static int __devinit fb_probe(struct platform_device *device)
+ lcd_revision = LCD_VERSION_1;
+ break;
+ case 0x4F200800:
++ case 0x4F201000:
+ lcd_revision = LCD_VERSION_2;
+ break;
+ default:
diff --git a/patches/linux-3.7-rc6/0087-da8xx-De-constify-members-in-the-platform-config.patch b/patches/linux-3.7-rc6/0087-da8xx-De-constify-members-in-the-platform-config.patch
new file mode 100644
index 0000000..d2773a9
--- /dev/null
+++ b/patches/linux-3.7-rc6/0087-da8xx-De-constify-members-in-the-platform-config.patch
@@ -0,0 +1,29 @@
+From d4638819046e8c3ea545eb8b63cc90466cd2dd1d Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:22:47 +0300
+Subject: [PATCH] da8xx: De-constify members in the platform config.
+
+There's no need for this to be const. It interferes with
+creating the platform data dynamically.
+
+Remove const.
+---
+ include/video/da8xx-fb.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h
+index 5a0e4f9..a512d6b 100644
+--- a/include/video/da8xx-fb.h
++++ b/include/video/da8xx-fb.h
+@@ -35,9 +35,9 @@ struct display_panel {
+ };
+
+ struct da8xx_lcdc_platform_data {
+- const char manu_name[10];
++ char manu_name[10];
+ void *controller_data;
+- const char type[25];
++ char type[25];
+ void (*panel_power_ctrl)(int);
+ };
+
diff --git a/patches/linux-3.7-rc6/0088-da8xx-Add-standard-panel-definition.patch b/patches/linux-3.7-rc6/0088-da8xx-Add-standard-panel-definition.patch
new file mode 100644
index 0000000..326ee0b
--- /dev/null
+++ b/patches/linux-3.7-rc6/0088-da8xx-Add-standard-panel-definition.patch
@@ -0,0 +1,36 @@
+From 8267defaabc2e24f3e57a1804982905b11e4a25f Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:24:19 +0300
+Subject: [PATCH] da8xx: Add standard panel definition
+
+Add standard panel definition that can work for the beaglebone
+DVI cape.
+---
+ drivers/video/da8xx-fb.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 866d804..4462d9e 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -270,6 +270,20 @@ static struct da8xx_panel known_lcd_panels[] = {
+ .pxl_clk = 7833600,
+ .invert_pxl_clk = 0,
+ },
++ [3] = {
++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
++ .name = "1024x768@60",
++ .width = 1024,
++ .height = 768,
++ .hfp = 48,
++ .hbp = 80,
++ .hsw = 32,
++ .vfp = 3,
++ .vbp = 15,
++ .vsw = 4,
++ .pxl_clk = 56000000,
++ .invert_pxl_clk = 0,
++ },
+ };
+
+ /* Enable the Raster Engine of the LCD Controller */
diff --git a/patches/linux-3.7-rc6/0089-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch b/patches/linux-3.7-rc6/0089-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch
new file mode 100644
index 0000000..5bff28d
--- /dev/null
+++ b/patches/linux-3.7-rc6/0089-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch
@@ -0,0 +1,34 @@
+From efa286cb8ea36c5c01aaa632449690528aefcfe9 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 17 Oct 2012 15:43:55 +0300
+Subject: [PATCH] da8xx: Add CDTech_S035Q01 panel (used by LCD3 bone cape)
+
+---
+ drivers/video/da8xx-fb.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 4462d9e..873789b 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -284,6 +284,20 @@ static struct da8xx_panel known_lcd_panels[] = {
+ .pxl_clk = 56000000,
+ .invert_pxl_clk = 0,
+ },
++ [4] = {
++ /* CDTech S035Q01 */
++ .name = "CDTech_S035Q01",
++ .width = 320,
++ .height = 240,
++ .hfp = 58,
++ .hbp = 21,
++ .hsw = 47,
++ .vfp = 23,
++ .vbp = 11,
++ .vsw = 2,
++ .pxl_clk = 8000000,
++ .invert_pxl_clk = 0,
++ },
+ };
+
+ /* Enable the Raster Engine of the LCD Controller */
diff --git a/patches/linux-3.7-rc6/0090-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch b/patches/linux-3.7-rc6/0090-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch
new file mode 100644
index 0000000..463ea9a
--- /dev/null
+++ b/patches/linux-3.7-rc6/0090-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch
@@ -0,0 +1,35 @@
+From 84ee386766bf356bfdb5adddeb17de5ffc2f948c Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 17 Oct 2012 11:32:24 +0200
+Subject: [PATCH] da8xx-fb: add panel definition for beaglebone LCD7 cape
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/video/da8xx-fb.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 873789b..6d98184 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -298,6 +298,20 @@ static struct da8xx_panel known_lcd_panels[] = {
+ .pxl_clk = 8000000,
+ .invert_pxl_clk = 0,
+ },
++ /* ThreeFive S9700RTWV35TR */
++ [5] = {
++ .name = "TFC_S9700RTWV35TR_01B",
++ .width = 800,
++ .height = 480,
++ .hfp = 39,
++ .hbp = 39,
++ .hsw = 47,
++ .vfp = 13,
++ .vbp = 29,
++ .vsw = 2,
++ .pxl_clk = 30000000,
++ .invert_pxl_clk = 0,
++ },
+ };
+
+ /* Enable the Raster Engine of the LCD Controller */
diff --git a/patches/linux-3.7-rc6/0092-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch b/patches/linux-3.7-rc6/0092-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch
new file mode 100644
index 0000000..92007c3
--- /dev/null
+++ b/patches/linux-3.7-rc6/0092-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch
@@ -0,0 +1,117 @@
+From 8f6c8615eb09d567eef77036e0d378b65b67ae40 Mon Sep 17 00:00:00 2001
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Tue, 4 Sep 2012 13:09:11 +0000
+Subject: [PATCH] mmc: omap_hsmmc: Enable HSPE bit for high speed cards
+
+HSMMC IP on AM33xx need a special setting to handle High-speed cards.
+Other platforms like TI81xx, OMAP4 may need this as-well. This depends
+on the HSMMC IP timing closure done for the high speed cards.
+
+>From AM335x TRM (SPRUH73F - 18.3.12 Output Signals Generation)
+
+The MMC/SD/SDIO output signals can be driven on either falling edge or
+rising edge depending on the SD_HCTL[2] HSPE bit. This feature allows
+to reach better timing performance, and thus to increase data transfer
+frequency.
+
+There are few pre-requisites for enabling the HSPE bit
+- Controller should support High-Speed-Enable Bit and
+- Controller should not be using DDR Mode and
+- Controller should advertise that it supports High Speed in
+ capabilities register and
+- MMC/SD clock coming out of controller > 25MHz
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+---
+ arch/arm/plat-omap/include/plat/mmc.h | 1 +
+ drivers/mmc/host/omap_hsmmc.c | 30 +++++++++++++++++++++++++++++-
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
+index 8b4e4f2..346af5b 100644
+--- a/arch/arm/plat-omap/include/plat/mmc.h
++++ b/arch/arm/plat-omap/include/plat/mmc.h
+@@ -126,6 +126,7 @@ struct omap_mmc_platform_data {
+ /* we can put the features above into this variable */
+ #define HSMMC_HAS_PBIAS (1 << 0)
+ #define HSMMC_HAS_UPDATED_RESET (1 << 1)
++#define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
+ unsigned features;
+
+ int switch_pin; /* gpio (card detect) */
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 4fe62b0..897b718 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -62,6 +62,7 @@
+
+ #define VS18 (1 << 26)
+ #define VS30 (1 << 25)
++#define HSS (1 << 21)
+ #define SDVS18 (0x5 << 9)
+ #define SDVS30 (0x6 << 9)
+ #define SDVS33 (0x7 << 9)
+@@ -89,6 +90,7 @@
+ #define MSBS (1 << 5)
+ #define BCE (1 << 1)
+ #define FOUR_BIT (1 << 1)
++#define HSPE (1 << 2)
+ #define DDR (1 << 19)
+ #define DW8 (1 << 5)
+ #define CC 0x1
+@@ -494,6 +496,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+ struct mmc_ios *ios = &host->mmc->ios;
+ unsigned long regval;
+ unsigned long timeout;
++ unsigned long clkdiv;
+
+ dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+
+@@ -501,7 +504,8 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+
+ regval = OMAP_HSMMC_READ(host->base, SYSCTL);
+ regval = regval & ~(CLKD_MASK | DTO_MASK);
+- regval = regval | (calc_divisor(host, ios) << 6) | (DTO << 16);
++ clkdiv = calc_divisor(host, ios);
++ regval = regval | (clkdiv << 6) | (DTO << 16);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+@@ -512,6 +516,27 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+ && time_before(jiffies, timeout))
+ cpu_relax();
+
++ /*
++ * Enable High-Speed Support
++ * Pre-Requisites
++ * - Controller should support High-Speed-Enable Bit
++ * - Controller should not be using DDR Mode
++ * - Controller should advertise that it supports High Speed
++ * in capabilities register
++ * - MMC/SD clock coming out of controller > 25MHz
++ */
++ if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) &&
++ (ios->timing != MMC_TIMING_UHS_DDR50) &&
++ ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) {
++ regval = OMAP_HSMMC_READ(host->base, HCTL);
++ if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000)
++ regval |= HSPE;
++ else
++ regval &= ~HSPE;
++
++ OMAP_HSMMC_WRITE(host->base, HCTL, regval);
++ }
++
+ omap_hsmmc_start_clock(host);
+ }
+
+@@ -1705,6 +1730,9 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ if (of_find_property(np, "ti,needs-special-reset", NULL))
+ pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+
++ if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
++ pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
++
+ return pdata;
+ }
+ #else
diff --git a/patches/linux-3.7-rc6/0093-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch b/patches/linux-3.7-rc6/0093-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
new file mode 100644
index 0000000..dd416dd
--- /dev/null
+++ b/patches/linux-3.7-rc6/0093-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
@@ -0,0 +1,38 @@
+From 6a28b2af338fb9b5800829474e26bcbc40005b1a Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 18 Oct 2012 10:11:48 +0200
+Subject: [PATCH] am33xx.dtsi: enable MMC HSPE bit for all 3 controllers
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 9bb71cb..8bddc9c 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -263,6 +263,7 @@
+ ti,hwmods = "mmc1";
+ ti,dual-volt;
+ ti,needs-special-reset;
++ ti,needs-special-hs-handling;
+ dmas = <&edma 24
+ &edma 25>;
+ dma-names = "tx", "rx";
+@@ -272,6 +273,7 @@
+ compatible = "ti,omap3-hsmmc";
+ ti,hwmods = "mmc2";
+ ti,needs-special-reset;
++ ti,needs-special-hs-handling;
+ dmas = <&edma 2
+ &edma 3>;
+ dma-names = "tx", "rx";
+@@ -282,6 +284,7 @@
+ compatible = "ti,omap3-hsmmc";
+ ti,hwmods = "mmc3";
+ ti,needs-special-reset;
++ ti,needs-special-hs-handling;
+ status = "disabled";
+ };
+
diff --git a/patches/linux-3.7-rc6/0094-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch b/patches/linux-3.7-rc6/0094-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
new file mode 100644
index 0000000..71658ad
--- /dev/null
+++ b/patches/linux-3.7-rc6/0094-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
@@ -0,0 +1,23 @@
+From 21e193d74c69102be68cbc76baf581abffcaef2a Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 26 Oct 2012 15:48:00 +0300
+Subject: [PATCH] omap-hsmmc: Correct usage of of_find_node_by_name
+
+of_find_node_by_name expect to have the parent node reference taken.
+---
+ drivers/mmc/host/omap_hsmmc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 897b718..7a1283c 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1864,7 +1864,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ /* Eventually we should get our max_segs limitation for EDMA by
+ * querying the dmaengine API */
+ if (pdev->dev.of_node) {
+- struct device_node *parent = pdev->dev.of_node->parent;
++ struct device_node *parent = of_node_get(pdev->dev.of_node->parent);
+ struct device_node *node;
+ node = of_find_node_by_name(parent, "edma");
+ if (node)
diff --git a/patches/linux-3.7-rc6/0096-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch b/patches/linux-3.7-rc6/0096-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch
new file mode 100644
index 0000000..66399f4
--- /dev/null
+++ b/patches/linux-3.7-rc6/0096-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch
@@ -0,0 +1,25 @@
+From 0e2a3d8d4c5c17660c8e3410826c4d9f7f222968 Mon Sep 17 00:00:00 2001
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Fri, 19 Oct 2012 02:01:39 +0530
+Subject: [PATCH] ARM: AM33XX: hwmod: Remove wrong INIT_NO_RESET/IDLE flags
+ from cpgmac entry
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index 2a5032f..76531f9 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -681,8 +681,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+- .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
+- HWMOD_INIT_NO_RESET | HWMOD_INIT_NO_IDLE),
++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+ };
+
+ /*
diff --git a/patches/linux-3.7-rc6/0098-f2fs-add-document.patch b/patches/linux-3.7-rc6/0098-f2fs-add-document.patch
new file mode 100644
index 0000000..367300f
--- /dev/null
+++ b/patches/linux-3.7-rc6/0098-f2fs-add-document.patch
@@ -0,0 +1,438 @@
+From c7823b127b80e70f1eabc0af8ddcab7640cc9d41 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:25:11 +0000
+Subject: [PATCH] f2fs: add document
+
+This adds a document describing the mount options, proc entries, usage, and
+design of Flash-Friendly File System, namely F2FS.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ Documentation/filesystems/00-INDEX | 2 +
+ Documentation/filesystems/f2fs.txt | 404 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 406 insertions(+)
+ create mode 100644 Documentation/filesystems/f2fs.txt
+
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 8c624a1..ce5fd46 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -48,6 +48,8 @@ ext4.txt
+ - info, mount options and specifications for the Ext4 filesystem.
+ files.txt
+ - info on file management in the Linux kernel.
++f2fs.txt
++ - info and mount options for the F2FS filesystem.
+ fuse.txt
+ - info on the Filesystem in User SpacE including mount options.
+ gfs2.txt
+diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
+new file mode 100644
+index 0000000..f2b4fde
+--- /dev/null
++++ b/Documentation/filesystems/f2fs.txt
+@@ -0,0 +1,404 @@
++================================================================================
++WHAT IS Flash-Friendly File System (F2FS)?
++================================================================================
++
++NAND flash memory-based storage devices, such as SSD, eMMC, and SD cards, have
++been widely being used for storage ranging from mobile to server systems. Since
++they are known to have different characteristics from the conventional rotating
++disks, a file system, an upper layer to the storage device, should adapt to the
++changes from the sketch in the design level.
++
++F2FS is a file system exploiting NAND flash memory-based storage devices, which
++is based on Log-structured File System (LFS). The design has been focused on
++addressing the fundamental issues in LFS, which are snowball effect of wandering
++tree and high cleaning overhead.
++
++Since a NAND flash memory-based storage device shows different characteristic
++according to its internal geometry or flash memory management scheme, namely FTL,
++F2FS and its tools support various parameters not only for configuring on-disk
++layout, but also for selecting allocation and cleaning algorithms.
++
++The file system formatting tool, "mkfs.f2fs", is available from the following
++download page: http://sourceforge.net/projects/f2fs-tools/
++
++================================================================================
++BACKGROUND AND DESIGN ISSUES
++================================================================================
++
++Log-structured File System (LFS)
++--------------------------------
++"A log-structured file system writes all modifications to disk sequentially in
++a log-like structure, thereby speeding up both file writing and crash recovery.
++The log is the only structure on disk; it contains indexing information so that
++files can be read back from the log efficiently. In order to maintain large free
++areas on disk for fast writing, we divide the log into segments and use a
++segment cleaner to compress the live information from heavily fragmented
++segments." from Rosenblum, M. and Ousterhout, J. K., 1992, "The design and
++implementation of a log-structured file system", ACM Trans. Computer Systems
++10, 1, 26–52.
++
++Wandering Tree Problem
++----------------------
++In LFS, when a file data is updated and written to the end of log, its direct
++pointer block is updated due to the changed location. Then the indirect pointer
++block is also updated due to the direct pointer block update. In this manner,
++the upper index structures such as inode, inode map, and checkpoint block are
++also updated recursively. This problem is called as wandering tree problem [1],
++and in order to enhance the performance, it should eliminate or relax the update
++propagation as much as possible.
++
++[1] Bityutskiy, A. 2005. JFFS3 design issues. http://www.linux-mtd.infradead.org/
++
++Cleaning Overhead
++-----------------
++Since LFS is based on out-of-place writes, it produces so many obsolete blocks
++scattered across the whole storage. In order to serve new empty log space, it
++needs to reclaim these obsolete blocks seamlessly to users. This job is called
++as a cleaning process.
++
++The process consists of three operations as follows.
++1. A victim segment is selected through referencing segment usage table.
++2. It loads parent index structures of all the data in the victim identified by
++ segment summary blocks.
++3. It checks the cross-reference between the data and its parent index structure.
++4. It moves valid data selectively.
++
++This cleaning job may cause unexpected long delays, so the most important goal
++is to hide the latencies to users. And also definitely, it should reduce the
++amount of valid data to be moved, and move them quickly as well.
++
++================================================================================
++KEY FEATURES
++================================================================================
++
++Flash Awareness
++---------------
++- Enlarge the random write area for better performance, but provide the high
++ spatial locality
++- Align FS data structures to the operational units in FTL as best efforts
++
++Wandering Tree Problem
++----------------------
++- Use a term, “node”, that represents inodes as well as various pointer blocks
++- Introduce Node Address Table (NAT) containing the locations of all the “node”
++ blocks; this will cut off the update propagation.
++
++Cleaning Overhead
++-----------------
++- Support a background cleaning process
++- Support greedy and cost-benefit algorithms for victim selection policies
++- Support multi-head logs for static/dynamic hot and cold data separation
++- Introduce adaptive logging for efficient block allocation
++
++================================================================================
++MOUNT OPTIONS
++================================================================================
++
++background_gc_off Turn off cleaning operations, namely garbage collection,
++ triggered in background when I/O subsystem is idle.
++disable_roll_forward Disable the roll-forward recovery routine
++discard Issue discard/TRIM commands when a segment is cleaned.
++no_heap Disable heap-style segment allocation which finds free
++ segments for data from the beginning of main area, while
++ for node from the end of main area.
++nouser_xattr Disable Extended User Attributes. Note: xattr is enabled
++ by default if CONFIG_F2FS_FS_XATTR is selected.
++noacl Disable POSIX Access Control List. Note: acl is enabled
++ by default if CONFIG_F2FS_FS_POSIX_ACL is selected.
++active_logs=%u Support configuring the number of active logs. In the
++ current design, f2fs supports only 2, 4, and 6 logs.
++ Default number is 6.
++disable_ext_identify Disable the extension list configured by mkfs, so f2fs
++ does not aware of cold files such as media files.
++
++================================================================================
++PROC ENTRIES
++================================================================================
++
++/proc/fs/f2fs/ contains information about partitions mounted as f2fs. For each
++partition, a corresponding directory, named as its device name, is provided with
++the following proc entries.
++
++- f2fs_stat major file system information managed by f2fs currently
++- f2fs_sit_stat average utilization information of the whole segments
++- f2fs_mem_stat current memory footprint consumed by f2fs
++
++e.g., in /proc/fs/f2fs/sdb1/
++
++================================================================================
++USAGE
++================================================================================
++
++1. Download userland tools
++
++2. Insmod f2fs.ko module:
++ # insmod f2fs.ko
++
++3. Check the directory trying to mount
++ # mkdir /mnt/f2fs
++
++4. Format the block device, and then mount as f2fs
++ # mkfs.f2fs -l label /dev/block_device
++ # mount -t f2fs /dev/block_device /mnt/f2fs
++
++Mount options
++-------------
++-l [label] : Give a volume label, up to 256 unicode name.
++-a [0 or 1] : Split start location of each area for heap-based allocation.
++ 1 is set by default, which performs this.
++-o [int] : Set overprovision ratio in percent over volume size.
++ 5 is set by default.
++-s [int] : Set the number of segments per section.
++ 1 is set by default.
++-z [int] : Set the number of sections per zone.
++ 1 is set by default.
++-e [str] : Set basic extension list. e.g. "mp3,gif,mov"
++
++================================================================================
++DESIGN
++================================================================================
++
++On-disk Layout
++--------------
++
++F2FS divides the whole volume into a number of segments, each of which is 2MB in
++size by default. A section is composed of consecutive segments, and a zone
++consists of a set of sections.
++
++F2FS maintains logically six log areas. Except SB, all the log areas are managed
++in a unit of multiple segments. SB is located at the beginning of the partition,
++and there exist two superblocks to avoid file system crash. Other file system
++metadata such as CP, NAT, SIT, and SSA are located in the front part of the
++volume. Main area contains file and directory data including their indices.
++
++Each area manages the following contents.
++- CP File system information, bitmaps for valid NAT/SIT sets, orphan
++ inode lists, and summary entries of current active segments.
++- NAT Block address table for all the node blocks stored in Main area.
++- SIT Segment information such as valid block count and bitmap for the
++ validity of all the blocks.
++- SSA Summary entries which contains the owner information of all the
++ data and node blocks stored in Main area.
++- Main Node and data blocks.
++
++In order to avoid misalignment between file system and flash-based storage, F2FS
++aligns the start block address of CP with the segment size. Also, it aligns the
++start block address of Main area with the zone size by reserving some segments
++in SSA area.
++
++ align with the zone size <-|
++ |-> align with the segment size
++ _________________________________________________________________________
++ | | | Node | Segment | Segment | |
++ | Superblock | Checkpoint | Address | Info. | Summary | Main |
++ | (SB) | (CP) | Table (NAT) | Table (SIT) | Area (SSA) | |
++ |____________|_____2______|______N______|______N______|______N_____|__N___|
++ . .
++ . .
++ . .
++ ._________________________________________.
++ |_Segment_|_..._|_Segment_|_..._|_Segment_|
++ . .
++ ._________._________
++ |_section_|__...__|_
++ . .
++ .________.
++ |__zone__|
++
++
++File System Metadata Structure
++------------------------------
++
++F2FS adopts the checkpointing scheme to maintain file system consistency. At
++mount time, F2FS first tries to find the last valid checkpoint data by scanning
++CP area. In order to reduce the scanning time, F2FS uses only two copies of CP.
++One of them always indicates the last valid data, which is called as shadow copy
++mechanism. In addition to CP, NAT and SIT also adopt the shadow copy mechanism.
++
++For file system consistency, each CP points to which NAT and SIT copies are
++valid, as shown as below.
++
++ +--------+----------+---------+
++ | CP | NAT | SIT |
++ +--------+----------+---------+
++ . . . .
++ . . . .
++ . . . .
++ +-------+-------+--------+--------+--------+--------+
++ | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 |
++ +-------+-------+--------+--------+--------+--------+
++ | ^ ^
++ | | |
++ `----------------------------------------'
++
++Index Structure
++---------------
++
++The key data structure to manage the data locations is a "node". Similar to
++traditional file structures, F2FS has three types of node: inode, direct node,
++indirect node. F2FS assigns 4KB to an inode block which contains 929 data block
++indices, two direct node pointers, two indirect node pointers, and one double
++indirect node pointer as described below. One direct node block contains 1018
++data blocks, and one indirect node block contains also 1018 node blocks. Thus,
++one inode block (i.e., a file) covers:
++
++ 4KB * (927 + 2 * 1018 + 2 * 1018 * 1018 + 1018 * 1018 * 1018) := 3.94TB.
++
++ Inode block (4KB)
++ |- data (927)
++ |- direct node (2)
++ | `- data (1018)
++ |- indirect node (2)
++ | `- direct node (1018)
++ | `- data (1018)
++ `- double indirect node (1)
++ `- indirect node (1018)
++ `- direct node (1018)
++ `- data (1018)
++
++Note that, all the node blocks are mapped by NAT which means the location of
++each node is translated by the NAT table. In the consideration of the wandering
++tree problem, F2FS is able to cut off the propagation of node updates caused by
++leaf data writes.
++
++Directory Structure
++-------------------
++
++A directory entry occupies 11 bytes, which consists of the following attributes.
++
++- hash hash value of the file name
++- ino inode number
++- len the length of file name
++- type file type such as directory, symlink, etc
++
++A dentry block consists of 214 dentry slots and file names. Therein a bitmap is
++used to represent whether each dentry is valid or not. A dentry block occupies
++4KB with the following composition.
++
++ Dentry Block(4 K) = bitmap (27 bytes) + reserved (3 bytes) +
++ dentries(11 * 214 bytes) + file name (8 * 214 bytes)
++
++ [Bucket]
++ +--------------------------------+
++ |dentry block 1 | dentry block 2 |
++ +--------------------------------+
++ . .
++ . .
++ . [Dentry Block Structure: 4KB] .
++ +--------+----------+----------+------------+
++ | bitmap | reserved | dentries | file names |
++ +--------+----------+----------+------------+
++ [Dentry Block: 4KB] . .
++ . .
++ . .
++ +------+------+-----+------+
++ | hash | ino | len | type |
++ +------+------+-----+------+
++ [Dentry Structure: 11 bytes]
++
++F2FS implements multi-level hash tables for directory structure. Each level has
++a hash table with dedicated number of hash buckets as shown below. Note that
++"A(2B)" means a bucket includes 2 data blocks.
++
++----------------------
++A : bucket
++B : block
++N : MAX_DIR_HASH_DEPTH
++----------------------
++
++level #0 | A(2B)
++ |
++level #1 | A(2B) - A(2B)
++ |
++level #2 | A(2B) - A(2B) - A(2B) - A(2B)
++ . | . . . .
++level #N/2 | A(2B) - A(2B) - A(2B) - A(2B) - A(2B) - ... - A(2B)
++ . | . . . .
++level #N | A(4B) - A(4B) - A(4B) - A(4B) - A(4B) - ... - A(4B)
++
++The number of blocks and buckets are determined by,
++
++ ,- 2, if n < MAX_DIR_HASH_DEPTH / 2,
++ # of blocks in level #n = |
++ `- 4, Otherwise
++
++ ,- 2^n, if n < MAX_DIR_HASH_DEPTH / 2,
++ # of buckets in level #n = |
++ `- 2^((MAX_DIR_HASH_DEPTH / 2) - 1), Otherwise
++
++When F2FS finds a file name in a directory, at first a hash value of the file
++name is calculated. Then, F2FS scans the hash table in level #0 to find the
++dentry consisting of the file name and its inode number. If not found, F2FS
++scans the next hash table in level #1. In this way, F2FS scans hash tables in
++each levels incrementally from 1 to N. In each levels F2FS needs to scan only
++one bucket determined by the following equation, which shows O(log(# of files))
++complexity.
++
++ bucket number to scan in level #n = (hash value) % (# of buckets in level #n)
++
++In the case of file creation, F2FS finds empty consecutive slots that cover the
++file name. F2FS searches the empty slots in the hash tables of whole levels from
++1 to N in the same way as the lookup operation.
++
++The following figure shows an example of two cases holding children.
++ --------------> Dir <--------------
++ | |
++ child child
++
++ child - child [hole] - child
++
++ child - child - child [hole] - [hole] - child
++
++ Case 1: Case 2:
++ Number of children = 6, Number of children = 3,
++ File size = 7 File size = 7
++
++Default Block Allocation
++------------------------
++
++At runtime, F2FS manages six active logs inside "Main" area: Hot/Warm/Cold node
++and Hot/Warm/Cold data.
++
++- Hot node contains direct node blocks of directories.
++- Warm node contains direct node blocks except hot node blocks.
++- Cold node contains indirect node blocks
++- Hot data contains dentry blocks
++- Warm data contains data blocks except hot and cold data blocks
++- Cold data contains multimedia data or migrated data blocks
++
++LFS has two schemes for free space management: threaded log and copy-and-compac-
++tion. The copy-and-compaction scheme which is known as cleaning, is well-suited
++for devices showing very good sequential write performance, since free segments
++are served all the time for writing new data. However, it suffers from cleaning
++overhead under high utilization. Contrarily, the threaded log scheme suffers
++from random writes, but no cleaning process is needed. F2FS adopts a hybrid
++scheme where the copy-and-compaction scheme is adopted by default, but the
++policy is dynamically changed to the threaded log scheme according to the file
++system status.
++
++In order to align F2FS with underlying flash-based storage, F2FS allocates a
++segment in a unit of section. F2FS expects that the section size would be the
++same as the unit size of garbage collection in FTL. Furthermore, with respect
++to the mapping granularity in FTL, F2FS allocates each section of the active
++logs from different zones as much as possible, since FTL can write the data in
++the active logs into one allocation unit according to its mapping granularity.
++
++Cleaning process
++----------------
++
++F2FS does cleaning both on demand and in the background. On-demand cleaning is
++triggered when there are not enough free segments to serve VFS calls. Background
++cleaner is operated by a kernel thread, and triggers the cleaning job when the
++system is idle.
++
++F2FS supports two victim selection policies: greedy and cost-benefit algorithms.
++In the greedy algorithm, F2FS selects a victim segment having the smallest number
++of valid blocks. In the cost-benefit algorithm, F2FS selects a victim segment
++according to the segment age and the number of valid blocks in order to address
++log block thrashing problem in the greedy algorithm. F2FS adopts the greedy
++algorithm for on-demand cleaner, while background cleaner adopts cost-benefit
++algorithm.
++
++In order to identify whether the data in the victim segment are valid or not,
++F2FS manages a bitmap. Each bit represents the validity of a block, and the
++bitmap is composed of a bit stream covering whole blocks in main area.
diff --git a/patches/linux-3.7-rc6/0099-f2fs-add-on-disk-layout.patch b/patches/linux-3.7-rc6/0099-f2fs-add-on-disk-layout.patch
new file mode 100644
index 0000000..be4892c
--- /dev/null
+++ b/patches/linux-3.7-rc6/0099-f2fs-add-on-disk-layout.patch
@@ -0,0 +1,383 @@
+From 902033dcdb656694672091702bc88f5020b69443 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:26:00 +0000
+Subject: [PATCH] f2fs: add on-disk layout
+
+This adds a header file describing the on-disk layout of f2fs.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Chul Lee <chur.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ include/linux/f2fs_fs.h | 362 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 362 insertions(+)
+ create mode 100644 include/linux/f2fs_fs.h
+
+diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
+new file mode 100644
+index 0000000..bd9c217
+--- /dev/null
++++ b/include/linux/f2fs_fs.h
+@@ -0,0 +1,362 @@
++/**
++ * include/linux/f2fs_fs.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _LINUX_F2FS_FS_H
++#define _LINUX_F2FS_FS_H
++
++#include <linux/pagemap.h>
++#include <linux/types.h>
++
++#define F2FS_SUPER_MAGIC 0xF2F52010
++#define F2FS_SUPER_OFFSET 0 /* start sector # for sb */
++#define F2FS_BLKSIZE 4096
++#define F2FS_MAX_EXTENSION 64
++
++#define NULL_ADDR 0x0U
++#define NEW_ADDR -1U
++
++#define F2FS_ROOT_INO(sbi) (sbi->root_ino_num)
++#define F2FS_NODE_INO(sbi) (sbi->node_ino_num)
++#define F2FS_META_INO(sbi) (sbi->meta_ino_num)
++
++#define GFP_F2FS_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_ZERO)
++
++#define MAX_ACTIVE_LOGS 16
++#define MAX_ACTIVE_NODE_LOGS 8
++#define MAX_ACTIVE_DATA_LOGS 8
++
++/*
++ * For superblock
++ */
++struct f2fs_super_block {
++ __le32 magic; /* Magic Number */
++ __le16 major_ver; /* Major Version */
++ __le16 minor_ver; /* Minor Version */
++ __le32 log_sectorsize; /* log2 (Sector size in bytes) */
++ __le32 log_sectors_per_block; /* log2 (Number of sectors per block */
++ __le32 log_blocksize; /* log2 (Block size in bytes) */
++ __le32 log_blocks_per_seg; /* log2 (Number of blocks per segment) */
++ __le32 segs_per_sec; /* Number of segments per section */
++ __le32 secs_per_zone; /* Number of sections per zone */
++ __le32 checksum_offset; /* Checksum position in this super block */
++ __le64 block_count; /* Total number of blocks */
++ __le32 section_count; /* Total number of sections */
++ __le32 segment_count; /* Total number of segments */
++ __le32 segment_count_ckpt; /* Total number of segments
++ in Checkpoint area */
++ __le32 segment_count_sit; /* Total number of segments
++ in Segment information table */
++ __le32 segment_count_nat; /* Total number of segments
++ in Node address table */
++ /*Total number of segments in Segment summary area */
++ __le32 segment_count_ssa;
++ /* Total number of segments in Main area */
++ __le32 segment_count_main;
++ __le32 failure_safe_block_distance;
++ __le32 segment0_blkaddr; /* Start block address of Segment 0 */
++ __le32 start_segment_checkpoint; /* Start block address of ckpt */
++ __le32 sit_blkaddr; /* Start block address of SIT */
++ __le32 nat_blkaddr; /* Start block address of NAT */
++ __le32 ssa_blkaddr; /* Start block address of SSA */
++ __le32 main_blkaddr; /* Start block address of Main area */
++ __le32 root_ino; /* Root directory inode number */
++ __le32 node_ino; /* node inode number */
++ __le32 meta_ino; /* meta inode number */
++ __le32 volume_serial_number; /* VSN is optional field */
++ __le16 volume_name[512]; /* Volume Name */
++ __le32 extension_count;
++ __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */
++} __packed;
++
++/*
++ * For checkpoint
++ */
++struct f2fs_checkpoint {
++ __le64 checkpoint_ver; /* Checkpoint block version number */
++ __le64 user_block_count; /* # of user blocks */
++ __le64 valid_block_count; /* # of valid blocks in Main area */
++ __le32 rsvd_segment_count; /* # of reserved segments for gc */
++ __le32 overprov_segment_count; /* # of overprovision segments */
++ __le32 free_segment_count; /* # of free segments in Main area */
++
++ /* information of current node segments */
++ __le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS];
++ __le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
++ __le16 nat_upd_blkoff[MAX_ACTIVE_NODE_LOGS];
++ /* information of current data segments */
++ __le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS];
++ __le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
++ __le32 ckpt_flags; /* Flags : umount and journal_present */
++ __le32 cp_pack_total_block_count;
++ __le32 cp_pack_start_sum; /* start block number of data summary */
++ __le32 valid_node_count; /* Total number of valid nodes */
++ __le32 valid_inode_count; /* Total number of valid inodes */
++ __le32 next_free_nid; /* Next free node number */
++ __le32 sit_ver_bitmap_bytesize; /* Default value 64 */
++ __le32 nat_ver_bitmap_bytesize; /* Default value 256 */
++ __le32 checksum_offset; /* Checksum position
++ in this checkpoint block */
++ __le64 elapsed_time; /* elapsed time while partition
++ is mounted */
++ /* allocation type of current segment */
++ unsigned char alloc_type[MAX_ACTIVE_LOGS];
++
++ /* SIT and NAT version bitmap */
++ unsigned char sit_nat_version_bitmap[1];
++} __packed;
++
++/*
++ * For orphan inode management
++ */
++#define F2FS_ORPHANS_PER_BLOCK 1020
++
++struct f2fs_orphan_block {
++ __le32 ino[F2FS_ORPHANS_PER_BLOCK]; /* inode numbers */
++ __le32 reserved;
++ __le16 blk_addr; /* block index in current CP */
++ __le16 blk_count; /* Number of orphan inode blocks in CP */
++ __le32 entry_count; /* Total number of orphan nodes in current CP */
++ __le32 check_sum; /* CRC32 for orphan inode block */
++} __packed;
++
++/*
++ * For NODE structure
++ */
++struct f2fs_extent {
++ __le32 fofs;
++ __le32 blk_addr;
++ __le32 len;
++} __packed;
++
++#define F2FS_MAX_NAME_LEN 256
++#define ADDRS_PER_INODE 927 /* Address Pointers in an Inode */
++#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */
++#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */
++
++struct f2fs_inode {
++ __le16 i_mode; /* File mode */
++ __u8 i_advise; /* File hints */
++ __u8 i_reserved; /* Reserved */
++ __le32 i_uid; /* User ID */
++ __le32 i_gid; /* Group ID */
++ __le32 i_links; /* Links count */
++ __le64 i_size; /* File size in bytes */
++ __le64 i_blocks; /* File size in blocks */
++ __le64 i_ctime; /* Inode change time */
++ __le64 i_mtime; /* Modification time */
++ __le32 i_ctime_nsec;
++ __le32 i_mtime_nsec;
++ __le32 current_depth;
++ __le32 i_xattr_nid; /* nid to save xattr */
++ __le32 i_flags; /* file attributes */
++ __le32 i_pino; /* parent inode number */
++ __le32 i_namelen; /* file name length */
++ __u8 i_name[F2FS_MAX_NAME_LEN]; /* file name for SPOR */
++
++ struct f2fs_extent i_ext; /* caching a largest extent */
++
++ __le32 i_addr[ADDRS_PER_INODE]; /* Pointers to data blocks */
++
++ __le32 i_nid[5]; /* direct(2), indirect(2),
++ double_indirect(1) node id */
++} __packed;
++
++struct direct_node {
++ __le32 addr[ADDRS_PER_BLOCK]; /* array of data block address */
++} __packed;
++
++struct indirect_node {
++ __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */
++} __packed;
++
++enum {
++ COLD_BIT_SHIFT = 0,
++ FSYNC_BIT_SHIFT,
++ DENT_BIT_SHIFT,
++ OFFSET_BIT_SHIFT
++};
++
++struct node_footer {
++ __le32 nid; /* node id */
++ __le32 ino; /* inode nunmber */
++ __le32 flag; /* include cold/fsync/dentry marks and offset */
++ __le64 cp_ver; /* checkpoint version */
++ __le32 next_blkaddr; /* next node page block address */
++} __packed;
++
++struct f2fs_node {
++ union {
++ struct f2fs_inode i;
++ struct direct_node dn;
++ struct indirect_node in;
++ };
++ struct node_footer footer;
++} __packed;
++
++/*
++ * For NAT entries
++ */
++#define NAT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_nat_entry))
++
++struct f2fs_nat_entry {
++ __u8 version;
++ __le32 ino;
++ __le32 block_addr;
++} __packed;
++
++struct f2fs_nat_block {
++ struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK];
++} __packed;
++
++/*
++ * For SIT entries
++ */
++#define SIT_VBLOCK_MAP_SIZE 64
++#define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry))
++
++struct f2fs_sit_entry {
++ __le16 vblocks;
++ __u8 valid_map[SIT_VBLOCK_MAP_SIZE];
++ __le64 mtime;
++} __packed;
++
++struct f2fs_sit_block {
++ struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK];
++} __packed;
++
++/**
++ * For segment summary
++ *
++ * NOTE : For initializing fields, you must use set_summary
++ *
++ * - If data page, nid represents dnode's nid
++ * - If node page, nid represents the node page's nid.
++ *
++ * The ofs_in_node is used by only data page. It represents offset
++ * from node's page's beginning to get a data block address.
++ * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
++ */
++struct f2fs_summary {
++ __le32 nid;
++ union {
++ __u8 reserved[3];
++ struct {
++ __u8 version;
++ __le16 ofs_in_node;
++ } __packed;
++ };
++} __packed;
++
++struct summary_footer {
++ unsigned char entry_type;
++ __u32 check_sum;
++} __packed;
++
++#define SUMMARY_SIZE (sizeof(struct f2fs_summary))
++#define SUM_FOOTER_SIZE (sizeof(struct summary_footer))
++#define ENTRIES_IN_SUM 512
++#define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM)
++#define SUM_JOURNAL_SIZE (PAGE_CACHE_SIZE - SUM_FOOTER_SIZE -\
++ SUM_ENTRY_SIZE)
++struct nat_journal_entry {
++ __le32 nid;
++ struct f2fs_nat_entry ne;
++} __packed;
++
++struct sit_journal_entry {
++ __le32 segno;
++ struct f2fs_sit_entry se;
++} __packed;
++
++#define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
++ sizeof(struct nat_journal_entry))
++#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
++ sizeof(struct nat_journal_entry))
++#define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
++ sizeof(struct sit_journal_entry))
++#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
++ sizeof(struct sit_journal_entry))
++enum {
++ NAT_JOURNAL = 0,
++ SIT_JOURNAL
++};
++
++struct nat_journal {
++ struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
++ __u8 reserved[NAT_JOURNAL_RESERVED];
++} __packed;
++
++struct sit_journal {
++ struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
++ __u8 reserved[SIT_JOURNAL_RESERVED];
++} __packed;
++
++struct f2fs_summary_block {
++ struct f2fs_summary entries[ENTRIES_IN_SUM];
++ union {
++ __le16 n_nats;
++ __le16 n_sits;
++ };
++ union {
++ struct nat_journal nat_j;
++ struct sit_journal sit_j;
++ };
++ struct summary_footer footer;
++} __packed;
++
++/*
++ * For directory operations
++ */
++#define F2FS_DOT_HASH 0
++#define F2FS_DDOT_HASH F2FS_DOT_HASH
++#define F2FS_MAX_HASH (~((0x3ULL) << 62))
++#define F2FS_HASH_COL_BIT ((0x1ULL) << 63)
++
++typedef __le32 f2fs_hash_t;
++
++#define F2FS_NAME_LEN 8
++#define NR_DENTRY_IN_BLOCK 214 /* the number of dentry in a block */
++#define MAX_DIR_HASH_DEPTH 63 /* MAX level for dir lookup */
++
++#define SIZE_OF_DIR_ENTRY 11 /* by byte */
++#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
++ BITS_PER_BYTE)
++#define SIZE_OF_RESERVED (PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
++ F2FS_NAME_LEN) * \
++ NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
++
++struct f2fs_dir_entry {
++ __le32 hash_code; /* hash code of file name */
++ __le32 ino; /* node number of inode */
++ __le16 name_len; /* the size of file name
++ length in unicode characters */
++ __u8 file_type;
++} __packed;
++
++struct f2fs_dentry_block {
++ __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
++ __u8 reserved[SIZE_OF_RESERVED];
++ struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
++ __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_NAME_LEN];
++} __packed;
++
++enum {
++ F2FS_FT_UNKNOWN,
++ F2FS_FT_REG_FILE,
++ F2FS_FT_DIR,
++ F2FS_FT_CHRDEV,
++ F2FS_FT_BLKDEV,
++ F2FS_FT_FIFO,
++ F2FS_FT_SOCK,
++ F2FS_FT_SYMLINK,
++ F2FS_FT_MAX
++};
++
++#endif /* _LINUX_F2FS_FS_H */
diff --git a/patches/linux-3.7-rc6/0100-f2fs-add-superblock-and-major-in-memory-structure.patch b/patches/linux-3.7-rc6/0100-f2fs-add-superblock-and-major-in-memory-structure.patch
new file mode 100644
index 0000000..4f978c2
--- /dev/null
+++ b/patches/linux-3.7-rc6/0100-f2fs-add-superblock-and-major-in-memory-structure.patch
@@ -0,0 +1,1962 @@
+From 3cfaeeaa816257ae02bbd9486355ad02abbc4c08 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:26:49 +0000
+Subject: [PATCH] f2fs: add superblock and major in-memory structure
+
+This adds the following major in-memory structures in f2fs.
+
+- f2fs_sb_info:
+ contains f2fs-specific information, two special inode pointers for node and
+ meta address spaces, and orphan inode management.
+
+- f2fs_inode_info:
+ contains vfs_inode and other fs-specific information.
+
+- f2fs_nm_info:
+ contains node manager information such as NAT entry cache, free nid list,
+ and NAT page management.
+
+- f2fs_node_info:
+ represents a node as node id, inode number, block address, and its version.
+
+- f2fs_sm_info:
+ contains segment manager information such as SIT entry cache, free segment
+ map, current active logs, dirty segment management, and segment utilization.
+ The specific structures are sit_info, free_segmap_info, dirty_seglist_info,
+ curseg_info.
+
+Signed-off-by: Chul Lee <chur.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/f2fs.h | 982 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/node.h | 330 ++++++++++++++++++
+ fs/f2fs/segment.h | 594 ++++++++++++++++++++++++++++++++
+ 3 files changed, 1906 insertions(+)
+ create mode 100644 fs/f2fs/f2fs.h
+ create mode 100644 fs/f2fs/node.h
+ create mode 100644 fs/f2fs/segment.h
+
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+new file mode 100644
+index 0000000..bbe2f02
+--- /dev/null
++++ b/fs/f2fs/f2fs.h
+@@ -0,0 +1,982 @@
++/**
++ * fs/f2fs/f2fs.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _LINUX_F2FS_H
++#define _LINUX_F2FS_H
++
++#include <linux/types.h>
++#include <linux/page-flags.h>
++#include <linux/buffer_head.h>
++#include <linux/version.h>
++#include <linux/slab.h>
++#include <linux/crc32.h>
++
++/**
++ * For mount options
++ */
++#define F2FS_MOUNT_BG_GC 0x00000001
++#define F2FS_MOUNT_DISABLE_ROLL_FORWARD 0x00000002
++#define F2FS_MOUNT_DISCARD 0x00000004
++#define F2FS_MOUNT_NOHEAP 0x00000008
++#define F2FS_MOUNT_XATTR_USER 0x00000010
++#define F2FS_MOUNT_POSIX_ACL 0x00000020
++#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY 0x00000040
++
++#define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
++#define set_opt(sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
++#define test_opt(sbi, option) (sbi->mount_opt.opt & F2FS_MOUNT_##option)
++
++#define ver_after(a, b) (typecheck(unsigned long long, a) && \
++ typecheck(unsigned long long, b) && \
++ ((long long)((a) - (b)) > 0))
++
++typedef u64 block_t;
++typedef u32 nid_t;
++
++struct f2fs_mount_info {
++ unsigned int opt;
++};
++
++static inline __u32 f2fs_crc32(void *buff, size_t len)
++{
++ return crc32_le(F2FS_SUPER_MAGIC, buff, len);
++}
++
++static inline bool f2fs_crc_valid(__u32 blk_crc, void *buff, size_t buff_size)
++{
++ return f2fs_crc32(buff, buff_size) == blk_crc;
++}
++
++/**
++ * For checkpoint manager
++ */
++#define CP_ERROR_FLAG 0x00000008
++#define CP_COMPACT_SUM_FLAG 0x00000004
++#define CP_ORPHAN_PRESENT_FLAG 0x00000002
++#define CP_UMOUNT_FLAG 0x00000001
++
++enum {
++ NAT_BITMAP,
++ SIT_BITMAP
++};
++
++struct orphan_inode_entry {
++ struct list_head list;
++ nid_t ino;
++};
++
++struct dir_inode_entry {
++ struct list_head list;
++ struct inode *inode;
++};
++
++struct fsync_inode_entry {
++ struct list_head list;
++ struct inode *inode;
++ block_t blkaddr;
++};
++
++#define nats_in_cursum(sum) (le16_to_cpu(sum->n_nats))
++#define sits_in_cursum(sum) (le16_to_cpu(sum->n_sits))
++
++#define nat_in_journal(sum, i) (sum->nat_j.entries[i].ne)
++#define nid_in_journal(sum, i) (sum->nat_j.entries[i].nid)
++#define sit_in_journal(sum, i) (sum->sit_j.entries[i].se)
++#define segno_in_journal(sum, i) (sum->sit_j.entries[i].segno)
++
++static inline int update_nats_in_cursum(struct f2fs_summary_block *rs, int i)
++{
++ int before = nats_in_cursum(rs);
++ rs->n_nats = cpu_to_le16(before + i);
++ return before;
++}
++
++static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
++{
++ int before = sits_in_cursum(rs);
++ rs->n_sits = cpu_to_le16(before + i);
++ return before;
++}
++
++/**
++ * For INODE and NODE manager
++ */
++#define XATTR_NODE_OFFSET (-1)
++#define RDONLY_NODE 1
++#define F2FS_LINK_MAX 32000
++
++struct extent_info {
++ rwlock_t ext_lock;
++ unsigned int fofs;
++ u32 blk_addr;
++ unsigned int len;
++};
++
++#define FADVISE_COLD_BIT 0x01
++/*
++ * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
++ */
++struct f2fs_inode_info {
++ struct inode vfs_inode;
++ unsigned long i_flags;
++ unsigned long flags;
++ unsigned long long data_version;
++ atomic_t dirty_dents;
++ unsigned int current_depth;
++ f2fs_hash_t chash;
++ unsigned int clevel;
++ nid_t i_xattr_nid;
++ struct extent_info ext;
++ umode_t i_acl_mode;
++ unsigned char i_advise; /* If true, this is cold data */
++};
++
++static inline void get_extent_info(struct extent_info *ext,
++ struct f2fs_extent i_ext)
++{
++ write_lock(&ext->ext_lock);
++ ext->fofs = le32_to_cpu(i_ext.fofs);
++ ext->blk_addr = le32_to_cpu(i_ext.blk_addr);
++ ext->len = le32_to_cpu(i_ext.len);
++ write_unlock(&ext->ext_lock);
++}
++
++static inline void set_raw_extent(struct extent_info *ext,
++ struct f2fs_extent *i_ext)
++{
++ read_lock(&ext->ext_lock);
++ i_ext->fofs = cpu_to_le32(ext->fofs);
++ i_ext->blk_addr = cpu_to_le32(ext->blk_addr);
++ i_ext->len = cpu_to_le32(ext->len);
++ read_unlock(&ext->ext_lock);
++}
++
++struct f2fs_nm_info {
++ block_t nat_blkaddr; /* base disk address of NAT */
++ unsigned int nat_segs; /* the number of nat segments */
++ unsigned int nat_blocks; /* the number of nat blocks of
++ one size */
++ nid_t max_nid;
++ unsigned int nat_cnt; /* the number of nodes in NAT Buffer */
++ struct radix_tree_root nat_root;
++ rwlock_t nat_tree_lock; /* Protect nat_tree_lock */
++ struct list_head nat_entries; /* cached nat entry list (clean) */
++ struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */
++
++ unsigned int fcnt; /* the number of free node id */
++ struct mutex build_lock; /* lock for build free nids */
++
++ int nat_upd_blkoff[3]; /* Block offset
++ in the current journal segment
++ where the last NAT update happened */
++ int lst_upd_blkoff[3]; /* Block offset
++ in current journal segment */
++
++ unsigned int written_valid_node_count;
++ unsigned int written_valid_inode_count;
++ char *nat_bitmap; /* NAT bitmap pointer */
++ int bitmap_size; /* bitmap size */
++
++ nid_t init_scan_nid; /* the first nid to be scanned */
++ nid_t next_scan_nid; /* the next nid to be scanned */
++ struct list_head free_nid_list;
++ spinlock_t free_nid_list_lock; /* Protect free nid list */
++};
++
++struct dnode_of_data {
++ struct inode *inode;
++ struct page *inode_page;
++ struct page *node_page;
++ nid_t nid;
++ unsigned int ofs_in_node;
++ bool inode_page_locked;
++ block_t data_blkaddr;
++};
++
++static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
++ struct page *ipage, struct page *npage, nid_t nid)
++{
++ dn->inode = inode;
++ dn->inode_page = ipage;
++ dn->node_page = npage;
++ dn->nid = nid;
++ dn->inode_page_locked = 0;
++}
++
++/**
++ * For SIT manager
++ */
++#define NR_CURSEG_DATA_TYPE (3)
++#define NR_CURSEG_NODE_TYPE (3)
++#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
++
++enum {
++ CURSEG_HOT_DATA = 0,
++ CURSEG_WARM_DATA,
++ CURSEG_COLD_DATA,
++ CURSEG_HOT_NODE,
++ CURSEG_WARM_NODE,
++ CURSEG_COLD_NODE,
++ NO_CHECK_TYPE
++};
++
++struct f2fs_sm_info {
++ /* SIT information */
++ struct sit_info *sit_info;
++
++ /* Free segmap infomation */
++ struct free_segmap_info *free_info;
++
++ /* Dirty segments list information for GC victim */
++ struct dirty_seglist_info *dirty_info;
++
++ /* Current working segments(i.e. logging point) information array */
++ struct curseg_info *curseg_array;
++
++ /* list head of all under-writeback pages for flush handling */
++ struct list_head wblist_head;
++ spinlock_t wblist_lock;
++
++ block_t seg0_blkaddr;
++ block_t main_blkaddr;
++ unsigned int segment_count;
++ unsigned int rsvd_segment_count;
++ unsigned int main_segment_count;
++ block_t ssa_blkaddr;
++ unsigned int segment_count_ssa;
++};
++
++/**
++ * For Garbage Collection
++ */
++struct f2fs_gc_info {
++#ifdef CONFIG_F2FS_STAT_FS
++ struct list_head stat_list;
++ struct f2fs_stat_info *stat_info;
++#endif
++ int cause;
++ int rsvd_segment_count;
++ int overp_segment_count;
++};
++
++/**
++ * For directory operation
++ */
++#define F2FS_INODE_SIZE (17 * 4 + F2FS_MAX_NAME_LEN)
++#define NODE_DIR1_BLOCK (ADDRS_PER_INODE + 1)
++#define NODE_DIR2_BLOCK (ADDRS_PER_INODE + 2)
++#define NODE_IND1_BLOCK (ADDRS_PER_INODE + 3)
++#define NODE_IND2_BLOCK (ADDRS_PER_INODE + 4)
++#define NODE_DIND_BLOCK (ADDRS_PER_INODE + 5)
++
++/**
++ * For superblock
++ */
++enum count_type {
++ F2FS_WRITEBACK,
++ F2FS_DIRTY_DENTS,
++ F2FS_DIRTY_NODES,
++ F2FS_DIRTY_META,
++ NR_COUNT_TYPE,
++};
++
++/*
++ * FS_LOCK nesting subclasses for the lock validator:
++ *
++ * The locking order between these classes is
++ * RENAME -> DENTRY_OPS -> DATA_WRITE -> DATA_NEW
++ * -> DATA_TRUNC -> NODE_WRITE -> NODE_NEW -> NODE_TRUNC
++ */
++enum lock_type {
++ RENAME, /* for renaming operations */
++ DENTRY_OPS, /* for directory operations */
++ DATA_WRITE, /* for data write */
++ DATA_NEW, /* for data allocation */
++ DATA_TRUNC, /* for data truncate */
++ NODE_NEW, /* for node allocation */
++ NODE_TRUNC, /* for node truncate */
++ NODE_WRITE, /* for node write */
++ NR_LOCK_TYPE,
++};
++
++/*
++ * The below are the page types of bios used in submti_bio().
++ * The available types are:
++ * DATA User data pages. It operates as async mode.
++ * NODE Node pages. It operates as async mode.
++ * META FS metadata pages such as SIT, NAT, CP.
++ * NR_PAGE_TYPE The number of page types.
++ * META_FLUSH Make sure the previous pages are written
++ * with waiting the bio's completion
++ * ... Only can be used with META.
++ */
++enum page_type {
++ DATA,
++ NODE,
++ META,
++ NR_PAGE_TYPE,
++ META_FLUSH,
++};
++
++struct f2fs_sb_info {
++ struct super_block *sb; /* Pointer to VFS super block */
++ int s_dirty;
++ struct f2fs_super_block *raw_super; /* Pointer to the super block
++ in the buffer */
++ struct buffer_head *raw_super_buf; /* Buffer containing
++ the f2fs raw super block */
++ struct f2fs_checkpoint *ckpt; /* Pointer to the checkpoint
++ in the buffer */
++ struct mutex orphan_inode_mutex;
++ spinlock_t dir_inode_lock;
++ struct mutex cp_mutex;
++ /* orphan Inode list to be written in Journal block during CP */
++ struct list_head orphan_inode_list;
++ struct list_head dir_inode_list;
++ unsigned int n_orphans, n_dirty_dirs;
++
++ unsigned int log_sectorsize;
++ unsigned int log_sectors_per_block;
++ unsigned int log_blocksize;
++ unsigned int blocksize;
++ unsigned int root_ino_num; /* Root Inode Number*/
++ unsigned int node_ino_num; /* Root Inode Number*/
++ unsigned int meta_ino_num; /* Root Inode Number*/
++ unsigned int log_blocks_per_seg;
++ unsigned int blocks_per_seg;
++ unsigned int segs_per_sec;
++ unsigned int secs_per_zone;
++ unsigned int total_sections;
++ unsigned int total_node_count;
++ unsigned int total_valid_node_count;
++ unsigned int total_valid_inode_count;
++ unsigned int segment_count[2];
++ unsigned int block_count[2];
++ unsigned int last_victim[2];
++ int active_logs;
++ block_t user_block_count;
++ block_t total_valid_block_count;
++ block_t alloc_valid_block_count;
++ block_t last_valid_block_count;
++ atomic_t nr_pages[NR_COUNT_TYPE];
++
++ struct f2fs_mount_info mount_opt;
++
++ /* related to NM */
++ struct f2fs_nm_info *nm_info; /* Node Manager information */
++
++ /* related to SM */
++ struct f2fs_sm_info *sm_info; /* Segment Manager
++ information */
++ int total_hit_ext, read_hit_ext;
++ int rr_flush;
++
++ /* related to GC */
++ struct proc_dir_entry *s_proc;
++ struct f2fs_gc_info *gc_info; /* Garbage Collector
++ information */
++ struct mutex gc_mutex; /* mutex for GC */
++ struct mutex fs_lock[NR_LOCK_TYPE]; /* mutex for GP */
++ struct mutex write_inode; /* mutex for write inode */
++ struct mutex writepages; /* mutex for writepages() */
++ struct f2fs_gc_kthread *gc_thread; /* GC thread */
++ int bg_gc;
++ int last_gc_status;
++ int por_doing;
++
++ struct inode *node_inode;
++ struct inode *meta_inode;
++
++ struct bio *bio[NR_PAGE_TYPE];
++ sector_t last_block_in_bio[NR_PAGE_TYPE];
++ struct rw_semaphore bio_sem;
++ spinlock_t stat_lock; /* lock for handling the number
++ of valid blocks and
++ valid nodes */
++};
++
++/**
++ * Inline functions
++ */
++static inline struct f2fs_inode_info *F2FS_I(struct inode *inode)
++{
++ return container_of(inode, struct f2fs_inode_info, vfs_inode);
++}
++
++static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb)
++{
++ return sb->s_fs_info;
++}
++
++static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_super_block *)(sbi->raw_super);
++}
++
++static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_checkpoint *)(sbi->ckpt);
++}
++
++static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_nm_info *)(sbi->nm_info);
++}
++
++static inline struct f2fs_sm_info *SM_I(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_sm_info *)(sbi->sm_info);
++}
++
++static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
++{
++ return (struct sit_info *)(SM_I(sbi)->sit_info);
++}
++
++static inline struct free_segmap_info *FREE_I(struct f2fs_sb_info *sbi)
++{
++ return (struct free_segmap_info *)(SM_I(sbi)->free_info);
++}
++
++static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi)
++{
++ return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
++}
++
++static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi)
++{
++ sbi->s_dirty = 1;
++}
++
++static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi)
++{
++ sbi->s_dirty = 0;
++}
++
++static inline void mutex_lock_op(struct f2fs_sb_info *sbi, enum lock_type t)
++{
++ mutex_lock_nested(&sbi->fs_lock[t], t);
++}
++
++static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, enum lock_type t)
++{
++ mutex_unlock(&sbi->fs_lock[t]);
++}
++
++/**
++ * Check whether the given nid is within node id range.
++ */
++static inline void check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ BUG_ON((nid >= NM_I(sbi)->max_nid));
++}
++
++#define F2FS_DEFAULT_ALLOCATED_BLOCKS 1
++
++/**
++ * Check whether the inode has blocks or not
++ */
++static inline int F2FS_HAS_BLOCKS(struct inode *inode)
++{
++ if (F2FS_I(inode)->i_xattr_nid)
++ return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1);
++ else
++ return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS);
++}
++
++static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
++ struct inode *inode, blkcnt_t count)
++{
++ block_t valid_block_count;
++
++ spin_lock(&sbi->stat_lock);
++ valid_block_count =
++ sbi->total_valid_block_count + (block_t)count;
++ if (valid_block_count > sbi->user_block_count) {
++ spin_unlock(&sbi->stat_lock);
++ return false;
++ }
++ inode->i_blocks += count;
++ sbi->total_valid_block_count = valid_block_count;
++ sbi->alloc_valid_block_count += (block_t)count;
++ spin_unlock(&sbi->stat_lock);
++ return true;
++}
++
++static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
++ struct inode *inode,
++ blkcnt_t count)
++{
++ spin_lock(&sbi->stat_lock);
++ BUG_ON(sbi->total_valid_block_count < (block_t) count);
++ BUG_ON(inode->i_blocks < count);
++ inode->i_blocks -= count;
++ sbi->total_valid_block_count -= (block_t)count;
++ spin_unlock(&sbi->stat_lock);
++ return 0;
++}
++
++static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
++{
++ atomic_inc(&sbi->nr_pages[count_type]);
++ F2FS_SET_SB_DIRT(sbi);
++}
++
++static inline void inode_inc_dirty_dents(struct inode *inode)
++{
++ atomic_inc(&F2FS_I(inode)->dirty_dents);
++}
++
++static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
++{
++ atomic_dec(&sbi->nr_pages[count_type]);
++}
++
++static inline void inode_dec_dirty_dents(struct inode *inode)
++{
++ atomic_dec(&F2FS_I(inode)->dirty_dents);
++}
++
++static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
++{
++ return atomic_read(&sbi->nr_pages[count_type]);
++}
++
++static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
++{
++ block_t ret;
++ spin_lock(&sbi->stat_lock);
++ ret = sbi->total_valid_block_count;
++ spin_unlock(&sbi->stat_lock);
++ return ret;
++}
++
++static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++
++ /* return NAT or SIT bitmap */
++ if (flag == NAT_BITMAP)
++ return le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
++ else if (flag == SIT_BITMAP)
++ return le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
++
++ return 0;
++}
++
++static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ int offset = (flag == NAT_BITMAP) ? ckpt->sit_ver_bitmap_bytesize : 0;
++ return &ckpt->sit_nat_version_bitmap + offset;
++}
++
++static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
++{
++ block_t start_addr;
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ unsigned long long ckpt_version = le64_to_cpu(ckpt->checkpoint_ver);
++
++ start_addr = le64_to_cpu(F2FS_RAW_SUPER(sbi)->start_segment_checkpoint);
++
++ /*
++ * odd numbered checkpoint shoukd at cp segment 0
++ * and even segent must be at cp segment 1
++ */
++ if (!(ckpt_version & 1))
++ start_addr += sbi->blocks_per_seg;
++
++ return start_addr;
++}
++
++static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
++{
++ return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
++}
++
++static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
++ struct inode *inode,
++ unsigned int count)
++{
++ block_t valid_block_count;
++ unsigned int valid_node_count;
++
++ spin_lock(&sbi->stat_lock);
++
++ valid_block_count = sbi->total_valid_block_count + (block_t)count;
++ sbi->alloc_valid_block_count += (block_t)count;
++ valid_node_count = sbi->total_valid_node_count + count;
++
++ if (valid_block_count > sbi->user_block_count) {
++ spin_unlock(&sbi->stat_lock);
++ return false;
++ }
++
++ if (valid_node_count > sbi->total_node_count) {
++ spin_unlock(&sbi->stat_lock);
++ return false;
++ }
++
++ if (inode)
++ inode->i_blocks += count;
++ sbi->total_valid_node_count = valid_node_count;
++ sbi->total_valid_block_count = valid_block_count;
++ spin_unlock(&sbi->stat_lock);
++
++ return true;
++}
++
++static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
++ struct inode *inode,
++ unsigned int count)
++{
++ spin_lock(&sbi->stat_lock);
++
++ BUG_ON(sbi->total_valid_block_count < count);
++ BUG_ON(sbi->total_valid_node_count < count);
++ BUG_ON(inode->i_blocks < count);
++
++ inode->i_blocks -= count;
++ sbi->total_valid_node_count -= count;
++ sbi->total_valid_block_count -= (block_t)count;
++
++ spin_unlock(&sbi->stat_lock);
++}
++
++static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
++{
++ unsigned int ret;
++ spin_lock(&sbi->stat_lock);
++ ret = sbi->total_valid_node_count;
++ spin_unlock(&sbi->stat_lock);
++ return ret;
++}
++
++static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
++{
++ spin_lock(&sbi->stat_lock);
++ BUG_ON(sbi->total_valid_inode_count == sbi->total_node_count);
++ sbi->total_valid_inode_count++;
++ spin_unlock(&sbi->stat_lock);
++}
++
++static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi)
++{
++ spin_lock(&sbi->stat_lock);
++ BUG_ON(!sbi->total_valid_inode_count);
++ sbi->total_valid_inode_count--;
++ spin_unlock(&sbi->stat_lock);
++ return 0;
++}
++
++static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
++{
++ unsigned int ret;
++ spin_lock(&sbi->stat_lock);
++ ret = sbi->total_valid_inode_count;
++ spin_unlock(&sbi->stat_lock);
++ return ret;
++}
++
++static inline void f2fs_put_page(struct page *page, int unlock)
++{
++ if (!page || IS_ERR(page))
++ return;
++
++ if (unlock) {
++ BUG_ON(!PageLocked(page));
++ unlock_page(page);
++ }
++ page_cache_release(page);
++}
++
++static inline void f2fs_put_dnode(struct dnode_of_data *dn)
++{
++ if (dn->node_page)
++ f2fs_put_page(dn->node_page, 1);
++ if (dn->inode_page && dn->node_page != dn->inode_page)
++ f2fs_put_page(dn->inode_page, 0);
++ dn->node_page = NULL;
++ dn->inode_page = NULL;
++}
++
++static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name,
++ size_t size, void (*ctor)(void *))
++{
++ return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, ctor);
++}
++
++#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino)
++
++static inline bool IS_INODE(struct page *page)
++{
++ struct f2fs_node *p = (struct f2fs_node *)page_address(page);
++ return RAW_IS_INODE(p);
++}
++
++static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
++{
++ return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr;
++}
++
++static inline block_t datablock_addr(struct page *node_page,
++ unsigned int offset)
++{
++ struct f2fs_node *raw_node;
++ __le32 *addr_array;
++ raw_node = (struct f2fs_node *)page_address(node_page);
++ addr_array = blkaddr_in_node(raw_node);
++ return le32_to_cpu(addr_array[offset]);
++}
++
++static inline int f2fs_test_bit(unsigned int nr, char *addr)
++{
++ int mask;
++
++ addr += (nr >> 3);
++ mask = 1 << (7 - (nr & 0x07));
++ return mask & *addr;
++}
++
++static inline int f2fs_set_bit(unsigned int nr, char *addr)
++{
++ int mask;
++ int ret;
++
++ addr += (nr >> 3);
++ mask = 1 << (7 - (nr & 0x07));
++ ret = mask & *addr;
++ *addr |= mask;
++ return ret;
++}
++
++static inline int f2fs_clear_bit(unsigned int nr, char *addr)
++{
++ int mask;
++ int ret;
++
++ addr += (nr >> 3);
++ mask = 1 << (7 - (nr & 0x07));
++ ret = mask & *addr;
++ *addr &= ~mask;
++ return ret;
++}
++
++enum {
++ FI_NEW_INODE,
++ FI_NEED_CP,
++ FI_INC_LINK,
++ FI_ACL_MODE,
++ FI_NO_ALLOC,
++};
++
++static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
++{
++ set_bit(flag, &fi->flags);
++}
++
++static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag)
++{
++ return test_bit(flag, &fi->flags);
++}
++
++static inline void clear_inode_flag(struct f2fs_inode_info *fi, int flag)
++{
++ clear_bit(flag, &fi->flags);
++}
++
++static inline void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode)
++{
++ fi->i_acl_mode = mode;
++ set_inode_flag(fi, FI_ACL_MODE);
++}
++
++static inline int cond_clear_inode_flag(struct f2fs_inode_info *fi, int flag)
++{
++ if (is_inode_flag_set(fi, FI_ACL_MODE)) {
++ clear_inode_flag(fi, FI_ACL_MODE);
++ return 1;
++ }
++ return 0;
++}
++
++/**
++ * file.c
++ */
++int f2fs_sync_file(struct file *, loff_t, loff_t, int);
++void truncate_data_blocks(struct dnode_of_data *);
++void f2fs_truncate(struct inode *);
++int f2fs_setattr(struct dentry *, struct iattr *);
++int truncate_hole(struct inode *, pgoff_t, pgoff_t);
++long f2fs_ioctl(struct file *, unsigned int, unsigned long);
++
++/**
++ * inode.c
++ */
++void f2fs_set_inode_flags(struct inode *);
++struct inode *f2fs_iget_nowait(struct super_block *, unsigned long);
++struct inode *f2fs_iget(struct super_block *, unsigned long);
++void update_inode(struct inode *, struct page *);
++int f2fs_write_inode(struct inode *, struct writeback_control *);
++void f2fs_evict_inode(struct inode *);
++
++/**
++ * dir.c
++ */
++struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
++ struct page **);
++struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
++void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
++ struct page *, struct inode *);
++void init_dent_inode(struct dentry *, struct page *);
++int f2fs_add_link(struct dentry *, struct inode *);
++void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *);
++int f2fs_make_empty(struct inode *, struct inode *);
++bool f2fs_empty_dir(struct inode *);
++
++/**
++ * super.c
++ */
++int f2fs_sync_fs(struct super_block *, int);
++
++/**
++ * hash.c
++ */
++f2fs_hash_t f2fs_dentry_hash(const char *, int);
++
++/**
++ * node.c
++ */
++struct dnode_of_data;
++struct node_info;
++
++int is_checkpointed_node(struct f2fs_sb_info *, nid_t);
++void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
++int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
++int truncate_inode_blocks(struct inode *, pgoff_t);
++int remove_inode_page(struct inode *);
++int new_inode_page(struct inode *, struct dentry *);
++struct page *new_node_page(struct dnode_of_data *, unsigned int);
++void ra_node_page(struct f2fs_sb_info *, nid_t);
++struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
++struct page *get_node_page_ra(struct page *, int);
++void sync_inode_page(struct dnode_of_data *);
++int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *);
++bool alloc_nid(struct f2fs_sb_info *, nid_t *);
++void alloc_nid_done(struct f2fs_sb_info *, nid_t);
++void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
++void recover_node_page(struct f2fs_sb_info *, struct page *,
++ struct f2fs_summary *, struct node_info *, block_t);
++int recover_inode_page(struct f2fs_sb_info *, struct page *);
++int restore_node_summary(struct f2fs_sb_info *, unsigned int,
++ struct f2fs_summary_block *);
++void flush_nat_entries(struct f2fs_sb_info *);
++int build_node_manager(struct f2fs_sb_info *);
++void destroy_node_manager(struct f2fs_sb_info *);
++int create_node_manager_caches(void);
++void destroy_node_manager_caches(void);
++
++/**
++ * segment.c
++ */
++void f2fs_balance_fs(struct f2fs_sb_info *);
++void invalidate_blocks(struct f2fs_sb_info *, block_t);
++void locate_dirty_segment(struct f2fs_sb_info *, unsigned int);
++void clear_prefree_segments(struct f2fs_sb_info *);
++int npages_for_summary_flush(struct f2fs_sb_info *);
++void allocate_new_segments(struct f2fs_sb_info *);
++struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
++struct bio *f2fs_bio_alloc(struct block_device *, sector_t, int, gfp_t);
++void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync);
++int write_meta_page(struct f2fs_sb_info *, struct page *,
++ struct writeback_control *);
++void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
++ block_t, block_t *);
++void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
++ block_t, block_t *);
++void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
++void recover_data_page(struct f2fs_sb_info *, struct page *,
++ struct f2fs_summary *, block_t, block_t);
++void rewrite_node_page(struct f2fs_sb_info *, struct page *,
++ struct f2fs_summary *, block_t, block_t);
++void write_data_summaries(struct f2fs_sb_info *, block_t);
++void write_node_summaries(struct f2fs_sb_info *, block_t);
++int lookup_journal_in_cursum(struct f2fs_summary_block *,
++ int, unsigned int, int);
++void flush_sit_entries(struct f2fs_sb_info *);
++int build_segment_manager(struct f2fs_sb_info *);
++void reset_victim_segmap(struct f2fs_sb_info *);
++void destroy_segment_manager(struct f2fs_sb_info *);
++
++/**
++ * checkpoint.c
++ */
++struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
++struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
++long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
++int check_orphan_space(struct f2fs_sb_info *);
++void add_orphan_inode(struct f2fs_sb_info *, nid_t);
++void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
++int recover_orphan_inodes(struct f2fs_sb_info *);
++int get_valid_checkpoint(struct f2fs_sb_info *);
++void set_dirty_dir_page(struct inode *, struct page *);
++void remove_dirty_dir_inode(struct inode *);
++void sync_dirty_dir_inodes(struct f2fs_sb_info *);
++void block_operations(struct f2fs_sb_info *);
++void write_checkpoint(struct f2fs_sb_info *, bool, bool);
++void init_orphan_info(struct f2fs_sb_info *);
++int create_checkpoint_caches(void);
++void destroy_checkpoint_caches(void);
++
++/**
++ * data.c
++ */
++int reserve_new_block(struct dnode_of_data *);
++void update_extent_cache(block_t, struct dnode_of_data *);
++struct page *find_data_page(struct inode *, pgoff_t);
++struct page *get_lock_data_page(struct inode *, pgoff_t);
++struct page *get_new_data_page(struct inode *, pgoff_t, bool);
++int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
++int do_write_data_page(struct page *);
++
++/**
++ * gc.c
++ */
++int start_gc_thread(struct f2fs_sb_info *);
++void stop_gc_thread(struct f2fs_sb_info *);
++block_t start_bidx_of_node(unsigned int);
++int f2fs_gc(struct f2fs_sb_info *, int);
++#ifdef CONFIG_F2FS_STAT_FS
++void f2fs_update_stat(struct f2fs_sb_info *);
++void f2fs_update_gc_metric(struct f2fs_sb_info *);
++int f2fs_stat_init(struct f2fs_sb_info *);
++void f2fs_stat_exit(struct f2fs_sb_info *);
++#endif
++int build_gc_manager(struct f2fs_sb_info *);
++void destroy_gc_manager(struct f2fs_sb_info *);
++int create_gc_caches(void);
++void destroy_gc_caches(void);
++
++/**
++ * recovery.c
++ */
++void recover_fsync_data(struct f2fs_sb_info *);
++bool space_for_roll_forward(struct f2fs_sb_info *);
++
++extern const struct file_operations f2fs_dir_operations;
++extern const struct file_operations f2fs_file_operations;
++extern const struct inode_operations f2fs_file_inode_operations;
++extern const struct address_space_operations f2fs_dblock_aops;
++extern const struct address_space_operations f2fs_node_aops;
++extern const struct address_space_operations f2fs_meta_aops;
++extern const struct inode_operations f2fs_dir_inode_operations;
++extern const struct inode_operations f2fs_symlink_inode_operations;
++extern const struct inode_operations f2fs_special_inode_operations;
++#endif
+diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
+new file mode 100644
+index 0000000..99ac689
+--- /dev/null
++++ b/fs/f2fs/node.h
+@@ -0,0 +1,330 @@
++/**
++ * fs/f2fs/node.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#define START_NID(nid) ((nid / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK)
++#define NAT_BLOCK_OFFSET(start_nid) (start_nid / NAT_ENTRY_PER_BLOCK)
++
++#define FREE_NID_PAGES 4
++#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
++
++#define MAX_RA_NODE 128 /* Max. readahead size for node */
++#define NM_WOUT_THRESHOLD (64 * NAT_ENTRY_PER_BLOCK)
++#define NATVEC_SIZE 64
++
++/**
++ * For node information
++ */
++struct node_info {
++ nid_t nid; /* node id */
++ nid_t ino; /* inode number of the node's owner */
++ block_t blk_addr; /* block address of the node */
++ unsigned char version; /* version of the node */
++};
++
++static inline unsigned char inc_node_version(unsigned char version)
++{
++ return ++version;
++}
++
++struct nat_entry {
++ struct list_head list; /* for clean or dirty nat list */
++ bool checkpointed;
++ struct node_info ni;
++};
++
++#define nat_get_nid(nat) (nat->ni.nid)
++#define nat_set_nid(nat, n) (nat->ni.nid = n)
++#define nat_get_blkaddr(nat) (nat->ni.blk_addr)
++#define nat_set_blkaddr(nat, b) (nat->ni.blk_addr = b)
++#define nat_get_ino(nat) (nat->ni.ino)
++#define nat_set_ino(nat, i) (nat->ni.ino = i)
++#define nat_get_version(nat) (nat->ni.version)
++#define nat_set_version(nat, v) (nat->ni.version = v)
++#define __set_nat_cache_dirty(nm_i, ne) \
++ list_move_tail(&ne->list, &nm_i->dirty_nat_entries);
++#define __clear_nat_cache_dirty(nm_i, ne) \
++ list_move_tail(&ne->list, &nm_i->nat_entries);
++
++static inline void node_info_from_raw_nat(struct node_info *ni,
++ struct f2fs_nat_entry *raw_ne)
++{
++ ni->ino = le32_to_cpu(raw_ne->ino);
++ ni->blk_addr = le32_to_cpu(raw_ne->block_addr);
++ ni->version = raw_ne->version;
++}
++
++/**
++ * For free nid mangement
++ */
++enum nid_state {
++ NID_NEW,
++ NID_ALLOC
++};
++
++struct free_nid {
++ nid_t nid;
++ int state;
++ struct list_head list;
++};
++
++static inline int next_free_nid(struct f2fs_sb_info *sbi, nid_t *nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *fnid;
++
++ if (nm_i->fcnt <= 0)
++ return -1;
++ spin_lock(&nm_i->free_nid_list_lock);
++ fnid = list_entry(nm_i->free_nid_list.next, struct free_nid, list);
++ *nid = fnid->nid;
++ spin_unlock(&nm_i->free_nid_list_lock);
++ return 0;
++}
++
++/**
++ * inline functions
++ */
++static inline void get_nat_bitmap(struct f2fs_sb_info *sbi, void *addr)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ memcpy(addr, nm_i->nat_bitmap, nm_i->bitmap_size);
++}
++
++static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ pgoff_t block_off;
++ pgoff_t block_addr;
++ int seg_off;
++
++ block_off = NAT_BLOCK_OFFSET(start);
++ seg_off = block_off >> sbi->log_blocks_per_seg;
++
++ block_addr = (pgoff_t)(nm_i->nat_blkaddr +
++ (seg_off << sbi->log_blocks_per_seg << 1) +
++ (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
++
++ if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
++ block_addr += sbi->blocks_per_seg;
++
++ return block_addr;
++}
++
++static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
++ pgoff_t block_addr)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++
++ block_addr -= nm_i->nat_blkaddr;
++ if ((block_addr >> sbi->log_blocks_per_seg) % 2)
++ block_addr -= sbi->blocks_per_seg;
++ else
++ block_addr += sbi->blocks_per_seg;
++
++ return block_addr + nm_i->nat_blkaddr;
++}
++
++static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
++{
++ unsigned int block_off = NAT_BLOCK_OFFSET(start_nid);
++
++ if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
++ f2fs_clear_bit(block_off, nm_i->nat_bitmap);
++ else
++ f2fs_set_bit(block_off, nm_i->nat_bitmap);
++}
++
++static inline void fill_node_footer(struct page *page, nid_t nid,
++ nid_t ino, unsigned int ofs, bool reset)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ if (reset)
++ memset(rn, 0, sizeof(*rn));
++ rn->footer.nid = cpu_to_le32(nid);
++ rn->footer.ino = cpu_to_le32(ino);
++ rn->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT);
++}
++
++static inline void copy_node_footer(struct page *dst, struct page *src)
++{
++ void *src_addr = page_address(src);
++ void *dst_addr = page_address(dst);
++ struct f2fs_node *src_rn = (struct f2fs_node *)src_addr;
++ struct f2fs_node *dst_rn = (struct f2fs_node *)dst_addr;
++ memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
++}
++
++static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ rn->footer.cp_ver = ckpt->checkpoint_ver;
++ rn->footer.next_blkaddr = blkaddr;
++}
++
++static inline nid_t ino_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le32_to_cpu(rn->footer.ino);
++}
++
++static inline nid_t nid_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le32_to_cpu(rn->footer.nid);
++}
++
++static inline unsigned int ofs_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned flag = le32_to_cpu(rn->footer.flag);
++ return flag >> OFFSET_BIT_SHIFT;
++}
++
++static inline unsigned long long cpver_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le64_to_cpu(rn->footer.cp_ver);
++}
++
++static inline block_t next_blkaddr_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le32_to_cpu(rn->footer.next_blkaddr);
++}
++
++static inline bool IS_DNODE(struct page *node_page)
++{
++ unsigned int ofs = ofs_of_node(node_page);
++ if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
++ ofs == 5 + 2 * NIDS_PER_BLOCK)
++ return false;
++ if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
++ ofs -= 6 + 2 * NIDS_PER_BLOCK;
++ if ((long int)ofs % (NIDS_PER_BLOCK + 1))
++ return false;
++ }
++ return true;
++}
++
++static inline void set_nid(struct page *p, int off, nid_t nid, bool i)
++{
++ struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
++
++ wait_on_page_writeback(p);
++
++ if (i)
++ rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
++ else
++ rn->in.nid[off] = cpu_to_le32(nid);
++ set_page_dirty(p);
++}
++
++static inline nid_t get_nid(struct page *p, int off, bool i)
++{
++ struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
++ if (i)
++ return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
++ return le32_to_cpu(rn->in.nid[off]);
++}
++
++/**
++ * Coldness identification:
++ * - Mark cold files in f2fs_inode_info
++ * - Mark cold node blocks in their node footer
++ * - Mark cold data pages in page cache
++ */
++static inline int is_cold_file(struct inode *inode)
++{
++ return F2FS_I(inode)->i_advise & FADVISE_COLD_BIT;
++}
++
++static inline int is_cold_data(struct page *page)
++{
++ return PageChecked(page);
++}
++
++static inline void set_cold_data(struct page *page)
++{
++ SetPageChecked(page);
++}
++
++static inline void clear_cold_data(struct page *page)
++{
++ ClearPageChecked(page);
++}
++
++static inline int is_cold_node(struct page *page)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ return flag & (0x1 << COLD_BIT_SHIFT);
++}
++
++static inline unsigned char is_fsync_dnode(struct page *page)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ return flag & (0x1 << FSYNC_BIT_SHIFT);
++}
++
++static inline unsigned char is_dent_dnode(struct page *page)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ return flag & (0x1 << DENT_BIT_SHIFT);
++}
++
++static inline void set_cold_node(struct inode *inode, struct page *page)
++{
++ struct f2fs_node *rn = (struct f2fs_node *)page_address(page);
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++
++ if (S_ISDIR(inode->i_mode))
++ flag &= ~(0x1 << COLD_BIT_SHIFT);
++ else
++ flag |= (0x1 << COLD_BIT_SHIFT);
++ rn->footer.flag = cpu_to_le32(flag);
++}
++
++static inline void set_fsync_mark(struct page *page, int mark)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ if (mark)
++ flag |= (0x1 << FSYNC_BIT_SHIFT);
++ else
++ flag &= ~(0x1 << FSYNC_BIT_SHIFT);
++ rn->footer.flag = cpu_to_le32(flag);
++}
++
++static inline void set_dentry_mark(struct page *page, int mark)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ if (mark)
++ flag |= (0x1 << DENT_BIT_SHIFT);
++ else
++ flag &= ~(0x1 << DENT_BIT_SHIFT);
++ rn->footer.flag = cpu_to_le32(flag);
++}
+diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
+new file mode 100644
+index 0000000..cd6268e
+--- /dev/null
++++ b/fs/f2fs/segment.h
+@@ -0,0 +1,594 @@
++/**
++ * fs/f2fs/segment.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++/* constant macro */
++#define NULL_SEGNO ((unsigned int)(~0))
++#define SUM_TYPE_NODE (1)
++#define SUM_TYPE_DATA (0)
++
++/* V: Logical segment # in volume, R: Relative segment # in main area */
++#define GET_L2R_SEGNO(free_i, segno) (segno - free_i->start_segno)
++#define GET_R2L_SEGNO(free_i, segno) (segno + free_i->start_segno)
++
++#define IS_DATASEG(t) \
++ ((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) || \
++ (t == CURSEG_WARM_DATA))
++
++#define IS_NODESEG(t) \
++ ((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) || \
++ (t == CURSEG_WARM_NODE))
++
++#define IS_CURSEG(sbi, segno) \
++ ((segno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
++
++#define IS_CURSEC(sbi, secno) \
++ ((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \
++ sbi->segs_per_sec)) \
++
++#define START_BLOCK(sbi, segno) \
++ (SM_I(sbi)->seg0_blkaddr + \
++ (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg))
++#define NEXT_FREE_BLKADDR(sbi, curseg) \
++ (START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff)
++
++#define MAIN_BASE_BLOCK(sbi) (SM_I(sbi)->main_blkaddr)
++
++#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr) \
++ ((blk_addr) - SM_I(sbi)->seg0_blkaddr)
++#define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \
++ (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
++#define GET_SEGNO(sbi, blk_addr) \
++ (((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ? \
++ NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \
++ GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
++#define GET_SECNO(sbi, segno) \
++ ((segno) / sbi->segs_per_sec)
++#define GET_ZONENO_FROM_SEGNO(sbi, segno) \
++ ((segno / sbi->segs_per_sec) / sbi->secs_per_zone)
++
++#define GET_SUM_BLOCK(sbi, segno) \
++ ((sbi->sm_info->ssa_blkaddr) + segno)
++
++#define GET_SUM_TYPE(footer) ((footer)->entry_type)
++#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type)
++
++#define SIT_ENTRY_OFFSET(sit_i, segno) \
++ (segno % sit_i->sents_per_block)
++#define SIT_BLOCK_OFFSET(sit_i, segno) \
++ (segno / SIT_ENTRY_PER_BLOCK)
++#define START_SEGNO(sit_i, segno) \
++ (SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK)
++#define f2fs_bitmap_size(nr) \
++ (BITS_TO_LONGS(nr) * sizeof(unsigned long))
++#define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segment_count)
++
++enum {
++ LFS = 0,
++ SSR
++};
++
++enum {
++ ALLOC_RIGHT = 0,
++ ALLOC_LEFT
++};
++
++#define SET_SSR_TYPE(type) (((type) + 1) << 16)
++#define GET_SSR_TYPE(type) (((type) >> 16) - 1)
++#define IS_SSR_TYPE(type) ((type) >= (0x1 << 16))
++#define IS_NEXT_SEG(sbi, curseg, type) \
++ (DIRTY_I(sbi)->v_ops->get_victim(sbi, &(curseg)->next_segno, \
++ BG_GC, SET_SSR_TYPE(type)))
++/**
++ * The MSB 6 bits of f2fs_sit_entry->vblocks has segment type,
++ * and LSB 10 bits has valid blocks.
++ */
++#define VBLOCKS_MASK ((1 << 10) - 1)
++
++#define GET_SIT_VBLOCKS(raw_sit) \
++ (le16_to_cpu((raw_sit)->vblocks) & VBLOCKS_MASK)
++#define GET_SIT_TYPE(raw_sit) \
++ ((le16_to_cpu((raw_sit)->vblocks) & ~VBLOCKS_MASK) >> 10)
++
++struct bio_private {
++ struct f2fs_sb_info *sbi;
++ bool is_sync;
++ void *wait;
++};
++
++enum {
++ GC_CB = 0,
++ GC_GREEDY
++};
++
++struct victim_sel_policy {
++ int alloc_mode;
++ int gc_mode;
++ int type;
++ unsigned long *dirty_segmap;
++ unsigned int offset;
++ unsigned int ofs_unit;
++ unsigned int min_cost;
++ unsigned int min_segno;
++};
++
++struct seg_entry {
++ unsigned short valid_blocks;
++ unsigned char *cur_valid_map;
++ unsigned short ckpt_valid_blocks;
++ unsigned char *ckpt_valid_map;
++ unsigned char type;
++ unsigned long long mtime;
++};
++
++struct sec_entry {
++ unsigned int valid_blocks;
++};
++
++struct segment_allocation {
++ void (*allocate_segment)(struct f2fs_sb_info *, int, bool);
++};
++
++struct sit_info {
++ const struct segment_allocation *s_ops;
++
++ block_t sit_base_addr;
++ block_t sit_blocks;
++ block_t written_valid_blocks; /* total number of valid blocks
++ in main area */
++ char *sit_bitmap; /* SIT bitmap pointer */
++ unsigned int bitmap_size;
++
++ unsigned int dirty_sentries; /* # of dirty sentries */
++ unsigned long *dirty_sentries_bitmap; /* bitmap for dirty sentries */
++ unsigned int sents_per_block; /* number of SIT entries
++ per SIT block */
++ struct mutex sentry_lock; /* to protect SIT entries */
++ struct seg_entry *sentries;
++ struct sec_entry *sec_entries;
++
++ unsigned long long elapsed_time;
++ unsigned long long mounted_time;
++ unsigned long long min_mtime;
++ unsigned long long max_mtime;
++};
++
++struct free_segmap_info {
++ unsigned int start_segno;
++ unsigned int free_segments;
++ unsigned int free_sections;
++ rwlock_t segmap_lock; /* free segmap lock */
++ unsigned long *free_segmap;
++ unsigned long *free_secmap;
++};
++
++/* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */
++enum dirty_type {
++ DIRTY_HOT_DATA, /* a few valid blocks in a data segment */
++ DIRTY_WARM_DATA,
++ DIRTY_COLD_DATA,
++ DIRTY_HOT_NODE, /* a few valid blocks in a node segment */
++ DIRTY_WARM_NODE,
++ DIRTY_COLD_NODE,
++ DIRTY,
++ PRE, /* no valid blocks in a segment */
++ NR_DIRTY_TYPE
++};
++
++enum {
++ BG_GC,
++ FG_GC
++};
++
++struct dirty_seglist_info {
++ const struct victim_selection *v_ops;
++ struct mutex seglist_lock;
++ unsigned long *dirty_segmap[NR_DIRTY_TYPE];
++ int nr_dirty[NR_DIRTY_TYPE];
++ unsigned long *victim_segmap[2]; /* BG_GC, FG_GC */
++};
++
++struct victim_selection {
++ int (*get_victim)(struct f2fs_sb_info *, unsigned int *, int, int);
++};
++
++struct curseg_info {
++ struct mutex curseg_mutex;
++ struct f2fs_summary_block *sum_blk;
++ unsigned char alloc_type;
++ unsigned int segno;
++ unsigned short next_blkoff;
++ unsigned int zone;
++ unsigned int next_segno;
++};
++
++/**
++ * inline functions
++ */
++static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
++{
++ return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
++}
++
++static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ return &sit_i->sentries[segno];
++}
++
++static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ return &sit_i->sec_entries[GET_SECNO(sbi, segno)];
++}
++
++static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
++ unsigned int segno, int section)
++{
++ if (section > 1)
++ return get_sec_entry(sbi, segno)->valid_blocks;
++ else
++ return get_seg_entry(sbi, segno)->valid_blocks;
++}
++
++static inline void seg_info_from_raw_sit(struct seg_entry *se,
++ struct f2fs_sit_entry *rs)
++{
++ se->valid_blocks = GET_SIT_VBLOCKS(rs);
++ se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs);
++ memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
++ memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
++ se->type = GET_SIT_TYPE(rs);
++ se->mtime = le64_to_cpu(rs->mtime);
++}
++
++static inline void seg_info_to_raw_sit(struct seg_entry *se,
++ struct f2fs_sit_entry *rs)
++{
++ unsigned short raw_vblocks = (se->type << 10) | se->valid_blocks;
++ rs->vblocks = cpu_to_le16(raw_vblocks);
++ memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
++ memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
++ se->ckpt_valid_blocks = se->valid_blocks;
++ rs->mtime = cpu_to_le64(se->mtime);
++}
++
++static inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
++ unsigned int max, unsigned int segno)
++{
++ unsigned int ret;
++ read_lock(&free_i->segmap_lock);
++ ret = find_next_bit(free_i->free_segmap, max, segno);
++ read_unlock(&free_i->segmap_lock);
++ return ret;
++}
++
++static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ unsigned int start_segno = secno * sbi->segs_per_sec;
++ unsigned int next;
++
++ write_lock(&free_i->segmap_lock);
++ clear_bit(segno, free_i->free_segmap);
++ free_i->free_segments++;
++
++ next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), start_segno);
++ if (next >= start_segno + sbi->segs_per_sec) {
++ clear_bit(secno, free_i->free_secmap);
++ free_i->free_sections++;
++ }
++ write_unlock(&free_i->segmap_lock);
++}
++
++static inline void __set_inuse(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ set_bit(segno, free_i->free_segmap);
++ free_i->free_segments--;
++ if (!test_and_set_bit(secno, free_i->free_secmap))
++ free_i->free_sections--;
++}
++
++static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ unsigned int start_segno = secno * sbi->segs_per_sec;
++ unsigned int next;
++
++ write_lock(&free_i->segmap_lock);
++ if (test_and_clear_bit(segno, free_i->free_segmap)) {
++ free_i->free_segments++;
++
++ next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi),
++ start_segno);
++ if (next >= start_segno + sbi->segs_per_sec) {
++ if (test_and_clear_bit(secno, free_i->free_secmap))
++ free_i->free_sections++;
++ }
++ }
++ write_unlock(&free_i->segmap_lock);
++}
++
++static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ write_lock(&free_i->segmap_lock);
++ if (!test_and_set_bit(segno, free_i->free_segmap)) {
++ free_i->free_segments--;
++ if (!test_and_set_bit(secno, free_i->free_secmap))
++ free_i->free_sections--;
++ }
++ write_unlock(&free_i->segmap_lock);
++}
++
++static inline void get_sit_bitmap(struct f2fs_sb_info *sbi,
++ void *dst_addr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size);
++}
++
++static inline block_t written_block_count(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ block_t vblocks;
++
++ mutex_lock(&sit_i->sentry_lock);
++ vblocks = sit_i->written_valid_blocks;
++ mutex_unlock(&sit_i->sentry_lock);
++
++ return vblocks;
++}
++
++static inline unsigned int free_segments(struct f2fs_sb_info *sbi)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int free_segs;
++
++ read_lock(&free_i->segmap_lock);
++ free_segs = free_i->free_segments;
++ read_unlock(&free_i->segmap_lock);
++
++ return free_segs;
++}
++
++static inline int reserved_segments(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return gc_i->rsvd_segment_count;
++}
++
++static inline unsigned int free_sections(struct f2fs_sb_info *sbi)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int free_secs;
++
++ read_lock(&free_i->segmap_lock);
++ free_secs = free_i->free_sections;
++ read_unlock(&free_i->segmap_lock);
++
++ return free_secs;
++}
++
++static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi)
++{
++ return DIRTY_I(sbi)->nr_dirty[PRE];
++}
++
++static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi)
++{
++ return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE];
++}
++
++static inline int overprovision_segments(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return gc_i->overp_segment_count;
++}
++
++static inline int overprovision_sections(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return ((unsigned int) gc_i->overp_segment_count) / sbi->segs_per_sec;
++}
++
++static inline int reserved_sections(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return ((unsigned int) gc_i->rsvd_segment_count) / sbi->segs_per_sec;
++}
++
++static inline bool need_SSR(struct f2fs_sb_info *sbi)
++{
++ return (free_sections(sbi) < overprovision_sections(sbi));
++}
++
++static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi)
++{
++ return free_sections(sbi) <= reserved_sections(sbi);
++}
++
++static inline int utilization(struct f2fs_sb_info *sbi)
++{
++ return (long int)valid_user_blocks(sbi) * 100 /
++ (long int)sbi->user_block_count;
++}
++
++/* Disable In-Place-Update by default */
++#define MIN_IPU_UTIL 100
++static inline bool need_inplace_update(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ if (S_ISDIR(inode->i_mode))
++ return false;
++ if (need_SSR(sbi) && utilization(sbi) > MIN_IPU_UTIL)
++ return true;
++ return false;
++}
++
++static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi,
++ int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ return curseg->segno;
++}
++
++static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi,
++ int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ return curseg->alloc_type;
++}
++
++static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ return curseg->next_blkoff;
++}
++
++static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ unsigned int end_segno = SM_I(sbi)->segment_count - 1;
++ BUG_ON(segno > end_segno);
++}
++
++/*
++ * This function is used for only debugging.
++ * NOTE: In future, we have to remove this function.
++ */
++static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ block_t total_blks = sm_info->segment_count << sbi->log_blocks_per_seg;
++ block_t start_addr = sm_info->seg0_blkaddr;
++ block_t end_addr = start_addr + total_blks - 1;
++ BUG_ON(blk_addr < start_addr);
++ BUG_ON(blk_addr > end_addr);
++}
++
++/**
++ * Summary block is always treated as invalid block
++ */
++static inline void check_block_count(struct f2fs_sb_info *sbi,
++ int segno, struct f2fs_sit_entry *raw_sit)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ unsigned int end_segno = sm_info->segment_count - 1;
++ int valid_blocks = 0;
++ int i;
++
++ /* check segment usage */
++ BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg);
++
++ /* check boundary of a given segment number */
++ BUG_ON(segno > end_segno);
++
++ /* check bitmap with valid block count */
++ for (i = 0; i < sbi->blocks_per_seg; i++)
++ if (f2fs_test_bit(i, raw_sit->valid_map))
++ valid_blocks++;
++ BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks);
++}
++
++static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
++ unsigned int start)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int offset = SIT_BLOCK_OFFSET(sit_i, start);
++ block_t blk_addr = sit_i->sit_base_addr + offset;
++
++ check_seg_range(sbi, start);
++
++ /* calculate sit block address */
++ if (f2fs_test_bit(offset, sit_i->sit_bitmap))
++ blk_addr += sit_i->sit_blocks;
++
++ return blk_addr;
++}
++
++static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi,
++ pgoff_t block_addr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ block_addr -= sit_i->sit_base_addr;
++ if (block_addr < sit_i->sit_blocks)
++ block_addr += sit_i->sit_blocks;
++ else
++ block_addr -= sit_i->sit_blocks;
++
++ return block_addr + sit_i->sit_base_addr;
++}
++
++static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
++{
++ unsigned int block_off = SIT_BLOCK_OFFSET(sit_i, start);
++
++ if (f2fs_test_bit(block_off, sit_i->sit_bitmap))
++ f2fs_clear_bit(block_off, sit_i->sit_bitmap);
++ else
++ f2fs_set_bit(block_off, sit_i->sit_bitmap);
++}
++
++static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec -
++ sit_i->mounted_time;
++}
++
++static inline void set_summary(struct f2fs_summary *sum, nid_t nid,
++ unsigned int ofs_in_node, unsigned char version)
++{
++ sum->nid = cpu_to_le32(nid);
++ sum->ofs_in_node = cpu_to_le16(ofs_in_node);
++ sum->version = version;
++}
++
++static inline block_t start_sum_block(struct f2fs_sb_info *sbi)
++{
++ return __start_cp_addr(sbi) +
++ le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
++}
++
++static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
++{
++ return __start_cp_addr(sbi) +
++ le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
++ - (base + 1) + type;
++}
diff --git a/patches/linux-3.7-rc6/0101-f2fs-add-super-block-operations.patch b/patches/linux-3.7-rc6/0101-f2fs-add-super-block-operations.patch
new file mode 100644
index 0000000..84e9529
--- /dev/null
+++ b/patches/linux-3.7-rc6/0101-f2fs-add-super-block-operations.patch
@@ -0,0 +1,612 @@
+From b75928193c6e929da5808d20204910c4c7b4eed7 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:27:13 +0000
+Subject: [PATCH] f2fs: add super block operations
+
+This adds the implementation of superblock operations for f2fs, which includes
+- init_f2fs_fs/exit_f2fs_fs
+- f2fs_mount
+- super_operations of f2fs
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/super.c | 590 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 590 insertions(+)
+ create mode 100644 fs/f2fs/super.c
+
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+new file mode 100644
+index 0000000..8e608a0
+--- /dev/null
++++ b/fs/f2fs/super.c
+@@ -0,0 +1,590 @@
++/**
++ * fs/f2fs/super.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/statfs.h>
++#include <linux/proc_fs.h>
++#include <linux/buffer_head.h>
++#include <linux/backing-dev.h>
++#include <linux/kthread.h>
++#include <linux/parser.h>
++#include <linux/mount.h>
++#include <linux/seq_file.h>
++#include <linux/f2fs_fs.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "xattr.h"
++
++static struct kmem_cache *f2fs_inode_cachep;
++static struct proc_dir_entry *f2fs_proc_root;
++
++enum {
++ Opt_gc_background_off,
++ Opt_disable_roll_forward,
++ Opt_discard,
++ Opt_noheap,
++ Opt_nouser_xattr,
++ Opt_noacl,
++ Opt_active_logs,
++ Opt_disable_ext_identify,
++ Opt_err,
++};
++
++static match_table_t f2fs_tokens = {
++ {Opt_gc_background_off, "background_gc_off"},
++ {Opt_disable_roll_forward, "disable_roll_forward"},
++ {Opt_discard, "discard"},
++ {Opt_noheap, "no_heap"},
++ {Opt_nouser_xattr, "nouser_xattr"},
++ {Opt_noacl, "noacl"},
++ {Opt_active_logs, "active_logs=%u"},
++ {Opt_disable_ext_identify, "disable_ext_identify"},
++ {Opt_err, NULL},
++};
++
++static void init_once(void *foo)
++{
++ struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
++
++ memset(fi, 0, sizeof(*fi));
++ inode_init_once(&fi->vfs_inode);
++}
++
++static struct inode *f2fs_alloc_inode(struct super_block *sb)
++{
++ struct f2fs_inode_info *fi;
++
++ fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_NOFS | __GFP_ZERO);
++ if (!fi)
++ return NULL;
++
++ init_once((void *) fi);
++
++ /* Initilize f2fs-specific inode info */
++ fi->vfs_inode.i_version = 1;
++ atomic_set(&fi->dirty_dents, 0);
++ fi->current_depth = 1;
++ fi->i_advise = 0;
++ rwlock_init(&fi->ext.ext_lock);
++
++ set_inode_flag(fi, FI_NEW_INODE);
++
++ return &fi->vfs_inode;
++}
++
++static void f2fs_i_callback(struct rcu_head *head)
++{
++ struct inode *inode = container_of(head, struct inode, i_rcu);
++ kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode));
++}
++
++void f2fs_destroy_inode(struct inode *inode)
++{
++ call_rcu(&inode->i_rcu, f2fs_i_callback);
++}
++
++static void f2fs_put_super(struct super_block *sb)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++
++#ifdef CONFIG_F2FS_STAT_FS
++ if (sbi->s_proc) {
++ f2fs_stat_exit(sbi);
++ remove_proc_entry(sb->s_id, f2fs_proc_root);
++ }
++#endif
++ stop_gc_thread(sbi);
++
++ write_checkpoint(sbi, false, true);
++
++ iput(sbi->node_inode);
++ iput(sbi->meta_inode);
++
++ /* destroy f2fs internal modules */
++ destroy_gc_manager(sbi);
++ destroy_node_manager(sbi);
++ destroy_segment_manager(sbi);
++
++ kfree(sbi->ckpt);
++
++ sb->s_fs_info = NULL;
++ brelse(sbi->raw_super_buf);
++ kfree(sbi);
++}
++
++int f2fs_sync_fs(struct super_block *sb, int sync)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ int ret = 0;
++
++ if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
++ return 0;
++
++ if (sync)
++ write_checkpoint(sbi, false, false);
++
++ return ret;
++}
++
++static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ struct super_block *sb = dentry->d_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ block_t total_count, user_block_count, start_count, ovp_count;
++
++ total_count = le64_to_cpu(sbi->raw_super->block_count);
++ user_block_count = sbi->user_block_count;
++ start_count = le32_to_cpu(sbi->raw_super->segment0_blkaddr);
++ ovp_count = sbi->gc_info->overp_segment_count
++ << sbi->log_blocks_per_seg;
++ buf->f_type = F2FS_SUPER_MAGIC;
++ buf->f_bsize = sbi->blocksize;
++
++ buf->f_blocks = total_count - start_count;
++ buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count;
++ buf->f_bavail = user_block_count - valid_user_blocks(sbi);
++
++ buf->f_files = valid_inode_count(sbi);
++ buf->f_ffree = sbi->total_node_count - valid_node_count(sbi);
++
++ buf->f_namelen = F2FS_MAX_NAME_LEN;
++
++ return 0;
++}
++
++static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb);
++
++ if (test_opt(sbi, BG_GC))
++ seq_puts(seq, ",background_gc_on");
++ else
++ seq_puts(seq, ",background_gc_off");
++ if (test_opt(sbi, DISABLE_ROLL_FORWARD))
++ seq_puts(seq, ",disable_roll_forward");
++ if (test_opt(sbi, DISCARD))
++ seq_puts(seq, ",discard");
++ if (test_opt(sbi, NOHEAP))
++ seq_puts(seq, ",no_heap_alloc");
++#ifdef CONFIG_F2FS_FS_XATTR
++ if (test_opt(sbi, XATTR_USER))
++ seq_puts(seq, ",user_xattr");
++ else
++ seq_puts(seq, ",nouser_xattr");
++#endif
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ if (test_opt(sbi, POSIX_ACL))
++ seq_puts(seq, ",acl");
++ else
++ seq_puts(seq, ",noacl");
++#endif
++ if (test_opt(sbi, DISABLE_EXT_IDENTIFY))
++ seq_puts(seq, ",disable_ext_indentify");
++
++ seq_printf(seq, ",active_logs=%u", sbi->active_logs);
++
++ return 0;
++}
++
++static struct super_operations f2fs_sops = {
++ .alloc_inode = f2fs_alloc_inode,
++ .destroy_inode = f2fs_destroy_inode,
++ .write_inode = f2fs_write_inode,
++ .show_options = f2fs_show_options,
++ .evict_inode = f2fs_evict_inode,
++ .put_super = f2fs_put_super,
++ .sync_fs = f2fs_sync_fs,
++ .statfs = f2fs_statfs,
++};
++
++static int parse_options(struct f2fs_sb_info *sbi, char *options)
++{
++ substring_t args[MAX_OPT_ARGS];
++ char *p;
++ int arg = 0;
++
++ if (!options)
++ return 0;
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ if (!*p)
++ continue;
++ /*
++ * Initialize args struct so we know whether arg was
++ * found; some options take optional arguments.
++ */
++ args[0].to = args[0].from = NULL;
++ token = match_token(p, f2fs_tokens, args);
++
++ switch (token) {
++ case Opt_gc_background_off:
++ clear_opt(sbi, BG_GC);
++ break;
++ case Opt_disable_roll_forward:
++ set_opt(sbi, DISABLE_ROLL_FORWARD);
++ break;
++ case Opt_discard:
++ set_opt(sbi, DISCARD);
++ break;
++ case Opt_noheap:
++ set_opt(sbi, NOHEAP);
++ break;
++#ifdef CONFIG_F2FS_FS_XATTR
++ case Opt_nouser_xattr:
++ clear_opt(sbi, XATTR_USER);
++ break;
++#else
++ case Opt_nouser_xattr:
++ pr_info("nouser_xattr options not supported\n");
++ break;
++#endif
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ case Opt_noacl:
++ clear_opt(sbi, POSIX_ACL);
++ break;
++#else
++ case Opt_noacl:
++ pr_info("noacl options not supported\n");
++ break;
++#endif
++ case Opt_active_logs:
++ if (args->from && match_int(args, &arg))
++ return -EINVAL;
++ if (arg != 2 && arg != 4 && arg != 6)
++ return -EINVAL;
++ sbi->active_logs = arg;
++ break;
++ case Opt_disable_ext_identify:
++ set_opt(sbi, DISABLE_EXT_IDENTIFY);
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
++ return 0;
++}
++
++static loff_t max_file_size(unsigned bits)
++{
++ loff_t result = ADDRS_PER_INODE;
++ loff_t leaf_count = ADDRS_PER_BLOCK;
++
++ result += (leaf_count * 2);
++
++ leaf_count *= NIDS_PER_BLOCK;
++ result += (leaf_count * 2);
++
++ leaf_count *= NIDS_PER_BLOCK;
++ result += (leaf_count * 2);
++
++ result <<= bits;
++ return result;
++}
++
++static int sanity_check_raw_super(struct f2fs_super_block *raw_super)
++{
++ unsigned int blocksize;
++
++ if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic))
++ return 1;
++
++ /* Currently, support only 4KB block size */
++ blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
++ if (blocksize != PAGE_CACHE_SIZE)
++ return 1;
++ if (le32_to_cpu(raw_super->log_sectorsize) != 9)
++ return 1;
++ if (le32_to_cpu(raw_super->log_sectors_per_block) != 3)
++ return 1;
++ return 0;
++}
++
++static int sanity_check_ckpt(struct f2fs_super_block *raw_super,
++ struct f2fs_checkpoint *ckpt)
++{
++ unsigned int total, fsmeta;
++
++ total = le32_to_cpu(raw_super->segment_count);
++ fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
++ fsmeta += le32_to_cpu(raw_super->segment_count_sit);
++ fsmeta += le32_to_cpu(raw_super->segment_count_nat);
++ fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
++ fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
++
++ if (fsmeta >= total)
++ return 1;
++ return 0;
++}
++
++static void init_sb_info(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *raw_super = sbi->raw_super;
++ int i;
++
++ sbi->log_sectorsize = le32_to_cpu(raw_super->log_sectorsize);
++ sbi->log_sectors_per_block =
++ le32_to_cpu(raw_super->log_sectors_per_block);
++ sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize);
++ sbi->blocksize = 1 << sbi->log_blocksize;
++ sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
++ sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg;
++ sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
++ sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
++ sbi->total_sections = le32_to_cpu(raw_super->section_count);
++ sbi->total_node_count =
++ (le32_to_cpu(raw_super->segment_count_nat) / 2)
++ * sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK;
++ sbi->root_ino_num = le32_to_cpu(raw_super->root_ino);
++ sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
++ sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
++
++ for (i = 0; i < NR_COUNT_TYPE; i++)
++ atomic_set(&sbi->nr_pages[i], 0);
++}
++
++static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
++{
++ struct f2fs_sb_info *sbi;
++ struct f2fs_super_block *raw_super;
++ struct buffer_head *raw_super_buf;
++ struct inode *root;
++ int i;
++
++ /* allocate memory for f2fs-specific super block info */
++ sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
++ if (!sbi)
++ return -ENOMEM;
++
++ /* set a temporary block size */
++ if (!sb_set_blocksize(sb, F2FS_BLKSIZE))
++ goto free_sbi;
++
++ /* read f2fs raw super block */
++ raw_super_buf = sb_bread(sb, F2FS_SUPER_OFFSET);
++ if (!raw_super_buf)
++ goto free_sbi;
++ raw_super = (struct f2fs_super_block *) ((char *)raw_super_buf->b_data);
++
++ /* init some FS parameters */
++ sbi->active_logs = NR_CURSEG_TYPE;
++
++ set_opt(sbi, BG_GC);
++
++#ifdef CONFIG_F2FS_FS_XATTR
++ set_opt(sbi, XATTR_USER);
++#endif
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ set_opt(sbi, POSIX_ACL);
++#endif
++ /* parse mount options */
++ if (parse_options(sbi, (char *)data))
++ goto free_sb_buf;
++
++ /* sanity checking of raw super */
++ if (sanity_check_raw_super(raw_super))
++ goto free_sb_buf;
++
++ sb->s_maxbytes = max_file_size(raw_super->log_blocksize);
++ sb->s_max_links = F2FS_LINK_MAX;
++
++ sb->s_op = &f2fs_sops;
++ sb->s_xattr = f2fs_xattr_handlers;
++ sb->s_magic = F2FS_SUPER_MAGIC;
++ sb->s_fs_info = sbi;
++ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
++ (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
++
++ /* init f2fs-specific super block info */
++ sbi->sb = sb;
++ sbi->raw_super = raw_super;
++ sbi->raw_super_buf = raw_super_buf;
++ mutex_init(&sbi->gc_mutex);
++ mutex_init(&sbi->write_inode);
++ mutex_init(&sbi->writepages);
++ mutex_init(&sbi->cp_mutex);
++ for (i = 0; i < NR_LOCK_TYPE; i++)
++ mutex_init(&sbi->fs_lock[i]);
++ sbi->por_doing = 0;
++ spin_lock_init(&sbi->stat_lock);
++ init_rwsem(&sbi->bio_sem);
++ init_sb_info(sbi);
++
++ /* get an inode for meta space */
++ sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
++ if (IS_ERR(sbi->meta_inode))
++ goto free_sb_buf;
++
++ if (get_valid_checkpoint(sbi))
++ goto free_meta_inode;
++
++ /* sanity checking of checkpoint */
++ if (sanity_check_ckpt(raw_super, sbi->ckpt))
++ goto free_cp;
++
++ sbi->total_valid_node_count =
++ le32_to_cpu(sbi->ckpt->valid_node_count);
++ sbi->total_valid_inode_count =
++ le32_to_cpu(sbi->ckpt->valid_inode_count);
++ sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);
++ sbi->total_valid_block_count =
++ le64_to_cpu(sbi->ckpt->valid_block_count);
++ sbi->last_valid_block_count = sbi->total_valid_block_count;
++ sbi->alloc_valid_block_count = 0;
++ INIT_LIST_HEAD(&sbi->dir_inode_list);
++ spin_lock_init(&sbi->dir_inode_lock);
++
++ /* init super block */
++ if (!sb_set_blocksize(sb, sbi->blocksize))
++ goto free_cp;
++
++ init_orphan_info(sbi);
++
++ /* setup f2fs internal modules */
++ if (build_segment_manager(sbi))
++ goto free_sm;
++ if (build_node_manager(sbi))
++ goto free_nm;
++ if (build_gc_manager(sbi))
++ goto free_gc;
++
++ /* get an inode for node space */
++ sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
++ if (IS_ERR(sbi->node_inode))
++ goto free_gc;
++
++ /* if there are nt orphan nodes free them */
++ if (recover_orphan_inodes(sbi))
++ goto free_node_inode;
++
++ /* read root inode and dentry */
++ root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
++ if (IS_ERR(root))
++ goto free_node_inode;
++ if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size)
++ goto free_root_inode;
++
++ sb->s_root = d_make_root(root); /* allocate root dentry */
++ if (!sb->s_root)
++ goto free_root_inode;
++
++ /* recover fsynced data */
++ if (!test_opt(sbi, DISABLE_ROLL_FORWARD))
++ recover_fsync_data(sbi);
++
++ /* After POR, we can run background GC thread */
++ if (start_gc_thread(sbi))
++ goto fail;
++
++#ifdef CONFIG_F2FS_STAT_FS
++ if (f2fs_proc_root) {
++ sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
++ if (f2fs_stat_init(sbi))
++ goto fail;
++ }
++#endif
++ return 0;
++fail:
++ stop_gc_thread(sbi);
++free_root_inode:
++ make_bad_inode(root);
++ iput(root);
++free_node_inode:
++ make_bad_inode(sbi->node_inode);
++ iput(sbi->node_inode);
++free_gc:
++ destroy_gc_manager(sbi);
++free_nm:
++ destroy_node_manager(sbi);
++free_sm:
++ destroy_segment_manager(sbi);
++free_cp:
++ kfree(sbi->ckpt);
++free_meta_inode:
++ make_bad_inode(sbi->meta_inode);
++ iput(sbi->meta_inode);
++free_sb_buf:
++ brelse(raw_super_buf);
++free_sbi:
++ kfree(sbi);
++ return -EINVAL;
++}
++
++static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *data)
++{
++ return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super);
++}
++
++static struct file_system_type f2fs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "f2fs",
++ .mount = f2fs_mount,
++ .kill_sb = kill_block_super,
++ .fs_flags = FS_REQUIRES_DEV,
++};
++
++static int init_inodecache(void)
++{
++ f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache",
++ sizeof(struct f2fs_inode_info), NULL);
++ if (f2fs_inode_cachep == NULL)
++ return -ENOMEM;
++ return 0;
++}
++
++static void destroy_inodecache(void)
++{
++ /*
++ * Make sure all delayed rcu free inodes are flushed before we
++ * destroy cache.
++ */
++ rcu_barrier();
++ kmem_cache_destroy(f2fs_inode_cachep);
++}
++
++static int __init init_f2fs_fs(void)
++{
++ if (init_inodecache())
++ goto fail;
++ if (create_node_manager_caches())
++ goto fail;
++ if (create_gc_caches())
++ goto fail;
++ if (create_checkpoint_caches())
++ goto fail;
++ if (register_filesystem(&f2fs_fs_type))
++ return -EBUSY;
++
++ f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
++ return 0;
++fail:
++ return -ENOMEM;
++}
++
++static void __exit exit_f2fs_fs(void)
++{
++ remove_proc_entry("fs/f2fs", NULL);
++ unregister_filesystem(&f2fs_fs_type);
++ destroy_checkpoint_caches();
++ destroy_gc_caches();
++ destroy_node_manager_caches();
++ destroy_inodecache();
++}
++
++module_init(init_f2fs_fs)
++module_exit(exit_f2fs_fs)
++
++MODULE_AUTHOR("Samsung Electronics's Praesto Team");
++MODULE_DESCRIPTION("Flash Friendly File System");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.7-rc6/0102-f2fs-add-checkpoint-operations.patch b/patches/linux-3.7-rc6/0102-f2fs-add-checkpoint-operations.patch
new file mode 100644
index 0000000..7da534b
--- /dev/null
+++ b/patches/linux-3.7-rc6/0102-f2fs-add-checkpoint-operations.patch
@@ -0,0 +1,834 @@
+From d7db5b2e4d88ad2fa8f6d03c653e081593e8602d Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:28:03 +0000
+Subject: [PATCH] f2fs: add checkpoint operations
+
+This adds functions required by the checkpoint operations.
+
+Basically, f2fs adopts a roll-back model with checkpoint blocks written in the
+CP area. The checkpoint procedure includes as follows.
+
+- write_checkpoint()
+1. block_operations() freezes VFS calls.
+2. submit cached bios.
+3. flush_nat_entries() writes NAT pages updated by dirty NAT entries.
+4. flush_sit_entries() writes SIT pages updated by dirty SIT entries.
+5. do_checkpoint() writes,
+ - checkpoint block (#0)
+ - orphan inode blocks
+ - summary blocks made by active logs
+ - checkpoint block (copy of #0)
+6. unblock_opeations()
+
+In order to provide an address space for meta pages, f2fs_sb_info has a special
+inode, namely meta_inode. This patch also adds the address space operations for
+meta_inode.
+
+Signed-off-by: Chul Lee <chur.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/checkpoint.c | 795 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 795 insertions(+)
+ create mode 100644 fs/f2fs/checkpoint.c
+
+diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
+new file mode 100644
+index 0000000..a0601cc
+--- /dev/null
++++ b/fs/f2fs/checkpoint.c
+@@ -0,0 +1,795 @@
++/**
++ * fs/f2fs/checkpoint.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/bio.h>
++#include <linux/mpage.h>
++#include <linux/writeback.h>
++#include <linux/blkdev.h>
++#include <linux/f2fs_fs.h>
++#include <linux/pagevec.h>
++#include <linux/swap.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++static struct kmem_cache *orphan_entry_slab;
++static struct kmem_cache *inode_entry_slab;
++
++/**
++ * We guarantee no failure on the returned page.
++ */
++struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ struct page *page = NULL;
++repeat:
++ page = grab_cache_page(mapping, index);
++ if (!page) {
++ cond_resched();
++ goto repeat;
++ }
++
++ /* We wait writeback only inside grab_meta_page() */
++ wait_on_page_writeback(page);
++ SetPageUptodate(page);
++ return page;
++}
++
++/**
++ * We guarantee no failure on the returned page.
++ */
++struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ struct page *page;
++repeat:
++ page = grab_cache_page(mapping, index);
++ if (!page) {
++ cond_resched();
++ goto repeat;
++ }
++ if (f2fs_readpage(sbi, page, index, READ_SYNC)) {
++ f2fs_put_page(page, 1);
++ goto repeat;
++ }
++ mark_page_accessed(page);
++
++ /* We do not allow returning an errorneous page */
++ return page;
++}
++
++static int f2fs_write_meta_page(struct page *page,
++ struct writeback_control *wbc)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int err;
++
++ wait_on_page_writeback(page);
++
++ err = write_meta_page(sbi, page, wbc);
++ if (err) {
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ }
++
++ dec_page_count(sbi, F2FS_DIRTY_META);
++
++ /* In this case, we should not unlock this page */
++ if (err != AOP_WRITEPAGE_ACTIVATE)
++ unlock_page(page);
++ return err;
++}
++
++static int f2fs_write_meta_pages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++ struct block_device *bdev = sbi->sb->s_bdev;
++ long written;
++
++ if (wbc->for_kupdate)
++ return 0;
++
++ if (get_pages(sbi, F2FS_DIRTY_META) == 0)
++ return 0;
++
++ /* if mounting is failed, skip writing node pages */
++ mutex_lock(&sbi->cp_mutex);
++ written = sync_meta_pages(sbi, META, bio_get_nr_vecs(bdev));
++ mutex_unlock(&sbi->cp_mutex);
++ wbc->nr_to_write -= written;
++ return 0;
++}
++
++long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
++ long nr_to_write)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ pgoff_t index = 0, end = LONG_MAX;
++ struct pagevec pvec;
++ long nwritten = 0;
++ struct writeback_control wbc = {
++ .for_reclaim = 0,
++ };
++
++ pagevec_init(&pvec, 0);
++
++ while (index <= end) {
++ int i, nr_pages;
++ nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
++ PAGECACHE_TAG_DIRTY,
++ min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
++ if (nr_pages == 0)
++ break;
++
++ for (i = 0; i < nr_pages; i++) {
++ struct page *page = pvec.pages[i];
++ lock_page(page);
++ BUG_ON(page->mapping != mapping);
++ BUG_ON(!PageDirty(page));
++ clear_page_dirty_for_io(page);
++ f2fs_write_meta_page(page, &wbc);
++ if (nwritten++ >= nr_to_write)
++ break;
++ }
++ pagevec_release(&pvec);
++ cond_resched();
++ }
++
++ if (nwritten)
++ f2fs_submit_bio(sbi, type, nr_to_write == LONG_MAX);
++
++ return nwritten;
++}
++
++static int f2fs_set_meta_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++
++ SetPageUptodate(page);
++ if (!PageDirty(page)) {
++ __set_page_dirty_nobuffers(page);
++ inc_page_count(sbi, F2FS_DIRTY_META);
++ F2FS_SET_SB_DIRT(sbi);
++ return 1;
++ }
++ return 0;
++}
++
++const struct address_space_operations f2fs_meta_aops = {
++ .writepage = f2fs_write_meta_page,
++ .writepages = f2fs_write_meta_pages,
++ .set_page_dirty = f2fs_set_meta_page_dirty,
++};
++
++int check_orphan_space(struct f2fs_sb_info *sbi)
++{
++ unsigned int max_orphans;
++ int err = 0;
++
++ /*
++ * considering 512 blocks in a segment 5 blocks are needed for cp
++ * and log segment summaries. Remaining blocks are used to keep
++ * orphan entries with the limitation one reserved segment
++ * for cp pack we can have max 1020*507 orphan entries
++ */
++ max_orphans = (sbi->blocks_per_seg - 5) * F2FS_ORPHANS_PER_BLOCK;
++ mutex_lock(&sbi->orphan_inode_mutex);
++ if (sbi->n_orphans >= max_orphans)
++ err = -ENOSPC;
++ mutex_unlock(&sbi->orphan_inode_mutex);
++ return err;
++}
++
++void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
++{
++ struct list_head *head, *this;
++ struct orphan_inode_entry *new = NULL, *orphan = NULL;
++
++ mutex_lock(&sbi->orphan_inode_mutex);
++ head = &sbi->orphan_inode_list;
++ list_for_each(this, head) {
++ orphan = list_entry(this, struct orphan_inode_entry, list);
++ if (orphan->ino == ino)
++ goto out;
++ if (orphan->ino > ino)
++ break;
++ orphan = NULL;
++ }
++retry:
++ new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
++ if (!new) {
++ cond_resched();
++ goto retry;
++ }
++ new->ino = ino;
++ INIT_LIST_HEAD(&new->list);
++
++ /* add new_oentry into list which is sorted by inode number */
++ if (orphan) {
++ struct orphan_inode_entry *prev;
++
++ /* get previous entry */
++ prev = list_entry(orphan->list.prev, typeof(*prev), list);
++ if (&prev->list != head)
++ /* insert new orphan inode entry */
++ list_add(&new->list, &prev->list);
++ else
++ list_add(&new->list, head);
++ } else {
++ list_add_tail(&new->list, head);
++ }
++ sbi->n_orphans++;
++out:
++ mutex_unlock(&sbi->orphan_inode_mutex);
++}
++
++void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
++{
++ struct list_head *this, *next, *head;
++ struct orphan_inode_entry *orphan;
++
++ mutex_lock(&sbi->orphan_inode_mutex);
++ head = &sbi->orphan_inode_list;
++ list_for_each_safe(this, next, head) {
++ orphan = list_entry(this, struct orphan_inode_entry, list);
++ if (orphan->ino == ino) {
++ list_del(&orphan->list);
++ kmem_cache_free(orphan_entry_slab, orphan);
++ sbi->n_orphans--;
++ break;
++ }
++ }
++ mutex_unlock(&sbi->orphan_inode_mutex);
++}
++
++static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
++{
++ struct inode *inode = f2fs_iget(sbi->sb, ino);
++ BUG_ON(IS_ERR(inode));
++ clear_nlink(inode);
++
++ /* truncate all the data during iput */
++ iput(inode);
++}
++
++int recover_orphan_inodes(struct f2fs_sb_info *sbi)
++{
++ block_t start_blk, orphan_blkaddr, i, j;
++
++ if (!(F2FS_CKPT(sbi)->ckpt_flags & CP_ORPHAN_PRESENT_FLAG))
++ return 0;
++
++ sbi->por_doing = 1;
++ start_blk = __start_cp_addr(sbi) + 1;
++ orphan_blkaddr = __start_sum_addr(sbi) - 1;
++
++ for (i = 0; i < orphan_blkaddr; i++) {
++ struct page *page = get_meta_page(sbi, start_blk + i);
++ struct f2fs_orphan_block *orphan_blk;
++
++ orphan_blk = (struct f2fs_orphan_block *)page_address(page);
++ for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
++ nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
++ recover_orphan_inode(sbi, ino);
++ }
++ f2fs_put_page(page, 1);
++ }
++ /* clear Orphan Flag */
++ F2FS_CKPT(sbi)->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
++ sbi->por_doing = 0;
++ return 0;
++}
++
++static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
++{
++ struct list_head *head, *this, *next;
++ struct f2fs_orphan_block *orphan_blk = NULL;
++ struct page *page = NULL;
++ unsigned int nentries = 0;
++ unsigned short index = 1;
++ unsigned short orphan_blocks;
++
++ orphan_blocks = (unsigned short)((sbi->n_orphans +
++ (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK);
++
++ mutex_lock(&sbi->orphan_inode_mutex);
++ head = &sbi->orphan_inode_list;
++
++ /* loop for each orphan inode entry and write them in Jornal block */
++ list_for_each_safe(this, next, head) {
++ struct orphan_inode_entry *orphan;
++
++ orphan = list_entry(this, struct orphan_inode_entry, list);
++
++ if (nentries == F2FS_ORPHANS_PER_BLOCK) {
++ /*
++ * an orphan block is full of 1020 entries,
++ * then we need to flush current orphan blocks
++ * and bring another one in memory
++ */
++ orphan_blk->blk_addr = cpu_to_le16(index);
++ orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
++ orphan_blk->entry_count = cpu_to_le32(nentries);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++ index++;
++ start_blk++;
++ nentries = 0;
++ page = NULL;
++ }
++ if (page)
++ goto page_exist;
++
++ page = grab_meta_page(sbi, start_blk);
++ orphan_blk = (struct f2fs_orphan_block *)page_address(page);
++ memset(orphan_blk, 0, sizeof(*orphan_blk));
++page_exist:
++ orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
++ }
++ if (!page)
++ goto end;
++
++ orphan_blk->blk_addr = cpu_to_le16(index);
++ orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
++ orphan_blk->entry_count = cpu_to_le32(nentries);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++end:
++ mutex_unlock(&sbi->orphan_inode_mutex);
++}
++
++static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
++ block_t cp_addr, unsigned long long *version)
++{
++ struct page *cp_page_1, *cp_page_2 = NULL;
++ unsigned long blk_size = sbi->blocksize;
++ struct f2fs_checkpoint *cp_block;
++ unsigned long long cur_version = 0, pre_version = 0;
++ unsigned int crc = 0;
++ size_t crc_offset;
++
++ /* Read the 1st cp block in this CP pack */
++ cp_page_1 = get_meta_page(sbi, cp_addr);
++
++ /* get the version number */
++ cp_block = (struct f2fs_checkpoint *)page_address(cp_page_1);
++ crc_offset = le32_to_cpu(cp_block->checksum_offset);
++ if (crc_offset >= blk_size)
++ goto invalid_cp1;
++
++ crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
++ if (!f2fs_crc_valid(crc, cp_block, crc_offset))
++ goto invalid_cp1;
++
++ pre_version = le64_to_cpu(cp_block->checkpoint_ver);
++
++ /* Read the 2nd cp block in this CP pack */
++ cp_addr += le64_to_cpu(cp_block->cp_pack_total_block_count) - 1;
++ cp_page_2 = get_meta_page(sbi, cp_addr);
++
++ cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2);
++ crc_offset = le32_to_cpu(cp_block->checksum_offset);
++ if (crc_offset >= blk_size)
++ goto invalid_cp2;
++
++ crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
++ if (!f2fs_crc_valid(crc, cp_block, crc_offset))
++ goto invalid_cp2;
++
++ cur_version = le64_to_cpu(cp_block->checkpoint_ver);
++
++ if (cur_version == pre_version) {
++ *version = cur_version;
++ f2fs_put_page(cp_page_2, 1);
++ return cp_page_1;
++ }
++invalid_cp2:
++ f2fs_put_page(cp_page_2, 1);
++invalid_cp1:
++ f2fs_put_page(cp_page_1, 1);
++ return NULL;
++}
++
++int get_valid_checkpoint(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_checkpoint *cp_block;
++ struct f2fs_super_block *fsb = sbi->raw_super;
++ struct page *cp1, *cp2, *cur_page;
++ unsigned long blk_size = sbi->blocksize;
++ unsigned long long cp1_version = 0, cp2_version = 0;
++ unsigned long long cp_start_blk_no;
++
++ sbi->ckpt = kzalloc(blk_size, GFP_KERNEL);
++ if (!sbi->ckpt)
++ return -ENOMEM;
++ /*
++ * Finding out valid cp block involves read both
++ * sets( cp pack1 and cp pack 2)
++ */
++ cp_start_blk_no = le32_to_cpu(fsb->start_segment_checkpoint);
++ cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
++
++ /* The second checkpoint pack should start at the next segment */
++ cp_start_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
++ cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
++
++ if (cp1 && cp2) {
++ if (ver_after(cp2_version, cp1_version))
++ cur_page = cp2;
++ else
++ cur_page = cp1;
++ } else if (cp1) {
++ cur_page = cp1;
++ } else if (cp2) {
++ cur_page = cp2;
++ } else {
++ goto fail_no_cp;
++ }
++
++ cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
++ memcpy(sbi->ckpt, cp_block, blk_size);
++
++ f2fs_put_page(cp1, 1);
++ f2fs_put_page(cp2, 1);
++ return 0;
++
++fail_no_cp:
++ kfree(sbi->ckpt);
++ return -EINVAL;
++}
++
++void set_dirty_dir_page(struct inode *inode, struct page *page)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct list_head *head = &sbi->dir_inode_list;
++ struct dir_inode_entry *new;
++ struct list_head *this;
++
++ if (!S_ISDIR(inode->i_mode))
++ return;
++retry:
++ new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
++ if (!new) {
++ cond_resched();
++ goto retry;
++ }
++ new->inode = inode;
++ INIT_LIST_HEAD(&new->list);
++
++ spin_lock(&sbi->dir_inode_lock);
++ list_for_each(this, head) {
++ struct dir_inode_entry *entry;
++ entry = list_entry(this, struct dir_inode_entry, list);
++ if (entry->inode == inode) {
++ kmem_cache_free(inode_entry_slab, new);
++ goto out;
++ }
++ }
++ list_add_tail(&new->list, head);
++ sbi->n_dirty_dirs++;
++
++ BUG_ON(!S_ISDIR(inode->i_mode));
++out:
++ inc_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_inc_dirty_dents(inode);
++ SetPagePrivate(page);
++
++ spin_unlock(&sbi->dir_inode_lock);
++}
++
++void remove_dirty_dir_inode(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct list_head *head = &sbi->dir_inode_list;
++ struct list_head *this;
++
++ if (!S_ISDIR(inode->i_mode))
++ return;
++
++ spin_lock(&sbi->dir_inode_lock);
++ if (atomic_read(&F2FS_I(inode)->dirty_dents))
++ goto out;
++
++ list_for_each(this, head) {
++ struct dir_inode_entry *entry;
++ entry = list_entry(this, struct dir_inode_entry, list);
++ if (entry->inode == inode) {
++ list_del(&entry->list);
++ kmem_cache_free(inode_entry_slab, entry);
++ sbi->n_dirty_dirs--;
++ break;
++ }
++ }
++out:
++ spin_unlock(&sbi->dir_inode_lock);
++}
++
++void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
++{
++ struct list_head *head = &sbi->dir_inode_list;
++ struct dir_inode_entry *entry;
++ struct inode *inode;
++retry:
++ spin_lock(&sbi->dir_inode_lock);
++ if (list_empty(head)) {
++ spin_unlock(&sbi->dir_inode_lock);
++ return;
++ }
++ entry = list_entry(head->next, struct dir_inode_entry, list);
++ inode = igrab(entry->inode);
++ spin_unlock(&sbi->dir_inode_lock);
++ if (inode) {
++ filemap_flush(inode->i_mapping);
++ iput(inode);
++ } else {
++ /*
++ * We should submit bio, since it exists several
++ * wribacking dentry pages in the freeing inode.
++ */
++ f2fs_submit_bio(sbi, DATA, true);
++ }
++ goto retry;
++}
++
++/**
++ * Freeze all the FS-operations for checkpoint.
++ */
++void block_operations(struct f2fs_sb_info *sbi)
++{
++ int t;
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++
++ /* Stop renaming operation */
++ mutex_lock_op(sbi, RENAME);
++ mutex_lock_op(sbi, DENTRY_OPS);
++
++retry_dents:
++ /* write all the dirty dentry pages */
++ sync_dirty_dir_inodes(sbi);
++
++ mutex_lock_op(sbi, DATA_WRITE);
++ if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
++ mutex_unlock_op(sbi, DATA_WRITE);
++ goto retry_dents;
++ }
++
++ /* block all the operations */
++ for (t = DATA_NEW; t <= NODE_TRUNC; t++)
++ mutex_lock_op(sbi, t);
++
++ mutex_lock(&sbi->write_inode);
++
++ /*
++ * POR: we should ensure that there is no dirty node pages
++ * until finishing nat/sit flush.
++ */
++retry:
++ sync_node_pages(sbi, 0, &wbc);
++
++ mutex_lock_op(sbi, NODE_WRITE);
++
++ if (get_pages(sbi, F2FS_DIRTY_NODES)) {
++ mutex_unlock_op(sbi, NODE_WRITE);
++ goto retry;
++ }
++ mutex_unlock(&sbi->write_inode);
++}
++
++static void unblock_operations(struct f2fs_sb_info *sbi)
++{
++ int t;
++ for (t = NODE_WRITE; t >= RENAME; t--)
++ mutex_unlock_op(sbi, t);
++}
++
++static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ nid_t last_nid = 0;
++ int nat_upd_blkoff[3];
++ block_t start_blk;
++ struct page *cp_page;
++ unsigned int data_sum_blocks, orphan_blocks;
++ void *kaddr;
++ __u32 crc32 = 0;
++ int i;
++
++ /* Flush all the NAT/SIT pages */
++ while (get_pages(sbi, F2FS_DIRTY_META))
++ sync_meta_pages(sbi, META, LONG_MAX);
++
++ next_free_nid(sbi, &last_nid);
++
++ /*
++ * modify checkpoint
++ * version number is already updated
++ */
++ ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi));
++ ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi));
++ ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
++ for (i = 0; i < 3; i++) {
++ ckpt->cur_node_segno[i] =
++ cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE));
++ ckpt->cur_node_blkoff[i] =
++ cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE));
++ nat_upd_blkoff[i] = NM_I(sbi)->nat_upd_blkoff[i];
++ ckpt->nat_upd_blkoff[i] = cpu_to_le16(nat_upd_blkoff[i]);
++ ckpt->alloc_type[i + CURSEG_HOT_NODE] =
++ curseg_alloc_type(sbi, i + CURSEG_HOT_NODE);
++ }
++ for (i = 0; i < 3; i++) {
++ ckpt->cur_data_segno[i] =
++ cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA));
++ ckpt->cur_data_blkoff[i] =
++ cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA));
++ ckpt->alloc_type[i + CURSEG_HOT_DATA] =
++ curseg_alloc_type(sbi, i + CURSEG_HOT_DATA);
++ }
++
++ ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
++ ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
++ ckpt->next_free_nid = cpu_to_le32(last_nid);
++
++ /* 2 cp + n data seg summary + orphan inode blocks */
++ data_sum_blocks = npages_for_summary_flush(sbi);
++ if (data_sum_blocks < 3)
++ ckpt->ckpt_flags |= CP_COMPACT_SUM_FLAG;
++ else
++ ckpt->ckpt_flags &= (~CP_COMPACT_SUM_FLAG);
++
++ orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
++ / F2FS_ORPHANS_PER_BLOCK;
++ ckpt->cp_pack_start_sum = 1 + orphan_blocks;
++ ckpt->cp_pack_total_block_count = 2 + data_sum_blocks + orphan_blocks;
++
++ if (is_umount) {
++ ckpt->ckpt_flags |= CP_UMOUNT_FLAG;
++ ckpt->cp_pack_total_block_count += NR_CURSEG_NODE_TYPE;
++ } else {
++ ckpt->ckpt_flags &= (~CP_UMOUNT_FLAG);
++ }
++
++ if (sbi->n_orphans)
++ ckpt->ckpt_flags |= CP_ORPHAN_PRESENT_FLAG;
++ else
++ ckpt->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
++
++ /* update SIT/NAT bitmap */
++ get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
++ get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
++
++ crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset));
++ *(__u32 *)((unsigned char *)ckpt +
++ le32_to_cpu(ckpt->checksum_offset))
++ = cpu_to_le32(crc32);
++
++ start_blk = __start_cp_addr(sbi);
++
++ /* write out checkpoint buffer at block 0 */
++ cp_page = grab_meta_page(sbi, start_blk++);
++ kaddr = page_address(cp_page);
++ memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
++ set_page_dirty(cp_page);
++ f2fs_put_page(cp_page, 1);
++
++ if (sbi->n_orphans) {
++ write_orphan_inodes(sbi, start_blk);
++ start_blk += orphan_blocks;
++ }
++
++ write_data_summaries(sbi, start_blk);
++ start_blk += data_sum_blocks;
++ if (is_umount) {
++ write_node_summaries(sbi, start_blk);
++ start_blk += NR_CURSEG_NODE_TYPE;
++ }
++
++ /* writeout checkpoint block */
++ cp_page = grab_meta_page(sbi, start_blk);
++ kaddr = page_address(cp_page);
++ memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
++ set_page_dirty(cp_page);
++ f2fs_put_page(cp_page, 1);
++
++ /* wait for previous submitted node/meta pages writeback */
++ while (get_pages(sbi, F2FS_WRITEBACK))
++ congestion_wait(BLK_RW_ASYNC, HZ / 50);
++
++ filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
++ filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
++
++ /* update user_block_counts */
++ sbi->last_valid_block_count = sbi->total_valid_block_count;
++ sbi->alloc_valid_block_count = 0;
++
++ /* Here, we only have one bio having CP pack */
++ if (sbi->ckpt->ckpt_flags & CP_ERROR_FLAG)
++ sbi->sb->s_flags |= MS_RDONLY;
++ else
++ sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
++
++ clear_prefree_segments(sbi);
++ F2FS_RESET_SB_DIRT(sbi);
++}
++
++/**
++ * We guarantee that this checkpoint procedure should not fail.
++ */
++void write_checkpoint(struct f2fs_sb_info *sbi, bool blocked, bool is_umount)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ unsigned long long ckpt_ver;
++
++ if (!blocked) {
++ mutex_lock(&sbi->cp_mutex);
++ block_operations(sbi);
++ }
++
++ f2fs_submit_bio(sbi, DATA, true);
++ f2fs_submit_bio(sbi, NODE, true);
++ f2fs_submit_bio(sbi, META, true);
++
++ /*
++ * update checkpoint pack index
++ * Increase the version number so that
++ * SIT entries and seg summaries are written at correct place
++ */
++ ckpt_ver = le64_to_cpu(ckpt->checkpoint_ver);
++ ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);
++
++ /* write cached NAT/SIT entries to NAT/SIT area */
++ flush_nat_entries(sbi);
++ flush_sit_entries(sbi);
++
++ reset_victim_segmap(sbi);
++
++ /* unlock all the fs_lock[] in do_checkpoint() */
++ do_checkpoint(sbi, is_umount);
++
++ unblock_operations(sbi);
++ mutex_unlock(&sbi->cp_mutex);
++}
++
++void init_orphan_info(struct f2fs_sb_info *sbi)
++{
++ mutex_init(&sbi->orphan_inode_mutex);
++ INIT_LIST_HEAD(&sbi->orphan_inode_list);
++ sbi->n_orphans = 0;
++}
++
++int create_checkpoint_caches(void)
++{
++ orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
++ sizeof(struct orphan_inode_entry), NULL);
++ if (unlikely(!orphan_entry_slab))
++ return -ENOMEM;
++ inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry",
++ sizeof(struct dir_inode_entry), NULL);
++ if (unlikely(!inode_entry_slab)) {
++ kmem_cache_destroy(orphan_entry_slab);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++void destroy_checkpoint_caches(void)
++{
++ kmem_cache_destroy(orphan_entry_slab);
++ kmem_cache_destroy(inode_entry_slab);
++}
diff --git a/patches/linux-3.7-rc6/0103-f2fs-add-node-operations.patch b/patches/linux-3.7-rc6/0103-f2fs-add-node-operations.patch
new file mode 100644
index 0000000..0acac64
--- /dev/null
+++ b/patches/linux-3.7-rc6/0103-f2fs-add-node-operations.patch
@@ -0,0 +1,1824 @@
+From ccdfa2eae0b5f0324955f0f24f34e47dc926bad7 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:28:19 +0000
+Subject: [PATCH] f2fs: add node operations
+
+This adds specific functions to manage NAT pages, a cache for NAT entries, free
+nids, direct/indirect node blocks for indexing data, and address space for node
+pages.
+
+- The key information of an NAT entry consists of a node id and a block address.
+
+- An NAT page is composed of block addresses covered by a certain range of NAT
+ entries, which is maintained by the address space of meta_inode.
+
+- A radix tree structure is used to cache NAT entries. The index for the tree
+ is a node id.
+
+- When there is no free nid, F2FS should scan NAT entries to find new one. In
+ order to avoid scanning frequently, F2FS manages a list containing a number of
+ free nids in memory. Only when free nids in the list are exhausted, scanning
+ process, build_free_nids(), is triggered.
+
+- F2FS has direct and indirect node blocks for indexing data. This patch adds
+ fuctions related to the node block management such as getting, allocating, and
+ truncating node blocks to index data.
+
+- In order to cache node blocks in memory, F2FS has a node_inode with an address
+ space for node pages. This patch also adds the address space operations for
+ node_inode.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/node.c | 1782 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 1782 insertions(+)
+ create mode 100644 fs/f2fs/node.c
+
+diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
+new file mode 100644
+index 0000000..df69058
+--- /dev/null
++++ b/fs/f2fs/node.c
+@@ -0,0 +1,1782 @@
++/**
++ * fs/f2fs/node.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/mpage.h>
++#include <linux/backing-dev.h>
++#include <linux/blkdev.h>
++#include <linux/pagevec.h>
++#include <linux/swap.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++static struct kmem_cache *nat_entry_slab;
++static struct kmem_cache *free_nid_slab;
++
++static void clear_node_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++ unsigned int long flags;
++
++ if (PageDirty(page)) {
++ spin_lock_irqsave(&mapping->tree_lock, flags);
++ radix_tree_tag_clear(&mapping->page_tree,
++ page_index(page),
++ PAGECACHE_TAG_DIRTY);
++ spin_unlock_irqrestore(&mapping->tree_lock, flags);
++
++ clear_page_dirty_for_io(page);
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++ }
++ ClearPageUptodate(page);
++}
++
++static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ pgoff_t index = current_nat_addr(sbi, nid);
++ return get_meta_page(sbi, index);
++}
++
++static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct page *src_page;
++ struct page *dst_page;
++ pgoff_t src_off;
++ pgoff_t dst_off;
++ void *src_addr;
++ void *dst_addr;
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++
++ src_off = current_nat_addr(sbi, nid);
++ dst_off = next_nat_addr(sbi, src_off);
++
++ /* get current nat block page with lock */
++ src_page = get_meta_page(sbi, src_off);
++
++ /* Dirty src_page means that it is already the new target NAT page. */
++ if (PageDirty(src_page))
++ return src_page;
++
++ dst_page = grab_meta_page(sbi, dst_off);
++
++ src_addr = page_address(src_page);
++ dst_addr = page_address(dst_page);
++ memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
++ set_page_dirty(dst_page);
++ f2fs_put_page(src_page, 1);
++
++ set_to_next_nat(nm_i, nid);
++
++ return dst_page;
++}
++
++/**
++ * Readahead NAT pages
++ */
++static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct page *page;
++ pgoff_t index;
++ int i;
++
++ for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) {
++ if (nid >= nm_i->max_nid)
++ nid = 0;
++ index = current_nat_addr(sbi, nid);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ continue;
++ if (f2fs_readpage(sbi, page, index, READ)) {
++ f2fs_put_page(page, 1);
++ continue;
++ }
++ page_cache_release(page);
++ }
++}
++
++static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
++{
++ return radix_tree_lookup(&nm_i->nat_root, n);
++}
++
++static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
++ nid_t start, unsigned int nr, struct nat_entry **ep)
++{
++ return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr);
++}
++
++static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
++{
++ list_del(&e->list);
++ radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
++ nm_i->nat_cnt--;
++ kmem_cache_free(nat_entry_slab, e);
++}
++
++int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct nat_entry *e;
++ int is_cp = 1;
++
++ read_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, nid);
++ if (e && !e->checkpointed)
++ is_cp = 0;
++ read_unlock(&nm_i->nat_tree_lock);
++ return is_cp;
++}
++
++static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid)
++{
++ struct nat_entry *new;
++
++ new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC);
++ if (!new)
++ return NULL;
++ if (radix_tree_insert(&nm_i->nat_root, nid, new)) {
++ kmem_cache_free(nat_entry_slab, new);
++ return NULL;
++ }
++ memset(new, 0, sizeof(struct nat_entry));
++ nat_set_nid(new, nid);
++ list_add_tail(&new->list, &nm_i->nat_entries);
++ nm_i->nat_cnt++;
++ return new;
++}
++
++static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid,
++ struct f2fs_nat_entry *ne)
++{
++ struct nat_entry *e;
++retry:
++ write_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, nid);
++ if (!e) {
++ e = grab_nat_entry(nm_i, nid);
++ if (!e) {
++ write_unlock(&nm_i->nat_tree_lock);
++ goto retry;
++ }
++ nat_set_blkaddr(e, le32_to_cpu(ne->block_addr));
++ nat_set_ino(e, le32_to_cpu(ne->ino));
++ nat_set_version(e, ne->version);
++ e->checkpointed = true;
++ }
++ write_unlock(&nm_i->nat_tree_lock);
++}
++
++static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
++ block_t new_blkaddr)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct nat_entry *e;
++retry:
++ write_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, ni->nid);
++ if (!e) {
++ e = grab_nat_entry(nm_i, ni->nid);
++ if (!e) {
++ write_unlock(&nm_i->nat_tree_lock);
++ goto retry;
++ }
++ e->ni = *ni;
++ e->checkpointed = true;
++ BUG_ON(ni->blk_addr == NEW_ADDR);
++ } else if (new_blkaddr == NEW_ADDR) {
++ /*
++ * when nid is reallocated,
++ * previous nat entry can be remained in nat cache.
++ * So, reinitialize it with new information.
++ */
++ e->ni = *ni;
++ BUG_ON(ni->blk_addr != NULL_ADDR);
++ }
++
++ if (new_blkaddr == NEW_ADDR)
++ e->checkpointed = false;
++
++ /* sanity check */
++ BUG_ON(nat_get_blkaddr(e) != ni->blk_addr);
++ BUG_ON(nat_get_blkaddr(e) == NULL_ADDR &&
++ new_blkaddr == NULL_ADDR);
++ BUG_ON(nat_get_blkaddr(e) == NEW_ADDR &&
++ new_blkaddr == NEW_ADDR);
++ BUG_ON(nat_get_blkaddr(e) != NEW_ADDR &&
++ nat_get_blkaddr(e) != NULL_ADDR &&
++ new_blkaddr == NEW_ADDR);
++
++ /* increament version no as node is removed */
++ if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) {
++ unsigned char version = nat_get_version(e);
++ nat_set_version(e, inc_node_version(version));
++ }
++
++ /* change address */
++ nat_set_blkaddr(e, new_blkaddr);
++ __set_nat_cache_dirty(nm_i, e);
++ write_unlock(&nm_i->nat_tree_lock);
++}
++
++static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++
++ if (nm_i->nat_cnt < 2 * NM_WOUT_THRESHOLD)
++ return 0;
++
++ write_lock(&nm_i->nat_tree_lock);
++ while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
++ struct nat_entry *ne;
++ ne = list_first_entry(&nm_i->nat_entries,
++ struct nat_entry, list);
++ __del_from_nat_cache(nm_i, ne);
++ nr_shrink--;
++ }
++ write_unlock(&nm_i->nat_tree_lock);
++ return nr_shrink;
++}
++
++/**
++ * This function returns always success
++ */
++void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ nid_t start_nid = START_NID(nid);
++ struct f2fs_nat_block *nat_blk;
++ struct page *page = NULL;
++ struct f2fs_nat_entry ne;
++ struct nat_entry *e;
++ int i;
++
++ ni->nid = nid;
++
++ /* Check nat cache */
++ read_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, nid);
++ if (e) {
++ ni->ino = nat_get_ino(e);
++ ni->blk_addr = nat_get_blkaddr(e);
++ ni->version = nat_get_version(e);
++ }
++ read_unlock(&nm_i->nat_tree_lock);
++ if (e)
++ return;
++
++ /* Check current segment summary */
++ mutex_lock(&curseg->curseg_mutex);
++ i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0);
++ if (i >= 0) {
++ ne = nat_in_journal(sum, i);
++ node_info_from_raw_nat(ni, &ne);
++ }
++ mutex_unlock(&curseg->curseg_mutex);
++ if (i >= 0)
++ goto cache;
++
++ /* Fill node_info from nat page */
++ page = get_current_nat_page(sbi, start_nid);
++ nat_blk = (struct f2fs_nat_block *)page_address(page);
++ ne = nat_blk->entries[nid - start_nid];
++ node_info_from_raw_nat(ni, &ne);
++ f2fs_put_page(page, 1);
++cache:
++ /* cache nat entry */
++ cache_nat_entry(NM_I(sbi), nid, &ne);
++}
++
++/**
++ * The maximum depth is four.
++ * Offset[0] will have raw inode offset.
++ */
++static int get_node_path(long block, int offset[4], unsigned int noffset[4])
++{
++ const long direct_index = ADDRS_PER_INODE;
++ const long direct_blks = ADDRS_PER_BLOCK;
++ const long dptrs_per_blk = NIDS_PER_BLOCK;
++ const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
++ const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
++ int n = 0;
++ int level = 0;
++
++ noffset[0] = 0;
++
++ if (block < direct_index) {
++ offset[n++] = block;
++ level = 0;
++ goto got;
++ }
++ block -= direct_index;
++ if (block < direct_blks) {
++ offset[n++] = NODE_DIR1_BLOCK;
++ noffset[n] = 1;
++ offset[n++] = block;
++ level = 1;
++ goto got;
++ }
++ block -= direct_blks;
++ if (block < direct_blks) {
++ offset[n++] = NODE_DIR2_BLOCK;
++ noffset[n] = 2;
++ offset[n++] = block;
++ level = 1;
++ goto got;
++ }
++ block -= direct_blks;
++ if (block < indirect_blks) {
++ offset[n++] = NODE_IND1_BLOCK;
++ noffset[n] = 3;
++ offset[n++] = block / direct_blks;
++ noffset[n] = 4 + offset[n - 1];
++ offset[n++] = block % direct_blks;
++ level = 2;
++ goto got;
++ }
++ block -= indirect_blks;
++ if (block < indirect_blks) {
++ offset[n++] = NODE_IND2_BLOCK;
++ noffset[n] = 4 + dptrs_per_blk;
++ offset[n++] = block / direct_blks;
++ noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
++ offset[n++] = block % direct_blks;
++ level = 2;
++ goto got;
++ }
++ block -= indirect_blks;
++ if (block < dindirect_blks) {
++ offset[n++] = NODE_DIND_BLOCK;
++ noffset[n] = 5 + (dptrs_per_blk * 2);
++ offset[n++] = block / indirect_blks;
++ noffset[n] = 6 + (dptrs_per_blk * 2) +
++ offset[n - 1] * (dptrs_per_blk + 1);
++ offset[n++] = (block / direct_blks) % dptrs_per_blk;
++ noffset[n] = 7 + (dptrs_per_blk * 2) +
++ offset[n - 2] * (dptrs_per_blk + 1) +
++ offset[n - 1];
++ offset[n++] = block % direct_blks;
++ level = 3;
++ goto got;
++ } else {
++ BUG();
++ }
++got:
++ return level;
++}
++
++/*
++ * Caller should call f2fs_put_dnode(dn).
++ */
++int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct page *npage[4];
++ struct page *parent;
++ int offset[4];
++ unsigned int noffset[4];
++ nid_t nids[4];
++ int level, i;
++ int err = 0;
++
++ level = get_node_path(index, offset, noffset);
++
++ nids[0] = dn->inode->i_ino;
++ npage[0] = get_node_page(sbi, nids[0]);
++ if (IS_ERR(npage[0]))
++ return PTR_ERR(npage[0]);
++
++ parent = npage[0];
++ nids[1] = get_nid(parent, offset[0], true);
++ dn->inode_page = npage[0];
++ dn->inode_page_locked = true;
++
++ /* get indirect or direct nodes */
++ for (i = 1; i <= level; i++) {
++ bool done = false;
++
++ if (!nids[i] && !ro) {
++ mutex_lock_op(sbi, NODE_NEW);
++
++ /* alloc new node */
++ if (!alloc_nid(sbi, &(nids[i]))) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ err = -ENOSPC;
++ goto release_pages;
++ }
++
++ dn->nid = nids[i];
++ npage[i] = new_node_page(dn, noffset[i]);
++ if (IS_ERR(npage[i])) {
++ alloc_nid_failed(sbi, nids[i]);
++ mutex_unlock_op(sbi, NODE_NEW);
++ err = PTR_ERR(npage[i]);
++ goto release_pages;
++ }
++
++ set_nid(parent, offset[i - 1], nids[i], i == 1);
++ alloc_nid_done(sbi, nids[i]);
++ mutex_unlock_op(sbi, NODE_NEW);
++ done = true;
++ } else if (ro && i == level && level > 1) {
++ npage[i] = get_node_page_ra(parent, offset[i - 1]);
++ if (IS_ERR(npage[i])) {
++ err = PTR_ERR(npage[i]);
++ goto release_pages;
++ }
++ done = true;
++ }
++ if (i == 1) {
++ dn->inode_page_locked = false;
++ unlock_page(parent);
++ } else {
++ f2fs_put_page(parent, 1);
++ }
++
++ if (!done) {
++ npage[i] = get_node_page(sbi, nids[i]);
++ if (IS_ERR(npage[i])) {
++ err = PTR_ERR(npage[i]);
++ f2fs_put_page(npage[0], 0);
++ goto release_out;
++ }
++ }
++ if (i < level) {
++ parent = npage[i];
++ nids[i + 1] = get_nid(parent, offset[i], false);
++ }
++ }
++ dn->nid = nids[level];
++ dn->ofs_in_node = offset[level];
++ dn->node_page = npage[level];
++ dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
++ return 0;
++
++release_pages:
++ f2fs_put_page(parent, 1);
++ if (i > 1)
++ f2fs_put_page(npage[0], 0);
++release_out:
++ dn->inode_page = NULL;
++ dn->node_page = NULL;
++ return err;
++}
++
++static void truncate_node(struct dnode_of_data *dn)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct node_info ni;
++
++ get_node_info(sbi, dn->nid, &ni);
++ BUG_ON(ni.blk_addr == NULL_ADDR);
++
++ if (ni.blk_addr != NULL_ADDR)
++ invalidate_blocks(sbi, ni.blk_addr);
++
++ /* Deallocate node address */
++ dec_valid_node_count(sbi, dn->inode, 1);
++ set_node_addr(sbi, &ni, NULL_ADDR);
++
++ if (dn->nid == dn->inode->i_ino) {
++ remove_orphan_inode(sbi, dn->nid);
++ dec_valid_inode_count(sbi);
++ } else {
++ sync_inode_page(dn);
++ }
++
++ clear_node_page_dirty(dn->node_page);
++ F2FS_SET_SB_DIRT(sbi);
++
++ f2fs_put_page(dn->node_page, 1);
++ dn->node_page = NULL;
++}
++
++static int truncate_dnode(struct dnode_of_data *dn)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct page *page;
++
++ if (dn->nid == 0)
++ return 1;
++
++ /* get direct node */
++ page = get_node_page(sbi, dn->nid);
++ if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
++ return 1;
++ else if (IS_ERR(page))
++ return PTR_ERR(page);
++
++ /* Make dnode_of_data for parameter */
++ dn->node_page = page;
++ dn->ofs_in_node = 0;
++ truncate_data_blocks(dn);
++ truncate_node(dn);
++ return 1;
++}
++
++static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
++ int ofs, int depth)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct dnode_of_data rdn = *dn;
++ struct page *page;
++ struct f2fs_node *rn;
++ nid_t child_nid;
++ unsigned int child_nofs;
++ int freed = 0;
++ int i, ret;
++
++ if (dn->nid == 0)
++ return NIDS_PER_BLOCK + 1;
++
++ page = get_node_page(sbi, dn->nid);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++
++ rn = (struct f2fs_node *)page_address(page);
++ if (depth < 3) {
++ for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
++ child_nid = le32_to_cpu(rn->in.nid[i]);
++ if (child_nid == 0)
++ continue;
++ rdn.nid = child_nid;
++ ret = truncate_dnode(&rdn);
++ if (ret < 0)
++ goto out_err;
++ set_nid(page, i, 0, false);
++ }
++ } else {
++ child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
++ for (i = ofs; i < NIDS_PER_BLOCK; i++) {
++ child_nid = le32_to_cpu(rn->in.nid[i]);
++ if (child_nid == 0) {
++ child_nofs += NIDS_PER_BLOCK + 1;
++ continue;
++ }
++ rdn.nid = child_nid;
++ ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
++ if (ret == (NIDS_PER_BLOCK + 1)) {
++ set_nid(page, i, 0, false);
++ child_nofs += ret;
++ } else if (ret < 0 && ret != -ENOENT) {
++ goto out_err;
++ }
++ }
++ freed = child_nofs;
++ }
++
++ if (!ofs) {
++ /* remove current indirect node */
++ dn->node_page = page;
++ truncate_node(dn);
++ freed++;
++ } else {
++ f2fs_put_page(page, 1);
++ }
++ return freed;
++
++out_err:
++ f2fs_put_page(page, 1);
++ return ret;
++}
++
++static int truncate_partial_nodes(struct dnode_of_data *dn,
++ struct f2fs_inode *ri, int *offset, int depth)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct page *pages[2];
++ nid_t nid[3];
++ nid_t child_nid;
++ int err = 0;
++ int i;
++ int idx = depth - 2;
++
++ nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
++ if (!nid[0])
++ return 0;
++
++ /* get indirect nodes in the path */
++ for (i = 0; i < depth - 1; i++) {
++ /* refernece count'll be increased */
++ pages[i] = get_node_page(sbi, nid[i]);
++ if (IS_ERR(pages[i])) {
++ depth = i + 1;
++ err = PTR_ERR(pages[i]);
++ goto fail;
++ }
++ nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
++ }
++
++ /* free direct nodes linked to a partial indirect node */
++ for (i = offset[depth - 1]; i < NIDS_PER_BLOCK; i++) {
++ child_nid = get_nid(pages[idx], i, false);
++ if (!child_nid)
++ continue;
++ dn->nid = child_nid;
++ err = truncate_dnode(dn);
++ if (err < 0)
++ goto fail;
++ set_nid(pages[idx], i, 0, false);
++ }
++
++ if (offset[depth - 1] == 0) {
++ dn->node_page = pages[idx];
++ dn->nid = nid[idx];
++ truncate_node(dn);
++ } else {
++ f2fs_put_page(pages[idx], 1);
++ }
++ offset[idx]++;
++ offset[depth - 1] = 0;
++fail:
++ for (i = depth - 3; i >= 0; i--)
++ f2fs_put_page(pages[i], 1);
++ return err;
++}
++
++/**
++ * All the block addresses of data and nodes should be nullified.
++ */
++int truncate_inode_blocks(struct inode *inode, pgoff_t from)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int err = 0, cont = 1;
++ int level, offset[4], noffset[4];
++ unsigned int nofs;
++ struct f2fs_node *rn;
++ struct dnode_of_data dn;
++ struct page *page;
++
++ level = get_node_path(from, offset, noffset);
++
++ page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++
++ set_new_dnode(&dn, inode, page, NULL, 0);
++ unlock_page(page);
++
++ rn = page_address(page);
++ switch (level) {
++ case 0:
++ case 1:
++ nofs = noffset[1];
++ break;
++ case 2:
++ nofs = noffset[1];
++ if (!offset[level - 1])
++ goto skip_partial;
++ err = truncate_partial_nodes(&dn, &rn->i, offset, level);
++ if (err < 0 && err != -ENOENT)
++ goto fail;
++ nofs += 1 + NIDS_PER_BLOCK;
++ break;
++ case 3:
++ nofs = 5 + 2 * NIDS_PER_BLOCK;
++ if (!offset[level - 1])
++ goto skip_partial;
++ err = truncate_partial_nodes(&dn, &rn->i, offset, level);
++ if (err < 0 && err != -ENOENT)
++ goto fail;
++ break;
++ default:
++ BUG();
++ }
++
++skip_partial:
++ while (cont) {
++ dn.nid = le32_to_cpu(rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]);
++ switch (offset[0]) {
++ case NODE_DIR1_BLOCK:
++ case NODE_DIR2_BLOCK:
++ err = truncate_dnode(&dn);
++ break;
++
++ case NODE_IND1_BLOCK:
++ case NODE_IND2_BLOCK:
++ err = truncate_nodes(&dn, nofs, offset[1], 2);
++ break;
++
++ case NODE_DIND_BLOCK:
++ err = truncate_nodes(&dn, nofs, offset[1], 3);
++ cont = 0;
++ break;
++
++ default:
++ BUG();
++ }
++ if (err < 0 && err != -ENOENT)
++ goto fail;
++ if (offset[1] == 0 &&
++ rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) {
++ lock_page(page);
++ wait_on_page_writeback(page);
++ rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
++ set_page_dirty(page);
++ unlock_page(page);
++ }
++ offset[1] = 0;
++ offset[0]++;
++ nofs += err;
++ }
++fail:
++ f2fs_put_page(page, 0);
++ return err > 0 ? 0 : err;
++}
++
++int remove_inode_page(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *page;
++ nid_t ino = inode->i_ino;
++ struct dnode_of_data dn;
++
++ mutex_lock_op(sbi, NODE_TRUNC);
++ page = get_node_page(sbi, ino);
++ if (IS_ERR(page)) {
++ mutex_unlock_op(sbi, NODE_TRUNC);
++ return PTR_ERR(page);
++ }
++
++ if (F2FS_I(inode)->i_xattr_nid) {
++ nid_t nid = F2FS_I(inode)->i_xattr_nid;
++ struct page *npage = get_node_page(sbi, nid);
++
++ if (IS_ERR(npage)) {
++ mutex_unlock_op(sbi, NODE_TRUNC);
++ return PTR_ERR(npage);
++ }
++
++ F2FS_I(inode)->i_xattr_nid = 0;
++ set_new_dnode(&dn, inode, page, npage, nid);
++ dn.inode_page_locked = 1;
++ truncate_node(&dn);
++ }
++ if (inode->i_blocks == 1) {
++ /* inernally call f2fs_put_page() */
++ set_new_dnode(&dn, inode, page, page, ino);
++ truncate_node(&dn);
++ } else if (inode->i_blocks == 0) {
++ struct node_info ni;
++ get_node_info(sbi, inode->i_ino, &ni);
++
++ /* called after f2fs_new_inode() is failed */
++ BUG_ON(ni.blk_addr != NULL_ADDR);
++ f2fs_put_page(page, 1);
++ } else {
++ BUG();
++ }
++ mutex_unlock_op(sbi, NODE_TRUNC);
++ return 0;
++}
++
++int new_inode_page(struct inode *inode, struct dentry *dentry)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *page;
++ struct dnode_of_data dn;
++
++ /* allocate inode page for new inode */
++ set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
++ mutex_lock_op(sbi, NODE_NEW);
++ page = new_node_page(&dn, 0);
++ init_dent_inode(dentry, page);
++ mutex_unlock_op(sbi, NODE_NEW);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++ f2fs_put_page(page, 1);
++ return 0;
++}
++
++struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ struct node_info old_ni, new_ni;
++ struct page *page;
++ int err;
++
++ if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
++ return ERR_PTR(-EPERM);
++
++ page = grab_cache_page(mapping, dn->nid);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ get_node_info(sbi, dn->nid, &old_ni);
++
++ SetPageUptodate(page);
++ fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
++
++ /* Reinitialize old_ni with new node page */
++ BUG_ON(old_ni.blk_addr != NULL_ADDR);
++ new_ni = old_ni;
++ new_ni.ino = dn->inode->i_ino;
++
++ if (!inc_valid_node_count(sbi, dn->inode, 1)) {
++ err = -ENOSPC;
++ goto fail;
++ }
++ set_node_addr(sbi, &new_ni, NEW_ADDR);
++
++ dn->node_page = page;
++ sync_inode_page(dn);
++ set_page_dirty(page);
++ set_cold_node(dn->inode, page);
++ if (ofs == 0)
++ inc_valid_inode_count(sbi);
++
++ return page;
++
++fail:
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++}
++
++static int read_node_page(struct page *page, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ struct node_info ni;
++
++ get_node_info(sbi, page->index, &ni);
++
++ if (ni.blk_addr == NULL_ADDR)
++ return -ENOENT;
++ return f2fs_readpage(sbi, page, ni.blk_addr, type);
++}
++
++/**
++ * Readahead a node page
++ */
++void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ struct page *apage;
++
++ apage = find_get_page(mapping, nid);
++ if (apage && PageUptodate(apage))
++ goto release_out;
++ f2fs_put_page(apage, 0);
++
++ apage = grab_cache_page(mapping, nid);
++ if (!apage)
++ return;
++
++ if (read_node_page(apage, READA))
++ goto unlock_out;
++
++ page_cache_release(apage);
++ return;
++
++unlock_out:
++ unlock_page(apage);
++release_out:
++ page_cache_release(apage);
++}
++
++struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
++{
++ int err;
++ struct page *page;
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++
++ page = grab_cache_page(mapping, nid);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ err = read_node_page(page, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++
++ BUG_ON(nid != nid_of_node(page));
++ mark_page_accessed(page);
++ return page;
++}
++
++/**
++ * Return a locked page for the desired node page.
++ * And, readahead MAX_RA_NODE number of node pages.
++ */
++struct page *get_node_page_ra(struct page *parent, int start)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb);
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ int i, end;
++ int err = 0;
++ nid_t nid;
++ struct page *page;
++
++ /* First, try getting the desired direct node. */
++ nid = get_nid(parent, start, false);
++ if (!nid)
++ return ERR_PTR(-ENOENT);
++
++ page = find_get_page(mapping, nid);
++ if (page && PageUptodate(page))
++ goto page_hit;
++ f2fs_put_page(page, 0);
++
++repeat:
++ page = grab_cache_page(mapping, nid);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ err = read_node_page(page, READA);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++
++ /* Then, try readahead for siblings of the desired node */
++ end = start + MAX_RA_NODE;
++ end = min(end, NIDS_PER_BLOCK);
++ for (i = start + 1; i < end; i++) {
++ nid = get_nid(parent, i, false);
++ if (!nid)
++ continue;
++ ra_node_page(sbi, nid);
++ }
++
++page_hit:
++ lock_page(page);
++ if (PageError(page)) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(-EIO);
++ }
++
++ /* Has the page been truncated? */
++ if (page->mapping != mapping) {
++ f2fs_put_page(page, 1);
++ goto repeat;
++ }
++ return page;
++}
++
++void sync_inode_page(struct dnode_of_data *dn)
++{
++ if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) {
++ update_inode(dn->inode, dn->node_page);
++ } else if (dn->inode_page) {
++ if (!dn->inode_page_locked)
++ lock_page(dn->inode_page);
++ update_inode(dn->inode, dn->inode_page);
++ if (!dn->inode_page_locked)
++ unlock_page(dn->inode_page);
++ } else {
++ f2fs_write_inode(dn->inode, NULL);
++ }
++}
++
++int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino,
++ struct writeback_control *wbc)
++{
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ pgoff_t index, end;
++ struct pagevec pvec;
++ int step = ino ? 2 : 0;
++ int nwritten = 0, wrote = 0;
++
++ pagevec_init(&pvec, 0);
++
++next_step:
++ index = 0;
++ end = LONG_MAX;
++
++ while (index <= end) {
++ int i, nr_pages;
++ nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
++ PAGECACHE_TAG_DIRTY,
++ min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
++ if (nr_pages == 0)
++ break;
++
++ for (i = 0; i < nr_pages; i++) {
++ struct page *page = pvec.pages[i];
++
++ /*
++ * flushing sequence with step:
++ * 0. indirect nodes
++ * 1. dentry dnodes
++ * 2. file dnodes
++ */
++ if (step == 0 && IS_DNODE(page))
++ continue;
++ if (step == 1 && (!IS_DNODE(page) ||
++ is_cold_node(page)))
++ continue;
++ if (step == 2 && (!IS_DNODE(page) ||
++ !is_cold_node(page)))
++ continue;
++
++ /*
++ * If an fsync mode,
++ * we should not skip writing node pages.
++ */
++ if (ino && ino_of_node(page) == ino)
++ lock_page(page);
++ else if (!trylock_page(page))
++ continue;
++
++ if (unlikely(page->mapping != mapping)) {
++continue_unlock:
++ unlock_page(page);
++ continue;
++ }
++ if (ino && ino_of_node(page) != ino)
++ goto continue_unlock;
++
++ if (!PageDirty(page)) {
++ /* someone wrote it for us */
++ goto continue_unlock;
++ }
++
++ if (!clear_page_dirty_for_io(page))
++ goto continue_unlock;
++
++ /* called by fsync() */
++ if (ino && IS_DNODE(page)) {
++ int mark = !is_checkpointed_node(sbi, ino);
++ set_fsync_mark(page, 1);
++ if (IS_INODE(page))
++ set_dentry_mark(page, mark);
++ nwritten++;
++ } else {
++ set_fsync_mark(page, 0);
++ set_dentry_mark(page, 0);
++ }
++ mapping->a_ops->writepage(page, wbc);
++ wrote++;
++
++ if (--wbc->nr_to_write == 0)
++ break;
++ }
++ pagevec_release(&pvec);
++ cond_resched();
++
++ if (wbc->nr_to_write == 0) {
++ step = 2;
++ break;
++ }
++ }
++
++ if (step < 2) {
++ step++;
++ goto next_step;
++ }
++
++ if (wrote)
++ f2fs_submit_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL);
++
++ return nwritten;
++}
++
++static int f2fs_write_node_page(struct page *page,
++ struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ nid_t nid;
++ unsigned int nofs;
++ block_t new_addr;
++ struct node_info ni;
++
++ if (wbc->for_reclaim) {
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ return AOP_WRITEPAGE_ACTIVATE;
++ }
++
++ wait_on_page_writeback(page);
++
++ mutex_lock_op(sbi, NODE_WRITE);
++
++ /* get old block addr of this node page */
++ nid = nid_of_node(page);
++ nofs = ofs_of_node(page);
++ BUG_ON(page->index != nid);
++
++ get_node_info(sbi, nid, &ni);
++
++ /* This page is already truncated */
++ if (ni.blk_addr == NULL_ADDR)
++ return 0;
++
++ set_page_writeback(page);
++
++ /* insert node offset */
++ write_node_page(sbi, page, nid, ni.blk_addr, &new_addr);
++ set_node_addr(sbi, &ni, new_addr);
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++
++ mutex_unlock_op(sbi, NODE_WRITE);
++ unlock_page(page);
++ return 0;
++}
++
++static int f2fs_write_node_pages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++ struct block_device *bdev = sbi->sb->s_bdev;
++ long nr_to_write = wbc->nr_to_write;
++
++ if (wbc->for_kupdate)
++ return 0;
++
++ if (get_pages(sbi, F2FS_DIRTY_NODES) == 0)
++ return 0;
++
++ if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
++ write_checkpoint(sbi, false, false);
++ return 0;
++ }
++
++ /* if mounting is failed, skip writing node pages */
++ wbc->nr_to_write = bio_get_nr_vecs(bdev);
++ sync_node_pages(sbi, 0, wbc);
++ wbc->nr_to_write = nr_to_write -
++ (bio_get_nr_vecs(bdev) - wbc->nr_to_write);
++ return 0;
++}
++
++static int f2fs_set_node_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++
++ SetPageUptodate(page);
++ if (!PageDirty(page)) {
++ __set_page_dirty_nobuffers(page);
++ inc_page_count(sbi, F2FS_DIRTY_NODES);
++ SetPagePrivate(page);
++ return 1;
++ }
++ return 0;
++}
++
++static void f2fs_invalidate_node_page(struct page *page, unsigned long offset)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ if (PageDirty(page))
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++ ClearPagePrivate(page);
++}
++
++static int f2fs_release_node_page(struct page *page, gfp_t wait)
++{
++ ClearPagePrivate(page);
++ return 0;
++}
++
++/**
++ * Structure of the f2fs node operations
++ */
++const struct address_space_operations f2fs_node_aops = {
++ .writepage = f2fs_write_node_page,
++ .writepages = f2fs_write_node_pages,
++ .set_page_dirty = f2fs_set_node_page_dirty,
++ .invalidatepage = f2fs_invalidate_node_page,
++ .releasepage = f2fs_release_node_page,
++};
++
++static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
++{
++ struct list_head *this;
++ struct free_nid *i = NULL;
++ list_for_each(this, head) {
++ i = list_entry(this, struct free_nid, list);
++ if (i->nid == n)
++ break;
++ i = NULL;
++ }
++ return i;
++}
++
++static void __del_from_free_nid_list(struct free_nid *i)
++{
++ list_del(&i->list);
++ kmem_cache_free(free_nid_slab, i);
++}
++
++static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
++{
++ struct free_nid *i;
++
++ if (nm_i->fcnt > 2 * MAX_FREE_NIDS)
++ return 0;
++retry:
++ i = kmem_cache_alloc(free_nid_slab, GFP_NOFS);
++ if (!i) {
++ cond_resched();
++ goto retry;
++ }
++ i->nid = nid;
++ i->state = NID_NEW;
++
++ spin_lock(&nm_i->free_nid_list_lock);
++ if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) {
++ spin_unlock(&nm_i->free_nid_list_lock);
++ kmem_cache_free(free_nid_slab, i);
++ return 0;
++ }
++ list_add_tail(&i->list, &nm_i->free_nid_list);
++ nm_i->fcnt++;
++ spin_unlock(&nm_i->free_nid_list_lock);
++ return 1;
++}
++
++static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
++{
++ struct free_nid *i;
++ spin_lock(&nm_i->free_nid_list_lock);
++ i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
++ if (i && i->state == NID_NEW) {
++ __del_from_free_nid_list(i);
++ nm_i->fcnt--;
++ }
++ spin_unlock(&nm_i->free_nid_list_lock);
++}
++
++static int scan_nat_page(struct f2fs_nm_info *nm_i,
++ struct page *nat_page, nid_t start_nid)
++{
++ struct f2fs_nat_block *nat_blk = page_address(nat_page);
++ block_t blk_addr;
++ int fcnt = 0;
++ int i;
++
++ /* 0 nid should not be used */
++ if (start_nid == 0)
++ ++start_nid;
++
++ i = start_nid % NAT_ENTRY_PER_BLOCK;
++
++ for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
++ blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
++ BUG_ON(blk_addr == NEW_ADDR);
++ if (blk_addr == NULL_ADDR)
++ fcnt += add_free_nid(nm_i, start_nid);
++ }
++ return fcnt;
++}
++
++static void build_free_nids(struct f2fs_sb_info *sbi)
++{
++ struct free_nid *fnid, *next_fnid;
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ nid_t nid = 0;
++ bool is_cycled = false;
++ int fcnt = 0;
++ int i;
++
++ nid = nm_i->next_scan_nid;
++ nm_i->init_scan_nid = nid;
++
++ ra_nat_pages(sbi, nid);
++
++ while (1) {
++ struct page *page = get_current_nat_page(sbi, nid);
++
++ fcnt += scan_nat_page(nm_i, page, nid);
++ f2fs_put_page(page, 1);
++
++ nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
++
++ if (nid >= nm_i->max_nid) {
++ nid = 0;
++ is_cycled = true;
++ }
++ if (fcnt > MAX_FREE_NIDS)
++ break;
++ if (is_cycled && nm_i->init_scan_nid <= nid)
++ break;
++ }
++
++ nm_i->next_scan_nid = nid;
++
++ /* find free nids from current sum_pages */
++ mutex_lock(&curseg->curseg_mutex);
++ for (i = 0; i < nats_in_cursum(sum); i++) {
++ block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr);
++ nid = le32_to_cpu(nid_in_journal(sum, i));
++ if (addr == NULL_ADDR)
++ add_free_nid(nm_i, nid);
++ else
++ remove_free_nid(nm_i, nid);
++ }
++ mutex_unlock(&curseg->curseg_mutex);
++
++ /* remove the free nids from current allocated nids */
++ list_for_each_entry_safe(fnid, next_fnid, &nm_i->free_nid_list, list) {
++ struct nat_entry *ne;
++
++ read_lock(&nm_i->nat_tree_lock);
++ ne = __lookup_nat_cache(nm_i, fnid->nid);
++ if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
++ remove_free_nid(nm_i, fnid->nid);
++ read_unlock(&nm_i->nat_tree_lock);
++ }
++}
++
++/*
++ * If this function returns success, caller can obtain a new nid
++ * from second parameter of this function.
++ * The returned nid could be used ino as well as nid when inode is created.
++ */
++bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *i = NULL;
++ struct list_head *this;
++retry:
++ mutex_lock(&nm_i->build_lock);
++ if (!nm_i->fcnt) {
++ /* scan NAT in order to build free nid list */
++ build_free_nids(sbi);
++ if (!nm_i->fcnt) {
++ mutex_unlock(&nm_i->build_lock);
++ return false;
++ }
++ }
++ mutex_unlock(&nm_i->build_lock);
++
++ /*
++ * We check fcnt again since previous check is racy as
++ * we didn't hold free_nid_list_lock. So other thread
++ * could consume all of free nids.
++ */
++ spin_lock(&nm_i->free_nid_list_lock);
++ if (!nm_i->fcnt) {
++ spin_unlock(&nm_i->free_nid_list_lock);
++ goto retry;
++ }
++
++ BUG_ON(list_empty(&nm_i->free_nid_list));
++ list_for_each(this, &nm_i->free_nid_list) {
++ i = list_entry(this, struct free_nid, list);
++ if (i->state == NID_NEW)
++ break;
++ }
++
++ BUG_ON(i->state != NID_NEW);
++ *nid = i->nid;
++ i->state = NID_ALLOC;
++ nm_i->fcnt--;
++ spin_unlock(&nm_i->free_nid_list_lock);
++ return true;
++}
++
++/**
++ * alloc_nid() should be called prior to this function.
++ */
++void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *i;
++
++ spin_lock(&nm_i->free_nid_list_lock);
++ i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
++ if (i) {
++ BUG_ON(i->state != NID_ALLOC);
++ __del_from_free_nid_list(i);
++ }
++ spin_unlock(&nm_i->free_nid_list_lock);
++}
++
++/**
++ * alloc_nid() should be called prior to this function.
++ */
++void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ alloc_nid_done(sbi, nid);
++ add_free_nid(NM_I(sbi), nid);
++}
++
++void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
++ struct f2fs_summary *sum, struct node_info *ni,
++ block_t new_blkaddr)
++{
++ rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr);
++ set_node_addr(sbi, ni, new_blkaddr);
++ clear_node_page_dirty(page);
++}
++
++int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
++{
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ struct f2fs_node *rn;
++ void *src, *dst;
++ nid_t ino = ino_of_node(page);
++ struct node_info old_ni, new_ni;
++ struct page *ipage;
++
++ ipage = grab_cache_page(mapping, ino);
++ if (!ipage)
++ return -ENOMEM;
++
++ /* Should not use this inode from free nid list */
++ remove_free_nid(NM_I(sbi), ino);
++
++ get_node_info(sbi, ino, &old_ni);
++ SetPageUptodate(ipage);
++ fill_node_footer(ipage, ino, ino, 0, true);
++
++ src = kmap_atomic(page);
++ dst = kmap_atomic(ipage);
++
++ memcpy(dst, src, F2FS_INODE_SIZE);
++ rn = (struct f2fs_node *)dst;
++ rn->i.i_size = 0;
++ rn->i.i_blocks = 1;
++ rn->i.i_links = 1;
++ rn->i.i_xattr_nid = 0;
++ kunmap_atomic(dst);
++ kunmap_atomic(src);
++
++ new_ni = old_ni;
++ new_ni.ino = ino;
++
++ set_node_addr(sbi, &new_ni, NEW_ADDR);
++ inc_valid_inode_count(sbi);
++
++ f2fs_put_page(ipage, 1);
++ return 0;
++}
++
++int restore_node_summary(struct f2fs_sb_info *sbi,
++ unsigned int segno, struct f2fs_summary_block *sum)
++{
++ struct f2fs_node *rn;
++ struct f2fs_summary *sum_entry;
++ struct page *page;
++ block_t addr;
++ int i, last_offset;
++
++ /* alloc temporal page for read node */
++ page = alloc_page(GFP_NOFS | __GFP_ZERO);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++ lock_page(page);
++
++ /* scan the node segment */
++ last_offset = sbi->blocks_per_seg;
++ addr = START_BLOCK(sbi, segno);
++ sum_entry = &sum->entries[0];
++
++ for (i = 0; i < last_offset; i++, sum_entry++) {
++ if (f2fs_readpage(sbi, page, addr, READ_SYNC))
++ goto out;
++
++ rn = (struct f2fs_node *)page_address(page);
++ sum_entry->nid = rn->footer.nid;
++ sum_entry->version = 0;
++ sum_entry->ofs_in_node = 0;
++ addr++;
++
++ /*
++ * In order to read next node page,
++ * we must clear PageUptodate flag.
++ */
++ ClearPageUptodate(page);
++ }
++out:
++ unlock_page(page);
++ __free_pages(page, 0);
++ return 0;
++}
++
++static bool flush_nats_in_journal(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ int i;
++
++ mutex_lock(&curseg->curseg_mutex);
++
++ if (nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) {
++ mutex_unlock(&curseg->curseg_mutex);
++ return false;
++ }
++
++ for (i = 0; i < nats_in_cursum(sum); i++) {
++ struct nat_entry *ne;
++ struct f2fs_nat_entry raw_ne;
++ nid_t nid = le32_to_cpu(nid_in_journal(sum, i));
++
++ raw_ne = nat_in_journal(sum, i);
++retry:
++ write_lock(&nm_i->nat_tree_lock);
++ ne = __lookup_nat_cache(nm_i, nid);
++ if (ne) {
++ __set_nat_cache_dirty(nm_i, ne);
++ write_unlock(&nm_i->nat_tree_lock);
++ continue;
++ }
++ ne = grab_nat_entry(nm_i, nid);
++ if (!ne) {
++ write_unlock(&nm_i->nat_tree_lock);
++ goto retry;
++ }
++ nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr));
++ nat_set_ino(ne, le32_to_cpu(raw_ne.ino));
++ nat_set_version(ne, raw_ne.version);
++ __set_nat_cache_dirty(nm_i, ne);
++ write_unlock(&nm_i->nat_tree_lock);
++ }
++ update_nats_in_cursum(sum, -i);
++ mutex_unlock(&curseg->curseg_mutex);
++ return true;
++}
++
++/**
++ * This function is called during the checkpointing process.
++ */
++void flush_nat_entries(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ struct list_head *cur, *n;
++ struct page *page = NULL;
++ struct f2fs_nat_block *nat_blk = NULL;
++ nid_t start_nid = 0, end_nid = 0;
++ bool flushed;
++
++ flushed = flush_nats_in_journal(sbi);
++
++ if (!flushed)
++ mutex_lock(&curseg->curseg_mutex);
++
++ /* 1) flush dirty nat caches */
++ list_for_each_safe(cur, n, &nm_i->dirty_nat_entries) {
++ struct nat_entry *ne;
++ nid_t nid;
++ struct f2fs_nat_entry raw_ne;
++ int offset = -1;
++ block_t old_blkaddr, new_blkaddr;
++
++ ne = list_entry(cur, struct nat_entry, list);
++ nid = nat_get_nid(ne);
++
++ if (nat_get_blkaddr(ne) == NEW_ADDR)
++ continue;
++ if (flushed)
++ goto to_nat_page;
++
++ /* if there is room for nat enries in curseg->sumpage */
++ offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1);
++ if (offset >= 0) {
++ raw_ne = nat_in_journal(sum, offset);
++ old_blkaddr = le32_to_cpu(raw_ne.block_addr);
++ goto flush_now;
++ }
++to_nat_page:
++ if (!page || (start_nid > nid || nid > end_nid)) {
++ if (page) {
++ f2fs_put_page(page, 1);
++ page = NULL;
++ }
++ start_nid = START_NID(nid);
++ end_nid = start_nid + NAT_ENTRY_PER_BLOCK - 1;
++
++ /*
++ * get nat block with dirty flag, increased reference
++ * count, mapped and lock
++ */
++ page = get_next_nat_page(sbi, start_nid);
++ nat_blk = page_address(page);
++ }
++
++ BUG_ON(!nat_blk);
++ raw_ne = nat_blk->entries[nid - start_nid];
++ old_blkaddr = le32_to_cpu(raw_ne.block_addr);
++flush_now:
++ new_blkaddr = nat_get_blkaddr(ne);
++
++ raw_ne.ino = cpu_to_le32(nat_get_ino(ne));
++ raw_ne.block_addr = cpu_to_le32(new_blkaddr);
++ raw_ne.version = nat_get_version(ne);
++
++ if (offset < 0) {
++ nat_blk->entries[nid - start_nid] = raw_ne;
++ } else {
++ nat_in_journal(sum, offset) = raw_ne;
++ nid_in_journal(sum, offset) = cpu_to_le32(nid);
++ }
++
++ if (nat_get_blkaddr(ne) == NULL_ADDR) {
++ write_lock(&nm_i->nat_tree_lock);
++ __del_from_nat_cache(nm_i, ne);
++ write_unlock(&nm_i->nat_tree_lock);
++
++ /* We can reuse this freed nid at this point */
++ add_free_nid(NM_I(sbi), nid);
++ } else {
++ write_lock(&nm_i->nat_tree_lock);
++ __clear_nat_cache_dirty(nm_i, ne);
++ ne->checkpointed = true;
++ write_unlock(&nm_i->nat_tree_lock);
++ }
++ }
++ if (!flushed)
++ mutex_unlock(&curseg->curseg_mutex);
++
++ /*
++ * set block offset in cur_journal_segno1/2
++ * where the last NAT update happened
++ */
++ memcpy(nm_i->nat_upd_blkoff,
++ nm_i->lst_upd_blkoff, sizeof(int) * 3);
++ f2fs_put_page(page, 1);
++
++ /* 2) shrink nat caches if necessary */
++ try_to_free_nats(sbi, nm_i->nat_cnt - NM_WOUT_THRESHOLD);
++}
++
++static int init_node_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ unsigned char *version_bitmap;
++ int i;
++
++ nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr);
++
++ /* segment_count_nat includes pair segment so divide to 2. */
++ nm_i->nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
++ nm_i->nat_blocks = nm_i->nat_segs <<
++ le32_to_cpu(sb_raw->log_blocks_per_seg);
++ nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks;
++ nm_i->fcnt = 0;
++ nm_i->nat_cnt = 0;
++
++ INIT_LIST_HEAD(&nm_i->free_nid_list);
++ INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC);
++ INIT_LIST_HEAD(&nm_i->nat_entries);
++ INIT_LIST_HEAD(&nm_i->dirty_nat_entries);
++
++ mutex_init(&nm_i->build_lock);
++ spin_lock_init(&nm_i->free_nid_list_lock);
++ rwlock_init(&nm_i->nat_tree_lock);
++
++ for (i = 0; i < 3; i++) {
++ nm_i->lst_upd_blkoff[i] =
++ le16_to_cpu(sbi->ckpt->nat_upd_blkoff[i]);
++ nm_i->nat_upd_blkoff[i] =
++ le16_to_cpu(sbi->ckpt->nat_upd_blkoff[i]);
++ }
++
++ nm_i->written_valid_node_count = sbi->total_valid_node_count;
++ nm_i->written_valid_inode_count = sbi->total_valid_inode_count;
++
++ nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
++ nm_i->init_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
++ nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
++
++ nm_i->nat_bitmap = kzalloc(nm_i->bitmap_size, GFP_KERNEL);
++ if (!nm_i->nat_bitmap)
++ return -ENOMEM;
++ version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
++ if (!version_bitmap)
++ return -EFAULT;
++
++ /* copy version bitmap */
++ memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size);
++ return 0;
++}
++
++int build_node_manager(struct f2fs_sb_info *sbi)
++{
++ sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL);
++ if (!sbi->nm_info)
++ return -ENOMEM;
++
++ if (init_node_manager(sbi))
++ return -EINVAL;
++
++ build_free_nids(sbi);
++ return 0;
++}
++
++void destroy_node_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *i, *next_i;
++ struct nat_entry *natvec[NATVEC_SIZE];
++ nid_t nid = 0;
++ unsigned int found;
++
++ if (!nm_i)
++ return;
++
++ /* destroy free nid list */
++ spin_lock(&nm_i->free_nid_list_lock);
++ list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
++ BUG_ON(i->state == NID_ALLOC);
++ __del_from_free_nid_list(i);
++ nm_i->fcnt--;
++ }
++ BUG_ON(nm_i->fcnt);
++ spin_unlock(&nm_i->free_nid_list_lock);
++
++ /* destroy nat cache */
++ write_lock(&nm_i->nat_tree_lock);
++ while ((found = __gang_lookup_nat_cache(nm_i,
++ nid, NATVEC_SIZE, natvec))) {
++ unsigned idx;
++ for (idx = 0; idx < found; idx++) {
++ struct nat_entry *e = natvec[idx];
++ nid = nat_get_nid(e) + 1;
++ __del_from_nat_cache(nm_i, e);
++ }
++ }
++ BUG_ON(nm_i->nat_cnt);
++ write_unlock(&nm_i->nat_tree_lock);
++
++ kfree(nm_i->nat_bitmap);
++ sbi->nm_info = NULL;
++ kfree(nm_i);
++}
++
++int create_node_manager_caches(void)
++{
++ nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
++ sizeof(struct nat_entry), NULL);
++ if (!nat_entry_slab)
++ return -ENOMEM;
++
++ free_nid_slab = f2fs_kmem_cache_create("free_nid",
++ sizeof(struct free_nid), NULL);
++ if (!free_nid_slab) {
++ kmem_cache_destroy(nat_entry_slab);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++void destroy_node_manager_caches(void)
++{
++ kmem_cache_destroy(free_nid_slab);
++ kmem_cache_destroy(nat_entry_slab);
++}
diff --git a/patches/linux-3.7-rc6/0104-f2fs-add-segment-operations.patch b/patches/linux-3.7-rc6/0104-f2fs-add-segment-operations.patch
new file mode 100644
index 0000000..958a1e2
--- /dev/null
+++ b/patches/linux-3.7-rc6/0104-f2fs-add-segment-operations.patch
@@ -0,0 +1,1843 @@
+From 781489b7a9285a53af3273801286908a68d5ab50 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:28:47 +0000
+Subject: [PATCH] f2fs: add segment operations
+
+This adds specific functions not only to manage dirty/free segments, SIT pages,
+a cache for SIT entries, and summary entries, but also to allocate free blocks
+and write three types of pages: data, node, and meta.
+
+- F2FS maintains three types of bitmaps in memory, which indicate free, prefree,
+ and dirty segments respectively.
+
+- The key information of an SIT entry consists of a segment number, the number
+ of valid blocks in the segment, a bitmap to identify there-in valid or invalid
+ blocks.
+
+- An SIT page is composed of a certain range of SIT entries, which is maintained
+ by the address space of meta_inode.
+
+- To cache SIT entries, a simple array is used. The index for the array is the
+ segment number.
+
+- A summary entry for data contains the parent node information. A summary entry
+ for node contains its node offset from the inode.
+
+- F2FS manages information about six active logs and those summary entries in
+ memory. Whenever one of them is changed, its summary entries are flushed to
+ its SIT page maintained by the address space of meta_inode.
+
+- This patch adds a default block allocation function which supports heap-based
+ allocation policy.
+
+- This patch adds core functions to write data, node, and meta pages. Since LFS
+ basically produces a series of sequential writes, F2FS merges sequential bios
+ with a single one as much as possible to reduce the IO scheduling overhead.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/segment.c | 1795 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 1795 insertions(+)
+ create mode 100644 fs/f2fs/segment.c
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+new file mode 100644
+index 0000000..57d0931
+--- /dev/null
++++ b/fs/f2fs/segment.c
+@@ -0,0 +1,1795 @@
++/**
++ * fs/f2fs/segment.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/bio.h>
++#include <linux/blkdev.h>
++
++#include "f2fs.h"
++#include "segment.h"
++#include "node.h"
++
++static int need_to_flush(struct f2fs_sb_info *sbi)
++{
++ unsigned int pages_per_sec = (1 << sbi->log_blocks_per_seg) *
++ sbi->segs_per_sec;
++ int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++ int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++
++ if (sbi->por_doing)
++ return 0;
++
++ if (free_sections(sbi) <= (node_secs + 2 * dent_secs +
++ reserved_sections(sbi)))
++ return 1;
++ return 0;
++}
++
++/**
++ * This function balances dirty node and dentry pages.
++ * In addition, it controls garbage collection.
++ */
++void f2fs_balance_fs(struct f2fs_sb_info *sbi)
++{
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++
++ if (sbi->por_doing)
++ return;
++
++ /*
++ * We should do checkpoint when there are so many dirty node pages
++ * with enough free segments. After then, we should do GC.
++ */
++ if (need_to_flush(sbi)) {
++ sync_dirty_dir_inodes(sbi);
++ sync_node_pages(sbi, 0, &wbc);
++ }
++
++ if (has_not_enough_free_secs(sbi)) {
++ mutex_lock(&sbi->gc_mutex);
++ f2fs_gc(sbi, 1);
++ }
++}
++
++static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
++ enum dirty_type dirty_type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ /* need not be added */
++ if (IS_CURSEG(sbi, segno))
++ return;
++
++ if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]++;
++
++ if (dirty_type == DIRTY) {
++ struct seg_entry *sentry = get_seg_entry(sbi, segno);
++ dirty_type = sentry->type;
++ if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]++;
++ }
++}
++
++static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
++ enum dirty_type dirty_type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]--;
++
++ if (dirty_type == DIRTY) {
++ struct seg_entry *sentry = get_seg_entry(sbi, segno);
++ dirty_type = sentry->type;
++ if (test_and_clear_bit(segno,
++ dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]--;
++ clear_bit(segno, dirty_i->victim_segmap[FG_GC]);
++ clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
++ }
++}
++
++/**
++ * Should not occur error such as -ENOMEM.
++ * Adding dirty entry into seglist is not critical operation.
++ * If a given segment is one of current working segments, it won't be added.
++ */
++void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned short valid_blocks;
++
++ if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno))
++ return;
++
++ mutex_lock(&dirty_i->seglist_lock);
++
++ valid_blocks = get_valid_blocks(sbi, segno, 0);
++
++ if (valid_blocks == 0) {
++ __locate_dirty_segment(sbi, segno, PRE);
++ __remove_dirty_segment(sbi, segno, DIRTY);
++ } else if (valid_blocks < sbi->blocks_per_seg) {
++ __locate_dirty_segment(sbi, segno, DIRTY);
++ } else {
++ /* Recovery routine with SSR needs this */
++ __remove_dirty_segment(sbi, segno, DIRTY);
++ }
++
++ mutex_unlock(&dirty_i->seglist_lock);
++ return;
++}
++
++/**
++ * Should call clear_prefree_segments after checkpoint is done.
++ */
++static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int segno, offset = 0;
++ unsigned int total_segs = TOTAL_SEGS(sbi);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ while (1) {
++ segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
++ offset);
++ if (segno >= total_segs)
++ break;
++ __set_test_and_free(sbi, segno);
++ offset = segno + 1;
++ }
++ mutex_unlock(&dirty_i->seglist_lock);
++}
++
++void clear_prefree_segments(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int segno, offset = 0;
++ unsigned int total_segs = TOTAL_SEGS(sbi);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ while (1) {
++ segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
++ offset);
++ if (segno >= total_segs)
++ break;
++
++ offset = segno + 1;
++ if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE]))
++ dirty_i->nr_dirty[PRE]--;
++
++ /* Let's use trim */
++ if (test_opt(sbi, DISCARD))
++ blkdev_issue_discard(sbi->sb->s_bdev,
++ START_BLOCK(sbi, segno) <<
++ sbi->log_sectors_per_block,
++ 1 << (sbi->log_sectors_per_block +
++ sbi->log_blocks_per_seg),
++ GFP_NOFS, 0);
++ }
++ mutex_unlock(&dirty_i->seglist_lock);
++}
++
++static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap))
++ sit_i->dirty_sentries++;
++}
++
++static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type,
++ unsigned int segno, int modified)
++{
++ struct seg_entry *se = get_seg_entry(sbi, segno);
++ se->type = type;
++ if (modified)
++ __mark_sit_entry_dirty(sbi, segno);
++}
++
++static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
++{
++ struct seg_entry *se;
++ unsigned int segno, offset;
++ long int new_vblocks;
++
++ segno = GET_SEGNO(sbi, blkaddr);
++
++ se = get_seg_entry(sbi, segno);
++ new_vblocks = se->valid_blocks + del;
++ offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1);
++
++ BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) ||
++ (new_vblocks > sbi->blocks_per_seg)));
++
++ se->valid_blocks = new_vblocks;
++ se->mtime = get_mtime(sbi);
++ SIT_I(sbi)->max_mtime = se->mtime;
++
++ /* Update valid block bitmap */
++ if (del > 0) {
++ if (f2fs_set_bit(offset, se->cur_valid_map))
++ BUG();
++ } else {
++ if (!f2fs_clear_bit(offset, se->cur_valid_map))
++ BUG();
++ }
++ if (!f2fs_test_bit(offset, se->ckpt_valid_map))
++ se->ckpt_valid_blocks += del;
++
++ __mark_sit_entry_dirty(sbi, segno);
++
++ /* update total number of valid blocks to be written in ckpt area */
++ SIT_I(sbi)->written_valid_blocks += del;
++
++ if (sbi->segs_per_sec > 1)
++ get_sec_entry(sbi, segno)->valid_blocks += del;
++}
++
++static void refresh_sit_entry(struct f2fs_sb_info *sbi,
++ block_t old_blkaddr, block_t new_blkaddr)
++{
++ update_sit_entry(sbi, new_blkaddr, 1);
++ if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
++ update_sit_entry(sbi, old_blkaddr, -1);
++}
++
++void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
++{
++ unsigned int segno = GET_SEGNO(sbi, addr);
++ struct sit_info *sit_i = SIT_I(sbi);
++
++ BUG_ON(addr == NULL_ADDR);
++ if (addr == NEW_ADDR)
++ return;
++
++ /* add it into sit main buffer */
++ mutex_lock(&sit_i->sentry_lock);
++
++ update_sit_entry(sbi, addr, -1);
++
++ /* add it into dirty seglist */
++ locate_dirty_segment(sbi, segno);
++
++ mutex_unlock(&sit_i->sentry_lock);
++}
++
++/**
++ * This function should be resided under the curseg_mutex lock
++ */
++static void __add_sum_entry(struct f2fs_sb_info *sbi, int type,
++ struct f2fs_summary *sum, unsigned short offset)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ void *addr = curseg->sum_blk;
++ addr += offset * sizeof(struct f2fs_summary);
++ memcpy(addr, sum, sizeof(struct f2fs_summary));
++ return;
++}
++
++/**
++ * Calculate the number of current summary pages for writing
++ */
++int npages_for_summary_flush(struct f2fs_sb_info *sbi)
++{
++ int total_size_bytes = 0;
++ int valid_sum_count = 0;
++ int i, sum_space;
++
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ if (sbi->ckpt->alloc_type[i] == SSR)
++ valid_sum_count += sbi->blocks_per_seg;
++ else
++ valid_sum_count += curseg_blkoff(sbi, i);
++ }
++
++ total_size_bytes = valid_sum_count * (SUMMARY_SIZE + 1)
++ + sizeof(struct nat_journal) + 2
++ + sizeof(struct sit_journal) + 2;
++ sum_space = PAGE_CACHE_SIZE - SUM_FOOTER_SIZE;
++ if (total_size_bytes < sum_space)
++ return 1;
++ else if (total_size_bytes < 2 * sum_space)
++ return 2;
++ return 3;
++}
++
++/**
++ * Caller should put this summary page
++ */
++struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno));
++}
++
++static void write_sum_page(struct f2fs_sb_info *sbi,
++ struct f2fs_summary_block *sum_blk, block_t blk_addr)
++{
++ struct page *page = grab_meta_page(sbi, blk_addr);
++ void *kaddr = page_address(page);
++ memcpy(kaddr, sum_blk, PAGE_CACHE_SIZE);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++}
++
++static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi,
++ int ofs_unit, int type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE];
++ unsigned int segno, next_segno, i;
++ int ofs = 0;
++
++ /*
++ * If there is not enough reserved sections,
++ * we should not reuse prefree segments.
++ */
++ if (has_not_enough_free_secs(sbi))
++ return NULL_SEGNO;
++
++ /*
++ * NODE page should not reuse prefree segment,
++ * since those information is used for SPOR.
++ */
++ if (IS_NODESEG(type))
++ return NULL_SEGNO;
++next:
++ segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs++);
++ ofs = ((segno / ofs_unit) * ofs_unit) + ofs_unit;
++ if (segno < TOTAL_SEGS(sbi)) {
++ /* skip intermediate segments in a section */
++ if (segno % ofs_unit)
++ goto next;
++
++ /* skip if whole section is not prefree */
++ next_segno = find_next_zero_bit(prefree_segmap,
++ TOTAL_SEGS(sbi), segno + 1);
++ if (next_segno - segno < ofs_unit)
++ goto next;
++
++ /* skip if whole section was not free at the last checkpoint */
++ for (i = 0; i < ofs_unit; i++)
++ if (get_seg_entry(sbi, segno)->ckpt_valid_blocks)
++ goto next;
++ return segno;
++ }
++ return NULL_SEGNO;
++}
++
++/**
++ * Find a new segment from the free segments bitmap to right order
++ * This function should be returned with success, otherwise BUG
++ */
++static void get_new_segment(struct f2fs_sb_info *sbi,
++ unsigned int *newseg, bool new_sec, int dir)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int total_secs = sbi->total_sections;
++ unsigned int segno, secno, zoneno;
++ unsigned int total_zones = sbi->total_sections / sbi->secs_per_zone;
++ unsigned int hint = *newseg / sbi->segs_per_sec;
++ unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg);
++ unsigned int left_start = hint;
++ bool init = true;
++ int go_left = 0;
++ int i;
++
++ write_lock(&free_i->segmap_lock);
++
++ if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) {
++ segno = find_next_zero_bit(free_i->free_segmap,
++ TOTAL_SEGS(sbi), *newseg + 1);
++ if (segno < TOTAL_SEGS(sbi))
++ goto got_it;
++ }
++find_other_zone:
++ secno = find_next_zero_bit(free_i->free_secmap, total_secs, hint);
++ if (secno >= total_secs) {
++ if (dir == ALLOC_RIGHT) {
++ secno = find_next_zero_bit(free_i->free_secmap,
++ total_secs, 0);
++ BUG_ON(secno >= total_secs);
++ } else {
++ go_left = 1;
++ left_start = hint - 1;
++ }
++ }
++ if (go_left == 0)
++ goto skip_left;
++
++ while (test_bit(left_start, free_i->free_secmap)) {
++ if (left_start > 0) {
++ left_start--;
++ continue;
++ }
++ left_start = find_next_zero_bit(free_i->free_secmap,
++ total_secs, 0);
++ BUG_ON(left_start >= total_secs);
++ break;
++ }
++ secno = left_start;
++skip_left:
++ hint = secno;
++ segno = secno * sbi->segs_per_sec;
++ zoneno = secno / sbi->secs_per_zone;
++
++ /* give up on finding another zone */
++ if (!init)
++ goto got_it;
++ if (sbi->secs_per_zone == 1)
++ goto got_it;
++ if (zoneno == old_zoneno)
++ goto got_it;
++ if (dir == ALLOC_LEFT) {
++ if (!go_left && zoneno + 1 >= total_zones)
++ goto got_it;
++ if (go_left && zoneno == 0)
++ goto got_it;
++ }
++ for (i = 0; i < NR_CURSEG_TYPE; i++)
++ if (CURSEG_I(sbi, i)->zone == zoneno)
++ break;
++
++ if (i < NR_CURSEG_TYPE) {
++ /* zone is in user, try another */
++ if (go_left)
++ hint = zoneno * sbi->secs_per_zone - 1;
++ else if (zoneno + 1 >= total_zones)
++ hint = 0;
++ else
++ hint = (zoneno + 1) * sbi->secs_per_zone;
++ init = false;
++ goto find_other_zone;
++ }
++got_it:
++ /* set it as dirty segment in free segmap */
++ BUG_ON(test_bit(segno, free_i->free_segmap));
++ __set_inuse(sbi, segno);
++ *newseg = segno;
++ write_unlock(&free_i->segmap_lock);
++}
++
++static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ struct summary_footer *sum_footer;
++
++ curseg->segno = curseg->next_segno;
++ curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno);
++ curseg->next_blkoff = 0;
++ curseg->next_segno = NULL_SEGNO;
++
++ sum_footer = &(curseg->sum_blk->footer);
++ memset(sum_footer, 0, sizeof(struct summary_footer));
++ if (IS_DATASEG(type))
++ SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
++ if (IS_NODESEG(type))
++ SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
++ __set_sit_entry_type(sbi, type, curseg->segno, modified);
++}
++
++/**
++ * Allocate a current working segment.
++ * This function always allocates a free segment in LFS manner.
++ */
++static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ unsigned int segno = curseg->segno;
++ int dir = ALLOC_LEFT;
++
++ write_sum_page(sbi, curseg->sum_blk,
++ GET_SUM_BLOCK(sbi, curseg->segno));
++ if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA)
++ dir = ALLOC_RIGHT;
++
++ if (test_opt(sbi, NOHEAP))
++ dir = ALLOC_RIGHT;
++
++ get_new_segment(sbi, &segno, new_sec, dir);
++ curseg->next_segno = segno;
++ reset_curseg(sbi, type, 1);
++ curseg->alloc_type = LFS;
++}
++
++static void __next_free_blkoff(struct f2fs_sb_info *sbi,
++ struct curseg_info *seg, block_t start)
++{
++ struct seg_entry *se = get_seg_entry(sbi, seg->segno);
++ block_t ofs;
++ for (ofs = start; ofs < sbi->blocks_per_seg; ofs++) {
++ if (!f2fs_test_bit(ofs, se->ckpt_valid_map)
++ && !f2fs_test_bit(ofs, se->cur_valid_map))
++ break;
++ }
++ seg->next_blkoff = ofs;
++}
++
++/**
++ * If a segment is written by LFS manner, next block offset is just obtained
++ * by increasing the current block offset. However, if a segment is written by
++ * SSR manner, next block offset obtained by calling __next_free_blkoff
++ */
++static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
++ struct curseg_info *seg)
++{
++ if (seg->alloc_type == SSR)
++ __next_free_blkoff(sbi, seg, seg->next_blkoff + 1);
++ else
++ seg->next_blkoff++;
++}
++
++/**
++ * This function always allocates a used segment (from dirty seglist) by SSR
++ * manner, so it should recover the existing segment information of valid blocks
++ */
++static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ unsigned int new_segno = curseg->next_segno;
++ struct f2fs_summary_block *sum_node;
++ struct page *sum_page;
++
++ write_sum_page(sbi, curseg->sum_blk,
++ GET_SUM_BLOCK(sbi, curseg->segno));
++ __set_test_and_inuse(sbi, new_segno);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ __remove_dirty_segment(sbi, new_segno, PRE);
++ __remove_dirty_segment(sbi, new_segno, DIRTY);
++ mutex_unlock(&dirty_i->seglist_lock);
++
++ reset_curseg(sbi, type, 1);
++ curseg->alloc_type = SSR;
++ __next_free_blkoff(sbi, curseg, 0);
++
++ if (reuse) {
++ sum_page = get_sum_page(sbi, new_segno);
++ sum_node = (struct f2fs_summary_block *)page_address(sum_page);
++ memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
++ f2fs_put_page(sum_page, 1);
++ }
++}
++
++/*
++ * flush out current segment and replace it with new segment
++ * This function should be returned with success, otherwise BUG
++ */
++static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
++ int type, bool force)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ unsigned int ofs_unit;
++
++ if (force) {
++ new_curseg(sbi, type, true);
++ goto out;
++ }
++
++ ofs_unit = need_SSR(sbi) ? 1 : sbi->segs_per_sec;
++ curseg->next_segno = check_prefree_segments(sbi, ofs_unit, type);
++
++ if (curseg->next_segno != NULL_SEGNO)
++ change_curseg(sbi, type, false);
++ else if (type == CURSEG_WARM_NODE)
++ new_curseg(sbi, type, false);
++ else if (need_SSR(sbi) && IS_NEXT_SEG(sbi, curseg, type))
++ change_curseg(sbi, type, true);
++ else
++ new_curseg(sbi, type, false);
++out:
++ sbi->segment_count[curseg->alloc_type]++;
++}
++
++void allocate_new_segments(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *curseg;
++ unsigned int old_curseg;
++ int i;
++
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ curseg = CURSEG_I(sbi, i);
++ old_curseg = curseg->segno;
++ SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true);
++ locate_dirty_segment(sbi, old_curseg);
++ }
++}
++
++static const struct segment_allocation default_salloc_ops = {
++ .allocate_segment = allocate_segment_by_default,
++};
++
++static void f2fs_end_io_write(struct bio *bio, int err)
++{
++ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
++ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
++ struct bio_private *p = bio->bi_private;
++
++ do {
++ struct page *page = bvec->bv_page;
++
++ if (--bvec >= bio->bi_io_vec)
++ prefetchw(&bvec->bv_page->flags);
++ if (!uptodate) {
++ SetPageError(page);
++ if (page->mapping)
++ set_bit(AS_EIO, &page->mapping->flags);
++ p->sbi->ckpt->ckpt_flags |= CP_ERROR_FLAG;
++ set_page_dirty(page);
++ }
++ end_page_writeback(page);
++ dec_page_count(p->sbi, F2FS_WRITEBACK);
++ } while (bvec >= bio->bi_io_vec);
++
++ if (p->is_sync)
++ complete(p->wait);
++ kfree(p);
++ bio_put(bio);
++}
++
++struct bio *f2fs_bio_alloc(struct block_device *bdev, sector_t first_sector,
++ int nr_vecs, gfp_t gfp_flags)
++{
++ struct bio *bio;
++repeat:
++ /* allocate new bio */
++ bio = bio_alloc(gfp_flags, nr_vecs);
++
++ if (bio == NULL && (current->flags & PF_MEMALLOC)) {
++ while (!bio && (nr_vecs /= 2))
++ bio = bio_alloc(gfp_flags, nr_vecs);
++ }
++ if (bio) {
++ bio->bi_bdev = bdev;
++ bio->bi_sector = first_sector;
++retry:
++ bio->bi_private = kmalloc(sizeof(struct bio_private),
++ GFP_NOFS | __GFP_HIGH);
++ if (!bio->bi_private) {
++ cond_resched();
++ goto retry;
++ }
++ }
++ if (bio == NULL) {
++ cond_resched();
++ goto repeat;
++ }
++ return bio;
++}
++
++static void do_submit_bio(struct f2fs_sb_info *sbi,
++ enum page_type type, bool sync)
++{
++ int rw = sync ? WRITE_SYNC : WRITE;
++ enum page_type btype = type > META ? META : type;
++
++ if (type >= META_FLUSH)
++ rw = WRITE_FLUSH_FUA;
++
++ if (sbi->bio[btype]) {
++ struct bio_private *p = sbi->bio[btype]->bi_private;
++ p->sbi = sbi;
++ sbi->bio[btype]->bi_end_io = f2fs_end_io_write;
++ if (type == META_FLUSH) {
++ DECLARE_COMPLETION_ONSTACK(wait);
++ p->is_sync = true;
++ p->wait = &wait;
++ submit_bio(rw, sbi->bio[btype]);
++ wait_for_completion(&wait);
++ } else {
++ p->is_sync = false;
++ submit_bio(rw, sbi->bio[btype]);
++ }
++ sbi->bio[btype] = NULL;
++ }
++}
++
++void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync)
++{
++ down_write(&sbi->bio_sem);
++ do_submit_bio(sbi, type, sync);
++ up_write(&sbi->bio_sem);
++}
++
++static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
++ block_t blk_addr, enum page_type type)
++{
++ struct block_device *bdev = sbi->sb->s_bdev;
++
++ verify_block_addr(sbi, blk_addr);
++
++ down_write(&sbi->bio_sem);
++
++ inc_page_count(sbi, F2FS_WRITEBACK);
++
++ if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1)
++ do_submit_bio(sbi, type, false);
++alloc_new:
++ if (sbi->bio[type] == NULL)
++ sbi->bio[type] = f2fs_bio_alloc(bdev,
++ blk_addr << (sbi->log_blocksize - 9),
++ bio_get_nr_vecs(bdev), GFP_NOFS | __GFP_HIGH);
++
++ if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) <
++ PAGE_CACHE_SIZE) {
++ do_submit_bio(sbi, type, false);
++ goto alloc_new;
++ }
++
++ sbi->last_block_in_bio[type] = blk_addr;
++
++ up_write(&sbi->bio_sem);
++}
++
++static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ if (curseg->next_blkoff < sbi->blocks_per_seg)
++ return true;
++ return false;
++}
++
++static int __get_segment_type_2(struct page *page, enum page_type p_type)
++{
++ if (p_type == DATA)
++ return CURSEG_HOT_DATA;
++ else
++ return CURSEG_HOT_NODE;
++}
++
++static int __get_segment_type_4(struct page *page, enum page_type p_type)
++{
++ if (p_type == DATA) {
++ struct inode *inode = page->mapping->host;
++
++ if (S_ISDIR(inode->i_mode))
++ return CURSEG_HOT_DATA;
++ else
++ return CURSEG_COLD_DATA;
++ } else {
++ if (IS_DNODE(page) && !is_cold_node(page))
++ return CURSEG_HOT_NODE;
++ else
++ return CURSEG_COLD_NODE;
++ }
++}
++
++static int __get_segment_type_6(struct page *page, enum page_type p_type)
++{
++ if (p_type == DATA) {
++ struct inode *inode = page->mapping->host;
++
++ if (S_ISDIR(inode->i_mode))
++ return CURSEG_HOT_DATA;
++ else if (is_cold_data(page) || is_cold_file(inode))
++ return CURSEG_COLD_DATA;
++ else
++ return CURSEG_WARM_DATA;
++ } else {
++ if (IS_DNODE(page))
++ return is_cold_node(page) ? CURSEG_WARM_NODE :
++ CURSEG_HOT_NODE;
++ else
++ return CURSEG_COLD_NODE;
++ }
++}
++
++static int __get_segment_type(struct page *page, enum page_type p_type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ switch (sbi->active_logs) {
++ case 2:
++ return __get_segment_type_2(page, p_type);
++ case 4:
++ return __get_segment_type_4(page, p_type);
++ case 6:
++ return __get_segment_type_6(page, p_type);
++ default:
++ BUG();
++ }
++}
++
++static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
++ block_t old_blkaddr, block_t *new_blkaddr,
++ struct f2fs_summary *sum, enum page_type p_type)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct curseg_info *curseg;
++ unsigned int old_cursegno;
++ int type;
++
++ type = __get_segment_type(page, p_type);
++ curseg = CURSEG_I(sbi, type);
++
++ mutex_lock(&curseg->curseg_mutex);
++
++ *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
++ old_cursegno = curseg->segno;
++
++ /*
++ * __add_sum_entry should be resided under the curseg_mutex
++ * because, this function updates a summary entry in the
++ * current summary block.
++ */
++ __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
++
++ mutex_lock(&sit_i->sentry_lock);
++ __refresh_next_blkoff(sbi, curseg);
++ sbi->block_count[curseg->alloc_type]++;
++
++ /*
++ * SIT information should be updated before segment allocation,
++ * since SSR needs latest valid block information.
++ */
++ refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr);
++
++ if (!__has_curseg_space(sbi, type))
++ sit_i->s_ops->allocate_segment(sbi, type, false);
++
++ locate_dirty_segment(sbi, old_cursegno);
++ locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
++ mutex_unlock(&sit_i->sentry_lock);
++
++ if (p_type == NODE)
++ fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
++
++ /* writeout dirty page into bdev */
++ submit_write_page(sbi, page, *new_blkaddr, p_type);
++
++ mutex_unlock(&curseg->curseg_mutex);
++}
++
++int write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
++ struct writeback_control *wbc)
++{
++ if (wbc->for_reclaim)
++ return AOP_WRITEPAGE_ACTIVATE;
++
++ set_page_writeback(page);
++ submit_write_page(sbi, page, page->index, META);
++ return 0;
++}
++
++void write_node_page(struct f2fs_sb_info *sbi, struct page *page,
++ unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr)
++{
++ struct f2fs_summary sum;
++ set_summary(&sum, nid, 0, 0);
++ do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE);
++}
++
++void write_data_page(struct inode *inode, struct page *page,
++ struct dnode_of_data *dn, block_t old_blkaddr,
++ block_t *new_blkaddr)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_summary sum;
++ struct node_info ni;
++
++ BUG_ON(old_blkaddr == NULL_ADDR);
++ get_node_info(sbi, dn->nid, &ni);
++ set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
++
++ do_write_page(sbi, page, old_blkaddr,
++ new_blkaddr, &sum, DATA);
++}
++
++void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page,
++ block_t old_blk_addr)
++{
++ submit_write_page(sbi, page, old_blk_addr, DATA);
++}
++
++void recover_data_page(struct f2fs_sb_info *sbi,
++ struct page *page, struct f2fs_summary *sum,
++ block_t old_blkaddr, block_t new_blkaddr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct curseg_info *curseg;
++ unsigned int segno, old_cursegno;
++ struct seg_entry *se;
++ int type;
++
++ segno = GET_SEGNO(sbi, new_blkaddr);
++ se = get_seg_entry(sbi, segno);
++ type = se->type;
++
++ if (se->valid_blocks == 0 && !IS_CURSEG(sbi, segno)) {
++ if (old_blkaddr == NULL_ADDR)
++ type = CURSEG_COLD_DATA;
++ else
++ type = CURSEG_WARM_DATA;
++ }
++ curseg = CURSEG_I(sbi, type);
++
++ mutex_lock(&curseg->curseg_mutex);
++ mutex_lock(&sit_i->sentry_lock);
++
++ old_cursegno = curseg->segno;
++
++ /* change the current segment */
++ if (segno != curseg->segno) {
++ curseg->next_segno = segno;
++ change_curseg(sbi, type, true);
++ }
++
++ curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
++ (sbi->blocks_per_seg - 1);
++ __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
++
++ refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
++
++ locate_dirty_segment(sbi, old_cursegno);
++ locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
++
++ mutex_unlock(&sit_i->sentry_lock);
++ mutex_unlock(&curseg->curseg_mutex);
++}
++
++void rewrite_node_page(struct f2fs_sb_info *sbi,
++ struct page *page, struct f2fs_summary *sum,
++ block_t old_blkaddr, block_t new_blkaddr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ int type = CURSEG_WARM_NODE;
++ struct curseg_info *curseg;
++ unsigned int segno, old_cursegno;
++ block_t next_blkaddr = next_blkaddr_of_node(page);
++ unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr);
++
++ curseg = CURSEG_I(sbi, type);
++
++ mutex_lock(&curseg->curseg_mutex);
++ mutex_lock(&sit_i->sentry_lock);
++
++ segno = GET_SEGNO(sbi, new_blkaddr);
++ old_cursegno = curseg->segno;
++
++ /* change the current segment */
++ if (segno != curseg->segno) {
++ curseg->next_segno = segno;
++ change_curseg(sbi, type, true);
++ }
++ curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
++ (sbi->blocks_per_seg - 1);
++ __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
++
++ /* change the current log to the next block addr in advance */
++ if (next_segno != segno) {
++ curseg->next_segno = next_segno;
++ change_curseg(sbi, type, true);
++ }
++ curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, next_blkaddr) &
++ (sbi->blocks_per_seg - 1);
++
++ /* rewrite node page */
++ set_page_writeback(page);
++ submit_write_page(sbi, page, new_blkaddr, NODE);
++ f2fs_submit_bio(sbi, NODE, true);
++ refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
++
++ locate_dirty_segment(sbi, old_cursegno);
++ locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
++
++ mutex_unlock(&sit_i->sentry_lock);
++ mutex_unlock(&curseg->curseg_mutex);
++}
++
++static int read_compacted_summaries(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct curseg_info *seg_i;
++ unsigned char *kaddr;
++ struct page *page;
++ block_t start;
++ int i, j, offset;
++
++ start = start_sum_block(sbi);
++
++ page = get_meta_page(sbi, start++);
++ kaddr = (unsigned char *)page_address(page);
++
++ /* Step 1: restore nat cache */
++ seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ memcpy(&seg_i->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE);
++
++ /* Step 2: restore sit cache */
++ seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ memcpy(&seg_i->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE,
++ SUM_JOURNAL_SIZE);
++ offset = 2 * SUM_JOURNAL_SIZE;
++
++ /* Step 3: restore summary entries */
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ unsigned short blk_off;
++ unsigned int segno;
++
++ seg_i = CURSEG_I(sbi, i);
++ segno = le32_to_cpu(ckpt->cur_data_segno[i]);
++ blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
++ seg_i->next_segno = segno;
++ reset_curseg(sbi, i, 0);
++ seg_i->alloc_type = ckpt->alloc_type[i];
++ seg_i->next_blkoff = blk_off;
++
++ if (seg_i->alloc_type == SSR)
++ blk_off = sbi->blocks_per_seg;
++
++ for (j = 0; j < blk_off; j++) {
++ struct f2fs_summary *s;
++ s = (struct f2fs_summary *)(kaddr + offset);
++ seg_i->sum_blk->entries[j] = *s;
++ offset += SUMMARY_SIZE;
++ if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
++ SUM_FOOTER_SIZE)
++ continue;
++
++ f2fs_put_page(page, 1);
++ page = NULL;
++
++ page = get_meta_page(sbi, start++);
++ kaddr = (unsigned char *)page_address(page);
++ offset = 0;
++ }
++ }
++ f2fs_put_page(page, 1);
++ return 0;
++}
++
++static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct f2fs_summary_block *sum;
++ struct curseg_info *curseg;
++ struct page *new;
++ unsigned short blk_off;
++ unsigned int segno = 0;
++ block_t blk_addr = 0;
++
++ /* get segment number and block addr */
++ if (IS_DATASEG(type)) {
++ segno = le32_to_cpu(ckpt->cur_data_segno[type]);
++ blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
++ CURSEG_HOT_DATA]);
++ if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
++ blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
++ else
++ blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
++ } else {
++ segno = le32_to_cpu(ckpt->cur_node_segno[type -
++ CURSEG_HOT_NODE]);
++ blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type -
++ CURSEG_HOT_NODE]);
++ if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
++ blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
++ type - CURSEG_HOT_NODE);
++ else
++ blk_addr = GET_SUM_BLOCK(sbi, segno);
++ }
++
++ new = get_meta_page(sbi, blk_addr);
++ sum = (struct f2fs_summary_block *)page_address(new);
++
++ if (IS_NODESEG(type)) {
++ if (ckpt->ckpt_flags & CP_UMOUNT_FLAG) {
++ struct f2fs_summary *ns = &sum->entries[0];
++ int i;
++ for (i = 0; i < sbi->blocks_per_seg; i++, ns++) {
++ ns->version = 0;
++ ns->ofs_in_node = 0;
++ }
++ } else {
++ if (restore_node_summary(sbi, segno, sum)) {
++ f2fs_put_page(new, 1);
++ return -EINVAL;
++ }
++ }
++ }
++
++ /* set uncompleted segment to curseg */
++ curseg = CURSEG_I(sbi, type);
++ mutex_lock(&curseg->curseg_mutex);
++ memcpy(curseg->sum_blk, sum, PAGE_CACHE_SIZE);
++ curseg->next_segno = segno;
++ reset_curseg(sbi, type, 0);
++ curseg->alloc_type = ckpt->alloc_type[type];
++ curseg->next_blkoff = blk_off;
++ mutex_unlock(&curseg->curseg_mutex);
++ f2fs_put_page(new, 1);
++ return 0;
++}
++
++static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
++{
++ int type = CURSEG_HOT_DATA;
++
++ if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG) {
++ /* restore for compacted data summary */
++ if (read_compacted_summaries(sbi))
++ return -EINVAL;
++ type = CURSEG_HOT_NODE;
++ }
++
++ for (; type <= CURSEG_COLD_NODE; type++)
++ if (read_normal_summaries(sbi, type))
++ return -EINVAL;
++ return 0;
++}
++
++static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
++{
++ struct page *page;
++ unsigned char *kaddr;
++ struct f2fs_summary *summary;
++ struct curseg_info *seg_i;
++ int written_size = 0;
++ int i, j;
++
++ page = grab_meta_page(sbi, blkaddr++);
++ kaddr = (unsigned char *)page_address(page);
++
++ /* Step 1: write nat cache */
++ seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ memcpy(kaddr, &seg_i->sum_blk->n_nats, SUM_JOURNAL_SIZE);
++ written_size += SUM_JOURNAL_SIZE;
++
++ /* Step 2: write sit cache */
++ seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ memcpy(kaddr + written_size, &seg_i->sum_blk->n_sits,
++ SUM_JOURNAL_SIZE);
++ written_size += SUM_JOURNAL_SIZE;
++
++ set_page_dirty(page);
++
++ /* Step 3: write summary entries */
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ unsigned short blkoff;
++ seg_i = CURSEG_I(sbi, i);
++ if (sbi->ckpt->alloc_type[i] == SSR)
++ blkoff = sbi->blocks_per_seg;
++ else
++ blkoff = curseg_blkoff(sbi, i);
++
++ for (j = 0; j < blkoff; j++) {
++ if (!page) {
++ page = grab_meta_page(sbi, blkaddr++);
++ kaddr = (unsigned char *)page_address(page);
++ written_size = 0;
++ }
++ summary = (struct f2fs_summary *)(kaddr + written_size);
++ *summary = seg_i->sum_blk->entries[j];
++ written_size += SUMMARY_SIZE;
++ set_page_dirty(page);
++
++ if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
++ SUM_FOOTER_SIZE)
++ continue;
++
++ f2fs_put_page(page, 1);
++ page = NULL;
++ }
++ }
++ if (page)
++ f2fs_put_page(page, 1);
++}
++
++static void write_normal_summaries(struct f2fs_sb_info *sbi,
++ block_t blkaddr, int type)
++{
++ int i, end;
++ if (IS_DATASEG(type))
++ end = type + NR_CURSEG_DATA_TYPE;
++ else
++ end = type + NR_CURSEG_NODE_TYPE;
++
++ for (i = type; i < end; i++) {
++ struct curseg_info *sum = CURSEG_I(sbi, i);
++ mutex_lock(&sum->curseg_mutex);
++ write_sum_page(sbi, sum->sum_blk, blkaddr + (i - type));
++ mutex_unlock(&sum->curseg_mutex);
++ }
++}
++
++void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
++{
++ if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG)
++ write_compacted_summaries(sbi, start_blk);
++ else
++ write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA);
++}
++
++void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
++{
++ if (sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG)
++ write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
++ return;
++}
++
++int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type,
++ unsigned int val, int alloc)
++{
++ int i;
++
++ if (type == NAT_JOURNAL) {
++ for (i = 0; i < nats_in_cursum(sum); i++) {
++ if (le32_to_cpu(nid_in_journal(sum, i)) == val)
++ return i;
++ }
++ if (alloc && nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES)
++ return update_nats_in_cursum(sum, 1);
++ } else if (type == SIT_JOURNAL) {
++ for (i = 0; i < sits_in_cursum(sum); i++)
++ if (le32_to_cpu(segno_in_journal(sum, i)) == val)
++ return i;
++ if (alloc && sits_in_cursum(sum) < SIT_JOURNAL_ENTRIES)
++ return update_sits_in_cursum(sum, 1);
++ }
++ return -1;
++}
++
++static struct page *get_current_sit_page(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
++ block_t blk_addr = sit_i->sit_base_addr + offset;
++
++ check_seg_range(sbi, segno);
++
++ /* calculate sit block address */
++ if (f2fs_test_bit(offset, sit_i->sit_bitmap))
++ blk_addr += sit_i->sit_blocks;
++
++ return get_meta_page(sbi, blk_addr);
++}
++
++static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
++ unsigned int start)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct page *src_page, *dst_page;
++ pgoff_t src_off, dst_off;
++ void *src_addr, *dst_addr;
++
++ src_off = current_sit_addr(sbi, start);
++ dst_off = next_sit_addr(sbi, src_off);
++
++ /* get current sit block page without lock */
++ src_page = get_meta_page(sbi, src_off);
++ dst_page = grab_meta_page(sbi, dst_off);
++ BUG_ON(PageDirty(src_page));
++
++ src_addr = page_address(src_page);
++ dst_addr = page_address(dst_page);
++ memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
++
++ set_page_dirty(dst_page);
++ f2fs_put_page(src_page, 1);
++
++ set_to_next_sit(sit_i, start);
++
++ return dst_page;
++}
++
++static bool flush_sits_in_journal(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ int i;
++
++ /*
++ * If the journal area in the current summary is full of sit entries,
++ * all the sit entries will be flushed. Otherwise the sit entries
++ * are not able to replace with newly hot sit entries.
++ */
++ if (sits_in_cursum(sum) >= SIT_JOURNAL_ENTRIES) {
++ for (i = sits_in_cursum(sum) - 1; i >= 0; i--) {
++ unsigned int segno;
++ segno = le32_to_cpu(segno_in_journal(sum, i));
++ __mark_sit_entry_dirty(sbi, segno);
++ }
++ update_sits_in_cursum(sum, -sits_in_cursum(sum));
++ return 1;
++ }
++ return 0;
++}
++
++/**
++ * CP calls this function, which flushes SIT entries including sit_journal,
++ * and moves prefree segs to free segs.
++ */
++void flush_sit_entries(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned long *bitmap = sit_i->dirty_sentries_bitmap;
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ unsigned long nsegs = TOTAL_SEGS(sbi);
++ struct page *page = NULL;
++ struct f2fs_sit_block *raw_sit = NULL;
++ unsigned int start = 0, end = 0;
++ unsigned int segno = -1;
++ bool flushed;
++
++ mutex_lock(&curseg->curseg_mutex);
++ mutex_lock(&sit_i->sentry_lock);
++
++ /*
++ * "flushed" indicates whether sit entries in journal are flushed
++ * to the SIT area or not.
++ */
++ flushed = flush_sits_in_journal(sbi);
++
++ while ((segno = find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) {
++ struct seg_entry *se = get_seg_entry(sbi, segno);
++ int sit_offset, offset;
++
++ sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
++
++ if (flushed)
++ goto to_sit_page;
++
++ offset = lookup_journal_in_cursum(sum, SIT_JOURNAL, segno, 1);
++ if (offset >= 0) {
++ segno_in_journal(sum, offset) = cpu_to_le32(segno);
++ seg_info_to_raw_sit(se, &sit_in_journal(sum, offset));
++ goto flush_done;
++ }
++to_sit_page:
++ if (!page || (start > segno) || (segno > end)) {
++ if (page) {
++ f2fs_put_page(page, 1);
++ page = NULL;
++ }
++
++ start = START_SEGNO(sit_i, segno);
++ end = start + SIT_ENTRY_PER_BLOCK - 1;
++
++ /* read sit block that will be updated */
++ page = get_next_sit_page(sbi, start);
++ raw_sit = page_address(page);
++ }
++
++ /* udpate entry in SIT block */
++ seg_info_to_raw_sit(se, &raw_sit->entries[sit_offset]);
++flush_done:
++ __clear_bit(segno, bitmap);
++ sit_i->dirty_sentries--;
++ }
++ mutex_unlock(&sit_i->sentry_lock);
++ mutex_unlock(&curseg->curseg_mutex);
++
++ /* writeout last modified SIT block */
++ f2fs_put_page(page, 1);
++
++ set_prefree_as_free_segments(sbi);
++}
++
++static int build_sit_info(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct sit_info *sit_i;
++ unsigned int sit_segs, start;
++ char *src_bitmap, *dst_bitmap;
++ unsigned int bitmap_size;
++
++ /* allocate memory for SIT information */
++ sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL);
++ if (!sit_i)
++ return -ENOMEM;
++
++ SM_I(sbi)->sit_info = sit_i;
++
++ sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry));
++ if (!sit_i->sentries)
++ return -ENOMEM;
++
++ bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
++ if (!sit_i->dirty_sentries_bitmap)
++ return -ENOMEM;
++
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ sit_i->sentries[start].cur_valid_map
++ = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
++ sit_i->sentries[start].ckpt_valid_map
++ = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
++ if (!sit_i->sentries[start].cur_valid_map
++ || !sit_i->sentries[start].ckpt_valid_map)
++ return -ENOMEM;
++ }
++
++ if (sbi->segs_per_sec > 1) {
++ sit_i->sec_entries = vzalloc(sbi->total_sections *
++ sizeof(struct sec_entry));
++ if (!sit_i->sec_entries)
++ return -ENOMEM;
++ }
++
++ /* get information related with SIT */
++ sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1;
++
++ /* setup SIT bitmap from ckeckpoint pack */
++ bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
++ src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
++
++ dst_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
++ if (!dst_bitmap)
++ return -ENOMEM;
++ memcpy(dst_bitmap, src_bitmap, bitmap_size);
++
++ /* init SIT information */
++ sit_i->s_ops = &default_salloc_ops;
++
++ sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr);
++ sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg;
++ sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count);
++ sit_i->sit_bitmap = dst_bitmap;
++ sit_i->bitmap_size = bitmap_size;
++ sit_i->dirty_sentries = 0;
++ sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
++ sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time);
++ sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec;
++ mutex_init(&sit_i->sentry_lock);
++ return 0;
++}
++
++static int build_free_segmap(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ struct free_segmap_info *free_i;
++ unsigned int bitmap_size, sec_bitmap_size;
++
++ /* allocate memory for free segmap information */
++ free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL);
++ if (!free_i)
++ return -ENOMEM;
++
++ SM_I(sbi)->free_info = free_i;
++
++ bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL);
++ if (!free_i->free_segmap)
++ return -ENOMEM;
++
++ sec_bitmap_size = f2fs_bitmap_size(sbi->total_sections);
++ free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL);
++ if (!free_i->free_secmap)
++ return -ENOMEM;
++
++ /* set all segments as dirty temporarily */
++ memset(free_i->free_segmap, 0xff, bitmap_size);
++ memset(free_i->free_secmap, 0xff, sec_bitmap_size);
++
++ /* init free segmap information */
++ free_i->start_segno =
++ (unsigned int) GET_SEGNO_FROM_SEG0(sbi, sm_info->main_blkaddr);
++ free_i->free_segments = 0;
++ free_i->free_sections = 0;
++ rwlock_init(&free_i->segmap_lock);
++ return 0;
++}
++
++static int build_curseg(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *array = NULL;
++ int i;
++
++ array = kzalloc(sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL);
++ if (!array)
++ return -ENOMEM;
++
++ SM_I(sbi)->curseg_array = array;
++
++ for (i = 0; i < NR_CURSEG_TYPE; i++) {
++ mutex_init(&array[i].curseg_mutex);
++ array[i].sum_blk = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
++ if (!array[i].sum_blk)
++ return -ENOMEM;
++ array[i].segno = NULL_SEGNO;
++ array[i].next_blkoff = 0;
++ }
++ return restore_curseg_summaries(sbi);
++}
++
++static void build_sit_entries(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ unsigned int start;
++
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ struct seg_entry *se = &sit_i->sentries[start];
++ struct f2fs_sit_block *sit_blk;
++ struct f2fs_sit_entry sit;
++ struct page *page;
++ int i;
++
++ mutex_lock(&curseg->curseg_mutex);
++ for (i = 0; i < sits_in_cursum(sum); i++) {
++ if (le32_to_cpu(segno_in_journal(sum, i)) == start) {
++ sit = sit_in_journal(sum, i);
++ mutex_unlock(&curseg->curseg_mutex);
++ goto got_it;
++ }
++ }
++ mutex_unlock(&curseg->curseg_mutex);
++ page = get_current_sit_page(sbi, start);
++ sit_blk = (struct f2fs_sit_block *)page_address(page);
++ sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
++ f2fs_put_page(page, 1);
++got_it:
++ check_block_count(sbi, start, &sit);
++ seg_info_from_raw_sit(se, &sit);
++ if (sbi->segs_per_sec > 1) {
++ struct sec_entry *e = get_sec_entry(sbi, start);
++ e->valid_blocks += se->valid_blocks;
++ }
++ }
++}
++
++static void init_free_segmap(struct f2fs_sb_info *sbi)
++{
++ unsigned int start;
++ int type;
++
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ struct seg_entry *sentry = get_seg_entry(sbi, start);
++ if (!sentry->valid_blocks)
++ __set_free(sbi, start);
++ }
++
++ /* set use the current segments */
++ for (type = CURSEG_HOT_DATA; type <= CURSEG_COLD_NODE; type++) {
++ struct curseg_info *curseg_t = CURSEG_I(sbi, type);
++ __set_test_and_inuse(sbi, curseg_t->segno);
++ }
++}
++
++static void init_dirty_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int segno = 0, offset = 0;
++ unsigned short valid_blocks;
++
++ while (segno < TOTAL_SEGS(sbi)) {
++ /* find dirty segment based on free segmap */
++ segno = find_next_inuse(free_i, TOTAL_SEGS(sbi), offset);
++ if (segno >= TOTAL_SEGS(sbi))
++ break;
++ offset = segno + 1;
++ valid_blocks = get_valid_blocks(sbi, segno, 0);
++ if (valid_blocks >= sbi->blocks_per_seg || !valid_blocks)
++ continue;
++ mutex_lock(&dirty_i->seglist_lock);
++ __locate_dirty_segment(sbi, segno, DIRTY);
++ mutex_unlock(&dirty_i->seglist_lock);
++ }
++}
++
++static int init_victim_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ dirty_i->victim_segmap[FG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
++ dirty_i->victim_segmap[BG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
++ if (!dirty_i->victim_segmap[FG_GC] || !dirty_i->victim_segmap[BG_GC])
++ return -ENOMEM;
++ return 0;
++}
++
++static int build_dirty_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i;
++ unsigned int bitmap_size, i;
++
++ /* allocate memory for dirty segments list information */
++ dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL);
++ if (!dirty_i)
++ return -ENOMEM;
++
++ SM_I(sbi)->dirty_info = dirty_i;
++ mutex_init(&dirty_i->seglist_lock);
++
++ bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ for (i = 0; i < NR_DIRTY_TYPE; i++) {
++ dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL);
++ dirty_i->nr_dirty[i] = 0;
++ if (!dirty_i->dirty_segmap[i])
++ return -ENOMEM;
++ }
++
++ init_dirty_segmap(sbi);
++ return init_victim_segmap(sbi);
++}
++
++/**
++ * Update min, max modified time for cost-benefit GC algorithm
++ */
++static void init_min_max_mtime(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int segno;
++
++ mutex_lock(&sit_i->sentry_lock);
++
++ sit_i->min_mtime = LLONG_MAX;
++
++ for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
++ unsigned int i;
++ unsigned long long mtime = 0;
++
++ for (i = 0; i < sbi->segs_per_sec; i++)
++ mtime += get_seg_entry(sbi, segno + i)->mtime;
++
++ mtime = div_u64(mtime, sbi->segs_per_sec);
++
++ if (sit_i->min_mtime > mtime)
++ sit_i->min_mtime = mtime;
++ }
++ sit_i->max_mtime = get_mtime(sbi);
++ mutex_unlock(&sit_i->sentry_lock);
++}
++
++int build_segment_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct f2fs_sm_info *sm_info = NULL;
++
++ sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL);
++ if (!sm_info)
++ return -ENOMEM;
++
++ /* init sm info */
++ sbi->sm_info = sm_info;
++ INIT_LIST_HEAD(&sm_info->wblist_head);
++ spin_lock_init(&sm_info->wblist_lock);
++ sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
++ sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr);
++ sm_info->segment_count = le32_to_cpu(raw_super->segment_count);
++ sm_info->rsvd_segment_count =
++ le32_to_cpu(ckpt->rsvd_segment_count);
++ sm_info->main_segment_count =
++ le32_to_cpu(raw_super->segment_count_main);
++ sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
++ sm_info->segment_count_ssa =
++ le32_to_cpu(raw_super->segment_count_ssa);
++
++ if (build_sit_info(sbi))
++ return -EINVAL;
++ if (build_free_segmap(sbi))
++ return -EINVAL;
++ if (build_curseg(sbi))
++ return -EINVAL;
++
++ /* reinit free segmap based on SIT */
++ build_sit_entries(sbi);
++
++ init_free_segmap(sbi);
++ if (build_dirty_segmap(sbi))
++ return -EINVAL;
++
++ init_min_max_mtime(sbi);
++ return 0;
++}
++
++static void discard_dirty_segmap(struct f2fs_sb_info *sbi,
++ enum dirty_type dirty_type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ kfree(dirty_i->dirty_segmap[dirty_type]);
++ dirty_i->nr_dirty[dirty_type] = 0;
++ mutex_unlock(&dirty_i->seglist_lock);
++}
++
++void reset_victim_segmap(struct f2fs_sb_info *sbi)
++{
++ unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ memset(DIRTY_I(sbi)->victim_segmap[FG_GC], 0, bitmap_size);
++}
++
++static void destroy_victim_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ kfree(dirty_i->victim_segmap[FG_GC]);
++ kfree(dirty_i->victim_segmap[BG_GC]);
++}
++
++static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ int i;
++
++ if (!dirty_i)
++ return;
++
++ /* discard pre-free/dirty segments list */
++ for (i = 0; i < NR_DIRTY_TYPE; i++)
++ discard_dirty_segmap(sbi, i);
++
++ destroy_victim_segmap(sbi);
++ SM_I(sbi)->dirty_info = NULL;
++ kfree(dirty_i);
++}
++
++static void destroy_curseg(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *array = SM_I(sbi)->curseg_array;
++ int i;
++
++ if (!array)
++ return;
++ SM_I(sbi)->curseg_array = NULL;
++ for (i = 0; i < NR_CURSEG_TYPE; i++)
++ kfree(array[i].sum_blk);
++ kfree(array);
++}
++
++static void destroy_free_segmap(struct f2fs_sb_info *sbi)
++{
++ struct free_segmap_info *free_i = SM_I(sbi)->free_info;
++ if (!free_i)
++ return;
++ SM_I(sbi)->free_info = NULL;
++ kfree(free_i->free_segmap);
++ kfree(free_i->free_secmap);
++ kfree(free_i);
++}
++
++static void destroy_sit_info(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int start;
++
++ if (!sit_i)
++ return;
++
++ if (sit_i->sentries) {
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ kfree(sit_i->sentries[start].cur_valid_map);
++ kfree(sit_i->sentries[start].ckpt_valid_map);
++ }
++ }
++ vfree(sit_i->sentries);
++ vfree(sit_i->sec_entries);
++ kfree(sit_i->dirty_sentries_bitmap);
++
++ SM_I(sbi)->sit_info = NULL;
++ kfree(sit_i->sit_bitmap);
++ kfree(sit_i);
++}
++
++void destroy_segment_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ destroy_dirty_segmap(sbi);
++ destroy_curseg(sbi);
++ destroy_free_segmap(sbi);
++ destroy_sit_info(sbi);
++ sbi->sm_info = NULL;
++ kfree(sm_info);
++}
diff --git a/patches/linux-3.7-rc6/0105-f2fs-add-file-operations.patch b/patches/linux-3.7-rc6/0105-f2fs-add-file-operations.patch
new file mode 100644
index 0000000..0416dee
--- /dev/null
+++ b/patches/linux-3.7-rc6/0105-f2fs-add-file-operations.patch
@@ -0,0 +1,661 @@
+From 4d8f1a7a068621436faf7b1b17e6a330e0eb3a79 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:29:21 +0000
+Subject: [PATCH] f2fs: add file operations
+
+This adds memory operations and file/file_inode operations.
+
+- F2FS supports fallocate(), mmap(), fsync(), and basic ioctl().
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/file.c | 640 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 640 insertions(+)
+ create mode 100644 fs/f2fs/file.c
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+new file mode 100644
+index 0000000..81b1fd0
+--- /dev/null
++++ b/fs/f2fs/file.c
+@@ -0,0 +1,640 @@
++/**
++ * fs/f2fs/file.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/stat.h>
++#include <linux/buffer_head.h>
++#include <linux/writeback.h>
++#include <linux/falloc.h>
++#include <linux/types.h>
++#include <linux/uaccess.h>
++#include <linux/mount.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++#include "xattr.h"
++#include "acl.h"
++
++static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
++ struct vm_fault *vmf)
++{
++ struct page *page = vmf->page;
++ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *node_page;
++ block_t old_blk_addr;
++ struct dnode_of_data dn;
++ int err;
++
++ f2fs_balance_fs(sbi);
++
++ sb_start_pagefault(inode->i_sb);
++
++ mutex_lock_op(sbi, DATA_NEW);
++
++ /* block allocation */
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, page->index, 0);
++ if (err) {
++ mutex_unlock_op(sbi, DATA_NEW);
++ goto out;
++ }
++
++ old_blk_addr = dn.data_blkaddr;
++ node_page = dn.node_page;
++
++ if (old_blk_addr == NULL_ADDR) {
++ err = reserve_new_block(&dn);
++ if (err) {
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_NEW);
++ goto out;
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ mutex_unlock_op(sbi, DATA_NEW);
++
++ lock_page(page);
++ if (page->mapping != inode->i_mapping ||
++ page_offset(page) >= i_size_read(inode) ||
++ !PageUptodate(page)) {
++ unlock_page(page);
++ err = -EFAULT;
++ goto out;
++ }
++
++ /*
++ * check to see if the page is mapped already (no holes)
++ */
++ if (PageMappedToDisk(page))
++ goto out;
++
++ /* fill the page */
++ wait_on_page_writeback(page);
++
++ /* page is wholly or partially inside EOF */
++ if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) {
++ unsigned offset;
++ offset = i_size_read(inode) & ~PAGE_CACHE_MASK;
++ zero_user_segment(page, offset, PAGE_CACHE_SIZE);
++ }
++ set_page_dirty(page);
++ SetPageUptodate(page);
++
++ file_update_time(vma->vm_file);
++out:
++ sb_end_pagefault(inode->i_sb);
++ return block_page_mkwrite_return(err);
++}
++
++static const struct vm_operations_struct f2fs_file_vm_ops = {
++ .fault = filemap_fault,
++ .page_mkwrite = f2fs_vm_page_mkwrite,
++};
++
++static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
++{
++ struct dentry *dentry;
++ nid_t pino;
++
++ inode = igrab(inode);
++ dentry = d_find_any_alias(inode);
++ if (!dentry) {
++ iput(inode);
++ return 0;
++ }
++ pino = dentry->d_parent->d_inode->i_ino;
++ dput(dentry);
++ iput(inode);
++ return !is_checkpointed_node(sbi, pino);
++}
++
++int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
++{
++ struct inode *inode = file->f_mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ unsigned long long cur_version;
++ int ret = 0;
++ bool need_cp = false;
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++
++ ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
++ if (ret)
++ return ret;
++
++ mutex_lock(&inode->i_mutex);
++
++ if (inode->i_sb->s_flags & MS_RDONLY)
++ goto out;
++ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
++ goto out;
++
++ mutex_lock(&sbi->cp_mutex);
++ cur_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
++ mutex_unlock(&sbi->cp_mutex);
++
++ if (F2FS_I(inode)->data_version != cur_version &&
++ !(inode->i_state & I_DIRTY))
++ goto out;
++ F2FS_I(inode)->data_version--;
++
++ if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
++ need_cp = true;
++ if (is_inode_flag_set(F2FS_I(inode), FI_NEED_CP))
++ need_cp = true;
++ if (!space_for_roll_forward(sbi))
++ need_cp = true;
++ if (need_to_sync_dir(sbi, inode))
++ need_cp = true;
++
++ f2fs_write_inode(inode, NULL);
++
++ if (need_cp) {
++ /* all the dirty node pages should be flushed for POR */
++ ret = f2fs_sync_fs(inode->i_sb, 1);
++ clear_inode_flag(F2FS_I(inode), FI_NEED_CP);
++ } else {
++ while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0)
++ f2fs_write_inode(inode, NULL);
++ filemap_fdatawait_range(sbi->node_inode->i_mapping,
++ 0, LONG_MAX);
++ }
++out:
++ mutex_unlock(&inode->i_mutex);
++ return ret;
++}
++
++static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ file_accessed(file);
++ vma->vm_ops = &f2fs_file_vm_ops;
++ return 0;
++}
++
++static int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
++{
++ int nr_free = 0, ofs = dn->ofs_in_node;
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct f2fs_node *raw_node;
++ __le32 *addr;
++
++ raw_node = page_address(dn->node_page);
++ addr = blkaddr_in_node(raw_node) + ofs;
++
++ for ( ; count > 0; count--, addr++, dn->ofs_in_node++) {
++ block_t blkaddr = le32_to_cpu(*addr);
++ if (blkaddr == NULL_ADDR)
++ continue;
++
++ update_extent_cache(NULL_ADDR, dn);
++ invalidate_blocks(sbi, blkaddr);
++ dec_valid_block_count(sbi, dn->inode, 1);
++ nr_free++;
++ }
++ if (nr_free) {
++ set_page_dirty(dn->node_page);
++ sync_inode_page(dn);
++ }
++ dn->ofs_in_node = ofs;
++ return nr_free;
++}
++
++void truncate_data_blocks(struct dnode_of_data *dn)
++{
++ truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
++}
++
++static void truncate_partial_data_page(struct inode *inode, u64 from)
++{
++ unsigned offset = from & (PAGE_CACHE_SIZE - 1);
++ struct page *page;
++
++ if (!offset)
++ return;
++
++ page = find_data_page(inode, from >> PAGE_CACHE_SHIFT);
++ if (IS_ERR(page))
++ return;
++
++ lock_page(page);
++ wait_on_page_writeback(page);
++ zero_user(page, offset, PAGE_CACHE_SIZE - offset);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++}
++
++static int truncate_blocks(struct inode *inode, u64 from)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ unsigned int blocksize = inode->i_sb->s_blocksize;
++ struct dnode_of_data dn;
++ pgoff_t free_from;
++ int count = 0;
++ int err;
++
++ free_from = (pgoff_t)
++ ((from + blocksize - 1) >> (sbi->log_blocksize));
++
++ mutex_lock_op(sbi, DATA_TRUNC);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, free_from, RDONLY_NODE);
++ if (err) {
++ if (err == -ENOENT)
++ goto free_next;
++ mutex_unlock_op(sbi, DATA_TRUNC);
++ return err;
++ }
++
++ if (IS_INODE(dn.node_page))
++ count = ADDRS_PER_INODE;
++ else
++ count = ADDRS_PER_BLOCK;
++
++ count -= dn.ofs_in_node;
++ BUG_ON(count < 0);
++ if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
++ truncate_data_blocks_range(&dn, count);
++ free_from += count;
++ }
++
++ f2fs_put_dnode(&dn);
++free_next:
++ err = truncate_inode_blocks(inode, free_from);
++ mutex_unlock_op(sbi, DATA_TRUNC);
++
++ /* lastly zero out the first data page */
++ truncate_partial_data_page(inode, from);
++
++ return err;
++}
++
++void f2fs_truncate(struct inode *inode)
++{
++ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
++ S_ISLNK(inode->i_mode)))
++ return;
++
++ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
++ return;
++
++ if (!truncate_blocks(inode, i_size_read(inode))) {
++ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ mark_inode_dirty(inode);
++ }
++
++ f2fs_balance_fs(F2FS_SB(inode->i_sb));
++}
++
++static int f2fs_getattr(struct vfsmount *mnt,
++ struct dentry *dentry, struct kstat *stat)
++{
++ struct inode *inode = dentry->d_inode;
++ generic_fillattr(inode, stat);
++ stat->blocks <<= 3;
++ return 0;
++}
++
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++static void __setattr_copy(struct inode *inode, const struct iattr *attr)
++{
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ unsigned int ia_valid = attr->ia_valid;
++
++ if (ia_valid & ATTR_UID)
++ inode->i_uid = attr->ia_uid;
++ if (ia_valid & ATTR_GID)
++ inode->i_gid = attr->ia_gid;
++ if (ia_valid & ATTR_ATIME)
++ inode->i_atime = timespec_trunc(attr->ia_atime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_MTIME)
++ inode->i_mtime = timespec_trunc(attr->ia_mtime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_CTIME)
++ inode->i_ctime = timespec_trunc(attr->ia_ctime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_MODE) {
++ umode_t mode = attr->ia_mode;
++
++ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
++ mode &= ~S_ISGID;
++ set_acl_inode(fi, mode);
++ }
++}
++#else
++#define __setattr_copy setattr_copy
++#endif
++
++int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
++{
++ struct inode *inode = dentry->d_inode;
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ int err;
++
++ err = inode_change_ok(inode, attr);
++ if (err)
++ return err;
++
++ if ((attr->ia_valid & ATTR_SIZE) &&
++ attr->ia_size != i_size_read(inode)) {
++ truncate_setsize(inode, attr->ia_size);
++ f2fs_truncate(inode);
++ }
++
++ __setattr_copy(inode, attr);
++
++ if (attr->ia_valid & ATTR_MODE) {
++ err = f2fs_acl_chmod(inode);
++ if (err || is_inode_flag_set(fi, FI_ACL_MODE)) {
++ inode->i_mode = fi->i_acl_mode;
++ clear_inode_flag(fi, FI_ACL_MODE);
++ }
++ }
++
++ mark_inode_dirty(inode);
++ return err;
++}
++
++const struct inode_operations f2fs_file_inode_operations = {
++ .getattr = f2fs_getattr,
++ .setattr = f2fs_setattr,
++ .get_acl = f2fs_get_acl,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
++
++static void fill_zero(struct inode *inode, pgoff_t index,
++ loff_t start, loff_t len)
++{
++ struct page *page;
++
++ if (!len)
++ return;
++
++ page = get_new_data_page(inode, index, false);
++
++ if (!IS_ERR(page)) {
++ wait_on_page_writeback(page);
++ zero_user(page, start, len);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++ }
++}
++
++int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
++{
++ pgoff_t index;
++ int err;
++
++ for (index = pg_start; index < pg_end; index++) {
++ struct dnode_of_data dn;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++
++ mutex_lock_op(sbi, DATA_TRUNC);
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, RDONLY_NODE);
++ if (err) {
++ mutex_unlock_op(sbi, DATA_TRUNC);
++ if (err == -ENOENT)
++ continue;
++ return err;
++ }
++
++ if (dn.data_blkaddr != NULL_ADDR)
++ truncate_data_blocks_range(&dn, 1);
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_TRUNC);
++ }
++ return 0;
++}
++
++static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode)
++{
++ pgoff_t pg_start, pg_end;
++ loff_t off_start, off_end;
++ int ret = 0;
++
++ pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
++ pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
++
++ off_start = offset & (PAGE_CACHE_SIZE - 1);
++ off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
++
++ if (pg_start == pg_end) {
++ fill_zero(inode, pg_start, off_start,
++ off_end - off_start);
++ } else {
++ if (off_start)
++ fill_zero(inode, pg_start++, off_start,
++ PAGE_CACHE_SIZE - off_start);
++ if (off_end)
++ fill_zero(inode, pg_end, 0, off_end);
++
++ if (pg_start < pg_end) {
++ struct address_space *mapping = inode->i_mapping;
++ loff_t blk_start, blk_end;
++
++ blk_start = pg_start << PAGE_CACHE_SHIFT;
++ blk_end = pg_end << PAGE_CACHE_SHIFT;
++ truncate_inode_pages_range(mapping, blk_start,
++ blk_end - 1);
++ ret = truncate_hole(inode, pg_start, pg_end);
++ }
++ }
++
++ if (!(mode & FALLOC_FL_KEEP_SIZE) &&
++ i_size_read(inode) <= (offset + len)) {
++ i_size_write(inode, offset);
++ mark_inode_dirty(inode);
++ }
++
++ return ret;
++}
++
++static int expand_inode_data(struct inode *inode, loff_t offset,
++ loff_t len, int mode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ pgoff_t index, pg_start, pg_end;
++ loff_t new_size = i_size_read(inode);
++ loff_t off_start, off_end;
++ int ret = 0;
++
++ ret = inode_newsize_ok(inode, (len + offset));
++ if (ret)
++ return ret;
++
++ pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
++ pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
++
++ off_start = offset & (PAGE_CACHE_SIZE - 1);
++ off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
++
++ for (index = pg_start; index <= pg_end; index++) {
++ struct dnode_of_data dn;
++
++ mutex_lock_op(sbi, DATA_NEW);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ ret = get_dnode_of_data(&dn, index, 0);
++ if (ret) {
++ mutex_unlock_op(sbi, DATA_NEW);
++ break;
++ }
++
++ if (dn.data_blkaddr == NULL_ADDR) {
++ ret = reserve_new_block(&dn);
++ if (ret) {
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_NEW);
++ break;
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ mutex_unlock_op(sbi, DATA_NEW);
++
++ if (pg_start == pg_end)
++ new_size = offset + len;
++ else if (index == pg_start && off_start)
++ new_size = (index + 1) << PAGE_CACHE_SHIFT;
++ else if (index == pg_end)
++ new_size = (index << PAGE_CACHE_SHIFT) + off_end;
++ else
++ new_size += PAGE_CACHE_SIZE;
++ }
++
++ if (!(mode & FALLOC_FL_KEEP_SIZE) &&
++ i_size_read(inode) < new_size) {
++ i_size_write(inode, new_size);
++ mark_inode_dirty(inode);
++ }
++
++ return ret;
++}
++
++static long f2fs_fallocate(struct file *file, int mode,
++ loff_t offset, loff_t len)
++{
++ struct inode *inode = file->f_path.dentry->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ long ret;
++
++ if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
++ return -EOPNOTSUPP;
++
++ if (mode & FALLOC_FL_PUNCH_HOLE)
++ ret = punch_hole(inode, offset, len, mode);
++ else
++ ret = expand_inode_data(inode, offset, len, mode);
++
++ f2fs_balance_fs(sbi);
++ return ret;
++}
++
++#define F2FS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
++#define F2FS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
++
++static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags)
++{
++ if (S_ISDIR(mode))
++ return flags;
++ else if (S_ISREG(mode))
++ return flags & F2FS_REG_FLMASK;
++ else
++ return flags & F2FS_OTHER_FLMASK;
++}
++
++long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
++{
++ struct inode *inode = filp->f_dentry->d_inode;
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ unsigned int flags;
++ int ret;
++
++ switch (cmd) {
++ case FS_IOC_GETFLAGS:
++ flags = fi->i_flags & FS_FL_USER_VISIBLE;
++ return put_user(flags, (int __user *) arg);
++ case FS_IOC_SETFLAGS:
++ {
++ unsigned int oldflags;
++
++ ret = mnt_want_write(filp->f_path.mnt);
++ if (ret)
++ return ret;
++
++ if (!inode_owner_or_capable(inode)) {
++ ret = -EACCES;
++ goto out;
++ }
++
++ if (get_user(flags, (int __user *) arg)) {
++ ret = -EFAULT;
++ goto out;
++ }
++
++ flags = f2fs_mask_flags(inode->i_mode, flags);
++
++ mutex_lock(&inode->i_mutex);
++
++ oldflags = fi->i_flags;
++
++ if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
++ if (!capable(CAP_LINUX_IMMUTABLE)) {
++ mutex_unlock(&inode->i_mutex);
++ ret = -EPERM;
++ goto out;
++ }
++ }
++
++ flags = flags & FS_FL_USER_MODIFIABLE;
++ flags |= oldflags & ~FS_FL_USER_MODIFIABLE;
++ fi->i_flags = flags;
++ mutex_unlock(&inode->i_mutex);
++
++ f2fs_set_inode_flags(inode);
++ inode->i_ctime = CURRENT_TIME;
++ mark_inode_dirty(inode);
++out:
++ mnt_drop_write(filp->f_path.mnt);
++ return ret;
++ }
++ default:
++ return -ENOTTY;
++ }
++}
++
++const struct file_operations f2fs_file_operations = {
++ .llseek = generic_file_llseek,
++ .read = do_sync_read,
++ .write = do_sync_write,
++ .aio_read = generic_file_aio_read,
++ .aio_write = generic_file_aio_write,
++ .open = generic_file_open,
++ .mmap = f2fs_file_mmap,
++ .fsync = f2fs_sync_file,
++ .fallocate = f2fs_fallocate,
++ .unlocked_ioctl = f2fs_ioctl,
++ .splice_read = generic_file_splice_read,
++ .splice_write = generic_file_splice_write,
++};
diff --git a/patches/linux-3.7-rc6/0106-f2fs-add-address-space-operations-for-data.patch b/patches/linux-3.7-rc6/0106-f2fs-add-address-space-operations-for-data.patch
new file mode 100644
index 0000000..998552a
--- /dev/null
+++ b/patches/linux-3.7-rc6/0106-f2fs-add-address-space-operations-for-data.patch
@@ -0,0 +1,724 @@
+From 451af621e358f0ac96c3fe8b2dfd940fbebcda29 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:29:49 +0000
+Subject: [PATCH] f2fs: add address space operations for data
+
+This adds address space operations for data.
+
+- F2FS supports readpages(), writepages(), and direct_IO().
+
+- Because of out-of-place writes, f2fs_direct_IO() does not write data in place.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/data.c | 701 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 701 insertions(+)
+ create mode 100644 fs/f2fs/data.c
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+new file mode 100644
+index 0000000..c2fd0a8
+--- /dev/null
++++ b/fs/f2fs/data.c
+@@ -0,0 +1,701 @@
++/**
++ * fs/f2fs/data.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/buffer_head.h>
++#include <linux/mpage.h>
++#include <linux/writeback.h>
++#include <linux/backing-dev.h>
++#include <linux/blkdev.h>
++#include <linux/bio.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++/**
++ * Lock ordering for the change of data block address:
++ * ->data_page
++ * ->node_page
++ * update block addresses in the node page
++ */
++static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr)
++{
++ struct f2fs_node *rn;
++ __le32 *addr_array;
++ struct page *node_page = dn->node_page;
++ unsigned int ofs_in_node = dn->ofs_in_node;
++
++ wait_on_page_writeback(node_page);
++
++ rn = (struct f2fs_node *)page_address(node_page);
++
++ /* Get physical address of data block */
++ addr_array = blkaddr_in_node(rn);
++ addr_array[ofs_in_node] = cpu_to_le32(new_addr);
++ set_page_dirty(node_page);
++}
++
++int reserve_new_block(struct dnode_of_data *dn)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++
++ if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
++ return -EPERM;
++ if (!inc_valid_block_count(sbi, dn->inode, 1))
++ return -ENOSPC;
++
++ __set_data_blkaddr(dn, NEW_ADDR);
++ dn->data_blkaddr = NEW_ADDR;
++ sync_inode_page(dn);
++ return 0;
++}
++
++static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
++ struct buffer_head *bh_result)
++{
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ pgoff_t start_fofs, end_fofs;
++ block_t start_blkaddr;
++
++ read_lock(&fi->ext.ext_lock);
++ if (fi->ext.len == 0) {
++ read_unlock(&fi->ext.ext_lock);
++ return 0;
++ }
++
++ sbi->total_hit_ext++;
++ start_fofs = fi->ext.fofs;
++ end_fofs = fi->ext.fofs + fi->ext.len - 1;
++ start_blkaddr = fi->ext.blk_addr;
++
++ if (pgofs >= start_fofs && pgofs <= end_fofs) {
++ unsigned int blkbits = inode->i_sb->s_blocksize_bits;
++ size_t count;
++
++ clear_buffer_new(bh_result);
++ map_bh(bh_result, inode->i_sb,
++ start_blkaddr + pgofs - start_fofs);
++ count = end_fofs - pgofs + 1;
++ if (count < (UINT_MAX >> blkbits))
++ bh_result->b_size = (count << blkbits);
++ else
++ bh_result->b_size = UINT_MAX;
++
++ sbi->read_hit_ext++;
++ read_unlock(&fi->ext.ext_lock);
++ return 1;
++ }
++ read_unlock(&fi->ext.ext_lock);
++ return 0;
++}
++
++void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
++{
++ struct f2fs_inode_info *fi = F2FS_I(dn->inode);
++ pgoff_t fofs, start_fofs, end_fofs;
++ block_t start_blkaddr, end_blkaddr;
++
++ BUG_ON(blk_addr == NEW_ADDR);
++ fofs = start_bidx_of_node(ofs_of_node(dn->node_page)) + dn->ofs_in_node;
++
++ /* Update the page address in the parent node */
++ __set_data_blkaddr(dn, blk_addr);
++
++ write_lock(&fi->ext.ext_lock);
++
++ start_fofs = fi->ext.fofs;
++ end_fofs = fi->ext.fofs + fi->ext.len - 1;
++ start_blkaddr = fi->ext.blk_addr;
++ end_blkaddr = fi->ext.blk_addr + fi->ext.len - 1;
++
++ /* Drop and initialize the matched extent */
++ if (fi->ext.len == 1 && fofs == start_fofs)
++ fi->ext.len = 0;
++
++ /* Initial extent */
++ if (fi->ext.len == 0) {
++ if (blk_addr != NULL_ADDR) {
++ fi->ext.fofs = fofs;
++ fi->ext.blk_addr = blk_addr;
++ fi->ext.len = 1;
++ }
++ goto end_update;
++ }
++
++ /* Frone merge */
++ if (fofs == start_fofs - 1 && blk_addr == start_blkaddr - 1) {
++ fi->ext.fofs--;
++ fi->ext.blk_addr--;
++ fi->ext.len++;
++ goto end_update;
++ }
++
++ /* Back merge */
++ if (fofs == end_fofs + 1 && blk_addr == end_blkaddr + 1) {
++ fi->ext.len++;
++ goto end_update;
++ }
++
++ /* Split the existing extent */
++ if (fi->ext.len > 1 &&
++ fofs >= start_fofs && fofs <= end_fofs) {
++ if ((end_fofs - fofs) < (fi->ext.len >> 1)) {
++ fi->ext.len = fofs - start_fofs;
++ } else {
++ fi->ext.fofs = fofs + 1;
++ fi->ext.blk_addr = start_blkaddr +
++ fofs - start_fofs + 1;
++ fi->ext.len -= fofs - start_fofs + 1;
++ }
++ goto end_update;
++ }
++ write_unlock(&fi->ext.ext_lock);
++ return;
++
++end_update:
++ write_unlock(&fi->ext.ext_lock);
++ sync_inode_page(dn);
++ return;
++}
++
++struct page *find_data_page(struct inode *inode, pgoff_t index)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct address_space *mapping = inode->i_mapping;
++ struct dnode_of_data dn;
++ struct page *page;
++ int err;
++
++ page = find_get_page(mapping, index);
++ if (page && PageUptodate(page))
++ return page;
++ f2fs_put_page(page, 0);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, RDONLY_NODE);
++ if (err)
++ return ERR_PTR(err);
++ f2fs_put_dnode(&dn);
++
++ if (dn.data_blkaddr == NULL_ADDR)
++ return ERR_PTR(-ENOENT);
++
++ /* By fallocate(), there is no cached page, but with NEW_ADDR */
++ if (dn.data_blkaddr == NEW_ADDR)
++ return ERR_PTR(-EINVAL);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++ unlock_page(page);
++ return page;
++}
++
++/**
++ * If it tries to access a hole, return an error.
++ * Because, the callers, functions in dir.c and GC, should be able to know
++ * whether this page exists or not.
++ */
++struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct address_space *mapping = inode->i_mapping;
++ struct dnode_of_data dn;
++ struct page *page;
++ int err;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, RDONLY_NODE);
++ if (err)
++ return ERR_PTR(err);
++ f2fs_put_dnode(&dn);
++
++ if (dn.data_blkaddr == NULL_ADDR)
++ return ERR_PTR(-ENOENT);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ if (PageUptodate(page))
++ return page;
++
++ BUG_ON(dn.data_blkaddr == NEW_ADDR);
++ BUG_ON(dn.data_blkaddr == NULL_ADDR);
++
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++ return page;
++}
++
++/**
++ * Caller ensures that this data page is never allocated.
++ * A new zero-filled data page is allocated in the page cache.
++ */
++struct page *get_new_data_page(struct inode *inode, pgoff_t index,
++ bool new_i_size)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct address_space *mapping = inode->i_mapping;
++ struct page *page;
++ struct dnode_of_data dn;
++ int err;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, 0);
++ if (err)
++ return ERR_PTR(err);
++
++ if (dn.data_blkaddr == NULL_ADDR) {
++ if (reserve_new_block(&dn)) {
++ f2fs_put_dnode(&dn);
++ return ERR_PTR(-ENOSPC);
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ if (PageUptodate(page))
++ return page;
++
++ if (dn.data_blkaddr == NEW_ADDR) {
++ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
++ } else {
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++ }
++ SetPageUptodate(page);
++
++ if (new_i_size &&
++ i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) {
++ i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT));
++ mark_inode_dirty_sync(inode);
++ }
++ return page;
++}
++
++static void read_end_io(struct bio *bio, int err)
++{
++ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
++ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
++
++ do {
++ struct page *page = bvec->bv_page;
++
++ if (--bvec >= bio->bi_io_vec)
++ prefetchw(&bvec->bv_page->flags);
++
++ if (uptodate) {
++ SetPageUptodate(page);
++ } else {
++ ClearPageUptodate(page);
++ SetPageError(page);
++ }
++ unlock_page(page);
++ } while (bvec >= bio->bi_io_vec);
++ kfree(bio->bi_private);
++ bio_put(bio);
++}
++
++/**
++ * Fill the locked page with data located in the block address.
++ * Read operation is synchronous, and caller must unlock the page.
++ */
++int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
++ block_t blk_addr, int type)
++{
++ struct block_device *bdev = sbi->sb->s_bdev;
++ bool sync = (type == READ_SYNC);
++ struct bio *bio;
++
++ /* This page can be already read by other threads */
++ if (PageUptodate(page)) {
++ if (!sync)
++ unlock_page(page);
++ return 0;
++ }
++
++ down_read(&sbi->bio_sem);
++
++ /* Allocate a new bio */
++ bio = f2fs_bio_alloc(bdev, blk_addr << (sbi->log_blocksize - 9),
++ 1, GFP_NOFS | __GFP_HIGH);
++
++ /* Initialize the bio */
++ bio->bi_end_io = read_end_io;
++ if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
++ kfree(bio->bi_private);
++ bio_put(bio);
++ up_read(&sbi->bio_sem);
++ return -EFAULT;
++ }
++
++ submit_bio(type, bio);
++ up_read(&sbi->bio_sem);
++
++ /* wait for read completion if sync */
++ if (sync) {
++ lock_page(page);
++ if (PageError(page))
++ return -EIO;
++ }
++ return 0;
++}
++
++/**
++ * This function should be used by the data read flow only where it
++ * does not check the "create" flag that indicates block allocation.
++ * The reason for this special functionality is to exploit VFS readahead
++ * mechanism.
++ */
++static int get_data_block_ro(struct inode *inode, sector_t iblock,
++ struct buffer_head *bh_result, int create)
++{
++ unsigned int blkbits = inode->i_sb->s_blocksize_bits;
++ unsigned maxblocks = bh_result->b_size >> blkbits;
++ struct dnode_of_data dn;
++ pgoff_t pgofs;
++ int err;
++
++ /* Get the page offset from the block offset(iblock) */
++ pgofs = (pgoff_t)(iblock >> (PAGE_CACHE_SHIFT - blkbits));
++
++ if (check_extent_cache(inode, pgofs, bh_result))
++ return 0;
++
++ /* When reading holes, we need its node page */
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, pgofs, RDONLY_NODE);
++ if (err)
++ return (err == -ENOENT) ? 0 : err;
++
++ /* It does not support data allocation */
++ BUG_ON(create);
++
++ if (dn.data_blkaddr != NEW_ADDR && dn.data_blkaddr != NULL_ADDR) {
++ int i;
++ unsigned int end_offset;
++
++ end_offset = IS_INODE(dn.node_page) ?
++ ADDRS_PER_INODE :
++ ADDRS_PER_BLOCK;
++
++ clear_buffer_new(bh_result);
++
++ /* Give more consecutive addresses for the read ahead */
++ for (i = 0; i < end_offset - dn.ofs_in_node; i++)
++ if (((datablock_addr(dn.node_page,
++ dn.ofs_in_node + i))
++ != (dn.data_blkaddr + i)) || maxblocks == i)
++ break;
++ map_bh(bh_result, inode->i_sb, dn.data_blkaddr);
++ bh_result->b_size = (i << blkbits);
++ }
++ f2fs_put_dnode(&dn);
++ return 0;
++}
++
++static int f2fs_read_data_page(struct file *file, struct page *page)
++{
++ return mpage_readpage(page, get_data_block_ro);
++}
++
++static int f2fs_read_data_pages(struct file *file,
++ struct address_space *mapping,
++ struct list_head *pages, unsigned nr_pages)
++{
++ return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro);
++}
++
++int do_write_data_page(struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ block_t old_blk_addr, new_blk_addr;
++ struct dnode_of_data dn;
++ int err = 0;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, page->index, RDONLY_NODE);
++ if (err)
++ return err;
++
++ old_blk_addr = dn.data_blkaddr;
++
++ /* This page is already truncated */
++ if (old_blk_addr == NULL_ADDR)
++ goto out_writepage;
++
++ set_page_writeback(page);
++
++ /*
++ * If current allocation needs SSR,
++ * it had better in-place writes for updated data.
++ */
++ if (old_blk_addr != NEW_ADDR && !is_cold_data(page) &&
++ need_inplace_update(inode)) {
++ rewrite_data_page(F2FS_SB(inode->i_sb), page,
++ old_blk_addr);
++ } else {
++ write_data_page(inode, page, &dn,
++ old_blk_addr, &new_blk_addr);
++ update_extent_cache(new_blk_addr, &dn);
++ F2FS_I(inode)->data_version =
++ le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
++ }
++out_writepage:
++ f2fs_put_dnode(&dn);
++ return err;
++}
++
++static int f2fs_write_data_page(struct page *page,
++ struct writeback_control *wbc)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ loff_t i_size = i_size_read(inode);
++ const pgoff_t end_index = ((unsigned long long) i_size)
++ >> PAGE_CACHE_SHIFT;
++ unsigned offset;
++ int err = 0;
++
++ if (page->index < end_index)
++ goto out;
++
++ /*
++ * If the offset is out-of-range of file size,
++ * this page does not have to be written to disk.
++ */
++ offset = i_size & (PAGE_CACHE_SIZE - 1);
++ if ((page->index >= end_index + 1) || !offset) {
++ if (S_ISDIR(inode->i_mode)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ goto unlock_out;
++ }
++
++ zero_user_segment(page, offset, PAGE_CACHE_SIZE);
++out:
++ if (sbi->por_doing)
++ goto redirty_out;
++
++ if (wbc->for_reclaim && !S_ISDIR(inode->i_mode) && !is_cold_data(page))
++ goto redirty_out;
++
++ mutex_lock_op(sbi, DATA_WRITE);
++ if (S_ISDIR(inode->i_mode)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ err = do_write_data_page(page);
++ if (err && err != -ENOENT) {
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ }
++ mutex_unlock_op(sbi, DATA_WRITE);
++
++ if (wbc->for_reclaim)
++ f2fs_submit_bio(sbi, DATA, true);
++
++ if (err == -ENOENT)
++ goto unlock_out;
++
++ clear_cold_data(page);
++ unlock_page(page);
++
++ if (!wbc->for_reclaim && !S_ISDIR(inode->i_mode))
++ f2fs_balance_fs(sbi);
++ return 0;
++
++unlock_out:
++ unlock_page(page);
++ return (err == -ENOENT) ? 0 : err;
++
++redirty_out:
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ return AOP_WRITEPAGE_ACTIVATE;
++}
++
++#define MAX_DESIRED_PAGES_WP 4096
++
++int f2fs_write_data_pages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{
++ struct inode *inode = mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int ret;
++ long excess_nrtw = 0, desired_nrtw;
++
++ if (wbc->nr_to_write < MAX_DESIRED_PAGES_WP) {
++ desired_nrtw = MAX_DESIRED_PAGES_WP;
++ excess_nrtw = desired_nrtw - wbc->nr_to_write;
++ wbc->nr_to_write = desired_nrtw;
++ }
++
++ if (!S_ISDIR(inode->i_mode))
++ mutex_lock(&sbi->writepages);
++ ret = generic_writepages(mapping, wbc);
++ if (!S_ISDIR(inode->i_mode))
++ mutex_unlock(&sbi->writepages);
++ f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
++
++ remove_dirty_dir_inode(inode);
++
++ wbc->nr_to_write -= excess_nrtw;
++ return ret;
++}
++
++static int f2fs_write_begin(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned flags,
++ struct page **pagep, void **fsdata)
++{
++ struct inode *inode = mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *page;
++ pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT;
++ struct dnode_of_data dn;
++ int err = 0;
++
++ /* for nobh_write_end */
++ *fsdata = NULL;
++
++ f2fs_balance_fs(sbi);
++
++ page = grab_cache_page_write_begin(mapping, index, flags);
++ if (!page)
++ return -ENOMEM;
++ *pagep = page;
++
++ mutex_lock_op(sbi, DATA_NEW);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, 0);
++ if (err) {
++ mutex_unlock_op(sbi, DATA_NEW);
++ f2fs_put_page(page, 1);
++ return err;
++ }
++
++ if (dn.data_blkaddr == NULL_ADDR) {
++ err = reserve_new_block(&dn);
++ if (err) {
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_NEW);
++ f2fs_put_page(page, 1);
++ return err;
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ mutex_unlock_op(sbi, DATA_NEW);
++
++ if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
++ return 0;
++
++ if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) {
++ unsigned start = pos & (PAGE_CACHE_SIZE - 1);
++ unsigned end = start + len;
++
++ /* Reading beyond i_size is simple: memset to zero */
++ zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE);
++ return 0;
++ }
++
++ if (dn.data_blkaddr == NEW_ADDR) {
++ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
++ } else {
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return err;
++ }
++ }
++ SetPageUptodate(page);
++ clear_cold_data(page);
++ return 0;
++}
++
++static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
++ const struct iovec *iov, loff_t offset, unsigned long nr_segs)
++{
++ struct file *file = iocb->ki_filp;
++ struct inode *inode = file->f_mapping->host;
++
++ if (rw == WRITE)
++ return 0;
++
++ /* Needs synchronization with the cleaner */
++ return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
++ get_data_block_ro);
++}
++
++static void f2fs_invalidate_data_page(struct page *page, unsigned long offset)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ if (S_ISDIR(inode->i_mode) && PageDirty(page)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ ClearPagePrivate(page);
++}
++
++static int f2fs_release_data_page(struct page *page, gfp_t wait)
++{
++ ClearPagePrivate(page);
++ return 0;
++}
++
++static int f2fs_set_data_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct inode *inode = mapping->host;
++
++ SetPageUptodate(page);
++ if (!PageDirty(page)) {
++ __set_page_dirty_nobuffers(page);
++ set_dirty_dir_page(inode, page);
++ return 1;
++ }
++ return 0;
++}
++
++const struct address_space_operations f2fs_dblock_aops = {
++ .readpage = f2fs_read_data_page,
++ .readpages = f2fs_read_data_pages,
++ .writepage = f2fs_write_data_page,
++ .writepages = f2fs_write_data_pages,
++ .write_begin = f2fs_write_begin,
++ .write_end = nobh_write_end,
++ .set_page_dirty = f2fs_set_data_page_dirty,
++ .invalidatepage = f2fs_invalidate_data_page,
++ .releasepage = f2fs_release_data_page,
++ .direct_IO = f2fs_direct_IO,
++};
diff --git a/patches/linux-3.7-rc6/0107-f2fs-add-core-inode-operations.patch b/patches/linux-3.7-rc6/0107-f2fs-add-core-inode-operations.patch
new file mode 100644
index 0000000..60484b6
--- /dev/null
+++ b/patches/linux-3.7-rc6/0107-f2fs-add-core-inode-operations.patch
@@ -0,0 +1,282 @@
+From dcf1bc84b5065c486a3eb6d516b3f7d150138120 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:30:16 +0000
+Subject: [PATCH] f2fs: add core inode operations
+
+This adds core functions to get, read, write, and evict an inode.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/inode.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 262 insertions(+)
+ create mode 100644 fs/f2fs/inode.c
+
+diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
+new file mode 100644
+index 0000000..0cf61da
+--- /dev/null
++++ b/fs/f2fs/inode.c
+@@ -0,0 +1,262 @@
++/**
++ * fs/f2fs/inode.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/buffer_head.h>
++#include <linux/writeback.h>
++
++#include "f2fs.h"
++#include "node.h"
++
++struct f2fs_iget_args {
++ u64 ino;
++ int on_free;
++};
++
++void f2fs_set_inode_flags(struct inode *inode)
++{
++ unsigned int flags = F2FS_I(inode)->i_flags;
++
++ inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE |
++ S_NOATIME | S_DIRSYNC);
++
++ if (flags & FS_SYNC_FL)
++ inode->i_flags |= S_SYNC;
++ if (flags & FS_APPEND_FL)
++ inode->i_flags |= S_APPEND;
++ if (flags & FS_IMMUTABLE_FL)
++ inode->i_flags |= S_IMMUTABLE;
++ if (flags & FS_NOATIME_FL)
++ inode->i_flags |= S_NOATIME;
++ if (flags & FS_DIRSYNC_FL)
++ inode->i_flags |= S_DIRSYNC;
++}
++
++static int f2fs_iget_test(struct inode *inode, void *data)
++{
++ struct f2fs_iget_args *args = data;
++
++ if (inode->i_ino != args->ino)
++ return 0;
++ if (inode->i_state & (I_FREEING | I_WILL_FREE)) {
++ args->on_free = 1;
++ return 0;
++ }
++ return 1;
++}
++
++struct inode *f2fs_iget_nowait(struct super_block *sb, unsigned long ino)
++{
++ struct f2fs_iget_args args = {
++ .ino = ino,
++ .on_free = 0
++ };
++ struct inode *inode = ilookup5(sb, ino, f2fs_iget_test, &args);
++
++ if (inode)
++ return inode;
++ if (!args.on_free)
++ return f2fs_iget(sb, ino);
++ return ERR_PTR(-ENOENT);
++}
++
++static int do_read_inode(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct page *node_page;
++ struct f2fs_node *rn;
++ struct f2fs_inode *ri;
++
++ /* Check if ino is within scope */
++ check_nid_range(sbi, inode->i_ino);
++
++ node_page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(node_page))
++ return PTR_ERR(node_page);
++
++ rn = page_address(node_page);
++ ri = &(rn->i);
++
++ inode->i_mode = le16_to_cpu(ri->i_mode);
++ i_uid_write(inode, le32_to_cpu(ri->i_uid));
++ i_gid_write(inode, le32_to_cpu(ri->i_gid));
++ set_nlink(inode, le32_to_cpu(ri->i_links));
++ inode->i_size = le64_to_cpu(ri->i_size);
++ inode->i_blocks = le64_to_cpu(ri->i_blocks);
++
++ inode->i_atime.tv_sec = le64_to_cpu(ri->i_mtime);
++ inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime);
++ inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime);
++ inode->i_atime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
++ inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
++ inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
++
++ fi->current_depth = le32_to_cpu(ri->current_depth);
++ fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
++ fi->i_flags = le32_to_cpu(ri->i_flags);
++ fi->flags = 0;
++ fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
++ fi->i_advise = ri->i_advise;
++ get_extent_info(&fi->ext, ri->i_ext);
++ f2fs_put_page(node_page, 1);
++ return 0;
++}
++
++struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ int ret;
++
++ inode = iget_locked(sb, ino);
++ if (!inode)
++ return ERR_PTR(-ENOMEM);
++ if (!(inode->i_state & I_NEW))
++ return inode;
++ if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
++ goto make_now;
++
++ ret = do_read_inode(inode);
++ if (ret)
++ goto bad_inode;
++
++ if (!sbi->por_doing && inode->i_nlink == 0) {
++ ret = -ENOENT;
++ goto bad_inode;
++ }
++
++make_now:
++ if (ino == F2FS_NODE_INO(sbi)) {
++ inode->i_mapping->a_ops = &f2fs_node_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_MOVABLE);
++ } else if (ino == F2FS_META_INO(sbi)) {
++ inode->i_mapping->a_ops = &f2fs_meta_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_MOVABLE);
++ } else if (S_ISREG(inode->i_mode)) {
++ inode->i_op = &f2fs_file_inode_operations;
++ inode->i_fop = &f2fs_file_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ } else if (S_ISDIR(inode->i_mode)) {
++ inode->i_op = &f2fs_dir_inode_operations;
++ inode->i_fop = &f2fs_dir_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE |
++ __GFP_ZERO);
++ } else if (S_ISLNK(inode->i_mode)) {
++ inode->i_op = &f2fs_symlink_inode_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
++ S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
++ inode->i_op = &f2fs_special_inode_operations;
++ init_special_inode(inode, inode->i_mode, inode->i_rdev);
++ } else {
++ ret = -EIO;
++ goto bad_inode;
++ }
++ unlock_new_inode(inode);
++
++ return inode;
++
++bad_inode:
++ iget_failed(inode);
++ return ERR_PTR(ret);
++}
++
++void update_inode(struct inode *inode, struct page *node_page)
++{
++ struct f2fs_node *rn;
++ struct f2fs_inode *ri;
++
++ wait_on_page_writeback(node_page);
++
++ rn = page_address(node_page);
++ ri = &(rn->i);
++
++ ri->i_mode = cpu_to_le16(inode->i_mode);
++ ri->i_advise = F2FS_I(inode)->i_advise;
++ ri->i_uid = cpu_to_le32(i_uid_read(inode));
++ ri->i_gid = cpu_to_le32(i_gid_read(inode));
++ ri->i_links = cpu_to_le32(inode->i_nlink);
++ ri->i_size = cpu_to_le64(i_size_read(inode));
++ ri->i_blocks = cpu_to_le64(inode->i_blocks);
++ set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext);
++
++ ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
++ ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
++ ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
++ ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
++ ri->current_depth = cpu_to_le32(F2FS_I(inode)->current_depth);
++ ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
++ ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
++ set_page_dirty(node_page);
++}
++
++int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *node_page;
++ bool need_lock = false;
++
++ if (inode->i_ino == F2FS_NODE_INO(sbi) ||
++ inode->i_ino == F2FS_META_INO(sbi))
++ return 0;
++
++ node_page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(node_page))
++ return PTR_ERR(node_page);
++
++ if (!PageDirty(node_page)) {
++ need_lock = true;
++ f2fs_put_page(node_page, 1);
++ mutex_lock(&sbi->write_inode);
++ node_page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(node_page)) {
++ mutex_unlock(&sbi->write_inode);
++ return PTR_ERR(node_page);
++ }
++ }
++ update_inode(inode, node_page);
++ f2fs_put_page(node_page, 1);
++ if (need_lock)
++ mutex_unlock(&sbi->write_inode);
++ return 0;
++}
++
++/**
++ * Called at the last iput() if i_nlink is zero
++ */
++void f2fs_evict_inode(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++
++ truncate_inode_pages(&inode->i_data, 0);
++
++ if (inode->i_ino == F2FS_NODE_INO(sbi) ||
++ inode->i_ino == F2FS_META_INO(sbi))
++ goto no_delete;
++
++ BUG_ON(atomic_read(&F2FS_I(inode)->dirty_dents));
++ remove_dirty_dir_inode(inode);
++
++ if (inode->i_nlink || is_bad_inode(inode))
++ goto no_delete;
++
++ set_inode_flag(F2FS_I(inode), FI_NO_ALLOC);
++ i_size_write(inode, 0);
++
++ if (F2FS_HAS_BLOCKS(inode))
++ f2fs_truncate(inode);
++
++ remove_inode_page(inode);
++no_delete:
++ clear_inode(inode);
++}
diff --git a/patches/linux-3.7-rc6/0108-f2fs-add-inode-operations-for-special-inodes.patch b/patches/linux-3.7-rc6/0108-f2fs-add-inode-operations-for-special-inodes.patch
new file mode 100644
index 0000000..4992a4e
--- /dev/null
+++ b/patches/linux-3.7-rc6/0108-f2fs-add-inode-operations-for-special-inodes.patch
@@ -0,0 +1,514 @@
+From 9a81dfce3a0c412925ec2fb68becab30e774089e Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:30:45 +0000
+Subject: [PATCH] f2fs: add inode operations for special inodes
+
+This adds inode operations for directory, symlink, and special inodes.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/namei.c | 494 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 494 insertions(+)
+ create mode 100644 fs/f2fs/namei.c
+
+diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
+new file mode 100644
+index 0000000..899d144
+--- /dev/null
++++ b/fs/f2fs/namei.c
+@@ -0,0 +1,494 @@
++/**
++ * fs/f2fs/namei.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/pagemap.h>
++#include <linux/sched.h>
++#include <linux/ctype.h>
++
++#include "f2fs.h"
++#include "xattr.h"
++#include "acl.h"
++
++static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ nid_t ino;
++ struct inode *inode;
++ bool nid_free = false;
++ int err;
++
++ inode = new_inode(sb);
++ if (!inode)
++ return ERR_PTR(-ENOMEM);
++
++ mutex_lock_op(sbi, NODE_NEW);
++ if (!alloc_nid(sbi, &ino)) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ err = -ENOSPC;
++ goto fail;
++ }
++ mutex_unlock_op(sbi, NODE_NEW);
++
++ inode->i_uid = current_fsuid();
++
++ if (dir->i_mode & S_ISGID) {
++ inode->i_gid = dir->i_gid;
++ if (S_ISDIR(mode))
++ mode |= S_ISGID;
++ } else {
++ inode->i_gid = current_fsgid();
++ }
++
++ inode->i_ino = ino;
++ inode->i_mode = mode;
++ inode->i_blocks = 0;
++ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
++
++ err = insert_inode_locked(inode);
++ if (err) {
++ err = -EINVAL;
++ nid_free = true;
++ goto out;
++ }
++
++ mark_inode_dirty(inode);
++ return inode;
++
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++fail:
++ iput(inode);
++ if (nid_free)
++ alloc_nid_failed(sbi, ino);
++ return ERR_PTR(err);
++}
++
++static int is_multimedia_file(const unsigned char *s, const char *sub)
++{
++ int slen = strlen(s);
++ int sublen = strlen(sub);
++ int ret;
++
++ if (sublen > slen)
++ return 1;
++
++ ret = memcmp(s + slen - sublen, sub, sublen);
++ if (ret) { /* compare upper case */
++ int i;
++ char upper_sub[8];
++ for (i = 0; i < sublen && i < sizeof(upper_sub); i++)
++ upper_sub[i] = toupper(sub[i]);
++ return memcmp(s + slen - sublen, upper_sub, sublen);
++ }
++
++ return ret;
++}
++
++/**
++ * Set multimedia files as cold files for hot/cold data separation
++ */
++static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode,
++ const unsigned char *name)
++{
++ int i;
++ __u8 (*extlist)[8] = sbi->raw_super->extension_list;
++
++ int count = le32_to_cpu(sbi->raw_super->extension_count);
++ for (i = 0; i < count; i++) {
++ if (!is_multimedia_file(name, extlist[i])) {
++ F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT;
++ break;
++ }
++ }
++}
++
++static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
++ bool excl)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ nid_t ino = 0;
++ int err;
++
++ inode = f2fs_new_inode(dir, mode);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++
++ if (!test_opt(sbi, DISABLE_EXT_IDENTIFY))
++ set_cold_file(sbi, inode, dentry->d_name.name);
++
++ inode->i_op = &f2fs_file_inode_operations;
++ inode->i_fop = &f2fs_file_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ ino = inode->i_ino;
++
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ alloc_nid_done(sbi, ino);
++
++ if (!sbi->por_doing)
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, ino);
++ return err;
++}
++
++static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ struct inode *inode = old_dentry->d_inode;
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ int err;
++
++ inode->i_ctime = CURRENT_TIME;
++ atomic_inc(&inode->i_count);
++
++ set_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ d_instantiate(dentry, inode);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++out:
++ clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ iput(inode);
++ return err;
++}
++
++static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
++ unsigned int flags)
++{
++ struct inode *inode = NULL;
++ struct f2fs_dir_entry *de;
++ struct page *page;
++
++ if (dentry->d_name.len > F2FS_MAX_NAME_LEN)
++ return ERR_PTR(-ENAMETOOLONG);
++
++ de = f2fs_find_entry(dir, &dentry->d_name, &page);
++ if (de) {
++ nid_t ino = le32_to_cpu(de->ino);
++ kunmap(page);
++ f2fs_put_page(page, 0);
++
++ inode = f2fs_iget(dir->i_sb, ino);
++ if (IS_ERR(inode))
++ return ERR_CAST(inode);
++ }
++
++ return d_splice_alias(inode, dentry);
++}
++
++static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode = dentry->d_inode;
++ struct f2fs_dir_entry *de;
++ struct page *page;
++ int err = -ENOENT;
++
++ de = f2fs_find_entry(dir, &dentry->d_name, &page);
++ if (!de)
++ goto fail;
++
++ err = check_orphan_space(sbi);
++ if (err) {
++ kunmap(page);
++ f2fs_put_page(page, 0);
++ goto fail;
++ }
++
++ f2fs_delete_entry(de, page, inode);
++
++ /* In order to evict this inode, we set it dirty */
++ mark_inode_dirty(inode);
++ f2fs_balance_fs(sbi);
++fail:
++ return err;
++}
++
++static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
++ const char *symname)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ unsigned symlen = strlen(symname) + 1;
++ int err;
++
++ inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++
++ inode->i_op = &f2fs_symlink_inode_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ err = page_symlink(inode, symname, symlen);
++ alloc_nid_done(sbi, inode->i_ino);
++
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++
++ return err;
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, inode->i_ino);
++ return err;
++}
++
++static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ struct inode *inode;
++ int err;
++
++ inode = f2fs_new_inode(dir, S_IFDIR | mode);
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ return err;
++
++ inode->i_op = &f2fs_dir_inode_operations;
++ inode->i_fop = &f2fs_dir_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS | __GFP_ZERO);
++
++ set_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out_fail;
++
++ alloc_nid_done(sbi, inode->i_ino);
++
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++
++out_fail:
++ clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, inode->i_ino);
++ return err;
++}
++
++static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ struct inode *inode = dentry->d_inode;
++ if (f2fs_empty_dir(inode))
++ return f2fs_unlink(dir, dentry);
++ return -ENOTEMPTY;
++}
++
++static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
++ umode_t mode, dev_t rdev)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ int err = 0;
++
++ if (!new_valid_dev(rdev))
++ return -EINVAL;
++
++ inode = f2fs_new_inode(dir, mode);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++
++ init_special_inode(inode, inode->i_mode, rdev);
++ inode->i_op = &f2fs_special_inode_operations;
++
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ alloc_nid_done(sbi, inode->i_ino);
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++
++ return 0;
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, inode->i_ino);
++ return err;
++}
++
++static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry)
++{
++ struct super_block *sb = old_dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *old_inode = old_dentry->d_inode;
++ struct inode *new_inode = new_dentry->d_inode;
++ struct page *old_dir_page;
++ struct page *old_page;
++ struct f2fs_dir_entry *old_dir_entry = NULL;
++ struct f2fs_dir_entry *old_entry;
++ struct f2fs_dir_entry *new_entry;
++ int err = -ENOENT;
++
++ old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
++ if (!old_entry)
++ goto out;
++
++ if (S_ISDIR(old_inode->i_mode)) {
++ err = -EIO;
++ old_dir_entry = f2fs_parent_dir(old_inode, &old_dir_page);
++ if (!old_dir_entry)
++ goto out_old;
++ }
++
++ mutex_lock_op(sbi, RENAME);
++
++ if (new_inode) {
++ struct page *new_page;
++
++ err = -ENOTEMPTY;
++ if (old_dir_entry && !f2fs_empty_dir(new_inode))
++ goto out_dir;
++
++ err = -ENOENT;
++ new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name,
++ &new_page);
++ if (!new_entry)
++ goto out_dir;
++
++ f2fs_set_link(new_dir, new_entry, new_page, old_inode);
++
++ new_inode->i_ctime = CURRENT_TIME;
++ if (old_dir_entry)
++ drop_nlink(new_inode);
++ drop_nlink(new_inode);
++ if (!new_inode->i_nlink)
++ add_orphan_inode(sbi, new_inode->i_ino);
++ f2fs_write_inode(new_inode, NULL);
++ } else {
++ err = f2fs_add_link(new_dentry, old_inode);
++ if (err)
++ goto out_dir;
++
++ if (old_dir_entry) {
++ inc_nlink(new_dir);
++ f2fs_write_inode(new_dir, NULL);
++ }
++ }
++
++ old_inode->i_ctime = CURRENT_TIME;
++ set_inode_flag(F2FS_I(old_inode), FI_NEED_CP);
++ mark_inode_dirty(old_inode);
++
++ f2fs_delete_entry(old_entry, old_page, NULL);
++
++ if (old_dir_entry) {
++ if (old_dir != new_dir) {
++ f2fs_set_link(old_inode, old_dir_entry,
++ old_dir_page, new_dir);
++ } else {
++ kunmap(old_dir_page);
++ f2fs_put_page(old_dir_page, 0);
++ }
++ drop_nlink(old_dir);
++ f2fs_write_inode(old_dir, NULL);
++ }
++
++ mutex_unlock_op(sbi, RENAME);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++
++out_dir:
++ if (old_dir_entry) {
++ kunmap(old_dir_page);
++ f2fs_put_page(old_dir_page, 0);
++ }
++ mutex_unlock_op(sbi, RENAME);
++out_old:
++ kunmap(old_page);
++ f2fs_put_page(old_page, 0);
++out:
++ return err;
++}
++
++const struct inode_operations f2fs_dir_inode_operations = {
++ .create = f2fs_create,
++ .lookup = f2fs_lookup,
++ .link = f2fs_link,
++ .unlink = f2fs_unlink,
++ .symlink = f2fs_symlink,
++ .mkdir = f2fs_mkdir,
++ .rmdir = f2fs_rmdir,
++ .mknod = f2fs_mknod,
++ .rename = f2fs_rename,
++ .setattr = f2fs_setattr,
++ .get_acl = f2fs_get_acl,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
++
++const struct inode_operations f2fs_symlink_inode_operations = {
++ .readlink = generic_readlink,
++ .follow_link = page_follow_link_light,
++ .put_link = page_put_link,
++ .setattr = f2fs_setattr,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
++
++const struct inode_operations f2fs_special_inode_operations = {
++ .setattr = f2fs_setattr,
++ .get_acl = f2fs_get_acl,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
diff --git a/patches/linux-3.7-rc6/0109-f2fs-add-core-directory-operations.patch b/patches/linux-3.7-rc6/0109-f2fs-add-core-directory-operations.patch
new file mode 100644
index 0000000..ac2824b
--- /dev/null
+++ b/patches/linux-3.7-rc6/0109-f2fs-add-core-directory-operations.patch
@@ -0,0 +1,782 @@
+From 39207d517eb7f9f43205c6fc2f0c3a9a6d398f97 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:31:34 +0000
+Subject: [PATCH] f2fs: add core directory operations
+
+This adds core functions to find, add, delete, and link dentries.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/dir.c | 657 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/hash.c | 98 +++++++++
+ 2 files changed, 755 insertions(+)
+ create mode 100644 fs/f2fs/dir.c
+ create mode 100644 fs/f2fs/hash.c
+
+diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
+new file mode 100644
+index 0000000..f3de333
+--- /dev/null
++++ b/fs/f2fs/dir.c
+@@ -0,0 +1,657 @@
++/**
++ * fs/f2fs/dir.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "acl.h"
++
++static unsigned long dir_blocks(struct inode *inode)
++{
++ return ((unsigned long long) (i_size_read(inode) + PAGE_CACHE_SIZE - 1))
++ >> PAGE_CACHE_SHIFT;
++}
++
++static unsigned int dir_buckets(unsigned int level)
++{
++ if (level < MAX_DIR_HASH_DEPTH / 2)
++ return 1 << level;
++ else
++ return 1 << ((MAX_DIR_HASH_DEPTH / 2) - 1);
++}
++
++static unsigned int bucket_blocks(unsigned int level)
++{
++ if (level < MAX_DIR_HASH_DEPTH / 2)
++ return 2;
++ else
++ return 4;
++}
++
++static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
++ [F2FS_FT_UNKNOWN] = DT_UNKNOWN,
++ [F2FS_FT_REG_FILE] = DT_REG,
++ [F2FS_FT_DIR] = DT_DIR,
++ [F2FS_FT_CHRDEV] = DT_CHR,
++ [F2FS_FT_BLKDEV] = DT_BLK,
++ [F2FS_FT_FIFO] = DT_FIFO,
++ [F2FS_FT_SOCK] = DT_SOCK,
++ [F2FS_FT_SYMLINK] = DT_LNK,
++};
++
++#define S_SHIFT 12
++static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
++ [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE,
++ [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR,
++ [S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV,
++ [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV,
++ [S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO,
++ [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK,
++ [S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK,
++};
++
++static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
++{
++ mode_t mode = inode->i_mode;
++ de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
++}
++
++static unsigned long dir_block_index(unsigned int level, unsigned int idx)
++{
++ unsigned long i;
++ unsigned long bidx = 0;
++
++ for (i = 0; i < level; i++)
++ bidx += dir_buckets(i) * bucket_blocks(i);
++ bidx += idx * bucket_blocks(level);
++ return bidx;
++}
++
++static bool early_match_name(const char *name, int namelen,
++ f2fs_hash_t namehash, struct f2fs_dir_entry *de)
++{
++ if (le16_to_cpu(de->name_len) != namelen)
++ return false;
++
++ if (le32_to_cpu(de->hash_code) != namehash)
++ return false;
++
++ return true;
++}
++
++static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
++ const char *name, int namelen, int *max_slots,
++ f2fs_hash_t namehash, struct page **res_page)
++{
++ struct f2fs_dir_entry *de;
++ unsigned long bit_pos, end_pos, next_pos;
++ struct f2fs_dentry_block *dentry_blk = kmap(dentry_page);
++ int slots;
++
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK, 0);
++ while (bit_pos < NR_DENTRY_IN_BLOCK) {
++ de = &dentry_blk->dentry[bit_pos];
++ slots = (le16_to_cpu(de->name_len) + F2FS_NAME_LEN - 1) /
++ F2FS_NAME_LEN;
++
++ if (early_match_name(name, namelen, namehash, de)) {
++ if (!memcmp(dentry_blk->filename[bit_pos],
++ name, namelen)) {
++ *res_page = dentry_page;
++ goto found;
++ }
++ }
++ next_pos = bit_pos + slots;
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK, next_pos);
++ if (bit_pos >= NR_DENTRY_IN_BLOCK)
++ end_pos = NR_DENTRY_IN_BLOCK;
++ else
++ end_pos = bit_pos;
++ if (*max_slots < end_pos - next_pos)
++ *max_slots = end_pos - next_pos;
++ }
++
++ de = NULL;
++ kunmap(dentry_page);
++found:
++ return de;
++}
++
++static struct f2fs_dir_entry *find_in_level(struct inode *dir,
++ unsigned int level, const char *name, int namelen,
++ f2fs_hash_t namehash, struct page **res_page)
++{
++ int s = (namelen + F2FS_NAME_LEN - 1) / F2FS_NAME_LEN;
++ unsigned int nbucket, nblock;
++ unsigned int bidx, end_block;
++ struct page *dentry_page;
++ struct f2fs_dir_entry *de = NULL;
++ bool room = false;
++ int max_slots = 0;
++
++ BUG_ON(level > MAX_DIR_HASH_DEPTH);
++
++ nbucket = dir_buckets(level);
++ nblock = bucket_blocks(level);
++
++ bidx = dir_block_index(level, namehash % nbucket);
++ end_block = bidx + nblock;
++
++ for (; bidx < end_block; bidx++) {
++ /* no need to allocate new dentry pages to all the indices */
++ dentry_page = find_data_page(dir, bidx);
++ if (IS_ERR(dentry_page)) {
++ room = true;
++ continue;
++ }
++
++ de = find_in_block(dentry_page, name, namelen,
++ &max_slots, namehash, res_page);
++ if (de)
++ break;
++
++ if (max_slots >= s)
++ room = true;
++ f2fs_put_page(dentry_page, 0);
++ }
++
++ if (!de && room && F2FS_I(dir)->chash != namehash) {
++ F2FS_I(dir)->chash = namehash;
++ F2FS_I(dir)->clevel = level;
++ }
++
++ return de;
++}
++
++/*
++ * Find an entry in the specified directory with the wanted name.
++ * It returns the page where the entry was found (as a parameter - res_page),
++ * and the entry itself. Page is returned mapped and unlocked.
++ * Entry is guaranteed to be valid.
++ */
++struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
++ struct qstr *child, struct page **res_page)
++{
++ const char *name = child->name;
++ int namelen = child->len;
++ unsigned long npages = dir_blocks(dir);
++ struct f2fs_dir_entry *de = NULL;
++ f2fs_hash_t name_hash;
++ unsigned int max_depth;
++ unsigned int level;
++
++ if (npages == 0)
++ return NULL;
++
++ *res_page = NULL;
++
++ name_hash = f2fs_dentry_hash(name, namelen);
++ max_depth = F2FS_I(dir)->current_depth;
++
++ for (level = 0; level < max_depth; level++) {
++ de = find_in_level(dir, level, name,
++ namelen, name_hash, res_page);
++ if (de)
++ break;
++ }
++ if (!de && F2FS_I(dir)->chash != name_hash) {
++ F2FS_I(dir)->chash = name_hash;
++ F2FS_I(dir)->clevel = level - 1;
++ }
++ return de;
++}
++
++struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
++{
++ struct page *page = NULL;
++ struct f2fs_dir_entry *de = NULL;
++ struct f2fs_dentry_block *dentry_blk = NULL;
++
++ page = get_lock_data_page(dir, 0);
++ if (IS_ERR(page))
++ return NULL;
++
++ dentry_blk = kmap(page);
++ de = &dentry_blk->dentry[1];
++ *p = page;
++ unlock_page(page);
++ return de;
++}
++
++void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
++ struct page *page, struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++
++ mutex_lock_op(sbi, DENTRY_OPS);
++ lock_page(page);
++ wait_on_page_writeback(page);
++ de->ino = cpu_to_le32(inode->i_ino);
++ set_de_type(de, inode);
++ kunmap(page);
++ set_page_dirty(page);
++ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
++ mark_inode_dirty(dir);
++ f2fs_put_page(page, 1);
++ mutex_unlock_op(sbi, DENTRY_OPS);
++}
++
++void init_dent_inode(struct dentry *dentry, struct page *ipage)
++{
++ struct inode *dir = dentry->d_parent->d_inode;
++ struct f2fs_node *rn;
++
++ if (IS_ERR(ipage))
++ return;
++
++ wait_on_page_writeback(ipage);
++
++ /* copy dentry info. to this inode page */
++ rn = (struct f2fs_node *)page_address(ipage);
++ rn->i.i_pino = cpu_to_le32(dir->i_ino);
++ rn->i.i_namelen = cpu_to_le32(dentry->d_name.len);
++ memcpy(rn->i.i_name, dentry->d_name.name, dentry->d_name.len);
++ set_page_dirty(ipage);
++}
++
++static int init_inode_metadata(struct inode *inode, struct dentry *dentry)
++{
++ struct inode *dir = dentry->d_parent->d_inode;
++
++ if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
++ int err;
++ err = new_inode_page(inode, dentry);
++ if (err)
++ return err;
++
++ if (S_ISDIR(inode->i_mode)) {
++ err = f2fs_make_empty(inode, dir);
++ if (err) {
++ remove_inode_page(inode);
++ return err;
++ }
++ }
++
++ err = f2fs_init_acl(inode, dir);
++ if (err) {
++ remove_inode_page(inode);
++ return err;
++ }
++ } else {
++ struct page *ipage;
++ ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
++ if (IS_ERR(ipage))
++ return PTR_ERR(ipage);
++ init_dent_inode(dentry, ipage);
++ f2fs_put_page(ipage, 1);
++ }
++ if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) {
++ inc_nlink(inode);
++ f2fs_write_inode(inode, NULL);
++ }
++ return 0;
++}
++
++static void update_parent_metadata(struct inode *dir, struct inode *inode,
++ unsigned int current_depth)
++{
++ bool need_dir_update = false;
++
++ if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
++ if (S_ISDIR(inode->i_mode)) {
++ inc_nlink(dir);
++ need_dir_update = true;
++ }
++ clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
++ }
++ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
++ if (F2FS_I(dir)->current_depth != current_depth) {
++ F2FS_I(dir)->current_depth = current_depth;
++ need_dir_update = true;
++ }
++
++ if (need_dir_update)
++ f2fs_write_inode(dir, NULL);
++ else
++ mark_inode_dirty(dir);
++
++ if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK))
++ clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
++}
++
++static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots)
++{
++ int bit_start = 0;
++ int zero_start, zero_end;
++next:
++ zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ bit_start);
++ if (zero_start >= NR_DENTRY_IN_BLOCK)
++ return NR_DENTRY_IN_BLOCK;
++
++ zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ zero_start);
++ if (zero_end - zero_start >= slots)
++ return zero_start;
++
++ bit_start = zero_end + 1;
++
++ if (zero_end + 1 >= NR_DENTRY_IN_BLOCK)
++ return NR_DENTRY_IN_BLOCK;
++ goto next;
++}
++
++int f2fs_add_link(struct dentry *dentry, struct inode *inode)
++{
++ unsigned int bit_pos;
++ unsigned int level;
++ unsigned int current_depth;
++ unsigned long bidx, block;
++ f2fs_hash_t dentry_hash;
++ struct f2fs_dir_entry *de;
++ unsigned int nbucket, nblock;
++ struct inode *dir = dentry->d_parent->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ const char *name = dentry->d_name.name;
++ int namelen = dentry->d_name.len;
++ struct page *dentry_page = NULL;
++ struct f2fs_dentry_block *dentry_blk = NULL;
++ int slots = (namelen + F2FS_NAME_LEN - 1) / F2FS_NAME_LEN;
++ int err = 0;
++ int i;
++
++ dentry_hash = f2fs_dentry_hash(name, dentry->d_name.len);
++ level = 0;
++ current_depth = F2FS_I(dir)->current_depth;
++ if (F2FS_I(dir)->chash == dentry_hash) {
++ level = F2FS_I(dir)->clevel;
++ F2FS_I(dir)->chash = 0;
++ }
++
++start:
++ if (current_depth == MAX_DIR_HASH_DEPTH)
++ return -ENOSPC;
++
++ /* Increase the depth, if required */
++ if (level == current_depth)
++ ++current_depth;
++
++ nbucket = dir_buckets(level);
++ nblock = bucket_blocks(level);
++
++ bidx = dir_block_index(level, (dentry_hash % nbucket));
++
++ for (block = bidx; block <= (bidx + nblock - 1); block++) {
++ mutex_lock_op(sbi, DENTRY_OPS);
++ dentry_page = get_new_data_page(dir, block, true);
++ if (IS_ERR(dentry_page)) {
++ mutex_unlock_op(sbi, DENTRY_OPS);
++ return PTR_ERR(dentry_page);
++ }
++
++ dentry_blk = kmap(dentry_page);
++ bit_pos = room_for_filename(dentry_blk, slots);
++ if (bit_pos < NR_DENTRY_IN_BLOCK)
++ goto add_dentry;
++
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ mutex_unlock_op(sbi, DENTRY_OPS);
++ }
++
++ /* Move to next level to find the empty slot for new dentry */
++ ++level;
++ goto start;
++add_dentry:
++ err = init_inode_metadata(inode, dentry);
++ if (err)
++ goto fail;
++
++ wait_on_page_writeback(dentry_page);
++
++ de = &dentry_blk->dentry[bit_pos];
++ de->hash_code = cpu_to_le32(dentry_hash);
++ de->name_len = cpu_to_le16(namelen);
++ memcpy(dentry_blk->filename[bit_pos], name, namelen);
++ de->ino = cpu_to_le32(inode->i_ino);
++ set_de_type(de, inode);
++ for (i = 0; i < slots; i++)
++ test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
++ set_page_dirty(dentry_page);
++ update_parent_metadata(dir, inode, current_depth);
++fail:
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ mutex_unlock_op(sbi, DENTRY_OPS);
++ return err;
++}
++
++/**
++ * It only removes the dentry from the dentry page,corresponding name
++ * entry in name page does not need to be touched during deletion.
++ */
++void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
++ struct inode *inode)
++{
++ struct f2fs_dentry_block *dentry_blk;
++ unsigned int bit_pos;
++ struct address_space *mapping = page->mapping;
++ struct inode *dir = mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ int slots = (le16_to_cpu(dentry->name_len) + F2FS_NAME_LEN - 1) /
++ F2FS_NAME_LEN;
++ void *kaddr = page_address(page);
++ int i;
++
++ mutex_lock_op(sbi, DENTRY_OPS);
++
++ lock_page(page);
++ wait_on_page_writeback(page);
++
++ dentry_blk = (struct f2fs_dentry_block *)kaddr;
++ bit_pos = dentry - (struct f2fs_dir_entry *)dentry_blk->dentry;
++ for (i = 0; i < slots; i++)
++ test_and_clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
++
++ /* Let's check and deallocate this dentry page */
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ 0);
++ kunmap(page); /* kunmap - pair of f2fs_find_entry */
++ set_page_dirty(page);
++
++ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++
++ if (inode && S_ISDIR(inode->i_mode)) {
++ drop_nlink(dir);
++ f2fs_write_inode(dir, NULL);
++ } else {
++ mark_inode_dirty(dir);
++ }
++
++ if (inode) {
++ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ drop_nlink(inode);
++ if (S_ISDIR(inode->i_mode)) {
++ drop_nlink(inode);
++ i_size_write(inode, 0);
++ }
++ f2fs_write_inode(inode, NULL);
++ if (inode->i_nlink == 0)
++ add_orphan_inode(sbi, inode->i_ino);
++ }
++
++ if (bit_pos == NR_DENTRY_IN_BLOCK) {
++ loff_t page_offset;
++ truncate_hole(dir, page->index, page->index + 1);
++ clear_page_dirty_for_io(page);
++ ClearPageUptodate(page);
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(dir);
++ page_offset = page->index << PAGE_CACHE_SHIFT;
++ f2fs_put_page(page, 1);
++ } else {
++ f2fs_put_page(page, 1);
++ }
++ mutex_unlock_op(sbi, DENTRY_OPS);
++}
++
++int f2fs_make_empty(struct inode *inode, struct inode *parent)
++{
++ struct page *dentry_page;
++ struct f2fs_dentry_block *dentry_blk;
++ struct f2fs_dir_entry *de;
++ void *kaddr;
++
++ dentry_page = get_new_data_page(inode, 0, true);
++ if (IS_ERR(dentry_page))
++ return PTR_ERR(dentry_page);
++
++ kaddr = kmap_atomic(dentry_page);
++ dentry_blk = (struct f2fs_dentry_block *)kaddr;
++
++ de = &dentry_blk->dentry[0];
++ de->name_len = cpu_to_le16(1);
++ de->hash_code = 0;
++ de->ino = cpu_to_le32(inode->i_ino);
++ memcpy(dentry_blk->filename[0], ".", 1);
++ set_de_type(de, inode);
++
++ de = &dentry_blk->dentry[1];
++ de->hash_code = 0;
++ de->name_len = cpu_to_le16(2);
++ de->ino = cpu_to_le32(parent->i_ino);
++ memcpy(dentry_blk->filename[1], "..", 2);
++ set_de_type(de, inode);
++
++ test_and_set_bit_le(0, &dentry_blk->dentry_bitmap);
++ test_and_set_bit_le(1, &dentry_blk->dentry_bitmap);
++ kunmap_atomic(kaddr);
++
++ set_page_dirty(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ return 0;
++}
++
++bool f2fs_empty_dir(struct inode *dir)
++{
++ unsigned long bidx;
++ struct page *dentry_page;
++ unsigned int bit_pos;
++ struct f2fs_dentry_block *dentry_blk;
++ unsigned long nblock = dir_blocks(dir);
++
++ for (bidx = 0; bidx < nblock; bidx++) {
++ void *kaddr;
++ dentry_page = get_lock_data_page(dir, bidx);
++ if (IS_ERR(dentry_page)) {
++ if (PTR_ERR(dentry_page) == -ENOENT)
++ continue;
++ else
++ return false;
++ }
++
++ kaddr = kmap_atomic(dentry_page);
++ dentry_blk = (struct f2fs_dentry_block *)kaddr;
++ if (bidx == 0)
++ bit_pos = 2;
++ else
++ bit_pos = 0;
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ bit_pos);
++ kunmap_atomic(kaddr);
++
++ f2fs_put_page(dentry_page, 1);
++
++ if (bit_pos < NR_DENTRY_IN_BLOCK)
++ return false;
++ }
++ return true;
++}
++
++static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ unsigned long pos = file->f_pos;
++ struct inode *inode = file->f_dentry->d_inode;
++ unsigned long npages = dir_blocks(inode);
++ unsigned char *types = NULL;
++ unsigned int bit_pos = 0, start_bit_pos = 0;
++ int over = 0;
++ struct f2fs_dentry_block *dentry_blk = NULL;
++ struct f2fs_dir_entry *de = NULL;
++ struct page *dentry_page = NULL;
++ unsigned int n = 0;
++ unsigned char *ptr = NULL;
++ unsigned char d_type = DT_UNKNOWN;
++ int slots;
++
++ types = f2fs_filetype_table;
++ bit_pos = (pos % NR_DENTRY_IN_BLOCK);
++ n = (pos / NR_DENTRY_IN_BLOCK);
++
++ for ( ; n < npages; n++) {
++ dentry_page = get_lock_data_page(inode, n);
++ if (IS_ERR(dentry_page))
++ continue;
++
++ start_bit_pos = bit_pos;
++ dentry_blk = kmap(dentry_page);
++ while (bit_pos < NR_DENTRY_IN_BLOCK) {
++ d_type = DT_UNKNOWN;
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ bit_pos);
++ if (bit_pos >= NR_DENTRY_IN_BLOCK)
++ break;
++
++ de = &dentry_blk->dentry[bit_pos];
++ if (types && de->file_type < F2FS_FT_MAX)
++ d_type = types[de->file_type];
++
++ ptr = dentry_blk->filename[bit_pos];
++ over = filldir(dirent,
++ dentry_blk->filename[bit_pos],
++ le16_to_cpu(de->name_len),
++ (n * NR_DENTRY_IN_BLOCK) + bit_pos,
++ le32_to_cpu(de->ino), d_type);
++ if (over) {
++ file->f_pos += bit_pos - start_bit_pos;
++ goto success;
++ }
++ slots = (le16_to_cpu(de->name_len) + F2FS_NAME_LEN - 1)
++ / F2FS_NAME_LEN;
++ bit_pos += slots;
++ }
++ bit_pos = 0;
++ file->f_pos = (n + 1) * NR_DENTRY_IN_BLOCK;
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ dentry_page = NULL;
++ }
++success:
++ if (dentry_page && !IS_ERR(dentry_page)) {
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ }
++
++ return 0;
++}
++
++const struct file_operations f2fs_dir_operations = {
++ .read = generic_read_dir,
++ .readdir = f2fs_readdir,
++ .fsync = f2fs_sync_file,
++ .unlocked_ioctl = f2fs_ioctl,
++};
+diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c
+new file mode 100644
+index 0000000..098a196
+--- /dev/null
++++ b/fs/f2fs/hash.c
+@@ -0,0 +1,98 @@
++/**
++ * fs/f2fs/hash.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext3/hash.c
++ *
++ * Copyright (C) 2002 by Theodore Ts'o
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/cryptohash.h>
++#include <linux/pagemap.h>
++
++#include "f2fs.h"
++
++/*
++ * Hashing code copied from ext3
++ */
++#define DELTA 0x9E3779B9
++
++static void TEA_transform(unsigned int buf[4], unsigned int const in[])
++{
++ __u32 sum = 0;
++ __u32 b0 = buf[0], b1 = buf[1];
++ __u32 a = in[0], b = in[1], c = in[2], d = in[3];
++ int n = 16;
++
++ do {
++ sum += DELTA;
++ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
++ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
++ } while (--n);
++
++ buf[0] += b0;
++ buf[1] += b1;
++}
++
++static void str2hashbuf(const char *msg, int len, unsigned int *buf, int num)
++{
++ unsigned pad, val;
++ int i;
++
++ pad = (__u32)len | ((__u32)len << 8);
++ pad |= pad << 16;
++
++ val = pad;
++ if (len > num * 4)
++ len = num * 4;
++ for (i = 0; i < len; i++) {
++ if ((i % 4) == 0)
++ val = pad;
++ val = msg[i] + (val << 8);
++ if ((i % 4) == 3) {
++ *buf++ = val;
++ val = pad;
++ num--;
++ }
++ }
++ if (--num >= 0)
++ *buf++ = val;
++ while (--num >= 0)
++ *buf++ = pad;
++}
++
++f2fs_hash_t f2fs_dentry_hash(const char *name, int len)
++{
++ __u32 hash, minor_hash;
++ f2fs_hash_t f2fs_hash;
++ const char *p;
++ __u32 in[8], buf[4];
++
++ /* Initialize the default seed for the hash checksum functions */
++ buf[0] = 0x67452301;
++ buf[1] = 0xefcdab89;
++ buf[2] = 0x98badcfe;
++ buf[3] = 0x10325476;
++
++ p = name;
++ while (len > 0) {
++ str2hashbuf(p, len, in, 4);
++ TEA_transform(buf, in);
++ len -= 16;
++ p += 16;
++ }
++ hash = buf[0];
++ minor_hash = buf[1];
++
++ f2fs_hash = hash;
++ f2fs_hash &= ~F2FS_HASH_COL_BIT;
++ return f2fs_hash;
++}
diff --git a/patches/linux-3.7-rc6/0110-f2fs-add-xattr-and-acl-functionalities.patch b/patches/linux-3.7-rc6/0110-f2fs-add-xattr-and-acl-functionalities.patch
new file mode 100644
index 0000000..eead241
--- /dev/null
+++ b/patches/linux-3.7-rc6/0110-f2fs-add-xattr-and-acl-functionalities.patch
@@ -0,0 +1,1102 @@
+From 8e21f5b0090aea281121c14542c55c7043e5168b Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:31:46 +0000
+Subject: [PATCH] f2fs: add xattr and acl functionalities
+
+This implements xattr and acl functionalities.
+
+- F2FS uses a node page to contain use extended attributes.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/acl.c | 465 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/acl.h | 57 +++++++
+ fs/f2fs/xattr.c | 389 ++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/xattr.h | 145 +++++++++++++++++
+ 4 files changed, 1056 insertions(+)
+ create mode 100644 fs/f2fs/acl.c
+ create mode 100644 fs/f2fs/acl.h
+ create mode 100644 fs/f2fs/xattr.c
+ create mode 100644 fs/f2fs/xattr.h
+
+diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
+new file mode 100644
+index 0000000..dff2a2b
+--- /dev/null
++++ b/fs/f2fs/acl.c
+@@ -0,0 +1,465 @@
++/**
++ * fs/f2fs/acl.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/acl.c
++ *
++ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "xattr.h"
++#include "acl.h"
++
++#define get_inode_mode(i) ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
++ (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
++
++static inline size_t f2fs_acl_size(int count)
++{
++ if (count <= 4) {
++ return sizeof(struct f2fs_acl_header) +
++ count * sizeof(struct f2fs_acl_entry_short);
++ } else {
++ return sizeof(struct f2fs_acl_header) +
++ 4 * sizeof(struct f2fs_acl_entry_short) +
++ (count - 4) * sizeof(struct f2fs_acl_entry);
++ }
++}
++
++static inline int f2fs_acl_count(size_t size)
++{
++ ssize_t s;
++ size -= sizeof(struct f2fs_acl_header);
++ s = size - 4 * sizeof(struct f2fs_acl_entry_short);
++ if (s < 0) {
++ if (size % sizeof(struct f2fs_acl_entry_short))
++ return -1;
++ return size / sizeof(struct f2fs_acl_entry_short);
++ } else {
++ if (s % sizeof(struct f2fs_acl_entry))
++ return -1;
++ return s / sizeof(struct f2fs_acl_entry) + 4;
++ }
++}
++
++static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
++{
++ int i, count;
++ struct posix_acl *acl;
++ struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
++ struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
++ const char *end = value + size;
++
++ if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION))
++ return ERR_PTR(-EINVAL);
++
++ count = f2fs_acl_count(size);
++ if (count < 0)
++ return ERR_PTR(-EINVAL);
++ if (count == 0)
++ return NULL;
++
++ acl = posix_acl_alloc(count, GFP_KERNEL);
++ if (!acl)
++ return ERR_PTR(-ENOMEM);
++
++ for (i = 0; i < count; i++) {
++
++ if ((char *)entry > end)
++ goto fail;
++
++ acl->a_entries[i].e_tag = le16_to_cpu(entry->e_tag);
++ acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm);
++
++ switch (acl->a_entries[i].e_tag) {
++ case ACL_USER_OBJ:
++ case ACL_GROUP_OBJ:
++ case ACL_MASK:
++ case ACL_OTHER:
++ acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry_short));
++ break;
++
++ case ACL_USER:
++ acl->a_entries[i].e_uid =
++ make_kuid(&init_user_ns,
++ le32_to_cpu(entry->e_id));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ case ACL_GROUP:
++ acl->a_entries[i].e_gid =
++ make_kgid(&init_user_ns,
++ le32_to_cpu(entry->e_id));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ default:
++ goto fail;
++ }
++ }
++ if ((char *)entry != end)
++ goto fail;
++ return acl;
++fail:
++ posix_acl_release(acl);
++ return ERR_PTR(-EINVAL);
++}
++
++static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size)
++{
++ struct f2fs_acl_header *f2fs_acl;
++ struct f2fs_acl_entry *entry;
++ int i;
++
++ f2fs_acl = kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count *
++ sizeof(struct f2fs_acl_entry), GFP_KERNEL);
++ if (!f2fs_acl)
++ return ERR_PTR(-ENOMEM);
++
++ f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION);
++ entry = (struct f2fs_acl_entry *)(f2fs_acl + 1);
++
++ for (i = 0; i < acl->a_count; i++) {
++
++ entry->e_tag = cpu_to_le16(acl->a_entries[i].e_tag);
++ entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm);
++
++ switch (acl->a_entries[i].e_tag) {
++ case ACL_USER:
++ entry->e_id = cpu_to_le32(
++ from_kuid(&init_user_ns,
++ acl->a_entries[i].e_uid));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ case ACL_GROUP:
++ entry->e_id = cpu_to_le32(
++ from_kgid(&init_user_ns,
++ acl->a_entries[i].e_gid));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ case ACL_USER_OBJ:
++ case ACL_GROUP_OBJ:
++ case ACL_MASK:
++ case ACL_OTHER:
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry_short));
++ break;
++ default:
++ goto fail;
++ }
++ }
++ *size = f2fs_acl_size(acl->a_count);
++ return (void *)f2fs_acl;
++
++fail:
++ kfree(f2fs_acl);
++ return ERR_PTR(-EINVAL);
++}
++
++struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
++ void *value = NULL;
++ struct posix_acl *acl;
++ int retval;
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return NULL;
++
++ acl = get_cached_acl(inode, type);
++ if (acl != ACL_NOT_CACHED)
++ return acl;
++
++ if (type == ACL_TYPE_ACCESS)
++ name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
++
++ retval = f2fs_getxattr(inode, name_index, "", NULL, 0);
++ if (retval > 0) {
++ value = kmalloc(retval, GFP_KERNEL);
++ if (!value)
++ return ERR_PTR(-ENOMEM);
++ retval = f2fs_getxattr(inode, name_index, "", value, retval);
++ }
++
++ if (retval < 0) {
++ if (retval == -ENODATA)
++ acl = NULL;
++ else
++ acl = ERR_PTR(retval);
++ } else {
++ acl = f2fs_acl_from_disk(value, retval);
++ }
++ kfree(value);
++ if (!IS_ERR(acl))
++ set_cached_acl(inode, type, acl);
++
++ return acl;
++}
++
++static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ int name_index;
++ void *value = NULL;
++ size_t size = 0;
++ int error;
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return 0;
++ if (S_ISLNK(inode->i_mode))
++ return -EOPNOTSUPP;
++
++ switch (type) {
++ case ACL_TYPE_ACCESS:
++ name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
++ if (acl) {
++ error = posix_acl_equiv_mode(acl, &inode->i_mode);
++ if (error < 0)
++ return error;
++ set_acl_inode(fi, inode->i_mode);
++ if (error == 0)
++ acl = NULL;
++ }
++ break;
++
++ case ACL_TYPE_DEFAULT:
++ name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
++ if (!S_ISDIR(inode->i_mode))
++ return acl ? -EACCES : 0;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ if (acl) {
++ value = f2fs_acl_to_disk(acl, &size);
++ if (IS_ERR(value)) {
++ cond_clear_inode_flag(fi, FI_ACL_MODE);
++ return (int)PTR_ERR(value);
++ }
++ }
++
++ error = f2fs_setxattr(inode, name_index, "", value, size);
++
++ kfree(value);
++ if (!error)
++ set_cached_acl(inode, type, acl);
++
++ cond_clear_inode_flag(fi, FI_ACL_MODE);
++ return error;
++}
++
++int f2fs_init_acl(struct inode *inode, struct inode *dir)
++{
++ struct posix_acl *acl = NULL;
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ int error = 0;
++
++ if (!S_ISLNK(inode->i_mode)) {
++ if (test_opt(sbi, POSIX_ACL)) {
++ acl = f2fs_get_acl(dir, ACL_TYPE_DEFAULT);
++ if (IS_ERR(acl))
++ return PTR_ERR(acl);
++ }
++ if (!acl)
++ inode->i_mode &= ~current_umask();
++ }
++
++ if (test_opt(sbi, POSIX_ACL) && acl) {
++
++ if (S_ISDIR(inode->i_mode)) {
++ error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
++ if (error)
++ goto cleanup;
++ }
++ error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
++ if (error < 0)
++ return error;
++ if (error > 0)
++ error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
++ }
++cleanup:
++ posix_acl_release(acl);
++ return error;
++}
++
++int f2fs_acl_chmod(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct posix_acl *acl;
++ int error;
++ mode_t mode = get_inode_mode(inode);
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return 0;
++ if (S_ISLNK(mode))
++ return -EOPNOTSUPP;
++
++ acl = f2fs_get_acl(inode, ACL_TYPE_ACCESS);
++ if (IS_ERR(acl) || !acl)
++ return PTR_ERR(acl);
++
++ error = posix_acl_chmod(&acl, GFP_KERNEL, mode);
++ if (error)
++ return error;
++ error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
++ posix_acl_release(acl);
++ return error;
++}
++
++static size_t f2fs_xattr_list_acl(struct dentry *dentry, char *list,
++ size_t list_size, const char *name, size_t name_len, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ const char *xname = POSIX_ACL_XATTR_DEFAULT;
++ size_t size;
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return 0;
++
++ if (type == ACL_TYPE_ACCESS)
++ xname = POSIX_ACL_XATTR_ACCESS;
++
++ size = strlen(xname) + 1;
++ if (list && size <= list_size)
++ memcpy(list, xname, size);
++ return size;
++}
++
++static int f2fs_xattr_get_acl(struct dentry *dentry, const char *name,
++ void *buffer, size_t size, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ struct posix_acl *acl;
++ int error;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++ if (!test_opt(sbi, POSIX_ACL))
++ return -EOPNOTSUPP;
++
++ acl = f2fs_get_acl(dentry->d_inode, type);
++ if (IS_ERR(acl))
++ return PTR_ERR(acl);
++ if (!acl)
++ return -ENODATA;
++ error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
++ posix_acl_release(acl);
++
++ return error;
++}
++
++static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ struct inode *inode = dentry->d_inode;
++ struct posix_acl *acl = NULL;
++ int error;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++ if (!test_opt(sbi, POSIX_ACL))
++ return -EOPNOTSUPP;
++ if (!inode_owner_or_capable(inode))
++ return -EPERM;
++
++ if (value) {
++ acl = posix_acl_from_xattr(&init_user_ns, value, size);
++ if (IS_ERR(acl))
++ return PTR_ERR(acl);
++ if (acl) {
++ error = posix_acl_valid(acl);
++ if (error)
++ goto release_and_out;
++ }
++ } else {
++ acl = NULL;
++ }
++
++ error = f2fs_set_acl(inode, type, acl);
++
++release_and_out:
++ posix_acl_release(acl);
++ return error;
++}
++
++const struct xattr_handler f2fs_xattr_acl_default_handler = {
++ .prefix = POSIX_ACL_XATTR_DEFAULT,
++ .flags = ACL_TYPE_DEFAULT,
++ .list = f2fs_xattr_list_acl,
++ .get = f2fs_xattr_get_acl,
++ .set = f2fs_xattr_set_acl,
++};
++
++const struct xattr_handler f2fs_xattr_acl_access_handler = {
++ .prefix = POSIX_ACL_XATTR_ACCESS,
++ .flags = ACL_TYPE_ACCESS,
++ .list = f2fs_xattr_list_acl,
++ .get = f2fs_xattr_get_acl,
++ .set = f2fs_xattr_set_acl,
++};
++
++static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
++ size_t list_size, const char *name, size_t name_len, int type)
++{
++ const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
++ size_t size;
++
++ if (type != F2FS_XATTR_INDEX_ADVISE)
++ return 0;
++
++ size = strlen(xname) + 1;
++ if (list && size <= list_size)
++ memcpy(list, xname, size);
++ return size;
++}
++
++static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
++ void *buffer, size_t size, int type)
++{
++ struct inode *inode = dentry->d_inode;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++
++ *((char *)buffer) = F2FS_I(inode)->i_advise;
++ return sizeof(char);
++}
++
++static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int type)
++{
++ struct inode *inode = dentry->d_inode;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++ if (!inode_owner_or_capable(inode))
++ return -EPERM;
++ if (value == NULL)
++ return -EINVAL;
++
++ F2FS_I(inode)->i_advise |= *(char *)value;
++ return 0;
++}
++
++const struct xattr_handler f2fs_xattr_advise_handler = {
++ .prefix = F2FS_SYSTEM_ADVISE_PREFIX,
++ .flags = F2FS_XATTR_INDEX_ADVISE,
++ .list = f2fs_xattr_advise_list,
++ .get = f2fs_xattr_advise_get,
++ .set = f2fs_xattr_advise_set,
++};
+diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h
+new file mode 100644
+index 0000000..c97675e
+--- /dev/null
++++ b/fs/f2fs/acl.h
+@@ -0,0 +1,57 @@
++/**
++ * fs/f2fs/acl.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/acl.h
++ *
++ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __F2FS_ACL_H__
++#define __F2FS_ACL_H__
++
++#include <linux/posix_acl_xattr.h>
++
++#define F2FS_ACL_VERSION 0x0001
++
++struct f2fs_acl_entry {
++ __le16 e_tag;
++ __le16 e_perm;
++ __le32 e_id;
++};
++
++struct f2fs_acl_entry_short {
++ __le16 e_tag;
++ __le16 e_perm;
++};
++
++struct f2fs_acl_header {
++ __le32 a_version;
++};
++
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++
++extern struct posix_acl *f2fs_get_acl(struct inode *inode, int type);
++extern int f2fs_acl_chmod(struct inode *inode);
++extern int f2fs_init_acl(struct inode *inode, struct inode *dir);
++#else
++#define f2fs_check_acl NULL
++#define f2fs_get_acl NULL
++#define f2fs_set_acl NULL
++
++static inline int f2fs_acl_chmod(struct inode *inode)
++{
++ return 0;
++}
++
++static inline int f2fs_init_acl(struct inode *inode, struct inode *dir)
++{
++ return 0;
++}
++#endif
++#endif /* __F2FS_ACL_H__ */
+diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
+new file mode 100644
+index 0000000..aca50fe
+--- /dev/null
++++ b/fs/f2fs/xattr.c
+@@ -0,0 +1,389 @@
++/**
++ * fs/f2fs/xattr.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/xattr.c
++ *
++ * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
++ *
++ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
++ * Extended attributes for symlinks and special files added per
++ * suggestion of Luka Renko <luka.renko@hermes.si>.
++ * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
++ * Red Hat Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/rwsem.h>
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "xattr.h"
++
++static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
++ size_t list_size, const char *name, size_t name_len, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ int total_len, prefix_len = 0;
++ const char *prefix = NULL;
++
++ switch (type) {
++ case F2FS_XATTR_INDEX_USER:
++ if (!test_opt(sbi, XATTR_USER))
++ return -EOPNOTSUPP;
++ prefix = XATTR_USER_PREFIX;
++ prefix_len = XATTR_USER_PREFIX_LEN;
++ break;
++ case F2FS_XATTR_INDEX_TRUSTED:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ prefix = XATTR_TRUSTED_PREFIX;
++ prefix_len = XATTR_TRUSTED_PREFIX_LEN;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ total_len = prefix_len + name_len + 1;
++ if (list && total_len <= list_size) {
++ memcpy(list, prefix, prefix_len);
++ memcpy(list+prefix_len, name, name_len);
++ list[prefix_len + name_len] = '\0';
++ }
++ return total_len;
++}
++
++static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
++ void *buffer, size_t size, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++
++ switch (type) {
++ case F2FS_XATTR_INDEX_USER:
++ if (!test_opt(sbi, XATTR_USER))
++ return -EOPNOTSUPP;
++ break;
++ case F2FS_XATTR_INDEX_TRUSTED:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ break;
++ default:
++ return -EINVAL;
++ }
++ if (strcmp(name, "") == 0)
++ return -EINVAL;
++ return f2fs_getxattr(dentry->d_inode, type, name,
++ buffer, size);
++}
++
++static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++
++ switch (type) {
++ case F2FS_XATTR_INDEX_USER:
++ if (!test_opt(sbi, XATTR_USER))
++ return -EOPNOTSUPP;
++ break;
++ case F2FS_XATTR_INDEX_TRUSTED:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ break;
++ default:
++ return -EINVAL;
++ }
++ if (strcmp(name, "") == 0)
++ return -EINVAL;
++
++ return f2fs_setxattr(dentry->d_inode, type, name, value, size);
++}
++
++const struct xattr_handler f2fs_xattr_user_handler = {
++ .prefix = XATTR_USER_PREFIX,
++ .flags = F2FS_XATTR_INDEX_USER,
++ .list = f2fs_xattr_generic_list,
++ .get = f2fs_xattr_generic_get,
++ .set = f2fs_xattr_generic_set,
++};
++
++const struct xattr_handler f2fs_xattr_trusted_handler = {
++ .prefix = XATTR_TRUSTED_PREFIX,
++ .flags = F2FS_XATTR_INDEX_TRUSTED,
++ .list = f2fs_xattr_generic_list,
++ .get = f2fs_xattr_generic_get,
++ .set = f2fs_xattr_generic_set,
++};
++
++static const struct xattr_handler *f2fs_xattr_handler_map[] = {
++ [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &f2fs_xattr_acl_access_handler,
++ [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler,
++#endif
++ [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
++ [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler,
++};
++
++const struct xattr_handler *f2fs_xattr_handlers[] = {
++ &f2fs_xattr_user_handler,
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ &f2fs_xattr_acl_access_handler,
++ &f2fs_xattr_acl_default_handler,
++#endif
++ &f2fs_xattr_trusted_handler,
++ &f2fs_xattr_advise_handler,
++ NULL,
++};
++
++static inline const struct xattr_handler *f2fs_xattr_handler(int name_index)
++{
++ const struct xattr_handler *handler = NULL;
++
++ if (name_index > 0 && name_index < ARRAY_SIZE(f2fs_xattr_handler_map))
++ handler = f2fs_xattr_handler_map[name_index];
++ return handler;
++}
++
++int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_xattr_entry *entry;
++ struct page *page;
++ void *base_addr;
++ int error = 0, found = 0;
++ int value_len, name_len;
++
++ if (name == NULL)
++ return -EINVAL;
++ name_len = strlen(name);
++
++ if (!fi->i_xattr_nid)
++ return -ENODATA;
++
++ page = get_node_page(sbi, fi->i_xattr_nid);
++ base_addr = page_address(page);
++
++ list_for_each_xattr(entry, base_addr) {
++ if (entry->e_name_index != name_index)
++ continue;
++ if (entry->e_name_len != name_len)
++ continue;
++ if (!memcmp(entry->e_name, name, name_len)) {
++ found = 1;
++ break;
++ }
++ }
++ if (!found) {
++ error = -ENODATA;
++ goto cleanup;
++ }
++
++ value_len = le16_to_cpu(entry->e_value_size);
++
++ if (buffer && value_len > buffer_size) {
++ error = -ERANGE;
++ goto cleanup;
++ }
++
++ if (buffer) {
++ char *pval = entry->e_name + entry->e_name_len;
++ memcpy(buffer, pval, value_len);
++ }
++ error = value_len;
++
++cleanup:
++ f2fs_put_page(page, 1);
++ return error;
++}
++
++ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
++{
++ struct inode *inode = dentry->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_xattr_entry *entry;
++ struct page *page;
++ void *base_addr;
++ int error = 0;
++ size_t rest = buffer_size;
++
++ if (!fi->i_xattr_nid)
++ return 0;
++
++ page = get_node_page(sbi, fi->i_xattr_nid);
++ base_addr = page_address(page);
++
++ list_for_each_xattr(entry, base_addr) {
++ const struct xattr_handler *handler =
++ f2fs_xattr_handler(entry->e_name_index);
++ size_t size;
++
++ if (!handler)
++ continue;
++
++ size = handler->list(dentry, buffer, rest, entry->e_name,
++ entry->e_name_len, handler->flags);
++ if (buffer && size > rest) {
++ error = -ERANGE;
++ goto cleanup;
++ }
++
++ if (buffer)
++ buffer += size;
++ rest -= size;
++ }
++ error = buffer_size - rest;
++cleanup:
++ f2fs_put_page(page, 1);
++ return error;
++}
++
++int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
++ const void *value, size_t value_len)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_xattr_header *header = NULL;
++ struct f2fs_xattr_entry *here, *last;
++ struct page *page;
++ void *base_addr;
++ int error, found, free, name_len, newsize;
++ char *pval;
++
++ if (name == NULL)
++ return -EINVAL;
++ name_len = strlen(name);
++
++ if (value == NULL)
++ value_len = 0;
++
++ if (name_len > 255 || value_len > MAX_VALUE_LEN)
++ return -ERANGE;
++
++ mutex_lock_op(sbi, NODE_NEW);
++ if (!fi->i_xattr_nid) {
++ /* Allocate new attribute block */
++ struct dnode_of_data dn;
++
++ if (!alloc_nid(sbi, &fi->i_xattr_nid)) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ return -ENOSPC;
++ }
++ set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
++ mark_inode_dirty(inode);
++
++ page = new_node_page(&dn, XATTR_NODE_OFFSET);
++ if (IS_ERR(page)) {
++ alloc_nid_failed(sbi, fi->i_xattr_nid);
++ fi->i_xattr_nid = 0;
++ mutex_unlock_op(sbi, NODE_NEW);
++ return PTR_ERR(page);
++ }
++
++ alloc_nid_done(sbi, fi->i_xattr_nid);
++ base_addr = page_address(page);
++ header = XATTR_HDR(base_addr);
++ header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
++ header->h_refcount = cpu_to_le32(1);
++ } else {
++ /* The inode already has an extended attribute block. */
++ page = get_node_page(sbi, fi->i_xattr_nid);
++ if (IS_ERR(page)) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ return PTR_ERR(page);
++ }
++
++ base_addr = page_address(page);
++ header = XATTR_HDR(base_addr);
++ }
++
++ if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
++ error = -EIO;
++ goto cleanup;
++ }
++
++ /* find entry with wanted name. */
++ found = 0;
++ list_for_each_xattr(here, base_addr) {
++ if (here->e_name_index != name_index)
++ continue;
++ if (here->e_name_len != name_len)
++ continue;
++ if (!memcmp(here->e_name, name, name_len)) {
++ found = 1;
++ break;
++ }
++ }
++
++ last = here;
++
++ while (!IS_XATTR_LAST_ENTRY(last))
++ last = XATTR_NEXT_ENTRY(last);
++
++ newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) +
++ name_len + value_len);
++
++ /* 1. Check space */
++ if (value) {
++ /* If value is NULL, it is remove operation.
++ * In case of update operation, we caculate free.
++ */
++ free = MIN_OFFSET - ((char *)last - (char *)header);
++ if (found)
++ free = free - ENTRY_SIZE(here);
++
++ if (free < newsize) {
++ error = -ENOSPC;
++ goto cleanup;
++ }
++ }
++
++ /* 2. Remove old entry */
++ if (found) {
++ /* If entry is found, remove old entry.
++ * If not found, remove operation is not needed.
++ */
++ struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
++ int oldsize = ENTRY_SIZE(here);
++
++ memmove(here, next, (char *)last - (char *)next);
++ last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
++ memset(last, 0, oldsize);
++ }
++
++ /* 3. Write new entry */
++ if (value) {
++ /* Before we come here, old entry is removed.
++ * We just write new entry. */
++ memset(last, 0, newsize);
++ last->e_name_index = name_index;
++ last->e_name_len = name_len;
++ memcpy(last->e_name, name, name_len);
++ pval = last->e_name + name_len;
++ memcpy(pval, value, value_len);
++ last->e_value_size = cpu_to_le16(value_len);
++ }
++
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++
++ if (is_inode_flag_set(fi, FI_ACL_MODE)) {
++ inode->i_mode = fi->i_acl_mode;
++ inode->i_ctime = CURRENT_TIME;
++ clear_inode_flag(fi, FI_ACL_MODE);
++ }
++ f2fs_write_inode(inode, NULL);
++ mutex_unlock_op(sbi, NODE_NEW);
++
++ return 0;
++cleanup:
++ f2fs_put_page(page, 1);
++ mutex_unlock_op(sbi, NODE_NEW);
++ return error;
++}
+diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
+new file mode 100644
+index 0000000..29b0a08
+--- /dev/null
++++ b/fs/f2fs/xattr.h
+@@ -0,0 +1,145 @@
++/**
++ * fs/f2fs/xattr.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/xattr.h
++ *
++ * On-disk format of extended attributes for the ext2 filesystem.
++ *
++ * (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __F2FS_XATTR_H__
++#define __F2FS_XATTR_H__
++
++#include <linux/init.h>
++#include <linux/xattr.h>
++
++/* Magic value in attribute blocks */
++#define F2FS_XATTR_MAGIC 0xF2F52011
++
++/* Maximum number of references to one attribute block */
++#define F2FS_XATTR_REFCOUNT_MAX 1024
++
++/* Name indexes */
++#define F2FS_SYSTEM_ADVISE_PREFIX "system.advise"
++#define F2FS_XATTR_INDEX_USER 1
++#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2
++#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3
++#define F2FS_XATTR_INDEX_TRUSTED 4
++#define F2FS_XATTR_INDEX_LUSTRE 5
++#define F2FS_XATTR_INDEX_SECURITY 6
++#define F2FS_XATTR_INDEX_ADVISE 7
++
++struct f2fs_xattr_header {
++ __le32 h_magic; /* magic number for identification */
++ __le32 h_refcount; /* reference count */
++ __u32 h_reserved[4]; /* zero right now */
++};
++
++struct f2fs_xattr_entry {
++ __u8 e_name_index;
++ __u8 e_name_len;
++ __le16 e_value_size; /* size of attribute value */
++ char e_name[0]; /* attribute name */
++};
++
++#define XATTR_HDR(ptr) ((struct f2fs_xattr_header *)(ptr))
++#define XATTR_ENTRY(ptr) ((struct f2fs_xattr_entry *)(ptr))
++#define XATTR_FIRST_ENTRY(ptr) (XATTR_ENTRY(XATTR_HDR(ptr)+1))
++#define XATTR_ROUND (3)
++
++#define XATTR_ALIGN(size) ((size + XATTR_ROUND) & ~XATTR_ROUND)
++
++#define ENTRY_SIZE(entry) (XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + \
++ entry->e_name_len + le16_to_cpu(entry->e_value_size)))
++
++#define XATTR_NEXT_ENTRY(entry) ((struct f2fs_xattr_entry *)((char *)(entry) +\
++ ENTRY_SIZE(entry)))
++
++#define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
++
++#define list_for_each_xattr(entry, addr) \
++ for (entry = XATTR_FIRST_ENTRY(addr);\
++ !IS_XATTR_LAST_ENTRY(entry);\
++ entry = XATTR_NEXT_ENTRY(entry))
++
++
++#define MIN_OFFSET XATTR_ALIGN(PAGE_SIZE - \
++ sizeof(struct node_footer) - \
++ sizeof(__u32))
++
++#define MAX_VALUE_LEN (MIN_OFFSET - sizeof(struct f2fs_xattr_header) - \
++ sizeof(struct f2fs_xattr_entry))
++
++/**
++ * On-disk structure of f2fs_xattr
++ * We use only 1 block for xattr.
++ *
++ * +--------------------+
++ * | f2fs_xattr_header |
++ * | |
++ * +--------------------+
++ * | f2fs_xattr_entry |
++ * | .e_name_index = 1 |
++ * | .e_name_len = 3 |
++ * | .e_value_size = 14 |
++ * | .e_name = "foo" |
++ * | "value_of_xattr" |<- value_offs = e_name + e_name_len
++ * +--------------------+
++ * | f2fs_xattr_entry |
++ * | .e_name_index = 4 |
++ * | .e_name = "bar" |
++ * +--------------------+
++ * | |
++ * | Free |
++ * | |
++ * +--------------------+<- MIN_OFFSET
++ * | node_footer |
++ * | (nid, ino, offset) |
++ * +--------------------+
++ *
++ **/
++
++#ifdef CONFIG_F2FS_FS_XATTR
++extern const struct xattr_handler f2fs_xattr_user_handler;
++extern const struct xattr_handler f2fs_xattr_trusted_handler;
++extern const struct xattr_handler f2fs_xattr_acl_access_handler;
++extern const struct xattr_handler f2fs_xattr_acl_default_handler;
++extern const struct xattr_handler f2fs_xattr_advise_handler;
++
++extern const struct xattr_handler *f2fs_xattr_handlers[];
++
++extern int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
++ const void *value, size_t value_len);
++extern int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size);
++extern ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
++ size_t buffer_size);
++
++#else
++
++#define f2fs_xattr_handlers NULL
++static inline int f2fs_setxattr(struct inode *inode, int name_index,
++ const char *name, const void *value, size_t value_len)
++{
++ return -EOPNOTSUPP;
++}
++static inline int f2fs_getxattr(struct inode *inode, int name_index,
++ const char *name, void *buffer, size_t buffer_size)
++{
++ return -EOPNOTSUPP;
++}
++static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
++ size_t buffer_size)
++{
++ return -EOPNOTSUPP;
++}
++#endif
++
++#endif /* __F2FS_XATTR_H__ */
diff --git a/patches/linux-3.7-rc6/0111-f2fs-add-garbage-collection-functions.patch b/patches/linux-3.7-rc6/0111-f2fs-add-garbage-collection-functions.patch
new file mode 100644
index 0000000..ef99275
--- /dev/null
+++ b/patches/linux-3.7-rc6/0111-f2fs-add-garbage-collection-functions.patch
@@ -0,0 +1,1395 @@
+From 441b0d2cd8b763ad0f4b5e6294c354e5ac4beee2 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:32:20 +0000
+Subject: [PATCH] f2fs: add garbage collection functions
+
+This adds on-demand and background cleaning functions.
+
+- The basic background cleaning policy is trying to do cleaning jobs as much as
+ possible whenever the system is idle. Once the background cleaning is done,
+ the cleaner sleeps an amount of time not to interfere with VFS calls. The time
+ is dynamically adjusted according to the status of whole segments, which is
+ decreased when the following conditions are satisfied.
+
+ . GC is not conducted currently, and
+ . IO subsystem is idle by checking the number of requets in bdev's request
+ list, and
+ . There are enough dirty segments.
+
+ Otherwise, the time is increased incrementally until to the maximum time.
+ Note that, min and max times are 10 secs and 30 secs by default.
+
+- F2FS adopts a default victim selection policy where background cleaning uses
+ a cost-benefit algorithm, while on-demand cleaning uses a greedy algorithm.
+
+- The method of moving data during the cleaning is slightly different between
+ background and on-demand cleaning schemes. In the case of background cleaning,
+ F2FS loads the data, and marks them as dirty. Then, F2FS expects that the data
+ will be moved by flusher or VM. In the case of on-demand cleaning, F2FS should
+ move the data right away.
+
+- In order to identify valid blocks in a victim segment, F2FS scans the bitmap
+ of the segment managed as an SIT entry.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/gc.c | 1139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/gc.h | 203 +++++++++++
+ 2 files changed, 1342 insertions(+)
+ create mode 100644 fs/f2fs/gc.c
+ create mode 100644 fs/f2fs/gc.h
+
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+new file mode 100644
+index 0000000..753b05e
+--- /dev/null
++++ b/fs/f2fs/gc.c
+@@ -0,0 +1,1139 @@
++/**
++ * fs/f2fs/gc.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/backing-dev.h>
++#include <linux/proc_fs.h>
++#include <linux/init.h>
++#include <linux/f2fs_fs.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++#include <linux/freezer.h>
++#include <linux/blkdev.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++#include "gc.h"
++
++static LIST_HEAD(f2fs_stat_list);
++static struct kmem_cache *winode_slab;
++
++static int gc_thread_func(void *data)
++{
++ struct f2fs_sb_info *sbi = data;
++ wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head;
++ long wait_ms;
++
++ wait_ms = GC_THREAD_MIN_SLEEP_TIME;
++
++ do {
++ if (try_to_freeze())
++ continue;
++ else
++ wait_event_interruptible_timeout(*wq,
++ kthread_should_stop(),
++ msecs_to_jiffies(wait_ms));
++ if (kthread_should_stop())
++ break;
++
++ f2fs_balance_fs(sbi);
++
++ if (!test_opt(sbi, BG_GC))
++ continue;
++
++ /*
++ * [GC triggering condition]
++ * 0. GC is not conducted currently.
++ * 1. There are enough dirty segments.
++ * 2. IO subsystem is idle by checking the # of writeback pages.
++ * 3. IO subsystem is idle by checking the # of requests in
++ * bdev's request list.
++ *
++ * Note) We have to avoid triggering GCs too much frequently.
++ * Because it is possible that some segments can be
++ * invalidated soon after by user update or deletion.
++ * So, I'd like to wait some time to collect dirty segments.
++ */
++ if (!mutex_trylock(&sbi->gc_mutex))
++ continue;
++
++ if (!is_idle(sbi)) {
++ wait_ms = increase_sleep_time(wait_ms);
++ mutex_unlock(&sbi->gc_mutex);
++ continue;
++ }
++
++ if (has_enough_invalid_blocks(sbi))
++ wait_ms = decrease_sleep_time(wait_ms);
++ else
++ wait_ms = increase_sleep_time(wait_ms);
++
++ sbi->bg_gc++;
++
++ if (f2fs_gc(sbi, 1) == GC_NONE)
++ wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
++ else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
++ wait_ms = GC_THREAD_MAX_SLEEP_TIME;
++
++ } while (!kthread_should_stop());
++ return 0;
++}
++
++int start_gc_thread(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_kthread *gc_th = NULL;
++
++ gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
++ if (!gc_th)
++ return -ENOMEM;
++
++ sbi->gc_thread = gc_th;
++ init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head);
++ sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
++ GC_THREAD_NAME);
++ if (IS_ERR(gc_th->f2fs_gc_task)) {
++ kfree(gc_th);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++void stop_gc_thread(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
++ if (!gc_th)
++ return;
++ kthread_stop(gc_th->f2fs_gc_task);
++ kfree(gc_th);
++ sbi->gc_thread = NULL;
++}
++
++static int select_gc_type(int gc_type)
++{
++ return (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
++}
++
++static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
++ int type, struct victim_sel_policy *p)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ if (IS_SSR_TYPE(type)) {
++ p->alloc_mode = SSR;
++ p->gc_mode = GC_GREEDY;
++ p->type = GET_SSR_TYPE(type);
++ p->dirty_segmap = dirty_i->dirty_segmap[p->type];
++ p->ofs_unit = 1;
++ } else {
++ p->alloc_mode = LFS;
++ p->gc_mode = select_gc_type(gc_type);
++ p->type = 0;
++ p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
++ p->ofs_unit = sbi->segs_per_sec;
++ }
++ p->offset = sbi->last_victim[p->gc_mode];
++}
++
++static unsigned int get_max_cost(struct f2fs_sb_info *sbi,
++ struct victim_sel_policy *p)
++{
++ if (p->gc_mode == GC_GREEDY)
++ return (1 << sbi->log_blocks_per_seg) * p->ofs_unit;
++ else if (p->gc_mode == GC_CB)
++ return UINT_MAX;
++ else /* No other gc_mode */
++ return 0;
++}
++
++static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int segno;
++
++ /*
++ * If the gc_type is FG_GC, we can select victim segments
++ * selected by background GC before.
++ * Those segments guarantee they have small valid blocks.
++ */
++ segno = find_next_bit(dirty_i->victim_segmap[BG_GC],
++ TOTAL_SEGS(sbi), 0);
++ if (segno < TOTAL_SEGS(sbi)) {
++ clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
++ return segno;
++ }
++ return NULL_SEGNO;
++}
++
++static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int secno = GET_SECNO(sbi, segno);
++ unsigned int start = secno * sbi->segs_per_sec;
++ unsigned long long mtime = 0;
++ unsigned int vblocks;
++ unsigned char age = 0;
++ unsigned char u;
++ unsigned int i;
++
++ for (i = 0; i < sbi->segs_per_sec; i++)
++ mtime += get_seg_entry(sbi, start + i)->mtime;
++ vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++
++ mtime = div_u64(mtime, sbi->segs_per_sec);
++ vblocks = div_u64(vblocks, sbi->segs_per_sec);
++
++ u = (vblocks * 100) >> sbi->log_blocks_per_seg;
++
++ /* Handle if the system time is changed by user */
++ if (mtime < sit_i->min_mtime)
++ sit_i->min_mtime = mtime;
++ if (mtime > sit_i->max_mtime)
++ sit_i->max_mtime = mtime;
++ if (sit_i->max_mtime != sit_i->min_mtime)
++ age = 100 - div64_u64(100 * (mtime - sit_i->min_mtime),
++ sit_i->max_mtime - sit_i->min_mtime);
++
++ return UINT_MAX - ((100 * (100 - u) * age) / (100 + u));
++}
++
++static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno,
++ struct victim_sel_policy *p)
++{
++ if (p->alloc_mode == SSR)
++ return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
++
++ /* alloc_mode == LFS */
++ if (p->gc_mode == GC_GREEDY)
++ return get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++ else
++ return get_cb_cost(sbi, segno);
++}
++
++/**
++ * This function is called from two pathes.
++ * One is garbage collection and the other is SSR segment selection.
++ * When it is called during GC, it just gets a victim segment
++ * and it does not remove it from dirty seglist.
++ * When it is called from SSR segment selection, it finds a segment
++ * which has minimum valid blocks and removes it from dirty seglist.
++ */
++static int get_victim_by_default(struct f2fs_sb_info *sbi,
++ unsigned int *result, int gc_type, int type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ struct victim_sel_policy p;
++ unsigned int segno;
++ int nsearched = 0;
++
++ select_policy(sbi, gc_type, type, &p);
++
++ p.min_segno = NULL_SEGNO;
++ p.min_cost = get_max_cost(sbi, &p);
++
++ mutex_lock(&dirty_i->seglist_lock);
++
++ if (p.alloc_mode == LFS && gc_type == FG_GC) {
++ p.min_segno = check_bg_victims(sbi);
++ if (p.min_segno != NULL_SEGNO)
++ goto got_it;
++ }
++
++ while (1) {
++ unsigned long cost;
++
++ segno = find_next_bit(p.dirty_segmap,
++ TOTAL_SEGS(sbi), p.offset);
++ if (segno >= TOTAL_SEGS(sbi)) {
++ if (sbi->last_victim[p.gc_mode]) {
++ sbi->last_victim[p.gc_mode] = 0;
++ p.offset = 0;
++ continue;
++ }
++ break;
++ }
++ p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
++
++ if (test_bit(segno, dirty_i->victim_segmap[FG_GC]))
++ continue;
++ if (gc_type == BG_GC &&
++ test_bit(segno, dirty_i->victim_segmap[BG_GC]))
++ continue;
++ if (IS_CURSEC(sbi, GET_SECNO(sbi, segno)))
++ continue;
++
++ cost = get_gc_cost(sbi, segno, &p);
++
++ if (p.min_cost > cost) {
++ p.min_segno = segno;
++ p.min_cost = cost;
++ }
++
++ if (cost == get_max_cost(sbi, &p))
++ continue;
++
++ if (nsearched++ >= MAX_VICTIM_SEARCH) {
++ sbi->last_victim[p.gc_mode] = segno;
++ break;
++ }
++ }
++got_it:
++ if (p.min_segno != NULL_SEGNO) {
++ *result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
++ if (p.alloc_mode == LFS) {
++ int i;
++ for (i = 0; i < p.ofs_unit; i++)
++ set_bit(*result + i,
++ dirty_i->victim_segmap[gc_type]);
++ }
++ }
++ mutex_unlock(&dirty_i->seglist_lock);
++
++ return (p.min_segno == NULL_SEGNO) ? 0 : 1;
++}
++
++static const struct victim_selection default_v_ops = {
++ .get_victim = get_victim_by_default,
++};
++
++static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist)
++{
++ struct list_head *this;
++ struct inode_entry *ie;
++
++ list_for_each(this, ilist) {
++ ie = list_entry(this, struct inode_entry, list);
++ if (ie->inode->i_ino == ino)
++ return ie->inode;
++ }
++ return NULL;
++}
++
++static void add_gc_inode(struct inode *inode, struct list_head *ilist)
++{
++ struct list_head *this;
++ struct inode_entry *new_ie, *ie;
++
++ list_for_each(this, ilist) {
++ ie = list_entry(this, struct inode_entry, list);
++ if (ie->inode == inode) {
++ iput(inode);
++ return;
++ }
++ }
++repeat:
++ new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS);
++ if (!new_ie) {
++ cond_resched();
++ goto repeat;
++ }
++ new_ie->inode = inode;
++ list_add_tail(&new_ie->list, ilist);
++}
++
++static void put_gc_inode(struct list_head *ilist)
++{
++ struct inode_entry *ie, *next_ie;
++ list_for_each_entry_safe(ie, next_ie, ilist, list) {
++ iput(ie->inode);
++ list_del(&ie->list);
++ kmem_cache_free(winode_slab, ie);
++ }
++}
++
++static int check_valid_map(struct f2fs_sb_info *sbi,
++ unsigned int segno, int offset)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct seg_entry *sentry;
++ int ret;
++
++ mutex_lock(&sit_i->sentry_lock);
++ sentry = get_seg_entry(sbi, segno);
++ ret = f2fs_test_bit(offset, sentry->cur_valid_map);
++ mutex_unlock(&sit_i->sentry_lock);
++ return ret ? GC_OK : GC_NEXT;
++}
++
++/**
++ * This function compares node address got in summary with that in NAT.
++ * On validity, copy that node with cold status, otherwise (invalid node)
++ * ignore that.
++ */
++static int gc_node_segment(struct f2fs_sb_info *sbi,
++ struct f2fs_summary *sum, unsigned int segno, int gc_type)
++{
++ bool initial = true;
++ struct f2fs_summary *entry;
++ int off;
++
++next_step:
++ entry = sum;
++ for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
++ nid_t nid = le32_to_cpu(entry->nid);
++ struct page *node_page;
++ int err;
++
++ /*
++ * It makes sure that free segments are able to write
++ * all the dirty node pages before CP after this CP.
++ * So let's check the space of dirty node pages.
++ */
++ if (should_do_checkpoint(sbi)) {
++ mutex_lock(&sbi->cp_mutex);
++ block_operations(sbi);
++ return GC_BLOCKED;
++ }
++
++ err = check_valid_map(sbi, segno, off);
++ if (err == GC_ERROR)
++ return err;
++ else if (err == GC_NEXT)
++ continue;
++
++ if (initial) {
++ ra_node_page(sbi, nid);
++ continue;
++ }
++ node_page = get_node_page(sbi, nid);
++ if (IS_ERR(node_page))
++ continue;
++
++ /* set page dirty and write it */
++ if (!PageWriteback(node_page))
++ set_page_dirty(node_page);
++ f2fs_put_page(node_page, 1);
++ gc_stat_inc_node_blk_count(sbi, 1);
++ }
++ if (initial) {
++ initial = false;
++ goto next_step;
++ }
++
++ if (gc_type == FG_GC) {
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++ sync_node_pages(sbi, 0, &wbc);
++ }
++ return GC_DONE;
++}
++
++/**
++ * Calculate start block index that this node page contains
++ */
++block_t start_bidx_of_node(unsigned int node_ofs)
++{
++ block_t start_bidx;
++ unsigned int bidx, indirect_blks;
++ int dec;
++
++ indirect_blks = 2 * NIDS_PER_BLOCK + 4;
++
++ start_bidx = 1;
++ if (node_ofs == 0) {
++ start_bidx = 0;
++ } else if (node_ofs <= 2) {
++ bidx = node_ofs - 1;
++ } else if (node_ofs <= indirect_blks) {
++ dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
++ bidx = node_ofs - 2 - dec;
++ } else {
++ dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
++ bidx = node_ofs - 5 - dec;
++ }
++
++ if (start_bidx)
++ start_bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE;
++ return start_bidx;
++}
++
++static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
++ struct node_info *dni, block_t blkaddr, unsigned int *nofs)
++{
++ struct page *node_page;
++ nid_t nid;
++ unsigned int ofs_in_node;
++ block_t source_blkaddr;
++
++ nid = le32_to_cpu(sum->nid);
++ ofs_in_node = le16_to_cpu(sum->ofs_in_node);
++
++ node_page = get_node_page(sbi, nid);
++ if (IS_ERR(node_page))
++ return GC_NEXT;
++
++ get_node_info(sbi, nid, dni);
++
++ if (sum->version != dni->version) {
++ f2fs_put_page(node_page, 1);
++ return GC_NEXT;
++ }
++
++ *nofs = ofs_of_node(node_page);
++ source_blkaddr = datablock_addr(node_page, ofs_in_node);
++ f2fs_put_page(node_page, 1);
++
++ if (source_blkaddr != blkaddr)
++ return GC_NEXT;
++ return GC_OK;
++}
++
++static void move_data_page(struct inode *inode, struct page *page, int gc_type)
++{
++ if (page->mapping != inode->i_mapping)
++ goto out;
++
++ if (inode != page->mapping->host)
++ goto out;
++
++ if (PageWriteback(page))
++ goto out;
++
++ if (gc_type == BG_GC) {
++ set_page_dirty(page);
++ set_cold_data(page);
++ } else {
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ mutex_lock_op(sbi, DATA_WRITE);
++ if (clear_page_dirty_for_io(page) &&
++ S_ISDIR(inode->i_mode)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ set_cold_data(page);
++ do_write_data_page(page);
++ mutex_unlock_op(sbi, DATA_WRITE);
++ clear_cold_data(page);
++ }
++out:
++ f2fs_put_page(page, 1);
++}
++
++/**
++ * This function tries to get parent node of victim data block, and identifies
++ * data block validity. If the block is valid, copy that with cold status and
++ * modify parent node.
++ * If the parent node is not valid or the data block address is different,
++ * the victim data block is ignored.
++ */
++static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
++ struct list_head *ilist, unsigned int segno, int gc_type)
++{
++ struct super_block *sb = sbi->sb;
++ struct f2fs_summary *entry;
++ block_t start_addr;
++ int err, off;
++ int phase = 0;
++
++ start_addr = START_BLOCK(sbi, segno);
++
++next_step:
++ entry = sum;
++ for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
++ struct page *data_page;
++ struct inode *inode;
++ struct node_info dni; /* dnode info for the data */
++ unsigned int ofs_in_node, nofs;
++ block_t start_bidx;
++
++ /*
++ * It makes sure that free segments are able to write
++ * all the dirty node pages before CP after this CP.
++ * So let's check the space of dirty node pages.
++ */
++ if (should_do_checkpoint(sbi)) {
++ mutex_lock(&sbi->cp_mutex);
++ block_operations(sbi);
++ err = GC_BLOCKED;
++ goto stop;
++ }
++
++ err = check_valid_map(sbi, segno, off);
++ if (err == GC_ERROR)
++ goto stop;
++ else if (err == GC_NEXT)
++ continue;
++
++ if (phase == 0) {
++ ra_node_page(sbi, le32_to_cpu(entry->nid));
++ continue;
++ }
++
++ /* Get an inode by ino with checking validity */
++ err = check_dnode(sbi, entry, &dni, start_addr + off, &nofs);
++ if (err == GC_ERROR)
++ goto stop;
++ else if (err == GC_NEXT)
++ continue;
++
++ if (phase == 1) {
++ ra_node_page(sbi, dni.ino);
++ continue;
++ }
++
++ start_bidx = start_bidx_of_node(nofs);
++ ofs_in_node = le16_to_cpu(entry->ofs_in_node);
++
++ if (phase == 2) {
++ inode = f2fs_iget_nowait(sb, dni.ino);
++ if (IS_ERR(inode))
++ continue;
++
++ data_page = find_data_page(inode,
++ start_bidx + ofs_in_node);
++ if (IS_ERR(data_page))
++ goto next_iput;
++
++ f2fs_put_page(data_page, 0);
++ add_gc_inode(inode, ilist);
++ } else {
++ inode = find_gc_inode(dni.ino, ilist);
++ if (inode) {
++ data_page = get_lock_data_page(inode,
++ start_bidx + ofs_in_node);
++ if (IS_ERR(data_page))
++ continue;
++ move_data_page(inode, data_page, gc_type);
++ gc_stat_inc_data_blk_count(sbi, 1);
++ }
++ }
++ continue;
++next_iput:
++ iput(inode);
++ }
++ if (++phase < 4)
++ goto next_step;
++ err = GC_DONE;
++stop:
++ if (gc_type == FG_GC)
++ f2fs_submit_bio(sbi, DATA, true);
++ return err;
++}
++
++static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
++ int gc_type, int type)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ int ret;
++ mutex_lock(&sit_i->sentry_lock);
++ ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, result, gc_type, type);
++ mutex_unlock(&sit_i->sentry_lock);
++ return ret;
++}
++
++static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
++ struct list_head *ilist, int gc_type)
++{
++ struct page *sum_page;
++ struct f2fs_summary_block *sum;
++ int ret = GC_DONE;
++
++ /* read segment summary of victim */
++ sum_page = get_sum_page(sbi, segno);
++ if (IS_ERR(sum_page))
++ return GC_ERROR;
++
++ /*
++ * CP needs to lock sum_page. In this time, we don't need
++ * to lock this page, because this summary page is not gone anywhere.
++ * Also, this page is not gonna be updated before GC is done.
++ */
++ unlock_page(sum_page);
++ sum = page_address(sum_page);
++
++ switch (GET_SUM_TYPE((&sum->footer))) {
++ case SUM_TYPE_NODE:
++ ret = gc_node_segment(sbi, sum->entries, segno, gc_type);
++ break;
++ case SUM_TYPE_DATA:
++ ret = gc_data_segment(sbi, sum->entries, ilist, segno, gc_type);
++ break;
++ }
++ gc_stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
++ gc_stat_inc_call_count(sbi->gc_info);
++
++ f2fs_put_page(sum_page, 0);
++ return ret;
++}
++
++int f2fs_gc(struct f2fs_sb_info *sbi, int nGC)
++{
++ unsigned int segno;
++ int old_free_secs, cur_free_secs;
++ int gc_status, nfree;
++ struct list_head ilist;
++ int gc_type = BG_GC;
++
++ INIT_LIST_HEAD(&ilist);
++gc_more:
++ nfree = 0;
++ gc_status = GC_NONE;
++
++ if (has_not_enough_free_secs(sbi))
++ old_free_secs = reserved_sections(sbi);
++ else
++ old_free_secs = free_sections(sbi);
++
++ while (sbi->sb->s_flags & MS_ACTIVE) {
++ int i;
++ if (has_not_enough_free_secs(sbi))
++ gc_type = FG_GC;
++
++ cur_free_secs = free_sections(sbi) + nfree;
++
++ /* We got free space successfully. */
++ if (nGC < cur_free_secs - old_free_secs)
++ break;
++
++ if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
++ break;
++
++ for (i = 0; i < sbi->segs_per_sec; i++) {
++ /*
++ * do_garbage_collect will give us three gc_status:
++ * GC_ERROR, GC_DONE, and GC_BLOCKED.
++ * If GC is finished uncleanly, we have to return
++ * the victim to dirty segment list.
++ */
++ gc_status = do_garbage_collect(sbi, segno + i,
++ &ilist, gc_type);
++ if (gc_status != GC_DONE)
++ goto stop;
++ nfree++;
++ }
++ }
++stop:
++ if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) {
++ write_checkpoint(sbi, (gc_status == GC_BLOCKED), false);
++ if (nfree)
++ goto gc_more;
++ }
++ sbi->last_gc_status = gc_status;
++ mutex_unlock(&sbi->gc_mutex);
++
++ put_gc_inode(&ilist);
++ BUG_ON(!list_empty(&ilist));
++ return gc_status;
++}
++
++#ifdef CONFIG_F2FS_STAT_FS
++void f2fs_update_stat(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ int i;
++
++ /* valid check of the segment numbers */
++ si->hit_ext = sbi->read_hit_ext;
++ si->total_ext = sbi->total_hit_ext;
++ si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
++ si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
++ si->ndirty_dirs = sbi->n_dirty_dirs;
++ si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
++ si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
++ si->rsvd_segs = reserved_segments(sbi);
++ si->overp_segs = overprovision_segments(sbi);
++ si->valid_count = valid_user_blocks(sbi);
++ si->valid_node_count = valid_node_count(sbi);
++ si->valid_inode_count = valid_inode_count(sbi);
++ si->utilization = utilization(sbi);
++
++ si->free_segs = free_segments(sbi);
++ si->free_secs = free_sections(sbi);
++ si->prefree_count = prefree_segments(sbi);
++ si->dirty_count = dirty_segments(sbi);
++ si->node_pages = sbi->node_inode->i_mapping->nrpages;
++ si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
++ si->nats = NM_I(sbi)->nat_cnt;
++ si->sits = SIT_I(sbi)->dirty_sentries;
++ si->fnids = NM_I(sbi)->fcnt;
++ si->bg_gc = sbi->bg_gc;
++ si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_valid = (int)(written_block_count(sbi) >>
++ sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_invalid = 50 - si->util_free - si->util_valid;
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
++ struct curseg_info *curseg = CURSEG_I(sbi, i);
++ si->curseg[i] = curseg->segno;
++ si->cursec[i] = curseg->segno / sbi->segs_per_sec;
++ si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
++ }
++
++ for (i = 0; i < 2; i++) {
++ si->segment_count[i] = sbi->segment_count[i];
++ si->block_count[i] = sbi->block_count[i];
++ }
++}
++
++/**
++ * This function calculates BDF of every segments
++ */
++void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int segno, vblocks;
++ int ndirty = 0;
++
++ bimodal = 0;
++ total_vblocks = 0;
++ blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
++ hblks_per_sec = blks_per_sec / 2;
++ mutex_lock(&sit_i->sentry_lock);
++ for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
++ vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++ dist = abs(vblocks - hblks_per_sec);
++ bimodal += dist * dist;
++
++ if (vblocks > 0 && vblocks < blks_per_sec) {
++ total_vblocks += vblocks;
++ ndirty++;
++ }
++ }
++ mutex_unlock(&sit_i->sentry_lock);
++ dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
++ si->bimodal = bimodal / dist;
++ if (si->dirty_count)
++ si->avg_vblocks = total_vblocks / ndirty;
++ else
++ si->avg_vblocks = 0;
++}
++
++static int f2fs_read_gc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++ int i = 0;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ int j;
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_stat(si->sbi);
++
++ buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
++ buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
++ si->nat_area_segs, si->sit_area_segs);
++ buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
++ si->ssa_area_segs, si->main_area_segs);
++ buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
++ si->overp_segs, si->rsvd_segs);
++ buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
++ si->utilization, si->valid_count);
++ buf += sprintf(buf, " - Node: %u (Inode: %u, ",
++ si->valid_node_count, si->valid_inode_count);
++ buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
++ si->valid_node_count - si->valid_inode_count,
++ si->valid_count - si->valid_node_count);
++ buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
++ si->main_area_segs, si->main_area_sections,
++ si->main_area_zones);
++ buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_DATA],
++ si->cursec[CURSEG_COLD_DATA],
++ si->curzone[CURSEG_COLD_DATA]);
++ buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_DATA],
++ si->cursec[CURSEG_WARM_DATA],
++ si->curzone[CURSEG_WARM_DATA]);
++ buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_DATA],
++ si->cursec[CURSEG_HOT_DATA],
++ si->curzone[CURSEG_HOT_DATA]);
++ buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_NODE],
++ si->cursec[CURSEG_HOT_NODE],
++ si->curzone[CURSEG_HOT_NODE]);
++ buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_NODE],
++ si->cursec[CURSEG_WARM_NODE],
++ si->curzone[CURSEG_WARM_NODE]);
++ buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_NODE],
++ si->cursec[CURSEG_COLD_NODE],
++ si->curzone[CURSEG_COLD_NODE]);
++ buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
++ si->main_area_segs - si->dirty_count -
++ si->prefree_count - si->free_segs,
++ si->dirty_count);
++ buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
++ si->prefree_count,
++ si->free_segs,
++ si->free_secs);
++ buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
++ si->call_count, si->bg_gc);
++ buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
++ buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
++ buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
++ buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
++ buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
++ buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
++ si->hit_ext, si->total_ext);
++ buf += sprintf(buf, "\nBalancing F2FS Async:\n");
++ buf += sprintf(buf, " - nodes %4d in %4d\n",
++ si->ndirty_node, si->node_pages);
++ buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
++ si->ndirty_dent, si->ndirty_dirs);
++ buf += sprintf(buf, " - meta %4d in %4d\n",
++ si->ndirty_meta, si->meta_pages);
++ buf += sprintf(buf, " - NATs %5d > %lu\n",
++ si->nats, NM_WOUT_THRESHOLD);
++ buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
++ si->sits, si->fnids);
++ buf += sprintf(buf, "\nDistribution of User Blocks:");
++ buf += sprintf(buf, " [ valid | invalid | free ]\n");
++ buf += sprintf(buf, " [");
++ for (j = 0; j < si->util_valid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_invalid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_free; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "]\n\n");
++ buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
++ si->block_count[SSR], si->segment_count[SSR]);
++ buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
++ si->block_count[LFS], si->segment_count[LFS]);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_sit(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_gc_metric(si->sbi);
++
++ buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
++ si->bimodal, si->avg_vblocks);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_mem(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
++ unsigned npages;
++ unsigned base_mem = 0, cache_mem = 0;
++
++ si = gc_i->stat_info;
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
++ base_mem += 2 * sizeof(struct f2fs_inode_info);
++ base_mem += sizeof(*sbi->ckpt);
++
++ /* build sm */
++ base_mem += sizeof(struct f2fs_sm_info);
++
++ /* build sit */
++ base_mem += sizeof(struct sit_info);
++ base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
++ if (sbi->segs_per_sec > 1)
++ base_mem += sbi->total_sections *
++ sizeof(struct sec_entry);
++ base_mem += __bitmap_size(sbi, SIT_BITMAP);
++
++ /* build free segmap */
++ base_mem += sizeof(struct free_segmap_info);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += f2fs_bitmap_size(sbi->total_sections);
++
++ /* build curseg */
++ base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
++ base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
++
++ /* build dirty segmap */
++ base_mem += sizeof(struct dirty_seglist_info);
++ base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ /* buld nm */
++ base_mem += sizeof(struct f2fs_nm_info);
++ base_mem += __bitmap_size(sbi, NAT_BITMAP);
++
++ /* build gc */
++ base_mem += sizeof(struct f2fs_gc_info);
++ base_mem += sizeof(struct f2fs_gc_kthread);
++
++ /* free nids */
++ cache_mem += NM_I(sbi)->fcnt;
++ cache_mem += NM_I(sbi)->nat_cnt;
++ npages = sbi->node_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ npages = sbi->meta_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
++ cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
++
++ buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
++ (base_mem + cache_mem) >> 10,
++ base_mem >> 10,
++ cache_mem >> 10);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++int f2fs_stat_init(struct f2fs_sb_info *sbi)
++{
++ struct proc_dir_entry *entry;
++
++ entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
++ if (!entry)
++ return -ENOMEM;
++ entry->read_proc = f2fs_read_gc;
++ entry->write_proc = NULL;
++
++ entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_sit;
++ entry->write_proc = NULL;
++ entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_mem;
++ entry->write_proc = NULL;
++ return 0;
++}
++
++void f2fs_stat_exit(struct f2fs_sb_info *sbi)
++{
++ if (sbi->s_proc) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
++ }
++}
++#endif
++
++int build_gc_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i;
++ struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi);
++#ifdef CONFIG_F2FS_STAT_FS
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_stat_info *si;
++#endif
++
++ gc_i = kzalloc(sizeof(struct f2fs_gc_info), GFP_KERNEL);
++ if (!gc_i)
++ return -ENOMEM;
++
++ sbi->gc_info = gc_i;
++ gc_i->rsvd_segment_count = le32_to_cpu(ckp->rsvd_segment_count);
++ gc_i->overp_segment_count = le32_to_cpu(ckp->overprov_segment_count);
++
++ DIRTY_I(sbi)->v_ops = &default_v_ops;
++
++#ifdef CONFIG_F2FS_STAT_FS
++ gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
++ GFP_KERNEL);
++ if (!gc_i->stat_info)
++ return -ENOMEM;
++ si = gc_i->stat_info;
++ mutex_init(&si->stat_list);
++ list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
++
++ si->all_area_segs = le32_to_cpu(raw_super->segment_count);
++ si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
++ si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
++ si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
++ si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
++ si->main_area_sections = le32_to_cpu(raw_super->section_count);
++ si->main_area_zones = si->main_area_sections /
++ le32_to_cpu(raw_super->secs_per_zone);
++ si->sbi = sbi;
++#endif
++ return 0;
++}
++
++void destroy_gc_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++#ifdef CONFIG_F2FS_STAT_FS
++ struct f2fs_stat_info *si = gc_i->stat_info;
++#endif
++ if (!gc_i)
++ return;
++
++#ifdef CONFIG_F2FS_STAT_FS
++ list_del(&gc_i->stat_list);
++ mutex_lock(&si->stat_list);
++ si->sbi = NULL;
++ mutex_unlock(&si->stat_list);
++ kfree(gc_i->stat_info);
++#endif
++ sbi->gc_info = NULL;
++ kfree(gc_i);
++}
++
++int create_gc_caches(void)
++{
++ winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes",
++ sizeof(struct inode_entry), NULL);
++ if (!winode_slab)
++ return -ENOMEM;
++ return 0;
++}
++
++void destroy_gc_caches(void)
++{
++ kmem_cache_destroy(winode_slab);
++}
+diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
+new file mode 100644
+index 0000000..29b345d
+--- /dev/null
++++ b/fs/f2fs/gc.h
+@@ -0,0 +1,203 @@
++/**
++ * fs/f2fs/gc.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#define GC_THREAD_NAME "f2fs_gc_task"
++#define GC_THREAD_MIN_WB_PAGES 1 /*
++ * a threshold to determine
++ * whether IO subsystem is idle
++ * or not
++ */
++#define GC_THREAD_MIN_SLEEP_TIME 10000 /* milliseconds */
++#define GC_THREAD_MAX_SLEEP_TIME 30000
++#define GC_THREAD_NOGC_SLEEP_TIME 10000
++#define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */
++#define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */
++
++/* Search max. number of dirty segments to select a victim segment */
++#define MAX_VICTIM_SEARCH 20
++
++enum {
++ GC_NONE = 0,
++ GC_ERROR,
++ GC_OK,
++ GC_NEXT,
++ GC_BLOCKED,
++ GC_DONE,
++};
++
++#ifdef CONFIG_F2FS_STAT_FS
++struct f2fs_stat_info {
++ struct f2fs_sb_info *sbi;
++ struct mutex stat_list;
++ int all_area_segs;
++ int sit_area_segs;
++ int nat_area_segs;
++ int ssa_area_segs;
++ int main_area_segs;
++ int main_area_sections;
++ int main_area_zones;
++ int hit_ext, total_ext;
++ int ndirty_node;
++ int ndirty_dent;
++ int ndirty_dirs;
++ int ndirty_meta;
++ int nats, sits, fnids;
++ int total_count;
++ int utilization;
++ int bg_gc;
++ unsigned int valid_count;
++ unsigned int valid_node_count;
++ unsigned int valid_inode_count;
++ unsigned int bimodal, avg_vblocks;
++ int util_free, util_valid, util_invalid;
++ int rsvd_segs, overp_segs;
++ int dirty_count;
++ int node_pages;
++ int meta_pages;
++ int prefree_count;
++ int call_count;
++ int tot_segs;
++ int node_segs;
++ int data_segs;
++ int free_segs;
++ int free_secs;
++ int tot_blks;
++ int data_blks;
++ int node_blks;
++ int curseg[6];
++ int cursec[6];
++ int curzone[6];
++
++ unsigned int segment_count[2];
++ unsigned int block_count[2];
++};
++
++#define GC_STAT_I(gi) ((gi)->stat_info)
++
++#define gc_stat_inc_call_count(gi) ((GC_STAT_I(gi))->call_count++)
++
++#define gc_stat_inc_seg_count(sbi, type) \
++ do { \
++ struct f2fs_gc_info *gi = sbi->gc_info; \
++ GC_STAT_I(gi)->tot_segs++; \
++ if (type == SUM_TYPE_DATA) \
++ GC_STAT_I(gi)->data_segs++; \
++ else \
++ GC_STAT_I(gi)->node_segs++; \
++ } while (0)
++
++#define gc_stat_inc_tot_blk_count(gi, blks) \
++ ((GC_STAT_I(gi)->tot_blks) += (blks))
++
++#define gc_stat_inc_data_blk_count(sbi, blks) \
++ do { \
++ struct f2fs_gc_info *gi = sbi->gc_info; \
++ gc_stat_inc_tot_blk_count(gi, blks); \
++ GC_STAT_I(gi)->data_blks += (blks); \
++ } while (0)
++
++#define gc_stat_inc_node_blk_count(sbi, blks) \
++ do { \
++ struct f2fs_gc_info *gi = sbi->gc_info; \
++ gc_stat_inc_tot_blk_count(gi, blks); \
++ GC_STAT_I(gi)->node_blks += (blks); \
++ } while (0)
++
++#else
++#define gc_stat_inc_call_count(gi)
++#define gc_stat_inc_seg_count(gi, type)
++#define gc_stat_inc_tot_blk_count(gi, blks)
++#define gc_stat_inc_data_blk_count(gi, blks)
++#define gc_stat_inc_node_blk_count(sbi, blks)
++#endif
++
++struct f2fs_gc_kthread {
++ struct task_struct *f2fs_gc_task;
++ wait_queue_head_t gc_wait_queue_head;
++};
++
++struct inode_entry {
++ struct list_head list;
++ struct inode *inode;
++};
++
++/**
++ * inline functions
++ */
++static inline block_t free_user_blocks(struct f2fs_sb_info *sbi)
++{
++ if (free_segments(sbi) < overprovision_segments(sbi))
++ return 0;
++ else
++ return (free_segments(sbi) - overprovision_segments(sbi))
++ << sbi->log_blocks_per_seg;
++}
++
++static inline block_t limit_invalid_user_blocks(struct f2fs_sb_info *sbi)
++{
++ return (long)(sbi->user_block_count * LIMIT_INVALID_BLOCK) / 100;
++}
++
++static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi)
++{
++ block_t reclaimable_user_blocks = sbi->user_block_count -
++ written_block_count(sbi);
++ return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100;
++}
++
++static inline long increase_sleep_time(long wait)
++{
++ wait += GC_THREAD_MIN_SLEEP_TIME;
++ if (wait > GC_THREAD_MAX_SLEEP_TIME)
++ wait = GC_THREAD_MAX_SLEEP_TIME;
++ return wait;
++}
++
++static inline long decrease_sleep_time(long wait)
++{
++ wait -= GC_THREAD_MIN_SLEEP_TIME;
++ if (wait <= GC_THREAD_MIN_SLEEP_TIME)
++ wait = GC_THREAD_MIN_SLEEP_TIME;
++ return wait;
++}
++
++static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
++{
++ block_t invalid_user_blocks = sbi->user_block_count -
++ written_block_count(sbi);
++ /*
++ * Background GC is triggered with the following condition.
++ * 1. There are a number of invalid blocks.
++ * 2. There is not enough free space.
++ */
++ if (invalid_user_blocks > limit_invalid_user_blocks(sbi) &&
++ free_user_blocks(sbi) < limit_free_user_blocks(sbi))
++ return true;
++ return false;
++}
++
++static inline int is_idle(struct f2fs_sb_info *sbi)
++{
++ struct block_device *bdev = sbi->sb->s_bdev;
++ struct request_queue *q = bdev_get_queue(bdev);
++ struct request_list *rl = &q->root_rl;
++ return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
++}
++
++static bool should_do_checkpoint(struct f2fs_sb_info *sbi)
++{
++ unsigned int pages_per_sec = sbi->segs_per_sec *
++ (1 << sbi->log_blocks_per_seg);
++ int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++ int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++ return free_sections(sbi) <= (node_secs + 2 * dent_secs + 2);
++}
diff --git a/patches/linux-3.7-rc6/0112-f2fs-add-recovery-routines-for-roll-forward.patch b/patches/linux-3.7-rc6/0112-f2fs-add-recovery-routines-for-roll-forward.patch
new file mode 100644
index 0000000..39a629a
--- /dev/null
+++ b/patches/linux-3.7-rc6/0112-f2fs-add-recovery-routines-for-roll-forward.patch
@@ -0,0 +1,411 @@
+From a458712f9bd670469b3aa1c474bbdc48465af27c Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:32:56 +0000
+Subject: [PATCH] f2fs: add recovery routines for roll-forward
+
+This adds roll-forward routines to recover fsynced data.
+
+- F2FS uses basically roll-back model with checkpointing.
+
+- In order to implement fsync(), there are two approaches as follows.
+
+1. A roll-back model with checkpointing at every fsync()
+ : This is a naive method, but suffers from very low performance.
+
+2. A roll-forward model
+ : F2FS adopts this model where all the fsynced data should be recovered, which
+ were written after checkpointing was done. In order to figure out the data,
+ F2FS keeps a "fsync" mark in direct node blocks. In addition, F2FS remains
+ the location of next node block in each direct node block for reconstructing
+ the chain of node blocks during the recovery.
+
+- In order to enhance the performance, F2FS keeps a "dentry" mark also in direct
+ node blocks. If this is set during the recovery, F2FS replays adding a dentry.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/recovery.c | 375 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 375 insertions(+)
+ create mode 100644 fs/f2fs/recovery.c
+
+diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
+new file mode 100644
+index 0000000..59b6331
+--- /dev/null
++++ b/fs/f2fs/recovery.c
+@@ -0,0 +1,375 @@
++/**
++ * fs/f2fs/recovery.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++static struct kmem_cache *fsync_entry_slab;
++
++bool space_for_roll_forward(struct f2fs_sb_info *sbi)
++{
++ if (sbi->last_valid_block_count + sbi->alloc_valid_block_count
++ > sbi->user_block_count)
++ return false;
++ return true;
++}
++
++static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
++ nid_t ino)
++{
++ struct list_head *this;
++ struct fsync_inode_entry *entry;
++
++ list_for_each(this, head) {
++ entry = list_entry(this, struct fsync_inode_entry, list);
++ if (entry->inode->i_ino == ino)
++ return entry;
++ }
++ return NULL;
++}
++
++static int recover_dentry(struct page *ipage, struct inode *inode)
++{
++ struct f2fs_node *raw_node = (struct f2fs_node *)kmap(ipage);
++ struct f2fs_inode *raw_inode = &(raw_node->i);
++ struct dentry dent, parent;
++ struct f2fs_dir_entry *de;
++ struct page *page;
++ struct inode *dir;
++ int err = 0;
++
++ if (!is_dent_dnode(ipage))
++ goto out;
++
++ dir = f2fs_iget(inode->i_sb, le32_to_cpu(raw_inode->i_pino));
++ if (IS_ERR(dir)) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ parent.d_inode = dir;
++ dent.d_parent = &parent;
++ dent.d_name.len = le32_to_cpu(raw_inode->i_namelen);
++ dent.d_name.name = raw_inode->i_name;
++
++ de = f2fs_find_entry(dir, &dent.d_name, &page);
++ if (de) {
++ kunmap(page);
++ f2fs_put_page(page, 0);
++ } else {
++ f2fs_add_link(&dent, inode);
++ }
++ iput(dir);
++out:
++ kunmap(ipage);
++ return err;
++}
++
++static int recover_inode(struct inode *inode, struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
++ struct f2fs_inode *raw_inode = &(raw_node->i);
++
++ inode->i_mode = le32_to_cpu(raw_inode->i_mode);
++ i_size_write(inode, le64_to_cpu(raw_inode->i_size));
++ inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
++ inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
++ inode->i_mtime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
++ inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
++ inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec);
++ inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
++
++ return recover_dentry(node_page, inode);
++}
++
++static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
++{
++ unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
++ struct curseg_info *curseg;
++ struct page *page;
++ block_t blkaddr;
++ int err = 0;
++
++ /* get node pages in the current segment */
++ curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
++ blkaddr = START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff;
++
++ /* read node page */
++ page = alloc_page(GFP_NOFS | __GFP_ZERO);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++ lock_page(page);
++
++ while (1) {
++ struct fsync_inode_entry *entry;
++
++ if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
++ goto out;
++
++ if (cp_ver != cpver_of_node(page))
++ goto out;
++
++ if (!is_fsync_dnode(page))
++ goto next;
++
++ entry = get_fsync_inode(head, ino_of_node(page));
++ if (entry) {
++ entry->blkaddr = blkaddr;
++ if (IS_INODE(page) && is_dent_dnode(page))
++ set_inode_flag(F2FS_I(entry->inode),
++ FI_INC_LINK);
++ } else {
++ if (IS_INODE(page) && is_dent_dnode(page)) {
++ if (recover_inode_page(sbi, page)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ }
++
++ /* add this fsync inode to the list */
++ entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS);
++ if (!entry) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ INIT_LIST_HEAD(&entry->list);
++ list_add_tail(&entry->list, head);
++
++ entry->inode = f2fs_iget(sbi->sb, ino_of_node(page));
++ if (IS_ERR(entry->inode)) {
++ err = PTR_ERR(entry->inode);
++ goto out;
++ }
++ entry->blkaddr = blkaddr;
++ }
++ if (IS_INODE(page)) {
++ err = recover_inode(entry->inode, page);
++ if (err)
++ goto out;
++ }
++next:
++ /* check next segment */
++ blkaddr = next_blkaddr_of_node(page);
++ ClearPageUptodate(page);
++ }
++out:
++ unlock_page(page);
++ __free_pages(page, 0);
++ return err;
++}
++
++static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi,
++ struct list_head *head)
++{
++ struct list_head *this;
++ struct fsync_inode_entry *entry;
++ list_for_each(this, head) {
++ entry = list_entry(this, struct fsync_inode_entry, list);
++ iput(entry->inode);
++ list_del(&entry->list);
++ kmem_cache_free(fsync_entry_slab, entry);
++ }
++}
++
++static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
++ block_t blkaddr)
++{
++ struct seg_entry *sentry;
++ unsigned int segno = GET_SEGNO(sbi, blkaddr);
++ unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) &
++ (sbi->blocks_per_seg - 1);
++ struct f2fs_summary sum;
++ nid_t ino;
++ void *kaddr;
++ struct inode *inode;
++ struct page *node_page;
++ block_t bidx;
++ int i;
++
++ sentry = get_seg_entry(sbi, segno);
++ if (!f2fs_test_bit(blkoff, sentry->cur_valid_map))
++ return;
++
++ /* Get the previous summary */
++ for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
++ struct curseg_info *curseg = CURSEG_I(sbi, i);
++ if (curseg->segno == segno) {
++ sum = curseg->sum_blk->entries[blkoff];
++ break;
++ }
++ }
++ if (i > CURSEG_COLD_DATA) {
++ struct page *sum_page = get_sum_page(sbi, segno);
++ struct f2fs_summary_block *sum_node;
++ kaddr = page_address(sum_page);
++ sum_node = (struct f2fs_summary_block *)kaddr;
++ sum = sum_node->entries[blkoff];
++ f2fs_put_page(sum_page, 1);
++ }
++
++ /* Get the node page */
++ node_page = get_node_page(sbi, le32_to_cpu(sum.nid));
++ bidx = start_bidx_of_node(ofs_of_node(node_page)) +
++ le16_to_cpu(sum.ofs_in_node);
++ ino = ino_of_node(node_page);
++ f2fs_put_page(node_page, 1);
++
++ /* Deallocate previous index in the node page */
++ inode = f2fs_iget_nowait(sbi->sb, ino);
++ truncate_hole(inode, bidx, bidx + 1);
++ iput(inode);
++}
++
++static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
++ struct page *page, block_t blkaddr)
++{
++ unsigned int start, end;
++ struct dnode_of_data dn;
++ struct f2fs_summary sum;
++ struct node_info ni;
++
++ start = start_bidx_of_node(ofs_of_node(page));
++ if (IS_INODE(page))
++ end = start + ADDRS_PER_INODE;
++ else
++ end = start + ADDRS_PER_BLOCK;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ if (get_dnode_of_data(&dn, start, 0))
++ return;
++
++ wait_on_page_writeback(dn.node_page);
++
++ get_node_info(sbi, dn.nid, &ni);
++ BUG_ON(ni.ino != ino_of_node(page));
++ BUG_ON(ofs_of_node(dn.node_page) != ofs_of_node(page));
++
++ for (; start < end; start++) {
++ block_t src, dest;
++
++ src = datablock_addr(dn.node_page, dn.ofs_in_node);
++ dest = datablock_addr(page, dn.ofs_in_node);
++
++ if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) {
++ if (src == NULL_ADDR) {
++ int err = reserve_new_block(&dn);
++ /* We should not get -ENOSPC */
++ BUG_ON(err);
++ }
++
++ /* Check the previous node page having this index */
++ check_index_in_prev_nodes(sbi, dest);
++
++ set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
++
++ /* write dummy data page */
++ recover_data_page(sbi, NULL, &sum, src, dest);
++ update_extent_cache(dest, &dn);
++ }
++ dn.ofs_in_node++;
++ }
++
++ /* write node page in place */
++ set_summary(&sum, dn.nid, 0, 0);
++ if (IS_INODE(dn.node_page))
++ sync_inode_page(&dn);
++
++ copy_node_footer(dn.node_page, page);
++ fill_node_footer(dn.node_page, dn.nid, ni.ino,
++ ofs_of_node(page), false);
++ set_page_dirty(dn.node_page);
++
++ recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
++ f2fs_put_dnode(&dn);
++}
++
++static void recover_data(struct f2fs_sb_info *sbi,
++ struct list_head *head, int type)
++{
++ unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
++ struct curseg_info *curseg;
++ struct page *page;
++ block_t blkaddr;
++
++ /* get node pages in the current segment */
++ curseg = CURSEG_I(sbi, type);
++ blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
++
++ /* read node page */
++ page = alloc_page(GFP_NOFS | __GFP_ZERO);
++ if (IS_ERR(page))
++ return;
++ lock_page(page);
++
++ while (1) {
++ struct fsync_inode_entry *entry;
++
++ if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
++ goto out;
++
++ if (cp_ver != cpver_of_node(page))
++ goto out;
++
++ entry = get_fsync_inode(head, ino_of_node(page));
++ if (!entry)
++ goto next;
++
++ do_recover_data(sbi, entry->inode, page, blkaddr);
++
++ if (entry->blkaddr == blkaddr) {
++ iput(entry->inode);
++ list_del(&entry->list);
++ kmem_cache_free(fsync_entry_slab, entry);
++ }
++next:
++ /* check next segment */
++ blkaddr = next_blkaddr_of_node(page);
++ ClearPageUptodate(page);
++ }
++out:
++ unlock_page(page);
++ __free_pages(page, 0);
++
++ allocate_new_segments(sbi);
++}
++
++void recover_fsync_data(struct f2fs_sb_info *sbi)
++{
++ struct list_head inode_list;
++
++ fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
++ sizeof(struct fsync_inode_entry), NULL);
++ if (unlikely(!fsync_entry_slab))
++ return;
++
++ INIT_LIST_HEAD(&inode_list);
++
++ /* step #1: find fsynced inode numbers */
++ if (find_fsync_dnodes(sbi, &inode_list))
++ goto out;
++
++ if (list_empty(&inode_list))
++ goto out;
++
++ /* step #2: recover data */
++ sbi->por_doing = 1;
++ recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
++ sbi->por_doing = 0;
++ BUG_ON(!list_empty(&inode_list));
++out:
++ destroy_fsync_dnodes(sbi, &inode_list);
++ kmem_cache_destroy(fsync_entry_slab);
++ write_checkpoint(sbi, false, false);
++}
diff --git a/patches/linux-3.7-rc6/0113-f2fs-update-Kconfig-and-Makefile.patch b/patches/linux-3.7-rc6/0113-f2fs-update-Kconfig-and-Makefile.patch
new file mode 100644
index 0000000..263eef8
--- /dev/null
+++ b/patches/linux-3.7-rc6/0113-f2fs-update-Kconfig-and-Makefile.patch
@@ -0,0 +1,115 @@
+From 4c78c6c29f9986e46020c04c8741db373565f473 Mon Sep 17 00:00:00 2001
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:33:28 +0000
+Subject: [PATCH] f2fs: update Kconfig and Makefile
+
+This adds Makefile and Kconfig for f2fs, and updates Makefile and Kconfig files
+in the fs directory.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/Kconfig | 1 +
+ fs/Makefile | 1 +
+ fs/f2fs/Kconfig | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/Makefile | 6 ++++++
+ 4 files changed, 63 insertions(+)
+ create mode 100644 fs/f2fs/Kconfig
+ create mode 100644 fs/f2fs/Makefile
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index f95ae3a..e352b37 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -220,6 +220,7 @@ source "fs/pstore/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
+ source "fs/exofs/Kconfig"
++source "fs/f2fs/Kconfig"
+
+ endif # MISC_FILESYSTEMS
+
+diff --git a/fs/Makefile b/fs/Makefile
+index 1d7af79..9d53192 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -123,6 +123,7 @@ obj-$(CONFIG_DEBUG_FS) += debugfs/
+ obj-$(CONFIG_OCFS2_FS) += ocfs2/
+ obj-$(CONFIG_BTRFS_FS) += btrfs/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
++obj-$(CONFIG_F2FS_FS) += f2fs/
+ obj-y += exofs/ # Multiple modules
+ obj-$(CONFIG_CEPH_FS) += ceph/
+ obj-$(CONFIG_PSTORE) += pstore/
+diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
+new file mode 100644
+index 0000000..8821c6a
+--- /dev/null
++++ b/fs/f2fs/Kconfig
+@@ -0,0 +1,55 @@
++config F2FS_FS
++ tristate "F2FS filesystem support (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ help
++ F2FS is based on Log-structured File System (LFS), which supports
++ versatile "flash-friendly" features. The design has been focused on
++ addressing the fundamental issues in LFS, which are snowball effect
++ of wandering tree and high cleaning overhead.
++
++ Since flash-based storages show different characteristics according to
++ the internal geometry or flash memory management schemes aka FTL, F2FS
++ and tools support various parameters not only for configuring on-disk
++ layout, but also for selecting allocation and cleaning algorithms.
++
++ If unsure, say N.
++
++config F2FS_STAT_FS
++ bool "F2FS Status Information"
++ depends on F2FS_FS
++ default y
++ help
++ /proc/fs/f2fs/ contains information about partitions mounted as f2fs.
++ For each partition, a corresponding directory, named as its device
++ name, is provided with the following proc entries.
++
++ f2fs_stat major file system information managed by f2fs currently
++ f2fs_sit_stat average SIT information about whole segments
++ f2fs_mem_stat current memory footprint consumed by f2fs
++
++ e.g., in /proc/fs/f2fs/sdb1/
++
++config F2FS_FS_XATTR
++ bool "F2FS extended attributes"
++ depends on F2FS_FS
++ default y
++ help
++ Extended attributes are name:value pairs associated with inodes by
++ the kernel or by users (see the attr(5) manual page, or visit
++ <http://acl.bestbits.at/> for details).
++
++ If unsure, say N.
++
++config F2FS_FS_POSIX_ACL
++ bool "F2FS Access Control Lists"
++ depends on F2FS_FS_XATTR
++ select FS_POSIX_ACL
++ default y
++ help
++ Posix Access Control Lists (ACLs) support permissions for users and
++ gourps beyond the owner/group/world scheme.
++
++ To learn more about Access Control Lists, visit the POSIX ACLs for
++ Linux website <http://acl.bestbits.at/>.
++
++ If you don't know what Access Control Lists are, say N
+diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile
+new file mode 100644
+index 0000000..72fcf9a
+--- /dev/null
++++ b/fs/f2fs/Makefile
+@@ -0,0 +1,6 @@
++obj-$(CONFIG_F2FS_FS) += f2fs.o
++
++f2fs-y := dir.o file.o inode.o namei.o hash.o super.o
++f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o
++f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
++f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
diff --git a/patches/linux-3.7-rc6/0114-f2fs-gc.h-make-should_do_checkpoint-inline.patch b/patches/linux-3.7-rc6/0114-f2fs-gc.h-make-should_do_checkpoint-inline.patch
new file mode 100644
index 0000000..66d5782
--- /dev/null
+++ b/patches/linux-3.7-rc6/0114-f2fs-gc.h-make-should_do_checkpoint-inline.patch
@@ -0,0 +1,26 @@
+From 26e33463d5f5705a2d0159209aff0404b97095c6 Mon Sep 17 00:00:00 2001
+From: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Date: Tue, 23 Oct 2012 18:21:46 +0000
+Subject: [PATCH] f2fs: gc.h: make should_do_checkpoint() inline
+
+This should be an inline function, not a "real" function. Now other
+files can properly include gc.h.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/gc.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
+index 29b345d..b70366f 100644
+--- a/fs/f2fs/gc.h
++++ b/fs/f2fs/gc.h
+@@ -191,7 +191,7 @@ static inline int is_idle(struct f2fs_sb_info *sbi)
+ return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
+ }
+
+-static bool should_do_checkpoint(struct f2fs_sb_info *sbi)
++static inline bool should_do_checkpoint(struct f2fs_sb_info *sbi)
+ {
+ unsigned int pages_per_sec = sbi->segs_per_sec *
+ (1 << sbi->log_blocks_per_seg);
diff --git a/patches/linux-3.7-rc6/0115-f2fs-move-statistics-code-into-one-file.patch b/patches/linux-3.7-rc6/0115-f2fs-move-statistics-code-into-one-file.patch
new file mode 100644
index 0000000..ec8bdd0
--- /dev/null
+++ b/patches/linux-3.7-rc6/0115-f2fs-move-statistics-code-into-one-file.patch
@@ -0,0 +1,967 @@
+From b6f5f093ec14b476ba7d0282488391add23365f6 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Tue, 23 Oct 2012 18:22:41 +0000
+Subject: [PATCH] f2fs: move statistics code into one file
+
+This moves all of the procfs statistics code into one file, debug.c and
+removes the #ifdefs from the core f2fs code when calling statistic
+functions.
+
+This will make it more obvious how to move from procfs to debugfs, no
+functionality was changed here at all.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/Makefile | 1 +
+ fs/f2fs/debug.c | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/f2fs.h | 25 +++-
+ fs/f2fs/gc.c | 373 +-----------------------------------------------
+ fs/f2fs/super.c | 21 +--
+ 5 files changed, 442 insertions(+), 392 deletions(-)
+ create mode 100644 fs/f2fs/debug.c
+
+diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile
+index 72fcf9a..27a0820 100644
+--- a/fs/f2fs/Makefile
++++ b/fs/f2fs/Makefile
+@@ -2,5 +2,6 @@ obj-$(CONFIG_F2FS_FS) += f2fs.o
+
+ f2fs-y := dir.o file.o inode.o namei.o hash.o super.o
+ f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o
++f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o
+ f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
+ f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
+diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
+new file mode 100644
+index 0000000..0145b02
+--- /dev/null
++++ b/fs/f2fs/debug.c
+@@ -0,0 +1,414 @@
++/**
++ * f2fs debugging statistics
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ * Copyright (c) 2012 Linux Foundation
++ * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/fs.h>
++#include <linux/backing-dev.h>
++#include <linux/proc_fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/blkdev.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++#include "gc.h"
++
++static LIST_HEAD(f2fs_stat_list);
++static struct proc_dir_entry *f2fs_proc_root;
++
++
++void f2fs_update_stat(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ int i;
++
++ /* valid check of the segment numbers */
++ si->hit_ext = sbi->read_hit_ext;
++ si->total_ext = sbi->total_hit_ext;
++ si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
++ si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
++ si->ndirty_dirs = sbi->n_dirty_dirs;
++ si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
++ si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
++ si->rsvd_segs = reserved_segments(sbi);
++ si->overp_segs = overprovision_segments(sbi);
++ si->valid_count = valid_user_blocks(sbi);
++ si->valid_node_count = valid_node_count(sbi);
++ si->valid_inode_count = valid_inode_count(sbi);
++ si->utilization = utilization(sbi);
++
++ si->free_segs = free_segments(sbi);
++ si->free_secs = free_sections(sbi);
++ si->prefree_count = prefree_segments(sbi);
++ si->dirty_count = dirty_segments(sbi);
++ si->node_pages = sbi->node_inode->i_mapping->nrpages;
++ si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
++ si->nats = NM_I(sbi)->nat_cnt;
++ si->sits = SIT_I(sbi)->dirty_sentries;
++ si->fnids = NM_I(sbi)->fcnt;
++ si->bg_gc = sbi->bg_gc;
++ si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_valid = (int)(written_block_count(sbi) >>
++ sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_invalid = 50 - si->util_free - si->util_valid;
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
++ struct curseg_info *curseg = CURSEG_I(sbi, i);
++ si->curseg[i] = curseg->segno;
++ si->cursec[i] = curseg->segno / sbi->segs_per_sec;
++ si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
++ }
++
++ for (i = 0; i < 2; i++) {
++ si->segment_count[i] = sbi->segment_count[i];
++ si->block_count[i] = sbi->block_count[i];
++ }
++}
++
++/**
++ * This function calculates BDF of every segments
++ */
++static void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int segno, vblocks;
++ int ndirty = 0;
++
++ bimodal = 0;
++ total_vblocks = 0;
++ blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
++ hblks_per_sec = blks_per_sec / 2;
++ mutex_lock(&sit_i->sentry_lock);
++ for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
++ vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++ dist = abs(vblocks - hblks_per_sec);
++ bimodal += dist * dist;
++
++ if (vblocks > 0 && vblocks < blks_per_sec) {
++ total_vblocks += vblocks;
++ ndirty++;
++ }
++ }
++ mutex_unlock(&sit_i->sentry_lock);
++ dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
++ si->bimodal = bimodal / dist;
++ if (si->dirty_count)
++ si->avg_vblocks = total_vblocks / ndirty;
++ else
++ si->avg_vblocks = 0;
++}
++
++static int f2fs_read_gc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++ int i = 0;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ int j;
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_stat(si->sbi);
++
++ buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
++ buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
++ si->nat_area_segs, si->sit_area_segs);
++ buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
++ si->ssa_area_segs, si->main_area_segs);
++ buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
++ si->overp_segs, si->rsvd_segs);
++ buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
++ si->utilization, si->valid_count);
++ buf += sprintf(buf, " - Node: %u (Inode: %u, ",
++ si->valid_node_count, si->valid_inode_count);
++ buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
++ si->valid_node_count - si->valid_inode_count,
++ si->valid_count - si->valid_node_count);
++ buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
++ si->main_area_segs, si->main_area_sections,
++ si->main_area_zones);
++ buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_DATA],
++ si->cursec[CURSEG_COLD_DATA],
++ si->curzone[CURSEG_COLD_DATA]);
++ buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_DATA],
++ si->cursec[CURSEG_WARM_DATA],
++ si->curzone[CURSEG_WARM_DATA]);
++ buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_DATA],
++ si->cursec[CURSEG_HOT_DATA],
++ si->curzone[CURSEG_HOT_DATA]);
++ buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_NODE],
++ si->cursec[CURSEG_HOT_NODE],
++ si->curzone[CURSEG_HOT_NODE]);
++ buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_NODE],
++ si->cursec[CURSEG_WARM_NODE],
++ si->curzone[CURSEG_WARM_NODE]);
++ buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_NODE],
++ si->cursec[CURSEG_COLD_NODE],
++ si->curzone[CURSEG_COLD_NODE]);
++ buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
++ si->main_area_segs - si->dirty_count -
++ si->prefree_count - si->free_segs,
++ si->dirty_count);
++ buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
++ si->prefree_count,
++ si->free_segs,
++ si->free_secs);
++ buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
++ si->call_count, si->bg_gc);
++ buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
++ buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
++ buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
++ buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
++ buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
++ buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
++ si->hit_ext, si->total_ext);
++ buf += sprintf(buf, "\nBalancing F2FS Async:\n");
++ buf += sprintf(buf, " - nodes %4d in %4d\n",
++ si->ndirty_node, si->node_pages);
++ buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
++ si->ndirty_dent, si->ndirty_dirs);
++ buf += sprintf(buf, " - meta %4d in %4d\n",
++ si->ndirty_meta, si->meta_pages);
++ buf += sprintf(buf, " - NATs %5d > %lu\n",
++ si->nats, NM_WOUT_THRESHOLD);
++ buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
++ si->sits, si->fnids);
++ buf += sprintf(buf, "\nDistribution of User Blocks:");
++ buf += sprintf(buf, " [ valid | invalid | free ]\n");
++ buf += sprintf(buf, " [");
++ for (j = 0; j < si->util_valid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_invalid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_free; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "]\n\n");
++ buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
++ si->block_count[SSR], si->segment_count[SSR]);
++ buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
++ si->block_count[LFS], si->segment_count[LFS]);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_sit(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_gc_metric(si->sbi);
++
++ buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
++ si->bimodal, si->avg_vblocks);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_mem(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
++ unsigned npages;
++ unsigned base_mem = 0, cache_mem = 0;
++
++ si = gc_i->stat_info;
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
++ base_mem += 2 * sizeof(struct f2fs_inode_info);
++ base_mem += sizeof(*sbi->ckpt);
++
++ /* build sm */
++ base_mem += sizeof(struct f2fs_sm_info);
++
++ /* build sit */
++ base_mem += sizeof(struct sit_info);
++ base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
++ if (sbi->segs_per_sec > 1)
++ base_mem += sbi->total_sections *
++ sizeof(struct sec_entry);
++ base_mem += __bitmap_size(sbi, SIT_BITMAP);
++
++ /* build free segmap */
++ base_mem += sizeof(struct free_segmap_info);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += f2fs_bitmap_size(sbi->total_sections);
++
++ /* build curseg */
++ base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
++ base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
++
++ /* build dirty segmap */
++ base_mem += sizeof(struct dirty_seglist_info);
++ base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ /* buld nm */
++ base_mem += sizeof(struct f2fs_nm_info);
++ base_mem += __bitmap_size(sbi, NAT_BITMAP);
++
++ /* build gc */
++ base_mem += sizeof(struct f2fs_gc_info);
++ base_mem += sizeof(struct f2fs_gc_kthread);
++
++ /* free nids */
++ cache_mem += NM_I(sbi)->fcnt;
++ cache_mem += NM_I(sbi)->nat_cnt;
++ npages = sbi->node_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ npages = sbi->meta_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
++ cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
++
++ buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
++ (base_mem + cache_mem) >> 10,
++ base_mem >> 10,
++ cache_mem >> 10);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int init_stats(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_stat_info *si;
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++
++ gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
++ GFP_KERNEL);
++ if (!gc_i->stat_info)
++ return -ENOMEM;
++ si = gc_i->stat_info;
++ mutex_init(&si->stat_list);
++ list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
++
++ si->all_area_segs = le32_to_cpu(raw_super->segment_count);
++ si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
++ si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
++ si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
++ si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
++ si->main_area_sections = le32_to_cpu(raw_super->section_count);
++ si->main_area_zones = si->main_area_sections /
++ le32_to_cpu(raw_super->secs_per_zone);
++ si->sbi = sbi;
++ return 0;
++}
++
++void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i)
++{
++ struct f2fs_stat_info *si = gc_i->stat_info;
++
++ list_del(&gc_i->stat_list);
++ mutex_lock(&si->stat_list);
++ si->sbi = NULL;
++ mutex_unlock(&si->stat_list);
++ kfree(gc_i->stat_info);
++}
++
++int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *sbi)
++{
++ struct proc_dir_entry *entry;
++ int retval;
++
++ if (!f2fs_proc_root)
++ f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
++
++ sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
++
++ retval = init_stats(sbi);
++ if (retval)
++ return retval;
++
++ entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
++ if (!entry)
++ return -ENOMEM;
++ entry->read_proc = f2fs_read_gc;
++ entry->write_proc = NULL;
++
++ entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_sit;
++ entry->write_proc = NULL;
++ entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_mem;
++ entry->write_proc = NULL;
++ return 0;
++}
++
++void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *sbi)
++{
++ if (sbi->s_proc) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
++ remove_proc_entry(sb->s_id, f2fs_proc_root);
++ }
++}
++
++void f2fs_remove_stats(void)
++{
++ remove_proc_entry("fs/f2fs", NULL);
++}
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index bbe2f02..7f508b2 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -953,12 +953,6 @@ int start_gc_thread(struct f2fs_sb_info *);
+ void stop_gc_thread(struct f2fs_sb_info *);
+ block_t start_bidx_of_node(unsigned int);
+ int f2fs_gc(struct f2fs_sb_info *, int);
+-#ifdef CONFIG_F2FS_STAT_FS
+-void f2fs_update_stat(struct f2fs_sb_info *);
+-void f2fs_update_gc_metric(struct f2fs_sb_info *);
+-int f2fs_stat_init(struct f2fs_sb_info *);
+-void f2fs_stat_exit(struct f2fs_sb_info *);
+-#endif
+ int build_gc_manager(struct f2fs_sb_info *);
+ void destroy_gc_manager(struct f2fs_sb_info *);
+ int create_gc_caches(void);
+@@ -970,6 +964,25 @@ void destroy_gc_caches(void);
+ void recover_fsync_data(struct f2fs_sb_info *);
+ bool space_for_roll_forward(struct f2fs_sb_info *);
+
++/**
++ * debug.c
++ */
++#ifdef CONFIG_F2FS_STAT_FS
++void f2fs_update_stat(struct f2fs_sb_info *);
++int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *);
++void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *);
++void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i);
++void f2fs_remove_stats(void);
++#else
++static inline void f2fs_update_stat(struct f2fs_sb_info *sbi) { }
++static inline int f2fs_stat_init(struct super_block *sb,
++ struct f2fs_sb_info *sbi) { return 0; }
++static inline void f2fs_stat_exit(struct super_block *sb,
++ struct f2fs_sb_info *sbi) { }
++static inline void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i) { }
++static inline void f2fs_remove_stats(void) { }
++#endif
++
+ extern const struct file_operations f2fs_dir_operations;
+ extern const struct file_operations f2fs_file_operations;
+ extern const struct inode_operations f2fs_file_inode_operations;
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 753b05e..cfdbd2c 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -24,7 +24,6 @@
+ #include "segment.h"
+ #include "gc.h"
+
+-static LIST_HEAD(f2fs_stat_list);
+ static struct kmem_cache *winode_slab;
+
+ static int gc_thread_func(void *data)
+@@ -727,350 +726,10 @@ stop:
+ return gc_status;
+ }
+
+-#ifdef CONFIG_F2FS_STAT_FS
+-void f2fs_update_stat(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_gc_info *gc_i = sbi->gc_info;
+- struct f2fs_stat_info *si = gc_i->stat_info;
+- int i;
+-
+- /* valid check of the segment numbers */
+- si->hit_ext = sbi->read_hit_ext;
+- si->total_ext = sbi->total_hit_ext;
+- si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
+- si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
+- si->ndirty_dirs = sbi->n_dirty_dirs;
+- si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
+- si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
+- si->rsvd_segs = reserved_segments(sbi);
+- si->overp_segs = overprovision_segments(sbi);
+- si->valid_count = valid_user_blocks(sbi);
+- si->valid_node_count = valid_node_count(sbi);
+- si->valid_inode_count = valid_inode_count(sbi);
+- si->utilization = utilization(sbi);
+-
+- si->free_segs = free_segments(sbi);
+- si->free_secs = free_sections(sbi);
+- si->prefree_count = prefree_segments(sbi);
+- si->dirty_count = dirty_segments(sbi);
+- si->node_pages = sbi->node_inode->i_mapping->nrpages;
+- si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
+- si->nats = NM_I(sbi)->nat_cnt;
+- si->sits = SIT_I(sbi)->dirty_sentries;
+- si->fnids = NM_I(sbi)->fcnt;
+- si->bg_gc = sbi->bg_gc;
+- si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
+- * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+- / 2;
+- si->util_valid = (int)(written_block_count(sbi) >>
+- sbi->log_blocks_per_seg)
+- * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+- / 2;
+- si->util_invalid = 50 - si->util_free - si->util_valid;
+- for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
+- struct curseg_info *curseg = CURSEG_I(sbi, i);
+- si->curseg[i] = curseg->segno;
+- si->cursec[i] = curseg->segno / sbi->segs_per_sec;
+- si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
+- }
+-
+- for (i = 0; i < 2; i++) {
+- si->segment_count[i] = sbi->segment_count[i];
+- si->block_count[i] = sbi->block_count[i];
+- }
+-}
+-
+-/**
+- * This function calculates BDF of every segments
+- */
+-void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_gc_info *gc_i = sbi->gc_info;
+- struct f2fs_stat_info *si = gc_i->stat_info;
+- unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
+- struct sit_info *sit_i = SIT_I(sbi);
+- unsigned int segno, vblocks;
+- int ndirty = 0;
+-
+- bimodal = 0;
+- total_vblocks = 0;
+- blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
+- hblks_per_sec = blks_per_sec / 2;
+- mutex_lock(&sit_i->sentry_lock);
+- for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
+- vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+- dist = abs(vblocks - hblks_per_sec);
+- bimodal += dist * dist;
+-
+- if (vblocks > 0 && vblocks < blks_per_sec) {
+- total_vblocks += vblocks;
+- ndirty++;
+- }
+- }
+- mutex_unlock(&sit_i->sentry_lock);
+- dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
+- si->bimodal = bimodal / dist;
+- if (si->dirty_count)
+- si->avg_vblocks = total_vblocks / ndirty;
+- else
+- si->avg_vblocks = 0;
+-}
+-
+-static int f2fs_read_gc(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+- int i = 0;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- int j;
+- si = gc_i->stat_info;
+-
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- f2fs_update_stat(si->sbi);
+-
+- buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
+- buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
+- si->nat_area_segs, si->sit_area_segs);
+- buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
+- si->ssa_area_segs, si->main_area_segs);
+- buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
+- si->overp_segs, si->rsvd_segs);
+- buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
+- si->utilization, si->valid_count);
+- buf += sprintf(buf, " - Node: %u (Inode: %u, ",
+- si->valid_node_count, si->valid_inode_count);
+- buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
+- si->valid_node_count - si->valid_inode_count,
+- si->valid_count - si->valid_node_count);
+- buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
+- si->main_area_segs, si->main_area_sections,
+- si->main_area_zones);
+- buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_DATA],
+- si->cursec[CURSEG_COLD_DATA],
+- si->curzone[CURSEG_COLD_DATA]);
+- buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_DATA],
+- si->cursec[CURSEG_WARM_DATA],
+- si->curzone[CURSEG_WARM_DATA]);
+- buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_DATA],
+- si->cursec[CURSEG_HOT_DATA],
+- si->curzone[CURSEG_HOT_DATA]);
+- buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_NODE],
+- si->cursec[CURSEG_HOT_NODE],
+- si->curzone[CURSEG_HOT_NODE]);
+- buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_NODE],
+- si->cursec[CURSEG_WARM_NODE],
+- si->curzone[CURSEG_WARM_NODE]);
+- buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_NODE],
+- si->cursec[CURSEG_COLD_NODE],
+- si->curzone[CURSEG_COLD_NODE]);
+- buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
+- si->main_area_segs - si->dirty_count -
+- si->prefree_count - si->free_segs,
+- si->dirty_count);
+- buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
+- si->prefree_count,
+- si->free_segs,
+- si->free_secs);
+- buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
+- si->call_count, si->bg_gc);
+- buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
+- buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
+- buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
+- buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
+- buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
+- buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
+- si->hit_ext, si->total_ext);
+- buf += sprintf(buf, "\nBalancing F2FS Async:\n");
+- buf += sprintf(buf, " - nodes %4d in %4d\n",
+- si->ndirty_node, si->node_pages);
+- buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
+- si->ndirty_dent, si->ndirty_dirs);
+- buf += sprintf(buf, " - meta %4d in %4d\n",
+- si->ndirty_meta, si->meta_pages);
+- buf += sprintf(buf, " - NATs %5d > %lu\n",
+- si->nats, NM_WOUT_THRESHOLD);
+- buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
+- si->sits, si->fnids);
+- buf += sprintf(buf, "\nDistribution of User Blocks:");
+- buf += sprintf(buf, " [ valid | invalid | free ]\n");
+- buf += sprintf(buf, " [");
+- for (j = 0; j < si->util_valid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
+- for (j = 0; j < si->util_invalid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
+- for (j = 0; j < si->util_free; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "]\n\n");
+- buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
+- si->block_count[SSR], si->segment_count[SSR]);
+- buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
+- si->block_count[LFS], si->segment_count[LFS]);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-static int f2fs_read_sit(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- si = gc_i->stat_info;
+-
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- f2fs_update_gc_metric(si->sbi);
+-
+- buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
+- si->bimodal, si->avg_vblocks);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-static int f2fs_read_mem(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
+- unsigned npages;
+- unsigned base_mem = 0, cache_mem = 0;
+-
+- si = gc_i->stat_info;
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
+- base_mem += 2 * sizeof(struct f2fs_inode_info);
+- base_mem += sizeof(*sbi->ckpt);
+-
+- /* build sm */
+- base_mem += sizeof(struct f2fs_sm_info);
+-
+- /* build sit */
+- base_mem += sizeof(struct sit_info);
+- base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
+- base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
+- if (sbi->segs_per_sec > 1)
+- base_mem += sbi->total_sections *
+- sizeof(struct sec_entry);
+- base_mem += __bitmap_size(sbi, SIT_BITMAP);
+-
+- /* build free segmap */
+- base_mem += sizeof(struct free_segmap_info);
+- base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += f2fs_bitmap_size(sbi->total_sections);
+-
+- /* build curseg */
+- base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
+- base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
+-
+- /* build dirty segmap */
+- base_mem += sizeof(struct dirty_seglist_info);
+- base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+-
+- /* buld nm */
+- base_mem += sizeof(struct f2fs_nm_info);
+- base_mem += __bitmap_size(sbi, NAT_BITMAP);
+-
+- /* build gc */
+- base_mem += sizeof(struct f2fs_gc_info);
+- base_mem += sizeof(struct f2fs_gc_kthread);
+-
+- /* free nids */
+- cache_mem += NM_I(sbi)->fcnt;
+- cache_mem += NM_I(sbi)->nat_cnt;
+- npages = sbi->node_inode->i_mapping->nrpages;
+- cache_mem += npages << PAGE_CACHE_SHIFT;
+- npages = sbi->meta_inode->i_mapping->nrpages;
+- cache_mem += npages << PAGE_CACHE_SHIFT;
+- cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
+- cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
+-
+- buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
+- (base_mem + cache_mem) >> 10,
+- base_mem >> 10,
+- cache_mem >> 10);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-int f2fs_stat_init(struct f2fs_sb_info *sbi)
+-{
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
+- if (!entry)
+- return -ENOMEM;
+- entry->read_proc = f2fs_read_gc;
+- entry->write_proc = NULL;
+-
+- entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_sit;
+- entry->write_proc = NULL;
+- entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_mem;
+- entry->write_proc = NULL;
+- return 0;
+-}
+-
+-void f2fs_stat_exit(struct f2fs_sb_info *sbi)
+-{
+- if (sbi->s_proc) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
+- }
+-}
+-#endif
+-
+ int build_gc_manager(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_gc_info *gc_i;
+ struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi);
+-#ifdef CONFIG_F2FS_STAT_FS
+- struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+- struct f2fs_stat_info *si;
+-#endif
+
+ gc_i = kzalloc(sizeof(struct f2fs_gc_info), GFP_KERNEL);
+ if (!gc_i)
+@@ -1082,44 +741,18 @@ int build_gc_manager(struct f2fs_sb_info *sbi)
+
+ DIRTY_I(sbi)->v_ops = &default_v_ops;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
+- GFP_KERNEL);
+- if (!gc_i->stat_info)
+- return -ENOMEM;
+- si = gc_i->stat_info;
+- mutex_init(&si->stat_list);
+- list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
+-
+- si->all_area_segs = le32_to_cpu(raw_super->segment_count);
+- si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
+- si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
+- si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
+- si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
+- si->main_area_sections = le32_to_cpu(raw_super->section_count);
+- si->main_area_zones = si->main_area_sections /
+- le32_to_cpu(raw_super->secs_per_zone);
+- si->sbi = sbi;
+-#endif
+ return 0;
+ }
+
+ void destroy_gc_manager(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_gc_info *gc_i = sbi->gc_info;
+-#ifdef CONFIG_F2FS_STAT_FS
+- struct f2fs_stat_info *si = gc_i->stat_info;
+-#endif
++
+ if (!gc_i)
+ return;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- list_del(&gc_i->stat_list);
+- mutex_lock(&si->stat_list);
+- si->sbi = NULL;
+- mutex_unlock(&si->stat_list);
+- kfree(gc_i->stat_info);
+-#endif
++ f2fs_destroy_gci_stats(gc_i);
++
+ sbi->gc_info = NULL;
+ kfree(gc_i);
+ }
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 8e608a0..65feb4b 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -26,7 +26,6 @@
+ #include "xattr.h"
+
+ static struct kmem_cache *f2fs_inode_cachep;
+-static struct proc_dir_entry *f2fs_proc_root;
+
+ enum {
+ Opt_gc_background_off,
+@@ -97,12 +96,7 @@ static void f2fs_put_super(struct super_block *sb)
+ {
+ struct f2fs_sb_info *sbi = F2FS_SB(sb);
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- if (sbi->s_proc) {
+- f2fs_stat_exit(sbi);
+- remove_proc_entry(sb->s_id, f2fs_proc_root);
+- }
+-#endif
++ f2fs_stat_exit(sb, sbi);
+ stop_gc_thread(sbi);
+
+ write_checkpoint(sbi, false, true);
+@@ -486,13 +480,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
+ if (start_gc_thread(sbi))
+ goto fail;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- if (f2fs_proc_root) {
+- sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
+- if (f2fs_stat_init(sbi))
+- goto fail;
+- }
+-#endif
++ if (f2fs_stat_init(sb, sbi))
++ goto fail;
++
+ return 0;
+ fail:
+ stop_gc_thread(sbi);
+@@ -566,7 +556,6 @@ static int __init init_f2fs_fs(void)
+ if (register_filesystem(&f2fs_fs_type))
+ return -EBUSY;
+
+- f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
+ return 0;
+ fail:
+ return -ENOMEM;
+@@ -574,7 +563,7 @@ fail:
+
+ static void __exit exit_f2fs_fs(void)
+ {
+- remove_proc_entry("fs/f2fs", NULL);
++ f2fs_remove_stats();
+ unregister_filesystem(&f2fs_fs_type);
+ destroy_checkpoint_caches();
+ destroy_gc_caches();
diff --git a/patches/linux-3.7-rc6/0116-f2fs-move-proc-files-to-debugfs.patch b/patches/linux-3.7-rc6/0116-f2fs-move-proc-files-to-debugfs.patch
new file mode 100644
index 0000000..aa87b59
--- /dev/null
+++ b/patches/linux-3.7-rc6/0116-f2fs-move-proc-files-to-debugfs.patch
@@ -0,0 +1,449 @@
+From 205e2ea14ae2f19cae72407e023d736c5c781027 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Tue, 23 Oct 2012 19:20:28 +0000
+Subject: [PATCH] f2fs: move proc files to debugfs
+
+This moves all of the f2fs debugging files into debugfs. The files are
+located in /sys/kernel/debug/f2fs/
+
+Note, I think we are generating all of the same information in each of
+the files for every unique f2fs filesystem in the machine. This copies
+the functionality that was present in the proc files, but this should be
+fixed up in the future.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/Kconfig | 8 +-
+ fs/f2fs/debug.c | 294 ++++++++++++++++++++++++++++++-------------------------
+ fs/f2fs/f2fs.h | 2 +-
+ 3 files changed, 165 insertions(+), 139 deletions(-)
+
+diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
+index 8821c6a..dd181c6 100644
+--- a/fs/f2fs/Kconfig
++++ b/fs/f2fs/Kconfig
+@@ -16,18 +16,18 @@ config F2FS_FS
+
+ config F2FS_STAT_FS
+ bool "F2FS Status Information"
+- depends on F2FS_FS
++ depends on F2FS_FS && DEBUG_FS
+ default y
+ help
+- /proc/fs/f2fs/ contains information about partitions mounted as f2fs.
++ /sys/kernel/debug/f2fs/ contains information about partitions mounted as f2fs.
+ For each partition, a corresponding directory, named as its device
+- name, is provided with the following proc entries.
++ name, is provided with the following files:
+
+ f2fs_stat major file system information managed by f2fs currently
+ f2fs_sit_stat average SIT information about whole segments
+ f2fs_mem_stat current memory footprint consumed by f2fs
+
+- e.g., in /proc/fs/f2fs/sdb1/
++ e.g., in /sys/kernel/debug/f2fs/sdb1/
+
+ config F2FS_FS_XATTR
+ bool "F2FS extended attributes"
+diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
+index 0145b02..ec5beba 100644
+--- a/fs/f2fs/debug.c
++++ b/fs/f2fs/debug.c
+@@ -16,6 +16,8 @@
+ #include <linux/proc_fs.h>
+ #include <linux/f2fs_fs.h>
+ #include <linux/blkdev.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
+
+ #include "f2fs.h"
+ #include "node.h"
+@@ -23,7 +25,7 @@
+ #include "gc.h"
+
+ static LIST_HEAD(f2fs_stat_list);
+-static struct proc_dir_entry *f2fs_proc_root;
++static struct dentry *debugfs_root;
+
+
+ void f2fs_update_stat(struct f2fs_sb_info *sbi)
+@@ -114,16 +116,14 @@ static void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
+ si->avg_vblocks = 0;
+ }
+
+-static int f2fs_read_gc(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++static int stat_show(struct seq_file *s, void *v)
+ {
+ struct f2fs_gc_info *gc_i, *next;
+ struct f2fs_stat_info *si;
+- char *buf = page;
+ int i = 0;
++ int j;
+
+ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- int j;
+ si = gc_i->stat_info;
+
+ mutex_lock(&si->stat_list);
+@@ -133,102 +133,111 @@ static int f2fs_read_gc(char *page, char **start, off_t off,
+ }
+ f2fs_update_stat(si->sbi);
+
+- buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
+- buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
+- si->nat_area_segs, si->sit_area_segs);
+- buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
+- si->ssa_area_segs, si->main_area_segs);
+- buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
+- si->overp_segs, si->rsvd_segs);
+- buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
+- si->utilization, si->valid_count);
+- buf += sprintf(buf, " - Node: %u (Inode: %u, ",
+- si->valid_node_count, si->valid_inode_count);
+- buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
+- si->valid_node_count - si->valid_inode_count,
+- si->valid_count - si->valid_node_count);
+- buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
+- si->main_area_segs, si->main_area_sections,
+- si->main_area_zones);
+- buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_DATA],
+- si->cursec[CURSEG_COLD_DATA],
+- si->curzone[CURSEG_COLD_DATA]);
+- buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_DATA],
+- si->cursec[CURSEG_WARM_DATA],
+- si->curzone[CURSEG_WARM_DATA]);
+- buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_DATA],
+- si->cursec[CURSEG_HOT_DATA],
+- si->curzone[CURSEG_HOT_DATA]);
+- buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_NODE],
+- si->cursec[CURSEG_HOT_NODE],
+- si->curzone[CURSEG_HOT_NODE]);
+- buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_NODE],
+- si->cursec[CURSEG_WARM_NODE],
+- si->curzone[CURSEG_WARM_NODE]);
+- buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_NODE],
+- si->cursec[CURSEG_COLD_NODE],
+- si->curzone[CURSEG_COLD_NODE]);
+- buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
+- si->main_area_segs - si->dirty_count -
+- si->prefree_count - si->free_segs,
+- si->dirty_count);
+- buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
+- si->prefree_count,
+- si->free_segs,
+- si->free_secs);
+- buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
+- si->call_count, si->bg_gc);
+- buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
+- buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
+- buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
+- buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
+- buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
+- buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
+- si->hit_ext, si->total_ext);
+- buf += sprintf(buf, "\nBalancing F2FS Async:\n");
+- buf += sprintf(buf, " - nodes %4d in %4d\n",
+- si->ndirty_node, si->node_pages);
+- buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
+- si->ndirty_dent, si->ndirty_dirs);
+- buf += sprintf(buf, " - meta %4d in %4d\n",
+- si->ndirty_meta, si->meta_pages);
+- buf += sprintf(buf, " - NATs %5d > %lu\n",
+- si->nats, NM_WOUT_THRESHOLD);
+- buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
+- si->sits, si->fnids);
+- buf += sprintf(buf, "\nDistribution of User Blocks:");
+- buf += sprintf(buf, " [ valid | invalid | free ]\n");
+- buf += sprintf(buf, " [");
++ seq_printf(s, "=====[ partition info. #%d ]=====\n", i++);
++ seq_printf(s, "=====[ partition info. #%d ]=====\n", i++);
++ seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
++ si->nat_area_segs, si->sit_area_segs);
++ seq_printf(s, "[SSA: %d] [MAIN: %d",
++ si->ssa_area_segs, si->main_area_segs);
++ seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
++ si->overp_segs, si->rsvd_segs);
++ seq_printf(s, "Utilization: %d%% (%d valid blocks)\n",
++ si->utilization, si->valid_count);
++ seq_printf(s, " - Node: %u (Inode: %u, ",
++ si->valid_node_count, si->valid_inode_count);
++ seq_printf(s, "Other: %u)\n - Data: %u\n",
++ si->valid_node_count - si->valid_inode_count,
++ si->valid_count - si->valid_node_count);
++ seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
++ si->main_area_segs, si->main_area_sections,
++ si->main_area_zones);
++ seq_printf(s, " - COLD data: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_DATA],
++ si->cursec[CURSEG_COLD_DATA],
++ si->curzone[CURSEG_COLD_DATA]);
++ seq_printf(s, " - WARM data: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_DATA],
++ si->cursec[CURSEG_WARM_DATA],
++ si->curzone[CURSEG_WARM_DATA]);
++ seq_printf(s, " - HOT data: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_DATA],
++ si->cursec[CURSEG_HOT_DATA],
++ si->curzone[CURSEG_HOT_DATA]);
++ seq_printf(s, " - Dir dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_NODE],
++ si->cursec[CURSEG_HOT_NODE],
++ si->curzone[CURSEG_HOT_NODE]);
++ seq_printf(s, " - File dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_NODE],
++ si->cursec[CURSEG_WARM_NODE],
++ si->curzone[CURSEG_WARM_NODE]);
++ seq_printf(s, " - Indir nodes: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_NODE],
++ si->cursec[CURSEG_COLD_NODE],
++ si->curzone[CURSEG_COLD_NODE]);
++ seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n",
++ si->main_area_segs - si->dirty_count -
++ si->prefree_count - si->free_segs,
++ si->dirty_count);
++ seq_printf(s, " - Prefree: %d\n - Free: %d (%d)\n\n",
++ si->prefree_count, si->free_segs, si->free_secs);
++ seq_printf(s, "GC calls: %d (BG: %d)\n",
++ si->call_count, si->bg_gc);
++ seq_printf(s, " - data segments : %d\n", si->data_segs);
++ seq_printf(s, " - node segments : %d\n", si->node_segs);
++ seq_printf(s, "Try to move %d blocks\n", si->tot_blks);
++ seq_printf(s, " - data blocks : %d\n", si->data_blks);
++ seq_printf(s, " - node blocks : %d\n", si->node_blks);
++ seq_printf(s, "\nExtent Hit Ratio: %d / %d\n",
++ si->hit_ext, si->total_ext);
++ seq_printf(s, "\nBalancing F2FS Async:\n");
++ seq_printf(s, " - nodes %4d in %4d\n",
++ si->ndirty_node, si->node_pages);
++ seq_printf(s, " - dents %4d in dirs:%4d\n",
++ si->ndirty_dent, si->ndirty_dirs);
++ seq_printf(s, " - meta %4d in %4d\n",
++ si->ndirty_meta, si->meta_pages);
++ seq_printf(s, " - NATs %5d > %lu\n",
++ si->nats, NM_WOUT_THRESHOLD);
++ seq_printf(s, " - SITs: %5d\n - free_nids: %5d\n",
++ si->sits, si->fnids);
++ seq_printf(s, "\nDistribution of User Blocks:");
++ seq_printf(s, " [ valid | invalid | free ]\n");
++ seq_printf(s, " [");
+ for (j = 0; j < si->util_valid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
++ seq_printf(s, "-");
++ seq_printf(s, "|");
+ for (j = 0; j < si->util_invalid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
++ seq_printf(s, "-");
++ seq_printf(s, "|");
+ for (j = 0; j < si->util_free; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "]\n\n");
+- buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
+- si->block_count[SSR], si->segment_count[SSR]);
+- buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
+- si->block_count[LFS], si->segment_count[LFS]);
++ seq_printf(s, "-");
++ seq_printf(s, "]\n\n");
++ seq_printf(s, "SSR: %u blocks in %u segments\n",
++ si->block_count[SSR], si->segment_count[SSR]);
++ seq_printf(s, "LFS: %u blocks in %u segments\n",
++ si->block_count[LFS], si->segment_count[LFS]);
+ mutex_unlock(&si->stat_list);
+ }
+- return buf - page;
++ return 0;
+ }
+
+-static int f2fs_read_sit(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++static int stat_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, stat_show, inode->i_private);
++}
++
++static const struct file_operations stat_fops = {
++ .open = stat_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int sit_show(struct seq_file *s, void *v)
+ {
+ struct f2fs_gc_info *gc_i, *next;
+ struct f2fs_stat_info *si;
+- char *buf = page;
+
+ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+ si = gc_i->stat_info;
+@@ -240,19 +249,29 @@ static int f2fs_read_sit(char *page, char **start, off_t off,
+ }
+ f2fs_update_gc_metric(si->sbi);
+
+- buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
+- si->bimodal, si->avg_vblocks);
++ seq_printf(s, "BDF: %u, avg. vblocks: %u\n",
++ si->bimodal, si->avg_vblocks);
+ mutex_unlock(&si->stat_list);
+ }
+- return buf - page;
++ return 0;
++}
++
++static int sit_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, sit_show, inode->i_private);
+ }
+
+-static int f2fs_read_mem(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++static const struct file_operations sit_fops = {
++ .open = sit_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int mem_show(struct seq_file *s, void *v)
+ {
+ struct f2fs_gc_info *gc_i, *next;
+ struct f2fs_stat_info *si;
+- char *buf = page;
+
+ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+ struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
+@@ -314,15 +333,27 @@ static int f2fs_read_mem(char *page, char **start, off_t off,
+ cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
+ cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
+
+- buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
+- (base_mem + cache_mem) >> 10,
+- base_mem >> 10,
+- cache_mem >> 10);
++ seq_printf(s, "%u KB = static: %u + cached: %u\n",
++ (base_mem + cache_mem) >> 10,
++ base_mem >> 10, cache_mem >> 10);
+ mutex_unlock(&si->stat_list);
+ }
+- return buf - page;
++ return 0;
++}
++
++static int mem_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, mem_show, inode->i_private);
+ }
+
++static const struct file_operations mem_fops = {
++ .open = mem_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++
+ static int init_stats(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_stat_info *si;
+@@ -362,53 +393,48 @@ void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i)
+
+ int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *sbi)
+ {
+- struct proc_dir_entry *entry;
+ int retval;
+
+- if (!f2fs_proc_root)
+- f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
+-
+- sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
+-
+ retval = init_stats(sbi);
+ if (retval)
+ return retval;
+
+- entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
+- if (!entry)
+- return -ENOMEM;
+- entry->read_proc = f2fs_read_gc;
+- entry->write_proc = NULL;
++ if (!debugfs_root)
++ debugfs_root = debugfs_create_dir("f2fs", NULL);
++
++ sbi->s_debug = debugfs_create_dir(sb->s_id, debugfs_root);
++ if (!sbi->s_debug)
++ return -EINVAL;
++
++ if (!debugfs_create_file("f2fs_stat", S_IRUGO, sbi->s_debug,
++ NULL, &stat_fops))
++ goto failed;
++
++ if (!debugfs_create_file("f2fs_sit_stat", S_IRUGO, sbi->s_debug,
++ NULL, &sit_fops))
++ goto failed;
++
++ if (!debugfs_create_file("f2fs_mem_stat", S_IRUGO, sbi->s_debug,
++ NULL, &mem_fops))
++ goto failed;
+
+- entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_sit;
+- entry->write_proc = NULL;
+- entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_mem;
+- entry->write_proc = NULL;
+ return 0;
++failed:
++ debugfs_remove_recursive(sbi->s_debug);
++ sbi->s_debug = NULL;
++ return -EINVAL;
+ }
+
+ void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *sbi)
+ {
+- if (sbi->s_proc) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
+- remove_proc_entry(sb->s_id, f2fs_proc_root);
++ if (sbi->s_debug) {
++ debugfs_remove_recursive(sbi->s_debug);
++ sbi->s_debug = NULL;
+ }
+ }
+
+ void f2fs_remove_stats(void)
+ {
+- remove_proc_entry("fs/f2fs", NULL);
++ debugfs_remove_recursive(debugfs_root);
++ debugfs_root = NULL;
+ }
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 7f508b2..dc8045c 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -379,7 +379,7 @@ struct f2fs_sb_info {
+ int rr_flush;
+
+ /* related to GC */
+- struct proc_dir_entry *s_proc;
++ struct dentry *s_debug;
+ struct f2fs_gc_info *gc_info; /* Garbage Collector
+ information */
+ struct mutex gc_mutex; /* mutex for GC */
diff --git a/patches/linux-3.7-rc6/0117-f2fs-compile-fix.patch b/patches/linux-3.7-rc6/0117-f2fs-compile-fix.patch
new file mode 100644
index 0000000..d93a4ea
--- /dev/null
+++ b/patches/linux-3.7-rc6/0117-f2fs-compile-fix.patch
@@ -0,0 +1,22 @@
+From 7988df6c5e0a9d19cbe68831a9e1ce11e85e35ad Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 24 Oct 2012 11:34:54 +0200
+Subject: [PATCH] f2fs: compile fix
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ fs/f2fs/segment.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 57d0931..5bab838 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -12,6 +12,7 @@
+ #include <linux/f2fs_fs.h>
+ #include <linux/bio.h>
+ #include <linux/blkdev.h>
++#include <linux/vmalloc.h>
+
+ #include "f2fs.h"
+ #include "segment.h"
diff --git a/patches/linux-3.7-rc6/0119-i2c-EEPROM-Export-memory-accessor.patch b/patches/linux-3.7-rc6/0119-i2c-EEPROM-Export-memory-accessor.patch
new file mode 100644
index 0000000..dc19a4a
--- /dev/null
+++ b/patches/linux-3.7-rc6/0119-i2c-EEPROM-Export-memory-accessor.patch
@@ -0,0 +1,89 @@
+From d13ed856c7be4d21b920a440f1784e3c13752954 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:06:48 +0300
+Subject: [PATCH] i2c-EEPROM: Export memory accessor
+
+Various platforms need access to the EEPROM in other
+places besides their platform registration callbacks.
+Export the memory accessor to the i2c_client and implement
+it for the at24 driver.
+---
+ drivers/misc/eeprom/at24.c | 5 +++++
+ include/linux/i2c.h | 24 ++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
+index ab1ad41..4f88ae65 100644
+--- a/drivers/misc/eeprom/at24.c
++++ b/drivers/misc/eeprom/at24.c
+@@ -609,6 +609,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+
+ at24->client[0] = client;
+
++ /* export accessor */
++ client->macc = &at24->macc;
++
+ /* use dummy devices for multiple-address chips */
+ for (i = 1; i < num_addresses; i++) {
+ at24->client[i] = i2c_new_dummy(client->adapter,
+@@ -619,6 +622,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ err = -EADDRINUSE;
+ goto err_clients;
+ }
++ at24->client[i]->macc = &at24->macc;
+ }
+
+ err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
+@@ -637,6 +641,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ I2C_SMBUS_WORD_DATA ? "word" : "byte");
+ }
+
++
+ /* export data to kernel code */
+ if (chip.setup)
+ chip.setup(&at24->macc, chip.context);
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+index 800de22..e20ad4e 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -33,6 +33,7 @@
+ #include <linux/of.h> /* for struct device_node */
+ #include <linux/swab.h> /* for swab16 */
+ #include <uapi/linux/i2c.h>
++#include <linux/memory.h>
+
+ extern struct bus_type i2c_bus_type;
+ extern struct device_type i2c_adapter_type;
+@@ -229,9 +230,32 @@ struct i2c_client {
+ struct device dev; /* the device structure */
+ int irq; /* irq issued by device */
+ struct list_head detected;
++
++ /* export accessor */
++ struct memory_accessor *macc;
+ };
+ #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
+
++static inline ssize_t i2c_memory_read(struct i2c_client *client, char *buf, off_t offset,
++ size_t count)
++{
++ struct memory_accessor *macc = client->macc;
++
++ if (macc == NULL || macc->read == NULL)
++ return -ENODEV;
++ return (*client->macc->read)(macc, buf, offset, count);
++}
++
++static inline ssize_t i2c_memory_write(struct i2c_client *client, const char *buf, off_t offset,
++ size_t count)
++{
++ struct memory_accessor *macc = client->macc;
++
++ if (macc == NULL || macc->write == NULL)
++ return -ENODEV;
++ return (*client->macc->write)(macc, buf, offset, count);
++}
++
+ extern struct i2c_client *i2c_verify_client(struct device *dev);
+ extern struct i2c_adapter *i2c_verify_adapter(struct device *dev);
+
diff --git a/patches/linux-3.7-rc6/0120-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch b/patches/linux-3.7-rc6/0120-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch
new file mode 100644
index 0000000..854ce11
--- /dev/null
+++ b/patches/linux-3.7-rc6/0120-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch
@@ -0,0 +1,71 @@
+From 1222463525efa67a795b293e46429f510768a2df Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:34:44 +0300
+Subject: [PATCH] omap: Export
+ omap_hwmod_lookup/omap_device_build/omap_device_build_ss
+
+These functions can be used just fine by modules, there's no need not
+to have them exported.
+---
+ arch/arm/mach-omap2/omap_hwmod.c | 2 ++
+ arch/arm/plat-omap/omap_device.c | 6 ++++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
+index 87cc6d0..f3c0947 100644
+--- a/arch/arm/mach-omap2/omap_hwmod.c
++++ b/arch/arm/mach-omap2/omap_hwmod.c
+@@ -138,6 +138,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/slab.h>
+ #include <linux/bootmem.h>
++#include <linux/export.h>
+
+ #include <plat/clock.h>
+ #include <plat/omap_hwmod.h>
+@@ -3076,6 +3077,7 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name)
+
+ return oh;
+ }
++EXPORT_SYMBOL(omap_hwmod_lookup);
+
+ /**
+ * omap_hwmod_for_each - call function for each registered omap_hwmod
+diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
+index 7a7d1f2..a15b715 100644
+--- a/arch/arm/plat-omap/omap_device.c
++++ b/arch/arm/plat-omap/omap_device.c
+@@ -663,7 +663,7 @@ void omap_device_delete(struct omap_device *od)
+ * information. Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
+ * passes along the return value of omap_device_build_ss().
+ */
+-struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id,
++struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
+ struct omap_hwmod *oh, void *pdata,
+ int pdata_len,
+ struct omap_device_pm_latency *pm_lats,
+@@ -678,6 +678,7 @@ struct platform_device __init *omap_device_build(const char *pdev_name, int pdev
+ pdata_len, pm_lats, pm_lats_cnt,
+ is_early_device);
+ }
++EXPORT_SYMBOL(omap_device_build);
+
+ /**
+ * omap_device_build_ss - build and register an omap_device with multiple hwmods
+@@ -696,7 +697,7 @@ struct platform_device __init *omap_device_build(const char *pdev_name, int pdev
+ * platform_device record. Returns an ERR_PTR() on error, or passes
+ * along the return value of omap_device_register().
+ */
+-struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id,
++struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+ struct omap_hwmod **ohs, int oh_cnt,
+ void *pdata, int pdata_len,
+ struct omap_device_pm_latency *pm_lats,
+@@ -751,6 +752,7 @@ odbs_exit:
+
+ return ERR_PTR(ret);
+ }
++EXPORT_SYMBOL(omap_device_build_ss);
+
+ /**
+ * omap_early_device_register - register an omap_device as an early platform
diff --git a/patches/linux-3.7-rc6/0121-gpio-keys-Pinctrl-fy.patch b/patches/linux-3.7-rc6/0121-gpio-keys-Pinctrl-fy.patch
new file mode 100644
index 0000000..3cf53f7
--- /dev/null
+++ b/patches/linux-3.7-rc6/0121-gpio-keys-Pinctrl-fy.patch
@@ -0,0 +1,40 @@
+From ae6cef3b75d1ab9a32fdd95d7a9ed516aa587972 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 17 Oct 2012 20:17:36 +0300
+Subject: [PATCH] gpio-keys: Pinctrl-fy
+
+---
+ drivers/input/keyboard/gpio_keys.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 6a68041..e421082 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -29,6 +29,7 @@
+ #include <linux/of_platform.h>
+ #include <linux/of_gpio.h>
+ #include <linux/spinlock.h>
++#include <linux/pinctrl/consumer.h>
+
+ struct gpio_button_data {
+ const struct gpio_keys_button *button;
+@@ -666,6 +667,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
+ struct input_dev *input;
+ int i, error;
+ int wakeup = 0;
++ struct pinctrl *pinctrl;
+
+ if (!pdata) {
+ pdata = gpio_keys_get_devtree_pdata(dev);
+@@ -731,6 +733,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
+ goto fail3;
+ }
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ /* get current state of buttons that are connected to GPIOs */
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_button_data *bdata = &ddata->data[i];
diff --git a/patches/linux-3.7-rc6/0122-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch b/patches/linux-3.7-rc6/0122-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
new file mode 100644
index 0000000..bdf9716
--- /dev/null
+++ b/patches/linux-3.7-rc6/0122-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
@@ -0,0 +1,195 @@
+From 60b3cfc365647a38b67719be3a134c392f1f6fe6 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 17 Oct 2012 20:17:57 +0300
+Subject: [PATCH] tps65217: Allow placement elsewhere than parent mfd device.
+
+The current code expect the configuration of the backlight to stay
+constant after initialization. This patch allows to move it around.
+---
+ drivers/video/backlight/tps65217_bl.c | 103 +++++++++++++++++++++++++++++----
+ 1 file changed, 92 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
+index 7088163..69c1dfe 100644
+--- a/drivers/video/backlight/tps65217_bl.c
++++ b/drivers/video/backlight/tps65217_bl.c
+@@ -24,8 +24,11 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/of_i2c.h>
+
+ struct tps65217_bl {
++ struct i2c_client *i2c_client;
+ struct tps65217 *tps;
+ struct device *dev;
+ struct backlight_device *bl;
+@@ -98,8 +101,6 @@ static int tps65217_bl_update_status(struct backlight_device *bl)
+ return rc;
+ }
+
+- dev_dbg(tps65217_bl->dev, "brightness set to %d\n", brightness);
+-
+ if (!tps65217_bl->is_enabled)
+ rc = tps65217_bl_enable(tps65217_bl);
+ } else {
+@@ -187,14 +188,69 @@ static int tps65217_bl_hw_init(struct tps65217_bl *tps65217_bl,
+
+ #ifdef CONFIG_OF
+ static struct tps65217_bl_pdata *
+-tps65217_bl_parse_dt(struct platform_device *pdev)
++tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
++ int *brightnessp)
+ {
+- struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+- struct device_node *node = of_node_get(tps->dev->of_node);
++ struct i2c_client *i2c_client;
++ struct tps65217 *tps;
++ struct device_node *node, *rnode, *pnode;
+ struct tps65217_bl_pdata *pdata, *err;
++ u32 tps_handle;
+ u32 val;
+
+- node = of_find_node_by_name(node, "backlight");
++ tps = NULL;
++ node = NULL;
++ *brightnessp = 0;
++
++ /* our node (compatible) */
++ pnode = pdev->dev.of_node;
++ if (pnode != NULL &&
++ of_property_read_u32(pnode, "tps", &tps_handle) == 0) {
++ /* we are not instantiated from the mfd */
++ node = of_find_node_by_phandle(tps_handle);
++ if (node == NULL) {
++ dev_err(&pdev->dev, "failed to find the tps node\n");
++ err = ERR_PTR(-EINVAL);
++ goto err;
++ }
++ i2c_client = of_find_i2c_device_by_node(node);
++ if (i2c_client == NULL) {
++ dev_err(&pdev->dev, "failed to find the i2c device "
++ "of tps node\n");
++ err = ERR_PTR(-EINVAL);
++ goto err;
++ }
++ /* yeah this is gross; the whole concept is */
++ tps = i2c_get_clientdata(i2c_client);
++ if (tps == NULL) {
++ dev_err(&pdev->dev, "failed to get tps structure\n");
++ err = ERR_PTR(-EINVAL);
++ goto err;
++ }
++
++ /* read default brightness */
++ val = 0;
++ of_property_read_u32(pnode, "brightness", &val);
++ if (val >= 100)
++ val = 100;
++
++ *brightnessp = val;
++
++ /* no need for this anymore */
++ of_node_put(node);
++
++ dev_info(&pdev->dev, "got tps=%p from handle 0x%x\n", tps, tps_handle);
++ }
++
++ if (tps == NULL)
++ tps = dev_get_drvdata(pdev->dev.parent);
++
++ rnode = of_node_get(tps->dev->of_node);
++
++ node = of_find_node_by_name(rnode, "backlight");
++ of_node_put(rnode);
++ rnode = NULL;
++
+ if (!node)
+ return ERR_PTR(-ENODEV);
+
+@@ -247,6 +303,7 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
+
+ of_node_put(node);
+
++ *tpsp = tps;
+ return pdata;
+
+ err:
+@@ -254,9 +311,16 @@ err:
+
+ return err;
+ }
++
++static struct of_device_id tps65217_backlight_of_match[] = {
++ { .compatible = "tps65217-backlight" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, tps65217_backlight_of_match);
+ #else
+ static struct tps65217_bl_pdata *
+-tps65217_bl_parse_dt(struct platform_device *pdev)
++tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
++ int *brightnessp)
+ {
+ return NULL;
+ }
+@@ -265,13 +329,16 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
+ static int tps65217_bl_probe(struct platform_device *pdev)
+ {
+ int rc;
+- struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
++ struct tps65217 *tps;
+ struct tps65217_bl *tps65217_bl;
+ struct tps65217_bl_pdata *pdata;
+ struct backlight_properties bl_props;
++ int brightness = 0;
+
+- if (tps->dev->of_node) {
+- pdata = tps65217_bl_parse_dt(pdev);
++ tps = NULL;
++
++ if (pdev->dev.of_node) {
++ pdata = tps65217_bl_parse_dt(pdev, &tps, &brightness);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ } else {
+@@ -281,6 +348,14 @@ static int tps65217_bl_probe(struct platform_device *pdev)
+ }
+
+ pdata = pdev->dev.platform_data;
++
++ /* get the parent device */
++ tps = dev_get_drvdata(pdev->dev.parent);
++ }
++
++ if (tps == NULL) {
++ dev_err(&pdev->dev, "failed to find tps\n");
++ return -EINVAL;
+ }
+
+ tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
+@@ -311,9 +386,14 @@ static int tps65217_bl_probe(struct platform_device *pdev)
+ return PTR_ERR(tps65217_bl->bl);
+ }
+
+- tps65217_bl->bl->props.brightness = 0;
++ tps65217_bl->bl->props.brightness = brightness;
+ platform_set_drvdata(pdev, tps65217_bl);
+
++ /* update with initial settings */
++ tps65217_bl_update_status(tps65217_bl->bl);
++
++ dev_info(&pdev->dev, "OK.\n");
++
+ return 0;
+ }
+
+@@ -332,6 +412,7 @@ static struct platform_driver tps65217_bl_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tps65217-bl",
++ .of_match_table = of_match_ptr(tps65217_backlight_of_match),
+ },
+ };
+
diff --git a/patches/linux-3.7-rc6/0123-pwm-export-of_pwm_request.patch b/patches/linux-3.7-rc6/0123-pwm-export-of_pwm_request.patch
new file mode 100644
index 0000000..2223575
--- /dev/null
+++ b/patches/linux-3.7-rc6/0123-pwm-export-of_pwm_request.patch
@@ -0,0 +1,67 @@
+From fbcf0d6f0fb39e6d70d41f32844a9c13622010ea Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 19 Oct 2012 10:38:00 +0300
+Subject: [PATCH] pwm: export of_pwm_request
+
+No need to hide this, it's useful.
+---
+ drivers/pwm/core.c | 6 +++++-
+ include/linux/pwm.h | 7 +++++++
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
+index f5acdaa..f8c7e6b 100644
+--- a/drivers/pwm/core.c
++++ b/drivers/pwm/core.c
+@@ -457,7 +457,7 @@ static struct pwm_chip *of_node_to_pwmchip(struct device_node *np)
+ * becomes mandatory for devices that look up the PWM device via the con_id
+ * parameter.
+ */
+-static struct pwm_device *of_pwm_request(struct device_node *np,
++struct pwm_device *of_pwm_request(struct device_node *np,
+ const char *con_id)
+ {
+ struct pwm_device *pwm = NULL;
+@@ -466,6 +466,9 @@ static struct pwm_device *of_pwm_request(struct device_node *np,
+ int index = 0;
+ int err;
+
++ if (!np)
++ return ERR_PTR(-ENODEV);
++
+ if (con_id) {
+ index = of_property_match_string(np, "pwm-names", con_id);
+ if (index < 0)
+@@ -516,6 +519,7 @@ put:
+
+ return pwm;
+ }
++EXPORT_SYMBOL(of_pwm_request);
+
+ /**
+ * pwm_add_table() - register PWM device consumers
+diff --git a/include/linux/pwm.h b/include/linux/pwm.h
+index 112b314..fafbb1c 100644
+--- a/include/linux/pwm.h
++++ b/include/linux/pwm.h
+@@ -171,6 +171,7 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ unsigned int index,
+ const char *label);
+
++struct pwm_device *of_pwm_request(struct device_node *np, const char *consumer);
+ struct pwm_device *pwm_get(struct device *dev, const char *consumer);
+ void pwm_put(struct pwm_device *pwm);
+
+@@ -204,6 +205,12 @@ static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ return ERR_PTR(-ENODEV);
+ }
+
++static inline struct pwm_device *of_pwm_request(struct device_node *np,
++ const char *consumer)
++{
++ return ERR_PTR(-ENODEV);
++}
++
+ static inline struct pwm_device *pwm_get(struct device *dev,
+ const char *consumer)
+ {
diff --git a/patches/linux-3.7-rc6/0124-i2c-Export-capability-to-probe-devices.patch b/patches/linux-3.7-rc6/0124-i2c-Export-capability-to-probe-devices.patch
new file mode 100644
index 0000000..d72b464
--- /dev/null
+++ b/patches/linux-3.7-rc6/0124-i2c-Export-capability-to-probe-devices.patch
@@ -0,0 +1,65 @@
+From b431efb8fef34dc5ea688fcf98851f4a2d42ef72 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 20 Oct 2012 14:08:17 +0300
+Subject: [PATCH] i2c: Export capability to probe devices
+
+Probe devices for a node other that the adapter node.
+---
+ drivers/of/of_i2c.c | 14 ++++++++++----
+ include/linux/of_i2c.h | 3 +++
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
+index 3550f3b..7f36b05 100644
+--- a/drivers/of/of_i2c.c
++++ b/drivers/of/of_i2c.c
+@@ -18,18 +18,18 @@
+ #include <linux/of_irq.h>
+ #include <linux/module.h>
+
+-void of_i2c_register_devices(struct i2c_adapter *adap)
++void of_i2c_register_node_devices(struct i2c_adapter *adap,
++ struct device_node *parent_node)
+ {
+ void *result;
+ struct device_node *node;
+
+- /* Only register child devices if the adapter has a node pointer set */
+- if (!adap->dev.of_node)
++ if (!parent_node)
+ return;
+
+ dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
+
+- for_each_child_of_node(adap->dev.of_node, node) {
++ for_each_child_of_node(parent_node, node) {
+ struct i2c_board_info info = {};
+ struct dev_archdata dev_ad = {};
+ const __be32 *addr;
+@@ -76,6 +76,12 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
+ }
+ }
+ }
++EXPORT_SYMBOL(of_i2c_register_node_devices);
++
++void of_i2c_register_devices(struct i2c_adapter *adap)
++{
++ of_i2c_register_node_devices(adap, adap->dev.of_node);
++}
+ EXPORT_SYMBOL(of_i2c_register_devices);
+
+ static int of_dev_node_match(struct device *dev, void *data)
+diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h
+index 1cb775f..d2f8ebb6 100644
+--- a/include/linux/of_i2c.h
++++ b/include/linux/of_i2c.h
+@@ -15,6 +15,9 @@
+ #if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE)
+ #include <linux/i2c.h>
+
++extern void of_i2c_register_node_devices(struct i2c_adapter *adap,
++ struct device_node *parent_node);
++
+ extern void of_i2c_register_devices(struct i2c_adapter *adap);
+
+ /* must call put_device() when done with returned i2c_client device */
diff --git a/patches/linux-3.7-rc6/0125-pwm-backlight-Pinctrl-fy.patch b/patches/linux-3.7-rc6/0125-pwm-backlight-Pinctrl-fy.patch
new file mode 100644
index 0000000..ccf1ddc
--- /dev/null
+++ b/patches/linux-3.7-rc6/0125-pwm-backlight-Pinctrl-fy.patch
@@ -0,0 +1,37 @@
+From cd1f5ff870b0977e4d6a4454c2758806f5f524c2 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 23 Oct 2012 11:48:58 +0300
+Subject: [PATCH] pwm-backlight: Pinctrl-fy
+
+---
+ drivers/video/backlight/pwm_bl.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
+index 0c91023..f3b6194 100644
+--- a/drivers/video/backlight/pwm_bl.c
++++ b/drivers/video/backlight/pwm_bl.c
+@@ -20,6 +20,8 @@
+ #include <linux/pwm.h>
+ #include <linux/pwm_backlight.h>
+ #include <linux/slab.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ struct pwm_bl_data {
+ struct pwm_device *pwm;
+@@ -180,9 +182,14 @@ static int pwm_backlight_probe(struct platform_device *pdev)
+ struct backlight_properties props;
+ struct backlight_device *bl;
+ struct pwm_bl_data *pb;
++ struct pinctrl *pinctrl;
+ unsigned int max;
+ int ret;
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ if (!data) {
+ ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
+ if (ret < 0) {
diff --git a/patches/linux-3.7-rc6/0126-spi-Export-OF-interfaces-for-capebus-use.patch b/patches/linux-3.7-rc6/0126-spi-Export-OF-interfaces-for-capebus-use.patch
new file mode 100644
index 0000000..deac5fc
--- /dev/null
+++ b/patches/linux-3.7-rc6/0126-spi-Export-OF-interfaces-for-capebus-use.patch
@@ -0,0 +1,119 @@
+From 0f227d7527b91f7c3536842549fc8de50c16b956 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 23 Oct 2012 13:23:14 +0300
+Subject: [PATCH] spi: Export OF interfaces for capebus use.
+
+---
+ drivers/spi/spi.c | 31 +++++++++++++++++++++++--------
+ include/linux/spi/spi.h | 18 ++++++++++++++++++
+ 2 files changed, 41 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 84c2861..f8de2f2 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -801,14 +801,17 @@ err_init_queue:
+ /*-------------------------------------------------------------------------*/
+
+ #if defined(CONFIG_OF) && !defined(CONFIG_SPARC)
++
+ /**
+- * of_register_spi_devices() - Register child devices onto the SPI bus
++ * of_register_node_spi_devices() - Register child devices onto the SPI bus
+ * @master: Pointer to spi_master device
++ * @parent_node: Pointer to the device node containg the devices
+ *
+ * Registers an spi_device for each child node of master node which has a 'reg'
+ * property.
+ */
+-static void of_register_spi_devices(struct spi_master *master)
++void of_register_node_spi_devices(struct spi_master *master,
++ struct device_node *parent_node)
+ {
+ struct spi_device *spi;
+ struct device_node *nc;
+@@ -816,10 +819,10 @@ static void of_register_spi_devices(struct spi_master *master)
+ int rc;
+ int len;
+
+- if (!master->dev.of_node)
++ if (!parent_node)
+ return;
+
+- for_each_child_of_node(master->dev.of_node, nc) {
++ for_each_child_of_node(parent_node, nc) {
+ /* Alloc an spi_device */
+ spi = spi_alloc_device(master);
+ if (!spi) {
+@@ -884,8 +887,20 @@ static void of_register_spi_devices(struct spi_master *master)
+
+ }
+ }
+-#else
+-static void of_register_spi_devices(struct spi_master *master) { }
++EXPORT_SYMBOL_GPL(of_register_node_spi_devices);
++
++/**
++ * of_register_spi_devices() - Register child devices onto the SPI bus
++ * @master: Pointer to spi_master device
++ *
++ * Registers an spi_device for each child node of master node which has a 'reg'
++ * property.
++ */
++void of_register_spi_devices(struct spi_master *master)
++{
++ of_register_node_spi_devices(master, master->dev.of_node);
++}
++EXPORT_SYMBOL_GPL(of_register_spi_devices);
+ #endif
+
+ static void spi_master_release(struct device *dev)
+@@ -896,12 +911,12 @@ static void spi_master_release(struct device *dev)
+ kfree(master);
+ }
+
+-static struct class spi_master_class = {
++struct class spi_master_class = {
+ .name = "spi_master",
+ .owner = THIS_MODULE,
+ .dev_release = spi_master_release,
+ };
+-
++EXPORT_SYMBOL_GPL(spi_master_class);
+
+
+ /**
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index fa702ae..618aa5e 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -30,6 +30,8 @@
+ */
+ extern struct bus_type spi_bus_type;
+
++extern struct class spi_master_class;
++
+ /**
+ * struct spi_device - Master side proxy for an SPI slave device
+ * @dev: Driver model representation of the device.
+@@ -856,4 +858,20 @@ spi_unregister_device(struct spi_device *spi)
+ extern const struct spi_device_id *
+ spi_get_device_id(const struct spi_device *sdev);
+
++#if defined(CONFIG_OF) && !defined(CONFIG_SPARC)
++
++void of_register_node_spi_devices(struct spi_master *master,
++ struct device_node *parent_node);
++
++void of_register_spi_devices(struct spi_master *master);
++
++#else
++
++static inline void of_register_node_spi_devices(struct spi_master *master,
++ struct device_node *parent_node) { }
++
++static inline void of_register_spi_devices(struct spi_master *master) { }
++
++#endif
++
+ #endif /* __LINUX_SPI_H */
diff --git a/patches/linux-3.7-rc6/0127-w1-gpio-Pinctrl-fy.patch b/patches/linux-3.7-rc6/0127-w1-gpio-Pinctrl-fy.patch
new file mode 100644
index 0000000..c735d63
--- /dev/null
+++ b/patches/linux-3.7-rc6/0127-w1-gpio-Pinctrl-fy.patch
@@ -0,0 +1,36 @@
+From 24e009b4e579b589dd3a3bed2577e22517b21054 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 24 Oct 2012 09:54:37 +0300
+Subject: [PATCH] w1-gpio: Pinctrl-fy
+
+---
+ drivers/w1/masters/w1-gpio.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index 6012c4e..aec35bd 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -16,6 +16,8 @@
+ #include <linux/gpio.h>
+ #include <linux/of_platform.h>
+ #include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ #include "../w1.h"
+ #include "../w1_int.h"
+@@ -85,8 +87,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
+ {
+ struct w1_bus_master *master;
+ struct w1_gpio_platform_data *pdata;
++ struct pinctrl *pinctrl;
+ int err;
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ err = w1_gpio_probe_dt(pdev);
+ if (err < 0)
+ return err;
diff --git a/patches/linux-3.7-rc6/0128-w1-gpio-Simplify-get-rid-of-defines.patch b/patches/linux-3.7-rc6/0128-w1-gpio-Simplify-get-rid-of-defines.patch
new file mode 100644
index 0000000..dd5640f
--- /dev/null
+++ b/patches/linux-3.7-rc6/0128-w1-gpio-Simplify-get-rid-of-defines.patch
@@ -0,0 +1,141 @@
+From 90429eda58f60e4684b5aba4ad8a6ff72da8f94e Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 24 Oct 2012 16:49:53 +0300
+Subject: [PATCH] w1-gpio: Simplify & get rid of defines
+
+---
+ drivers/w1/masters/w1-gpio.c | 58 +++++++++++++++++++-----------------------
+ 1 file changed, 26 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index aec35bd..85b363a 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -18,6 +18,7 @@
+ #include <linux/of_gpio.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/err.h>
++#include <linux/of.h>
+
+ #include "../w1.h"
+ #include "../w1_int.h"
+@@ -46,7 +47,6 @@ static u8 w1_gpio_read_bit(void *data)
+ return gpio_get_value(pdata->pin) ? 1 : 0;
+ }
+
+-#ifdef CONFIG_OF
+ static struct of_device_id w1_gpio_dt_ids[] = {
+ { .compatible = "w1-gpio" },
+ {}
+@@ -57,11 +57,6 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
+ {
+ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct device_node *np = pdev->dev.of_node;
+- const struct of_device_id *of_id =
+- of_match_device(w1_gpio_dt_ids, &pdev->dev);
+-
+- if (!of_id)
+- return 0;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+@@ -76,12 +71,6 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
+
+ return 0;
+ }
+-#else
+-static int w1_gpio_probe_dt(struct platform_device *pdev)
+-{
+- return 0;
+-}
+-#endif
+
+ static int __init w1_gpio_probe(struct platform_device *pdev)
+ {
+@@ -94,28 +83,41 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev, "unable to select pin group\n");
+
+- err = w1_gpio_probe_dt(pdev);
+- if (err < 0)
+- return err;
++ if (of_have_populated_dt()) {
++ err = w1_gpio_probe_dt(pdev);
++ if (err < 0) {
++ dev_err(&pdev->dev, "Failed to parse DT\n");
++ return err;
++ }
++ }
+
+ pdata = pdev->dev.platform_data;
+
+- if (!pdata)
++ if (!pdata) {
++ dev_err(&pdev->dev, "No configuration data\n");
+ return -ENXIO;
++ }
+
+ master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
+- if (!master)
++ if (!master) {
++ dev_err(&pdev->dev, "Out of memory\n");
+ return -ENOMEM;
++ }
+
+ err = gpio_request(pdata->pin, "w1");
+- if (err)
++ if (err) {
++ dev_err(&pdev->dev, "gpio_request (pin) failed\n");
+ goto free_master;
++ }
+
+ if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
+ err = gpio_request_one(pdata->ext_pullup_enable_pin,
+ GPIOF_INIT_LOW, "w1 pullup");
+- if (err < 0)
++ if (err < 0) {
++ dev_err(&pdev->dev, "gpio_request_one "
++ "(ext_pullup_enable_pin) failed\n");
+ goto free_gpio;
++ }
+ }
+
+ master->data = pdata;
+@@ -130,8 +132,10 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
+ }
+
+ err = w1_add_master_device(master);
+- if (err)
++ if (err) {
++ dev_err(&pdev->dev, "w1_add_master device failed\n");
+ goto free_gpio_ext_pu;
++ }
+
+ if (pdata->enable_external_pullup)
+ pdata->enable_external_pullup(1);
+@@ -205,23 +209,13 @@ static struct platform_driver w1_gpio_driver = {
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(w1_gpio_dt_ids),
+ },
++ .probe = w1_gpio_probe,
+ .remove = __exit_p(w1_gpio_remove),
+ .suspend = w1_gpio_suspend,
+ .resume = w1_gpio_resume,
+ };
+
+-static int __init w1_gpio_init(void)
+-{
+- return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
+-}
+-
+-static void __exit w1_gpio_exit(void)
+-{
+- platform_driver_unregister(&w1_gpio_driver);
+-}
+-
+-module_init(w1_gpio_init);
+-module_exit(w1_gpio_exit);
++module_platform_driver(w1_gpio_driver);
+
+ MODULE_DESCRIPTION("GPIO w1 bus master driver");
+ MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
diff --git a/patches/linux-3.7-rc6/0129-arm-dt-Enable-DT-proc-updates.patch b/patches/linux-3.7-rc6/0129-arm-dt-Enable-DT-proc-updates.patch
new file mode 100644
index 0000000..0442646
--- /dev/null
+++ b/patches/linux-3.7-rc6/0129-arm-dt-Enable-DT-proc-updates.patch
@@ -0,0 +1,22 @@
+From 291e077b7d6d86c75b1ecbd894072d6256140a7e Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 26 Oct 2012 16:11:46 +0300
+Subject: [PATCH] arm-dt: Enable DT proc updates.
+
+---
+ arch/arm/include/asm/prom.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
+index aeae9c6..6d65ba2 100644
+--- a/arch/arm/include/asm/prom.h
++++ b/arch/arm/include/asm/prom.h
+@@ -11,6 +11,8 @@
+ #ifndef __ASMARM_PROM_H
+ #define __ASMARM_PROM_H
+
++#define HAVE_ARCH_DEVTREE_FIXUPS
++
+ #ifdef CONFIG_OF
+
+ extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
diff --git a/patches/linux-3.7-rc6/0130-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch b/patches/linux-3.7-rc6/0130-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
new file mode 100644
index 0000000..f5470f4
--- /dev/null
+++ b/patches/linux-3.7-rc6/0130-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
@@ -0,0 +1,57 @@
+From 99b06dce3bcdf014160203950451b9f84269c3e2 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Tue, 2 Aug 2011 15:30:09 +0100
+Subject: [PATCH] ARM: CUSTOM: Build a uImage with dtb already appended
+
+Do not commit to mainline; this is a useful hack only for now.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+
+Conflicts:
+
+ arch/arm/Makefile
+---
+ arch/arm/Makefile | 3 +++
+ arch/arm/boot/Makefile | 7 +++++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index 5f914fc..05df486 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -291,6 +291,9 @@ zImage Image xipImage bootpImage uImage: vmlinux
+ zinstall uinstall install: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
+
++uImage-dtb.%:
++ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
++
+ %.dtb: scripts
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
+index 9137df5..416fbe9 100644
+--- a/arch/arm/boot/Makefile
++++ b/arch/arm/boot/Makefile
+@@ -57,6 +57,9 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+ $(call if_changed,objcopy)
+ @$(kecho) ' Kernel: $@ is ready'
+
++$(obj)/zImage-dtb.%: $(obj)/%.dtb $(obj)/zImage
++ cat $(obj)/zImage $< > $@
++
+ endif
+
+ targets += $(dtb-y)
+@@ -92,6 +95,10 @@ $(obj)/uImage: $(obj)/zImage FORCE
+ $(call if_changed,uimage)
+ @$(kecho) ' Image $@ is ready'
+
++$(obj)/uImage-dtb.%: $(obj)/zImage-dtb.% FORCE
++ $(call if_changed,uimage)
++ @echo ' Image $@ is ready'
++
+ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
+ $(Q)$(MAKE) $(build)=$(obj)/bootp $@
+ @:
diff --git a/patches/linux-3.7-rc6/0131-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch b/patches/linux-3.7-rc6/0131-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
new file mode 100644
index 0000000..7d33a69
--- /dev/null
+++ b/patches/linux-3.7-rc6/0131-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
@@ -0,0 +1,501 @@
+From 69ae0a2048568b5ebc61c947153b4935b644f4b3 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 30 Oct 2012 12:30:18 +0100
+Subject: [PATCH] beaglebone: create a shared dtsi for beaglebone based boards
+ and add a new dts for bonelt
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/Makefile | 3 +-
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 201 +++++++++++++++++++++++++
+ arch/arm/boot/dts/am335x-bone.dts | 233 +----------------------------
+ arch/arm/boot/dts/am335x-bonelt.dts | 17 +++
+ 4 files changed, 221 insertions(+), 233 deletions(-)
+ create mode 100644 arch/arm/boot/dts/am335x-bone-common.dtsi
+ create mode 100644 arch/arm/boot/dts/am335x-bonelt.dts
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index f37cf9f..607114b 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -72,7 +72,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
+ omap4-sdp.dtb \
+ omap5-evm.dtb \
+ am335x-evm.dtb \
+- am335x-bone.dtb
++ am335x-bone.dtb \
++ am335x-bonelt.dtb
+ dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+ dtb-$(CONFIG_ARCH_U8500) += snowball.dtb
+ dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+new file mode 100644
+index 0000000..e674a19
+--- /dev/null
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -0,0 +1,201 @@
++/*
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/include/ "am33xx.dtsi"
++
++/ {
++ model = "TI AM335x BeagleBone";
++ compatible = "ti,am335x-bone", "ti,am33xx";
++
++ cpus {
++ cpu@0 {
++ cpu0-supply = <&dcdc2_reg>;
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0x80000000 0x10000000>; /* 256 MB */
++ };
++
++ am3358_pinmux: pinmux@44e10800 {
++ spi1_pins: pinmux_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x13 /* mcasp0_aclkx.spi1_sclk, OUTPUT_PULLUP | MODE3 */
++ 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
++ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
++ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
++ >;
++ };
++ lcd_pins: pinmux_lcd_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
++ gpevt_pins: pinmux_gpevt_pins {
++ pinctrl-single,pins = <
++ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
++ >;
++ };
++ userled_pins: pinmux_userled_pins {
++ pinctrl-single,pins = <
++ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
++ 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
++ 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
++ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
++ };
++
++ ocp {
++ uart1: serial@44e09000 {
++ status = "okay";
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&userled_pins>;
++
++ led0 {
++ label = "beaglebone:green:usr0";
++ gpios = <&gpio2 21 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ led1 {
++ label = "beaglebone:green:usr1";
++ gpios = <&gpio2 22 0>;
++ linux,default-trigger = "mmc0";
++ default-state = "off";
++ };
++
++ led2 {
++ label = "beaglebone:green:usr2";
++ gpios = <&gpio2 23 0>;
++ linux,default-trigger = "cpu0";
++ default-state = "off";
++ };
++
++ led3 {
++ label = "beaglebone:green:usr3";
++ gpios = <&gpio2 24 0>;
++ default-state = "off";
++ };
++ };
++
++ i2c1: i2c@44e0b000 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ tps: tps@24 {
++ reg = <0x24>;
++ };
++
++ };
++
++ gpevt {
++ compatible = "gpevt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpevt_pins>;
++ dmas = <&edma 12>;
++ dma-names = "gpioevt";
++ gpio-evt = <&gpio3 2 0>;
++ };
++ };
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "st7735fb";
++ brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
++ default-brightness-level = <50>; /* index to the array above */
++ };
++};
++
++/include/ "tps65217.dtsi"
++
++&tps {
++ regulators {
++ dcdc1_reg: regulator@0 {
++ regulator-always-on;
++ };
++
++ dcdc2_reg: regulator@1 {
++ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
++ regulator-name = "vdd_mpu";
++ regulator-min-microvolt = <925000>;
++ regulator-max-microvolt = <1325000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++
++ dcdc3_reg: regulator@2 {
++ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
++ regulator-name = "vdd_core";
++ regulator-min-microvolt = <925000>;
++ regulator-max-microvolt = <1150000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++
++ ldo1_reg: regulator@3 {
++ regulator-always-on;
++ };
++
++ ldo2_reg: regulator@4 {
++ regulator-always-on;
++ };
++
++ ldo3_reg: regulator@5 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ ldo4_reg: regulator@6 {
++ regulator-always-on;
++ };
++ };
++};
++
++&mmc1 {
++ vmmc-supply = <&ldo3_reg>;
++};
++
++&spi1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi1_pins>;
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ pinctrl-names = "default";
++ pinctrl-0 = <&lcd_pins>;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++};
++
++&edma {
++ ti,edma-xbar-event-map = <32 12>;
++};
++
++&cpsw_emac0 {
++ phy_id = "4a101000.mdio:00";
++};
++
++&cpsw_emac1 {
++ phy_id = "4a101000.mdio:01";
++};
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 667842d..7f0b0df 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -8,235 +8,4 @@
+ /dts-v1/;
+
+ /include/ "am33xx.dtsi"
+-
+-/ {
+- model = "TI AM335x BeagleBone";
+- compatible = "ti,am335x-bone", "ti,am33xx";
+-
+- cpus {
+- cpu@0 {
+- cpu0-supply = <&dcdc2_reg>;
+- };
+- };
+-
+- memory {
+- device_type = "memory";
+- reg = <0x80000000 0x10000000>; /* 256 MB */
+- };
+-
+- am3358_pinmux: pinmux@44e10800 {
+- spi1_pins: pinmux_spi1_pins {
+- pinctrl-single,pins = <
+- 0x190 0x13 /* mcasp0_aclkx.spi1_sclk, OUTPUT_PULLUP | MODE3 */
+- 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+- 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+- 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+- >;
+- };
+- lcd_pins: pinmux_lcd_pins {
+- pinctrl-single,pins = <
+- 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
+- 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+- >;
+- };
+- gpevt_pins: pinmux_gpevt_pins {
+- pinctrl-single,pins = <
+- 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
+- >;
+- };
+- userled_pins: pinmux_userled_pins {
+- pinctrl-single,pins = <
+- 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
+- 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
+- 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
+- 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+- >;
+- };
+- i2c2_pins: pinmux_i2c2_pins {
+- pinctrl-single,pins = <
+- 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+- 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+- >;
+- };
+- };
+-
+- ocp {
+- uart1: serial@44e09000 {
+- status = "okay";
+- };
+-
+- gpio-leds {
+- compatible = "gpio-leds";
+- pinctrl-names = "default";
+- pinctrl-0 = <&userled_pins>;
+-
+- led0 {
+- label = "beaglebone:green:usr0";
+- gpios = <&gpio2 21 0>;
+- linux,default-trigger = "heartbeat";
+- default-state = "off";
+- };
+-
+- led1 {
+- label = "beaglebone:green:usr1";
+- gpios = <&gpio2 22 0>;
+- linux,default-trigger = "mmc0";
+- default-state = "off";
+- };
+-
+- led2 {
+- label = "beaglebone:green:usr2";
+- gpios = <&gpio2 23 0>;
+- linux,default-trigger = "cpu0";
+- default-state = "off";
+- };
+-
+- led3 {
+- label = "beaglebone:green:usr3";
+- gpios = <&gpio2 24 0>;
+- default-state = "off";
+- };
+- };
+-
+- gpevt {
+- compatible = "gpevt";
+- pinctrl-names = "default";
+- pinctrl-0 = <&gpevt_pins>;
+- dmas = <&edma 12>;
+- dma-names = "gpioevt";
+- gpio-evt = <&gpio3 2 0>;
+- };
+- };
+-
+- backlight {
+- compatible = "pwm-backlight";
+- pwms = <&ehrpwm1 0 500000 0>;
+- pwm-names = "st7735fb";
+- brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+- default-brightness-level = <50>; /* index to the array above */
+- };
+-};
+-
+-&i2c0 {
+- status = "okay";
+- clock-frequency = <400000>;
+-
+- tps: tps@24 {
+- reg = <0x24>;
+- };
+-
+- baseboard_eeprom: baseboard_eeprom@50 {
+- compatible = "at,24c256";
+- reg = <0x50>;
+- };
+-
+-};
+-
+-&i2c2 {
+- status = "okay";
+- pinctrl-names = "default";
+- pinctrl-0 = <&i2c2_pins>;
+-
+- clock-frequency = <100000>;
+-
+- /* OK, I know these are cape but for now it will do */
+- cape_eeprom_0: cape_eeprom_0@54 {
+- compatible = "at,24c256";
+- reg = <0x54>;
+- };
+-
+- cape_eeprom_1: cape_eeprom_1@55 {
+- compatible = "at,24c256";
+- reg = <0x55>;
+- };
+-
+- cape_eeprom_2: cape_eeprom_2@56 {
+- compatible = "at,24c256";
+- reg = <0x56>;
+- };
+-
+- cape_eeprom_3: cape_eeprom_3@57 {
+- compatible = "at,24c256";
+- reg = <0x57>;
+- };
+-};
+-
+-/include/ "tps65217.dtsi"
+-
+-&tps {
+- regulators {
+- dcdc1_reg: regulator@0 {
+- regulator-always-on;
+- };
+-
+- dcdc2_reg: regulator@1 {
+- /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+- regulator-name = "vdd_mpu";
+- regulator-min-microvolt = <925000>;
+- regulator-max-microvolt = <1325000>;
+- regulator-boot-on;
+- regulator-always-on;
+- };
+-
+- dcdc3_reg: regulator@2 {
+- /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+- regulator-name = "vdd_core";
+- regulator-min-microvolt = <925000>;
+- regulator-max-microvolt = <1150000>;
+- regulator-boot-on;
+- regulator-always-on;
+- };
+-
+- ldo1_reg: regulator@3 {
+- regulator-always-on;
+- };
+-
+- ldo2_reg: regulator@4 {
+- regulator-always-on;
+- };
+-
+- ldo3_reg: regulator@5 {
+- regulator-min-microvolt = <1800000>;
+- regulator-max-microvolt = <3300000>;
+- regulator-always-on;
+- };
+-
+- ldo4_reg: regulator@6 {
+- regulator-always-on;
+- };
+- };
+-};
+-
+-&mmc1 {
+- vmmc-supply = <&ldo3_reg>;
+-};
+-
+-&spi1 {
+- status = "okay";
+- pinctrl-names = "default";
+- pinctrl-0 = <&spi1_pins>;
+-
+- lcd@0 {
+- compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
+- spi-max-frequency = <8000000>;
+- reg = <0>;
+- spi-cpol;
+- spi-cpha;
+- pinctrl-names = "default";
+- pinctrl-0 = <&lcd_pins>;
+- st7735-rst = <&gpio4 19 0>;
+- st7735-dc = <&gpio4 21 0>;
+- };
+-};
+-
+-&edma {
+- ti,edma-xbar-event-map = <32 12>;
+-};
+-
+-&cpsw_emac0 {
+- phy_id = "4a101000.mdio:00";
+-};
+-
+-&cpsw_emac1 {
+- phy_id = "4a101000.mdio:01";
+-};
++/include/ "am335x-bone-common.dtsi"
+diff --git a/arch/arm/boot/dts/am335x-bonelt.dts b/arch/arm/boot/dts/am335x-bonelt.dts
+new file mode 100644
+index 0000000..03c875f
+--- /dev/null
++++ b/arch/arm/boot/dts/am335x-bonelt.dts
+@@ -0,0 +1,17 @@
++/*
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++/dts-v1/;
++
++/include/ "am335x-bone-common.dtsi"
++
++&mmc2 {
++ vmmc-supply = <&ldo3_reg>;
++ bus-width = <4>;
++ ti,non-removable;
++ status = "okay";
++};
diff --git a/patches/linux-3.7-rc6/0132-beaglebone-enable-emmc-for-bonelt.patch b/patches/linux-3.7-rc6/0132-beaglebone-enable-emmc-for-bonelt.patch
new file mode 100644
index 0000000..dfe59fe
--- /dev/null
+++ b/patches/linux-3.7-rc6/0132-beaglebone-enable-emmc-for-bonelt.patch
@@ -0,0 +1,49 @@
+From 8b82f3581e17f14f6d7ac5bce043bb6bde7f9fe5 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 24 Oct 2012 11:47:13 +0200
+Subject: [PATCH] beaglebone: enable emmc for bonelt
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 1 +
+ arch/arm/boot/dts/am335x-bonelt.dts | 15 +++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index e674a19..99240a5 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -88,6 +88,7 @@
+ label = "beaglebone:green:usr3";
+ gpios = <&gpio2 24 0>;
+ default-state = "off";
++ linux,default-trigger = "mmc1";
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/am335x-bonelt.dts b/arch/arm/boot/dts/am335x-bonelt.dts
+index 03c875f..87257ac 100644
+--- a/arch/arm/boot/dts/am335x-bonelt.dts
++++ b/arch/arm/boot/dts/am335x-bonelt.dts
+@@ -9,6 +9,21 @@
+
+ /include/ "am335x-bone-common.dtsi"
+
++&userled_pins {
++ pinctrl-single,pins = <
++ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
++ 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
++ 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
++ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
++ 0x00c 0x31 /* P8_6 gpmc_ad3.mmc1_dat1 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x008 0x31 /* P8_5 gpmc_ad2.mmc1_dat2 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x004 0x31 /* P8_24 gpmc_ad1.mmc1_dat1 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x000 0x31 /* P8_25 gpmc_ad0.mmc1_dat0 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x084 0x32 /* P8_20 gpmc_csn2.mmc1_cmd OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP} */
++ 0x080 0x32 /* P8_21 gpmc_csn1.immc1_clk OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP} */
++ >;
++};
++
+ &mmc2 {
+ vmmc-supply = <&ldo3_reg>;
+ bus-width = <4>;
diff --git a/patches/linux-3.7-rc6/0133-capebus-Core-capebus-support.patch b/patches/linux-3.7-rc6/0133-capebus-Core-capebus-support.patch
new file mode 100644
index 0000000..cf81437
--- /dev/null
+++ b/patches/linux-3.7-rc6/0133-capebus-Core-capebus-support.patch
@@ -0,0 +1,1383 @@
+From cad1e139fd88a35c63f0119541de52e5d9cb45fc Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:06:06 +0200
+Subject: [PATCH] capebus: Core capebus support
+
+---
+ drivers/Kconfig | 2 +
+ drivers/Makefile | 3 +
+ drivers/capebus/Kconfig | 17 ++
+ drivers/capebus/Makefile | 8 +
+ drivers/capebus/capebus-driver.c | 608 ++++++++++++++++++++++++++++++++++++++
+ drivers/capebus/capebus-probe.c | 320 ++++++++++++++++++++
+ drivers/capebus/capebus-sysfs.c | 52 ++++
+ include/linux/capebus.h | 298 +++++++++++++++++++
+ 8 files changed, 1308 insertions(+)
+ create mode 100644 drivers/capebus/Kconfig
+ create mode 100644 drivers/capebus/Makefile
+ create mode 100644 drivers/capebus/capebus-driver.c
+ create mode 100644 drivers/capebus/capebus-probe.c
+ create mode 100644 drivers/capebus/capebus-sysfs.c
+ create mode 100644 include/linux/capebus.h
+
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index dbdefa3..bfbe1d1 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -156,4 +156,6 @@ source "drivers/pwm/Kconfig"
+
+ source "drivers/irqchip/Kconfig"
+
++source "drivers/capebus/Kconfig"
++
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index a16a8d0..d7a103b 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -145,3 +145,6 @@ obj-$(CONFIG_EXTCON) += extcon/
+ obj-$(CONFIG_MEMORY) += memory/
+ obj-$(CONFIG_IIO) += iio/
+ obj-$(CONFIG_VME_BUS) += vme/
++
++# Capebus
++obj-$(CONFIG_CAPEBUS) += capebus/
+diff --git a/drivers/capebus/Kconfig b/drivers/capebus/Kconfig
+new file mode 100644
+index 0000000..cea1b68
+--- /dev/null
++++ b/drivers/capebus/Kconfig
+@@ -0,0 +1,17 @@
++#
++# Capebus core support
++#
++
++menu "CAPEBUS support"
++
++config CAPEBUS
++ bool "Capebus support"
++ default n
++ help
++ Enable to support capebus devices.
++
++source "drivers/capebus/boards/Kconfig"
++
++source "drivers/capebus/capes/Kconfig"
++
++endmenu
+diff --git a/drivers/capebus/Makefile b/drivers/capebus/Makefile
+new file mode 100644
+index 0000000..45aa303
+--- /dev/null
++++ b/drivers/capebus/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for CAPEBUS devices
++#
++
++obj-$(CONFIG_CAPEBUS) += capebus-probe.o \
++ capebus-driver.o capebus-sysfs.o
++obj-$(CONFIG_CAPEBUS) += boards/
++obj-$(CONFIG_CAPEBUS) += capes/
+diff --git a/drivers/capebus/capebus-driver.c b/drivers/capebus/capebus-driver.c
+new file mode 100644
+index 0000000..82b1d1b
+--- /dev/null
++++ b/drivers/capebus/capebus-driver.c
+@@ -0,0 +1,608 @@
++/*
++ * Capebus driver infrastructure
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/mempolicy.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/cpu.h>
++#include <linux/pm_runtime.h>
++#include <linux/suspend.h>
++
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_platform.h>
++
++#include <linux/capebus.h>
++
++/**
++ * capebus_match_device - Tell if a cape device structure has a
++ * matching cape device id structure
++ * @drv: the cape driver to match against
++ * @dev: the cape device structure to match against
++ *
++ * Used by a driver to check whether a cape device present in the
++ * system is in its list of supported devices. Returns the matching
++ * cape_device_id structure or %NULL if there is no match.
++ */
++static const struct cape_device_id *capebus_match_device(
++ struct cape_driver *drv, struct cape_dev *dev)
++{
++ struct cape_bus *bus = dev->bus;
++ struct cape_slot *slot = dev->slot;
++
++ BUG_ON(bus == NULL);
++ BUG_ON(slot == NULL);
++ BUG_ON(bus->ops == NULL);
++ BUG_ON(bus->ops->get_dev_id == NULL);
++
++ return bus->ops->get_dev_id(slot);
++}
++
++/**
++ * capebus_device_probe - check if a driver wants to claim a
++ * specific cape device
++ * @dev: cape device being probed
++ *
++ * returns 0 on success, else error.
++ * side-effect: cape_dev->driver is set to drv when drv claims cape_dev.
++ */
++static int capebus_device_probe(struct device *dev)
++{
++ const struct cape_device_id *id;
++ int error = 0;
++ struct cape_driver *drv;
++ struct cape_dev *cape_dev;
++ struct device *parent;
++
++ drv = to_cape_driver(dev->driver);
++ cape_dev = to_cape_dev(dev);
++ cape_dev = capebus_dev_get(cape_dev);
++
++ /* sanity checks */
++ if (cape_dev == NULL ||
++ cape_dev->bus == NULL || cape_dev->bus->ops == NULL ||
++ cape_dev->driver != NULL || drv->probe == NULL) {
++ error = -EINVAL;
++ goto err_no_sanity;
++ }
++
++ id = capebus_match_device(drv, cape_dev);
++ if (!id) {
++ error = -ENODEV;
++ goto err_no_match;
++ }
++
++ /* The parent device must be in active state when probing */
++ parent = cape_dev->dev.parent;
++ if (parent)
++ pm_runtime_get_sync(parent);
++
++ /* Unbound cape devices are always set to disabled and suspended.
++ * During probe, the device is set to enabled and active and the
++ * usage count is incremented. If the driver supports runtime PM,
++ * it should call pm_runtime_put_noidle() in its probe routine and
++ * pm_runtime_get_noresume() in its remove routine.
++ */
++ pm_runtime_get_noresume(&cape_dev->dev);
++ pm_runtime_set_active(&cape_dev->dev);
++ pm_runtime_enable(&cape_dev->dev);
++
++ /* call the driver's probe method */
++ error = drv->probe(cape_dev, id);
++
++ /* release the parent no matter what */
++ if (parent)
++ pm_runtime_put(parent);
++
++ if (error != 0)
++ goto err_probe_fail;
++
++ /* call the probed bus method */
++ if (cape_dev->bus->ops->dev_probed != NULL) {
++ error = cape_dev->bus->ops->dev_probed(cape_dev);
++ if (error != 0)
++ goto err_dev_probed_fail;
++ }
++
++ /* all is fine... */
++ cape_dev->driver = drv;
++ cape_dev->added = 1;
++
++ return 0;
++
++err_dev_probed_fail:
++ if (drv->remove) {
++ pm_runtime_get_sync(&cape_dev->dev);
++ drv->remove(cape_dev);
++ pm_runtime_put_noidle(&cape_dev->dev);
++ }
++err_probe_fail:
++ pm_runtime_disable(&cape_dev->dev);
++ pm_runtime_set_suspended(&cape_dev->dev);
++ pm_runtime_put_noidle(&cape_dev->dev);
++err_no_match:
++ /* nothing */
++err_no_sanity:
++ capebus_dev_put(cape_dev);
++ return error;
++}
++
++static int capebus_device_remove(struct device *dev)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++ struct cape_driver *drv = cape_dev->driver;
++
++ if (drv) {
++ /* call the removed bus method (if added prev.) */
++ if (cape_dev->added) {
++ BUG_ON(cape_dev->bus == NULL);
++ BUG_ON(cape_dev->bus->ops == NULL);
++ if (cape_dev->bus->ops->dev_removed)
++ cape_dev->bus->ops->dev_removed(cape_dev);
++ cape_dev->added = 0;
++ }
++ if (drv->remove) {
++ pm_runtime_get_sync(dev);
++ drv->remove(cape_dev);
++ pm_runtime_put_noidle(dev);
++ }
++ cape_dev->driver = NULL;
++ }
++
++ /* Undo the runtime PM settings in local_capebus_probe() */
++ pm_runtime_disable(dev);
++ pm_runtime_set_suspended(dev);
++ pm_runtime_put_noidle(dev);
++
++ capebus_dev_put(cape_dev);
++ return 0;
++}
++
++static void capebus_device_shutdown(struct device *dev)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++ struct cape_driver *drv = cape_dev->driver;
++
++ if (drv && drv->shutdown)
++ drv->shutdown(cape_dev);
++
++ capebus_disable_device(cape_dev);
++
++ if (!device_may_wakeup(dev))
++ capebus_enable_wake(cape_dev, false);
++}
++
++static int capebus_bus_match(struct device *dev, struct device_driver *drv);
++static int capebus_device_probe(struct device *dev);
++static int capebus_device_remove(struct device *dev);
++static void capebus_device_shutdown(struct device *dev);
++
++struct bus_type capebus_bus_type = {
++ .name = "capebus",
++ .match = capebus_bus_match,
++ .probe = capebus_device_probe,
++ .remove = capebus_device_remove,
++ .shutdown = capebus_device_shutdown,
++ .dev_attrs = capebus_dev_attrs,
++ .bus_attrs = capebus_bus_attrs,
++ .pm = NULL, /* No PM for now */
++};
++EXPORT_SYMBOL(capebus_bus_type);
++
++/**
++ * __capebus_register_driver - register a new capebus driver
++ * @drv: the driver structure to register
++ * @owner: owner module of drv
++ * @mod_name: module name string
++ *
++ * Adds the driver structure to the list of registered drivers.
++ * Returns a negative value on error, otherwise 0.
++ * If no error occurred, the driver remains registered even if
++ * no device was claimed during registration.
++ */
++int __capebus_register_driver(struct cape_driver *drv, struct module *owner,
++ const char *mod_name)
++{
++ /* initialize common driver fields */
++ drv->driver.bus = &capebus_bus_type;
++ drv->driver.owner = owner;
++ drv->driver.mod_name = mod_name;
++
++ /* register with core */
++ return driver_register(&drv->driver);
++}
++EXPORT_SYMBOL(__capebus_register_driver);
++
++/**
++ * capebus_unregister_driver - unregister a capebus driver
++ * @drv: the driver structure to unregister
++ *
++ * Deletes the driver structure from the list of registered cape drivers,
++ * gives it a chance to clean up by calling its remove() function for
++ * each device it was responsible for, and marks those devices as
++ * driverless.
++ */
++
++void
++capebus_unregister_driver(struct cape_driver *drv)
++{
++ /* TODO: not really working properly */
++ driver_unregister(&drv->driver);
++}
++EXPORT_SYMBOL(capebus_unregister_driver);
++
++/**
++ * capebus_bus_match - Tell if a cape device structure has a matching
++ * cape device id structure
++ * @dev: the cape device structure to match against
++ * @drv: the device driver to search for matching cape device id structures
++ *
++ * Used by a driver to check whether a cape device present in the
++ * system is in its list of supported devices. Returns the matching
++ * cape_device_id structure or %NULL if there is no match.
++ */
++static int capebus_bus_match(struct device *dev, struct device_driver *drv)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++ struct cape_driver *cape_drv = to_cape_driver(drv);
++ const struct cape_device_id *found_id;
++
++ found_id = capebus_match_device(cape_drv, cape_dev);
++ if (found_id)
++ return 1;
++
++ return 0;
++}
++
++/**
++ * capebus_dev_get - increments the reference count of the capebus
++ * device structure
++ * @dev: the device being referenced
++ *
++ * Each live reference to a device should be refcounted.
++ *
++ * Drivers for cape devices should normally record such references in
++ * their probe() methods, when they bind to a device, and release
++ * them by calling capebus_dev_put(), in their disconnect() methods.
++ *
++ * A pointer to the device with the incremented reference counter is returned.
++ */
++struct cape_dev *capebus_dev_get(struct cape_dev *dev)
++{
++ if (dev)
++ get_device(&dev->dev);
++ return dev;
++}
++EXPORT_SYMBOL(capebus_dev_get);
++
++/**
++ * capebus_dev_put - release a use of the capebus device structure
++ * @dev: device that's been disconnected
++ *
++ * Must be called when a user of a device is finished with it. When the last
++ * user of the device calls this function, the memory of the device is freed.
++ */
++void capebus_dev_put(struct cape_dev *dev)
++{
++ if (dev)
++ put_device(&dev->dev);
++}
++EXPORT_SYMBOL(capebus_dev_put);
++
++static int __init capebus_driver_init(void)
++{
++ return bus_register(&capebus_bus_type);
++}
++
++postcore_initcall(capebus_driver_init);
++
++const struct of_device_id *
++capebus_of_match_device(struct cape_dev *cdev,
++ const char *property, const char *value)
++{
++ struct cape_bus *bus = cdev->bus;
++ struct device *dev = &cdev->dev;
++ struct device_node *pnode = cape_bus_to_parent_of_node(bus);
++ struct device_node *node;
++ const struct of_device_id *match;
++ const char* cp;
++ int cplen, l;
++
++ dev_dbg(dev, "Iterating on parent of node "
++ "name='%s' type='%s' full_name='%s'\n",
++ pnode->name, pnode->type, pnode->full_name);
++
++ match = NULL;
++ for_each_child_of_node(pnode, node) {
++
++ dev->of_node = node;
++ match = of_match_device(dev->driver->of_match_table, dev);
++ if (!match)
++ goto next_node;
++
++ cp = of_get_property(node, property, &cplen);
++ if (cp == NULL)
++ goto next_node;
++
++ while (cplen > 0) {
++ if (of_compat_cmp(cp, value, strlen(value)) == 0)
++ break;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ /* matched */
++ if (cplen > 0)
++ break;
++next_node:
++ match = NULL;
++ dev->of_node = NULL;
++ }
++
++ if (match == NULL) {
++ dev_dbg(dev, "Failed to find matching child-node\n");
++ return NULL;
++ }
++
++ dev_dbg(dev, "Found matching child node "
++ "name='%s' type='%s' "
++ "full_name='%s' (compatible='%s')\n",
++ node->name, node->type, node->full_name,
++ match->compatible);
++
++ return match;
++}
++EXPORT_SYMBOL(capebus_of_match_device);
++
++struct device_node *
++capebus_of_compatible_device_property_match(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *prop, const char *prop_value)
++{
++ const struct of_device_id *match;
++ struct device_node *node, *cnode;
++ const char* cp;
++ int cplen, l;
++
++ if (prop == NULL || prop_value == NULL)
++ goto try_non_property;
++
++ /* at first try secondary match */
++ for_each_child_of_node(dev->dev.of_node, node) {
++
++ cp = of_get_property(node, prop, &cplen);
++ if (cp == NULL)
++ continue;
++
++ while (cplen > 0) {
++ if (of_compat_cmp(cp, prop_value,
++ strlen(prop_value)) == 0)
++ break;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ /* not matched */
++ if (cplen <= 0)
++ continue;
++
++ /* now iterate in the children nodes */
++ for_each_child_of_node(node, cnode) {
++
++ match = of_match_node(matches, cnode);
++ if (match) {
++ /* release reference to parent, keep this one */
++ of_node_put(node);
++ return cnode;
++ }
++ }
++ }
++
++try_non_property:
++ for_each_child_of_node(dev->dev.of_node, node) {
++
++ match = of_match_node(matches, node);
++ if (match)
++ return node;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(capebus_of_compatible_device_property_match);
++
++struct platform_device *
++capebus_of_platform_compatible_device_create(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *pdev_name,
++ const char *prop, const char *prop_value)
++{
++ struct device_node *node;
++ struct platform_device *pdev;
++
++ node = capebus_of_compatible_device_property_match(dev, matches, prop,
++ prop_value);
++ if (node == NULL)
++ return ERR_PTR(-ENXIO);
++
++ pdev = of_platform_device_create(node, pdev_name, dev->bus->dev.parent);
++
++ /* release the reference to the node */
++ of_node_put(node);
++ node = NULL;
++
++ if (pdev == NULL) {
++ dev_err(&dev->dev, "Failed to create platform device '%s'\n",
++ pdev_name);
++ return ERR_PTR(-ENODEV);
++ }
++
++ return pdev;
++}
++EXPORT_SYMBOL(capebus_of_platform_compatible_device_create);
++
++struct device_node *
++capebus_of_find_property_node(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name)
++{
++ struct device_node *node;
++ const char* cp;
++ int cplen, l;
++ struct property *pp;
++
++ node = NULL;
++ if (prop == NULL || prop_value == NULL)
++ goto find_direct;
++
++ /* at first try secondary match */
++ for_each_child_of_node(dev->dev.of_node, node) {
++
++ cp = of_get_property(node, prop, &cplen);
++ if (cp == NULL)
++ continue;
++
++ while (cplen > 0) {
++ if (of_compat_cmp(cp, prop_value,
++ strlen(prop_value)) == 0)
++ break;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ /* not matched */
++ if (cplen <= 0)
++ continue;
++
++ /* found ? */
++ pp = of_find_property(node, name, NULL);
++ if (pp != NULL)
++ return node;
++ }
++find_direct:
++ pp = of_find_property(dev->dev.of_node, name, NULL);
++ if (pp == NULL)
++ return NULL;
++
++ return of_node_get(dev->dev.of_node);
++}
++EXPORT_SYMBOL_GPL(capebus_of_find_property_node);
++
++struct property *
++capebus_of_find_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp)
++{
++ struct device_node *node;
++ struct property *pp;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ if (node == NULL)
++ return NULL;
++
++ pp = of_find_property(node, name, lenp);
++
++ of_node_put(node);
++
++ return pp;
++}
++EXPORT_SYMBOL_GPL(capebus_of_find_property);
++
++const void *capebus_of_get_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp)
++{
++ struct property *pp;
++
++ pp = capebus_of_find_property(dev, prop, prop_value, name, lenp);
++ return pp ? pp->value : NULL;
++}
++EXPORT_SYMBOL_GPL(capebus_of_get_property);
++
++/* node exists, but it's not available? make it so */
++int capebus_of_device_node_enable(struct device_node *node)
++{
++ struct property *prop;
++ int ret;
++
++ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
++ if (prop == NULL)
++ goto err_no_prop_mem;
++
++ prop->name = kstrdup("status", GFP_KERNEL);
++ if (prop->name == NULL)
++ goto err_no_name_mem;
++
++ prop->value = kstrdup("okay", GFP_KERNEL);
++ if (prop->value == NULL)
++ goto err_no_value_mem;
++
++ prop->length = strlen(prop->value) + 1;
++ set_bit(OF_DYNAMIC, &prop->_flags);
++
++ ret = prom_update_property(node, prop);
++ if (ret != 0)
++ goto err_update_failed;
++
++ return 0;
++
++err_update_failed:
++ kfree(prop->value);
++err_no_value_mem:
++ kfree(prop->name);
++err_no_name_mem:
++ kfree(prop);
++err_no_prop_mem:
++ return -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(capebus_of_device_node_enable);
++
++/* Make sure this node is activated (even if it was disabled) */
++int capebus_of_platform_device_enable(struct device_node *node)
++{
++ struct platform_device *pdev, *ppdev;
++ int ret;
++
++ if (of_device_is_available(node))
++ return 0;
++
++ ret = capebus_of_device_node_enable(node);
++ if (ret != 0)
++ return ret;
++
++ /* now we need to find the parent of the node */
++ ppdev = of_find_device_by_node(node->parent);
++
++ pdev = of_platform_device_create(node, NULL,
++ ppdev ? &ppdev->dev : NULL);
++ if (IS_ERR_OR_NULL(pdev)) {
++ ret = pdev ? PTR_ERR(pdev) : -ENODEV;
++ return ret;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(capebus_of_platform_device_enable);
+diff --git a/drivers/capebus/capebus-probe.c b/drivers/capebus/capebus-probe.c
+new file mode 100644
+index 0000000..b46e915
+--- /dev/null
++++ b/drivers/capebus/capebus-probe.c
+@@ -0,0 +1,320 @@
++/*
++ * Capebus bus infrastructure
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_i2c.h>
++#include <linux/of_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/err.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/slab.h>
++
++#include <linux/capebus.h>
++
++LIST_HEAD(cape_buses);
++EXPORT_SYMBOL(cape_buses);
++
++DEFINE_MUTEX(cape_buses_mutex);
++EXPORT_SYMBOL(cape_buses_mutex);
++
++/*
++ * Cape Bus Class
++ */
++static void release_capebus_dev(struct device *dev)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++
++ kfree(cape_dev);
++}
++
++static struct class capebus_class = {
++ .name = "capebus",
++ .dev_release = &release_capebus_dev,
++};
++
++static int __init capebus_class_init(void)
++{
++ return class_register(&capebus_class);
++}
++postcore_initcall(capebus_class_init);
++
++static struct cape_bus *cape_bus_find(const char *name, int busno)
++{
++ struct cape_bus *bus;
++ int found;
++
++ if (busno < 0)
++ return NULL;
++
++ found = 0;
++ cape_bus_for_each(bus) {
++ if (strcmp(name, bus->name) == 0 && bus->busno == busno) {
++ found = 1;
++ break;
++ }
++ }
++ return found ? bus : NULL;
++}
++
++static int cape_bus_pick_busno(const char *name, int busno)
++{
++ struct cape_bus *bus;
++
++ BUG_ON(name == NULL);
++
++ /* fixed id */
++ if (busno >= 0)
++ return busno;
++
++ /* dynamic id */
++ busno = -1;
++ cape_bus_for_each(bus) {
++ /* name must match */
++ if (strcmp(name, bus->name) != 0)
++ continue;
++ busno = max(busno, bus->busno);
++ }
++ return busno + 1;
++}
++
++int cape_bus_register(struct cape_bus *bus, const char *name, int busno,
++ struct device *parent, struct cape_bus_ops *ops)
++{
++ struct cape_bus *b2;
++ int r;
++
++ if (name == NULL)
++ return -EINVAL;
++
++ INIT_LIST_HEAD(&bus->node);
++ INIT_LIST_HEAD(&bus->devices);
++ INIT_LIST_HEAD(&bus->slots);
++
++ /* do everything under lock */
++ mutex_lock(&cape_buses_mutex);
++
++ b2 = cape_bus_find(name, busno);
++ if (b2 != NULL) {
++ if (parent != NULL)
++ dev_err(parent, "capebus %s:%d in use\n", name, busno);
++ else
++ pr_err("capebus %s:%d in use\n", name, busno);
++ r = -EBUSY;
++ goto err_unlock;
++ }
++ bus->name = name;
++ bus->busno = cape_bus_pick_busno(name, busno);
++ bus->ops = ops;
++
++ bus->dev.class = &capebus_class;
++ bus->dev.parent = parent;
++ dev_set_name(&bus->dev, "%s:%d", bus->name, bus->busno);
++ r = device_register(&bus->dev);
++ if (r != 0) {
++ if (parent != NULL)
++ dev_err(parent, "capebus #%d failed to register dev\n",
++ bus->busno);
++ else
++ pr_err("capebus #%d failed to register dev\n",
++ bus->busno);
++ goto err_unlock;
++ }
++
++ list_add_tail(&bus->node, &cape_buses);
++ mutex_unlock(&cape_buses_mutex);
++
++ dev_info(&bus->dev, "Registered\n");
++
++ return 0;
++err_unlock:
++ mutex_unlock(&cape_buses_mutex);
++ return r;
++}
++
++int cape_bus_deregister(struct cape_bus *bus)
++{
++ return -EINVAL; /* not yet supported */
++}
++
++/* must have cape_buses_mutex */
++struct cape_slot *cape_slot_find(struct cape_bus *bus, int slotno)
++{
++ struct cape_slot *slot;
++ int found;
++
++ found = 0;
++ cape_slot_for_each(bus, slot) {
++ if (slot->slotno == slotno) {
++ found = 1;
++ break;
++ }
++ }
++ return found ? slot : NULL;
++}
++
++/**
++ * cape_bus_release_dev - free a cape device structure when all users
++ * of it are finished.
++ * @dev: device that's been disconnected
++ *
++ * Will be called only by the device core when all users of this cape device are
++ * done.
++ */
++static void cape_bus_release_dev(struct device *dev)
++{
++ struct cape_dev *cdev;
++
++ cdev = to_cape_dev(dev);
++ /* cape_release_capabilities(cdev); TODO */
++ /* cape_release_of_node(cdev); TODO */
++ kfree(cdev);
++}
++
++/* mutex lock must be held */
++static struct cape_dev *cape_bus_scan_slot(struct cape_slot *slot)
++{
++ struct cape_bus *bus = slot->bus;
++ struct cape_dev *dev;
++ const struct cape_device_id *id;
++
++ /* get the ID (if a device exists) */
++ id = bus->ops->get_dev_id(slot);
++ if (id == NULL)
++ return ERR_PTR(-ENODEV);
++
++ /* slot must not have a device yet */
++ dev = slot->dev;
++ if (dev == NULL) {
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (dev == NULL) {
++ dev_info(&bus->dev, "Failed to allocate cape device "
++ "for slot #%d\n", slot->slotno);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ INIT_LIST_HEAD(&dev->bus_list);
++ dev->bus = bus;
++ dev->slot = slot;
++ }
++
++ dev->id = id;
++ dev->text_id = bus->ops->get_text_dev_id(slot);
++
++ /* capebus_set_of_node(dev); TODO */
++
++ return dev;
++}
++
++int cape_bus_scan_one_slot(struct cape_bus *bus, struct cape_slot *slot)
++{
++ struct cape_dev *dev;
++ int r;
++
++ mutex_lock(&cape_buses_mutex);
++
++ dev = slot->dev;
++ if (dev == NULL) {
++
++ dev = cape_bus_scan_slot(slot);
++ if (IS_ERR(dev)) {
++ r = PTR_ERR(dev);
++ goto err_out;
++ }
++
++ dev_info(&bus->dev, "Slot #%d id='%s'\n", slot->slotno,
++ dev->text_id ? dev->text_id : "");
++
++ slot->dev = dev;
++
++ dev->dev.release = cape_bus_release_dev;
++ dev->dev.parent = &dev->bus->dev;
++ dev->dev.bus = &capebus_bus_type;
++ dev_set_name(&dev->dev, "%s-%d:%d",
++ dev->bus->name, dev->bus->busno,
++ dev->slot->slotno);
++
++ list_add_tail(&dev->bus_list, &bus->devices);
++
++ } else {
++ dev_info(&bus->dev, "Slot #%d id='%s' - rescan\n", slot->slotno,
++ dev->text_id ? dev->text_id : "");
++
++ if (dev->added) {
++ r = -EEXIST;
++ goto err_out;
++ }
++ }
++
++ r = device_register(&dev->dev);
++ if (r != 0) {
++ dev_info(&bus->dev, "Slot #%d id='%s' - "
++ "Failed to register\n",
++ slot->slotno,
++ dev->text_id ? dev->text_id : "");
++ r = 0;
++ } else {
++ if (dev->bus->ops->dev_registered)
++ dev->bus->ops->dev_registered(dev);
++ }
++
++err_out:
++ mutex_unlock(&cape_buses_mutex);
++
++ return r;
++}
++
++int cape_bus_register_slot(struct cape_bus *bus, struct cape_slot *slot,
++ int slotno)
++{
++ struct cape_slot *s2;
++ int r;
++
++ r = 0;
++
++ /* invalid (slot must always be numbered - no hotplug) */
++ if (slotno < 0) {
++ dev_err(&bus->dev, "Slot registration #%d failed\n", slotno);
++ return -EINVAL;
++ }
++
++ mutex_lock(&cape_buses_mutex);
++ s2 = cape_slot_find(bus, slotno);
++ if (s2 != NULL) {
++ dev_err(&bus->dev, "Slot #%d already exists\n", slotno);
++ mutex_unlock(&cape_buses_mutex);
++ return -EINVAL;
++ }
++
++ INIT_LIST_HEAD(&slot->node);
++ slot->bus = bus;
++ list_add(&slot->node, &bus->slots);
++ slot->slotno = slotno;
++ slot->dev = NULL;
++ mutex_unlock(&cape_buses_mutex);
++
++ dev_info(&bus->dev, "Slot #%d registered\n", slot->slotno);
++
++ return cape_bus_scan_one_slot(bus, slot);
++}
+diff --git a/drivers/capebus/capebus-sysfs.c b/drivers/capebus/capebus-sysfs.c
+new file mode 100644
+index 0000000..81c21fe
+--- /dev/null
++++ b/drivers/capebus/capebus-sysfs.c
+@@ -0,0 +1,52 @@
++/*
++ * drivers/capebus/capebus-sysfs.c
++ *
++ * sysfs for capebus devices
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Modeled after PCI's pci-sysfs.c
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/stat.h>
++#include <linux/export.h>
++#include <linux/fs.h>
++#include <linux/slab.h>
++#include <linux/pm_runtime.h>
++
++#include <linux/capebus.h>
++
++static ssize_t id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev;
++
++ cdev = to_cape_dev(dev);
++ return sprintf(buf, "%s\n", cdev->text_id);
++}
++
++struct device_attribute capebus_dev_attrs[] = {
++ __ATTR_RO(id),
++ __ATTR_NULL,
++};
++
++struct bus_attribute capebus_bus_attrs[] = {
++ __ATTR_NULL
++};
+diff --git a/include/linux/capebus.h b/include/linux/capebus.h
+new file mode 100644
+index 0000000..7524401
+--- /dev/null
++++ b/include/linux/capebus.h
+@@ -0,0 +1,298 @@
++/*
++ * capebus.h
++ *
++ * Cape bus defines and function prototypes
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef LINUX_CAPEBUS_H
++#define LINUX_CAPEBUS_H
++
++#include <linux/list.h>
++#include <linux/device.h>
++#include <linux/spinlock.h>
++#include <linux/types.h>
++#include <linux/atomic.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++
++struct cape_device_id {
++ const char *cntrlboard; /* controlling board; i.e. "beaglebone" */
++ int len; /* opaque addressing data */
++ const void *data;
++};
++
++struct cape_dev;
++struct cape_bus;
++struct cape_slot;
++
++struct cape_slot {
++ struct list_head node;
++ struct cape_bus *bus; /* the bus this slot is on */
++ int slotno; /* index of this slot */
++ struct cape_dev *dev; /* the device (if found) */
++};
++
++struct cape_driver {
++ struct list_head node;
++ int (*probe)(struct cape_dev *dev, const struct cape_device_id *id);
++ void (*remove)(struct cape_dev *dev);
++ int (*suspend) (struct cape_dev *dev, pm_message_t state);
++ int (*suspend_late) (struct cape_dev *dev, pm_message_t state);
++ int (*resume_early) (struct cape_dev *dev);
++ int (*resume) (struct cape_dev *dev);
++ void (*shutdown) (struct cape_dev *dev);
++ struct device_driver driver;
++};
++
++/*
++ * capebus_register_driver must be a macro so that
++ * KBUILD_MODNAME can be expanded
++ */
++#define capebus_register_driver(driver) \
++ __capebus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
++
++int __capebus_register_driver(struct cape_driver *drv, struct module *owner,
++ const char *mod_name);
++
++void capebus_unregister_driver(struct cape_driver *dev);
++
++/**
++ * module_capebus_driver() - Helper macro for registering a capebus driver
++ * @__capebus_driver: capebus_driver struct
++ *
++ * Helper macro for capebus drivers which do not do anything special in module
++ * init/exit. This eliminates a lot of boilerplate. Each module may only
++ * use this macro once, and calling it replaces module_init() and module_exit()
++ */
++#define module_capebus_driver(__capebus_driver) \
++ module_driver(__capebus_driver, capebus_register_driver, \
++ capebus_unregister_driver)
++
++#define to_cape_driver(n) container_of(n, struct cape_driver, driver)
++
++struct cape_bus_ops {
++ const struct cape_device_id *(*get_dev_id)(struct cape_slot *slot);
++ const char *(*get_text_dev_id)(struct cape_slot *slot);
++ int (*dev_probed)(struct cape_dev *dev); /* probed succesfully */
++ void (*dev_removed)(struct cape_dev *dev); /* removed */
++ int (*dev_registered)(struct cape_dev *dev); /* registered OK */
++};
++
++struct cape_bus {
++ struct list_head node;
++ const char *name;
++ struct list_head devices;
++ struct cape_dev *self;
++ struct list_head slots;
++ struct cape_bus_ops *ops;
++ int busno;
++ struct device dev;
++ /* TODO: resources.... */
++};
++
++#define to_cape_bus(n) container_of(n, struct cape_bus, dev)
++
++#define cape_bus_to_parent_of_node(n) ((n)->dev.parent->of_node)
++
++struct cape_dev {
++ struct list_head bus_list; /* node in per-bus list */
++ struct cape_bus *bus; /* bus this device is on */
++ struct cape_slot *slot; /* cape slot of this device */
++ struct cape_driver *driver; /* driver of this device */
++ struct device dev;
++ atomic_t enable_cnt; /* capebus_enable_device */
++ /* has been called */
++ const struct cape_device_id *id;
++ const char *text_id;
++ unsigned int added : 1; /* device has been added */
++ void *drv_priv; /* driver private data */
++};
++
++#define to_cape_dev(n) container_of(n, struct cape_dev, dev)
++
++struct cape_dev *capebus_dev_get(struct cape_dev *dev);
++void capebus_dev_put(struct cape_dev *dev);
++
++/* must have cape_buses_mutex */
++#define cape_bus_for_each(_bus) \
++ list_for_each_entry(_bus, &cape_buses, node)
++
++#define cape_bus_for_each_safe(_bus, _busn) \
++ list_for_each_entry_safe(_bus, _busn, &cape_buses, node)
++
++int cape_bus_register(struct cape_bus *bus, const char *name, int busno,
++ struct device *parent, struct cape_bus_ops *ops);
++
++/* must have cape_buses_mutex */
++#define cape_slot_for_each(_bus, _slot) \
++ list_for_each_entry(_slot, &(_bus)->slots, node)
++
++#define cape_slot_for_each_safe(_bus, _slot, _slotn) \
++ list_for_each_entry_safe(_slot, _slotn, &(_bus)->slots, node)
++
++int cape_bus_register_slot(struct cape_bus *bus,
++ struct cape_slot *slot, int slotno);
++
++int cape_bus_scan_one_slot(struct cape_bus *bus, struct cape_slot *slot);
++int cape_bus_scan(struct cape_bus *bus);
++
++extern struct list_head cape_buses;
++extern struct mutex cape_buses_mutex;
++
++static inline int capebus_is_enabled(struct cape_dev *cdev)
++{
++ return atomic_read(&cdev->enable_cnt) > 0;
++}
++
++static inline int capebus_enable_device(struct cape_dev *cdev)
++{
++ if (atomic_add_return(1, &cdev->enable_cnt) > 1)
++ return 0; /* already enabled */
++
++ /* XXX do enable */
++
++ return 0;
++}
++
++static inline void capebus_disable_device(struct cape_dev *cdev)
++{
++ if (atomic_sub_return(1, &cdev->enable_cnt) != 0)
++ return;
++
++ /* callback to disable device? */
++}
++
++static inline int capebus_enable_wake(struct cape_dev *dev, int what)
++{
++ return 0;
++}
++
++extern struct device_attribute capebus_dev_attrs[];
++extern struct bus_attribute capebus_bus_attrs[];
++
++extern struct bus_type capebus_bus_type;
++
++const struct of_device_id *
++capebus_of_match_device(struct cape_dev *cdev,
++ const char *property, const char *value);
++
++struct device_node *
++capebus_of_compatible_device_property_match(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *prop, const char *prop_value);
++
++struct platform_device *
++capebus_of_platform_compatible_device_create(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *pdev_name,
++ const char *prop, const char *prop_value);
++
++/* of tree support */
++
++struct device_node *
++capebus_of_find_property_node(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name);
++
++struct property *
++capebus_of_find_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp);
++
++const void *capebus_of_get_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp);
++
++static inline int capebus_of_property_read_u32_array(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, u32 *out_values, size_t sz)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_u32_array(node, name, out_values, sz);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_u32(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, u32 *out_value)
++{
++ return capebus_of_property_read_u32_array(dev, prop,
++ prop_value, name, out_value, 1);
++}
++
++static inline bool capebus_of_property_read_bool(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name)
++{
++ struct device_node *node;
++ bool ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_bool(node, name);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_string(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, const char **out_string)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_string(node, name, out_string);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_string_index(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int index, const char **out_string)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_string_index(node, name, index, out_string);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_u64(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, u64 *out_value)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_u64(node, name, out_value);
++ of_node_put(node);
++ return ret;
++}
++
++int capebus_of_device_node_enable(struct device_node *node);
++int capebus_of_platform_device_enable(struct device_node *node);
++
++#endif
diff --git a/patches/linux-3.7-rc6/0134-capebus-Add-beaglebone-board-support.patch b/patches/linux-3.7-rc6/0134-capebus-Add-beaglebone-board-support.patch
new file mode 100644
index 0000000..edf46cb
--- /dev/null
+++ b/patches/linux-3.7-rc6/0134-capebus-Add-beaglebone-board-support.patch
@@ -0,0 +1,1955 @@
+From 2f38e4b945ff8671b3a8341872188cfd0b5ff1f2 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:07:50 +0200
+Subject: [PATCH] capebus: Add beaglebone board support
+
+---
+ drivers/capebus/boards/Kconfig | 6 +
+ drivers/capebus/boards/Makefile | 3 +
+ drivers/capebus/boards/capebus-bone-generic.c | 237 +++++++
+ drivers/capebus/boards/capebus-bone-pdevs.c | 602 ++++++++++++++++
+ drivers/capebus/boards/capebus-bone.c | 931 +++++++++++++++++++++++++
+ include/linux/capebus/capebus-bone.h | 120 ++++
+ 6 files changed, 1899 insertions(+)
+ create mode 100644 drivers/capebus/boards/Kconfig
+ create mode 100644 drivers/capebus/boards/Makefile
+ create mode 100644 drivers/capebus/boards/capebus-bone-generic.c
+ create mode 100644 drivers/capebus/boards/capebus-bone-pdevs.c
+ create mode 100644 drivers/capebus/boards/capebus-bone.c
+ create mode 100644 include/linux/capebus/capebus-bone.h
+
+diff --git a/drivers/capebus/boards/Kconfig b/drivers/capebus/boards/Kconfig
+new file mode 100644
+index 0000000..76b0f94
+--- /dev/null
++++ b/drivers/capebus/boards/Kconfig
+@@ -0,0 +1,6 @@
++config CAPEBUS_BONE_CONTROLLER
++ bool "Beaglebone capebus board controller"
++ depends on CAPEBUS && ARCH_OMAP2PLUS && OF && I2C
++ default n
++ help
++ "Select this to enable the beaglebone capebus board controller"
+diff --git a/drivers/capebus/boards/Makefile b/drivers/capebus/boards/Makefile
+new file mode 100644
+index 0000000..9048231
+--- /dev/null
++++ b/drivers/capebus/boards/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_CAPEBUS_BONE_CONTROLLER) += capebus-bone.o \
++ capebus-bone-pdevs.o \
++ capebus-bone-generic.o \
+diff --git a/drivers/capebus/boards/capebus-bone-generic.c b/drivers/capebus/boards/capebus-bone-generic.c
+new file mode 100644
+index 0000000..b1b79eb
+--- /dev/null
++++ b/drivers/capebus/boards/capebus-bone-generic.c
+@@ -0,0 +1,237 @@
++/*
++ * TI Beaglebone capebus controller - Generic devices
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <video/da8xx-fb.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <asm/barrier.h>
++#include <plat/clock.h>
++#include <plat/omap_device.h>
++#include <linux/clkdev.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++#include <linux/mfd/ti_am335x_tscadc.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++int bone_capebus_probe_prolog(struct cape_dev *dev,
++ const struct cape_device_id *id)
++{
++ char boardbuf[33];
++ char versionbuf[5];
++ const char *board_name;
++ const char *version;
++ const struct of_device_id *match;
++ struct pinctrl *pinctrl;
++
++ /* get the board name (also matches the cntrlboard before checking) */
++ board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ boardbuf, sizeof(boardbuf));
++ if (board_name == NULL)
++ return -ENODEV;
++
++ /* match compatible? */
++ match = capebus_of_match_device(dev, "board-name", board_name);
++ if (match == NULL)
++ return -ENODEV;
++
++ /* get the board version */
++ version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ versionbuf, sizeof(versionbuf));
++ if (version == NULL)
++ return -ENODEV;
++
++ pinctrl = devm_pinctrl_get_select_default(&dev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&dev->dev,
++ "pins are not configured from the driver\n");
++
++ dev_info(&dev->dev, "%s: V=%s '%s'\n", board_name,
++ version, match->compatible);
++
++ return 0;
++}
++EXPORT_SYMBOL(bone_capebus_probe_prolog);
++
++static const struct bone_capebus_generic_device_data gendevs[] = {
++ {
++ .name = "leds",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "gpio-leds", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "tps-bl",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "tps65217-backlight", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "keys",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "gpio-keys", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "tscadc",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "ti-tscadc-dt", }, { },
++ },
++ .units = 1,
++ }, {
++ .name = "lcdc",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "da8xx-dt", }, { },
++ },
++ .units = 1,
++ },{
++ .name = "i2c-dt",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "i2c-dt", }, { },
++ },
++ .units = 0,
++ }, {
++ .name = "w1-gpio",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "w1-gpio", }, { },
++ },
++ .units = 0,
++ }, {
++ .name = "pwm-backlight",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "pwm-backlight", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "spi-dt",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "spi-dt", }, { },
++ },
++ .units = 0, /* no limit */
++ }
++};
++
++struct bone_capebus_generic_info *
++bone_capebus_probe_generic(struct cape_dev *dev,
++ const struct cape_device_id *id)
++{
++ struct bone_capebus_generic_info *info;
++ char boardbuf[33];
++ char versionbuf[5];
++ const char *board_name;
++ const char *version;
++ struct platform_device *pdev;
++ const struct bone_capebus_generic_device_data *dd;
++ struct bone_capebus_generic_device_entry *de;
++ int i;
++
++ /* get the board name (also matches the cntrlboard before checking) */
++ board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ boardbuf, sizeof(boardbuf));
++ /* get the board version */
++ version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ versionbuf, sizeof(versionbuf));
++
++ /* should never happen, but it doesn't hurt to play it safe */
++ if (board_name == NULL || version == NULL)
++ return ERR_PTR(-ENODEV);
++
++ info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ dev_err(&dev->dev, "Failed to allocate info\n");
++ return ERR_PTR(-ENOMEM);
++ }
++ info->dev = dev;
++ INIT_LIST_HEAD(&info->pdev_list);
++
++ /* iterate over the supported devices */
++ for (i = 0, dd = gendevs; i < ARRAY_SIZE(gendevs); i++, dd++) {
++
++ pdev = capebus_of_platform_compatible_device_create(dev,
++ dd->of_match, dd->name, "version", version);
++
++ /* node not found (mostly harmless) */
++ if (IS_ERR(pdev) && PTR_ERR(pdev) == -ENXIO) {
++ /* TODO: deal with required nodes */
++ continue;
++ }
++
++ /* failed to create due to an error; fatal */
++ if (IS_ERR_OR_NULL(pdev)) {
++ dev_err(&dev->dev, "failed to create device %s\n",
++ dd->name);
++ goto err_fail;
++ }
++
++ de = devm_kzalloc(&dev->dev, sizeof(*de), GFP_KERNEL);
++ if (de == NULL) {
++ dev_err(&dev->dev, "failed to allocate entry for %s\n",
++ dd->name);
++ goto err_fail;
++ }
++
++ /* add it to the list */
++ de->data = dd;
++ de->pdev = pdev;
++ list_add_tail(&de->node, &info->pdev_list);
++ }
++
++ return info;
++
++err_fail:
++ bone_capebus_remove_generic(info);
++ return NULL;
++}
++EXPORT_SYMBOL(bone_capebus_probe_generic);
++
++void bone_capebus_remove_generic(struct bone_capebus_generic_info *info)
++{
++ struct list_head *lh, *lhn;
++ struct bone_capebus_generic_device_entry *de;
++
++ if (info == NULL || info->dev == NULL)
++ return;
++
++ list_for_each_safe(lh, lhn, &info->pdev_list) {
++ de = list_entry(lh, struct bone_capebus_generic_device_entry,
++ node);
++ list_del(lh);
++ platform_device_unregister(de->pdev);
++ devm_kfree(&info->dev->dev, de);
++ }
++ devm_kfree(&info->dev->dev, info);
++}
++EXPORT_SYMBOL(bone_capebus_remove_generic);
+diff --git a/drivers/capebus/boards/capebus-bone-pdevs.c b/drivers/capebus/boards/capebus-bone-pdevs.c
+new file mode 100644
+index 0000000..a55aad6
+--- /dev/null
++++ b/drivers/capebus/boards/capebus-bone-pdevs.c
+@@ -0,0 +1,602 @@
++/*
++ * TI Beaglebone capebus controller - Platform adapters
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <video/da8xx-fb.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <asm/barrier.h>
++#include <plat/clock.h>
++#include <plat/omap_device.h>
++#include <linux/clkdev.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++#include <linux/mfd/ti_am335x_tscadc.h>
++#include <linux/i2c.h>
++#include <linux/of_i2c.h>
++#include <linux/spi/spi.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++#if defined(CONFIG_FB_DA8XX) || defined(CONFIG_FB_DA8XX_MODULE)
++
++struct da8xx_priv {
++ struct da8xx_lcdc_platform_data lcd_pdata;
++ struct lcd_ctrl_config lcd_cfg;
++ struct display_panel lcd_panel;
++ struct platform_device *lcdc_pdev;
++ struct omap_hwmod *lcdc_oh;
++ struct resource lcdc_res[1];
++ int power_dn_gpio;
++};
++
++static const struct of_device_id of_da8xx_dt_match[] = {
++ { .compatible = "da8xx-dt", },
++ {},
++};
++
++static int __devinit da8xx_dt_probe(struct platform_device *pdev)
++{
++ struct da8xx_priv *priv;
++ struct clk *disp_pll;
++ struct pinctrl *pinctrl;
++ u32 disp_pll_val;
++ const char *panel_type;
++ int ret = -EINVAL;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++ priv->power_dn_gpio = -1;
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ ret = of_property_read_u32(pdev->dev.of_node, "disp-pll", &disp_pll_val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read disp-pll property\n");
++ return ret;
++ }
++
++ ret = of_property_read_string(pdev->dev.of_node, "panel-type", &panel_type);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read panel-type property\n");
++ return ret;
++ }
++
++ /* conf_disp_pll(disp_pll); */
++ disp_pll = clk_get(NULL, "dpll_disp_ck");
++ if (IS_ERR(disp_pll)) {
++ dev_err(&pdev->dev, "Cannot clk_get disp_pll\n");
++ return PTR_ERR(disp_pll);
++ }
++ ret = clk_set_rate(disp_pll, disp_pll_val);
++ clk_put(disp_pll);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to set disp_pll\n");
++ return ret;
++ }
++
++ ret = of_get_named_gpio_flags(pdev->dev.of_node, "powerdn-gpio",
++ 0, NULL);
++ if (IS_ERR_VALUE(ret)) {
++ dev_info(&pdev->dev, "No power down GPIO\n");
++ } else {
++ priv->power_dn_gpio = ret;
++
++ ret = devm_gpio_request(&pdev->dev, priv->power_dn_gpio, "bone-dvi-cape:DVI_PDN");
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to gpio_request\n");
++ return ret;
++ }
++
++ ret = gpio_direction_output(priv->power_dn_gpio, 1);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to set powerdn to 1\n");
++ return ret;
++ }
++ }
++
++ /* display_panel */
++ priv->lcd_panel.panel_type = QVGA;
++ priv->lcd_panel.max_bpp = 16;
++ priv->lcd_panel.min_bpp = 16;
++ priv->lcd_panel.panel_shade = COLOR_ACTIVE;
++
++ /* lcd_ctrl_config */
++ priv->lcd_cfg.p_disp_panel = &priv->lcd_panel;
++ priv->lcd_cfg.ac_bias = 255;
++ priv->lcd_cfg.ac_bias_intrpt = 0;
++ priv->lcd_cfg.dma_burst_sz = 16;
++ priv->lcd_cfg.bpp = 16;
++ priv->lcd_cfg.fdd = 0x80;
++ priv->lcd_cfg.tft_alt_mode = 0;
++ priv->lcd_cfg.stn_565_mode = 0;
++ priv->lcd_cfg.mono_8bit_mode = 0;
++ priv->lcd_cfg.invert_line_clock = 1;
++ priv->lcd_cfg.invert_frm_clock = 1;
++ priv->lcd_cfg.sync_edge = 0;
++ priv->lcd_cfg.sync_ctrl = 1;
++ priv->lcd_cfg.raster_order = 0;
++
++ /* da8xx_lcdc_platform_data */
++ strcpy(priv->lcd_pdata.manu_name, "BBToys");
++ priv->lcd_pdata.controller_data = &priv->lcd_cfg;
++ strcpy(priv->lcd_pdata.type, panel_type);
++
++ priv->lcdc_oh = omap_hwmod_lookup("lcdc");
++ if (priv->lcdc_oh == NULL) {
++ dev_err(&pdev->dev, "Failed to lookup omap_hwmod lcdc\n");
++ return -ENODEV;
++ }
++
++ priv->lcdc_pdev = omap_device_build("da8xx_lcdc", 0, priv->lcdc_oh,
++ &priv->lcd_pdata,
++ sizeof(struct da8xx_lcdc_platform_data),
++ NULL, 0, 0);
++ if (priv->lcdc_pdev == NULL) {
++ dev_err(&pdev->dev, "Failed to build LCDC device\n");
++ return -ENODEV;
++ }
++
++ dev_info(&pdev->dev, "Registered bone LCDC OK.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++}
++
++static int __devexit da8xx_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver da8xx_dt_driver = {
++ .probe = da8xx_dt_probe,
++ .remove = __devexit_p(da8xx_dt_remove),
++ .driver = {
++ .name = "da8xx-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_da8xx_dt_match,
++ },
++};
++
++#endif
++
++#if defined(CONFIG_MFD_TI_AM335X_TSCADC) || defined(CONFIG_MFD_TI_AM335X_TSCADC_MODULE)
++
++struct ti_tscadc_priv {
++ struct omap_hwmod *tsc_oh;
++ struct tsc_data tsc_data;
++ struct adc_data adc_data;
++ struct mfd_tscadc_board tscadc_data;
++ struct platform_device *tscadc_pdev;
++};
++
++static const struct of_device_id of_ti_tscadc_dt_match[] = {
++ { .compatible = "ti-tscadc-dt", },
++ {},
++};
++
++static int __devinit ti_tscadc_dt_probe(struct platform_device *pdev)
++{
++ struct ti_tscadc_priv *priv;
++ struct pinctrl *pinctrl;
++ u32 val;
++ int ret;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ ret = of_property_read_u32(pdev->dev.of_node, "tsc-wires", &val);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "no tsc-wires property; disabling TSC\n");
++ val = 0;
++ }
++ priv->tsc_data.wires = val;
++
++ if (priv->tsc_data.wires > 0) {
++ ret = of_property_read_u32(pdev->dev.of_node,
++ "tsc-x-plate-resistance", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read "
++ "tsc-x-plate-resistance property\n");
++ return ret;
++ }
++ priv->tsc_data.x_plate_resistance = val;
++
++ ret = of_property_read_u32(pdev->dev.of_node,
++ "tsc-steps", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read "
++ "tsc-steps property\n");
++ return ret;
++ }
++ priv->tsc_data.steps_to_configure = val;
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "adc-channels", &val);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "No adc-channels property; disabling adc\n");
++ val = 0;
++ }
++ priv->adc_data.adc_channels = val;
++
++ priv->tscadc_data.tsc_init = &priv->tsc_data;
++ priv->tscadc_data.adc_init = &priv->adc_data;
++
++ priv->tsc_oh = omap_hwmod_lookup("adc_tsc");
++ if (priv->tsc_oh == NULL) {
++ dev_err(&pdev->dev, "Could not lookup HWMOD %s\n", "adc_tsc");
++ return -ENODEV;
++ }
++
++ priv->tscadc_pdev = omap_device_build("ti_tscadc", -1, priv->tsc_oh,
++ &priv->tscadc_data, sizeof(priv->tscadc_data),
++ NULL, 0, 0);
++ if (priv->tscadc_pdev == NULL) {
++ dev_err(&pdev->dev, "Could not create tsc_adc device\n");
++ return -ENODEV;
++ }
++
++ dev_info(&pdev->dev, "TI tscadc pdev created OK\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++}
++
++static int __devexit ti_tscadc_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver ti_tscadc_dt_driver = {
++ .probe = ti_tscadc_dt_probe,
++ .remove = __devexit_p(ti_tscadc_dt_remove),
++ .driver = {
++ .name = "ti_tscadc-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_ti_tscadc_dt_match,
++ },
++};
++
++#endif
++
++struct i2c_priv {
++ struct i2c_adapter *i2c_adapter;
++ phandle parent_handle;
++};
++
++static const struct of_device_id of_i2c_dt_match[] = {
++ { .compatible = "i2c-dt", },
++ {},
++};
++
++static int __devinit i2c_dt_probe(struct platform_device *pdev)
++{
++ struct i2c_priv *priv = NULL;
++ int ret = -EINVAL;
++ struct device_node *adap_node;
++ u32 val;
++
++ if (pdev->dev.of_node == NULL) {
++ dev_err(&pdev->dev, "Only support OF case\n");
++ return -ENOMEM;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "parent", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to find parent property\n");
++ goto err_prop_fail;
++ }
++ priv->parent_handle = val;
++
++ adap_node = of_find_node_by_phandle(priv->parent_handle);
++ if (adap_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find i2c adapter node\n");
++ ret = -EINVAL;
++ goto err_node_fail;
++ }
++
++ ret = capebus_of_platform_device_enable(adap_node);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "I2C adapter platform device failed "
++ "to enable\n");
++ goto err_enable_fail;
++ }
++
++ priv->i2c_adapter = of_find_i2c_adapter_by_node(adap_node);
++ if (priv->i2c_adapter == NULL) {
++ dev_err(&pdev->dev, "Failed to find i2c adapter node\n");
++ ret = -EINVAL;
++ goto err_adap_fail;
++ }
++
++ of_i2c_register_node_devices(priv->i2c_adapter, pdev->dev.of_node);
++
++ of_node_put(adap_node);
++
++ dev_info(&pdev->dev, "Registered bone I2C OK.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++err_adap_fail:
++ of_node_put(adap_node);
++err_enable_fail:
++ /* nothing */
++err_node_fail:
++ /* nothing */
++err_prop_fail:
++ devm_kfree(&pdev->dev, priv);
++ return ret;
++}
++
++static int __devexit i2c_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver i2c_dt_driver = {
++ .probe = i2c_dt_probe,
++ .remove = __devexit_p(i2c_dt_remove),
++ .driver = {
++ .name = "i2c-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_i2c_dt_match,
++ },
++};
++
++struct spi_priv {
++ struct spi_master *master;
++ phandle parent_handle;
++};
++
++static const struct of_device_id of_spi_dt_match[] = {
++ { .compatible = "spi-dt", },
++ {},
++};
++
++static int of_dev_node_match(struct device *dev, void *data)
++{
++ return dev->of_node == data;
++}
++
++/* must call put_device() when done with returned i2c_adapter device */
++static struct spi_master *of_find_spi_master_by_node(struct device_node *node)
++{
++ struct device *dev;
++ struct spi_master *master;
++
++ dev = class_find_device(&spi_master_class, NULL, node,
++ of_dev_node_match);
++ if (!dev)
++ return NULL;
++
++ master = container_of(dev, struct spi_master, dev);
++
++ /* TODO: No checks what-so-ever... be careful. */
++ return master;
++}
++
++static int __devinit spi_dt_probe(struct platform_device *pdev)
++{
++ struct spi_priv *priv = NULL;
++ int ret = -EINVAL;
++ struct device_node *master_node;
++ u32 val;
++
++ if (pdev->dev.of_node == NULL) {
++ dev_err(&pdev->dev, "Only support OF case\n");
++ return -ENOMEM;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "parent", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to find parent property\n");
++ goto err_prop_fail;
++ }
++ priv->parent_handle = val;
++
++ master_node = of_find_node_by_phandle(priv->parent_handle);
++ if (master_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find spi bus master node\n");
++ ret = -EINVAL;
++ goto err_node_fail;
++ }
++
++ ret = capebus_of_platform_device_enable(master_node);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "SPI platform device failed to enable\n");
++ goto err_enable_fail;
++ }
++
++ priv->master = of_find_spi_master_by_node(master_node);
++ if (priv->master == NULL) {
++ dev_err(&pdev->dev, "Failed to find bus master node\n");
++ ret = -EINVAL;
++ goto err_master_fail;
++ }
++
++ of_register_node_spi_devices(priv->master, pdev->dev.of_node);
++
++ of_node_put(master_node);
++
++ dev_info(&pdev->dev, "Registered bone SPI OK.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++err_master_fail:
++ of_node_put(master_node);
++err_enable_fail:
++ /* nothing */
++err_node_fail:
++ /* nothing */
++err_prop_fail:
++ devm_kfree(&pdev->dev, priv);
++ return ret;
++}
++
++static int __devexit spi_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver spi_dt_driver = {
++ .probe = spi_dt_probe,
++ .remove = __devexit_p(spi_dt_remove),
++ .driver = {
++ .name = "spi-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_spi_dt_match,
++ },
++};
++
++/*
++ *
++ */
++struct bone_capebus_pdev_driver {
++ struct platform_driver *driver;
++ unsigned int registered : 1;
++ /* more? */
++};
++
++static struct bone_capebus_pdev_driver pdev_drivers[] = {
++#if defined(CONFIG_FB_DA8XX) || defined(CONFIG_FB_DA8XX_MODULE)
++ {
++ .driver = &da8xx_dt_driver,
++ },
++#endif
++#if defined(CONFIG_MFD_TI_AM335X_TSCADC) || defined(CONFIG_MFD_TI_AM335X_TSCADC_MODULE)
++ {
++ .driver = &ti_tscadc_dt_driver,
++ },
++#endif
++ {
++ .driver = &i2c_dt_driver,
++ },
++ {
++ .driver = &spi_dt_driver,
++ },
++ {
++ .driver = NULL,
++ }
++};
++
++int bone_capebus_register_pdev_adapters(struct bone_capebus_bus *bus)
++{
++ struct bone_capebus_pdev_driver *drvp;
++ int err;
++
++ /* first check if we do it twice */
++ for (drvp = pdev_drivers; drvp->driver != NULL; drvp++)
++ if (drvp->registered)
++ return -EBUSY;
++
++ for (drvp = pdev_drivers; drvp->driver != NULL; drvp++) {
++
++ err = platform_driver_register(drvp->driver);
++ if (err != 0)
++ goto err_out;
++
++ drvp->registered = 1;
++
++ dev_info(bus->dev, "Registered %s "
++ "platform driver\n", drvp->driver->driver.name);
++ }
++
++ return 0;
++
++err_out:
++ dev_err(bus->dev, "Failed to register %s "
++ "platform driver\n", drvp->driver->driver.name);
++
++ /* unregister */
++ while (--drvp >= pdev_drivers) {
++
++ if (!drvp->registered)
++ continue;
++
++ platform_driver_unregister(drvp->driver);
++ }
++
++ return err;
++}
++
++void bone_capebus_unregister_pdev_adapters(struct bone_capebus_bus *bus)
++{
++ struct bone_capebus_pdev_driver *drvp;
++
++ /* unregister */
++ drvp = &pdev_drivers[ARRAY_SIZE(pdev_drivers)];
++ while (--drvp >= pdev_drivers) {
++
++ if (drvp->driver == NULL) /* skip terminator */
++ continue;
++
++ if (!drvp->registered)
++ continue;
++
++ platform_driver_unregister(drvp->driver);
++
++ drvp->registered = 0;
++ }
++}
+diff --git a/drivers/capebus/boards/capebus-bone.c b/drivers/capebus/boards/capebus-bone.c
+new file mode 100644
+index 0000000..33a6bde
+--- /dev/null
++++ b/drivers/capebus/boards/capebus-bone.c
+@@ -0,0 +1,931 @@
++/*
++ * TI Beaglebone capebus controller
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/completion.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_i2c.h>
++#include <linux/of_device.h>
++#include <linux/slab.h>
++#include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
++#include <linux/ctype.h>
++
++#include <linux/capebus.h>
++#include <linux/capebus/capebus-bone.h>
++
++/* what to fill in to the cntrlboard field of the id */
++#define BONE_CAPEBUS_CNTRLBOARD "beaglebone"
++
++/* various EEPROM definition for the bone */
++struct bone_capebus_eeprom_field {
++ const char *name;
++ int start;
++ int size;
++ unsigned int ascii : 1;
++ unsigned int strip_trailing_dots : 1;
++ const char *override;
++};
++
++static const struct bone_capebus_eeprom_field eeprom_fields[] = {
++ [BONE_CAPEBUS_HEADER] = {
++ .name = "header",
++ .start = 0,
++ .size = 4,
++ .ascii = 0,
++ .override = "\xaa\x55\x33\xee", /* AA 55 33 EE */
++ },
++ [BONE_CAPEBUS_EEPROM_REV] = {
++ .name = "eeprom-format-revision",
++ .start = 4,
++ .size = 2,
++ .ascii = 1,
++ .override = "A0",
++ },
++ [BONE_CAPEBUS_BOARD_NAME] = {
++ .name = "board-name",
++ .start = 6,
++ .size = 32,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Override Board Name",
++ },
++ [BONE_CAPEBUS_VERSION] = {
++ .name = "version",
++ .start = 38,
++ .size = 4,
++ .ascii = 1,
++ .override = "00A0",
++ },
++ [BONE_CAPEBUS_MANUFACTURER] = {
++ .name = "manufacturer",
++ .start = 42,
++ .size = 16,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Override Manuf",
++ },
++ [BONE_CAPEBUS_PART_NUMBER] = {
++ .name = "part-number",
++ .start = 58,
++ .size = 16,
++ .ascii = 1,
++ .override = "Override Part#",
++ },
++ [BONE_CAPEBUS_NUMBER_OF_PINS] = {
++ .name = "number-of-pins",
++ .start = 74,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_SERIAL_NUMBER] = {
++ .name = "serial-number",
++ .start = 76,
++ .size = 12,
++ .ascii = 1,
++ .override = "0000000000",
++ },
++ [BONE_CAPEBUS_PIN_USAGE] = {
++ .name = "pin-usage",
++ .start = 88,
++ .size = 140,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_VDD_3V3EXP] = {
++ .name = "vdd-3v3exp",
++ .start = 228,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_VDD_5V] = {
++ .name = "vdd-5v",
++ .start = 230,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_SYS_5V] = {
++ .name = "sys-5v",
++ .start = 232,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_DC_SUPPLIED] = {
++ .name = "dc-supplied",
++ .start = 234,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++};
++
++char *bone_capebus_id_get_field(const struct cape_device_id *id,
++ int field, char *buf, int bufsz)
++{
++ const struct bone_capebus_eeprom_field *ee_field;
++ int len;
++
++ /* make sure the ID is valid for the bone */
++ if (bone_capebus_match_cntrlboard(id) != 0)
++ return NULL;
++
++ if ((unsigned int)field >= ARRAY_SIZE(eeprom_fields))
++ return NULL;
++
++ ee_field = &eeprom_fields[field];
++
++ /* enough space? */
++ if (bufsz < ee_field->size + ee_field->ascii)
++ return NULL;
++
++ memcpy(buf, (char *)id->data + ee_field->start, ee_field->size);
++
++ /* terminate ascii field */
++ if (ee_field->ascii)
++ buf[ee_field->size] = '\0';;
++
++ if (ee_field->strip_trailing_dots) {
++ len = strlen(buf);
++ while (len > 1 && buf[len - 1] == '.')
++ buf[--len] = '\0';
++ }
++
++ return buf;
++}
++EXPORT_SYMBOL(bone_capebus_id_get_field);
++
++int bone_capebus_match_cntrlboard(const struct cape_device_id *id)
++{
++ if (strcmp(id->cntrlboard, BONE_CAPEBUS_CNTRLBOARD) != 0)
++ return -ENODEV;
++ return 0;
++}
++EXPORT_SYMBOL(bone_capebus_match_cntrlboard);
++
++int bone_capebus_match_board(const struct cape_device_id *id,
++ const char **board_names)
++{
++ char rname[33];
++ const char *s;
++ int ret;
++ int i;
++
++ /* be safe; check for matching cntrlboard */
++ ret = bone_capebus_match_cntrlboard(id);
++ if (ret != 0)
++ return ret;
++
++ s = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ rname, sizeof(rname));
++ if (s == NULL)
++ return -EINVAL;
++
++ i = 0;
++ while (*board_names) {
++ if (strcmp(rname, *board_names) == 0)
++ return i;
++ board_names++;
++ }
++
++ return -1;
++}
++EXPORT_SYMBOL(bone_capebus_match_board);
++
++#ifdef CONFIG_OF
++static const struct of_device_id bone_capebus_of_match[] = {
++ {
++ .compatible = "bone-capebus",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bone_capebus_of_match);
++
++static const struct of_device_id slot_override_of_match[] = {
++ {
++ .compatible = "bone-capebus-slot-override",
++ },
++ { },
++};
++
++#endif
++
++const struct cape_device_id *bone_capebus_get_dev_id(struct cape_slot *slot)
++{
++ struct cape_bus *bus = slot->bus;
++ struct bone_capebus_slot *bone_slot = to_bone_capebus_slot(slot);
++ struct i2c_client *client = bone_slot->client;
++ struct cape_device_id *id;
++ const u8 *p;
++ int r;
++ char board_name[32+1];
++ char version[4+1];
++ char manufacturer[16+1];
++ char part_number[16+1];
++
++ id = &bone_slot->id;
++
++ /* need to read EEPROM? */
++ if (!bone_slot->eeprom_probed) {
++
++ bone_slot->eeprom_probed = 1;
++
++ if (!bone_slot->eeprom_override) {
++ r = i2c_memory_read(bone_slot->client,
++ bone_slot->eeprom_signature, 0,
++ sizeof(bone_slot->eeprom_signature));
++ if (r != sizeof(bone_slot->eeprom_signature)) {
++ dev_err(&bus->dev,
++ "bone: Failed to read EEPROM at "
++ "slot %d (addr 0x%02x)\n",
++ slot->slotno, client->addr & 0x7f);
++ bone_slot->eeprom_failed = 1;
++ return NULL;
++ }
++ } else
++ dev_info(&bus->dev,
++ "bone: Using override eeprom data at slot %d\n",
++ slot->slotno);
++
++ p = bone_slot->eeprom_signature;
++ if (BONE_CAPEBUS_MAKE_HEADER(p) != BONE_CAPEBUS_HEADER_VALID) {
++ dev_err(&bus->dev, "bone: Invalid EEPROM signature "
++ "'%08x' at slot %d (addr 0x%02x)\n",
++ BONE_CAPEBUS_MAKE_HEADER(p),
++ slot->slotno, client->addr & 0x7f);
++ bone_slot->eeprom_failed = 1;
++ return NULL;
++ }
++
++ bone_slot->id.cntrlboard = BONE_CAPEBUS_CNTRLBOARD;
++ bone_slot->id.len = sizeof(bone_slot->eeprom_signature);
++ bone_slot->id.data = bone_slot->eeprom_signature;
++
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ board_name, sizeof(board_name));
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ version, sizeof(version));
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_MANUFACTURER,
++ manufacturer, sizeof(manufacturer));
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_PART_NUMBER,
++ part_number, sizeof(part_number));
++
++ /* board_name,version,manufacturer,part_number */
++ snprintf(bone_slot->text_id, sizeof(bone_slot->text_id) - 1,
++ "%s,%s,%s,%s", board_name, version,
++ manufacturer, part_number);
++
++ /* terminate always */
++ bone_slot->text_id[sizeof(bone_slot->text_id) - 1] = '\0';
++
++ }
++
++ /* slot has failed and we don't support hotpluging */
++ if (bone_slot->eeprom_failed)
++ return NULL;
++
++ return id;
++}
++
++const char *bone_capebus_get_text_dev_id(struct cape_slot *slot)
++{
++ struct bone_capebus_slot *bone_slot = to_bone_capebus_slot(slot);
++
++ if (bone_slot->eeprom_failed || !bone_slot->eeprom_probed)
++ return NULL;
++
++ return bone_slot->text_id;
++}
++
++struct bonedev_ee_attribute {
++ struct device_attribute devattr;
++ unsigned int field;
++};
++#define to_bonedev_ee_attribute(x) \
++ container_of((x), struct bonedev_ee_attribute, devattr)
++
++static ssize_t bonedev_ee_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct bonedev_ee_attribute *ee_attr = to_bonedev_ee_attribute(attr);
++ struct cape_dev *cdev = to_cape_dev(dev);
++ const struct cape_device_id *id = cdev->id;
++ const struct bone_capebus_eeprom_field *ee_field;
++ int i, len;
++ char *p, *s;
++ u16 val;
++
++ if (id == NULL)
++ return -EINVAL;
++
++ /* add newline for ascii fields */
++ ee_field = &eeprom_fields[ee_attr->field];
++
++ len = ee_field->size + ee_field->ascii;
++ p = kmalloc(len, GFP_KERNEL);
++ if (p == NULL)
++ return -ENOMEM;
++
++ s = bone_capebus_id_get_field(id, ee_attr->field, p, len);
++ if (s == NULL)
++ return -EINVAL;
++
++ /* add newline for ascii fields and return */
++ if (ee_field->ascii) {
++ len = sprintf(buf, "%s\n", s);
++ goto out;
++ }
++
++ /* case by case handling */
++ switch (ee_attr->field) {
++ case BONE_CAPEBUS_HEADER:
++ len = sprintf(buf, "%02x %02x %02x %02x\n",
++ s[0], s[1], s[2], s[3]);
++ break;
++
++ /* 2 bytes */
++ case BONE_CAPEBUS_NUMBER_OF_PINS:
++ case BONE_CAPEBUS_VDD_3V3EXP:
++ case BONE_CAPEBUS_VDD_5V:
++ case BONE_CAPEBUS_SYS_5V:
++ case BONE_CAPEBUS_DC_SUPPLIED:
++ /* the bone is LE */
++ val = s[0] & (s[1] << 8);
++ len = sprintf(buf, "%u\n", (unsigned int)val & 0xffff);
++ break;
++
++ case BONE_CAPEBUS_PIN_USAGE:
++
++ len = 0;
++ for (i = 0; i < ee_field->size / 2; i++) {
++ /* the bone is LE */
++ val = s[0] & (s[1] << 8);
++ sprintf(buf, "%04x\n", val);
++ buf += 5;
++ len += 5;
++ s += 2;
++ }
++
++ break;
++
++ default:
++ *buf = '\0';
++ len = 0;
++ break;
++ }
++
++out:
++ kfree(p);
++
++ return len;
++}
++
++#define BONEDEV_EE_ATTR(_name, _field) \
++ { \
++ .devattr = __ATTR(_name, 0440, bonedev_ee_show, NULL), \
++ .field = BONE_CAPEBUS_##_field , \
++ }
++
++struct bonedev_ee_attribute ee_attrs[] = {
++ BONEDEV_EE_ATTR(header, HEADER),
++ BONEDEV_EE_ATTR(eeprom-format-revision, EEPROM_REV),
++ BONEDEV_EE_ATTR(board-name, BOARD_NAME),
++ BONEDEV_EE_ATTR(version, VERSION),
++ BONEDEV_EE_ATTR(manufacturer, MANUFACTURER),
++ BONEDEV_EE_ATTR(part-number, PART_NUMBER),
++ BONEDEV_EE_ATTR(number-of-pins, NUMBER_OF_PINS),
++ BONEDEV_EE_ATTR(serial-number, SERIAL_NUMBER),
++ BONEDEV_EE_ATTR(pin-usage, PIN_USAGE),
++ BONEDEV_EE_ATTR(vdd-3v3exp, VDD_3V3EXP),
++ BONEDEV_EE_ATTR(vdd-5v, VDD_5V),
++ BONEDEV_EE_ATTR(sys-5v, SYS_5V),
++ BONEDEV_EE_ATTR(dc-supplied, DC_SUPPLIED),
++};
++
++static struct attribute *ee_attrs_flat[] = {
++ &ee_attrs[BONE_CAPEBUS_HEADER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_EEPROM_REV ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_BOARD_NAME ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_VERSION ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_MANUFACTURER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_PART_NUMBER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_NUMBER_OF_PINS ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_SERIAL_NUMBER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_PIN_USAGE ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_VDD_3V3EXP ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_VDD_5V ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_SYS_5V ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_DC_SUPPLIED ].devattr.attr,
++ NULL,
++};
++
++static const struct attribute_group bone_ee_attrgroup = {
++ .name = "ee-fields",
++ .is_visible = NULL,
++ .attrs = ee_attrs_flat,
++};
++
++static int bone_capebus_sysfs_register(struct cape_dev *dev)
++{
++ return sysfs_create_group(&dev->dev.kobj, &bone_ee_attrgroup);
++}
++
++static void bone_capebus_sysfs_unregister(struct cape_dev *dev)
++{
++ sysfs_remove_group(&dev->dev.kobj, &bone_ee_attrgroup);
++}
++
++static int bone_capebus_dev_probed(struct cape_dev *dev)
++{
++ return 0;
++}
++
++static void bone_capebus_dev_removed(struct cape_dev *dev)
++{
++ bone_capebus_sysfs_unregister(dev);
++}
++
++static int bone_capebus_dev_registered(struct cape_dev *dev)
++{
++ int ret;
++
++ ret = bone_capebus_sysfs_register(dev);
++ if (ret != 0) {
++ dev_err(&dev->dev, "bone_capebus sysfs registration failed\n");
++ return ret;
++ }
++
++ return 0;
++}
++
++static struct cape_bus_ops bone_capebus_ops = {
++ .get_dev_id = bone_capebus_get_dev_id,
++ .get_text_dev_id = bone_capebus_get_text_dev_id,
++ .dev_probed = bone_capebus_dev_probed,
++ .dev_removed = bone_capebus_dev_removed,
++ .dev_registered = bone_capebus_dev_registered,
++};
++
++static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *bus = platform_get_drvdata(pdev);
++ struct bone_capebus_slot *slot;
++ ssize_t len, sz;
++ int i;
++
++ sz = 0;
++
++ for (i = 0; i < bus->slots_nr; i++) {
++ slot = &bus->slots[i];
++
++ len = sprintf(buf, "%02x:%c%c%c%c %s\n",
++ (int)slot->eeprom_addr & 0x7f,
++ slot->eeprom_probed ? 'P' : '-',
++ slot->eeprom_failed ? 'F' : '-',
++ slot->eeprom_override ? 'O' : '-',
++ (slot->cape_slot.dev && slot->cape_slot.dev->added) ? 'A' : '-',
++ slot->text_id);
++
++ buf += len;
++ sz += len;
++ }
++ return sz;
++}
++
++static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *bus = platform_get_drvdata(pdev);
++ int slotno, err, i, len;
++ char *s, *board_name, *version, *p;
++ const struct bone_capebus_eeprom_field *ee_field, *eebrd, *eevrs;
++ struct bone_capebus_slot *slot;
++
++ eebrd = &eeprom_fields[BONE_CAPEBUS_BOARD_NAME];
++ eevrs = &eeprom_fields[BONE_CAPEBUS_VERSION];
++
++ slotno = simple_strtoul(buf, &s, 10);
++ if (slotno < 0 || slotno >= bus->slots_nr)
++ return -EINVAL;
++ slot = &bus->slots[slotno];
++ if (slot->eeprom_override || (slot->cape_slot.dev && slot->cape_slot.dev->added))
++ return -EINVAL;
++
++ board_name = kzalloc(eebrd->size + 1 + eevrs->size + 1, GFP_KERNEL);
++ if (board_name == NULL)
++ return -ENOMEM;
++ version = board_name + eebrd->size + 1;
++
++ s = strchr(s, ':');
++ if (s == NULL) {
++ kfree(board_name);
++ return -EINVAL;
++ }
++ s++;
++ p = strchr(s, ':');
++ if (p == NULL) {
++ len = strlen(s);
++ strncpy(board_name, s, eebrd->size);
++ strcpy(version, "00A0");
++ } else {
++ len = p - s;
++ if (len > eebrd->size)
++ len = p - s;
++ memcpy(board_name, s, len);
++ board_name[len] = '\0';
++ strncpy(version, p + 1, eevrs->size);
++ }
++ board_name[eebrd->size] = '\0';
++ version[eevrs->size] = '\0';
++
++ /* strip trailing spaces, dots & newlines */
++ s = board_name + strlen(board_name);
++ while (s > board_name &&
++ (isspace(s[-1]) || s[-1] == '\n' || s[-1] == '.'))
++ *--s = '\0';
++
++ printk(KERN_INFO "Override for slot #%d, board-name '%s', version '%s'\n",
++ slotno, board_name, version);
++
++ slot->eeprom_override = 1;
++ slot->eeprom_failed = 0;
++ slot->eeprom_probed = 0;
++
++ /* zero out signature */
++ memset(slot->eeprom_signature, 0,
++ sizeof(slot->eeprom_signature));
++
++ /* create an eeprom field */
++ for (i = 0; i < ARRAY_SIZE(eeprom_fields); i++) {
++
++ ee_field = &eeprom_fields[i];
++
++ /* point to the entry */
++ p = slot->eeprom_signature + ee_field->start;
++
++ /* if no such property, assign default */
++ if (i != BONE_CAPEBUS_BOARD_NAME) {
++
++ if (ee_field->override)
++ memcpy(p, ee_field->override,
++ ee_field->size);
++ else
++ memset(p, 0, ee_field->size);
++
++ continue;
++ }
++
++ /* copy it to the eeprom signature buf */
++ len = strlen(board_name);
++ if (len > ee_field->size)
++ len = ee_field->size;
++
++ /* copy and zero out rest */
++ memcpy(p, board_name, len);
++ if (len < ee_field->size)
++ memset(p + len, 0, ee_field->size - len);
++ }
++
++ printk(KERN_INFO "calling cape_bus_scan_one_slot\n");
++ err = cape_bus_scan_one_slot(&bus->cape_bus, &slot->cape_slot);
++
++ printk(KERN_INFO "cape_bus_scan_one_slot returned %d\n", err);
++
++ /* failed to scan... */
++ if (err != 0)
++ slot->eeprom_override = 0;
++
++ kfree(board_name);
++
++ return strlen(buf);
++}
++
++static DEVICE_ATTR(slots, 0644, slots_show, slots_store);
++
++static int bone_capebus_bus_sysfs_register(struct bone_capebus_bus *bus)
++{
++ return device_create_file(bus->dev, &dev_attr_slots);
++}
++
++static void bone_capebus_bus_sysfs_unregister(struct bone_capebus_bus *bus)
++{
++ device_remove_file(bus->dev, &dev_attr_slots);
++}
++
++static int __devinit
++bone_capebus_probe(struct platform_device *pdev)
++{
++ struct bone_capebus_bus *bus;
++ struct device_node *pnode = pdev->dev.of_node;
++ const struct of_device_id *cntrlboard_match;
++ const struct of_device_id *dev_match;
++ struct bone_capebus_slot *slot;
++ const struct bone_capebus_eeprom_field *ee_field;
++ struct property *prop;
++ int length;
++ int r;
++ struct device_node *node;
++ struct i2c_client *client;
++ phandle handle;
++ u32 *slot_handles = NULL;
++ u32 val;
++ const char *str;
++ u8 *p;
++ int i, len;
++
++ /* we don't use platform_data */
++
++ bus = devm_kzalloc(&pdev->dev,
++ sizeof(struct bone_capebus_bus), GFP_KERNEL);
++ if (!bus) {
++ dev_err(&pdev->dev, "Failed to allocate device structure\n");
++ return -ENOMEM;
++ }
++
++ /* register the cape bus */
++ r = cape_bus_register(&bus->cape_bus, "bone", 0, &pdev->dev,
++ &bone_capebus_ops);
++ if (r != 0) {
++ dev_err(&pdev->dev, "Failed to register the cape device\n");
++ return r;
++ }
++
++ cntrlboard_match = of_match_device(of_match_ptr(bone_capebus_of_match),
++ &pdev->dev);
++ if (!cntrlboard_match) {
++ dev_err(&pdev->dev, "Failed to configure bone capebus\n");
++ return -ENODEV;
++ }
++ bus->dev = &pdev->dev;
++
++ prop = of_find_property(pnode, "slots", &length);
++ if (prop == NULL) {
++ dev_err(&pdev->dev, "Unable to find required "
++ "property 'slots'\n");
++ return -EINVAL;
++ }
++ bus->slots_nr = length / sizeof(u32);
++ bus->slots = devm_kzalloc(&pdev->dev,
++ sizeof(bus->slots[0]) * bus->slots_nr, GFP_KERNEL);
++ if (!bus->slots) {
++ dev_err(&pdev->dev, "Failed to allocate %d slot areas\n",
++ bus->slots_nr);
++ return -ENOMEM;
++ }
++ slot_handles = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
++ if (!slot_handles) {
++ dev_err(&pdev->dev, "Failed to allocate %d slot areas\n",
++ bus->slots_nr);
++ return -ENOMEM;
++ }
++ r = of_property_read_u32_array(pnode, "slots",
++ slot_handles, bus->slots_nr);
++ if (r < 0) {
++ dev_err(&pdev->dev, "Failed to read %d slot handles\n",
++ bus->slots_nr);
++ return r;
++ }
++
++ /* now we iterate over any overrides */
++ for_each_child_of_node(pnode, node) {
++
++ dev_match = of_match_node(slot_override_of_match, node);
++ if (!dev_match)
++ continue;
++
++ /* no reg property */
++ if (of_property_read_u32(node, "slot", &val) != 0) {
++ dev_warn(&pdev->dev, "override: Failed to read "
++ "slot property\n");
++ continue;
++ }
++
++ if (val >= bus->slots_nr) {
++ dev_warn(&pdev->dev, "override: invalid slot #%u\n",
++ val);
++ continue;
++ }
++
++ slot = &bus->slots[val];
++
++ if (slot->eeprom_override) {
++ dev_warn(&pdev->dev, "override: slot #%u is already "
++ "overriden\n", val);
++ continue;
++ }
++
++ slot->eeprom_override = 1;
++
++ /* zero out signature */
++ memset(slot->eeprom_signature, 0,
++ sizeof(slot->eeprom_signature));
++
++ /* for any matching field assign them */
++ for (i = 0; i < ARRAY_SIZE(eeprom_fields); i++) {
++
++ ee_field = &eeprom_fields[i];
++
++ /* point to the entry */
++ p = slot->eeprom_signature + ee_field->start;
++
++ /* if no such property, assign default */
++ if (of_property_read_string(node, ee_field->name,
++ &str) != 0) {
++
++ if (ee_field->override)
++ memcpy(p, ee_field->override,
++ ee_field->size);
++ else
++ memset(p, 0, ee_field->size);
++
++ continue;
++ }
++
++ /* copy it to the eeprom signature buf */
++ len = strlen(str);
++ if (len > ee_field->size)
++ len = ee_field->size;
++
++ /* copy and zero out rest */
++ memcpy(p, str, len);
++ if (len < ee_field->size)
++ memset(p + len, 0, ee_field->size - len);
++ }
++ }
++
++ platform_set_drvdata(pdev, bus);
++
++ /* now find the i2c clients */
++ for (i = 0; i < bus->slots_nr; i++) {
++
++ slot = &bus->slots[i];
++
++ handle = slot_handles[i];
++ node = of_find_node_by_phandle(handle);
++ if (node == NULL) {
++ dev_warn(&pdev->dev, "Failed to find node with phandle "
++ "0x%x (#%d)\n", handle, i);
++ continue;
++ }
++ dev_dbg(&pdev->dev, "Found device node for phandle "
++ "0x%x (#%d)\n", handle, i);
++
++ client = of_find_i2c_device_by_node(node);
++ if (client == NULL) {
++ dev_warn(&pdev->dev, "Invalid I2C client node with "
++ "phandle 0x%x (#%d)\n", handle, i);
++ continue;
++ }
++
++ slot->client = i2c_use_client(client);
++ /* no use for this anymore */
++ of_node_put(node);
++
++ /* save handle */
++ client = slot->client; /* get again */
++ slot->eeprom_addr = client->addr;
++ dev_dbg(&pdev->dev, "Found i2c_client at #%d "
++ "(address = 0x%02x)\n",
++ i, slot->eeprom_addr);
++
++ r = cape_bus_register_slot(&bus->cape_bus, &slot->cape_slot, i);
++ if (r != 0) {
++ dev_err(&pdev->dev, "Failed to register slot #%d\n", i);
++ continue;
++ }
++
++ dev_info(&pdev->dev, "Registered slot #%d OK\n", i);
++ }
++
++ /* we don't need the handles anymore */
++ devm_kfree(&pdev->dev, slot_handles);
++ slot_handles = NULL;
++
++ r = bone_capebus_register_pdev_adapters(bus);
++ if (r != 0) {
++ dev_err(&pdev->dev, "Failed to register the pdev adapters\n");
++ goto err_no_pdevs;
++ }
++
++ pm_runtime_enable(bus->dev);
++ r = pm_runtime_get_sync(bus->dev);
++ if (IS_ERR_VALUE(r)) {
++ dev_err(&pdev->dev, "Failed to pm_runtime_get_sync()\n");
++ goto err_exit;
++ }
++
++ pm_runtime_put(bus->dev);
++
++ bone_capebus_bus_sysfs_register(bus);
++
++ dev_info(&pdev->dev, "initialized OK.\n");
++
++ return 0;
++
++err_exit:
++ bone_capebus_unregister_pdev_adapters(bus);
++err_no_pdevs:
++ platform_set_drvdata(pdev, NULL);
++
++ return r;
++}
++
++static int __devexit bone_capebus_remove(struct platform_device *pdev)
++{
++ struct bone_capebus_bus *bus = platform_get_drvdata(pdev);
++ int ret;
++
++ bone_capebus_bus_sysfs_unregister(bus);
++ bone_capebus_unregister_pdev_adapters(bus);
++
++ platform_set_drvdata(pdev, NULL);
++
++ ret = pm_runtime_get_sync(&pdev->dev);
++ if (IS_ERR_VALUE(ret))
++ return ret;
++
++ pm_runtime_put(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++#ifdef CONFIG_PM_RUNTIME
++static int bone_capebus_runtime_suspend(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++
++static int bone_capebus_runtime_resume(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++#endif /* CONFIG_PM_RUNTIME */
++
++static struct dev_pm_ops bone_capebus_pm_ops = {
++ SET_RUNTIME_PM_OPS(bone_capebus_runtime_suspend,
++ bone_capebus_runtime_resume, NULL)
++};
++#define BONE_CAPEBUS_PM_OPS (&bone_capebus_pm_ops)
++#else
++#define BONE_CAPEBUS_PM_OPS NULL
++#endif /* CONFIG_PM */
++
++static struct platform_driver bone_capebus_driver = {
++ .probe = bone_capebus_probe,
++ .remove = __devexit_p(bone_capebus_remove),
++ .driver = {
++ .name = "bone-capebus",
++ .owner = THIS_MODULE,
++ .pm = BONE_CAPEBUS_PM_OPS,
++ .of_match_table = of_match_ptr(bone_capebus_of_match),
++ },
++};
++
++module_platform_driver(bone_capebus_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone cape bus controller");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:capebus_bone");
+diff --git a/include/linux/capebus/capebus-bone.h b/include/linux/capebus/capebus-bone.h
+new file mode 100644
+index 0000000..e394304
+--- /dev/null
++++ b/include/linux/capebus/capebus-bone.h
+@@ -0,0 +1,120 @@
++/*
++ * capebus-bone.h
++ *
++ * Cape bus defines and function prototypes for the beaglebone
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef LINUX_CAPEBUS_BONE_H
++#define LINUX_CAPEBUS_BONE_H
++
++#include <linux/list.h>
++#include <linux/capebus.h>
++
++struct bone_capebus_slot {
++ struct cape_slot cape_slot;
++ u32 slot_handle;
++ int eeprom_addr;
++ struct i2c_client *client;
++ unsigned int eeprom_probed : 1;
++ unsigned int eeprom_failed : 1;
++ unsigned int eeprom_override : 1;
++ struct cape_device_id id;
++ char text_id[256];
++ char eeprom_signature[256];
++};
++
++#define to_bone_capebus_slot(n) \
++ container_of(n, struct bone_capebus_slot, cape_slot)
++
++struct bone_capebus_bus {
++ struct cape_bus cape_bus;
++ struct device *dev; /* pdev->dev */
++ int slots_nr;
++ struct bone_capebus_slot *slots;
++};
++
++#define to_bone_capebus_bus(n) \
++ container_of(n, struct bone_capebus_bus, cape_bus)
++
++#define BONE_CAPEBUS_HEADER 0
++#define BONE_CAPEBUS_EEPROM_REV 1
++#define BONE_CAPEBUS_BOARD_NAME 2
++#define BONE_CAPEBUS_VERSION 3
++#define BONE_CAPEBUS_MANUFACTURER 4
++#define BONE_CAPEBUS_PART_NUMBER 5
++#define BONE_CAPEBUS_NUMBER_OF_PINS 6
++#define BONE_CAPEBUS_SERIAL_NUMBER 7
++#define BONE_CAPEBUS_PIN_USAGE 8
++#define BONE_CAPEBUS_VDD_3V3EXP 9
++#define BONE_CAPEBUS_VDD_5V 10
++#define BONE_CAPEBUS_SYS_5V 11
++#define BONE_CAPEBUS_DC_SUPPLIED 12
++#define BONE_CAPEBUS_FIELDS_NR 13
++
++#define BONE_CAPEBUS_MAKE_HEADER(p) \
++ ({ \
++ const u8 *_p = (p); \
++ (((u32)_p[0] << 24) | ((u32)_p[1] << 16) | \
++ ((u32)_p[2] << 8) | (u32)_p[3] ); \
++ })
++
++#define BONE_CAPEBUS_HEADER_VALID 0xaa5533ee
++
++char *bone_capebus_id_get_field(const struct cape_device_id *id,
++ int field, char *buf, int bufsz);
++
++int bone_capebus_match_cntrlboard(const struct cape_device_id *id);
++
++int bone_capebus_match_board(const struct cape_device_id *id,
++ const char **board_names);
++
++/* in pdevs */
++int bone_capebus_register_pdev_adapters(struct bone_capebus_bus *bus);
++void bone_capebus_unregister_pdev_adapters(struct bone_capebus_bus *bus);
++
++/* generic cape support */
++
++struct bone_capebus_generic_device_data {
++ const char *name;
++ const struct of_device_id *of_match;
++ unsigned int units;
++};
++
++struct bone_capebus_generic_device_entry {
++ struct list_head node;
++ const struct bone_capebus_generic_device_data *data;
++ struct platform_device *pdev;
++};
++
++struct bone_capebus_generic_info {
++ struct cape_dev *dev;
++ struct list_head pdev_list;
++};
++
++int bone_capebus_probe_prolog(struct cape_dev *dev,
++ const struct cape_device_id *id);
++
++struct bone_capebus_generic_info *
++bone_capebus_probe_generic(struct cape_dev *dev,
++ const struct cape_device_id *id);
++
++void bone_capebus_remove_generic(
++ struct bone_capebus_generic_info *info);
++
++#endif
diff --git a/patches/linux-3.7-rc6/0135-capebus-Beaglebone-generic-board.patch b/patches/linux-3.7-rc6/0135-capebus-Beaglebone-generic-board.patch
new file mode 100644
index 0000000..a122522
--- /dev/null
+++ b/patches/linux-3.7-rc6/0135-capebus-Beaglebone-generic-board.patch
@@ -0,0 +1,135 @@
+From 48eaefd05e5487625d5b58c959daf785af664b95 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:09:49 +0200
+Subject: [PATCH] capebus: Beaglebone generic board
+
+---
+ drivers/capebus/capes/Kconfig | 6 ++
+ drivers/capebus/capes/Makefile | 1 +
+ drivers/capebus/capes/bone-generic-cape.c | 96 +++++++++++++++++++++++++++++
+ 3 files changed, 103 insertions(+)
+ create mode 100644 drivers/capebus/capes/Kconfig
+ create mode 100644 drivers/capebus/capes/Makefile
+ create mode 100644 drivers/capebus/capes/bone-generic-cape.c
+
+diff --git a/drivers/capebus/capes/Kconfig b/drivers/capebus/capes/Kconfig
+new file mode 100644
+index 0000000..bfe54a6
+--- /dev/null
++++ b/drivers/capebus/capes/Kconfig
+@@ -0,0 +1,6 @@
++config CAPEBUS_BONE_GENERIC
++ tristate "Beaglebone Generic cape driver"
++ depends on CAPEBUS_BONE_CONTROLLER
++ default n
++ help
++ "Select this to enable a generic cape driver; LCD/DVI capes etc"
+diff --git a/drivers/capebus/capes/Makefile b/drivers/capebus/capes/Makefile
+new file mode 100644
+index 0000000..83da381
+--- /dev/null
++++ b/drivers/capebus/capes/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_CAPEBUS_BONE_GENERIC) += bone-generic-cape.o
+diff --git a/drivers/capebus/capes/bone-generic-cape.c b/drivers/capebus/capes/bone-generic-cape.c
+new file mode 100644
+index 0000000..70be50a
+--- /dev/null
++++ b/drivers/capebus/capes/bone-generic-cape.c
+@@ -0,0 +1,96 @@
++/*
++ * Generic cape support
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <asm/barrier.h>
++#include <plat/clock.h>
++#include <plat/omap_device.h>
++#include <linux/clkdev.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++#include <linux/mfd/ti_am335x_tscadc.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++/* fwd decl. */
++extern struct cape_driver bonegeneric_driver;
++
++static const struct of_device_id bonegeneric_of_match[] = {
++ {
++ .compatible = "bone-generic-cape",
++ }, { },
++};
++MODULE_DEVICE_TABLE(of, bonegeneric_of_match);
++
++static int bonegeneric_probe(struct cape_dev *dev,
++ const struct cape_device_id *id)
++{
++ struct bone_capebus_generic_info *ginfo;
++ int err;
++
++ err = bone_capebus_probe_prolog(dev, id);
++ if (err != 0)
++ return err;
++
++ ginfo = bone_capebus_probe_generic(dev, id);
++ if (IS_ERR_OR_NULL(ginfo))
++ return IS_ERR(ginfo) ? PTR_ERR(ginfo) : -ENODEV;
++ dev->drv_priv = ginfo;
++ return 0;
++}
++
++static void bonegeneric_remove(struct cape_dev *dev)
++{
++ bone_capebus_remove_generic(dev->drv_priv);
++}
++
++struct cape_driver bonegeneric_driver = {
++ .driver = {
++ .name = "bonegeneric",
++ .owner = THIS_MODULE,
++ .of_match_table = bonegeneric_of_match,
++ },
++ .probe = bonegeneric_probe,
++ .remove = bonegeneric_remove,
++};
++
++module_capebus_driver(bonegeneric_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone generic cape");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-generic-cape");
diff --git a/patches/linux-3.7-rc6/0136-capebus-Add-beaglebone-geiger-cape.patch b/patches/linux-3.7-rc6/0136-capebus-Add-beaglebone-geiger-cape.patch
new file mode 100644
index 0000000..b927473
--- /dev/null
+++ b/patches/linux-3.7-rc6/0136-capebus-Add-beaglebone-geiger-cape.patch
@@ -0,0 +1,546 @@
+From fbcfeae4d5b070b1300d5b42036a5714fc35cd34 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:12:20 +0200
+Subject: [PATCH] capebus: Add beaglebone geiger cape
+
+---
+ drivers/capebus/capes/Kconfig | 7 +
+ drivers/capebus/capes/Makefile | 1 +
+ drivers/capebus/capes/bone-geiger-cape.c | 506 ++++++++++++++++++++++++++++++
+ 3 files changed, 514 insertions(+)
+ create mode 100644 drivers/capebus/capes/bone-geiger-cape.c
+
+diff --git a/drivers/capebus/capes/Kconfig b/drivers/capebus/capes/Kconfig
+index bfe54a6..0418bef 100644
+--- a/drivers/capebus/capes/Kconfig
++++ b/drivers/capebus/capes/Kconfig
+@@ -4,3 +4,10 @@ config CAPEBUS_BONE_GENERIC
+ default n
+ help
+ "Select this to enable a generic cape driver; LCD/DVI capes etc"
++
++config CAPEBUS_BONE_GEIGER
++ tristate "Beaglebone Geiger cape driver"
++ depends on CAPEBUS_BONE_CONTROLLER
++ default n
++ help
++ "Select this to enable a driver for the geiger cape"
+diff --git a/drivers/capebus/capes/Makefile b/drivers/capebus/capes/Makefile
+index 83da381..d6f94ce 100644
+--- a/drivers/capebus/capes/Makefile
++++ b/drivers/capebus/capes/Makefile
+@@ -1 +1,2 @@
+ obj-$(CONFIG_CAPEBUS_BONE_GENERIC) += bone-generic-cape.o
++obj-$(CONFIG_CAPEBUS_BONE_GEIGER) += bone-geiger-cape.o
+diff --git a/drivers/capebus/capes/bone-geiger-cape.c b/drivers/capebus/capes/bone-geiger-cape.c
+new file mode 100644
+index 0000000..880eaae
+--- /dev/null
++++ b/drivers/capebus/capes/bone-geiger-cape.c
+@@ -0,0 +1,506 @@
++/*
++ * Driver for beaglebone Geiger cape
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <asm/barrier.h>
++#include <plat/clock.h>
++#include <plat/omap_device.h>
++#include <linux/clkdev.h>
++#include <linux/pwm.h>
++#include <linux/math64.h>
++#include <linux/atomic.h>
++#include <linux/leds.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++#include <linux/mfd/ti_am335x_tscadc.h>
++#include <plat/omap_device.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/machine.h>
++#include <linux/iio/consumer.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++/* fwd decl. */
++extern struct cape_driver bonegeiger_driver;
++
++struct bone_geiger_info {
++ struct cape_dev *dev;
++ struct bone_capebus_generic_info *geninfo;
++ struct pwm_device *pwm_dev;
++ int pwm_frequency;
++ int pwm_duty_cycle;
++ int run;
++ atomic64_t counter;
++ int event_gpio;
++ int event_irq;
++ struct led_trigger *event_led; /* event detect */
++ struct led_trigger *run_led; /* running */
++ unsigned long event_blink_delay;
++ struct sysfs_dirent *counter_sd; /* notifier */
++ const char *vsense_name;
++ unsigned int vsense_scale;
++ struct iio_channel *vsense_channel;
++};
++
++static const struct of_device_id bonegeiger_of_match[] = {
++ {
++ .compatible = "bone-geiger-cape",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bonegeiger_of_match);
++
++static int bonegeiger_start(struct cape_dev *dev)
++{
++ struct bone_geiger_info *info = dev->drv_priv;
++ int duty, period;
++
++ if (info->run != 0)
++ return 0;
++
++ /* checks */
++ if (info->pwm_frequency < 1000 || info->pwm_frequency > 50000) {
++ dev_err(&dev->dev, "Cowardly refusing to use a "
++ "frequency of %d\n",
++ info->pwm_frequency);
++ return -EINVAL;
++ }
++ if (info->pwm_duty_cycle > 80) {
++ dev_err(&dev->dev, "Cowardly refusing to use a "
++ "duty cycle of %d\n",
++ info->pwm_duty_cycle);
++ return -EINVAL;
++ }
++
++ period = div_u64(1000000000LLU, info->pwm_frequency);
++ duty = (period * info->pwm_duty_cycle) / 100;
++
++ dev_info(&dev->dev, "starting geiger tube with "
++ "duty=%duns period=%dus\n",
++ duty, period);
++
++ pwm_config(info->pwm_dev, duty, period);
++ pwm_enable(info->pwm_dev);
++
++ info->run = 1;
++ led_trigger_event(info->run_led, LED_FULL);
++
++ return 0;
++}
++
++static int bonegeiger_stop(struct cape_dev *dev)
++{
++ struct bone_geiger_info *info = dev->drv_priv;
++
++ if (info->run == 0)
++ return 0;
++
++ dev_info(&dev->dev, "disabling geiger tube\n");
++ pwm_config(info->pwm_dev, 0, 50000); /* 0% duty cycle, 20KHz */
++ pwm_disable(info->pwm_dev);
++
++ info->run = 0;
++ led_trigger_event(info->run_led, LED_OFF);
++
++ return 0;
++}
++
++static ssize_t bonegeiger_show_run(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++
++ return sprintf(buf, "%d\n", info->run);
++}
++
++static ssize_t bonegeiger_store_run(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ int run, err;
++
++ if (sscanf(buf, "%i", &run) != 1)
++ return -EINVAL;
++
++ if (run)
++ err = bonegeiger_start(cdev);
++ else
++ err = bonegeiger_stop(cdev);
++
++ return err ? err : count;
++}
++
++static ssize_t bonegeiger_show_counter(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++
++ return sprintf(buf, "%llu\n", atomic64_read(&info->counter));
++}
++
++static ssize_t bonegeiger_store_counter(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++
++ atomic64_set(&info->counter, 0); /* just reset */
++ return count;
++}
++
++static ssize_t bonegeiger_show_vsense(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++ int ret, val;
++ u32 mvolts;
++
++ ret = iio_read_channel_raw(info->vsense_channel, &val);
++ if (ret < 0)
++ return ret;
++
++ /* V = (1800 / 4096) * val * scale) = (1.8 * val * scale / 4096) */
++ mvolts = div_u64(1800 * info->vsense_scale * (u64)val, 4096 * 100);
++
++ return sprintf(buf, "%d\n", mvolts);
++}
++
++static DEVICE_ATTR(run, S_IRUGO | S_IWUSR,
++ bonegeiger_show_run, bonegeiger_store_run);
++static DEVICE_ATTR(counter, S_IRUGO | S_IWUSR,
++ bonegeiger_show_counter, bonegeiger_store_counter);
++static DEVICE_ATTR(vsense, S_IRUGO,
++ bonegeiger_show_vsense, NULL);
++
++static int bonegeiger_sysfs_register(struct cape_dev *cdev)
++{
++ int err;
++
++ err = device_create_file(&cdev->dev, &dev_attr_run);
++ if (err != 0)
++ goto err_no_run;
++
++ err = device_create_file(&cdev->dev, &dev_attr_counter);
++ if (err != 0)
++ goto err_no_counter;
++
++ err = device_create_file(&cdev->dev, &dev_attr_vsense);
++ if (err != 0)
++ goto err_no_vsense;
++
++ return 0;
++
++err_no_vsense:
++ device_remove_file(&cdev->dev, &dev_attr_counter);
++err_no_counter:
++ device_remove_file(&cdev->dev, &dev_attr_run);
++err_no_run:
++ return err;
++}
++
++static void bonegeiger_sysfs_unregister(struct cape_dev *cdev)
++{
++ device_remove_file(&cdev->dev, &dev_attr_vsense);
++ device_remove_file(&cdev->dev, &dev_attr_counter);
++ device_remove_file(&cdev->dev, &dev_attr_run);
++}
++
++static irqreturn_t bonegeiger_irq_handler(int irq, void *dev_id)
++{
++ struct cape_dev *dev = dev_id;
++ struct bone_geiger_info *info = dev->drv_priv;
++
++ atomic64_inc(&info->counter);
++
++ led_trigger_blink_oneshot(info->event_led,
++ &info->event_blink_delay, &info->event_blink_delay, 0);
++
++ sysfs_notify_dirent(info->counter_sd);
++
++ return IRQ_HANDLED;
++}
++
++static int bonegeiger_probe(struct cape_dev *dev, const struct cape_device_id *id)
++{
++ char boardbuf[33];
++ char versionbuf[5];
++ const char *board_name;
++ const char *version;
++ struct bone_geiger_info *info;
++ struct pinctrl *pinctrl;
++ struct device_node *node, *pwm_node;
++ phandle phandle;
++ u32 val;
++ int err;
++
++ /* boiler plate probing */
++ err = bone_capebus_probe_prolog(dev, id);
++ if (err != 0)
++ return err;
++
++ /* get the board name (after check of cntrlboard match) */
++ board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ boardbuf, sizeof(boardbuf));
++ /* get the board version */
++ version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ versionbuf, sizeof(versionbuf));
++ /* should never happen; but check anyway */
++ if (board_name == NULL || version == NULL)
++ return -ENODEV;
++
++ dev->drv_priv = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
++ if (dev->drv_priv == NULL) {
++ dev_err(&dev->dev, "Failed to allocate info\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ info = dev->drv_priv;
++
++ pinctrl = devm_pinctrl_get_select_default(&dev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&dev->dev,
++ "pins are not configured from the driver\n");
++
++ node = capebus_of_find_property_node(dev, "version", version, "pwms");
++ if (node == NULL) {
++ dev_err(&dev->dev, "unable to find pwms property\n");
++ err = -ENODEV;
++ goto err_no_pwm;
++ }
++
++ err = of_property_read_u32(node, "pwms", &val);
++ if (err != 0) {
++ dev_err(&dev->dev, "unable to read pwm handle\n");
++ goto err_no_pwm;
++ }
++ phandle = val;
++
++ pwm_node = of_find_node_by_phandle(phandle);
++ if (pwm_node == NULL) {
++ dev_err(&dev->dev, "Failed to pwm node\n");
++ err = -EINVAL;
++ goto err_no_pwm;
++ }
++
++ err = capebus_of_platform_device_enable(pwm_node);
++ of_node_put(pwm_node);
++ if (err != 0) {
++ dev_err(&dev->dev, "Failed to pwm node\n");
++ goto err_no_pwm;
++ }
++
++ info->pwm_dev = of_pwm_request(node, NULL);
++ of_node_put(node);
++ if (IS_ERR(info->pwm_dev)) {
++ dev_err(&dev->dev, "unable to request PWM\n");
++ err = PTR_ERR(info->pwm_dev);
++ goto err_no_pwm;
++ }
++
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "pwm-frequency", &val) != 0) {
++ val = 20000;
++ dev_warn(&dev->dev, "Could not read pwm-frequency property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_frequency = val;
++
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "pwm-duty-cycle", &val) != 0) {
++ val = 60;
++ dev_warn(&dev->dev, "Could not read pwm-duty-cycle property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_duty_cycle = val;
++
++ node = capebus_of_find_property_node(dev, "gpios", version, "pwms");
++ info->event_gpio = of_get_gpio_flags(node, 0, NULL);
++ of_node_put(node);
++ if (IS_ERR_VALUE(info->event_gpio)) {
++ dev_err(&dev->dev, "unable to get event GPIO\n");
++ err = info->event_gpio;
++ goto err_no_gpio;
++ }
++
++ err = gpio_request_one(info->event_gpio,
++ GPIOF_DIR_IN | GPIOF_EXPORT,
++ "bone-geiger-cape-event");
++ if (err != 0) {
++ dev_err(&dev->dev, "failed to request event GPIO\n");
++ goto err_no_gpio;
++ }
++
++ atomic64_set(&info->counter, 0);
++
++ info->event_irq = gpio_to_irq(info->event_gpio);
++ if (IS_ERR_VALUE(info->event_irq)) {
++ dev_err(&dev->dev, "unable to get event GPIO IRQ\n");
++ err = info->event_irq;
++ goto err_no_irq;
++ }
++
++ err = request_irq(info->event_irq, bonegeiger_irq_handler,
++ IRQF_TRIGGER_RISING | IRQF_SHARED,
++ "bone-geiger-irq", dev);
++ if (err != 0) {
++ dev_err(&dev->dev, "unable to request irq\n");
++ goto err_no_irq;
++ }
++
++ err = bonegeiger_sysfs_register(dev);
++ if (err != 0) {
++ dev_err(&dev->dev, "unable to register sysfs\n");
++ goto err_no_sysfs;
++ }
++
++ info->counter_sd = sysfs_get_dirent(dev->dev.kobj.sd, NULL, "counter");
++ if (info->counter_sd == NULL) {
++ dev_err(&dev->dev, "unable to get dirent of counter\n");
++ err = -ENODEV;
++ goto err_no_counter_dirent;
++ }
++
++ led_trigger_register_simple("geiger-event", &info->event_led);
++ led_trigger_register_simple("geiger-run", &info->run_led);
++
++ /* pick up the generics; tsc & leds */
++ info->geninfo = bone_capebus_probe_generic(dev, id);
++ if (info->geninfo == NULL) {
++ dev_err(&dev->dev, "Could not probe generic\n");
++ goto err_no_generic;
++ }
++
++ led_trigger_event(info->run_led, LED_OFF);
++
++ /* default */
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "event-blink-delay", &val) != 0) {
++ val = 30;
++ dev_warn(&dev->dev, "Could not read event-blink-delay "
++ "property; using default %u\n",
++ val);
++ }
++ info->event_blink_delay = val;
++
++ /* default */
++ if (capebus_of_property_read_string(dev,
++ "version", version,
++ "vsense-name", &info->vsense_name) != 0) {
++ info->vsense_name = "AIN5";
++ dev_warn(&dev->dev, "Could not read vsense-name property; "
++ "using default %u\n",
++ val);
++ }
++
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "vsense-scale", &info->vsense_scale) != 0) {
++ info->vsense_scale = 37325; /* 373.25 */
++ dev_warn(&dev->dev, "Could not read vsense-scale property; "
++ "using default %u\n",
++ info->vsense_scale);
++ }
++
++ info->vsense_channel = iio_channel_get(NULL, info->vsense_name);
++ if (IS_ERR(info->vsense_channel)) {
++ dev_err(&dev->dev, "Could not get AIN5 analog input\n");
++ err = PTR_ERR(info->vsense_channel);
++ goto err_no_vsense;
++ }
++
++ dev_info(&dev->dev, "ready\n");
++
++ err = bonegeiger_start(dev);
++ if (err != 0) {
++ dev_err(&dev->dev, "Could not start geiger device\n");
++ goto err_no_start;
++ }
++
++ return 0;
++
++err_no_start:
++ iio_channel_release(info->vsense_channel);
++err_no_vsense:
++ bone_capebus_remove_generic(info->geninfo);
++err_no_generic:
++ led_trigger_unregister_simple(info->run_led);
++ led_trigger_unregister_simple(info->event_led);
++ sysfs_put(info->counter_sd);
++err_no_counter_dirent:
++ bonegeiger_sysfs_unregister(dev);
++err_no_sysfs:
++ free_irq(info->event_irq, dev);
++err_no_irq:
++ gpio_free(info->event_gpio);
++err_no_gpio:
++ pwm_put(info->pwm_dev);
++err_no_pwm:
++ devm_kfree(&dev->dev, info);
++err_no_mem:
++ return err;
++}
++
++static void bonegeiger_remove(struct cape_dev *dev)
++{
++ struct bone_geiger_info *info = dev->drv_priv;
++
++ dev_info(&dev->dev, "Removing geiger cape driver...\n");
++
++ bonegeiger_stop(dev);
++
++ iio_channel_release(info->vsense_channel);
++ bone_capebus_remove_generic(info->geninfo);
++ led_trigger_unregister_simple(info->run_led);
++ led_trigger_unregister_simple(info->event_led);
++ sysfs_put(info->counter_sd);
++ bonegeiger_sysfs_unregister(dev);
++ free_irq(info->event_irq, dev);
++ gpio_free(info->event_gpio);
++ pwm_put(info->pwm_dev);
++}
++
++struct cape_driver bonegeiger_driver = {
++ .driver = {
++ .name = "bonegeiger",
++ .owner = THIS_MODULE,
++ .of_match_table = bonegeiger_of_match,
++ },
++ .probe = bonegeiger_probe,
++ .remove = bonegeiger_remove,
++};
++
++module_capebus_driver(bonegeiger_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone geiger cape");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-geiger-cape");
diff --git a/patches/linux-3.7-rc6/0137-capebus-Beaglebone-capebus-DT-update.patch b/patches/linux-3.7-rc6/0137-capebus-Beaglebone-capebus-DT-update.patch
new file mode 100644
index 0000000..6bd80a7
--- /dev/null
+++ b/patches/linux-3.7-rc6/0137-capebus-Beaglebone-capebus-DT-update.patch
@@ -0,0 +1,745 @@
+From 7433fff737ca214acb70407dfec888312a19057f Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:16:57 +0200
+Subject: [PATCH] capebus: Beaglebone capebus DT update
+
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 689 +++++++++++++++++++++++++++--
+ 1 file changed, 659 insertions(+), 30 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 99240a5..46d5f27 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -51,6 +51,143 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++ i2c2_pins: pinmux_i2c2_pins {
++ pinctrl-single,pins = <
++ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ >;
++ };
++
++ bone_dvi_cape_led_pins: pinmux_bone_dvi_cape_led_pins {
++ pinctrl-single,pins = <
++ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
++ 0x4c 0x07 /* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_dvi_cape_dvi_00A0_pins: pinmux_bone_dvi_cape_dvi_00A0_pins {
++ pinctrl-single,pins = <
++ 0x1c 0x07 /* gpmc_ad7.gpio1_7, OUTPUT | MODE7 - DVIPDn */
++
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_dvi_cape_dvi_00A1_pins: pinmux_bone_dvi_cape_dvi_00A1_pins {
++ pinctrl-single,pins = <
++ 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - DVIPDn */
++
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_geiger_cape_led_pins: pinmux_bone_geiger_cape_led_pins {
++ pinctrl-single,pins = <
++ 0xe4 0x07 /* lcd_hsync.gpio2_23, OUTPUT | MODE7 */
++ 0xec 0x07 /* lcd_ac_bias_en.gpio2_25, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_geiger_cape_pins: pinmux_bone_geiger_cape_pins {
++ pinctrl-single,pins = <
++ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ /* 0x19c 0x34 */ /* mcasp0_ahclkr.eCAP2_in_PWM2_out, OMAP_MUX_MODE4 | INPUT_PULLUP */
++ 0x19c 0x37 /* mcasp0_ahclkr.gpio3_17, OMAP_MUX_MODE4 | INPUT_PULLUP */
++ >;
++ };
++
++ bone_lcd3_cape_led_00A0_pins: pinmux_bone_lcd3_cape_led_00A0_pins {
++ pinctrl-single,pins = <
++ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
++ 0x4c 0x07 /* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_lcd3_cape_lcd_pins: pinmux_bone_lcd3_cape_lcd_pins {
++ pinctrl-single,pins = <
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_lcd3_cape_keys_00A0_pins: pinmux_bone_lcd3_cape_keys_00A0_pins {
++ pinctrl-single,pins = <
++ 0x040 0x2f /* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ 0x044 0x2f /* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
++ 0x1a4 0x2f /* mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
++ 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ 0x164 0x2f /* ecap0_in_pwm0_out.gpio0_7, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ pwm_bl_pins: pinmux_pwm_bl_pins {
++ pinctrl-single,pins = <
++ 0x4c 0x06 /* gpmc_a3.ehrpwm1b, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ // 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ weather_cape_w1_pins: pinmux_weather_cape_w1_pins {
++ pinctrl-single,pins = <
++ 0x0c 0x37 /* gpmc_ad3.gpio1_3, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7 - w1-gpio */
++ >;
++ };
+ };
+
+ ocp {
+@@ -92,16 +229,6 @@
+ };
+ };
+
+- i2c1: i2c@44e0b000 {
+- status = "okay";
+- clock-frequency = <400000>;
+-
+- tps: tps@24 {
+- reg = <0x24>;
+- };
+-
+- };
+-
+ gpevt {
+ compatible = "gpevt";
+ pinctrl-names = "default";
+@@ -110,15 +237,117 @@
+ dma-names = "gpioevt";
+ gpio-evt = <&gpio3 2 0>;
+ };
++
++ };
++
++ capebus: capebus@0 {
++ compatible = "bone-capebus";
++
++ bone_dvi_cape: cape@0 {
++ compatible = "bone-generic-cape";
++ };
++
++ bone_geiger_cape: cape@1 {
++ compatible = "bone-geiger-cape";
++ };
++
++ bone_lcd3_cape: cape@2 {
++ compatible = "bone-generic-cape";
++ };
++
++ bone_lcd7_cape: cape@3 {
++ compatible = "bone-lcd7-cape";
++ };
++
++ bone_weather_cape: cape@4 {
++ compatible = "bone-generic-cape";
++ };
++
++ bone_adafruit_cape: cape@5 {
++ compatible = "bone-generic-cape";
++ };
++
++ /* overrides; no EEPROM (prototyping) */
++// override@3 {
++// compatible = "bone-capebus-slot-override";
++// slot = <3>;
++// board-name = "Geiger Cape";
++// version = "00A0";
++// manufacturer = "Geiger Inc";
++// /* TODO: Add the rest */
++// };
++
++// override@2 {
++// compatible = "bone-capebus-slot-override";
++// slot = <2>;
++// board-name = "Weather Cape";
++// version = "00A0";
++// manufacturer = "CCO Inc";
++// /* TODO: Add the rest */
++// };
++
++// override@1 {
++// compatible = "bone-capebus-slot-override";
++// slot = <1>;
++// board-name = "Adafruit 1.8 Cape";
++// version = "00A0";
++// manufacturer = "Adafruit";
++// /* TODO: Add the rest */
++// };
++
++// override@0 {
++// compatible = "bone-capebus-slot-override";
++// slot = <0>;
++// board-name = "BeagleBone Weather CAPE";
++// version = "00A0";
++// manufacturer = "Beagleboardtoys";
++// /* TODO: Add the rest */
++// };
+ };
+
+- backlight {
+- compatible = "pwm-backlight";
+- pwms = <&ehrpwm1 0 500000 0>;
+- pwm-names = "st7735fb";
+- brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+- default-brightness-level = <50>; /* index to the array above */
+- };
++};
++
++&i2c0 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ tps: tps@24 {
++ reg = <0x24>;
++ };
++
++ baseboard_eeprom: baseboard_eeprom@50 {
++ compatible = "at,24c256";
++ reg = <0x50>;
++ };
++};
++
++&i2c2 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c2_pins>;
++
++ clock-frequency = <100000>;
++
++ /* OK, I know these are cape but for now it will do */
++ cape_eeprom_0: cape_eeprom_0@54 {
++ compatible = "at,24c256";
++ reg = <0x54>;
++ };
++
++ cape_eeprom_1: cape_eeprom_1@55 {
++ compatible = "at,24c256";
++ reg = <0x55>;
++ };
++
++ cape_eeprom_2: cape_eeprom_2@56 {
++ compatible = "at,24c256";
++ reg = <0x56>;
++ };
++
++ cape_eeprom_3: cape_eeprom_3@57 {
++ compatible = "at,24c256";
++ reg = <0x57>;
++ };
+ };
+
+ /include/ "tps65217.dtsi"
+@@ -165,6 +394,7 @@
+ regulator-always-on;
+ };
+ };
++
+ };
+
+ &mmc1 {
+@@ -172,21 +402,8 @@
+ };
+
+ &spi1 {
+- status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+-
+- lcd@0 {
+- compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
+- spi-max-frequency = <8000000>;
+- reg = <0>;
+- spi-cpol;
+- spi-cpha;
+- pinctrl-names = "default";
+- pinctrl-0 = <&lcd_pins>;
+- st7735-rst = <&gpio4 19 0>;
+- st7735-dc = <&gpio4 21 0>;
+- };
+ };
+
+ &edma {
+@@ -200,3 +417,415 @@
+ &cpsw_emac1 {
+ phy_id = "4a101000.mdio:01";
+ };
++
++&ehrpwm1 {
++ status = "okay";
++};
++
++&capebus {
++ slots = <&cape_eeprom_0 &cape_eeprom_1 &cape_eeprom_2 &cape_eeprom_3>;
++};
++
++&bone_dvi_cape {
++ board-name = "BeagleBone DVI-D CAPE";
++
++ /* hacky, since this is not a proper DT platform device */
++ /* but until we have DT bindings... */
++ version@00A0 {
++ version = "00A0";
++ dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++ powerdn-gpio = <&gpio2 7 0>;
++ };
++ };
++
++ version@00A1 {
++ version = "00A1", "01";
++ dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++ powerdn-gpio = <&gpio2 31 0>;
++ };
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_led_pins>;
++
++ dvi-led0 {
++ label = "dvi:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ dvi-led1 {
++ label = "dvi:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "mmc0";
++ default-state = "off";
++ };
++ };
++};
++
++&bone_geiger_cape {
++ board-name = "Geiger Cape";
++
++ /* note that these can't be versioned... */
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_geiger_cape_pins>;
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "bone-geiger-cape";
++
++ pwm-frequency = <20000>; /* 20KHz */
++ pwm-duty-cycle = <60>; /* 60% */
++
++ event-blink-delay = <30>; /* 30ms */
++
++ gpios = <&gpio4 17 0>; /* pulse */
++
++ vsense-name = "AIN5"; /* analog vsense */
++ vsense-scale = <37325>; /* scaling */
++
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ adc-channels = <8>;
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_geiger_cape_led_pins>;
++
++ geiger-led0 {
++ label = "geiger:green:usr0";
++ gpios = <&gpio3 23 0>;
++ linux,default-trigger = "geiger-run";
++ default-state = "off";
++ };
++
++ geiger-led1 {
++ label = "geiger:red:usr1";
++ gpios = <&gpio3 25 0>;
++ linux,default-trigger = "geiger-event";
++ default-state = "off";
++ };
++ };
++};
++
++&bone_lcd3_cape {
++ board-name = "BeagleBone LCD3 CAPE";
++
++ /* hacky, since this is not a proper DT platform device */
++ /* but until we have DT bindings... */
++ lcd3 {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++
++ ti,hwmods = "lcdc";
++
++ disp-pll = <16000000>;
++ panel-type = "CDTech_S035Q01";
++ };
++
++ /* same thing as above */
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ tsc-wires = <4>;
++ tsc-x-plate-resistance = <200>;
++ tsc-steps = <6>;
++
++ adc-channels = <4>;
++ };
++
++ version@00A0 {
++ version = "00A0";
++
++ backlight {
++ compatible = "tps65217-backlight";
++ isel = <1>;
++ fdim = <200>;
++
++ tps = <&tps>; /* link to the tps */
++ brightness = <100>;
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_led_00A0_pins>;
++
++ lcd3-led0 {
++ label = "lcd3:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ lcd3-led1 {
++ label = "lcd3:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "cpu0";
++ default-state = "off";
++ };
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_keys_00A0_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ button@1 {
++ debounce_interval = <50>;
++ linux,code = <105>;
++ label = "left";
++ gpios = <&gpio2 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@2 {
++ debounce_interval = <50>;
++ linux,code = <106>;
++ label = "right";
++ gpios = <&gpio2 17 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@3 {
++ debounce_interval = <50>;
++ linux,code = <103>;
++ label = "up";
++ gpios = <&gpio4 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio2 28 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 7 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++ };
++};
++
++&bone_lcd7_cape {
++ board-name = "BeagleBone LCD7 CAPE";
++
++ /* hacky, since this is not a proper DT platform device */
++ /* but until we have DT bindings... */
++ lcd7 {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++
++ ti,hwmods = "lcdc";
++
++ disp-pll = <60000000>;
++ panel-type = "TFC_S9700RTWV35TR_01B";
++ };
++
++ /* same thing as above */
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ tsc-wires = <4>;
++ tsc-x-plate-resistance = <200>;
++ tsc-steps = <6>;
++
++ adc-channels = <4>;
++ };
++
++ version@00A0 {
++ version = "00A0";
++
++ backlight {
++ compatible = "tps65217-backlight";
++ isel = <1>;
++ fdim = <200>;
++
++ tps = <&tps>; /* link to the tps */
++ brightness = <100>;
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_led_00A0_pins>;
++
++ lcd3-led0 {
++ label = "lcd3:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ lcd3-led1 {
++ label = "lcd3:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "cpu0";
++ default-state = "off";
++ };
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_keys_00A0_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ button@1 {
++ debounce_interval = <50>;
++ linux,code = <105>;
++ label = "left";
++ gpios = <&gpio2 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@2 {
++ debounce_interval = <50>;
++ linux,code = <106>;
++ label = "right";
++ gpios = <&gpio2 17 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@3 {
++ debounce_interval = <50>;
++ linux,code = <103>;
++ label = "up";
++ gpios = <&gpio4 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio2 28 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 7 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++ };
++};
++
++&bone_weather_cape {
++ board-name = "BeagleBone Weather CAPE";
++
++ i2c2-devices {
++ compatible = "i2c-dt";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ parent = <&i2c2>;
++
++ /* Ambient light sensor */
++ tsl2550@39 {
++ compatible = "tsl,tsl2550";
++ reg = <0x39>;
++ };
++
++ /* Humidity Sensor */
++ sht21@40 {
++ compatible = "sensiron,sht21";
++ reg = <0x40>;
++ };
++
++ /* Barometric pressure sensor */
++ bmp085@77 {
++ compatible = "bosch,bmp085";
++ reg = <0x77>;
++ };
++ };
++
++ onewire@0 {
++ compatible = "w1-gpio";
++ pinctrl-names = "default";
++ pinctrl-0 = <&weather_cape_w1_pins>;
++ status = "okay";
++
++ gpios = <&gpio2 3 0>;
++ };
++
++};
++
++&bone_adafruit_cape {
++ board-name = "Adafruit 1.8 Cape";
++
++ backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_bl_pins>;
++
++ pwms = <&ehrpwm1 1 500000 0>;
++ pwm-names = "st7735fb";
++ brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
++ default-brightness-level = <50>; /* index to the array above */
++ };
++
++ spi1-devices {
++ compatible = "spi-dt";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ parent = <&spi1>;
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ pinctrl-names = "default";
++ pinctrl-0 = <&lcd_pins>;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++
++ };
++};
diff --git a/patches/linux-3.7-rc6/0138-beaglebone-Update-default-config-for-capebus.patch b/patches/linux-3.7-rc6/0138-beaglebone-Update-default-config-for-capebus.patch
new file mode 100644
index 0000000..49a5602
--- /dev/null
+++ b/patches/linux-3.7-rc6/0138-beaglebone-Update-default-config-for-capebus.patch
@@ -0,0 +1,3909 @@
+From 116c5c49c91c1638620714ddfb74eb21b79505c3 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:17:39 +0200
+Subject: [PATCH] beaglebone: Update default config for capebus
+
+---
+ defconfig | 3893 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 3893 insertions(+)
+ create mode 100644 defconfig
+
+diff --git a/defconfig b/defconfig
+new file mode 100644
+index 0000000..ee51fa1
+--- /dev/null
++++ b/defconfig
+@@ -0,0 +1,3893 @@
++#
++# Automatically generated file; DO NOT EDIT.
++# Linux/arm 3.7.0-rc2 Kernel Configuration
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_HAVE_PROC_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_ARCH_HAS_CPUFREQ=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_NEED_DMA_MAP_STATE=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_ARM_PATCH_PHYS_VIRT=y
++CONFIG_NEED_MACH_GPIO_H=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_HAVE_IRQ_WORK=y
++CONFIG_IRQ_WORK=y
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_CROSS_COMPILE=""
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_HAVE_KERNEL_GZIP=y
++CONFIG_HAVE_KERNEL_LZMA=y
++CONFIG_HAVE_KERNEL_XZ=y
++CONFIG_HAVE_KERNEL_LZO=y
++# CONFIG_KERNEL_GZIP is not set
++# CONFIG_KERNEL_LZMA is not set
++# CONFIG_KERNEL_XZ is not set
++CONFIG_KERNEL_LZO=y
++CONFIG_DEFAULT_HOSTNAME="(none)"
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_POSIX_MQUEUE_SYSCTL=y
++# CONFIG_FHANDLE is not set
++# CONFIG_AUDIT is not set
++CONFIG_HAVE_GENERIC_HARDIRQS=y
++
++#
++# IRQ subsystem
++#
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_IRQ_SHOW=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_CHIP=y
++CONFIG_IRQ_DOMAIN=y
++# CONFIG_IRQ_DOMAIN_DEBUG is not set
++CONFIG_SPARSE_IRQ=y
++CONFIG_KTIME_SCALAR=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
++
++#
++# Timers subsystem
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++
++#
++# CPU/Task time and stats accounting
++#
++CONFIG_TICK_CPU_ACCOUNTING=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_TASKSTATS=y
++CONFIG_TASK_DELAY_ACCT=y
++CONFIG_TASK_XACCT=y
++CONFIG_TASK_IO_ACCOUNTING=y
++
++#
++# RCU Subsystem
++#
++CONFIG_TREE_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_RCU_FANOUT=32
++CONFIG_RCU_FANOUT_LEAF=16
++# CONFIG_RCU_FANOUT_EXACT is not set
++# CONFIG_RCU_FAST_NO_HZ is not set
++# CONFIG_TREE_RCU_TRACE is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=17
++CONFIG_CGROUPS=y
++# CONFIG_CGROUP_DEBUG is not set
++# CONFIG_CGROUP_FREEZER is not set
++# CONFIG_CGROUP_DEVICE is not set
++# CONFIG_CPUSETS is not set
++# CONFIG_CGROUP_CPUACCT is not set
++# CONFIG_RESOURCE_COUNTERS is not set
++# CONFIG_CGROUP_PERF is not set
++CONFIG_CGROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_CFS_BANDWIDTH is not set
++# CONFIG_RT_GROUP_SCHED is not set
++# CONFIG_BLK_CGROUP is not set
++# CONFIG_CHECKPOINT_RESTORE is not set
++CONFIG_NAMESPACES=y
++CONFIG_UTS_NS=y
++CONFIG_IPC_NS=y
++CONFIG_PID_NS=y
++CONFIG_NET_NS=y
++CONFIG_SCHED_AUTOGROUP=y
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
++# CONFIG_RD_XZ is not set
++# CONFIG_RD_LZO is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EXPERT=y
++CONFIG_HAVE_UID16=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++# CONFIG_EMBEDDED is not set
++CONFIG_HAVE_PERF_EVENTS=y
++CONFIG_PERF_USE_VMALLOC=y
++
++#
++# Kernel Performance Events And Counters
++#
++CONFIG_PERF_EVENTS=y
++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_COMPAT_BRK=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_PROFILING=y
++CONFIG_TRACEPOINTS=y
++CONFIG_OPROFILE=m
++CONFIG_HAVE_OPROFILE=y
++CONFIG_KPROBES=y
++# CONFIG_JUMP_LABEL is not set
++CONFIG_KRETPROBES=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_ARCH_TRACEHOOK=y
++CONFIG_HAVE_DMA_ATTRS=y
++CONFIG_HAVE_DMA_CONTIGUOUS=y
++CONFIG_USE_GENERIC_SMP_HELPERS=y
++CONFIG_GENERIC_SMP_IDLE_THREAD=y
++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
++CONFIG_HAVE_CLK=y
++CONFIG_HAVE_DMA_API_DEBUG=y
++CONFIG_HAVE_HW_BREAKPOINT=y
++CONFIG_HAVE_ARCH_JUMP_LABEL=y
++CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
++CONFIG_GENERIC_KERNEL_THREAD=y
++CONFIG_GENERIC_KERNEL_EXECVE=y
++CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
++CONFIG_MODULES_USE_ELF_REL=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_GCOV_KERNEL is not set
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_FORCE_LOAD=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++# CONFIG_MODULE_SIG is not set
++CONFIG_STOP_MACHINE=y
++CONFIG_BLOCK=y
++CONFIG_LBDAF=y
++CONFIG_BLK_DEV_BSG=y
++CONFIG_BLK_DEV_BSGLIB=y
++CONFIG_BLK_DEV_INTEGRITY=y
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++CONFIG_MAC_PARTITION=y
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++CONFIG_EFI_PARTITION=y
++# CONFIG_SYSV68_PARTITION is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_PADATA=y
++CONFIG_ASN1=m
++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
++CONFIG_INLINE_READ_UNLOCK=y
++CONFIG_INLINE_READ_UNLOCK_IRQ=y
++CONFIG_INLINE_WRITE_UNLOCK=y
++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
++CONFIG_MUTEX_SPIN_ON_OWNER=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_MMU=y
++# CONFIG_ARCH_MULTIPLATFORM is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_BCM2835 is not set
++# CONFIG_ARCH_CNS3XXX is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
++# CONFIG_ARCH_SIRF is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_MXS is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_DOVE is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_W90X900 is not set
++# CONFIG_ARCH_LPC32XX is not set
++# CONFIG_ARCH_TEGRA is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_SHMOBILE is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C24XX is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_S5P64X0 is not set
++# CONFIG_ARCH_S5PC100 is not set
++# CONFIG_ARCH_S5PV210 is not set
++# CONFIG_ARCH_EXYNOS is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_U300 is not set
++# CONFIG_ARCH_U8500 is not set
++# CONFIG_ARCH_NOMADIK is not set
++# CONFIG_PLAT_SPEAR is not set
++# CONFIG_ARCH_DAVINCI is not set
++CONFIG_ARCH_OMAP=y
++# CONFIG_ARCH_VT8500 is not set
++# CONFIG_ARCH_ZYNQ is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_KEYBOARD_GPIO_POLLED is not set
++
++#
++# TI OMAP Common Features
++#
++# CONFIG_ARCH_OMAP1 is not set
++CONFIG_ARCH_OMAP2PLUS=y
++
++#
++# OMAP Feature Selections
++#
++CONFIG_OMAP_RESET_CLOCKS=y
++CONFIG_OMAP_MUX=y
++CONFIG_OMAP_MUX_DEBUG=y
++CONFIG_OMAP_MUX_WARNINGS=y
++# CONFIG_OMAP_MBOX_FWK is not set
++CONFIG_OMAP_32K_TIMER=y
++# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
++CONFIG_OMAP_32K_TIMER_HZ=128
++CONFIG_OMAP_DM_TIMER=y
++CONFIG_OMAP_PM_NOOP=y
++CONFIG_MACH_OMAP_GENERIC=y
++
++#
++# TI OMAP2/3/4 Specific Features
++#
++CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
++CONFIG_SOC_HAS_OMAP2_SDRC=y
++# CONFIG_SOC_HAS_REALTIME_COUNTER is not set
++# CONFIG_ARCH_OMAP2 is not set
++CONFIG_ARCH_OMAP3=y
++CONFIG_ARCH_OMAP4=y
++# CONFIG_SOC_OMAP5 is not set
++CONFIG_SOC_OMAP3430=y
++# CONFIG_SOC_TI81XX is not set
++CONFIG_SOC_AM33XX=y
++CONFIG_OMAP_PACKAGE_CBB=y
++CONFIG_OMAP_PACKAGE_CBL=y
++CONFIG_OMAP_PACKAGE_CBS=y
++
++#
++# OMAP Board Type
++#
++CONFIG_MACH_OMAP3_BEAGLE=y
++# CONFIG_MACH_DEVKIT8000 is not set
++# CONFIG_MACH_OMAP_LDP is not set
++# CONFIG_MACH_OMAP3530_LV_SOM is not set
++# CONFIG_MACH_OMAP3_TORPEDO is not set
++# CONFIG_MACH_OVERO is not set
++# CONFIG_MACH_OMAP3EVM is not set
++# CONFIG_MACH_OMAP3517EVM is not set
++# CONFIG_MACH_CRANEBOARD is not set
++# CONFIG_MACH_OMAP3_PANDORA is not set
++# CONFIG_MACH_TOUCHBOOK is not set
++# CONFIG_MACH_OMAP_3430SDP is not set
++# CONFIG_MACH_NOKIA_RM680 is not set
++# CONFIG_MACH_NOKIA_RX51 is not set
++# CONFIG_MACH_OMAP_ZOOM2 is not set
++# CONFIG_MACH_OMAP_ZOOM3 is not set
++# CONFIG_MACH_CM_T35 is not set
++# CONFIG_MACH_CM_T3517 is not set
++CONFIG_MACH_IGEP0020=y
++# CONFIG_MACH_IGEP0030 is not set
++# CONFIG_MACH_SBC3530 is not set
++# CONFIG_MACH_OMAP_3630SDP is not set
++# CONFIG_MACH_OMAP_4430SDP is not set
++CONFIG_MACH_OMAP4_PANDA=y
++# CONFIG_OMAP3_EMU is not set
++# CONFIG_OMAP3_SDRC_AC_TIMING is not set
++# CONFIG_OMAP4_ERRATA_I688 is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_V7=y
++CONFIG_CPU_32v6K=y
++CONFIG_CPU_32v7=y
++CONFIG_CPU_ABRT_EV7=y
++CONFIG_CPU_PABRT_V7=y
++CONFIG_CPU_CACHE_V7=y
++CONFIG_CPU_CACHE_VIPT=y
++CONFIG_CPU_COPY_V6=y
++CONFIG_CPU_TLB_V7=y
++CONFIG_CPU_HAS_ASID=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_LPAE is not set
++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
++CONFIG_ARM_THUMB=y
++CONFIG_ARM_THUMBEE=y
++# CONFIG_ARM_VIRT_EXT is not set
++CONFIG_SWP_EMULATE=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_BPREDICT_DISABLE is not set
++CONFIG_OUTER_CACHE=y
++CONFIG_OUTER_CACHE_SYNC=y
++CONFIG_CACHE_L2X0=y
++CONFIG_CACHE_PL310=y
++CONFIG_ARM_L1_CACHE_SHIFT_6=y
++CONFIG_ARM_L1_CACHE_SHIFT=6
++CONFIG_ARM_DMA_MEM_BUFFERABLE=y
++CONFIG_ARM_NR_BANKS=8
++CONFIG_MULTI_IRQ_HANDLER=y
++# CONFIG_ARM_ERRATA_430973 is not set
++# CONFIG_ARM_ERRATA_458693 is not set
++# CONFIG_ARM_ERRATA_460075 is not set
++# CONFIG_ARM_ERRATA_742230 is not set
++# CONFIG_ARM_ERRATA_742231 is not set
++CONFIG_PL310_ERRATA_588369=y
++CONFIG_ARM_ERRATA_720789=y
++CONFIG_PL310_ERRATA_727915=y
++# CONFIG_ARM_ERRATA_743622 is not set
++# CONFIG_ARM_ERRATA_751472 is not set
++# CONFIG_PL310_ERRATA_753970 is not set
++# CONFIG_ARM_ERRATA_754322 is not set
++# CONFIG_ARM_ERRATA_754327 is not set
++# CONFIG_ARM_ERRATA_764369 is not set
++# CONFIG_PL310_ERRATA_769419 is not set
++# CONFIG_ARM_ERRATA_775420 is not set
++CONFIG_ARM_GIC=y
++CONFIG_TI_PRIV_EDMA=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_HAVE_SMP=y
++CONFIG_SMP=y
++CONFIG_SMP_ON_UP=y
++CONFIG_ARM_CPU_TOPOLOGY=y
++# CONFIG_SCHED_MC is not set
++# CONFIG_SCHED_SMT is not set
++CONFIG_HAVE_ARM_SCU=y
++# CONFIG_ARM_ARCH_TIMER is not set
++CONFIG_HAVE_ARM_TWD=y
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++CONFIG_NR_CPUS=4
++CONFIG_HOTPLUG_CPU=y
++CONFIG_LOCAL_TIMERS=y
++CONFIG_ARCH_NR_GPIO=0
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=128
++CONFIG_THUMB2_KERNEL=y
++CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11=y
++CONFIG_ARM_ASM_UNIFIED=y
++CONFIG_AEABI=y
++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_HAVE_ARCH_PFN_VALID=y
++CONFIG_HIGHMEM=y
++# CONFIG_HIGHPTE is not set
++CONFIG_HW_PERF_EVENTS=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_HAVE_MEMBLOCK=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_COMPACTION is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_KSM is not set
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
++CONFIG_CROSS_MEMORY_ATTACH=y
++# CONFIG_CLEANCACHE is not set
++# CONFIG_FRONTSWAP is not set
++CONFIG_FORCE_MAX_ZONEORDER=12
++CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
++# CONFIG_SECCOMP is not set
++# CONFIG_CC_STACKPROTECTOR is not set
++# CONFIG_XEN is not set
++
++#
++# Boot options
++#
++CONFIG_USE_OF=y
++CONFIG_ATAGS=y
++# CONFIG_DEPRECATED_PARAM_STRUCT is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_ARM_APPENDED_DTB=y
++CONFIG_ARM_ATAG_DTB_COMPAT=y
++CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++# CONFIG_CRASH_DUMP is not set
++# CONFIG_AUTO_ZRELADDR is not set
++
++#
++# CPU Power Management
++#
++
++#
++# CPU Frequency scaling
++#
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++CONFIG_CPU_FREQ_STAT=y
++CONFIG_CPU_FREQ_STAT_DETAILS=y
++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++CONFIG_CPU_FREQ_GOV_POWERSAVE=y
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
++CONFIG_GENERIC_CPUFREQ_CPU0=y
++
++#
++# ARM CPU frequency scaling drivers
++#
++# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
++CONFIG_CPU_IDLE=y
++CONFIG_CPU_IDLE_GOV_LADDER=y
++CONFIG_CPU_IDLE_GOV_MENU=y
++CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_VFP=y
++CONFIG_VFPv3=y
++CONFIG_NEON=y
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_MISC=y
++# CONFIG_COREDUMP is not set
++
++#
++# Power management options
++#
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++CONFIG_PM_SLEEP=y
++CONFIG_PM_SLEEP_SMP=y
++# CONFIG_PM_AUTOSLEEP is not set
++# CONFIG_PM_WAKELOCKS is not set
++CONFIG_PM_RUNTIME=y
++CONFIG_PM=y
++CONFIG_PM_DEBUG=y
++# CONFIG_PM_ADVANCED_DEBUG is not set
++# CONFIG_PM_TEST_SUSPEND is not set
++CONFIG_PM_SLEEP_DEBUG=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_HAS_OPP=y
++CONFIG_PM_OPP=y
++CONFIG_PM_CLK=y
++CONFIG_CPU_PM=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_ARM_CPU_SUSPEND=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_DIAG=m
++CONFIG_UNIX=y
++CONFIG_UNIX_DIAG=m
++CONFIG_XFRM=y
++CONFIG_XFRM_ALGO=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++CONFIG_XFRM_MIGRATE=y
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_XFRM_IPCOMP=m
++CONFIG_NET_KEY=y
++CONFIG_NET_KEY_MIGRATE=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++# CONFIG_IP_FIB_TRIE_STATS is not set
++# CONFIG_IP_MULTIPLE_TABLES is not set
++# CONFIG_IP_ROUTE_MULTIPATH is not set
++# CONFIG_IP_ROUTE_VERBOSE is not set
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_NET_IPIP=m
++CONFIG_NET_IPGRE_DEMUX=m
++CONFIG_NET_IPGRE=m
++# CONFIG_NET_IPGRE_BROADCAST is not set
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_ARPD=y
++CONFIG_SYN_COOKIES=y
++# CONFIG_NET_IPVTI is not set
++CONFIG_INET_AH=m
++CONFIG_INET_ESP=m
++CONFIG_INET_IPCOMP=m
++CONFIG_INET_XFRM_TUNNEL=m
++CONFIG_INET_TUNNEL=m
++CONFIG_INET_XFRM_MODE_TRANSPORT=m
++CONFIG_INET_XFRM_MODE_TUNNEL=m
++CONFIG_INET_XFRM_MODE_BEET=m
++CONFIG_INET_LRO=m
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++CONFIG_INET_UDP_DIAG=m
++CONFIG_TCP_CONG_ADVANCED=y
++CONFIG_TCP_CONG_BIC=m
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_TCP_CONG_WESTWOOD=m
++CONFIG_TCP_CONG_HTCP=m
++CONFIG_TCP_CONG_HSTCP=m
++CONFIG_TCP_CONG_HYBLA=m
++CONFIG_TCP_CONG_VEGAS=m
++CONFIG_TCP_CONG_SCALABLE=m
++CONFIG_TCP_CONG_LP=m
++CONFIG_TCP_CONG_VENO=m
++CONFIG_TCP_CONG_YEAH=m
++CONFIG_TCP_CONG_ILLINOIS=m
++CONFIG_DEFAULT_CUBIC=y
++# CONFIG_DEFAULT_RENO is not set
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++CONFIG_IPV6_PRIVACY=y
++CONFIG_IPV6_ROUTER_PREF=y
++CONFIG_IPV6_ROUTE_INFO=y
++CONFIG_IPV6_OPTIMISTIC_DAD=y
++CONFIG_INET6_AH=m
++CONFIG_INET6_ESP=m
++CONFIG_INET6_IPCOMP=m
++CONFIG_IPV6_MIP6=m
++CONFIG_INET6_XFRM_TUNNEL=m
++CONFIG_INET6_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
++CONFIG_IPV6_SIT=m
++# CONFIG_IPV6_SIT_6RD is not set
++CONFIG_IPV6_NDISC_NODETYPE=y
++CONFIG_IPV6_TUNNEL=m
++CONFIG_IPV6_GRE=m
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_IPV6_SUBTREES=y
++CONFIG_IPV6_MROUTE=y
++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IPV6_PIMSM_V2=y
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++CONFIG_BRIDGE_NETFILTER=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_ACCT is not set
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_TPROXY is not set
++CONFIG_NETFILTER_XTABLES=m
++
++#
++# Xtables combined modules
++#
++# CONFIG_NETFILTER_XT_MARK is not set
++
++#
++# Xtables targets
++#
++# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++CONFIG_NETFILTER_XT_TARGET_HL=m
++# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
++# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
++# CONFIG_NETFILTER_XT_TARGET_LED is not set
++# CONFIG_NETFILTER_XT_TARGET_LOG is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
++# CONFIG_NETFILTER_XT_TARGET_TEE is not set
++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
++
++#
++# Xtables matches
++#
++# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_CPU is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++CONFIG_NETFILTER_XT_MATCH_ECN=m
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++CONFIG_NETFILTER_XT_MATCH_HL=m
++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++CONFIG_IP_VS=m
++# CONFIG_IP_VS_IPV6 is not set
++# CONFIG_IP_VS_DEBUG is not set
++CONFIG_IP_VS_TAB_BITS=12
++
++#
++# IPVS transport protocol load balancing support
++#
++# CONFIG_IP_VS_PROTO_TCP is not set
++# CONFIG_IP_VS_PROTO_UDP is not set
++# CONFIG_IP_VS_PROTO_AH_ESP is not set
++# CONFIG_IP_VS_PROTO_ESP is not set
++# CONFIG_IP_VS_PROTO_AH is not set
++# CONFIG_IP_VS_PROTO_SCTP is not set
++
++#
++# IPVS scheduler
++#
++# CONFIG_IP_VS_RR is not set
++# CONFIG_IP_VS_WRR is not set
++# CONFIG_IP_VS_LC is not set
++# CONFIG_IP_VS_WLC is not set
++# CONFIG_IP_VS_LBLC is not set
++# CONFIG_IP_VS_LBLCR is not set
++# CONFIG_IP_VS_DH is not set
++# CONFIG_IP_VS_SH is not set
++# CONFIG_IP_VS_SED is not set
++# CONFIG_IP_VS_NQ is not set
++
++#
++# IPVS SH scheduler
++#
++CONFIG_IP_VS_SH_TAB_BITS=8
++
++#
++# IPVS application helper
++#
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV4 is not set
++CONFIG_IP_NF_QUEUE=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_AH=m
++CONFIG_IP_NF_MATCH_ECN=m
++CONFIG_IP_NF_MATCH_RPFILTER=m
++CONFIG_IP_NF_MATCH_TTL=m
++CONFIG_IP_NF_FILTER=m
++CONFIG_IP_NF_TARGET_REJECT=m
++CONFIG_IP_NF_TARGET_ULOG=m
++CONFIG_IP_NF_MANGLE=m
++CONFIG_IP_NF_TARGET_ECN=m
++CONFIG_IP_NF_TARGET_TTL=m
++CONFIG_IP_NF_RAW=m
++CONFIG_IP_NF_SECURITY=m
++CONFIG_IP_NF_ARPTABLES=m
++CONFIG_IP_NF_ARPFILTER=m
++CONFIG_IP_NF_ARP_MANGLE=m
++
++#
++# IPv6: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV6 is not set
++CONFIG_IP6_NF_IPTABLES=m
++CONFIG_IP6_NF_MATCH_AH=m
++CONFIG_IP6_NF_MATCH_EUI64=m
++CONFIG_IP6_NF_MATCH_FRAG=m
++CONFIG_IP6_NF_MATCH_OPTS=m
++CONFIG_IP6_NF_MATCH_HL=m
++CONFIG_IP6_NF_MATCH_IPV6HEADER=m
++CONFIG_IP6_NF_MATCH_MH=m
++CONFIG_IP6_NF_MATCH_RPFILTER=m
++CONFIG_IP6_NF_MATCH_RT=m
++CONFIG_IP6_NF_TARGET_HL=m
++CONFIG_IP6_NF_FILTER=m
++CONFIG_IP6_NF_TARGET_REJECT=m
++CONFIG_IP6_NF_MANGLE=m
++CONFIG_IP6_NF_RAW=m
++CONFIG_IP6_NF_SECURITY=m
++# CONFIG_BRIDGE_NF_EBTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_RDS is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++CONFIG_L2TP=m
++CONFIG_L2TP_DEBUGFS=m
++# CONFIG_L2TP_V3 is not set
++CONFIG_STP=m
++CONFIG_GARP=m
++CONFIG_BRIDGE=m
++CONFIG_BRIDGE_IGMP_SNOOPING=y
++CONFIG_NET_DSA=m
++# CONFIG_NET_DSA_TAG_DSA is not set
++# CONFIG_NET_DSA_TAG_EDSA is not set
++# CONFIG_NET_DSA_TAG_TRAILER is not set
++CONFIG_VLAN_8021Q=m
++CONFIG_VLAN_8021Q_GVRP=y
++# CONFIG_DECNET is not set
++CONFIG_LLC=m
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_WAN_ROUTER is not set
++CONFIG_PHONET=m
++# CONFIG_IEEE802154 is not set
++CONFIG_NET_SCHED=y
++
++#
++# Queueing/Scheduling
++#
++# CONFIG_NET_SCH_CBQ is not set
++# CONFIG_NET_SCH_HTB is not set
++# CONFIG_NET_SCH_HFSC is not set
++# CONFIG_NET_SCH_PRIO is not set
++# CONFIG_NET_SCH_MULTIQ is not set
++# CONFIG_NET_SCH_RED is not set
++# CONFIG_NET_SCH_SFB is not set
++# CONFIG_NET_SCH_SFQ is not set
++# CONFIG_NET_SCH_TEQL is not set
++# CONFIG_NET_SCH_TBF is not set
++# CONFIG_NET_SCH_GRED is not set
++# CONFIG_NET_SCH_DSMARK is not set
++# CONFIG_NET_SCH_NETEM is not set
++# CONFIG_NET_SCH_DRR is not set
++# CONFIG_NET_SCH_MQPRIO is not set
++# CONFIG_NET_SCH_CHOKE is not set
++# CONFIG_NET_SCH_QFQ is not set
++CONFIG_NET_SCH_CODEL=y
++CONFIG_NET_SCH_FQ_CODEL=y
++# CONFIG_NET_SCH_PLUG is not set
++
++#
++# Classification
++#
++CONFIG_NET_CLS=y
++# CONFIG_NET_CLS_BASIC is not set
++# CONFIG_NET_CLS_TCINDEX is not set
++# CONFIG_NET_CLS_ROUTE4 is not set
++# CONFIG_NET_CLS_FW is not set
++# CONFIG_NET_CLS_U32 is not set
++# CONFIG_NET_CLS_RSVP is not set
++# CONFIG_NET_CLS_RSVP6 is not set
++# CONFIG_NET_CLS_FLOW is not set
++CONFIG_NET_CLS_CGROUP=m
++# CONFIG_NET_EMATCH is not set
++# CONFIG_NET_CLS_ACT is not set
++CONFIG_NET_SCH_FIFO=y
++# CONFIG_DCB is not set
++CONFIG_DNS_RESOLVER=y
++CONFIG_BATMAN_ADV=m
++CONFIG_BATMAN_ADV_BLA=y
++# CONFIG_BATMAN_ADV_DEBUG is not set
++CONFIG_OPENVSWITCH=m
++CONFIG_RPS=y
++CONFIG_RFS_ACCEL=y
++CONFIG_XPS=y
++CONFIG_NETPRIO_CGROUP=m
++CONFIG_BQL=y
++CONFIG_BPF_JIT=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NET_TCPPROBE is not set
++# CONFIG_NET_DROP_MONITOR is not set
++# CONFIG_HAMRADIO is not set
++CONFIG_CAN=m
++CONFIG_CAN_RAW=m
++CONFIG_CAN_BCM=m
++CONFIG_CAN_GW=m
++
++#
++# CAN Device Drivers
++#
++# CONFIG_CAN_VCAN is not set
++# CONFIG_CAN_SLCAN is not set
++CONFIG_CAN_DEV=m
++CONFIG_CAN_CALC_BITTIMING=y
++CONFIG_CAN_TI_HECC=m
++CONFIG_CAN_MCP251X=m
++# CONFIG_CAN_SJA1000 is not set
++CONFIG_CAN_C_CAN=m
++CONFIG_CAN_C_CAN_PLATFORM=m
++# CONFIG_CAN_CC770 is not set
++
++#
++# CAN USB interfaces
++#
++CONFIG_CAN_EMS_USB=m
++CONFIG_CAN_ESD_USB2=m
++CONFIG_CAN_PEAK_USB=m
++# CONFIG_CAN_SOFTING is not set
++# CONFIG_CAN_DEBUG_DEVICES is not set
++CONFIG_IRDA=m
++
++#
++# IrDA protocols
++#
++CONFIG_IRLAN=m
++# CONFIG_IRNET is not set
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++
++#
++# IrDA options
++#
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++# CONFIG_IRDA_DEBUG is not set
++
++#
++# Infrared-port device drivers
++#
++
++#
++# SIR device drivers
++#
++CONFIG_IRTTY_SIR=m
++
++#
++# Dongle support
++#
++CONFIG_DONGLE=y
++CONFIG_ESI_DONGLE=m
++CONFIG_ACTISYS_DONGLE=m
++CONFIG_TEKRAM_DONGLE=m
++CONFIG_TOIM3232_DONGLE=m
++CONFIG_LITELINK_DONGLE=m
++CONFIG_MA600_DONGLE=m
++CONFIG_GIRBIL_DONGLE=m
++CONFIG_MCP2120_DONGLE=m
++CONFIG_OLD_BELKIN_DONGLE=m
++CONFIG_ACT200L_DONGLE=m
++CONFIG_KINGSUN_DONGLE=m
++CONFIG_KSDAZZLE_DONGLE=m
++CONFIG_KS959_DONGLE=m
++
++#
++# FIR device drivers
++#
++CONFIG_USB_IRDA=m
++# CONFIG_SIGMATEL_FIR is not set
++CONFIG_MCS_FIR=m
++CONFIG_BT=m
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++
++#
++# Bluetooth device drivers
++#
++CONFIG_BT_HCIBTUSB=m
++CONFIG_BT_HCIBTSDIO=m
++CONFIG_BT_HCIUART=m
++CONFIG_BT_HCIUART_H4=y
++CONFIG_BT_HCIUART_BCSP=y
++CONFIG_BT_HCIUART_ATH3K=y
++CONFIG_BT_HCIUART_LL=y
++CONFIG_BT_HCIUART_3WIRE=y
++CONFIG_BT_HCIBCM203X=m
++CONFIG_BT_HCIBPA10X=m
++CONFIG_BT_HCIBFUSB=m
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_BT_MRVL is not set
++CONFIG_BT_ATH3K=m
++# CONFIG_BT_WILINK is not set
++CONFIG_AF_RXRPC=m
++# CONFIG_AF_RXRPC_DEBUG is not set
++# CONFIG_RXKAD is not set
++CONFIG_FIB_RULES=y
++CONFIG_WIRELESS=y
++CONFIG_WIRELESS_EXT=y
++CONFIG_WEXT_CORE=y
++CONFIG_WEXT_PROC=y
++CONFIG_WEXT_SPY=y
++CONFIG_CFG80211=m
++# CONFIG_NL80211_TESTMODE is not set
++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
++# CONFIG_CFG80211_REG_DEBUG is not set
++# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
++CONFIG_CFG80211_DEFAULT_PS=y
++CONFIG_CFG80211_DEBUGFS=y
++# CONFIG_CFG80211_INTERNAL_REGDB is not set
++CONFIG_CFG80211_WEXT=y
++CONFIG_LIB80211=m
++# CONFIG_LIB80211_DEBUG is not set
++CONFIG_MAC80211=m
++CONFIG_MAC80211_HAS_RC=y
++CONFIG_MAC80211_RC_PID=y
++CONFIG_MAC80211_RC_MINSTREL=y
++CONFIG_MAC80211_RC_MINSTREL_HT=y
++CONFIG_MAC80211_RC_DEFAULT_PID=y
++# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
++CONFIG_MAC80211_RC_DEFAULT="pid"
++CONFIG_MAC80211_MESH=y
++CONFIG_MAC80211_LEDS=y
++CONFIG_MAC80211_DEBUGFS=y
++# CONFIG_MAC80211_MESSAGE_TRACING is not set
++# CONFIG_MAC80211_DEBUG_MENU is not set
++CONFIG_WIMAX=m
++CONFIG_WIMAX_DEBUG_LEVEL=8
++CONFIG_RFKILL=m
++CONFIG_RFKILL_LEDS=y
++CONFIG_RFKILL_INPUT=y
++CONFIG_RFKILL_REGULATOR=m
++CONFIG_RFKILL_GPIO=m
++CONFIG_NET_9P=m
++CONFIG_NET_9P_VIRTIO=m
++# CONFIG_NET_9P_DEBUG is not set
++# CONFIG_CAIF is not set
++CONFIG_CEPH_LIB=m
++# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
++# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
++CONFIG_NFC=m
++CONFIG_NFC_NCI=m
++CONFIG_NFC_HCI=m
++CONFIG_NFC_SHDLC=y
++# CONFIG_NFC_LLCP is not set
++
++#
++# Near Field Communication (NFC) devices
++#
++CONFIG_PN544_HCI_NFC=m
++CONFIG_NFC_PN533=m
++# CONFIG_NFC_WILINK is not set
++CONFIG_HAVE_BPF_JIT=y
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH=""
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_GENERIC_CPU_DEVICES is not set
++CONFIG_REGMAP=y
++CONFIG_REGMAP_I2C=y
++CONFIG_REGMAP_SPI=m
++CONFIG_REGMAP_MMIO=y
++# CONFIG_DMA_SHARED_BUFFER is not set
++# CONFIG_CMA is not set
++
++#
++# Bus devices
++#
++CONFIG_OMAP_OCP2SCP=y
++CONFIG_OMAP_INTERCONNECT=y
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_TESTS is not set
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++CONFIG_MTD_OF_PARTS=y
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_SM_FTL is not set
++# CONFIG_MTD_OOPS is not set
++# CONFIG_MTD_SWAP is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_PHYSMAP_OF is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SST25L is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_DOCG3 is not set
++CONFIG_MTD_NAND_ECC=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_ECC_BCH is not set
++# CONFIG_MTD_SM_COMMON is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++# CONFIG_MTD_NAND_GPIO is not set
++CONFIG_MTD_NAND_OMAP2=y
++# CONFIG_MTD_NAND_OMAP_BCH is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_DOCG4 is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
++CONFIG_MTD_ONENAND=y
++CONFIG_MTD_ONENAND_VERIFY_WRITE=y
++# CONFIG_MTD_ONENAND_GENERIC is not set
++CONFIG_MTD_ONENAND_OMAP2=y
++# CONFIG_MTD_ONENAND_OTP is not set
++# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
++# CONFIG_MTD_ONENAND_SIM is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++CONFIG_MTD_UBI=y
++CONFIG_MTD_UBI_WL_THRESHOLD=4096
++CONFIG_MTD_UBI_BEB_LIMIT=20
++CONFIG_MTD_UBI_FASTMAP=y
++# CONFIG_MTD_UBI_GLUEBI is not set
++CONFIG_DTC=y
++CONFIG_OF=y
++
++#
++# Device Tree and Open Firmware support
++#
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_OF_SELFTEST is not set
++CONFIG_OF_FLATTREE=y
++CONFIG_OF_EARLY_FLATTREE=y
++CONFIG_OF_ADDRESS=y
++CONFIG_OF_IRQ=y
++CONFIG_OF_DEVICE=y
++CONFIG_OF_I2C=y
++CONFIG_OF_NET=y
++CONFIG_OF_MDIO=y
++CONFIG_OF_MTD=y
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_DRBD is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MG_DISK is not set
++CONFIG_VIRTIO_BLK=m
++# CONFIG_BLK_DEV_RBD is not set
++
++#
++# Misc devices
++#
++# CONFIG_SENSORS_LIS3LV02D is not set
++# CONFIG_AD525X_DPOT is not set
++# CONFIG_ATMEL_PWM is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_APDS9802ALS is not set
++# CONFIG_ISL29003 is not set
++# CONFIG_ISL29020 is not set
++CONFIG_SENSORS_TSL2550=m
++# CONFIG_SENSORS_BH1780 is not set
++# CONFIG_SENSORS_BH1770 is not set
++# CONFIG_SENSORS_APDS990X is not set
++# CONFIG_HMC6352 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_TI_DAC7512 is not set
++CONFIG_BMP085=y
++CONFIG_BMP085_I2C=m
++# CONFIG_BMP085_SPI is not set
++# CONFIG_USB_SWITCH_FSA9480 is not set
++# CONFIG_GPEVT is not set
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
++CONFIG_EEPROM_AT24=y
++# CONFIG_EEPROM_AT25 is not set
++# CONFIG_EEPROM_LEGACY is not set
++# CONFIG_EEPROM_MAX6875 is not set
++CONFIG_EEPROM_93CX6=y
++# CONFIG_EEPROM_93XX46 is not set
++
++#
++# Texas Instruments shared transport line discipline
++#
++CONFIG_TI_ST=m
++# CONFIG_SENSORS_LIS3_SPI is not set
++# CONFIG_SENSORS_LIS3_I2C is not set
++
++#
++# Altera FPGA firmware download module
++#
++# CONFIG_ALTERA_STAPL is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI_MOD=y
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_ISCSI_BOOT_SYSFS is not set
++# CONFIG_LIBFC is not set
++# CONFIG_LIBFCOE is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_SCSI_VIRTIO=m
++# CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
++# CONFIG_ATA is not set
++CONFIG_MD=y
++# CONFIG_BLK_DEV_MD is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_TARGET_CORE is not set
++CONFIG_NETDEVICES=y
++CONFIG_NET_CORE=y
++# CONFIG_BONDING is not set
++# CONFIG_DUMMY is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_MII=y
++# CONFIG_NET_TEAM is not set
++# CONFIG_MACVLAN is not set
++CONFIG_VXLAN=m
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++CONFIG_VIRTIO_NET=m
++
++#
++# CAIF transport drivers
++#
++
++#
++# Distributed Switch Architecture drivers
++#
++# CONFIG_NET_DSA_MV88E6XXX is not set
++# CONFIG_NET_DSA_MV88E6060 is not set
++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
++# CONFIG_NET_DSA_MV88E6131 is not set
++# CONFIG_NET_DSA_MV88E6123_61_65 is not set
++CONFIG_ETHERNET=y
++CONFIG_NET_VENDOR_BROADCOM=y
++# CONFIG_B44 is not set
++# CONFIG_NET_CALXEDA_XGMAC is not set
++CONFIG_NET_VENDOR_CHELSIO=y
++CONFIG_NET_VENDOR_CIRRUS=y
++# CONFIG_CS89x0 is not set
++# CONFIG_DM9000 is not set
++# CONFIG_DNET is not set
++CONFIG_NET_VENDOR_FARADAY=y
++# CONFIG_FTMAC100 is not set
++# CONFIG_FTGMAC100 is not set
++CONFIG_NET_VENDOR_INTEL=y
++CONFIG_NET_VENDOR_I825XX=y
++CONFIG_NET_VENDOR_MARVELL=y
++CONFIG_NET_VENDOR_MICREL=y
++CONFIG_KS8842=m
++CONFIG_KS8851=y
++CONFIG_KS8851_MLL=y
++CONFIG_NET_VENDOR_MICROCHIP=y
++# CONFIG_ENC28J60 is not set
++CONFIG_NET_VENDOR_NATSEMI=y
++CONFIG_NET_VENDOR_8390=y
++# CONFIG_AX88796 is not set
++# CONFIG_ETHOC is not set
++CONFIG_NET_VENDOR_SEEQ=y
++# CONFIG_SEEQ8005 is not set
++CONFIG_NET_VENDOR_SMSC=y
++CONFIG_SMC91X=y
++# CONFIG_SMC911X is not set
++CONFIG_SMSC911X=y
++# CONFIG_SMSC911X_ARCH_HOOKS is not set
++CONFIG_NET_VENDOR_STMICRO=y
++# CONFIG_STMMAC_ETH is not set
++CONFIG_NET_VENDOR_TI=y
++CONFIG_TI_DAVINCI_EMAC=y
++CONFIG_TI_DAVINCI_MDIO=y
++CONFIG_TI_DAVINCI_CPDMA=y
++CONFIG_TI_CPSW=y
++CONFIG_NET_VENDOR_WIZNET=y
++# CONFIG_WIZNET_W5100 is not set
++# CONFIG_WIZNET_W5300 is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_AMD_PHY is not set
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++# CONFIG_LXT_PHY is not set
++# CONFIG_CICADA_PHY is not set
++# CONFIG_VITESSE_PHY is not set
++CONFIG_SMSC_PHY=y
++# CONFIG_BROADCOM_PHY is not set
++# CONFIG_BCM87XX_PHY is not set
++# CONFIG_ICPLUS_PHY is not set
++# CONFIG_REALTEK_PHY is not set
++# CONFIG_NATIONAL_PHY is not set
++# CONFIG_STE10XP is not set
++# CONFIG_LSI_ET1011C_PHY is not set
++# CONFIG_MICREL_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_MDIO_BUS_MUX=m
++# CONFIG_MDIO_BUS_MUX_GPIO is not set
++CONFIG_MDIO_BUS_MUX_MMIOREG=m
++# CONFIG_MICREL_KS8995MA is not set
++CONFIG_PPP=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_MPPE=m
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPPOE=m
++CONFIG_PPTP=m
++CONFIG_PPPOL2TP=m
++CONFIG_PPP_ASYNC=m
++# CONFIG_PPP_SYNC_TTY is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=m
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX8817X=y
++CONFIG_USB_NET_CDCETHER=y
++# CONFIG_USB_NET_CDC_EEM is not set
++CONFIG_USB_NET_CDC_NCM=y
++# CONFIG_USB_NET_DM9601 is not set
++# CONFIG_USB_NET_SMSC75XX is not set
++CONFIG_USB_NET_SMSC95XX=y
++# CONFIG_USB_NET_GL620A is not set
++CONFIG_USB_NET_NET1080=y
++# CONFIG_USB_NET_PLUSB is not set
++# CONFIG_USB_NET_MCS7830 is not set
++# CONFIG_USB_NET_RNDIS_HOST is not set
++CONFIG_USB_NET_CDC_SUBSET=y
++CONFIG_USB_ALI_M5632=y
++CONFIG_USB_AN2720=y
++CONFIG_USB_BELKIN=y
++CONFIG_USB_ARMLINUX=y
++CONFIG_USB_EPSON2888=y
++CONFIG_USB_KC2190=y
++CONFIG_USB_NET_ZAURUS=y
++# CONFIG_USB_NET_CX82310_ETH is not set
++# CONFIG_USB_NET_KALMIA is not set
++# CONFIG_USB_NET_QMI_WWAN is not set
++# CONFIG_USB_HSO is not set
++# CONFIG_USB_NET_INT51X1 is not set
++# CONFIG_USB_CDC_PHONET is not set
++# CONFIG_USB_IPHETH is not set
++# CONFIG_USB_SIERRA_NET is not set
++# CONFIG_USB_VL600 is not set
++CONFIG_WLAN=y
++# CONFIG_LIBERTAS_THINFIRM is not set
++# CONFIG_AT76C50X_USB is not set
++# CONFIG_USB_ZD1201 is not set
++# CONFIG_USB_NET_RNDIS_WLAN is not set
++# CONFIG_RTL8187 is not set
++# CONFIG_MAC80211_HWSIM is not set
++# CONFIG_ATH_COMMON is not set
++# CONFIG_B43 is not set
++# CONFIG_B43LEGACY is not set
++# CONFIG_BRCMFMAC is not set
++# CONFIG_HOSTAP is not set
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++# CONFIG_LIBERTAS_SPI is not set
++CONFIG_LIBERTAS_DEBUG=y
++# CONFIG_LIBERTAS_MESH is not set
++# CONFIG_P54_COMMON is not set
++# CONFIG_RT2X00 is not set
++# CONFIG_RTL8192CU is not set
++# CONFIG_WL_TI is not set
++# CONFIG_ZD1211RW is not set
++# CONFIG_MWIFIEX is not set
++
++#
++# WiMAX Wireless Broadband devices
++#
++# CONFIG_WIMAX_I2400M_USB is not set
++# CONFIG_WAN is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++# CONFIG_INPUT_SPARSEKMAP is not set
++CONFIG_INPUT_MATRIXKMAP=y
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++CONFIG_INPUT_JOYDEV=y
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ADP5588 is not set
++# CONFIG_KEYBOARD_ADP5589 is not set
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_QT1070 is not set
++# CONFIG_KEYBOARD_QT2160 is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++CONFIG_KEYBOARD_GPIO=y
++# CONFIG_KEYBOARD_TCA6416 is not set
++# CONFIG_KEYBOARD_TCA8418 is not set
++# CONFIG_KEYBOARD_MATRIX is not set
++# CONFIG_KEYBOARD_LM8323 is not set
++# CONFIG_KEYBOARD_LM8333 is not set
++# CONFIG_KEYBOARD_MAX7359 is not set
++# CONFIG_KEYBOARD_MCS is not set
++# CONFIG_KEYBOARD_MPR121 is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_KEYBOARD_SAMSUNG is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_OMAP4 is not set
++CONFIG_KEYBOARD_TWL4030=y
++# CONFIG_KEYBOARD_XTKBD is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_SENTELIC is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_MOUSE_GPIO is not set
++# CONFIG_MOUSE_SYNAPTICS_I2C is not set
++# CONFIG_MOUSE_SYNAPTICS_USB is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_AD7877 is not set
++# CONFIG_TOUCHSCREEN_AD7879 is not set
++# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
++# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
++# CONFIG_TOUCHSCREEN_BU21013 is not set
++# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
++# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
++# CONFIG_TOUCHSCREEN_DYNAPRO is not set
++# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
++# CONFIG_TOUCHSCREEN_EETI is not set
++# CONFIG_TOUCHSCREEN_EGALAX is not set
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_ILI210X is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
++# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
++# CONFIG_TOUCHSCREEN_MAX11801 is not set
++# CONFIG_TOUCHSCREEN_MCS5000 is not set
++CONFIG_TOUCHSCREEN_MMS114=m
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_INEXIO is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++CONFIG_TOUCHSCREEN_EDT_FT5X06=m
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y
++# CONFIG_TOUCHSCREEN_PIXCIR is not set
++CONFIG_TOUCHSCREEN_WM97XX=m
++CONFIG_TOUCHSCREEN_WM9705=y
++CONFIG_TOUCHSCREEN_WM9712=y
++CONFIG_TOUCHSCREEN_WM9713=y
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
++# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
++# CONFIG_TOUCHSCREEN_TSC2005 is not set
++# CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_TOUCHSCREEN_W90X900 is not set
++# CONFIG_TOUCHSCREEN_ST1232 is not set
++# CONFIG_TOUCHSCREEN_TPS6507X is not set
++CONFIG_INPUT_MISC=y
++# CONFIG_INPUT_AD714X is not set
++# CONFIG_INPUT_BMA150 is not set
++# CONFIG_INPUT_MMA8450 is not set
++# CONFIG_INPUT_MPU3050 is not set
++# CONFIG_INPUT_GP2A is not set
++# CONFIG_INPUT_GPIO_TILT_POLLED is not set
++# CONFIG_INPUT_ATI_REMOTE2 is not set
++# CONFIG_INPUT_KEYSPAN_REMOTE is not set
++# CONFIG_INPUT_KXTJ9 is not set
++# CONFIG_INPUT_POWERMATE is not set
++# CONFIG_INPUT_YEALINK is not set
++# CONFIG_INPUT_CM109 is not set
++CONFIG_INPUT_TWL4030_PWRBUTTON=y
++# CONFIG_INPUT_TWL4030_VIBRA is not set
++# CONFIG_INPUT_UINPUT is not set
++# CONFIG_INPUT_PCF8574 is not set
++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
++# CONFIG_INPUT_ADXL34X is not set
++# CONFIG_INPUT_CMA3000 is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_SERIO_ALTERA_PS2 is not set
++# CONFIG_SERIO_PS2MULT is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_VT_CONSOLE_SLEEP=y
++CONFIG_HW_CONSOLE=y
++CONFIG_VT_HW_CONSOLE_BINDING=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_N_GSM is not set
++# CONFIG_TRACE_SINK is not set
++CONFIG_DEVKMEM=y
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=32
++CONFIG_SERIAL_8250_RUNTIME_UARTS=4
++CONFIG_SERIAL_8250_EXTENDED=y
++CONFIG_SERIAL_8250_MANY_PORTS=y
++CONFIG_SERIAL_8250_SHARE_IRQ=y
++CONFIG_SERIAL_8250_DETECT_IRQ=y
++CONFIG_SERIAL_8250_RSA=y
++# CONFIG_SERIAL_8250_DW is not set
++# CONFIG_SERIAL_8250_EM is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_MAX3100 is not set
++# CONFIG_SERIAL_MAX310X is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_SERIAL_OMAP=y
++CONFIG_SERIAL_OMAP_CONSOLE=y
++# CONFIG_SERIAL_SCCNXP is not set
++# CONFIG_SERIAL_TIMBERDALE is not set
++# CONFIG_SERIAL_ALTERA_JTAGUART is not set
++# CONFIG_SERIAL_ALTERA_UART is not set
++# CONFIG_SERIAL_IFX6X60 is not set
++# CONFIG_SERIAL_XILINX_PS_UART is not set
++# CONFIG_TTY_PRINTK is not set
++CONFIG_HVC_DRIVER=y
++# CONFIG_HVC_DCC is not set
++CONFIG_VIRTIO_CONSOLE=m
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
++# CONFIG_HW_RANDOM_ATMEL is not set
++CONFIG_HW_RANDOM_VIRTIO=m
++# CONFIG_HW_RANDOM_EXYNOS is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++CONFIG_I2C_COMPAT=y
++CONFIG_I2C_CHARDEV=y
++# CONFIG_I2C_MUX is not set
++CONFIG_I2C_HELPER_AUTO=y
++CONFIG_I2C_ALGOBIT=m
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_OMAP=y
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_PXA_PCI is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_XILINX is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_DIOLAN_U2C is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_ALTERA is not set
++# CONFIG_SPI_BITBANG is not set
++# CONFIG_SPI_GPIO is not set
++# CONFIG_SPI_OC_TINY is not set
++CONFIG_SPI_OMAP24XX=y
++# CONFIG_SPI_PXA2XX_PCI is not set
++CONFIG_SPI_SC18IS602=m
++CONFIG_SPI_XCOMM=m
++# CONFIG_SPI_XILINX is not set
++# CONFIG_SPI_DESIGNWARE is not set
++
++#
++# SPI Protocol Masters
++#
++CONFIG_SPI_SPIDEV=y
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_HSI is not set
++
++#
++# PPS support
++#
++# CONFIG_PPS is not set
++
++#
++# PPS generators support
++#
++
++#
++# PTP clock support
++#
++
++#
++# Enable Device Drivers -> PPS to see the PTP clock options.
++#
++CONFIG_PINCTRL=y
++
++#
++# Pin controllers
++#
++CONFIG_PINMUX=y
++CONFIG_PINCONF=y
++# CONFIG_DEBUG_PINCTRL is not set
++CONFIG_PINCTRL_SINGLE=y
++# CONFIG_PINCTRL_SAMSUNG is not set
++# CONFIG_PINCTRL_EXYNOS4 is not set
++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_OF_GPIO=y
++CONFIG_DEBUG_GPIO=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO drivers:
++#
++# CONFIG_GPIO_GENERIC_PLATFORM is not set
++# CONFIG_GPIO_EM is not set
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX7300 is not set
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCF857X is not set
++# CONFIG_GPIO_SX150X is not set
++CONFIG_GPIO_TWL4030=y
++# CONFIG_GPIO_ADP5588 is not set
++# CONFIG_GPIO_ADNP is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_GPIO_MC33880 is not set
++# CONFIG_GPIO_74X164 is not set
++
++#
++# AC97 GPIO expanders:
++#
++
++#
++# MODULbus GPIO expanders:
++#
++CONFIG_W1=y
++CONFIG_W1_CON=y
++
++#
++# 1-wire Bus Masters
++#
++CONFIG_W1_MASTER_DS2490=m
++CONFIG_W1_MASTER_DS2482=m
++CONFIG_W1_MASTER_DS1WM=m
++CONFIG_W1_MASTER_GPIO=y
++CONFIG_HDQ_MASTER_OMAP=m
++
++#
++# 1-wire Slaves
++#
++CONFIG_W1_SLAVE_THERM=y
++CONFIG_W1_SLAVE_SMEM=y
++CONFIG_W1_SLAVE_DS2408=m
++CONFIG_W1_SLAVE_DS2423=m
++CONFIG_W1_SLAVE_DS2431=m
++CONFIG_W1_SLAVE_DS2433=m
++CONFIG_W1_SLAVE_DS2433_CRC=y
++CONFIG_W1_SLAVE_DS2760=m
++CONFIG_W1_SLAVE_DS2780=m
++CONFIG_W1_SLAVE_DS2781=m
++CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_W1_SLAVE_BQ27000=m
++CONFIG_POWER_SUPPLY=y
++# CONFIG_POWER_SUPPLY_DEBUG is not set
++# CONFIG_PDA_POWER is not set
++CONFIG_GENERIC_ADC_BATTERY=m
++# CONFIG_TEST_POWER is not set
++# CONFIG_BATTERY_DS2760 is not set
++# CONFIG_BATTERY_DS2780 is not set
++# CONFIG_BATTERY_DS2781 is not set
++# CONFIG_BATTERY_DS2782 is not set
++# CONFIG_BATTERY_SBS is not set
++# CONFIG_BATTERY_BQ27x00 is not set
++# CONFIG_BATTERY_MAX17040 is not set
++# CONFIG_BATTERY_MAX17042 is not set
++# CONFIG_CHARGER_ISP1704 is not set
++# CONFIG_CHARGER_MAX8903 is not set
++# CONFIG_CHARGER_TWL4030 is not set
++# CONFIG_CHARGER_LP8727 is not set
++CONFIG_CHARGER_GPIO=m
++# CONFIG_CHARGER_MANAGER is not set
++# CONFIG_CHARGER_SMB347 is not set
++# CONFIG_POWER_AVS is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Native drivers
++#
++# CONFIG_SENSORS_AD7314 is not set
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++CONFIG_SENSORS_ADT7410=m
++# CONFIG_SENSORS_ADT7411 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7475 is not set
++# CONFIG_SENSORS_ASC7621 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS620 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_G760A is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++CONFIG_SENSORS_GPIO_FAN=m
++CONFIG_SENSORS_HIH6130=m
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_JC42 is not set
++# CONFIG_SENSORS_LINEAGE is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM73 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_LTC4151 is not set
++# CONFIG_SENSORS_LTC4215 is not set
++# CONFIG_SENSORS_LTC4245 is not set
++# CONFIG_SENSORS_LTC4261 is not set
++# CONFIG_SENSORS_LM95241 is not set
++# CONFIG_SENSORS_LM95245 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX16065 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX1668 is not set
++CONFIG_SENSORS_MAX197=m
++# CONFIG_SENSORS_MAX6639 is not set
++# CONFIG_SENSORS_MAX6642 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_MCP3021 is not set
++# CONFIG_SENSORS_NTC_THERMISTOR is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_PMBUS is not set
++# CONFIG_SENSORS_SHT15 is not set
++CONFIG_SENSORS_SHT21=m
++# CONFIG_SENSORS_SMM665 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_EMC1403 is not set
++# CONFIG_SENSORS_EMC2103 is not set
++# CONFIG_SENSORS_EMC6W201 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_SCH56XX_COMMON is not set
++# CONFIG_SENSORS_SCH5627 is not set
++# CONFIG_SENSORS_SCH5636 is not set
++# CONFIG_SENSORS_ADS1015 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_ADS7871 is not set
++# CONFIG_SENSORS_AMC6821 is not set
++# CONFIG_SENSORS_INA2XX is not set
++# CONFIG_SENSORS_THMC50 is not set
++CONFIG_SENSORS_TMP102=m
++# CONFIG_SENSORS_TMP401 is not set
++# CONFIG_SENSORS_TMP421 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83795 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++CONFIG_THERMAL=y
++CONFIG_THERMAL_HWMON=y
++CONFIG_CPU_THERMAL=y
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_CORE is not set
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_DW_WATCHDOG is not set
++# CONFIG_MPCORE_WATCHDOG is not set
++CONFIG_OMAP_WATCHDOG=y
++CONFIG_TWL4030_WATCHDOG=y
++# CONFIG_MAX63XX_WATCHDOG is not set
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++CONFIG_BCMA_POSSIBLE=y
++
++#
++# Broadcom specific AMBA
++#
++# CONFIG_BCMA is not set
++
++#
++# Multifunction device drivers
++#
++CONFIG_MFD_CORE=y
++# CONFIG_MFD_88PM860X is not set
++# CONFIG_MFD_88PM800 is not set
++# CONFIG_MFD_88PM805 is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++CONFIG_MFD_TI_AM335X_TSCADC=y
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_HTC_I2CPLD is not set
++# CONFIG_UCB1400_CORE is not set
++# CONFIG_MFD_LM3533 is not set
++# CONFIG_TPS6105X is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_TPS6507X is not set
++CONFIG_MFD_TPS65217=y
++# CONFIG_MFD_TPS6586X is not set
++# CONFIG_MFD_TPS65910 is not set
++# CONFIG_MFD_TPS65912_I2C is not set
++# CONFIG_MFD_TPS65912_SPI is not set
++CONFIG_TWL4030_CORE=y
++# CONFIG_TWL4030_MADC is not set
++CONFIG_TWL4030_POWER=y
++# CONFIG_MFD_TWL4030_AUDIO is not set
++# CONFIG_TWL6040_CORE is not set
++# CONFIG_MFD_STMPE is not set
++# CONFIG_MFD_TC3589X is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_T7L66XB is not set
++# CONFIG_MFD_SMSC is not set
++# CONFIG_MFD_TC6387XB is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_DA9052_SPI is not set
++# CONFIG_MFD_DA9052_I2C is not set
++# CONFIG_MFD_DA9055 is not set
++# CONFIG_PMIC_ADP5520 is not set
++# CONFIG_MFD_LP8788 is not set
++# CONFIG_MFD_MAX77686 is not set
++# CONFIG_MFD_MAX77693 is not set
++# CONFIG_MFD_MAX8907 is not set
++# CONFIG_MFD_MAX8925 is not set
++# CONFIG_MFD_MAX8997 is not set
++# CONFIG_MFD_MAX8998 is not set
++# CONFIG_MFD_SEC_CORE is not set
++# CONFIG_MFD_ARIZONA_I2C is not set
++# CONFIG_MFD_ARIZONA_SPI is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM831X_I2C is not set
++# CONFIG_MFD_WM831X_SPI is not set
++# CONFIG_MFD_WM8350_I2C is not set
++# CONFIG_MFD_WM8994 is not set
++# CONFIG_MFD_PCF50633 is not set
++# CONFIG_MFD_MC13XXX_SPI is not set
++# CONFIG_MFD_MC13XXX_I2C is not set
++# CONFIG_ABX500_CORE is not set
++# CONFIG_EZX_PCAP is not set
++CONFIG_MFD_WL1273_CORE=m
++# CONFIG_MFD_TPS65090 is not set
++# CONFIG_MFD_AAT2870_CORE is not set
++# CONFIG_MFD_RC5T583 is not set
++# CONFIG_MFD_SYSCON is not set
++# CONFIG_MFD_PALMAS is not set
++CONFIG_REGULATOR=y
++# CONFIG_REGULATOR_DEBUG is not set
++# CONFIG_REGULATOR_DUMMY is not set
++CONFIG_REGULATOR_FIXED_VOLTAGE=y
++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
++# CONFIG_REGULATOR_GPIO is not set
++# CONFIG_REGULATOR_AD5398 is not set
++# CONFIG_REGULATOR_FAN53555 is not set
++# CONFIG_REGULATOR_ISL6271A is not set
++# CONFIG_REGULATOR_MAX1586 is not set
++# CONFIG_REGULATOR_MAX8649 is not set
++# CONFIG_REGULATOR_MAX8660 is not set
++# CONFIG_REGULATOR_MAX8952 is not set
++# CONFIG_REGULATOR_LP3971 is not set
++# CONFIG_REGULATOR_LP3972 is not set
++# CONFIG_REGULATOR_LP872X is not set
++# CONFIG_REGULATOR_TPS62360 is not set
++CONFIG_REGULATOR_TPS65023=y
++CONFIG_REGULATOR_TPS6507X=y
++CONFIG_REGULATOR_TPS65217=y
++# CONFIG_REGULATOR_TPS6524X is not set
++CONFIG_REGULATOR_TWL4030=y
++CONFIG_MEDIA_SUPPORT=m
++
++#
++# Multimedia core support
++#
++CONFIG_MEDIA_CAMERA_SUPPORT=y
++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
++CONFIG_MEDIA_RADIO_SUPPORT=y
++CONFIG_MEDIA_RC_SUPPORT=y
++CONFIG_MEDIA_CONTROLLER=y
++CONFIG_VIDEO_DEV=m
++CONFIG_VIDEO_V4L2_SUBDEV_API=y
++CONFIG_VIDEO_V4L2=m
++# CONFIG_VIDEO_ADV_DEBUG is not set
++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
++CONFIG_VIDEO_TUNER=m
++CONFIG_V4L2_MEM2MEM_DEV=m
++CONFIG_VIDEOBUF_GEN=m
++CONFIG_VIDEOBUF_VMALLOC=m
++CONFIG_VIDEOBUF_DMA_CONTIG=m
++CONFIG_VIDEOBUF_DVB=m
++CONFIG_VIDEOBUF2_CORE=m
++CONFIG_VIDEOBUF2_MEMOPS=m
++CONFIG_VIDEOBUF2_DMA_CONTIG=m
++CONFIG_VIDEOBUF2_VMALLOC=m
++CONFIG_DVB_CORE=m
++CONFIG_DVB_NET=y
++CONFIG_DVB_MAX_ADAPTERS=8
++CONFIG_DVB_DYNAMIC_MINORS=y
++
++#
++# Media drivers
++#
++CONFIG_RC_CORE=m
++CONFIG_RC_MAP=m
++CONFIG_RC_DECODERS=y
++CONFIG_LIRC=m
++CONFIG_IR_LIRC_CODEC=m
++CONFIG_IR_NEC_DECODER=m
++CONFIG_IR_RC5_DECODER=m
++CONFIG_IR_RC6_DECODER=m
++CONFIG_IR_JVC_DECODER=m
++CONFIG_IR_SONY_DECODER=m
++CONFIG_IR_RC5_SZ_DECODER=m
++CONFIG_IR_SANYO_DECODER=m
++CONFIG_IR_MCE_KBD_DECODER=m
++CONFIG_RC_DEVICES=y
++CONFIG_RC_ATI_REMOTE=m
++CONFIG_IR_IMON=m
++CONFIG_IR_MCEUSB=m
++CONFIG_IR_REDRAT3=m
++CONFIG_IR_STREAMZAP=m
++CONFIG_IR_IGUANA=m
++CONFIG_IR_TTUSBIR=m
++CONFIG_IR_RX51=m
++CONFIG_RC_LOOPBACK=m
++CONFIG_IR_GPIO_CIR=m
++CONFIG_MEDIA_USB_SUPPORT=y
++
++#
++# Webcam devices
++#
++CONFIG_USB_VIDEO_CLASS=m
++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
++CONFIG_USB_GSPCA=m
++CONFIG_USB_M5602=m
++CONFIG_USB_STV06XX=m
++CONFIG_USB_GL860=m
++CONFIG_USB_GSPCA_BENQ=m
++CONFIG_USB_GSPCA_CONEX=m
++CONFIG_USB_GSPCA_CPIA1=m
++CONFIG_USB_GSPCA_ETOMS=m
++CONFIG_USB_GSPCA_FINEPIX=m
++CONFIG_USB_GSPCA_JEILINJ=m
++CONFIG_USB_GSPCA_JL2005BCD=m
++CONFIG_USB_GSPCA_KINECT=m
++CONFIG_USB_GSPCA_KONICA=m
++CONFIG_USB_GSPCA_MARS=m
++CONFIG_USB_GSPCA_MR97310A=m
++CONFIG_USB_GSPCA_NW80X=m
++CONFIG_USB_GSPCA_OV519=m
++CONFIG_USB_GSPCA_OV534=m
++CONFIG_USB_GSPCA_OV534_9=m
++CONFIG_USB_GSPCA_PAC207=m
++CONFIG_USB_GSPCA_PAC7302=m
++CONFIG_USB_GSPCA_PAC7311=m
++CONFIG_USB_GSPCA_SE401=m
++CONFIG_USB_GSPCA_SN9C2028=m
++CONFIG_USB_GSPCA_SN9C20X=m
++CONFIG_USB_GSPCA_SONIXB=m
++CONFIG_USB_GSPCA_SONIXJ=m
++CONFIG_USB_GSPCA_SPCA500=m
++CONFIG_USB_GSPCA_SPCA501=m
++CONFIG_USB_GSPCA_SPCA505=m
++CONFIG_USB_GSPCA_SPCA506=m
++CONFIG_USB_GSPCA_SPCA508=m
++CONFIG_USB_GSPCA_SPCA561=m
++CONFIG_USB_GSPCA_SPCA1528=m
++CONFIG_USB_GSPCA_SQ905=m
++CONFIG_USB_GSPCA_SQ905C=m
++CONFIG_USB_GSPCA_SQ930X=m
++CONFIG_USB_GSPCA_STK014=m
++CONFIG_USB_GSPCA_STV0680=m
++CONFIG_USB_GSPCA_SUNPLUS=m
++CONFIG_USB_GSPCA_T613=m
++CONFIG_USB_GSPCA_TOPRO=m
++CONFIG_USB_GSPCA_TV8532=m
++CONFIG_USB_GSPCA_VC032X=m
++CONFIG_USB_GSPCA_VICAM=m
++CONFIG_USB_GSPCA_XIRLINK_CIT=m
++CONFIG_USB_GSPCA_ZC3XX=m
++CONFIG_USB_PWC=m
++# CONFIG_USB_PWC_DEBUG is not set
++CONFIG_USB_PWC_INPUT_EVDEV=y
++CONFIG_VIDEO_CPIA2=m
++CONFIG_USB_ZR364XX=m
++CONFIG_USB_STKWEBCAM=m
++CONFIG_USB_S2255=m
++CONFIG_USB_SN9C102=m
++
++#
++# Analog TV USB devices
++#
++CONFIG_VIDEO_AU0828=m
++CONFIG_VIDEO_PVRUSB2=m
++CONFIG_VIDEO_PVRUSB2_SYSFS=y
++CONFIG_VIDEO_PVRUSB2_DVB=y
++# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
++CONFIG_VIDEO_HDPVR=m
++CONFIG_VIDEO_TLG2300=m
++CONFIG_VIDEO_USBVISION=m
++CONFIG_VIDEO_STK1160=m
++CONFIG_VIDEO_STK1160_AC97=y
++
++#
++# Analog/digital TV USB devices
++#
++CONFIG_VIDEO_CX231XX=m
++CONFIG_VIDEO_CX231XX_RC=y
++CONFIG_VIDEO_CX231XX_ALSA=m
++CONFIG_VIDEO_CX231XX_DVB=m
++CONFIG_VIDEO_TM6000=m
++CONFIG_VIDEO_TM6000_ALSA=m
++CONFIG_VIDEO_TM6000_DVB=m
++
++#
++# Digital TV USB devices
++#
++CONFIG_DVB_USB=m
++# CONFIG_DVB_USB_DEBUG is not set
++CONFIG_DVB_USB_A800=m
++CONFIG_DVB_USB_DIBUSB_MB=m
++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
++CONFIG_DVB_USB_DIBUSB_MC=m
++CONFIG_DVB_USB_DIB0700=m
++CONFIG_DVB_USB_UMT_010=m
++CONFIG_DVB_USB_CXUSB=m
++CONFIG_DVB_USB_M920X=m
++CONFIG_DVB_USB_DIGITV=m
++CONFIG_DVB_USB_VP7045=m
++CONFIG_DVB_USB_VP702X=m
++CONFIG_DVB_USB_GP8PSK=m
++CONFIG_DVB_USB_NOVA_T_USB2=m
++CONFIG_DVB_USB_TTUSB2=m
++CONFIG_DVB_USB_DTT200U=m
++CONFIG_DVB_USB_OPERA1=m
++CONFIG_DVB_USB_AF9005=m
++CONFIG_DVB_USB_AF9005_REMOTE=m
++CONFIG_DVB_USB_PCTV452E=m
++CONFIG_DVB_USB_DW2102=m
++CONFIG_DVB_USB_CINERGY_T2=m
++CONFIG_DVB_USB_DTV5100=m
++CONFIG_DVB_USB_FRIIO=m
++CONFIG_DVB_USB_AZ6027=m
++CONFIG_DVB_USB_TECHNISAT_USB2=m
++CONFIG_DVB_USB_V2=m
++CONFIG_DVB_USB_CYPRESS_FIRMWARE=m
++CONFIG_DVB_USB_AF9015=m
++CONFIG_DVB_USB_AF9035=m
++CONFIG_DVB_USB_ANYSEE=m
++CONFIG_DVB_USB_AU6610=m
++CONFIG_DVB_USB_AZ6007=m
++CONFIG_DVB_USB_CE6230=m
++CONFIG_DVB_USB_EC168=m
++CONFIG_DVB_USB_GL861=m
++CONFIG_DVB_USB_IT913X=m
++CONFIG_DVB_USB_LME2510=m
++CONFIG_DVB_USB_MXL111SF=m
++CONFIG_DVB_USB_RTL28XXU=m
++# CONFIG_SMS_USB_DRV is not set
++CONFIG_DVB_B2C2_FLEXCOP_USB=m
++# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set
++
++#
++# Webcam, TV (analog/digital) USB devices
++#
++CONFIG_VIDEO_EM28XX=m
++CONFIG_VIDEO_EM28XX_ALSA=m
++CONFIG_VIDEO_EM28XX_DVB=m
++CONFIG_VIDEO_EM28XX_RC=m
++CONFIG_TTPCI_EEPROM=m
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_VIDEO_VPSS_SYSTEM=m
++CONFIG_VIDEO_VPFE_CAPTURE=m
++CONFIG_VIDEO_DM6446_CCDC=m
++CONFIG_VIDEO_OMAP2_VOUT_VRFB=y
++CONFIG_VIDEO_OMAP2_VOUT=m
++# CONFIG_VIDEO_TIMBERDALE is not set
++CONFIG_SOC_CAMERA=m
++CONFIG_SOC_CAMERA_PLATFORM=m
++# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
++# CONFIG_VIDEO_SH_MOBILE_CEU is not set
++CONFIG_V4L_MEM2MEM_DRIVERS=y
++CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
++CONFIG_V4L_TEST_DRIVERS=y
++CONFIG_VIDEO_VIVI=m
++CONFIG_VIDEO_MEM2MEM_TESTDEV=m
++
++#
++# Supported MMC/SDIO adapters
++#
++# CONFIG_SMS_SDIO_DRV is not set
++CONFIG_RADIO_ADAPTERS=y
++CONFIG_RADIO_SI470X=y
++CONFIG_USB_SI470X=m
++CONFIG_I2C_SI470X=m
++CONFIG_USB_MR800=m
++CONFIG_USB_DSBR=m
++# CONFIG_RADIO_SHARK is not set
++CONFIG_RADIO_SHARK2=m
++CONFIG_I2C_SI4713=m
++CONFIG_RADIO_SI4713=m
++CONFIG_USB_KEENE=m
++CONFIG_RADIO_TEA5764=m
++CONFIG_RADIO_SAA7706H=m
++CONFIG_RADIO_TEF6862=m
++CONFIG_RADIO_WL1273=m
++
++#
++# Texas Instruments WL128x FM driver (ST based)
++#
++CONFIG_RADIO_WL128X=m
++CONFIG_DVB_B2C2_FLEXCOP=m
++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
++
++#
++# Media ancillary drivers (tuners, sensors, i2c, frontends)
++#
++CONFIG_VIDEO_TVEEPROM=m
++CONFIG_VIDEO_IR_I2C=m
++
++#
++# Audio decoders, processors and mixers
++#
++CONFIG_VIDEO_MSP3400=m
++CONFIG_VIDEO_CS53L32A=m
++CONFIG_VIDEO_WM8775=m
++
++#
++# RDS decoders
++#
++
++#
++# Video decoders
++#
++CONFIG_VIDEO_SAA711X=m
++CONFIG_VIDEO_TVP5150=m
++
++#
++# Video and audio decoders
++#
++CONFIG_VIDEO_CX25840=m
++
++#
++# MPEG video encoders
++#
++CONFIG_VIDEO_CX2341X=m
++
++#
++# Video encoders
++#
++
++#
++# Camera sensor devices
++#
++CONFIG_VIDEO_MT9V011=m
++
++#
++# Flash devices
++#
++
++#
++# Video improvement chips
++#
++
++#
++# Miscelaneous helper chips
++#
++
++#
++# Sensors used on soc_camera driver
++#
++
++#
++# soc_camera sensor drivers
++#
++# CONFIG_SOC_CAMERA_IMX074 is not set
++CONFIG_SOC_CAMERA_MT9M001=m
++CONFIG_SOC_CAMERA_MT9M111=m
++CONFIG_SOC_CAMERA_MT9T031=m
++CONFIG_SOC_CAMERA_MT9T112=m
++CONFIG_SOC_CAMERA_MT9V022=m
++# CONFIG_SOC_CAMERA_OV2640 is not set
++# CONFIG_SOC_CAMERA_OV5642 is not set
++# CONFIG_SOC_CAMERA_OV6650 is not set
++# CONFIG_SOC_CAMERA_OV772X is not set
++# CONFIG_SOC_CAMERA_OV9640 is not set
++# CONFIG_SOC_CAMERA_OV9740 is not set
++# CONFIG_SOC_CAMERA_RJ54N1 is not set
++# CONFIG_SOC_CAMERA_TW9910 is not set
++CONFIG_MEDIA_ATTACH=y
++CONFIG_MEDIA_TUNER=m
++CONFIG_MEDIA_TUNER_SIMPLE=m
++CONFIG_MEDIA_TUNER_TDA8290=m
++CONFIG_MEDIA_TUNER_TDA827X=m
++CONFIG_MEDIA_TUNER_TDA18271=m
++CONFIG_MEDIA_TUNER_TDA9887=m
++CONFIG_MEDIA_TUNER_TEA5761=m
++CONFIG_MEDIA_TUNER_TEA5767=m
++CONFIG_MEDIA_TUNER_MT20XX=m
++CONFIG_MEDIA_TUNER_MT2060=m
++CONFIG_MEDIA_TUNER_MT2063=m
++CONFIG_MEDIA_TUNER_MT2266=m
++CONFIG_MEDIA_TUNER_QT1010=m
++CONFIG_MEDIA_TUNER_XC2028=m
++CONFIG_MEDIA_TUNER_XC5000=m
++CONFIG_MEDIA_TUNER_XC4000=m
++CONFIG_MEDIA_TUNER_MXL5005S=m
++CONFIG_MEDIA_TUNER_MXL5007T=m
++CONFIG_MEDIA_TUNER_MC44S803=m
++CONFIG_MEDIA_TUNER_MAX2165=m
++CONFIG_MEDIA_TUNER_TDA18218=m
++CONFIG_MEDIA_TUNER_FC0011=m
++CONFIG_MEDIA_TUNER_FC0012=m
++CONFIG_MEDIA_TUNER_FC0013=m
++CONFIG_MEDIA_TUNER_TDA18212=m
++CONFIG_MEDIA_TUNER_E4000=m
++CONFIG_MEDIA_TUNER_FC2580=m
++CONFIG_MEDIA_TUNER_TUA9001=m
++
++#
++# Multistandard (satellite) frontends
++#
++CONFIG_DVB_STB0899=m
++CONFIG_DVB_STB6100=m
++CONFIG_DVB_STV090x=m
++CONFIG_DVB_STV6110x=m
++
++#
++# Multistandard (cable + terrestrial) frontends
++#
++CONFIG_DVB_DRXK=m
++CONFIG_DVB_TDA18271C2DD=m
++
++#
++# DVB-S (satellite) frontends
++#
++CONFIG_DVB_CX24123=m
++CONFIG_DVB_MT312=m
++CONFIG_DVB_ZL10039=m
++CONFIG_DVB_S5H1420=m
++CONFIG_DVB_STV0288=m
++CONFIG_DVB_STB6000=m
++CONFIG_DVB_STV0299=m
++CONFIG_DVB_STV6110=m
++CONFIG_DVB_STV0900=m
++CONFIG_DVB_TDA10086=m
++CONFIG_DVB_TUNER_ITD1000=m
++CONFIG_DVB_TUNER_CX24113=m
++CONFIG_DVB_TDA826X=m
++CONFIG_DVB_CX24116=m
++CONFIG_DVB_SI21XX=m
++CONFIG_DVB_DS3000=m
++CONFIG_DVB_TDA10071=m
++
++#
++# DVB-T (terrestrial) frontends
++#
++CONFIG_DVB_CX22702=m
++CONFIG_DVB_DRXD=m
++CONFIG_DVB_TDA1004X=m
++CONFIG_DVB_NXT6000=m
++CONFIG_DVB_MT352=m
++CONFIG_DVB_ZL10353=m
++CONFIG_DVB_DIB3000MB=m
++CONFIG_DVB_DIB3000MC=m
++CONFIG_DVB_DIB7000M=m
++CONFIG_DVB_DIB7000P=m
++CONFIG_DVB_TDA10048=m
++CONFIG_DVB_AF9013=m
++CONFIG_DVB_EC100=m
++CONFIG_DVB_CXD2820R=m
++CONFIG_DVB_RTL2830=m
++CONFIG_DVB_RTL2832=m
++
++#
++# DVB-C (cable) frontends
++#
++CONFIG_DVB_TDA10023=m
++CONFIG_DVB_STV0297=m
++
++#
++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
++#
++CONFIG_DVB_NXT200X=m
++CONFIG_DVB_BCM3510=m
++CONFIG_DVB_LGDT330X=m
++CONFIG_DVB_LGDT3305=m
++CONFIG_DVB_LG2160=m
++CONFIG_DVB_S5H1409=m
++CONFIG_DVB_AU8522=m
++CONFIG_DVB_AU8522_DTV=m
++CONFIG_DVB_AU8522_V4L=m
++CONFIG_DVB_S5H1411=m
++
++#
++# ISDB-T (terrestrial) frontends
++#
++CONFIG_DVB_S921=m
++CONFIG_DVB_DIB8000=m
++CONFIG_DVB_MB86A20S=m
++
++#
++# Digital terrestrial only tuners/PLL
++#
++CONFIG_DVB_PLL=m
++CONFIG_DVB_TUNER_DIB0070=m
++CONFIG_DVB_TUNER_DIB0090=m
++
++#
++# SEC control devices for DVB-S
++#
++CONFIG_DVB_LNBP21=m
++CONFIG_DVB_LNBP22=m
++CONFIG_DVB_ISL6421=m
++CONFIG_DVB_ISL6423=m
++CONFIG_DVB_A8293=m
++CONFIG_DVB_LGS8GXX=m
++CONFIG_DVB_ATBM8830=m
++CONFIG_DVB_IX2505V=m
++CONFIG_DVB_IT913X_FE=m
++CONFIG_DVB_M88RS2000=m
++CONFIG_DVB_AF9033=m
++
++#
++# Tools to develop new frontends
++#
++# CONFIG_DVB_DUMMY_FE is not set
++
++#
++# Graphics support
++#
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++CONFIG_FIRMWARE_EDID=y
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++CONFIG_FB_CFB_REV_PIXELS_IN_BYTE=y
++CONFIG_FB_SYS_FILLRECT=y
++CONFIG_FB_SYS_COPYAREA=y
++CONFIG_FB_SYS_IMAGEBLIT=y
++CONFIG_FB_FOREIGN_ENDIAN=y
++CONFIG_FB_BOTH_ENDIAN=y
++# CONFIG_FB_BIG_ENDIAN is not set
++# CONFIG_FB_LITTLE_ENDIAN is not set
++CONFIG_FB_SYS_FOPS=y
++# CONFIG_FB_WMT_GE_ROPS is not set
++CONFIG_FB_DEFERRED_IO=y
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++CONFIG_FB_MODE_HELPERS=y
++CONFIG_FB_TILEBLITTING=y
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_UVESA is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_TMIO is not set
++# CONFIG_FB_SMSCUFX is not set
++# CONFIG_FB_UDL is not set
++CONFIG_FB_DA8XX=y
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_BROADSHEET is not set
++# CONFIG_FB_AUO_K190X is not set
++CONFIG_FB_ST7735=y
++CONFIG_OMAP2_VRAM=y
++CONFIG_OMAP2_VRFB=y
++CONFIG_OMAP2_DSS=m
++CONFIG_OMAP2_VRAM_SIZE=0
++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
++# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
++CONFIG_OMAP2_DSS_DPI=y
++CONFIG_OMAP2_DSS_RFBI=y
++CONFIG_OMAP2_DSS_VENC=y
++CONFIG_OMAP4_DSS_HDMI=y
++CONFIG_OMAP2_DSS_SDI=y
++CONFIG_OMAP2_DSS_DSI=y
++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
++CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
++CONFIG_FB_OMAP2=m
++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
++CONFIG_FB_OMAP2_NUM_FBS=3
++
++#
++# OMAP2/3 Display Device Drivers
++#
++CONFIG_PANEL_GENERIC_DPI=m
++# CONFIG_PANEL_TFP410 is not set
++# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
++CONFIG_PANEL_SHARP_LS037V7DW01=m
++CONFIG_PANEL_NEC_NL8048HL11_01B=m
++# CONFIG_PANEL_PICODLP is not set
++CONFIG_PANEL_TAAL=m
++CONFIG_PANEL_TPO_TD043MTEA1=m
++CONFIG_PANEL_ACX565AKM=m
++# CONFIG_PANEL_N8X0 is not set
++# CONFIG_EXYNOS_VIDEO is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_LCD_CLASS_DEVICE=y
++# CONFIG_LCD_L4F00242T03 is not set
++# CONFIG_LCD_LMS283GF05 is not set
++# CONFIG_LCD_LTV350QV is not set
++# CONFIG_LCD_TDO24M is not set
++# CONFIG_LCD_VGG2432A4 is not set
++CONFIG_LCD_PLATFORM=y
++# CONFIG_LCD_S6E63M0 is not set
++# CONFIG_LCD_LD9040 is not set
++# CONFIG_LCD_AMS369FG06 is not set
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_GENERIC=m
++CONFIG_BACKLIGHT_PWM=y
++# CONFIG_BACKLIGHT_ADP8860 is not set
++# CONFIG_BACKLIGHT_ADP8870 is not set
++CONFIG_BACKLIGHT_LM3630=m
++CONFIG_BACKLIGHT_LM3639=m
++# CONFIG_BACKLIGHT_LP855X is not set
++# CONFIG_BACKLIGHT_PANDORA is not set
++CONFIG_BACKLIGHT_TPS65217=y
++
++#
++# Console display driver support
++#
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++CONFIG_FONT_MINI_4x6=y
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++CONFIG_SOUND=m
++CONFIG_SOUND_OSS_CORE=y
++CONFIG_SOUND_OSS_CORE_PRECLAIM=y
++CONFIG_SND=m
++CONFIG_SND_TIMER=m
++CONFIG_SND_PCM=m
++CONFIG_SND_HWDEP=m
++CONFIG_SND_RAWMIDI=m
++CONFIG_SND_COMPRESS_OFFLOAD=m
++CONFIG_SND_JACK=y
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_HRTIMER is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++# CONFIG_SND_DEBUG_VERBOSE is not set
++# CONFIG_SND_PCM_XRUN_DEBUG is not set
++CONFIG_SND_VMASTER=y
++# CONFIG_SND_RAWMIDI_SEQ is not set
++# CONFIG_SND_OPL3_LIB_SEQ is not set
++# CONFIG_SND_OPL4_LIB_SEQ is not set
++# CONFIG_SND_SBAWE_SEQ is not set
++# CONFIG_SND_EMU10K1_SEQ is not set
++CONFIG_SND_AC97_CODEC=m
++CONFIG_SND_DRIVERS=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_ALOOP is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++CONFIG_SND_AC97_POWER_SAVE=y
++CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
++CONFIG_SND_ARM=y
++CONFIG_SND_SPI=y
++CONFIG_SND_USB=y
++CONFIG_SND_USB_AUDIO=m
++# CONFIG_SND_USB_UA101 is not set
++# CONFIG_SND_USB_CAIAQ is not set
++# CONFIG_SND_USB_6FIRE is not set
++CONFIG_SND_SOC=m
++# CONFIG_SND_DESIGNWARE_I2S is not set
++CONFIG_SND_SOC_I2C_AND_SPI=m
++# CONFIG_SND_SOC_ALL_CODECS is not set
++# CONFIG_SND_SIMPLE_CARD is not set
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=m
++
++#
++# HID support
++#
++CONFIG_HID=y
++# CONFIG_HID_BATTERY_STRENGTH is not set
++# CONFIG_HIDRAW is not set
++CONFIG_UHID=m
++CONFIG_HID_GENERIC=y
++
++#
++# Special HID drivers
++#
++# CONFIG_HID_A4TECH is not set
++# CONFIG_HID_ACRUX is not set
++# CONFIG_HID_APPLE is not set
++# CONFIG_HID_AUREAL is not set
++# CONFIG_HID_BELKIN is not set
++# CONFIG_HID_CHERRY is not set
++# CONFIG_HID_CHICONY is not set
++# CONFIG_HID_PRODIKEYS is not set
++# CONFIG_HID_CYPRESS is not set
++# CONFIG_HID_DRAGONRISE is not set
++# CONFIG_HID_EMS_FF is not set
++# CONFIG_HID_ELECOM is not set
++# CONFIG_HID_EZKEY is not set
++# CONFIG_HID_HOLTEK is not set
++# CONFIG_HID_KEYTOUCH is not set
++# CONFIG_HID_KYE is not set
++# CONFIG_HID_UCLOGIC is not set
++# CONFIG_HID_WALTOP is not set
++# CONFIG_HID_GYRATION is not set
++# CONFIG_HID_TWINHAN is not set
++# CONFIG_HID_KENSINGTON is not set
++# CONFIG_HID_LCPOWER is not set
++CONFIG_HID_LENOVO_TPKBD=m
++# CONFIG_HID_LOGITECH is not set
++# CONFIG_HID_MAGICMOUSE is not set
++# CONFIG_HID_MICROSOFT is not set
++# CONFIG_HID_MONTEREY is not set
++# CONFIG_HID_MULTITOUCH is not set
++# CONFIG_HID_NTRIG is not set
++# CONFIG_HID_ORTEK is not set
++# CONFIG_HID_PANTHERLORD is not set
++# CONFIG_HID_PETALYNX is not set
++# CONFIG_HID_PICOLCD is not set
++# CONFIG_HID_PRIMAX is not set
++CONFIG_HID_PS3REMOTE=m
++# CONFIG_HID_ROCCAT is not set
++# CONFIG_HID_SAITEK is not set
++# CONFIG_HID_SAMSUNG is not set
++# CONFIG_HID_SONY is not set
++# CONFIG_HID_SPEEDLINK is not set
++# CONFIG_HID_SUNPLUS is not set
++# CONFIG_HID_GREENASIA is not set
++# CONFIG_HID_SMARTJOYPLUS is not set
++# CONFIG_HID_TIVO is not set
++# CONFIG_HID_TOPSEED is not set
++# CONFIG_HID_THRUSTMASTER is not set
++# CONFIG_HID_WACOM is not set
++# CONFIG_HID_WIIMOTE is not set
++# CONFIG_HID_ZEROPLUS is not set
++# CONFIG_HID_ZYDACRON is not set
++CONFIG_HID_SENSOR_HUB=m
++
++#
++# USB HID support
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB_ARCH_HAS_XHCI is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_COMMON=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DYNAMIC_MINORS is not set
++CONFIG_USB_SUSPEND=y
++# CONFIG_USB_OTG is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++# CONFIG_USB_DWC3 is not set
++CONFIG_USB_MON=y
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_OXU210HP_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_ISP1362_HCD is not set
++# CONFIG_USB_OHCI_HCD is not set
++# CONFIG_USB_U132_HCD is not set
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++CONFIG_USB_MUSB_HDRC=y
++# CONFIG_USB_MUSB_TUSB6010 is not set
++# CONFIG_USB_MUSB_OMAP2PLUS is not set
++# CONFIG_USB_MUSB_AM35X is not set
++CONFIG_USB_MUSB_DSPS=y
++CONFIG_MUSB_PIO_ONLY=y
++# CONFIG_USB_CHIPIDEA is not set
++# CONFIG_USB_RENESAS_USBHS is not set
++
++#
++# USB Device Class drivers
++#
++CONFIG_USB_ACM=m
++CONFIG_USB_PRINTER=m
++CONFIG_USB_WDM=m
++CONFIG_USB_TMC=m
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
++#
++
++#
++# also be needed; see USB_STORAGE Help for more info
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_REALTEK is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_STORAGE_ENE_UB6250 is not set
++CONFIG_USB_UAS=y
++
++#
++# USB Imaging devices
++#
++CONFIG_USB_MDC800=m
++CONFIG_USB_MICROTEK=m
++
++#
++# USB port drivers
++#
++CONFIG_USB_SERIAL=m
++CONFIG_USB_SERIAL_GENERIC=y
++CONFIG_USB_SERIAL_AIRCABLE=m
++CONFIG_USB_SERIAL_ARK3116=m
++CONFIG_USB_SERIAL_BELKIN=m
++CONFIG_USB_SERIAL_CH341=m
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++CONFIG_USB_SERIAL_CP210X=m
++CONFIG_USB_SERIAL_CYPRESS_M8=m
++CONFIG_USB_SERIAL_EMPEG=m
++CONFIG_USB_SERIAL_FTDI_SIO=m
++CONFIG_USB_SERIAL_FUNSOFT=m
++CONFIG_USB_SERIAL_VISOR=m
++CONFIG_USB_SERIAL_IPAQ=m
++CONFIG_USB_SERIAL_IR=m
++CONFIG_USB_SERIAL_EDGEPORT=m
++CONFIG_USB_SERIAL_EDGEPORT_TI=m
++CONFIG_USB_SERIAL_F81232=m
++CONFIG_USB_SERIAL_GARMIN=m
++CONFIG_USB_SERIAL_IPW=m
++CONFIG_USB_SERIAL_IUU=m
++CONFIG_USB_SERIAL_KEYSPAN_PDA=m
++CONFIG_USB_SERIAL_KEYSPAN=m
++CONFIG_USB_SERIAL_KEYSPAN_MPR=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
++CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19=y
++CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
++CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
++CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
++CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
++CONFIG_USB_SERIAL_KLSI=m
++CONFIG_USB_SERIAL_KOBIL_SCT=m
++CONFIG_USB_SERIAL_MCT_U232=m
++CONFIG_USB_SERIAL_METRO=m
++CONFIG_USB_SERIAL_MOS7720=m
++CONFIG_USB_SERIAL_MOS7840=m
++CONFIG_USB_SERIAL_MOTOROLA=m
++CONFIG_USB_SERIAL_NAVMAN=m
++CONFIG_USB_SERIAL_PL2303=m
++CONFIG_USB_SERIAL_OTI6858=m
++CONFIG_USB_SERIAL_QCAUX=m
++CONFIG_USB_SERIAL_QUALCOMM=m
++CONFIG_USB_SERIAL_SPCP8X5=m
++CONFIG_USB_SERIAL_HP4X=m
++CONFIG_USB_SERIAL_SAFE=m
++# CONFIG_USB_SERIAL_SAFE_PADDED is not set
++CONFIG_USB_SERIAL_SIEMENS_MPI=m
++CONFIG_USB_SERIAL_SIERRAWIRELESS=m
++CONFIG_USB_SERIAL_SYMBOL=m
++CONFIG_USB_SERIAL_TI=m
++CONFIG_USB_SERIAL_CYBERJACK=m
++CONFIG_USB_SERIAL_XIRCOM=m
++CONFIG_USB_SERIAL_WWAN=m
++CONFIG_USB_SERIAL_OPTION=m
++CONFIG_USB_SERIAL_OMNINET=m
++CONFIG_USB_SERIAL_OPTICON=m
++CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
++CONFIG_USB_SERIAL_ZIO=m
++CONFIG_USB_SERIAL_ZTE=m
++CONFIG_USB_SERIAL_SSU100=m
++CONFIG_USB_SERIAL_QT2=m
++CONFIG_USB_SERIAL_DEBUG=m
++
++#
++# USB Miscellaneous drivers
++#
++CONFIG_USB_EMI62=m
++CONFIG_USB_EMI26=m
++CONFIG_USB_ADUTUX=m
++CONFIG_USB_SEVSEG=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=m
++CONFIG_USB_LED=m
++CONFIG_USB_CYPRESS_CY7C63=m
++CONFIG_USB_CYTHERM=m
++CONFIG_USB_IDMOUSE=m
++CONFIG_USB_FTDI_ELAN=m
++CONFIG_USB_APPLEDISPLAY=m
++CONFIG_USB_SISUSBVGA=m
++CONFIG_USB_SISUSBVGA_CON=y
++CONFIG_USB_LD=m
++CONFIG_USB_TRANCEVIBRATOR=m
++CONFIG_USB_IOWARRIOR=m
++CONFIG_USB_TEST=m
++CONFIG_USB_ISIGHTFW=m
++CONFIG_USB_YUREX=m
++CONFIG_USB_EZUSB_FX2=m
++
++#
++# USB Physical Layer drivers
++#
++CONFIG_OMAP_USB2=y
++CONFIG_USB_ISP1301=m
++CONFIG_USB_GADGET=y
++CONFIG_USB_GADGET_DEBUG=y
++CONFIG_USB_GADGET_DEBUG_FILES=y
++CONFIG_USB_GADGET_DEBUG_FS=y
++CONFIG_USB_GADGET_VBUS_DRAW=2
++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
++
++#
++# USB Peripheral Controller
++#
++# CONFIG_USB_FUSB300 is not set
++# CONFIG_USB_R8A66597 is not set
++# CONFIG_USB_MV_UDC is not set
++CONFIG_USB_GADGET_MUSB_HDRC=y
++# CONFIG_USB_M66592 is not set
++# CONFIG_USB_NET2272 is not set
++# CONFIG_USB_DUMMY_HCD is not set
++CONFIG_USB_LIBCOMPOSITE=m
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_AUDIO is not set
++CONFIG_USB_ETH=m
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_ETH_EEM is not set
++# CONFIG_USB_G_NCM is not set
++CONFIG_USB_GADGETFS=m
++# CONFIG_USB_FUNCTIONFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++CONFIG_USB_MASS_STORAGE=m
++CONFIG_USB_G_SERIAL=m
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++CONFIG_USB_CDC_COMPOSITE=m
++# CONFIG_USB_G_NOKIA is not set
++# CONFIG_USB_G_ACM_MS is not set
++# CONFIG_USB_G_MULTI is not set
++CONFIG_USB_G_HID=m
++# CONFIG_USB_G_DBGP is not set
++# CONFIG_USB_G_WEBCAM is not set
++
++#
++# OTG and related infrastructure
++#
++CONFIG_USB_OTG_UTILS=y
++CONFIG_USB_GPIO_VBUS=m
++# CONFIG_USB_ULPI is not set
++CONFIG_TWL4030_USB=y
++CONFIG_TWL6030_USB=y
++CONFIG_NOP_USB_XCEIV=y
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++CONFIG_MMC_UNSAFE_RESUME=y
++# CONFIG_MMC_CLKGATE is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_MINORS=8
++CONFIG_MMC_BLOCK_BOUNCE=y
++CONFIG_SDIO_UART=y
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++# CONFIG_MMC_SDHCI is not set
++# CONFIG_MMC_SDHCI_PXAV3 is not set
++# CONFIG_MMC_SDHCI_PXAV2 is not set
++CONFIG_MMC_OMAP=y
++CONFIG_MMC_OMAP_HS=y
++# CONFIG_MMC_DW is not set
++# CONFIG_MMC_VUB300 is not set
++# CONFIG_MMC_USHC is not set
++# CONFIG_MEMSTICK is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++# CONFIG_LEDS_LM3530 is not set
++CONFIG_LEDS_LM3642=m
++# CONFIG_LEDS_PCA9532 is not set
++CONFIG_LEDS_GPIO=y
++# CONFIG_LEDS_LP3944 is not set
++# CONFIG_LEDS_LP5521 is not set
++# CONFIG_LEDS_LP5523 is not set
++# CONFIG_LEDS_PCA955X is not set
++# CONFIG_LEDS_PCA9633 is not set
++# CONFIG_LEDS_DAC124S085 is not set
++# CONFIG_LEDS_REGULATOR is not set
++# CONFIG_LEDS_BD2802 is not set
++# CONFIG_LEDS_LT3593 is not set
++# CONFIG_LEDS_RENESAS_TPU is not set
++# CONFIG_LEDS_TCA6507 is not set
++CONFIG_LEDS_LM355x=m
++# CONFIG_LEDS_OT200 is not set
++CONFIG_LEDS_BLINKM=m
++CONFIG_LEDS_TRIGGERS=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_ONESHOT=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_LEDS_TRIGGER_BACKLIGHT=y
++CONFIG_LEDS_TRIGGER_CPU=y
++CONFIG_LEDS_TRIGGER_GPIO=y
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
++
++#
++# iptables trigger is under Netfilter config (LED target)
++#
++CONFIG_LEDS_TRIGGER_TRANSIENT=y
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_DS3232 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_ISL12022 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_BQ32K is not set
++CONFIG_RTC_DRV_TWL4030=y
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++# CONFIG_RTC_DRV_RX8025 is not set
++# CONFIG_RTC_DRV_EM3027 is not set
++# CONFIG_RTC_DRV_RV3029C2 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T93 is not set
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++# CONFIG_RTC_DRV_PCF2123 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_MSM6242 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_RP5C01 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++CONFIG_RTC_DRV_DS2404=m
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_SNVS=m
++CONFIG_DMADEVICES=y
++# CONFIG_DMADEVICES_DEBUG is not set
++
++#
++# DMA Devices
++#
++# CONFIG_DW_DMAC is not set
++# CONFIG_TIMB_DMA is not set
++CONFIG_TI_EDMA=y
++# CONFIG_DMA_OMAP is not set
++CONFIG_DMA_ENGINE=y
++CONFIG_DMA_VIRTUAL_CHANNELS=y
++
++#
++# DMA Clients
++#
++CONFIG_NET_DMA=y
++CONFIG_ASYNC_TX_DMA=y
++CONFIG_DMATEST=m
++# CONFIG_AUXDISPLAY is not set
++CONFIG_UIO=y
++CONFIG_UIO_PDRV=y
++CONFIG_UIO_PDRV_GENIRQ=y
++CONFIG_VIRTIO=m
++
++#
++# Virtio drivers
++#
++# CONFIG_VIRTIO_BALLOON is not set
++# CONFIG_VIRTIO_MMIO is not set
++
++#
++# Microsoft Hyper-V guest support
++#
++# CONFIG_STAGING is not set
++CONFIG_CLKDEV_LOOKUP=y
++CONFIG_HWSPINLOCK=m
++
++#
++# Hardware Spinlock drivers
++#
++CONFIG_HWSPINLOCK_OMAP=m
++CONFIG_CLKSRC_MMIO=y
++CONFIG_IOMMU_SUPPORT=y
++CONFIG_OF_IOMMU=y
++# CONFIG_OMAP_IOMMU is not set
++
++#
++# Remoteproc drivers (EXPERIMENTAL)
++#
++CONFIG_REMOTEPROC=m
++CONFIG_STE_MODEM_RPROC=m
++
++#
++# Rpmsg drivers (EXPERIMENTAL)
++#
++# CONFIG_VIRT_DRIVERS is not set
++# CONFIG_PM_DEVFREQ is not set
++# CONFIG_EXTCON is not set
++# CONFIG_MEMORY is not set
++CONFIG_IIO=y
++CONFIG_IIO_BUFFER=y
++CONFIG_IIO_KFIFO_BUF=m
++CONFIG_IIO_TRIGGERED_BUFFER=m
++CONFIG_IIO_TRIGGER=y
++CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
++
++#
++# Accelerometers
++#
++CONFIG_HID_SENSOR_ACCEL_3D=m
++
++#
++# Analog to digital converters
++#
++CONFIG_AD_SIGMA_DELTA=m
++CONFIG_AD7266=m
++CONFIG_AD7791=m
++CONFIG_AD7476=m
++CONFIG_TI_AM335X_ADC=y
++
++#
++# Amplifiers
++#
++# CONFIG_AD8366 is not set
++
++#
++# Light sensors
++#
++CONFIG_ADJD_S311=m
++CONFIG_VCNL4000=m
++CONFIG_HID_SENSOR_ALS=m
++
++#
++# Frequency Synthesizers DDS/PLL
++#
++
++#
++# Clock Generator/Distribution
++#
++CONFIG_AD9523=m
++
++#
++# Phase-Locked Loop (PLL) frequency synthesizers
++#
++CONFIG_ADF4350=m
++
++#
++# Digital to analog converters
++#
++CONFIG_AD5064=m
++CONFIG_AD5360=m
++CONFIG_AD5380=m
++CONFIG_AD5421=m
++CONFIG_AD5624R_SPI=m
++CONFIG_AD5446=m
++CONFIG_AD5504=m
++CONFIG_AD5755=m
++CONFIG_AD5764=m
++CONFIG_AD5791=m
++CONFIG_AD5686=m
++CONFIG_MAX517=m
++CONFIG_MCP4725=m
++
++#
++# Hid Sensor IIO Common
++#
++CONFIG_HID_SENSOR_IIO_COMMON=m
++CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS=m
++
++#
++# Digital gyroscope sensors
++#
++CONFIG_HID_SENSOR_GYRO_3D=m
++
++#
++# Light sensors
++#
++
++#
++# Magnetometer sensors
++#
++CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
++CONFIG_PWM=y
++CONFIG_PWM_TIECAP=y
++CONFIG_PWM_TIEHRPWM=y
++# CONFIG_PWM_TWL6030 is not set
++CONFIG_EHRPWM_TEST=m
++
++#
++# CAPEBUS support
++#
++CONFIG_CAPEBUS=y
++CONFIG_CAPEBUS_BONE_CONTROLLER=y
++CONFIG_CAPEBUS_BONE_GENERIC=y
++CONFIG_CAPEBUS_BONE_GEIGER=y
++
++#
++# File systems
++#
++CONFIG_DCACHE_WORD_ACCESS=y
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
++# CONFIG_EXT3_FS_XATTR is not set
++CONFIG_EXT4_FS=y
++CONFIG_EXT4_FS_XATTR=y
++# CONFIG_EXT4_FS_POSIX_ACL is not set
++# CONFIG_EXT4_FS_SECURITY is not set
++# CONFIG_EXT4_DEBUG is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_JBD2=y
++# CONFIG_JBD2_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=m
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++CONFIG_JFS_FS=m
++# CONFIG_JFS_POSIX_ACL is not set
++# CONFIG_JFS_SECURITY is not set
++# CONFIG_JFS_DEBUG is not set
++# CONFIG_JFS_STATISTICS is not set
++CONFIG_XFS_FS=m
++CONFIG_XFS_QUOTA=y
++CONFIG_XFS_POSIX_ACL=y
++CONFIG_XFS_RT=y
++# CONFIG_XFS_DEBUG is not set
++CONFIG_GFS2_FS=m
++CONFIG_BTRFS_FS=m
++# CONFIG_BTRFS_FS_POSIX_ACL is not set
++# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
++CONFIG_NILFS2_FS=m
++CONFIG_FS_POSIX_ACL=y
++CONFIG_EXPORTFS=m
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_FANOTIFY is not set
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++# CONFIG_QUOTA_DEBUG is not set
++CONFIG_QUOTA_TREE=y
++# CONFIG_QFMT_V1 is not set
++CONFIG_QFMT_V2=y
++CONFIG_QUOTACTL=y
++CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
++CONFIG_CUSE=m
++
++#
++# Caches
++#
++# CONFIG_FSCACHE is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_ECRYPT_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_JFFS2_FS_XATTR=y
++CONFIG_JFFS2_FS_POSIX_ACL=y
++CONFIG_JFFS2_FS_SECURITY=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_LZO=y
++CONFIG_JFFS2_RTIME=y
++CONFIG_JFFS2_RUBIN=y
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
++CONFIG_UBIFS_FS=y
++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
++CONFIG_UBIFS_FS_LZO=y
++CONFIG_UBIFS_FS_ZLIB=y
++# CONFIG_LOGFS is not set
++CONFIG_CRAMFS=y
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX6FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_PSTORE is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_F2FS_FS=y
++CONFIG_F2FS_STAT_FS=y
++CONFIG_F2FS_FS_XATTR=y
++CONFIG_F2FS_FS_POSIX_ACL=y
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V2=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_NFS_SWAP=y
++# CONFIG_NFS_V4_1 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFS_USE_LEGACY_DNS is not set
++CONFIG_NFS_USE_KERNEL_DNS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_ACL_SUPPORT=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++CONFIG_SUNRPC_SWAP=y
++# CONFIG_SUNRPC_DEBUG is not set
++# CONFIG_CEPH_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_MAC_ROMAN is not set
++# CONFIG_NLS_MAC_CELTIC is not set
++# CONFIG_NLS_MAC_CENTEURO is not set
++# CONFIG_NLS_MAC_CROATIAN is not set
++# CONFIG_NLS_MAC_CYRILLIC is not set
++# CONFIG_NLS_MAC_GAELIC is not set
++# CONFIG_NLS_MAC_GREEK is not set
++# CONFIG_NLS_MAC_ICELAND is not set
++# CONFIG_NLS_MAC_INUIT is not set
++# CONFIG_NLS_MAC_ROMANIAN is not set
++# CONFIG_NLS_MAC_TURKISH is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Kernel hacking
++#
++CONFIG_PRINTK_TIME=y
++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_STRIP_ASM_SYMS is not set
++# CONFIG_READABLE_ASM is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_SECTION_MISMATCH is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_LOCKUP_DETECTOR is not set
++# CONFIG_PANIC_ON_OOPS is not set
++CONFIG_PANIC_ON_OOPS_VALUE=0
++# CONFIG_DETECT_HUNG_TASK is not set
++CONFIG_SCHED_DEBUG=y
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_DEBUG_SLAB is not set
++CONFIG_HAVE_DEBUG_KMEMLEAK=y
++# CONFIG_DEBUG_KMEMLEAK is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_SPARSE_RCU_POINTER is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_ATOMIC_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++CONFIG_STACKTRACE=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_INFO_REDUCED=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
++# CONFIG_DEBUG_MEMORY_INIT is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_TEST_LIST_SORT is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_DEBUG_NOTIFIERS is not set
++# CONFIG_DEBUG_CREDENTIALS is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++CONFIG_RCU_CPU_STALL_TIMEOUT=60
++# CONFIG_RCU_CPU_STALL_INFO is not set
++# CONFIG_RCU_TRACE is not set
++# CONFIG_KPROBES_SANITY_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
++# CONFIG_DEBUG_PER_CPU_MAPS is not set
++# CONFIG_LKDTM is not set
++CONFIG_NOTIFIER_ERROR_INJECTION=m
++# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
++CONFIG_PM_NOTIFIER_ERROR_INJECT=m
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_NOP_TRACER=y
++CONFIG_HAVE_FUNCTION_TRACER=y
++CONFIG_HAVE_DYNAMIC_FTRACE=y
++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
++CONFIG_HAVE_C_RECORDMCOUNT=y
++CONFIG_TRACE_CLOCK=y
++CONFIG_RING_BUFFER=y
++CONFIG_EVENT_TRACING=y
++CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
++CONFIG_CONTEXT_SWITCH_TRACER=y
++CONFIG_RING_BUFFER_ALLOW_SWAP=y
++CONFIG_TRACING=y
++CONFIG_TRACING_SUPPORT=y
++CONFIG_FTRACE=y
++# CONFIG_FUNCTION_TRACER is not set
++# CONFIG_IRQSOFF_TRACER is not set
++# CONFIG_SCHED_TRACER is not set
++# CONFIG_ENABLE_DEFAULT_TRACERS is not set
++# CONFIG_FTRACE_SYSCALLS is not set
++CONFIG_BRANCH_PROFILE_NONE=y
++# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
++# CONFIG_PROFILE_ALL_BRANCHES is not set
++# CONFIG_STACK_TRACER is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++CONFIG_KPROBE_EVENT=y
++CONFIG_PROBE_EVENTS=y
++# CONFIG_RING_BUFFER_BENCHMARK is not set
++# CONFIG_RBTREE_TEST is not set
++# CONFIG_INTERVAL_TREE_TEST is not set
++# CONFIG_DYNAMIC_DEBUG is not set
++# CONFIG_DMA_API_DEBUG is not set
++# CONFIG_ATOMIC64_SELFTEST is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++# CONFIG_TEST_KSTRTOX is not set
++# CONFIG_STRICT_DEVMEM is not set
++CONFIG_ARM_UNWIND=y
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_LL is not set
++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
++# CONFIG_ARM_KPROBES_TEST is not set
++# CONFIG_PID_IN_CONTEXTIDR is not set
++
++#
++# Security options
++#
++CONFIG_KEYS=y
++# CONFIG_ENCRYPTED_KEYS is not set
++# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
++# CONFIG_SECURITY_DMESG_RESTRICT is not set
++CONFIG_SECURITY=y
++CONFIG_SECURITYFS=y
++# CONFIG_SECURITY_NETWORK is not set
++# CONFIG_SECURITY_PATH is not set
++# CONFIG_SECURITY_TOMOYO is not set
++# CONFIG_SECURITY_APPARMOR is not set
++# CONFIG_SECURITY_YAMA is not set
++# CONFIG_IMA is not set
++# CONFIG_EVM is not set
++CONFIG_DEFAULT_SECURITY_DAC=y
++CONFIG_DEFAULT_SECURITY=""
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=y
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=m
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_PCOMP2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_USER is not set
++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++CONFIG_CRYPTO_PCRYPT=y
++CONFIG_CRYPTO_WORKQUEUE=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++CONFIG_CRYPTO_CBC=m
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=m
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=m
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_VMAC is not set
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=y
++# CONFIG_CRYPTO_GHASH is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=m
++CONFIG_CRYPTO_MICHAEL_MIC=y
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA1_ARM is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++CONFIG_CRYPTO_AES=y
++CONFIG_CRYPTO_AES_ARM=y
++# CONFIG_CRYPTO_ANUBIS is not set
++CONFIG_CRYPTO_ARC4=m
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++CONFIG_CRYPTO_DES=m
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=y
++# CONFIG_CRYPTO_ZLIB is not set
++CONFIG_CRYPTO_LZO=y
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_USER_API_HASH is not set
++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
++# CONFIG_CRYPTO_DEV_OMAP_AES is not set
++CONFIG_ASYMMETRIC_KEY_TYPE=m
++CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
++CONFIG_PUBLIC_KEY_ALGO_RSA=m
++CONFIG_X509_CERTIFICATE_PARSER=m
++CONFIG_BINARY_PRINTF=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_STRNCPY_FROM_USER=y
++CONFIG_GENERIC_STRNLEN_USER=y
++CONFIG_GENERIC_PCI_IOMAP=y
++CONFIG_GENERIC_IO=y
++CONFIG_CRC_CCITT=y
++CONFIG_CRC16=y
++CONFIG_CRC_T10DIF=y
++CONFIG_CRC_ITU_T=y
++CONFIG_CRC32=y
++# CONFIG_CRC32_SELFTEST is not set
++CONFIG_CRC32_SLICEBY8=y
++# CONFIG_CRC32_SLICEBY4 is not set
++# CONFIG_CRC32_SARWATE is not set
++# CONFIG_CRC32_BIT is not set
++CONFIG_CRC7=y
++CONFIG_LIBCRC32C=y
++# CONFIG_CRC8 is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++# CONFIG_XZ_DEC is not set
++# CONFIG_XZ_DEC_BCJ is not set
++CONFIG_DECOMPRESS_GZIP=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_CPU_RMAP=y
++CONFIG_DQL=y
++CONFIG_NLATTR=y
++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
++CONFIG_AVERAGE=y
++CONFIG_CLZ_TAB=y
++# CONFIG_CORDIC is not set
++# CONFIG_DDR is not set
++CONFIG_MPILIB=m
++CONFIG_OID_REGISTRY=m
diff --git a/patches/linux-3.7-rc6/0139-capebus-Geiger-Cape-config-bugfixs.patch b/patches/linux-3.7-rc6/0139-capebus-Geiger-Cape-config-bugfixs.patch
new file mode 100644
index 0000000..3af0453
--- /dev/null
+++ b/patches/linux-3.7-rc6/0139-capebus-Geiger-Cape-config-bugfixs.patch
@@ -0,0 +1,27 @@
+From 441e11b11ca8dcca74fb85715a204a52899feb49 Mon Sep 17 00:00:00 2001
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Sun, 18 Nov 2012 23:26:20 +0000
+Subject: [PATCH] capebus: Geiger Cape config bugfixs
+
+The display of 'vsense-name' default is incorrect.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/capebus/capes/bone-geiger-cape.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/capebus/capes/bone-geiger-cape.c b/drivers/capebus/capes/bone-geiger-cape.c
+index 880eaae..9e53d8d 100644
+--- a/drivers/capebus/capes/bone-geiger-cape.c
++++ b/drivers/capebus/capes/bone-geiger-cape.c
+@@ -417,8 +417,8 @@ static int bonegeiger_probe(struct cape_dev *dev, const struct cape_device_id *i
+ "vsense-name", &info->vsense_name) != 0) {
+ info->vsense_name = "AIN5";
+ dev_warn(&dev->dev, "Could not read vsense-name property; "
+- "using default %u\n",
+- val);
++ "using default '%s'\n",
++ info->vsense_name);
+ }
+
+ if (capebus_of_property_read_u32(dev,
diff --git a/patches/linux-3.7-rc6/series b/patches/linux-3.7-rc6/series
new file mode 100644
index 0000000..2c0930a
--- /dev/null
+++ b/patches/linux-3.7-rc6/series
@@ -0,0 +1,128 @@
+0000-linux-master.patch
+0001-video-st7735fb-add-st7735-framebuffer-driver.patch
+0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch
+0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
+0004-of-Add-generic-device-tree-DMA-helpers.patch
+0005-of-dma-fix-build-break-for-CONFIG_OF.patch
+0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch
+0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
+0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
+0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
+0010-ARM-edma-remove-unused-transfer-controller-handlers.patch
+0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch
+0012-ARM-edma-add-AM33XX-crossbar-event-support.patch
+0013-dmaengine-edma-enable-build-for-AM33XX.patch
+0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
+0015-ARM-dts-add-AM33XX-EDMA-support.patch
+0016-dmaengine-add-dma_request_slave_channel_compat.patch
+0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
+0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch
+0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
+0020-ARM-dts-add-AM33XX-MMC-support.patch
+0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
+0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
+0023-ARM-dts-add-AM33XX-SPI-support.patch
+0024-Documentation-bindings-add-spansion.patch
+0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
+0026-misc-add-gpevt-driver.patch
+0027-ARM-dts-add-BeagleBone-gpevt-support.patch
+0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch
+0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch
+0030-misc-gpevt-null-terminate-the-of_match_table.patch
+0031-proposed-probe-fix-works-for-me-on-evm.patch
+0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch
+0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch
+0035-net-cpsw-Add-parent-child-relation-support-between-c.patch
+0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch
+0038-i2c-pinctrl-ify-i2c-omap.c.patch
+0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
+0040-beaglebone-DT-set-default-triggers-for-LEDS.patch
+0041-beaglebone-add-a-cpu-led-trigger.patch
+0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch
+0045-input-TSC-ti_tscadc-Correct-register-usage.patch
+0046-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch
+0047-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch
+0048-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch
+0049-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch
+0050-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch
+0051-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch
+0052-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch
+0053-input-ti_am335x_tsc-Make-steps-enable-configurable.patch
+0054-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch
+0055-input-ti_am335x_tsc-Add-variance-filters.patch
+0056-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch
+0057-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch
+0059-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch
+0060-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
+0061-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch
+0062-Control-module-EHRPWM-clk-enabling.patch
+0063-pwm-pwm-tiecap-Enable-clock-gating.patch
+0064-PWM-ti-ehrpwm-fix-up-merge-conflict.patch
+0065-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
+0066-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch
+0067-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch
+0069-pinctrl-pinctrl-single-must-be-initialized-early.patch
+0070-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
+0071-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
+0072-beaglebone-fix-backlight-entry-in-DT.patch
+0074-Shut-up-musb.patch
+0075-musb-Fix-crashes-and-other-weirdness.patch
+0076-musb-revert-parts-of-032ec49f.patch
+0077-usb-musb-dsps-get-the-PHY-using-phandle-api.patch
+0078-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch
+0079-usb-otg-nop-add-dt-support.patch
+0080-usb-musb-dsps-add-phy-control-logic-to-glue.patch
+0081-usb-musb-dsps-enable-phy-control-for-am335x.patch
+0082-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch
+0084-omap2-clk-Add-missing-lcdc-clock-definition.patch
+0085-da8xx-Allow-use-by-am33xx-based-devices.patch
+0086-da8xx-Fix-revision-check-on-the-da8xx-driver.patch
+0087-da8xx-De-constify-members-in-the-platform-config.patch
+0088-da8xx-Add-standard-panel-definition.patch
+0089-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch
+0090-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch
+0092-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch
+0093-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
+0094-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
+0096-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch
+0098-f2fs-add-document.patch
+0099-f2fs-add-on-disk-layout.patch
+0100-f2fs-add-superblock-and-major-in-memory-structure.patch
+0101-f2fs-add-super-block-operations.patch
+0102-f2fs-add-checkpoint-operations.patch
+0103-f2fs-add-node-operations.patch
+0104-f2fs-add-segment-operations.patch
+0105-f2fs-add-file-operations.patch
+0106-f2fs-add-address-space-operations-for-data.patch
+0107-f2fs-add-core-inode-operations.patch
+0108-f2fs-add-inode-operations-for-special-inodes.patch
+0109-f2fs-add-core-directory-operations.patch
+0110-f2fs-add-xattr-and-acl-functionalities.patch
+0111-f2fs-add-garbage-collection-functions.patch
+0112-f2fs-add-recovery-routines-for-roll-forward.patch
+0113-f2fs-update-Kconfig-and-Makefile.patch
+0114-f2fs-gc.h-make-should_do_checkpoint-inline.patch
+0115-f2fs-move-statistics-code-into-one-file.patch
+0116-f2fs-move-proc-files-to-debugfs.patch
+0117-f2fs-compile-fix.patch
+0119-i2c-EEPROM-Export-memory-accessor.patch
+0120-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch
+0121-gpio-keys-Pinctrl-fy.patch
+0122-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
+0123-pwm-export-of_pwm_request.patch
+0124-i2c-Export-capability-to-probe-devices.patch
+0125-pwm-backlight-Pinctrl-fy.patch
+0126-spi-Export-OF-interfaces-for-capebus-use.patch
+0127-w1-gpio-Pinctrl-fy.patch
+0128-w1-gpio-Simplify-get-rid-of-defines.patch
+0129-arm-dt-Enable-DT-proc-updates.patch
+0130-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
+0131-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
+0132-beaglebone-enable-emmc-for-bonelt.patch
+0133-capebus-Core-capebus-support.patch
+0134-capebus-Add-beaglebone-board-support.patch
+0135-capebus-Beaglebone-generic-board.patch
+0136-capebus-Add-beaglebone-geiger-cape.patch
+0137-capebus-Beaglebone-capebus-DT-update.patch
+0138-beaglebone-Update-default-config-for-capebus.patch
+0139-capebus-Geiger-Cape-config-bugfixs.patch
diff --git a/platformconfig b/platformconfig
index c706a9d..726a692 100644
--- a/platformconfig
+++ b/platformconfig
@@ -1,8 +1,8 @@
#
# Automatically generated make config: don't edit
-# PTXdist 2012.09.1
+# PTXdist 2012.10.0-00092-g335bb61
#
-PTXCONF_PLATFORMCONFIG_VERSION="2012.09.1"
+PTXCONF_PLATFORMCONFIG_VERSION="2012.10.0-00092-g335bb61"
PTXCONF_RUNTIME=y
PTXCONF_BUILDTIME=y
PTXCONF__platformconfig_MAGIC__=y
@@ -19,7 +19,7 @@ PTXCONF__platformconfig_MAGIC__=y
# ------------------------------------
#
PTXCONF_PLATFORM="pengutronix-beagleboneti"
-PTXCONF_PLATFORM_VERSION="-2012.09.1"
+PTXCONF_PLATFORM_VERSION="-2012.10.0+master"
#
# architecture
@@ -83,8 +83,8 @@ PTXCONF_KERNEL_INSTALL=y
PTXCONF_KERNEL_MODULES=y
PTXCONF_KERNEL_MODULES_INSTALL=y
PTXCONF_KERNEL_MODULES_BUILD="modules"
-PTXCONF_KERNEL_VERSION="3.2.16"
-PTXCONF_KERNEL_MD5="8719646144bbadf51ab79e797a0ee0ee"
+PTXCONF_KERNEL_VERSION="3.7-rc6"
+PTXCONF_KERNEL_MD5="66a670a84bacec902d548362e9679112"
PTXCONF_KERNEL_ARCH_STRING="arm"
# PTXCONF_KERNEL_IMAGE_BZ is not set
# PTXCONF_KERNEL_IMAGE_Z is not set
@@ -95,6 +95,7 @@ PTXCONF_KERNEL_IMAGE_U=y
# PTXCONF_KERNEL_IMAGE_RAW is not set
# PTXCONF_KERNEL_IMAGE_SIMPLE is not set
PTXCONF_KERNEL_IMAGE="uImage"
+PTXCONF_KERNEL_DTC=y
PTXCONF_KERNEL_XZ=y
PTXCONF_KERNEL_LZOP=y
@@ -102,14 +103,17 @@ PTXCONF_KERNEL_LZOP=y
# patching & configuration
#
PTXCONF_KERNEL_SERIES="series"
-PTXCONF_KERNEL_CONFIG="kernelconfig-${PTXCONF_KERNEL_VERSION}"
+PTXCONF_KERNEL_CONFIG="kernelconfig"
#
# Development features
#
PTXCONF_KERNEL_EXTRA_MAKEVARS="CONFIG_DEBUG_SECTION_MISMATCH=y"
-# PTXCONF_HOST_DTC is not set
-# PTXCONF_DTC is not set
+PTXCONF_DTC=y
+# PTXCONF_DTC_INSTALL_OFTREE is not set
+PTXCONF_DTC_OFTREE_DTS="${KERNEL_DIR}/arch/arm/boot/dts/am335x-bone.dts"
+PTXCONF_DTC_KERNEL=y
+PTXCONF_DTC_EXTRA_ARGS=""
#
# console options
@@ -186,6 +190,8 @@ PTXCONF_IMAGE_VFAT_TOOLS=y
# new image creation options
#
PTXCONF_IMAGE_BOOT_MLO=y
+# PTXCONF_IMAGE_ROOT_CPIO_GZ is not set
+# PTXCONF_IMAGE_ROOT_CPIO is not set
PTXCONF_IMAGE_ROOT_EXT=y
PTXCONF_IMAGE_ROOT_EXT_SIZE="256M"
# PTXCONF_IMAGE_ROOT_EXT_EXT2 is not set
@@ -194,7 +200,6 @@ PTXCONF_IMAGE_ROOT_EXT_EXT4=y
PTXCONF_IMAGE_ROOT_EXT_TYPE="ext4"
PTXCONF_IMAGE_ROOT_TGZ=y
PTXCONF_IMAGE_SD=y
-PTXCONF_CROSS_MODULE_INIT_TOOLS=y
# PTXCONF_HOST_CDRKIT is not set
# PTXCONF_HOST_CMAKE is not set
# PTXCONF_HOST_CRAMFS is not set
@@ -209,6 +214,7 @@ PTXCONF_HOST_GENIMAGE=y
# PTXCONF_HOST_LIBBZ2 is not set
# PTXCONF_HOST_LIBCAP is not set
PTXCONF_HOST_LIBCONFUSE=y
+PTXCONF_HOST_LIBKMOD=y
PTXCONF_HOST_LIBLZO=y
# PTXCONF_HOST_LIBUUID is not set
PTXCONF_HOST_LZOP=y