summaryrefslogtreecommitdiffstats
path: root/patches/linux-3.8.13
diff options
context:
space:
mode:
Diffstat (limited to 'patches/linux-3.8.13')
-rw-r--r--patches/linux-3.8.13/0001-Without-MACH_-option-Early-printk-DEBUG_LL.patch117
-rw-r--r--patches/linux-3.8.13/0002-ARM-OMAP-Hack-AM33xx-clock-data-to-allow-JTAG-use.patch25
-rw-r--r--patches/linux-3.8.13/0003-video-st7735fb-add-st7735-framebuffer-driver.patch799
-rw-r--r--patches/linux-3.8.13/0004-dmaengine-add-helper-function-to-request-a-slave-DMA.patch93
-rw-r--r--patches/linux-3.8.13/0005-of-Add-generic-device-tree-DMA-helpers.patch532
-rw-r--r--patches/linux-3.8.13/0006-of-dma-fix-build-break-for-CONFIG_OF.patch53
-rw-r--r--patches/linux-3.8.13/0007-of-dma-fix-typos-in-generic-dma-binding-definition.patch68
-rw-r--r--patches/linux-3.8.13/0008-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch23
-rw-r--r--patches/linux-3.8.13/0009-dmaengine-edma-fix-slave-config-dependency-on-direct.patch143
-rw-r--r--patches/linux-3.8.13/0010-dmaengine-add-dma_get_channel_caps.patch96
-rw-r--r--patches/linux-3.8.13/0011-dma-edma-add-device_channel_caps-support.patch81
-rw-r--r--patches/linux-3.8.13/0012-mmc-davinci-get-SG-segment-limits-with-dma_get_chann.patch150
-rw-r--r--patches/linux-3.8.13/0013-ARM-davinci-move-private-EDMA-API-to-arm-common.patch4037
-rw-r--r--patches/linux-3.8.13/0014-ARM-edma-remove-unused-transfer-controller-handlers.patch68
-rw-r--r--patches/linux-3.8.13/0015-ARM-edma-add-AM33XX-support-to-the-private-EDMA-API.patch400
-rw-r--r--patches/linux-3.8.13/0016-dmaengine-edma-enable-build-for-AM33XX.patch24
-rw-r--r--patches/linux-3.8.13/0017-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch68
-rw-r--r--patches/linux-3.8.13/0018-ARM-dts-add-AM33XX-EDMA-support.patch43
-rw-r--r--patches/linux-3.8.13/0019-dmaengine-add-dma_request_slave_channel_compat.patch42
-rw-r--r--patches/linux-3.8.13/0020-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch45
-rw-r--r--patches/linux-3.8.13/0021-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch42
-rw-r--r--patches/linux-3.8.13/0022-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch55
-rw-r--r--patches/linux-3.8.13/0023-ARM-dts-add-AM33XX-MMC-support.patch118
-rw-r--r--patches/linux-3.8.13/0024-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch118
-rw-r--r--patches/linux-3.8.13/0025-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch55
-rw-r--r--patches/linux-3.8.13/0026-ARM-dts-add-AM33XX-SPI-DMA-support.patch39
-rw-r--r--patches/linux-3.8.13/0027-ARM-dts-Add-SPI-Flash-support-to-am335x-evm.patch54
-rw-r--r--patches/linux-3.8.13/0028-Documentation-bindings-add-spansion.patch21
-rw-r--r--patches/linux-3.8.13/0029-ARM-dts-enable-spi1-node-and-pinmux-on-BeagleBone.patch49
-rw-r--r--patches/linux-3.8.13/0030-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch51
-rw-r--r--patches/linux-3.8.13/0031-misc-add-gpevt-driver.patch218
-rw-r--r--patches/linux-3.8.13/0032-ARM-dts-add-BeagleBone-gpevt-support.patch57
-rw-r--r--patches/linux-3.8.13/0033-ARM-configs-working-dmaengine-configs-for-da8xx-and-.patch4874
-rw-r--r--patches/linux-3.8.13/0034-ARM-dts-Add-UART4-support-to-BeagleBone.patch24
-rw-r--r--patches/linux-3.8.13/0035-gpevnt-Remove-__devinit.patch42
-rw-r--r--patches/linux-3.8.13/0036-ARM-OMAP2-am33xx-hwmod-Fix-register-offset-NULL-chec.patch42
-rw-r--r--patches/linux-3.8.13/0037-rtc-OMAP-Add-system-pm_power_off-to-rtc-driver.patch170
-rw-r--r--patches/linux-3.8.13/0038-ARM-dts-AM33XX-Set-pmic-shutdown-controller-for-Beag.patch27
-rw-r--r--patches/linux-3.8.13/0039-ARM-dts-AM33XX-Enable-system-power-off-control-in-am.patch29
-rw-r--r--patches/linux-3.8.13/0040-i2c-pinctrl-ify-i2c-omap.c.patch44
-rw-r--r--patches/linux-3.8.13/0041-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch69
-rw-r--r--patches/linux-3.8.13/0042-beaglebone-DT-set-default-triggers-for-LEDS.patch28
-rw-r--r--patches/linux-3.8.13/0043-beaglebone-add-a-cpu-led-trigger.patch21
-rw-r--r--patches/linux-3.8.13/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch24
-rw-r--r--patches/linux-3.8.13/0045-mfd-input-iio-ti_am335x_adc-use-one-structure-for-ti.patch136
-rw-r--r--patches/linux-3.8.13/0046-input-ti_am33x_tsc-Step-enable-bits-made-configurabl.patch215
-rw-r--r--patches/linux-3.8.13/0047-input-ti_am33x_tsc-Order-of-TSC-wires-made-configura.patch257
-rw-r--r--patches/linux-3.8.13/0048-input-ti_am33x_tsc-remove-unwanted-fifo-flush.patch42
-rw-r--r--patches/linux-3.8.13/0049-input-ti_am33x_tsc-Add-DT-support.patch312
-rw-r--r--patches/linux-3.8.13/0050-iio-ti_am335x_adc-Add-DT-support.patch96
-rw-r--r--patches/linux-3.8.13/0051-arm-dts-AM335x-evm-Add-TSC-ADC-MFD-device-support.patch52
-rw-r--r--patches/linux-3.8.13/0052-mfd-ti_am335x_tscadc-Add-DT-support.patch86
-rw-r--r--patches/linux-3.8.13/0053-iio-ti_tscadc-provide-datasheet_name-and-scan_type.patch85
-rw-r--r--patches/linux-3.8.13/0054-mfd-ti_tscadc-deal-with-partial-activation.patch110
-rw-r--r--patches/linux-3.8.13/0055-input-ti_am335x_adc-use-only-FIFO0-and-clean-up-a-li.patch261
-rw-r--r--patches/linux-3.8.13/0056-input-ti_am335x_tsc-ACK-the-HW_PEN-irq-in-ISR.patch32
-rw-r--r--patches/linux-3.8.13/0057-input-ti_am335x_tsc-return-IRQ_NONE-if-there-was-no-.patch37
-rw-r--r--patches/linux-3.8.13/0058-iio-ti_am335x_adc-Allow-to-specify-input-line.patch213
-rw-r--r--patches/linux-3.8.13/0059-iio-ti_am335x_adc-check-if-we-found-the-value.patch43
-rw-r--r--patches/linux-3.8.13/0060-MFD-ti_tscadc-disable-TSC-control.patch59
-rw-r--r--patches/linux-3.8.13/0061-IIO-ADC-ti_adc-Fix-1st-sample-read.patch119
-rw-r--r--patches/linux-3.8.13/0062-input-ti_tsc-Enable-shared-IRQ-TSC.patch61
-rw-r--r--patches/linux-3.8.13/0063-Revert.-Backport-IIO.patch49
-rw-r--r--patches/linux-3.8.13/0064-iio-ti_am335x_adc-Added-iio_voltageX_scale.patch60
-rw-r--r--patches/linux-3.8.13/0065-iio-ti_am335x_adc-Add-the-in-kernel-IIO-map-interfac.patch122
-rw-r--r--patches/linux-3.8.13/0066-pinctrl-pinctrl-single-must-be-initialized-early.patch34
-rw-r--r--patches/linux-3.8.13/0067-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch93
-rw-r--r--patches/linux-3.8.13/0068-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch104
-rw-r--r--patches/linux-3.8.13/0069-am335x-evm-hack-around-i2c-node-names.patch36
-rw-r--r--patches/linux-3.8.13/0070-tsl2550-fix-lux1_input-error-in-low-light.patch31
-rw-r--r--patches/linux-3.8.13/0071-viafb-rename-display_timing-to-via_display_timing.patch137
-rw-r--r--patches/linux-3.8.13/0072-video-add-display_timing-and-videomode.patch340
-rw-r--r--patches/linux-3.8.13/0073-video-add-of-helper-for-display-timings-videomode.patch545
-rw-r--r--patches/linux-3.8.13/0074-fbmon-add-videomode-helpers.patch110
-rw-r--r--patches/linux-3.8.13/0075-fbmon-add-of_videomode-helpers.patch100
-rw-r--r--patches/linux-3.8.13/0076-drm_modes-add-videomode-helpers.patch96
-rw-r--r--patches/linux-3.8.13/0077-drm_modes-add-of_videomode-helpers.patch91
-rw-r--r--patches/linux-3.8.13/0078-fbmon-fix-build-error.patch33
-rw-r--r--patches/linux-3.8.13/0079-of-display-timings-use-of_get_child_by_name.patch22
-rw-r--r--patches/linux-3.8.13/0080-da8xx-Allow-use-by-am33xx-based-devices.patch24
-rw-r--r--patches/linux-3.8.13/0081-video-da8xx-fb-fb_check_var-enhancement.patch52
-rw-r--r--patches/linux-3.8.13/0082-video-da8xx-fb-simplify-lcd_reset.patch33
-rw-r--r--patches/linux-3.8.13/0083-video-da8xx-fb-use-modedb-helper-to-update-var.patch58
-rw-r--r--patches/linux-3.8.13/0084-video-da8xx-fb-remove-unneeded-var-initialization.patch52
-rw-r--r--patches/linux-3.8.13/0085-video-da8xx-fb-store-current-display-information.patch40
-rw-r--r--patches/linux-3.8.13/0086-video-da8xx-fb-store-clk-rate-even-if-CPUFREQ.patch37
-rw-r--r--patches/linux-3.8.13/0087-video-da8xx-fb-pix-clk-and-clk-div-handling-cleanup.patch150
-rw-r--r--patches/linux-3.8.13/0088-video-da8xx-fb-store-struct-device.patch32
-rw-r--r--patches/linux-3.8.13/0089-video-da8xx-fb-report-correct-pixclock.patch41
-rw-r--r--patches/linux-3.8.13/0090-video-da8xx-fb-fb_set_par-support.patch123
-rw-r--r--patches/linux-3.8.13/0091-ARM-dts-AM33XX-Add-lcdc-node.patch29
-rw-r--r--patches/linux-3.8.13/0092-ARM-dts-AM33XX-Add-am335x-evm-lcdc-panel-timings.patch39
-rw-r--r--patches/linux-3.8.13/0093-ARM-dts-AM33XX-Add-am335x-evm-lcdc-pincontrol-info.patch66
-rw-r--r--patches/linux-3.8.13/0094-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-panel-timings.patch39
-rw-r--r--patches/linux-3.8.13/0095-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-pincontrol-info.patch64
-rw-r--r--patches/linux-3.8.13/0096-ARM-OMAP-AM33xx-hwmod-Corrects-PWM-subsystem-HWMOD-e.patch250
-rw-r--r--patches/linux-3.8.13/0097-ARM-OMAP-AM33xx-hwmod-Add-parent-child-relationship-.patch654
-rw-r--r--patches/linux-3.8.13/0098-ARM-dts-AM33XX-Add-PWMSS-device-tree-nodes.patch113
-rw-r--r--patches/linux-3.8.13/0099-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch65
-rw-r--r--patches/linux-3.8.13/0100-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch66
-rw-r--r--patches/linux-3.8.13/0101-clk-divider-prepare-for-minimum-divider.patch165
-rw-r--r--patches/linux-3.8.13/0102-clk-divider-handle-minimum-divider.patch58
-rw-r--r--patches/linux-3.8.13/0103-ARM-OMAP2-dpll-round-rate-to-closest-value.patch58
-rw-r--r--patches/linux-3.8.13/0104-ARM-OMAP2-dpll-am335x-avoid-freqsel.patch27
-rw-r--r--patches/linux-3.8.13/0105-ARM-OMAP2-clock-DEFINE_STRUCT_CLK_FLAGS-helper.patch35
-rw-r--r--patches/linux-3.8.13/0106-ARM-AM33XX-clock-SET_RATE_PARENT-in-lcd-path.patch54
-rw-r--r--patches/linux-3.8.13/0107-video-da8xx-fb-make-io-operations-safe.patch31
-rw-r--r--patches/linux-3.8.13/0108-video-da8xx-fb-fix-24bpp-raster-configuration.patch33
-rw-r--r--patches/linux-3.8.13/0109-video-da8xx-fb-enable-sync-lost-intr-for-v2-ip.patch25
-rw-r--r--patches/linux-3.8.13/0110-video-da8xx-fb-use-devres.patch94
-rw-r--r--patches/linux-3.8.13/0111-video-da8xx-fb-ensure-non-null-cfg-in-pdata.patch27
-rw-r--r--patches/linux-3.8.13/0112-video-da8xx-fb-reorganize-panel-detection.patch86
-rw-r--r--patches/linux-3.8.13/0113-video-da8xx-fb-minimal-dt-support.patch60
-rw-r--r--patches/linux-3.8.13/0114-video-da8xx-fb-invoke-platform-callback-safely.patch27
-rw-r--r--patches/linux-3.8.13/0115-video-da8xx-fb-obtain-fb_videomode-info-from-dt.patch87
-rw-r--r--patches/linux-3.8.13/0116-video-da8xx-fb-ensure-pdata-only-for-non-dt.patch25
-rw-r--r--patches/linux-3.8.13/0117-video-da8xx-fb-setup-struct-lcd_ctrl_config-for-dt.patch66
-rw-r--r--patches/linux-3.8.13/0118-video-da8xx-fb-CCF-clock-divider-handling.patch164
-rw-r--r--patches/linux-3.8.13/0119-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch67
-rw-r--r--patches/linux-3.8.13/0120-Control-module-EHRPWM-clk-enabling.patch42
-rw-r--r--patches/linux-3.8.13/0121-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch369
-rw-r--r--patches/linux-3.8.13/0122-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch26
-rw-r--r--patches/linux-3.8.13/0123-pwm-export-of_pwm_request.patch71
-rw-r--r--patches/linux-3.8.13/0124-pwm-pwm-tiehrpwm-Update-the-clock-handling-of-pwm-ti.patch38
-rw-r--r--patches/linux-3.8.13/0125-ARM-AM33XX-clk-Add-clock-node-for-EHRPWM-TBCLK.patch80
-rw-r--r--patches/linux-3.8.13/0126-HACK-am33xx.dtsi-turn-on-all-PWMs.patch94
-rw-r--r--patches/linux-3.8.13/0127-pwm-add-sysfs-interface.patch790
-rw-r--r--patches/linux-3.8.13/0128-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch37
-rw-r--r--patches/linux-3.8.13/0129-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch30
-rw-r--r--patches/linux-3.8.13/0130-ARM-OMAP2xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch211
-rw-r--r--patches/linux-3.8.13/0131-ARM-OMAP2xxx-hwmod-Add-DMA-support-for-SHAM-module.patch45
-rw-r--r--patches/linux-3.8.13/0132-ARM-OMAP3xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch176
-rw-r--r--patches/linux-3.8.13/0133-ARM-OMAP2-Remove-unnecessary-message-when-no-SHA-IP-.patch46
-rw-r--r--patches/linux-3.8.13/0134-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch29
-rw-r--r--patches/linux-3.8.13/0135-ARM-AM33XX-Add-sha0-crypto-clock-data.patch36
-rw-r--r--patches/linux-3.8.13/0136-ARM-AM33XX-hwmod-Update-and-uncomment-SHA0-module-da.patch109
-rw-r--r--patches/linux-3.8.13/0137-ARM-dts-Add-SHAM-data-and-documentation-for-AM33XX.patch119
-rw-r--r--patches/linux-3.8.13/0138-ARM-OMAP2xxx-hwmod-Convert-AES-crypto-devcie-data-to.patch218
-rw-r--r--patches/linux-3.8.13/0139-ARM-OMAP3xxx-hwmod-Convert-AES-crypto-device-data-to.patch176
-rw-r--r--patches/linux-3.8.13/0140-ARM-OMAP2-Remove-unnecessary-message-when-no-AES-IP-.patch48
-rw-r--r--patches/linux-3.8.13/0141-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch29
-rw-r--r--patches/linux-3.8.13/0142-ARM-AM33XX-Add-aes0-crypto-clock-data.patch36
-rw-r--r--patches/linux-3.8.13/0143-ARM-AM33XX-hwmod-Update-and-uncomment-AES0-module-da.patch116
-rw-r--r--patches/linux-3.8.13/0144-ARM-dts-Add-AES-data-and-documentation-for-AM33XX.patch122
-rw-r--r--patches/linux-3.8.13/0145-crypto-omap-sham-Remove-unnecessary-pr_info-noise.patch25
-rw-r--r--patches/linux-3.8.13/0146-crypto-omap-sham-Convert-to-use-pm_runtime-API.patch111
-rw-r--r--patches/linux-3.8.13/0147-crypto-omap-sham-Add-suspend-resume-support.patch48
-rw-r--r--patches/linux-3.8.13/0148-crypto-omap-sham-Add-code-to-use-dmaengine-API.patch369
-rw-r--r--patches/linux-3.8.13/0149-crypto-omap-sham-Remove-usage-of-private-DMA-API.patch273
-rw-r--r--patches/linux-3.8.13/0150-crypto-omap-sham-Add-Device-Tree-Support.patch231
-rw-r--r--patches/linux-3.8.13/0151-crypto-omap-sham-Convert-to-dma_request_slave_channe.patch29
-rw-r--r--patches/linux-3.8.13/0152-crypto-omap-sham-Add-OMAP4-AM33XX-SHAM-Support.patch761
-rw-r--r--patches/linux-3.8.13/0153-crypto-omap-sham-Add-SHA224-and-SHA256-Support.patch310
-rw-r--r--patches/linux-3.8.13/0154-crypto-omap-aes-Remmove-unnecessary-pr_info-noise.patch35
-rw-r--r--patches/linux-3.8.13/0155-crypto-omap-aes-Don-t-reset-controller-for-every-ope.patch60
-rw-r--r--patches/linux-3.8.13/0156-crypto-omap-aes-Convert-to-use-pm_runtime-API.patch108
-rw-r--r--patches/linux-3.8.13/0157-crypto-omap-aes-Add-suspend-resume-support.patch48
-rw-r--r--patches/linux-3.8.13/0158-crypto-omap-aes-Add-code-to-use-dmaengine-API.patch384
-rw-r--r--patches/linux-3.8.13/0159-crypto-omap-aes-Remove-usage-of-private-DMA-API.patch327
-rw-r--r--patches/linux-3.8.13/0160-crypto-omap-aes-Add-Device-Tree-Support.patch194
-rw-r--r--patches/linux-3.8.13/0161-crypto-omap-aes-Convert-to-dma_request_slave_channel.patch43
-rw-r--r--patches/linux-3.8.13/0162-crypto-omap-aes-Add-OMAP4-AM33XX-AES-Support.patch315
-rw-r--r--patches/linux-3.8.13/0163-crypto-omap-aes-Add-CTR-algorithm-Support.patch289
-rw-r--r--patches/linux-3.8.13/0164-6lowpan-Refactor-packet-delivery-into-a-function.patch72
-rw-r--r--patches/linux-3.8.13/0165-6lowpan-Handle-uncompressed-IPv6-packets-over-6LoWPA.patch68
-rw-r--r--patches/linux-3.8.13/0166-wpan-whitespace-fix.patch23
-rw-r--r--patches/linux-3.8.13/0167-6lowpan-use-stack-buffer-instead-of-heap.patch50
-rw-r--r--patches/linux-3.8.13/0168-wpan-use-stack-buffer-instead-of-heap.patch43
-rw-r--r--patches/linux-3.8.13/0169-mrf24j40-pinctrl-support.patch43
-rw-r--r--patches/linux-3.8.13/0170-mrf24j40-Warn-if-transmit-interrupts-timeout.patch23
-rw-r--r--patches/linux-3.8.13/0171-mrf24j40-Increase-max-SPI-speed-to-10MHz.patch28
-rw-r--r--patches/linux-3.8.13/0172-mrf24j40-Fix-byte-order-of-IEEE-address.patch25
-rw-r--r--patches/linux-3.8.13/0173-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch31
-rw-r--r--patches/linux-3.8.13/0174-6lowpan-next-header-is-not-properly-set-upon-decompr.patch29
-rw-r--r--patches/linux-3.8.13/0175-6lowpan-always-enable-link-layer-acknowledgments.patch30
-rw-r--r--patches/linux-3.8.13/0176-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch22
-rw-r--r--patches/linux-3.8.13/0177-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch54
-rw-r--r--patches/linux-3.8.13/0178-6lowpan-fix-first-fragment-FRAG1-handling.patch119
-rw-r--r--patches/linux-3.8.13/0179-6lowpan-add-debug-messages-for-6LoWPAN-fragmentation.patch80
-rw-r--r--patches/linux-3.8.13/0180-6lowpan-store-fragment-tag-values-per-device-instead.patch64
-rw-r--r--patches/linux-3.8.13/0181-mac802154-add-mac802154_dev_get_dsn.patch57
-rw-r--r--patches/linux-3.8.13/0182-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch46
-rw-r--r--patches/linux-3.8.13/0183-6lowpan-use-the-PANID-provided-by-the-device-instead.patch29
-rw-r--r--patches/linux-3.8.13/0184-6lowpan-modify-udp-compression-uncompression-to-matc.patch86
-rw-r--r--patches/linux-3.8.13/0185-6lowpan-fix-a-small-formatting-issue.patch25
-rw-r--r--patches/linux-3.8.13/0186-6lowpan-use-IEEE802154_ADDR_LEN-instead-of-a-magic-n.patch22
-rw-r--r--patches/linux-3.8.13/0187-gpio-keys-Pinctrl-fy.patch47
-rw-r--r--patches/linux-3.8.13/0188-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch194
-rw-r--r--patches/linux-3.8.13/0189-pwm-backlight-Pinctrl-fy.patch36
-rw-r--r--patches/linux-3.8.13/0190-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch56
-rw-r--r--patches/linux-3.8.13/0191-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch640
-rw-r--r--patches/linux-3.8.13/0192-beaglebone-enable-emmc-for-bonelt.patch48
-rw-r--r--patches/linux-3.8.13/0193-Fix-appended-dtb-rule.patch36
-rw-r--r--patches/linux-3.8.13/0194-deb-pkg-Simplify-architecture-matching-for-cross-bui.patch135
-rw-r--r--patches/linux-3.8.13/0195-Without-MACH_-option-Early-printk-DEBUG_LL.patch105
-rw-r--r--patches/linux-3.8.13/0196-ARM-7668-1-fix-memset-related-crashes-caused-by-rece.patch252
-rw-r--r--patches/linux-3.8.13/0197-ARM-7670-1-fix-the-memset-fix.patch79
-rw-r--r--patches/linux-3.8.13/0198-regulator-core-if-voltage-scaling-fails-restore-orig.patch53
-rw-r--r--patches/linux-3.8.13/0199-omap2-twl-common-Add-default-power-configuration.patch84
-rw-r--r--patches/linux-3.8.13/0200-omap2-irq-fix-interrupt-latency.patch22
-rw-r--r--patches/linux-3.8.13/0201-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch74
-rw-r--r--patches/linux-3.8.13/0202-video-add-timings-for-hd720.patch24
-rw-r--r--patches/linux-3.8.13/0203-Beagle-expansion-add-buddy-param-for-expansionboard-.patch58
-rw-r--r--patches/linux-3.8.13/0204-Beagle-expansion-add-zippy.patch238
-rw-r--r--patches/linux-3.8.13/0205-Beagle-expansion-add-zippy2.patch82
-rw-r--r--patches/linux-3.8.13/0206-Beagle-expansion-add-trainer.patch51
-rw-r--r--patches/linux-3.8.13/0207-Beagle-expansion-add-CircuitCo-ulcd-Support.patch289
-rw-r--r--patches/linux-3.8.13/0208-Beagle-expansion-add-wifi.patch176
-rw-r--r--patches/linux-3.8.13/0209-Beagle-expansion-add-beaglefpga.patch111
-rw-r--r--patches/linux-3.8.13/0210-Beagle-expansion-add-spidev.patch29
-rw-r--r--patches/linux-3.8.13/0211-Beagle-expansion-add-Aptina-li5m03-camera.patch223
-rw-r--r--patches/linux-3.8.13/0212-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch119
-rw-r--r--patches/linux-3.8.13/0213-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch26
-rw-r--r--patches/linux-3.8.13/0214-backlight-Add-TLC59108-backlight-control-driver.patch212
-rw-r--r--patches/linux-3.8.13/0215-tlc59108-adjust-for-beagleboard-uLCD7.patch120
-rw-r--r--patches/linux-3.8.13/0216-zeroMAP-Open-your-eyes.patch27
-rw-r--r--patches/linux-3.8.13/0217-ARM-OMAP-Beagle-use-TWL4030-generic-reset-script.patch25
-rw-r--r--patches/linux-3.8.13/0218-panda-fix-wl12xx-regulator.patch23
-rw-r--r--patches/linux-3.8.13/0219-ti-st-st-kim-fixing-firmware-path.patch32
-rw-r--r--patches/linux-3.8.13/0220-am33xx-cpsw-default-to-ethernet-hwaddr-from-efuse-if.patch151
-rw-r--r--patches/linux-3.8.13/0221-Attempted-SMC911x-BQL-patch.patch56
-rw-r--r--patches/linux-3.8.13/0222-cpsw-Fix-interrupt-storm-among-other-things.patch419
-rw-r--r--patches/linux-3.8.13/0223-beaglebone-TT3201-MCP2515-fixes.patch162
-rw-r--r--patches/linux-3.8.13/0224-add-proper-db.txt-for-CRDA.patch830
-rw-r--r--patches/linux-3.8.13/0225-mcp251x-add-device-tree-support.patch349
-rw-r--r--patches/linux-3.8.13/0226-am33xx-Add-clock-for-the-lcdc-DRM-driver.patch23
-rw-r--r--patches/linux-3.8.13/0227-drm-small-fix-in-drm_send_vblank_event.patch25
-rw-r--r--patches/linux-3.8.13/0228-drm-cma-add-debugfs-helpers.patch144
-rw-r--r--patches/linux-3.8.13/0229-drm-i2c-encoder-helper-wrappers.patch114
-rw-r--r--patches/linux-3.8.13/0230-drm-nouveau-use-i2c-encoder-helper-wrappers.patch90
-rw-r--r--patches/linux-3.8.13/0231-drm-i2c-give-i2c-it-s-own-Kconfig.patch88
-rw-r--r--patches/linux-3.8.13/0232-drm-tilcdc-add-TI-LCD-Controller-DRM-driver-v4.patch2089
-rw-r--r--patches/linux-3.8.13/0233-drm-i2c-nxp-tda998x-v3.patch956
-rw-r--r--patches/linux-3.8.13/0234-drm-tilcdc-add-encoder-slave.patch475
-rw-r--r--patches/linux-3.8.13/0235-drm-tilcdc-add-support-for-LCD-panels-v5.patch557
-rw-r--r--patches/linux-3.8.13/0236-drm-lcdc-Power-control-GPIO-support.patch62
-rw-r--r--patches/linux-3.8.13/0237-drm-tilcdc-Fix-scheduling-while-atomic-from-irq-hand.patch53
-rw-r--r--patches/linux-3.8.13/0238-add-dvi-pinmuxes-to-am33xx.dtsi.patch74
-rw-r--r--patches/linux-3.8.13/0239-add-defconfig-file-to-use-as-.config.patch4013
-rw-r--r--patches/linux-3.8.13/0240-am33xx-musb-Add-OF-definitions.patch82
-rw-r--r--patches/linux-3.8.13/0241-Mark-the-device-as-PRIVATE.patch52
-rw-r--r--patches/linux-3.8.13/0242-omap_hsmmc-Bug-fixes-pinctl-gpio-reset.patch138
-rw-r--r--patches/linux-3.8.13/0243-tps65217-bl-Locate-backlight-node-correctly.patch47
-rw-r--r--patches/linux-3.8.13/0244-arm-Export-cache-flush-management-symbols-when-MULTI.patch29
-rw-r--r--patches/linux-3.8.13/0245-am335x-bone-dtsi-Clean-up.patch127
-rw-r--r--patches/linux-3.8.13/0246-am335x-bone-dtsi-Introduce-new-I2C-entries.patch55
-rw-r--r--patches/linux-3.8.13/0247-am335x-dt-Add-I2C0-pinctrl-entries.patch38
-rw-r--r--patches/linux-3.8.13/0248-Cleanup-am33xx.dtsi.patch73
-rw-r--r--patches/linux-3.8.13/0249-Fix-platform-device-resource-linking.patch214
-rw-r--r--patches/linux-3.8.13/0250-Link-platform-device-resources-properly.patch27
-rw-r--r--patches/linux-3.8.13/0251-Properly-handle-resources-for-omap_devices.patch290
-rw-r--r--patches/linux-3.8.13/0252-omap-Avoid-crashes-in-the-case-of-hwmod-misconfigura.patch79
-rw-r--r--patches/linux-3.8.13/0253-i2c-EEPROM-In-kernel-memory-accessor-interface.patch127
-rw-r--r--patches/linux-3.8.13/0254-Fix-util_is_printable_string.patch50
-rw-r--r--patches/linux-3.8.13/0255-fdtdump-properly-handle-multi-string-properties.patch41
-rw-r--r--patches/linux-3.8.13/0256-dtc-Dynamic-symbols-fixup-support.patch2901
-rw-r--r--patches/linux-3.8.13/0257-dtc-Add-DTCO-rule-for-DTB-objects.patch26
-rw-r--r--patches/linux-3.8.13/0258-OF-Compile-Device-Tree-sources-with-resolve-option.patch57
-rw-r--r--patches/linux-3.8.13/0259-firmware-update-.gitignore-with-dtbo-objects.patch20
-rw-r--r--patches/linux-3.8.13/0260-OF-Introduce-device-tree-node-flag-helpers.patch42
-rw-r--r--patches/linux-3.8.13/0261-OF-export-of_property_notify.patch60
-rw-r--r--patches/linux-3.8.13/0262-OF-Export-all-DT-proc-update-functions.patch209
-rw-r--r--patches/linux-3.8.13/0263-OF-Introduce-utility-helper-functions.patch360
-rw-r--r--patches/linux-3.8.13/0264-OF-Introduce-Device-Tree-resolve-support.patch504
-rw-r--r--patches/linux-3.8.13/0265-OF-Introduce-DT-overlay-support.patch1186
-rw-r--r--patches/linux-3.8.13/0266-capemgr-Capemgr-makefiles-and-Kconfig-fragments.patch115
-rw-r--r--patches/linux-3.8.13/0267-capemgr-Beaglebone-capemanager.patch1855
-rw-r--r--patches/linux-3.8.13/0268-capemgr-Add-beaglebone-s-cape-driver-bindings.patch128
-rw-r--r--patches/linux-3.8.13/0269-capemgr-am33xx-family-DT-bindings.patch125
-rw-r--r--patches/linux-3.8.13/0270-bone-geiger-Geiger-bone-driver.patch507
-rw-r--r--patches/linux-3.8.13/0271-capemgr-firmware-makefiles-for-DT-objects.patch53
-rw-r--r--patches/linux-3.8.13/0272-capemgr-emmc2-cape-definition.patch71
-rw-r--r--patches/linux-3.8.13/0273-capemgr-DVI-capes-definitions.patch216
-rw-r--r--patches/linux-3.8.13/0274-capemgr-Geiger-cape-definition.patch116
-rw-r--r--patches/linux-3.8.13/0275-capemgr-LCD3-cape-definition.patch196
-rw-r--r--patches/linux-3.8.13/0276-capemgr-Add-weather-cape-definition.patch122
-rw-r--r--patches/linux-3.8.13/0277-ehrpwm-add-missing-dts-nodes.patch49
-rw-r--r--patches/linux-3.8.13/0278-am33xx-DT-Update-am33xx.dsi-with-the-new-PWM-DT-bind.patch140
-rw-r--r--patches/linux-3.8.13/0279-geiger-cape-Update-to-using-the-new-PWM-interface.patch38
-rw-r--r--patches/linux-3.8.13/0280-lcd3-cape-Change-into-using-the-lcdc-DRM-driver-inst.patch102
-rw-r--r--patches/linux-3.8.13/0281-am33xx-Add-default-config.patch621
-rw-r--r--patches/linux-3.8.13/0282-lcd3-cape-Convert-to-using-the-proper-touchscreen-dr.patch64
-rw-r--r--patches/linux-3.8.13/0283-geiger-cape-Convert-to-using-the-new-ADC-driver.patch47
-rw-r--r--patches/linux-3.8.13/0284-cape-dvi-Convert-DVI-capes-to-the-new-LCDC-DRM-drive.patch163
-rw-r--r--patches/linux-3.8.13/0285-boneblack-Add-default-HDMI-cape.patch161
-rw-r--r--patches/linux-3.8.13/0286-cape-bone-dvi-Use-720p-mode-as-default.patch75
-rw-r--r--patches/linux-3.8.13/0287-am33xx.dtsi-Make-the-MUSB-not-crash-on-load.patch104
-rw-r--r--patches/linux-3.8.13/0288-regulator-DUMMY_REGULATOR-should-work-for-OF-too.patch32
-rw-r--r--patches/linux-3.8.13/0289-OF-Overlay-Remove-excessive-debugging-crud.patch84
-rw-r--r--patches/linux-3.8.13/0290-of-i2c-Export-single-device-registration-method.patch167
-rw-r--r--patches/linux-3.8.13/0291-OF-Overlay-I2C-client-devices-special-handling.patch193
-rw-r--r--patches/linux-3.8.13/0292-omap-Fix-bug-on-partial-resource-addition.patch25
-rw-r--r--patches/linux-3.8.13/0293-ASoC-davinci-mcasp-Add-pinctrl-support.patch41
-rw-r--r--patches/linux-3.8.13/0294-ASoC-Davinci-machine-Add-device-tree-binding.patch313
-rw-r--r--patches/linux-3.8.13/0295-am33xx-Add-mcasp0-and-mcasp1-device-tree-entries.patch42
-rw-r--r--patches/linux-3.8.13/0296-ASoC-dts-OMAP2-AM33xx-HACK-Add-missing-dma-info.patch91
-rw-r--r--patches/linux-3.8.13/0297-ASoC-Davinci-McASP-remove-unused-header-include.patch29
-rw-r--r--patches/linux-3.8.13/0298-ASoC-AM33XX-Add-support-for-AM33xx-SoC-Audio.patch55
-rw-r--r--patches/linux-3.8.13/0299-am33xx-mcasp-Add-dma-channel-definitions.patch37
-rw-r--r--patches/linux-3.8.13/0300-ARM-OMAP2-AM33xx-removed-invalid-McASP-HWMOD-data.patch77
-rw-r--r--patches/linux-3.8.13/0301-davinci-evm-Header-include-move-fix.patch25
-rw-r--r--patches/linux-3.8.13/0302-bone-dvi-cape-Add-DT-definition-for-00A2-revision.patch23
-rw-r--r--patches/linux-3.8.13/0303-bone-dvi-cape-Update-A1-cape-definition-with-sound.patch129
-rw-r--r--patches/linux-3.8.13/0304-sndsoc-mcasp-Get-DMA-channels-via-byname.patch40
-rw-r--r--patches/linux-3.8.13/0305-sound-soc-Davinci-Remove-__devinit-__devexit.patch33
-rw-r--r--patches/linux-3.8.13/0306-st7735fb-Remove-__devinit-__devexit.patch60
-rw-r--r--patches/linux-3.8.13/0307-capemgr-Remove-__devinit-__devexit.patch42
-rw-r--r--patches/linux-3.8.13/0308-capes-fw-target-firmware-directory-change.patch54
-rw-r--r--patches/linux-3.8.13/0309-am33xx-edma-Always-update-unused-channel-list.patch57
-rw-r--r--patches/linux-3.8.13/0310-defconfig-Update-bone-default-config.patch169
-rw-r--r--patches/linux-3.8.13/0311-capes-add-dvi-a2-and-lcd3-a2-dts-files.patch560
-rw-r--r--patches/linux-3.8.13/0312-capemgr-catch-up-with-lcdc-tilcdc-rename.patch145
-rw-r--r--patches/linux-3.8.13/0313-firmware-fix-dvi-a1-target.patch23
-rw-r--r--patches/linux-3.8.13/0314-capes-remove-tda-from-hdmi-cape-lcdc-handles-it-by-t.patch37
-rw-r--r--patches/linux-3.8.13/0315-tilcdc-magic-debug-statement-makes-power-gpio-work-o.patch29
-rw-r--r--patches/linux-3.8.13/0316-capemgr-add-dts-overlay-for-LCD7-00A2-cape.patch256
-rw-r--r--patches/linux-3.8.13/0317-HACK-am33xx.dtsi-enable-all-PWMs.patch94
-rw-r--r--patches/linux-3.8.13/0318-beaglebone-Add-nixie-cape-prototype-driver.patch447
-rw-r--r--patches/linux-3.8.13/0319-beaglebone-Add-nixie-cape-device-tree-entry.patch179
-rw-r--r--patches/linux-3.8.13/0320-am335x-bone-common.dtsi-Cleanup-test-remnants.patch52
-rw-r--r--patches/linux-3.8.13/0321-omap_hsmmc-Add-ti-vcc-aux-disable-is-sleep-DT-proper.patch25
-rw-r--r--patches/linux-3.8.13/0322-bone-common-ti-vcc-aux-disable-is-sleep-enable.patch36
-rw-r--r--patches/linux-3.8.13/0323-am33xx-disable-NAPI.patch21
-rw-r--r--patches/linux-3.8.13/0324-capemgr-Fixed-AIN-name-display-in-error-message.patch25
-rw-r--r--patches/linux-3.8.13/0325-am33xx.dtsi-remove-duplicate-nodes.patch110
-rw-r--r--patches/linux-3.8.13/0326-cape-dtbos-update-to-latest-OF-videomode-bindings.patch77
-rw-r--r--patches/linux-3.8.13/0327-beaglebone-uncomment-eMMC-override.patch36
-rw-r--r--patches/linux-3.8.13/0328-bone-capes-Update-with-new-tscadc-bindings.patch111
-rw-r--r--patches/linux-3.8.13/0329-am33xx.dtsi-Update-and-disable-status-of-nodes.patch101
-rw-r--r--patches/linux-3.8.13/0330-bone-capes-Adapt-to-new-pwms-setup.patch87
-rw-r--r--patches/linux-3.8.13/0331-tilcdc-introduce-panel-tfp410-power-down-gpio-contro.patch115
-rw-r--r--patches/linux-3.8.13/0332-bone-dvi-Update-to-new-style-tilcdc-bindings.patch154
-rw-r--r--patches/linux-3.8.13/0333-tilcdc-tfp410-Rework-power-down-GPIO-logic.patch76
-rw-r--r--patches/linux-3.8.13/0334-tilcdc-Add-reduced-blanking-mode-checks.patch74
-rw-r--r--patches/linux-3.8.13/0335-cape-dvi-Switch-all-DVI-capes-to-using-the-TFTP410-p.patch208
-rw-r--r--patches/linux-3.8.13/0336-beaglebone-switch-eMMC-to-8bit-mode.patch36
-rw-r--r--patches/linux-3.8.13/0337-Pinmux-helper-driver.patch130
-rw-r--r--patches/linux-3.8.13/0338-OF-Clear-detach-flag-on-attach.patch24
-rw-r--r--patches/linux-3.8.13/0339-OF-overlay-Fix-overlay-revert-failure.patch337
-rw-r--r--patches/linux-3.8.13/0340-bone-capemgr-Make-sure-cape-removal-works.patch109
-rw-r--r--patches/linux-3.8.13/0341-bone-capemgr-Fix-crash-when-trying-to-remove-non-exi.patch36
-rw-r--r--patches/linux-3.8.13/0342-beaglebone-LCD7-cape-enable-PWM-and-allow-the-specif.patch42
-rw-r--r--patches/linux-3.8.13/0343-bone-capemgr-Introduce-pinmux-helper.patch74
-rw-r--r--patches/linux-3.8.13/0344-bone-geiger-Fix-comment-to-match-the-contents.patch21
-rw-r--r--patches/linux-3.8.13/0345-of-overlay-Handle-I2C-devices-already-registered-by-.patch54
-rw-r--r--patches/linux-3.8.13/0346-pinmux-helper-Add-runtime-configuration-capability.patch171
-rw-r--r--patches/linux-3.8.13/0347-pinmux-helper-Switch-to-using-kmalloc.patch64
-rw-r--r--patches/linux-3.8.13/0348-i2c-DTify-pca954x-driver.patch151
-rw-r--r--patches/linux-3.8.13/0349-tty-Add-JHD629-I2C-LCD-Keypad-TTY-driver.patch1042
-rw-r--r--patches/linux-3.8.13/0350-grove-i2c-Add-rudimentary-grove-i2c-motor-control-dr.patch286
-rw-r--r--patches/linux-3.8.13/0351-tty-jhd629-i2c-Clean-keypad-buffer-when-starting.patch32
-rw-r--r--patches/linux-3.8.13/0352-am335x-bone-common-Remove-SPI-unused-pinmux-config.patch31
-rw-r--r--patches/linux-3.8.13/0353-bone-capemgr-Force-a-slot-to-load-unconditionally.patch27
-rw-r--r--patches/linux-3.8.13/0354-beaglebone-Added-Adafruit-prototype-cape.patch195
-rw-r--r--patches/linux-3.8.13/0355-tilcdc-Enable-reduced-blanking-check-only-on-DVI-sla.patch103
-rw-r--r--patches/linux-3.8.13/0356-cape-adafruit-Use-the-correct-spi-bus-spi1-no-spi0.patch24
-rw-r--r--patches/linux-3.8.13/0357-BBB-tester-Introduce-board-DTS.patch416
-rw-r--r--patches/linux-3.8.13/0358-BBB-tester-Introduce-cape-describing-the-contents-of.patch453
-rw-r--r--patches/linux-3.8.13/0359-bone-tester-Add-overrides-for-BB-BONE-TESTER.patch48
-rw-r--r--patches/linux-3.8.13/0360-cape-tester-Add-uart-specific-default-pinmux-state.patch96
-rw-r--r--patches/linux-3.8.13/0361-cape-tester-Add-pinmux-helper-for-drvvbus-gpio.patch47
-rw-r--r--patches/linux-3.8.13/0362-cape-Added-support-for-IIO-helper-cape.patch227
-rw-r--r--patches/linux-3.8.13/0363-cape-Added-example-IIO-tester-dynamics-overlay.patch66
-rw-r--r--patches/linux-3.8.13/0364-docs-Added-capemanager-extra_override-usage.patch25
-rw-r--r--patches/linux-3.8.13/0365-capemgr-Added-module-param-descriptions.patch23
-rw-r--r--patches/linux-3.8.13/0366-beaglebone-Add-Adafruit-RTC-prototype-cape.patch122
-rw-r--r--patches/linux-3.8.13/0367-cape-vsense-scale-division-by-zero-check.patch47
-rw-r--r--patches/linux-3.8.13/0368-capes-add-cape-for-beaglebone-based-Hexy-robot.patch214
-rw-r--r--patches/linux-3.8.13/0369-Extend-bone-iio-helper.patch232
-rw-r--r--patches/linux-3.8.13/0370-Update-iio-helper-with-more-channels.patch40
-rw-r--r--patches/linux-3.8.13/0371-Add-ADC-IIO-helper.patch48
-rw-r--r--patches/linux-3.8.13/0372-Changing-DT-data-to-make-selection-of-standard-i.e.-.patch21
-rw-r--r--patches/linux-3.8.13/0373-Enhancing-to-support-extra-device-tree-options-for-t.patch147
-rw-r--r--patches/linux-3.8.13/0374-add-WIP-support-LCD4-rev-00A4.patch269
-rw-r--r--patches/linux-3.8.13/0375-add-eMMC-cape-support.patch82
-rw-r--r--patches/linux-3.8.13/0376-Remove-UART-pins-from-the-expansion-set.patch34
-rw-r--r--patches/linux-3.8.13/0377-Remove-LCD-pins-from-the-expansion-test-part.patch106
-rw-r--r--patches/linux-3.8.13/0378-Remove-I2C2-pins-from-expansion-test.patch36
-rw-r--r--patches/linux-3.8.13/0379-Add-expansion-test-cape-fragment.patch185
-rw-r--r--patches/linux-3.8.13/0380-tilcdc-added-some-extra-debug-and-softened-the-wordi.patch48
-rw-r--r--patches/linux-3.8.13/0381-Make-sure-various-timings-fit-within-the-bits-availa.patch137
-rw-r--r--patches/linux-3.8.13/0382-fix-cape-bone-hexy.patch91
-rw-r--r--patches/linux-3.8.13/0383-firmware-DT-Fragment-for-MRF24J40-BeagleBone-Cape.patch109
-rw-r--r--patches/linux-3.8.13/0384-firmware-capes-Update-MRF24J40-cape-to-work-with-lat.patch70
-rw-r--r--patches/linux-3.8.13/0385-am335x-bone-common-DT-Override-for-MRF24J40-Cape.patch52
-rw-r--r--patches/linux-3.8.13/0386-beaglebone-black-limit-LDO3-to-1.8V.patch26
-rw-r--r--patches/linux-3.8.13/0387-beaglebone-black-add-new-fixed-regulator-for-uSD-eMM.patch47
-rw-r--r--patches/linux-3.8.13/0388-capemgr-Implement-disable-overrides-on-the-cmd-line.patch218
-rw-r--r--patches/linux-3.8.13/0389-tilcdc-Enable-pinmux-states.patch492
-rw-r--r--patches/linux-3.8.13/0390-cape-Add-a-simple-cape-for-handling-the-uSD-button.patch84
-rw-r--r--patches/linux-3.8.13/0391-beaglebone-add-support-for-DVI-00A3.patch42
-rw-r--r--patches/linux-3.8.13/0392-beaglebone-remove-audio-section-from-DVID-rev-2-and-.patch90
-rw-r--r--patches/linux-3.8.13/0393-beaglebone-add-dts-for-audio-cape.patch154
-rw-r--r--patches/linux-3.8.13/0394-cape-bone-hexy-add-iio-helper.patch48
-rw-r--r--patches/linux-3.8.13/0395-cape-Add-CAPE-BONE-EXPTEST-to-capemaps.patch27
-rw-r--r--patches/linux-3.8.13/0396-tester-button-cape.patch31
-rw-r--r--patches/linux-3.8.13/0397-pwm_test-fix-some-issues.patch89
-rw-r--r--patches/linux-3.8.13/0398-pwm_test-Clean-up-and-make-it-work-on-DT-correctly.patch467
-rw-r--r--patches/linux-3.8.13/0399-capes-Add-PWM-test-example-cape.patch89
-rw-r--r--patches/linux-3.8.13/0400-Sync-tester-DTS-with-am335x-common.patch134
-rw-r--r--patches/linux-3.8.13/0401-Add-in-missing-cape-bone-tester-back-in.patch28
-rw-r--r--patches/linux-3.8.13/0402-cape-bone-hexy-move-OLED-to-different-reset-gpio.patch22
-rw-r--r--patches/linux-3.8.13/0403-firmware-capes-added-dts-file-for-every-PWM-pin.patch830
-rw-r--r--patches/linux-3.8.13/0404-capes-add-LCD7-A3.patch271
-rw-r--r--patches/linux-3.8.13/0405-capes-add-basic-support-for-LCD4-capes.patch440
-rw-r--r--patches/linux-3.8.13/0406-OF-overlay-Add-depth-option-for-device-creation.patch83
-rw-r--r--patches/linux-3.8.13/0407-capes-Add-BB-BONE-GPEVT-cape.patch72
-rw-r--r--patches/linux-3.8.13/0408-clock-Export-__clock_set_parent.patch47
-rw-r--r--patches/linux-3.8.13/0409-omap-clk-Add-adjustable-clkout2.patch276
-rw-r--r--patches/linux-3.8.13/0410-am33xx-Update-DTS-EDMA.patch48
-rw-r--r--patches/linux-3.8.13/0411-bone-Added-RS232-prototype-cape-DT-object.patch110
-rw-r--r--patches/linux-3.8.13/0412-Add-support-for-BB-BONE_SERL-01-00A1-CanBus-cape.patch66
-rw-r--r--patches/linux-3.8.13/0413-capes-Add-virtual-capes-serving-as-examples.patch676
-rw-r--r--patches/linux-3.8.13/0414-capes-Add-TowerTech-TT3201-CAN-Bus-Cape-TT3201-001-3.patch175
-rw-r--r--patches/linux-3.8.13/0415-capes-Add-commented-out-example-of-use-of-spi1_cs1.patch28
-rw-r--r--patches/linux-3.8.13/0416-cape-LCD4-Correct-key-active-polarity.patch57
-rw-r--r--patches/linux-3.8.13/0417-capes-lcd3-Correct-button-polarity.patch107
-rw-r--r--patches/linux-3.8.13/0418-cape-Fix-LCD7-keys-polarity.patch157
-rw-r--r--patches/linux-3.8.13/0419-gpio-Introduce-GPIO-OF-helper.patch470
-rw-r--r--patches/linux-3.8.13/0420-capes-ADC-GPIO-helper-capes.patch168
-rw-r--r--patches/linux-3.8.13/0421-capes-RS232-Cape-support-added.patch81
-rw-r--r--patches/linux-3.8.13/0422-uio-uio_pruss-port-to-AM33xx.patch189
-rw-r--r--patches/linux-3.8.13/0423-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch94
-rw-r--r--patches/linux-3.8.13/0424-ARM-dts-AM33xx-PRUSS-support.patch34
-rw-r--r--patches/linux-3.8.13/0425-uio_pruss-add-dt-support-replicape-00A1.patch75
-rw-r--r--patches/linux-3.8.13/0426-pruss-Make-sure-it-works-when-no-child-nodes-are-pre.patch79
-rw-r--r--patches/linux-3.8.13/0427-am33xx-pru-Very-simple-led-cape-via-GPO-of-the-PRU.patch76
-rw-r--r--patches/linux-3.8.13/0428-PRU-remote-proc-wip.patch355
-rw-r--r--patches/linux-3.8.13/0429-Add-sysfs-entry-for-DDR-sync.patch64
-rw-r--r--patches/linux-3.8.13/0430-virtio-ring-Introduce-dma-mapping-for-real-devices.patch227
-rw-r--r--patches/linux-3.8.13/0431-virtio_console-Simplify-virtio_console-for-h-w-devic.patch81
-rw-r--r--patches/linux-3.8.13/0432-rpmsg-Make-the-buffers-number-and-size-configurable.patch59
-rw-r--r--patches/linux-3.8.13/0433-remoteproc-Use-driver-ops-for-allocation-of-virtqueu.patch167
-rw-r--r--patches/linux-3.8.13/0434-rproc-core-Allow-bootup-without-resources.patch40
-rw-r--r--patches/linux-3.8.13/0435-tools-virtio-fix-build-for-3.8.patch87
-rw-r--r--patches/linux-3.8.13/0436-rproc-pru-PRU-remoteproc-updated-to-work-with-virtio.patch2487
-rw-r--r--patches/linux-3.8.13/0437-capes-pru-Update-with-PRU-03-PRU-04.patch547
-rw-r--r--patches/linux-3.8.13/0438-rproc-PRU-Add-downcall-RPC-capability.patch587
-rw-r--r--patches/linux-3.8.13/0439-rproc-pru-Implement-a-software-defined-PWM-channel-s.patch326
-rw-r--r--patches/linux-3.8.13/0440-capes-PRU-PWM-channels-information.patch59
-rw-r--r--patches/linux-3.8.13/0441-drivers-usb-phy-add-a-new-driver-for-usb-part-of-con.patch377
-rw-r--r--patches/linux-3.8.13/0442-drivers-usb-start-using-the-control-module-driver.patch404
-rw-r--r--patches/linux-3.8.13/0443-usb-otg-Add-an-API-to-bind-the-USB-controller-and-PH.patch118
-rw-r--r--patches/linux-3.8.13/0444-usb-otg-utils-add-facilities-in-phy-lib-to-support-m.patch209
-rw-r--r--patches/linux-3.8.13/0445-ARM-OMAP-USB-Add-phy-binding-information.patch371
-rw-r--r--patches/linux-3.8.13/0446-drivers-usb-musb-omap-make-use-of-the-new-PHY-lib-AP.patch72
-rw-r--r--patches/linux-3.8.13/0447-usb-otg-add-device-tree-support-to-otg-library.patch145
-rw-r--r--patches/linux-3.8.13/0448-USB-MUSB-OMAP-get-PHY-by-phandle-for-dt-boot.patch29
-rw-r--r--patches/linux-3.8.13/0449-MUSB-Hack-around-to-make-host-port-to-work.patch234
-rw-r--r--patches/linux-3.8.13/0450-make-sure-we-register-unregister-the-NOP-xceiver-onl.patch46
-rw-r--r--patches/linux-3.8.13/0451-ARM-OMAP-am335x-musb-use-250-for-power.patch42
-rw-r--r--patches/linux-3.8.13/0452-ARM-OMAP2-MUSB-Specify-omap4-has-mailbox.patch42
-rw-r--r--patches/linux-3.8.13/0453-usb-musb-avoid-stopping-the-session-in-host-mode.patch30
-rw-r--r--patches/linux-3.8.13/0454-beaglebone-black-1ghz-hack.patch47
-rw-r--r--patches/linux-3.8.13/0455-ARM-AM33xx-Add-SoC-specific-restart-hook.patch100
-rw-r--r--patches/linux-3.8.13/0456-iio-common-Add-STMicroelectronics-common-library.patch1312
-rw-r--r--patches/linux-3.8.13/0457-iio-accel-Add-STMicroelectronics-accelerometers-driv.patch950
-rw-r--r--patches/linux-3.8.13/0458-iio-gyro-Add-STMicroelectronics-gyroscopes-driver.patch801
-rw-r--r--patches/linux-3.8.13/0459-iio-magnetometer-Add-STMicroelectronics-magnetometer.patch808
-rw-r--r--patches/linux-3.8.13/0460-iio-magn-Add-sensors_supported-in-st_magn_sensors.patch34
-rw-r--r--patches/linux-3.8.13/0461-pwm-pca9685-skeleton-i2c-client-driver-for-PCA9685-1.patch223
-rw-r--r--patches/linux-3.8.13/0462-Invensense-MPU6050-Device-Driver.patch1553
-rw-r--r--patches/linux-3.8.13/0463-iio-imu-inv_mpu6050-depends-on-IIO_BUFFER.patch31
-rw-r--r--patches/linux-3.8.13/0464-using-kfifo_in_spinlocked-instead-of-separate-code.patch26
-rw-r--r--patches/linux-3.8.13/0465-W1-w1-gpio-switch-to-using-dev_pm_ops.patch66
-rw-r--r--patches/linux-3.8.13/0466-W1-w1-gpio-guard-DT-IDs-with-CONFIG_OF.patch49
-rw-r--r--patches/linux-3.8.13/0467-W1-w1-gpio-rework-handling-of-platform-data.patch122
-rw-r--r--patches/linux-3.8.13/0468-W1-w1-gpio-switch-to-using-managed-resources-devm.patch86
-rw-r--r--patches/linux-3.8.13/0469-ARM-OMAP-Clear-GPMC-bits-when-applying-new-setting.patch54
-rw-r--r--patches/linux-3.8.13/0470-ARM-omap2-gpmc-Mark-local-scoped-functions-static.patch107
-rw-r--r--patches/linux-3.8.13/0471-ARM-omap2-gpmc-Remove-unused-gpmc_round_ns_to_ticks-.patch33
-rw-r--r--patches/linux-3.8.13/0472-ARM-omap2-gpmc-Fix-gpmc_cs_reserved-return-value.patch37
-rw-r--r--patches/linux-3.8.13/0473-ARM-omap2-gpmc-nand-Print-something-useful-on-CS-req.patch29
-rw-r--r--patches/linux-3.8.13/0474-ARM-omap2-gpmc-onenand-Print-something-useful-on-CS-.patch29
-rw-r--r--patches/linux-3.8.13/0475-ARM-omap2-gpmc-onenand-Replace-pr_err-with-dev_err.patch46
-rw-r--r--patches/linux-3.8.13/0476-ARM-omap2-gpmc-onenand-Replace-printk-KERN_ERR-with-.patch28
-rw-r--r--patches/linux-3.8.13/0477-ARM-omap2-gpmc-Remove-redundant-chip-select-out-of-r.patch44
-rw-r--r--patches/linux-3.8.13/0478-ARM-OMAP2-Simplify-code-configuring-ONENAND-devices.patch103
-rw-r--r--patches/linux-3.8.13/0479-ARM-OMAP2-Add-variable-to-store-number-of-GPMC-waitp.patch285
-rw-r--r--patches/linux-3.8.13/0480-ARM-OMAP2-Add-structure-for-storing-GPMC-settings.patch323
-rw-r--r--patches/linux-3.8.13/0481-ARM-OMAP2-Add-function-for-configuring-GPMC-settings.patch176
-rw-r--r--patches/linux-3.8.13/0482-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch133
-rw-r--r--patches/linux-3.8.13/0483-ARM-OMAP2-Convert-NAND-to-use-gpmc_cs_program_settin.patch84
-rw-r--r--patches/linux-3.8.13/0484-ARM-OMAP2-Convert-SMC91x-to-use-gpmc_cs_program_sett.patch81
-rw-r--r--patches/linux-3.8.13/0485-ARM-OMAP2-Convert-TUSB-to-use-gpmc_cs_program_settin.patch98
-rw-r--r--patches/linux-3.8.13/0486-ARM-OMAP2-Don-t-configure-of-chip-select-options-in-.patch129
-rw-r--r--patches/linux-3.8.13/0487-ARM-OMAP2-Add-function-to-read-GPMC-settings-from-de.patch196
-rw-r--r--patches/linux-3.8.13/0488-ARM-OMAP2-Add-additional-GPMC-timing-parameters.patch238
-rw-r--r--patches/linux-3.8.13/0489-ARM-OMAP2-Add-device-tree-support-for-NOR-flash.patch273
-rw-r--r--patches/linux-3.8.13/0490-ARM-OMAP2-Convert-NAND-to-retrieve-GPMC-settings-fro.patch42
-rw-r--r--patches/linux-3.8.13/0491-ARM-OMAP2-Convert-ONENAND-to-retrieve-GPMC-settings-.patch122
-rw-r--r--patches/linux-3.8.13/0492-ARM-OMAP2-Detect-incorrectly-aligned-GPMC-base-addre.patch76
-rw-r--r--patches/linux-3.8.13/0493-ARM-OMAP2-Remove-unnecesssary-GPMC-definitions-and-v.patch52
-rw-r--r--patches/linux-3.8.13/0494-ARM-OMAP2-Allow-GPMC-probe-to-complete-even-if-CS-ma.patch79
-rw-r--r--patches/linux-3.8.13/0495-ARM-OMAP2-return-ENODEV-if-GPMC-child-device-creatio.patch34
-rw-r--r--patches/linux-3.8.13/0496-ARM-OMAP2-rename-gpmc_probe_nor_child-to-gpmc_probe_.patch52
-rw-r--r--patches/linux-3.8.13/0497-ARM-OMAP2-Add-GPMC-DT-support-for-Ethernet-child-nod.patch142
-rw-r--r--patches/linux-3.8.13/0498-mtd-omap-nand-pass-device_node-in-platform-data.patch56
-rw-r--r--patches/linux-3.8.13/0499-ARM-OMAP-gpmc-nand-drop-__init-annotation.patch39
-rw-r--r--patches/linux-3.8.13/0500-ARM-OMAP-gpmc-enable-hwecc-for-AM33xx-SoCs.patch41
-rw-r--r--patches/linux-3.8.13/0501-ARM-OMAP-gpmc-don-t-create-devices-from-initcall-on-.patch32
-rw-r--r--patches/linux-3.8.13/0502-ARM-OMAP2-gpmc-onenand-drop-__init-annotation.patch26
-rw-r--r--patches/linux-3.8.13/0503-gpmc-Add-missing-gpmc-includes.patch22
-rw-r--r--patches/linux-3.8.13/0504-mtd-omap-onenand-pass-device_node-in-platform-data.patch54
-rw-r--r--patches/linux-3.8.13/0505-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch44
-rw-r--r--patches/linux-3.8.13/0506-omap-gpmc-Various-driver-fixes.patch203
-rw-r--r--patches/linux-3.8.13/0507-gpmc-Add-DT-node-for-gpmc-on-am33xx.patch35
-rw-r--r--patches/linux-3.8.13/0508-CHROMIUM-Input-atmel_mxt_ts-refactor-i2c-error-handl.patch163
-rw-r--r--patches/linux-3.8.13/0509-CHROMIUM-Input-atmel_mxt_ts-register-input-device-be.patch109
-rw-r--r--patches/linux-3.8.13/0510-CHROMIUM-Input-atmel_mxt_ts-refactor-input-device-cr.patch157
-rw-r--r--patches/linux-3.8.13/0511-CHROMIUM-Input-atmel_mxt_ts-handle-bootloader-mode-a.patch180
-rw-r--r--patches/linux-3.8.13/0512-CHROMIUM-Input-atmel_mxt_ts-handle-errors-during-fw-.patch74
-rw-r--r--patches/linux-3.8.13/0513-CHROMIUM-Input-atmel_mxt_ts-destroy-state-before-fw-.patch51
-rw-r--r--patches/linux-3.8.13/0514-CHROMIUM-Input-atmel_mxt_ts-refactor-bootloader-entr.patch239
-rw-r--r--patches/linux-3.8.13/0515-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-assert-in-m.patch170
-rw-r--r--patches/linux-3.8.13/0516-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-after-bootl.patch84
-rw-r--r--patches/linux-3.8.13/0517-CHROMIUM-Input-atmel_mxt_ts-change-MXT_BOOT_LOW-to-0.patch37
-rw-r--r--patches/linux-3.8.13/0518-CHROMIUM-Input-atmel_mxt_ts-Increase-FWRESET_TIME.patch31
-rw-r--r--patches/linux-3.8.13/0519-CHROMIUM-Input-atmel_mxt_ts-add-calibrate-sysfs-entr.patch80
-rw-r--r--patches/linux-3.8.13/0520-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch82
-rw-r--r--patches/linux-3.8.13/0521-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch103
-rw-r--r--patches/linux-3.8.13/0522-CHROMIUM-Input-atmel_mxt_ts-verify-info-block-checks.patch111
-rw-r--r--patches/linux-3.8.13/0523-CHROMIUM-Input-atmel_mxt_tx-add-matrix_size-sysfs-en.patch63
-rw-r--r--patches/linux-3.8.13/0524-CHROMIUM-Input-atmel_mxt_ts-define-helper-functions-.patch117
-rw-r--r--patches/linux-3.8.13/0525-CHROMIUM-Input-atmel_mxt_ts-add-debugfs-infrastructu.patch127
-rw-r--r--patches/linux-3.8.13/0526-CHROMIUM-Input-atmel_mxt_ts-add-deltas-and-refs-debu.patch338
-rw-r--r--patches/linux-3.8.13/0527-CHROMIUM-Input-atmel_mxt_ts-add-device-id-for-touchp.patch180
-rw-r--r--patches/linux-3.8.13/0528-CHROMIUM-Input-atmel_mxt_ts-Read-resolution-from-dev.patch130
-rw-r--r--patches/linux-3.8.13/0529-CHROMIUM-Input-atmel_mxt_ts-Report-TOUCH-MAJOR-in-te.patch147
-rw-r--r--patches/linux-3.8.13/0530-CHROMIUM-Input-atmel_mxt_ts-add-new-object-types.patch78
-rw-r--r--patches/linux-3.8.13/0531-CHROMIUM-INPUT-atmel_mxt_ts-Increase-the-wait-times-.patch48
-rw-r--r--patches/linux-3.8.13/0532-CHROMIUM-Input-atmel_mxt_ts-dump-mxt_read-write_reg.patch91
-rw-r--r--patches/linux-3.8.13/0533-CHROMIUM-Input-atmel_mxt_ts-take-an-instance-for-mxt.patch59
-rw-r--r--patches/linux-3.8.13/0534-CHROMIUM-Input-atmel_mxt_ts-allow-writing-to-object-.patch108
-rw-r--r--patches/linux-3.8.13/0535-CHROMIUM-Input-atmel_mxt_ts-add-backupnv-sysfs-entry.patch72
-rw-r--r--patches/linux-3.8.13/0536-CHROMIUM-Input-atmel_mxt_ts-read-num-messages-then-a.patch237
-rw-r--r--patches/linux-3.8.13/0537-CHROMIUM-Input-atmel_mxt_ts-remove-mxt_make_highchg.patch104
-rw-r--r--patches/linux-3.8.13/0538-CHROMIUM-Input-atmel_mxt_ts-Remove-matrix-size-updat.patch64
-rw-r--r--patches/linux-3.8.13/0539-CHROMIUM-Input-atmel_mxt_ts-parse-vector-field-of-da.patch69
-rw-r--r--patches/linux-3.8.13/0540-CHROMIUM-Input-atmel_mxt_ts-Add-IDLE-DEEP-SLEEP-mode.patch226
-rw-r--r--patches/linux-3.8.13/0541-CHROMIUM-Input-atmel_mxt_ts-Move-object-from-sysfs-t.patch372
-rw-r--r--patches/linux-3.8.13/0542-CHROMIUM-Input-atmel_mxt_ts-Set-default-irqflags-whe.patch55
-rw-r--r--patches/linux-3.8.13/0543-CHROMIUM-Input-atmel_mxt_ts-Support-the-case-with-no.patch110
-rw-r--r--patches/linux-3.8.13/0544-CHROMIUM-Input-atmel_mxt_ts-Wait-on-auto-calibration.patch117
-rw-r--r--patches/linux-3.8.13/0545-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch182
-rw-r--r--patches/linux-3.8.13/0546-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch137
-rw-r--r--patches/linux-3.8.13/0547-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-for-writ.patch408
-rw-r--r--patches/linux-3.8.13/0548-CHROMIUM-Input-atmel_mxt_ts-make-mxt_initialize-asyn.patch223
-rw-r--r--patches/linux-3.8.13/0549-CHROMIUM-Input-atmel_mxt_ts-move-backup_nv-to-handle.patch62
-rw-r--r--patches/linux-3.8.13/0550-CHROMIUM-Input-atmel_mxt_ts-Add-defines-for-T9-Touch.patch81
-rw-r--r--patches/linux-3.8.13/0551-CHROMIUM-Input-atmel_mxt_ts-disable-reporting-on-sto.patch48
-rw-r--r--patches/linux-3.8.13/0552-CHROMIUM-Input-atmel_mxt_ts-Suppress-handle-messages.patch112
-rw-r--r--patches/linux-3.8.13/0553-CHROMIUM-Input-atmel_mxt_ts-save-and-restore-t9_ctrl.patch70
-rw-r--r--patches/linux-3.8.13/0554-CHROMIUM-Input-atmel_mxt_ts-enable-RPTEN-if-can-wake.patch95
-rw-r--r--patches/linux-3.8.13/0555-CHROMIUM-Input-atmel_mxt_ts-release-all-fingers-on-r.patch126
-rw-r--r--patches/linux-3.8.13/0556-CHROMIUM-Input-atmel_mxt_ts-make-suspend-power-acqui.patch167
-rw-r--r--patches/linux-3.8.13/0557-CHROMIUM-Input-atmel_mxt_ts-recalibrate-on-system-re.patch80
-rw-r--r--patches/linux-3.8.13/0558-CHROMIUM-Input-atmel_mxt_ts-Use-correct-max-touch_ma.patch59
-rw-r--r--patches/linux-3.8.13/0559-CHROMIUM-Input-atmel_mxt_ts-Add-support-for-T65-Lens.patch70
-rw-r--r--patches/linux-3.8.13/0560-CHROMIUM-Input-atmel_mxt_ts-On-Tpads-enable-T42-disa.patch118
-rw-r--r--patches/linux-3.8.13/0561-CHROMIUM-Input-atmel_mxt_ts-Set-power-wakeup-to-disa.patch39
-rw-r--r--patches/linux-3.8.13/0562-CHROMIUM-Input-atmel_mxt_ts-mxt_stop-on-lid-close.patch121
-rw-r--r--patches/linux-3.8.13/0563-CHROMIUM-Input-atmel_mxt_ts-Disable-T9-on-mxt_stop.patch49
-rw-r--r--patches/linux-3.8.13/0564-CHROMIUM-Input-atmel_mxt_ts-Set-T9-in-mxt_resume-bas.patch73
-rw-r--r--patches/linux-3.8.13/0565-video-ssd1307fb-Add-support-for-SSD1306-OLED-control.patch431
-rw-r--r--patches/linux-3.8.13/0566-ssd1307fb-Rework-the-communication-functions.patch111
-rw-r--r--patches/linux-3.8.13/0567-ssd1307fb-Speed-up-the-communication-with-the-contro.patch53
-rw-r--r--patches/linux-3.8.13/0568-ssd1307fb-Make-use-of-horizontal-addressing-mode.patch105
-rw-r--r--patches/linux-3.8.13/0569-SSD1307fb-1Hz-8Hz-defio-updates.patch22
-rw-r--r--patches/linux-3.8.13/0570-ARM-force-march-armv7a-for-thumb2-builds-http-lists..patch23
-rw-r--r--patches/linux-3.8.13/0571-headers_install-Fix-build-failures-on-deep-directory.patch56
-rw-r--r--patches/linux-3.8.13/0572-libtraceevent-Remove-hard-coded-include-to-usr-local.patch33
-rw-r--r--patches/linux-3.8.13/0573-Make-single-.dtb-targets-also-with-DTC_FLAGS.patch21
-rw-r--r--patches/linux-3.8.13/0574-video-Add-generic-HDMI-infoframe-helpers.patch593
-rw-r--r--patches/linux-3.8.13/0575-BeagleBone-Black-TDA998x-Initial-HDMI-Audio-support.patch784
-rw-r--r--patches/linux-3.8.13/0576-Clean-up-some-formating-and-debug-in-Davinci-MCASP-d.patch55
-rw-r--r--patches/linux-3.8.13/0577-tilcdc-Prune-modes-that-can-t-support-audio.patch240
-rw-r--r--patches/linux-3.8.13/0578-Enable-output-of-correct-AVI-Infoframe-type-hdmi.patch24
-rw-r--r--patches/linux-3.8.13/0579-drm-am335x-add-support-for-2048-lines-vertical.patch86
-rw-r--r--patches/linux-3.8.13/0580-drm-tda998x-Adding-extra-CEA-mode-for-1920x1080-24.patch31
-rw-r--r--patches/linux-3.8.13/0581-tilcdc-Remove-superfluous-newlines-from-DBG-messages.patch63
-rw-r--r--patches/linux-3.8.13/0582-tilcdc-1280x1024x60-bw-1920x1080x24-bw.patch43
-rw-r--r--patches/linux-3.8.13/0583-tilcdc-Only-support-Audio-on-50-60-Hz-modes.patch62
-rw-r--r--patches/linux-3.8.13/0584-drm-i2c-nxp-tda998x-fix-EDID-reading-on-TDA19988-dev.patch68
-rw-r--r--patches/linux-3.8.13/0585-tilcdc-Allow-non-audio-modes-when-we-don-t-support-t.patch26
-rw-r--r--patches/linux-3.8.13/0586-drm-i2c-nxp-tda998x-ensure-VIP-output-mux-is-properl.patch39
-rw-r--r--patches/linux-3.8.13/0587-drm-i2c-nxp-tda998x-fix-npix-nline-programming.patch28
-rw-r--r--patches/linux-3.8.13/0588-drm-tilcdc-Clear-bits-of-register-we-re-going-to-set.patch63
-rw-r--r--patches/linux-3.8.13/0589-DRM-tda998x-add-missing-include.patch42
-rw-r--r--patches/linux-3.8.13/0590-drm-i2c-nxp-tda998x-prepare-for-video-input-configur.patch50
-rw-r--r--patches/linux-3.8.13/0591-WIP-of-new-tda998x-patches.patch808
-rw-r--r--patches/linux-3.8.13/0592-tilcdc-Slave-panel-settings-read-from-DT-now.patch221
-rw-r--r--patches/linux-3.8.13/0593-drm-tda998x-Revert-WIP-to-previous-state.patch838
-rw-r--r--patches/linux-3.8.13/0594-tilcdc-More-refined-audio-mode-compatibility-check.patch69
-rw-r--r--patches/linux-3.8.13/0595-drm-tilcdc-Implement-whitelist-blacklist-mode-suppor.patch435
-rw-r--r--patches/linux-3.8.13/0596-boneblack-Remove-default-pinmuxing-for-MMC1.patch43
-rw-r--r--patches/linux-3.8.13/0597-capemgr-Implement-cape-priorities.patch276
-rw-r--r--patches/linux-3.8.13/0598-rstctl-Reset-control-subsystem.patch1049
-rw-r--r--patches/linux-3.8.13/0599-omap_hsmmc-Enable-rstctl-bindings.patch82
-rw-r--r--patches/linux-3.8.13/0600-bone-Add-rstctl-DT-binding-for-beaglebone.patch77
-rw-r--r--patches/linux-3.8.13/0601-bone-eMMC-Add-rstctl-rstctl-DT-bindings.patch64
-rw-r--r--patches/linux-3.8.13/0602-capes-Add-testing-capes-for-rstctl.patch115
-rw-r--r--patches/linux-3.8.13/0603-omap_hsmmc-Bail-out-when-rstctl-error-is-unrecoverab.patch35
-rw-r--r--patches/linux-3.8.13/0604-bone-Put-priorities-in-built-in-capes.patch114
-rw-r--r--patches/linux-3.8.13/0605-bone-common-dtsi-remove-reset-cape.patch30
-rw-r--r--patches/linux-3.8.13/0606-mmc-add-missing-select-RSTCTL-in-MMC_OMAP.patch24
-rw-r--r--patches/linux-3.8.13/0607-soc_camera-QL-mt9l112-camera-driver-for-the-beaglebo.patch1606
-rw-r--r--patches/linux-3.8.13/0608-capes-Add-BB-BONE-CAM3-cape.patch202
-rw-r--r--patches/linux-3.8.13/0609-cssp_camera-Correct-license-identifier.patch24
-rw-r--r--patches/linux-3.8.13/0610-cssp_camera-increase-delays-make-sensor-detection-wo.patch32
-rw-r--r--patches/linux-3.8.13/0611-mt9t112-forward-port-optimizations-from-Angstrom-3.2.patch585
-rw-r--r--patches/linux-3.8.13/0612-cssp_camera-Use-flip-if-available.patch53
-rw-r--r--patches/linux-3.8.13/0613-cssp_camera-Fix-it-for-small-resolutions.patch932
-rw-r--r--patches/linux-3.8.13/0614-cssp_camera-Increase-delay-after-enabling-clocks-to-.patch30
-rw-r--r--patches/linux-3.8.13/0615-Debugging-camera-stuff.patch93
-rw-r--r--patches/linux-3.8.13/0616-cssp_camera-Make-it-work-with-Beaglebone-black.patch112
-rw-r--r--patches/linux-3.8.13/0617-bone-capemgr-Introduce-simple-resource-tracking.patch163
-rw-r--r--patches/linux-3.8.13/0618-capes-Add-resources-to-capes.patch705
-rw-r--r--patches/linux-3.8.13/0619-capes-Update-most-of-the-capes-with-resource-definit.patch1100
-rw-r--r--patches/linux-3.8.13/0620-capes-Update-RS232-CAN-capes-with-resources.patch47
-rw-r--r--patches/linux-3.8.13/0621-capemgr-Add-enable_partno-parameter.patch114
-rw-r--r--patches/linux-3.8.13/0622-cape-GPIOHELP-use-correct-part-number.patch21
-rw-r--r--patches/linux-3.8.13/0623-bbb-Add-a-fall-back-non-audio-HDMI-cape.patch186
-rw-r--r--patches/linux-3.8.13/0624-capes-HDMI-slaves-need-panel-settings.patch57
-rw-r--r--patches/linux-3.8.13/0625-capes-boneblack-HDMI-capes-have-blacklisted-modes.patch65
-rw-r--r--patches/linux-3.8.13/0626-capes-LCD7-Fix-definitions.patch106
-rw-r--r--patches/linux-3.8.13/0627-capes-LCD7-Fix-enter-key-pinmux.patch37
-rw-r--r--patches/linux-3.8.13/0628-Fix-timings-for-LCD3-cape.patch41
-rw-r--r--patches/linux-3.8.13/0629-capes-LCD-capes-updated-with-timing-fixes.patch183
-rw-r--r--patches/linux-3.8.13/0630-Fix-mmc2-being-enabled-when-eMMC-is-disabled.patch22
-rw-r--r--patches/linux-3.8.13/0631-capes-LCD7-fix-vsync-len-off-by-one.patch49
-rw-r--r--patches/linux-3.8.13/0632-LCD-capes-set-default-brightness-to-100.patch106
-rw-r--r--patches/linux-3.8.13/0633-lcd-capes-update-adc-channels.patch50
-rw-r--r--patches/linux-3.8.13/0634-bone-renamed-adafruit-RTC-cape.patch177
-rw-r--r--patches/linux-3.8.13/0635-bone-add-PPS-to-BB-BONE-RTC-cape.patch79
-rw-r--r--patches/linux-3.8.13/0636-firmware-remove-rule-for-cape-bone-adafruit-lcd-00A0.patch21
-rw-r--r--patches/linux-3.8.13/0637-tps65217-Enable-KEY_POWER-press-on-AC-loss-PWR_BUT.patch201
-rw-r--r--patches/linux-3.8.13/0638-dt-bone-common-Add-interrupt-for-PMIC.patch33
-rw-r--r--patches/linux-3.8.13/0639-drivers-pps-clients-pps-gpio.c-convert-to-module_pla.patch44
-rw-r--r--patches/linux-3.8.13/0640-drivers-pps-clients-pps-gpio.c-convert-to-devm_-help.patch88
-rw-r--r--patches/linux-3.8.13/0641-pps-gpio-add-device-tree-binding-and-support.patch126
-rw-r--r--patches/linux-3.8.13/0642-leds-leds-pwm-Convert-to-use-devm_get_pwm.patch84
-rw-r--r--patches/linux-3.8.13/0643-leds-leds-pwm-Preparing-the-driver-for-device-tree-s.patch104
-rw-r--r--patches/linux-3.8.13/0644-leds-leds-pwm-Simplify-cleanup-code.patch35
-rw-r--r--patches/linux-3.8.13/0645-leds-leds-pwm-Add-device-tree-bindings.patch240
-rw-r--r--patches/linux-3.8.13/0646-leds-leds-pwm-Defer-led_pwm_set-if-PWM-can-sleep.patch118
-rw-r--r--patches/linux-3.8.13/0647-leds-pwm-Enable-compilation-on-this-version-of-the-k.patch54
-rw-r--r--patches/linux-3.8.13/0648-capes-Add-bacon-cape.patch247
-rw-r--r--patches/linux-3.8.13/0649-cape-bacon-Cosmetic-change-of-the-adc-helper-name.patch21
-rw-r--r--patches/linux-3.8.13/0650-cape-bacon-educational-edition.patch199
-rw-r--r--patches/linux-3.8.13/0651-capes-bacon-Update-with-new-ADC-driver-method.patch35
-rw-r--r--patches/linux-3.8.13/0652-capes-BACON-Educational-cape-with-free-form-muxing.patch234
-rw-r--r--patches/linux-3.8.13/0653-firmware-add-BeBoPr-cape.patch446
-rw-r--r--patches/linux-3.8.13/0701-Release-distrokit-beaglebone-20130720.patch22
-rw-r--r--patches/linux-3.8.13/series663
655 files changed, 114683 insertions, 0 deletions
diff --git a/patches/linux-3.8.13/0001-Without-MACH_-option-Early-printk-DEBUG_LL.patch b/patches/linux-3.8.13/0001-Without-MACH_-option-Early-printk-DEBUG_LL.patch
new file mode 100644
index 0000000..85222c4
--- /dev/null
+++ b/patches/linux-3.8.13/0001-Without-MACH_-option-Early-printk-DEBUG_LL.patch
@@ -0,0 +1,117 @@
+From: "hvaibhav@ti.com" <hvaibhav@ti.com>
+Date: Fri, 31 Aug 2012 16:47:12 +0000
+Subject: [PATCH] Without MACH_ option Early printk (DEBUG_LL)
+
+On Fri, Aug 31, 2012 at 22:07:37, Hiremath, Vaibhav wrote:
+> On Fri, Aug 31, 2012 at 21:41:22, Tony Lindgren wrote:
+> > * Hiremath, Vaibhav <hvaibhav@ti.com> [120831 09:06]:
+> > > On Fri, Aug 31, 2012 at 21:22:26, Tony Lindgren wrote:
+> > > > * Vaibhav Hiremath <hvaibhav@ti.com> [120831 07:55]:
+> > > > > Hi Russell & Tony,
+> > > > >
+> > > > > AM335X EVM (based on AM33XX device) only supports DT boot mode and
+> > > > > doesn't have CONFIG_MACH_AM335XEVM option defined. Some time back during
+> > > > > baseport submission we had aligned that, we won't create separate EVM
+> > > > > options, killing the board file all-together.
+> > > > >
+> > > > > Having said that, the early printk option (DEBUG_LL) is broken, the
+> > > > > auto-generated file "./include/generated/mach-types.h" still refers to
+> > > > > CONFIG_MACH_AM335XEVM option,
+> > > >
+> > > > The way we're heading is that the DEBUG_LL options will only work for
+> > > > one hardcoded machine where you need to select the uart type and address
+> > > > in Kconfig. Or just patch it in.
+> > > >
+> > > > > #ifdef CONFIG_MACH_AM335XEVM
+> > > > > # ifdef machine_arch_type
+> > > > > # undef machine_arch_type
+> > > > > # define machine_arch_type __machine_arch_type
+> > > > > # else
+> > > > > # define machine_arch_type MACH_TYPE_AM335XEVM
+> > > > > # endif
+> > > > > # define machine_is_am335xevm() (machine_arch_type == MACH_TYPE_AM335XEVM)
+> > > > > #else
+> > > > > # define machine_is_am335xevm() (0)
+> > > > > #endif
+> > > > >
+> > > > >
+> > > > > So I am thinking of changing the config_xxx option to SOC_AM33XX or
+> > > > > ARCH_OMAP2PLUS, something like below,
+> > > > >
+> > > > > am335xevm SOC_AM33XX AM335XEVM 3589
+> > > > >
+> > > > > OR
+> > > > >
+> > > > > am335xevm ARCH_OMAP2PLUS AM335XEVM 3589
+> > > > >
+> > > > >
+> > > > > Can you comment on this? Based on that I will submit the patch.
+> > > >
+> > > > I think that would at minimum break things for autogenerated
+> > > > mach-types.h where if only some other non-am335xevm machine is
+> > > > selected (like omap-generic) things don't get optimized out any
+> > > > longer as they currently do.
+> > > >
+> > >
+> > > Agreed. In that case the first option should work here, right?
+> >
+> > It gets messy if we start mixing mach and soc defines there..
+> >
+> > How about just add a hidden Kconfig option to mach-omap2/Kconfig
+> > that always selects MACH_TYPE_AM335XEVM if SOC_AM33XX is set?
+>
+> Great, this is what I had in my mind but since it is hidden option I thought
+> may not be right thing to do.
+> I was just thinking in the direction that, it should be logical and fine if
+> SOC_AM33XX is used for all AM33xx based machines, isn't it?
+>
+> Anyway, I think we are on same page here, I will add it and submit the patch
+> ASAP.
+>
+> > Or does that require that MACHINE_START is there as well?
+> >
+>
+> I do not think so, they are not related to each other, this option is
+> required only during decompression.
+> I have tested it on BeagleBone and it is working.
+>
+
+Can you please review below patch? If you think its ok, I will send the
+patch -
+
+Thanks,
+Vaibhav
+---
+ arch/arm/mach-omap2/Kconfig | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
+index 41b581f..ce05b87 100644
+--- a/arch/arm/mach-omap2/Kconfig
++++ b/arch/arm/mach-omap2/Kconfig
+@@ -35,6 +35,9 @@ config ARCH_OMAP2
+ default y
+ select CPU_V6
+ select MULTI_IRQ_HANDLER
++ select MACH_AM335XEVM
++ select MACH_AM335XIAEVM
++ select MACH_TAM335X
+ select SOC_HAS_OMAP2_SDRC
+ select COMMON_CLK
+
+@@ -153,6 +156,15 @@ config MACH_OMAP_GENERIC
+ Support for generic TI OMAP2+ boards using Flattened Device Tree.
+ More information at Documentation/devicetree
+
++config MACH_AM335XEVM
++ bool
++
++config MACH_AM335XIAEVM
++ bool
++
++config MACH_TAM335X
++ bool
++
+ config MACH_OMAP2_TUSB6010
+ bool
+ depends on ARCH_OMAP2 && SOC_OMAP2420
diff --git a/patches/linux-3.8.13/0002-ARM-OMAP-Hack-AM33xx-clock-data-to-allow-JTAG-use.patch b/patches/linux-3.8.13/0002-ARM-OMAP-Hack-AM33xx-clock-data-to-allow-JTAG-use.patch
new file mode 100644
index 0000000..691f2c1
--- /dev/null
+++ b/patches/linux-3.8.13/0002-ARM-OMAP-Hack-AM33xx-clock-data-to-allow-JTAG-use.patch
@@ -0,0 +1,25 @@
+From: Matt Porter <mporter@ti.com>
+Date: Mon, 7 Jan 2013 11:55:00 -0500
+Subject: [PATCH] ARM: OMAP: Hack AM33xx clock data to allow JTAG use
+
+The debugss interface clock must remain enabled at init
+in order to prevent an attached JTAG probe from hanging.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/mach-omap2/cclock33xx_data.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
+index ea64ad6..a09d6d7 100644
+--- a/arch/arm/mach-omap2/cclock33xx_data.c
++++ b/arch/arm/mach-omap2/cclock33xx_data.c
+@@ -428,7 +428,7 @@ DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null);
+ * - usbotg_fck (its additional clock and not really a modulemode)
+ * - ieee5000
+ */
+-DEFINE_CLK_GATE(debugss_ick, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0,
++DEFINE_CLK_GATE(debugss_ick, "dpll_core_m4_ck", &dpll_core_m4_ck, ENABLE_ON_INIT,
+ AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
+ 0x0, NULL);
+
diff --git a/patches/linux-3.8.13/0003-video-st7735fb-add-st7735-framebuffer-driver.patch b/patches/linux-3.8.13/0003-video-st7735fb-add-st7735-framebuffer-driver.patch
new file mode 100644
index 0000000..b707989
--- /dev/null
+++ b/patches/linux-3.8.13/0003-video-st7735fb-add-st7735-framebuffer-driver.patch
@@ -0,0 +1,799 @@
+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 902b1b1..2e000ea 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.
+ ak Asahi Kasei Corp.
+ amcc Applied Micro Circuits Corporation (APM, formally AMCC)
+@@ -48,6 +49,7 @@ schindler Schindler
+ sil Silicon Image
+ simtek
+ sirf SiRF Technology, Inc.
++sitronix Sitronix Technology Corp.
+ snps Synopsys, Inc.
+ st STMicroelectronics
+ stericsson ST-Ericsson
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index e7068c5..b532f02 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2419,6 +2419,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 768a137..58dbeaf 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.8.13/0004-dmaengine-add-helper-function-to-request-a-slave-DMA.patch b/patches/linux-3.8.13/0004-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
new file mode 100644
index 0000000..3368d21
--- /dev/null
+++ b/patches/linux-3.8.13/0004-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
@@ -0,0 +1,93 @@
+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.8.13/0005-of-Add-generic-device-tree-DMA-helpers.patch b/patches/linux-3.8.13/0005-of-Add-generic-device-tree-DMA-helpers.patch
new file mode 100644
index 0000000..71a2fc0
--- /dev/null
+++ b/patches/linux-3.8.13/0005-of-Add-generic-device-tree-DMA-helpers.patch
@@ -0,0 +1,532 @@
+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.8.13/0006-of-dma-fix-build-break-for-CONFIG_OF.patch b/patches/linux-3.8.13/0006-of-dma-fix-build-break-for-CONFIG_OF.patch
new file mode 100644
index 0000000..04d864c
--- /dev/null
+++ b/patches/linux-3.8.13/0006-of-dma-fix-build-break-for-CONFIG_OF.patch
@@ -0,0 +1,53 @@
+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.8.13/0007-of-dma-fix-typos-in-generic-dma-binding-definition.patch b/patches/linux-3.8.13/0007-of-dma-fix-typos-in-generic-dma-binding-definition.patch
new file mode 100644
index 0000000..bfbfad4
--- /dev/null
+++ b/patches/linux-3.8.13/0007-of-dma-fix-typos-in-generic-dma-binding-definition.patch
@@ -0,0 +1,68 @@
+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.8.13/0008-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch b/patches/linux-3.8.13/0008-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
new file mode 100644
index 0000000..52ab593
--- /dev/null
+++ b/patches/linux-3.8.13/0008-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
@@ -0,0 +1,23 @@
+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.8.13/0009-dmaengine-edma-fix-slave-config-dependency-on-direct.patch b/patches/linux-3.8.13/0009-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
new file mode 100644
index 0000000..e0ff593
--- /dev/null
+++ b/patches/linux-3.8.13/0009-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
@@ -0,0 +1,143 @@
+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 f424298..06ea4b8 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.8.13/0010-dmaengine-add-dma_get_channel_caps.patch b/patches/linux-3.8.13/0010-dmaengine-add-dma_get_channel_caps.patch
new file mode 100644
index 0000000..53f84d4
--- /dev/null
+++ b/patches/linux-3.8.13/0010-dmaengine-add-dma_get_channel_caps.patch
@@ -0,0 +1,96 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 18 Oct 2012 21:07:28 -0400
+Subject: [PATCH] dmaengine: add dma_get_channel_caps()
+
+Add a dmaengine API to retrieve per channel capabilities.
+Currently, only channel ops and SG segment limitations are
+implemented caps.
+
+The API is optionally implemented by drivers and when
+unimplemented will return a NULL pointer. It is intended
+to be executed after a channel has been requested and, if
+the channel is intended to be used with slave SG transfers,
+then it may only be called after dmaengine_slave_config()
+has executed. The slave driver provides parameters such as
+burst size and address width which may be necessary for
+the dmaengine driver to use in order to properly return SG
+segment limit caps.
+
+Suggested-by: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ include/linux/dmaengine.h | 40 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index c88f302..9fd0c5b 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -371,6 +371,26 @@ struct dma_slave_config {
+ unsigned int slave_id;
+ };
+
++/* struct dmaengine_chan_caps - expose capability of a channel
++ * Note: each channel can have same or different capabilities
++ *
++ * This primarily classifies capabilities into
++ * a) APIs/ops supported
++ * b) channel physical capabilities
++ *
++ * @cap_mask: api/ops capability (DMA_INTERRUPT and DMA_PRIVATE
++ * are invalid api/ops and will never be set)
++ * @seg_nr: maximum number of SG segments supported on a SG/SLAVE
++ * channel (0 for no maximum or not a SG/SLAVE channel)
++ * @seg_len: maximum length of SG segments supported on a SG/SLAVE
++ * channel (0 for no maximum or not a SG/SLAVE channel)
++ */
++struct dmaengine_chan_caps {
++ dma_cap_mask_t cap_mask;
++ int seg_nr;
++ int seg_len;
++};
++
+ static inline const char *dma_chan_name(struct dma_chan *chan)
+ {
+ return dev_name(&chan->dev->device);
+@@ -534,6 +554,7 @@ struct dma_tx_state {
+ * struct with auxiliary transfer status information, otherwise the call
+ * will just return a simple status code
+ * @device_issue_pending: push pending transactions to hardware
++ * @device_channel_caps: return the channel capabilities
+ */
+ struct dma_device {
+
+@@ -602,6 +623,8 @@ struct dma_device {
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate);
+ void (*device_issue_pending)(struct dma_chan *chan);
++ struct dmaengine_chan_caps *(*device_channel_caps)(
++ struct dma_chan *chan, enum dma_transfer_direction direction);
+ };
+
+ static inline int dmaengine_device_control(struct dma_chan *chan,
+@@ -969,6 +992,23 @@ dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used,
+ }
+ }
+
++/**
++ * dma_get_channel_caps - flush pending transactions to HW
++ * @chan: target DMA channel
++ * @dir: direction of transfer
++ *
++ * Get the channel-specific capabilities. If the dmaengine
++ * driver does not implement per channel capbilities then
++ * NULL is returned.
++ */
++static inline struct dmaengine_chan_caps
++*dma_get_channel_caps(struct dma_chan *chan, enum dma_transfer_direction dir)
++{
++ if (chan->device->device_channel_caps)
++ return chan->device->device_channel_caps(chan, dir);
++ return NULL;
++}
++
+ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
+ #ifdef CONFIG_DMA_ENGINE
+ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
diff --git a/patches/linux-3.8.13/0011-dma-edma-add-device_channel_caps-support.patch b/patches/linux-3.8.13/0011-dma-edma-add-device_channel_caps-support.patch
new file mode 100644
index 0000000..505ac29
--- /dev/null
+++ b/patches/linux-3.8.13/0011-dma-edma-add-device_channel_caps-support.patch
@@ -0,0 +1,81 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 18 Oct 2012 21:08:59 -0400
+Subject: [PATCH] dma: edma: add device_channel_caps() support
+
+Implement device_channel_caps().
+
+EDMA has a finite set of PaRAM slots available for linking
+a multi-segment SG transfer. In order to prevent any one
+channel from consuming all PaRAM slots to fulfill a large SG
+transfer, the driver reports a static per-channel max number
+of SG segments it will handle.
+
+The maximum size of SG segment is limited by the slave config
+maxburst and addr_width for the channel in question. These values
+are used from the current channel config to calculate and return
+the max segment length cap.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/dma/edma.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index 06ea4b8..023c8f2 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -70,6 +70,7 @@ struct edma_chan {
+ bool alloced;
+ int slot[EDMA_MAX_SLOTS];
+ struct dma_slave_config cfg;
++ struct dmaengine_chan_caps caps;
+ };
+
+ struct edma_cc {
+@@ -462,6 +463,28 @@ static void edma_issue_pending(struct dma_chan *chan)
+ spin_unlock_irqrestore(&echan->vchan.lock, flags);
+ }
+
++static struct dmaengine_chan_caps
++*edma_get_channel_caps(struct dma_chan *chan, enum dma_transfer_direction dir)
++{
++ struct edma_chan *echan;
++ enum dma_slave_buswidth width = 0;
++ u32 burst = 0;
++
++ if (chan) {
++ echan = to_edma_chan(chan);
++ if (dir == DMA_MEM_TO_DEV) {
++ width = echan->cfg.dst_addr_width;
++ burst = echan->cfg.dst_maxburst;
++ } else if (dir == DMA_DEV_TO_MEM) {
++ width = echan->cfg.src_addr_width;
++ burst = echan->cfg.src_maxburst;
++ }
++ echan->caps.seg_len = (SZ_64K - 1) * width * burst;
++ return &echan->caps;
++ }
++ return NULL;
++}
++
+ static size_t edma_desc_size(struct edma_desc *edesc)
+ {
+ int i;
+@@ -521,6 +544,9 @@ static void __init edma_chan_init(struct edma_cc *ecc,
+ echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i);
+ echan->ecc = ecc;
+ echan->vchan.desc_free = edma_desc_free;
++ dma_cap_set(DMA_SLAVE, echan->caps.cap_mask);
++ dma_cap_set(DMA_SG, echan->caps.cap_mask);
++ echan->caps.seg_nr = MAX_NR_SG;
+
+ vchan_init(&echan->vchan, dma);
+
+@@ -537,6 +563,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
+ dma->device_alloc_chan_resources = edma_alloc_chan_resources;
+ dma->device_free_chan_resources = edma_free_chan_resources;
+ dma->device_issue_pending = edma_issue_pending;
++ dma->device_channel_caps = edma_get_channel_caps;
+ dma->device_tx_status = edma_tx_status;
+ dma->device_control = edma_control;
+ dma->dev = dev;
diff --git a/patches/linux-3.8.13/0012-mmc-davinci-get-SG-segment-limits-with-dma_get_chann.patch b/patches/linux-3.8.13/0012-mmc-davinci-get-SG-segment-limits-with-dma_get_chann.patch
new file mode 100644
index 0000000..368a583
--- /dev/null
+++ b/patches/linux-3.8.13/0012-mmc-davinci-get-SG-segment-limits-with-dma_get_chann.patch
@@ -0,0 +1,150 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 18 Oct 2012 21:10:47 -0400
+Subject: [PATCH] mmc: davinci: get SG segment limits with
+ dma_get_channel_caps()
+
+Replace the hardcoded values used to set max_segs/max_seg_size with
+a dma_get_channel_caps() query to the dmaengine driver.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/mmc/host/davinci_mmc.c | 66 +++++++++--------------------
+ include/linux/platform_data/mmc-davinci.h | 3 --
+ 2 files changed, 21 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
+index 2063677..17e186d 100644
+--- a/drivers/mmc/host/davinci_mmc.c
++++ b/drivers/mmc/host/davinci_mmc.c
+@@ -144,18 +144,6 @@
+ /* MMCSD Init clock in Hz in opendrain mode */
+ #define MMCSD_INIT_CLOCK 200000
+
+-/*
+- * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units,
+- * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only
+- * for drivers with max_segs == 1, making the segments bigger (64KB)
+- * than the page or two that's otherwise typical. nr_sg (passed from
+- * platform data) == 16 gives at least the same throughput boost, using
+- * EDMA transfer linkage instead of spending CPU time copying pages.
+- */
+-#define MAX_CCNT ((1 << 16) - 1)
+-
+-#define MAX_NR_SG 16
+-
+ static unsigned rw_threshold = 32;
+ module_param(rw_threshold, uint, S_IRUGO);
+ MODULE_PARM_DESC(rw_threshold,
+@@ -216,8 +204,6 @@ struct mmc_davinci_host {
+ u8 version;
+ /* for ns in one cycle calculation */
+ unsigned ns_in_one_cycle;
+- /* Number of sg segments */
+- u8 nr_sg;
+ #ifdef CONFIG_CPU_FREQ
+ struct notifier_block freq_transition;
+ #endif
+@@ -421,16 +407,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
+ int ret = 0;
+
+ if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
+- struct dma_slave_config dma_tx_conf = {
+- .direction = DMA_MEM_TO_DEV,
+- .dst_addr = host->mem_res->start + DAVINCI_MMCDXR,
+- .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+- .dst_maxburst =
+- rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+- };
+ chan = host->dma_tx;
+- dmaengine_slave_config(host->dma_tx, &dma_tx_conf);
+-
+ desc = dmaengine_prep_slave_sg(host->dma_tx,
+ data->sg,
+ host->sg_len,
+@@ -443,16 +420,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
+ goto out;
+ }
+ } else {
+- struct dma_slave_config dma_rx_conf = {
+- .direction = DMA_DEV_TO_MEM,
+- .src_addr = host->mem_res->start + DAVINCI_MMCDRR,
+- .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+- .src_maxburst =
+- rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+- };
+ chan = host->dma_rx;
+- dmaengine_slave_config(host->dma_rx, &dma_rx_conf);
+-
+ desc = dmaengine_prep_slave_sg(host->dma_rx,
+ data->sg,
+ host->sg_len,
+@@ -1165,6 +1133,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
+ struct resource *r, *mem = NULL;
+ int ret = 0, irq = 0;
+ size_t mem_size;
++ struct dmaengine_chan_caps *dma_chan_caps;
+
+ /* REVISIT: when we're fully converted, fail if pdata is NULL */
+
+@@ -1214,12 +1183,6 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
+
+ init_mmcsd_host(host);
+
+- if (pdata->nr_sg)
+- host->nr_sg = pdata->nr_sg - 1;
+-
+- if (host->nr_sg > MAX_NR_SG || !host->nr_sg)
+- host->nr_sg = MAX_NR_SG;
+-
+ host->use_dma = use_dma;
+ host->mmc_irq = irq;
+ host->sdio_irq = platform_get_irq(pdev, 1);
+@@ -1248,14 +1211,27 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
+ mmc->caps |= pdata->caps;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+- /* With no iommu coalescing pages, each phys_seg is a hw_seg.
+- * Each hw_seg uses one EDMA parameter RAM slot, always one
+- * channel and then usually some linked slots.
+- */
+- mmc->max_segs = MAX_NR_SG;
++ {
++ struct dma_slave_config dma_txrx_conf = {
++ .src_addr = host->mem_res->start + DAVINCI_MMCDRR,
++ .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
++ .src_maxburst =
++ rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
++ .dst_addr = host->mem_res->start + DAVINCI_MMCDXR,
++ .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
++ .dst_maxburst =
++ rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
++ };
++ dmaengine_slave_config(host->dma_tx, &dma_txrx_conf);
++ dmaengine_slave_config(host->dma_rx, &dma_txrx_conf);
++ }
+
+- /* EDMA limit per hw segment (one or two MBytes) */
+- mmc->max_seg_size = MAX_CCNT * rw_threshold;
++ /* Just check one channel for the DMA SG limits */
++ dma_chan_caps = dma_get_channel_caps(host->dma_tx, DMA_MEM_TO_DEV);
++ if (dma_chan_caps) {
++ mmc->max_segs = dma_chan_caps->seg_nr;
++ mmc->max_seg_size = dma_chan_caps->seg_len;
++ }
+
+ /* MMC/SD controller limits for multiblock requests */
+ mmc->max_blk_size = 4095; /* BLEN is 12 bits */
+diff --git a/include/linux/platform_data/mmc-davinci.h b/include/linux/platform_data/mmc-davinci.h
+index 5ba6b22..6910209 100644
+--- a/include/linux/platform_data/mmc-davinci.h
++++ b/include/linux/platform_data/mmc-davinci.h
+@@ -25,9 +25,6 @@ struct davinci_mmc_config {
+
+ /* Version of the MMC/SD controller */
+ u8 version;
+-
+- /* Number of sg segments */
+- u8 nr_sg;
+ };
+ void davinci_setup_mmc(int module, struct davinci_mmc_config *config);
+
diff --git a/patches/linux-3.8.13/0013-ARM-davinci-move-private-EDMA-API-to-arm-common.patch b/patches/linux-3.8.13/0013-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
new file mode 100644
index 0000000..6c58818
--- /dev/null
+++ b/patches/linux-3.8.13/0013-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
@@ -0,0 +1,4037 @@
+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 and enables it to build on 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 | 1591 +++++++++++++++++++++++++++
+ 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 | 1591 ---------------------------
+ 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 | 182 +++
+ 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, 1802 insertions(+), 1878 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 67874b8..7637d31 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -932,6 +932,7 @@ config ARCH_DAVINCI
+ select GENERIC_IRQ_CHIP
+ select HAVE_IDE
+ select NEED_MACH_GPIO_H
++ select TI_PRIV_EDMA
+ select USE_OF
+ select ZONE_DMA
+ help
+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..36a0676
+--- /dev/null
++++ b/arch/arm/common/edma.c
+@@ -0,0 +1,1591 @@
++/*
++ * 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 (!edma_cc[ctlr])
++ return -EINVAL;
++
++ 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 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 fb5c1aa..493a36b 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 773ab07..ba37760 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..3bdf9f7 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), /* MMCRXEVT */
+ .flags = IORESOURCE_DMA,
+ }, {
+- .start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCTXEVT),
++ .start = EDMA_CTLR_CHAN(0, 27), /* MMCTXEVT */
+ .flags = IORESOURCE_DMA,
+ },
+ };
+diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
+index b49c3b7..53998d8 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 6c39805..9b41d33 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 11c79a3..a08910e 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 ac7b431..6d52a32 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 45b7c71..0000000
+--- a/arch/arm/mach-davinci/dma.c
++++ /dev/null
+@@ -1,1591 +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 (!edma_cc[ctlr])
+- return -EINVAL;
+-
+- 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 700d311..9d77f9b 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 665870d..0b81d6c 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 023c8f2..e57cce3 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 17e186d..d1efacc 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..2344ea2
+--- /dev/null
++++ b/include/linux/platform_data/edma.h
+@@ -0,0 +1,182 @@
++/*
++ * TI EDMA definitions
++ *
++ * Copyright (C) 2006-2013 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 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 d55e647..591f547 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 afab81f..9bdd71b 100644
+--- a/sound/soc/davinci/davinci-pcm.c
++++ b/sound/soc/davinci/davinci-pcm.c
+@@ -17,6 +17,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/kernel.h>
+ #include <linux/genalloc.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 b6ef703..fbb710c 100644
+--- a/sound/soc/davinci/davinci-pcm.h
++++ b/sound/soc/davinci/davinci-pcm.h
+@@ -14,7 +14,7 @@
+
+ #include <linux/genalloc.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..074fc5d 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, /* MCBSP_TX */
++ .rx_dma_ch = 3, /* MCBSP_RX */
+ };
+
+ static struct platform_device *sffsdr_snd_device;
diff --git a/patches/linux-3.8.13/0014-ARM-edma-remove-unused-transfer-controller-handlers.patch b/patches/linux-3.8.13/0014-ARM-edma-remove-unused-transfer-controller-handlers.patch
new file mode 100644
index 0000000..0b07488
--- /dev/null
+++ b/patches/linux-3.8.13/0014-ARM-edma-remove-unused-transfer-controller-handlers.patch
@@ -0,0 +1,68 @@
+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 36a0676..3580eca 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)
+@@ -1541,23 +1521,6 @@ static int 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.8.13/0015-ARM-edma-add-AM33XX-support-to-the-private-EDMA-API.patch b/patches/linux-3.8.13/0015-ARM-edma-add-AM33XX-support-to-the-private-EDMA-API.patch
new file mode 100644
index 0000000..fc41be5
--- /dev/null
+++ b/patches/linux-3.8.13/0015-ARM-edma-add-AM33XX-support-to-the-private-EDMA-API.patch
@@ -0,0 +1,400 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 6 Sep 2012 17:40:42 -0400
+Subject: [PATCH] ARM: edma: add AM33XX support to the private EDMA API
+
+Adds support for parsing the TI EDMA DT data into the required
+EDMA private API platform data. Enables runtime PM support to
+initialize the EDMA hwmod. Adds AM33XX EMDA crossbar event mux
+support.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 311 ++++++++++++++++++++++++++++++++++--
+ include/linux/platform_data/edma.h | 1 +
+ 2 files changed, 303 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index 3580eca..beeb1d2 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>
+
+@@ -1369,31 +1376,291 @@ 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_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;
++ const 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 -ENOMEM;
++
++ 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 = readl((void *)((u32)xbar + offset));
++ mux &= ~(0xff << shift);
++ mux |= xbar_chans[i][0] << shift;
++ 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)
++{
++ int ret = 0;
++ u32 value;
++ struct property *prop;
++ size_t sz;
++ struct edma_rsv_info *rsv_info;
++ const s16 (*rsv_chans)[2], (*rsv_slots)[2];
++ const s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
++
++ memset(pdata, 0, sizeof(struct edma_soc_info));
++
++ 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;
++ 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;
++
++ prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
++ if (prop)
++ ret = edma_xbar_event_map(dev, node, pdata, sz);
++
++ return ret;
++}
++
++static struct of_dma_filter_info edma_filter_info = {
++ .filter_fn = edma_filter_fn,
++};
+
+ static int 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;
+ 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];
++ const 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};
++ 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;
++ int ret;
++
++ if (node) {
++ 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,
++ &edma_filter_info);
++ }
+
+ if (!info)
+ return -ENODEV;
+
++ 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;
++ }
++
+ 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
+@@ -1468,8 +1735,22 @@ static int edma_probe(struct platform_device *pdev)
+ }
+ }
+
+- sprintf(irq_name, "edma%d", j);
+- irq[j] = platform_get_irq_byname(pdev, irq_name);
++ /* 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 {
++ 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);
+@@ -1479,8 +1760,12 @@ static int 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);
+@@ -1541,9 +1826,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/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
+index 2344ea2..ffc1fb2 100644
+--- a/include/linux/platform_data/edma.h
++++ b/include/linux/platform_data/edma.h
+@@ -177,6 +177,7 @@ struct edma_soc_info {
+
+ const s8 (*queue_tc_mapping)[2];
+ const s8 (*queue_priority_mapping)[2];
++ const s16 (*xbar_chans)[2];
+ };
+
+ #endif
diff --git a/patches/linux-3.8.13/0016-dmaengine-edma-enable-build-for-AM33XX.patch b/patches/linux-3.8.13/0016-dmaengine-edma-enable-build-for-AM33XX.patch
new file mode 100644
index 0000000..b3d58ab
--- /dev/null
+++ b/patches/linux-3.8.13/0016-dmaengine-edma-enable-build-for-AM33XX.patch
@@ -0,0 +1,24 @@
+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.8.13/0017-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch b/patches/linux-3.8.13/0017-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
new file mode 100644
index 0000000..b4a0772
--- /dev/null
+++ b/patches/linux-3.8.13/0017-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
@@ -0,0 +1,68 @@
+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 | 49 +++++++++++++++++++++
+ 1 file changed, 49 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..075a60e3
+--- /dev/null
++++ b/Documentation/devicetree/bindings/dma/ti-edma.txt
+@@ -0,0 +1,49 @@
++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 {
++ 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.8.13/0018-ARM-dts-add-AM33XX-EDMA-support.patch b/patches/linux-3.8.13/0018-ARM-dts-add-AM33XX-EDMA-support.patch
new file mode 100644
index 0000000..102ab48
--- /dev/null
+++ b/patches/linux-3.8.13/0018-ARM-dts-add-AM33XX-EDMA-support.patch
@@ -0,0 +1,43 @@
+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 | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index c2f14e8..e711ffb 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -87,6 +87,26 @@
+ 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-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.8.13/0019-dmaengine-add-dma_request_slave_channel_compat.patch b/patches/linux-3.8.13/0019-dmaengine-add-dma_request_slave_channel_compat.patch
new file mode 100644
index 0000000..f03996a
--- /dev/null
+++ b/patches/linux-3.8.13/0019-dmaengine-add-dma_request_slave_channel_compat.patch
@@ -0,0 +1,42 @@
+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>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ include/linux/dmaengine.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index 9fd0c5b..64f9f69 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -1047,6 +1047,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.8.13/0020-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch b/patches/linux-3.8.13/0020-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
new file mode 100644
index 0000000..261f813
--- /dev/null
+++ b/patches/linux-3.8.13/0020-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
@@ -0,0 +1,45 @@
+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>
+Acked-by: Tony Lindgren <tony@atomide.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 bc58078..e79b12d 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1915,14 +1915,20 @@ static int 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.8.13/0021-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch b/patches/linux-3.8.13/0021-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch
new file mode 100644
index 0000000..d87faf0
--- /dev/null
+++ b/patches/linux-3.8.13/0021-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch
@@ -0,0 +1,42 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 08:55:41 -0400
+Subject: [PATCH] mmc: omap_hsmmc: set max_segs based on dma engine
+ limitations
+
+The EDMA DMAC has a hardware limitation that prevents supporting
+scatter gather lists with any number of segments. The DMA Engine
+API reports the maximum number of segments a channel can support
+via the optional dma_get_channel_caps() API. If the nr_segs
+capability is present, the value is used to configure mmc->max_segs
+appropriately.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index e79b12d..f74bd69 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1769,6 +1769,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ const struct of_device_id *match;
+ dma_cap_mask_t mask;
+ unsigned tx_req, rx_req;
++ struct dmaengine_chan_caps *dma_chan_caps;
+ struct pinctrl *pinctrl;
+
+ match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
+@@ -1935,6 +1936,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ goto err_irq;
+ }
+
++ /* Some DMA Engines only handle a limited number of SG segments */
++ dma_chan_caps = dma_get_channel_caps(host->rx_chan, DMA_DEV_TO_MEM);
++ if (dma_chan_caps && dma_chan_caps->seg_nr)
++ mmc->max_segs = dma_chan_caps->seg_nr;
++
+ /* Request IRQ for MMC operations */
+ ret = request_irq(host->irq, omap_hsmmc_irq, 0,
+ mmc_hostname(mmc), host);
diff --git a/patches/linux-3.8.13/0022-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch b/patches/linux-3.8.13/0022-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
new file mode 100644
index 0000000..5246c41
--- /dev/null
+++ b/patches/linux-3.8.13/0022-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
@@ -0,0 +1,55 @@
+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>
+Acked-by: Tony Lindgren <tony@atomide.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 ed271fc..826cc51 100644
+--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
++++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+@@ -20,8 +20,28 @@ ti,dual-volt: boolean, supports dual voltage cards
+ ti,non-removable: non-removable slot (like eMMC)
+ ti,needs-special-reset: Requires a special softreset sequence
+ ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
++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>;
+@@ -30,4 +50,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.8.13/0023-ARM-dts-add-AM33XX-MMC-support.patch b/patches/linux-3.8.13/0023-ARM-dts-add-AM33XX-MMC-support.patch
new file mode 100644
index 0000000..6f625fa
--- /dev/null
+++ b/patches/linux-3.8.13/0023-ARM-dts-add-AM33XX-MMC-support.patch
@@ -0,0 +1,118 @@
+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, am335x-evm, and
+am335x-evmsk.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 7 +++++++
+ arch/arm/boot/dts/am335x-evm.dts | 7 +++++++
+ arch/arm/boot/dts/am335x-evmsk.dts | 7 +++++++
+ arch/arm/boot/dts/am33xx.dtsi | 28 ++++++++++++++++++++++++++++
+ 4 files changed, 49 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 11b240c..a154ce0 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -120,6 +120,8 @@
+ };
+
+ ldo3_reg: regulator@5 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+@@ -136,3 +138,8 @@
+ &cpsw_emac1 {
+ phy_id = <&davinci_mdio>, <1>;
+ };
++
++&mmc1 {
++ status = "okay";
++ vmmc-supply = <&ldo3_reg>;
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index d649644..2907da6 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -232,6 +232,8 @@
+ };
+
+ vmmc_reg: regulator@12 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+@@ -244,3 +246,8 @@
+ &cpsw_emac1 {
+ phy_id = <&davinci_mdio>, <1>;
+ };
++
++&mmc1 {
++ status = "okay";
++ vmmc-supply = <&vmmc_reg>;
++};
+diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
+index f5a6162..f050c46 100644
+--- a/arch/arm/boot/dts/am335x-evmsk.dts
++++ b/arch/arm/boot/dts/am335x-evmsk.dts
+@@ -244,7 +244,14 @@
+ };
+
+ vmmc_reg: regulator@12 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
++
++&mmc1 {
++ status = "okay";
++ vmmc-supply = <&vmmc_reg>;
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index e711ffb..278b75d 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -235,6 +235,34 @@
+ 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";
++ status = "disabled";
++ };
++
++ 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.8.13/0024-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch b/patches/linux-3.8.13/0024-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
new file mode 100644
index 0000000..292f2ac
--- /dev/null
+++ b/patches/linux-3.8.13/0024-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
@@ -0,0 +1,118 @@
+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 b610f52..2c02c02 100644
+--- a/drivers/spi/spi-omap2-mcspi.c
++++ b/drivers/spi/spi-omap2-mcspi.c
+@@ -102,6 +102,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
+@@ -822,14 +825,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);
+@@ -1223,29 +1235,42 @@ static int 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.8.13/0025-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch b/patches/linux-3.8.13/0025-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
new file mode 100644
index 0000000..450c402
--- /dev/null
+++ b/patches/linux-3.8.13/0025-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
@@ -0,0 +1,55 @@
+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 | 28 +++++++++++++++++++-
+ 1 file changed, 27 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/spi/omap-spi.txt b/Documentation/devicetree/bindings/spi/omap-spi.txt
+index 938809c..3bd8eed 100644
+--- a/Documentation/devicetree/bindings/spi/omap-spi.txt
++++ b/Documentation/devicetree/bindings/spi/omap-spi.txt
+@@ -10,7 +10,18 @@ Required properties:
+ input. The default is D0 as input and
+ D1 as output.
+
+-Example:
++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.
++
++Examples:
++
++[hwmod populated DMA resources]
+
+ mcspi1: mcspi@1 {
+ #address-cells = <1>;
+@@ -20,3 +31,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.8.13/0026-ARM-dts-add-AM33XX-SPI-DMA-support.patch b/patches/linux-3.8.13/0026-ARM-dts-add-AM33XX-SPI-DMA-support.patch
new file mode 100644
index 0000000..4277582
--- /dev/null
+++ b/patches/linux-3.8.13/0026-ARM-dts-add-AM33XX-SPI-DMA-support.patch
@@ -0,0 +1,39 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 10 Jan 2013 19:09:50 -0500
+Subject: [PATCH] ARM: dts: add AM33XX SPI DMA support
+
+Adds DMA resources to the AM33XX SPI nodes.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 278b75d..8fd3648 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -356,6 +356,11 @@
+ interrupt = <65>;
+ ti,spi-num-cs = <2>;
+ ti,hwmods = "spi0";
++ dmas = <&edma 16
++ &edma 17
++ &edma 18
++ &edma 19>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
+ status = "disabled";
+ };
+
+@@ -367,6 +372,11 @@
+ interrupt = <125>;
+ ti,spi-num-cs = <2>;
+ ti,hwmods = "spi1";
++ dmas = <&edma 42
++ &edma 43
++ &edma 44
++ &edma 45>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
+ status = "disabled";
+ };
+
diff --git a/patches/linux-3.8.13/0027-ARM-dts-Add-SPI-Flash-support-to-am335x-evm.patch b/patches/linux-3.8.13/0027-ARM-dts-Add-SPI-Flash-support-to-am335x-evm.patch
new file mode 100644
index 0000000..7402d18
--- /dev/null
+++ b/patches/linux-3.8.13/0027-ARM-dts-Add-SPI-Flash-support-to-am335x-evm.patch
@@ -0,0 +1,54 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 10 Jan 2013 19:11:38 -0500
+Subject: [PATCH] ARM: dts: Add SPI Flash support to am335x-evm
+
+Add SPI pinmuxing and spansion device node for profile 2..
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-evm.dts | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 2907da6..0dda333 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -26,7 +26,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0>;
++ pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &spi0_pins_s0>;
+
+ matrix_keypad_s0: matrix_keypad_s0 {
+ pinctrl-single,pins = <
+@@ -44,6 +44,16 @@
+ 0x154 0x27 /* spi0_d0.gpio0_3, INPUT | MODE7 */
+ >;
+ };
++
++ spi0_pins_s0: spi0_pins_s0 {
++ pinctrl-single,pins = <
++ 0x150 0x30 /* spi0_sclk.spi0_sclk, INPUT_PULLUP | MODE0 */
++ 0x154 0x30 /* spi0_d0.spi0_d0, INPUT_PULLUP | MODE0 */
++ 0x158 0x10 /* spi0_d1.spi0_d1, OUTPUT_PULLUP | MODE0 */
++ 0x15c 0x10 /* spi0_cs0.spi0_cs0, OUTPUT_PULLUP | MODE0 */
++ >;
++ };
++
+ };
+
+ ocp {
+@@ -251,3 +261,12 @@
+ status = "okay";
+ vmmc-supply = <&vmmc_reg>;
+ };
++
++&spi0 {
++ status = "okay";
++ spi-flash@0 {
++ compatible = "spansion,s25fl064k", "m25p80";
++ spi-max-frequency = <24000000>;
++ reg = <0>;
++ };
++};
diff --git a/patches/linux-3.8.13/0028-Documentation-bindings-add-spansion.patch b/patches/linux-3.8.13/0028-Documentation-bindings-add-spansion.patch
new file mode 100644
index 0000000..9715369
--- /dev/null
+++ b/patches/linux-3.8.13/0028-Documentation-bindings-add-spansion.patch
@@ -0,0 +1,21 @@
+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 2e000ea..cb0209a 100644
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -51,6 +51,7 @@ simtek
+ sirf SiRF Technology, Inc.
+ sitronix Sitronix Technology Corp.
+ snps Synopsys, Inc.
++spansion Spansion, Inc.
+ st STMicroelectronics
+ stericsson ST-Ericsson
+ ti Texas Instruments
diff --git a/patches/linux-3.8.13/0029-ARM-dts-enable-spi1-node-and-pinmux-on-BeagleBone.patch b/patches/linux-3.8.13/0029-ARM-dts-enable-spi1-node-and-pinmux-on-BeagleBone.patch
new file mode 100644
index 0000000..058e066
--- /dev/null
+++ b/patches/linux-3.8.13/0029-ARM-dts-enable-spi1-node-and-pinmux-on-BeagleBone.patch
@@ -0,0 +1,49 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 10 Jan 2013 19:13:30 -0500
+Subject: [PATCH] ARM: dts: enable spi1 node and pinmux on BeagleBone
+
+Enables the spi1 IP and pinmuxes for use on the mcasp0
+pins.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index a154ce0..ccff86a 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -26,7 +26,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&user_leds_s0>;
++ pinctrl-0 = <&user_leds_s0 &spi1_pins_s0>;
+
+ user_leds_s0: user_leds_s0 {
+ pinctrl-single,pins = <
+@@ -36,6 +36,15 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++
++ spi1_pins_s0: spi1_pins_s0 {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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 {
+@@ -143,3 +152,7 @@
+ status = "okay";
+ vmmc-supply = <&ldo3_reg>;
+ };
++
++&spi1 {
++ status = "okay";
++};
diff --git a/patches/linux-3.8.13/0030-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch b/patches/linux-3.8.13/0030-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
new file mode 100644
index 0000000..406bea2
--- /dev/null
+++ b/patches/linux-3.8.13/0030-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
@@ -0,0 +1,51 @@
+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 | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index ccff86a..8ac3ae4 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -26,7 +26,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&user_leds_s0 &spi1_pins_s0>;
++ pinctrl-0 = <&user_leds_s0 &spi1_pins_s0 &lcd_pins_s0>;
+
+ user_leds_s0: user_leds_s0 {
+ pinctrl-single,pins = <
+@@ -45,6 +45,13 @@
+ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+ >;
+ };
++
++ lcd_pins_s0: lcd_pins_s0 {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -155,4 +162,14 @@
+
+ &spi1 {
+ status = "okay";
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
+ };
diff --git a/patches/linux-3.8.13/0031-misc-add-gpevt-driver.patch b/patches/linux-3.8.13/0031-misc-add-gpevt-driver.patch
new file mode 100644
index 0000000..757e48c
--- /dev/null
+++ b/patches/linux-3.8.13/0031-misc-add-gpevt-driver.patch
@@ -0,0 +1,218 @@
+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.8.13/0032-ARM-dts-add-BeagleBone-gpevt-support.patch b/patches/linux-3.8.13/0032-ARM-dts-add-BeagleBone-gpevt-support.patch
new file mode 100644
index 0000000..d672e6b
--- /dev/null
+++ b/patches/linux-3.8.13/0032-ARM-dts-add-BeagleBone-gpevt-support.patch
@@ -0,0 +1,57 @@
+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 | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 8ac3ae4..8f35a81 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -26,7 +26,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&user_leds_s0 &spi1_pins_s0 &lcd_pins_s0>;
++ pinctrl-0 = <&user_leds_s0 &spi1_pins_s0 &lcd_pins_s0 &gpevt_pins_s0>;
+
+ user_leds_s0: user_leds_s0 {
+ pinctrl-single,pins = <
+@@ -52,6 +52,12 @@
+ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++
++ gpevt_pins_s0: gpevt_pins_s0 {
++ pinctrl-single,pins = <
++ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -68,6 +74,13 @@
+ };
+
+ };
++
++ gpevt {
++ compatible = "gpevt";
++ dmas = <&edma 12>;
++ dma-names = "gpioevt";
++ gpio-evt = <&gpio3 2 0>;
++ };
+ };
+
+ leds {
+@@ -173,3 +186,7 @@
+ st7735-dc = <&gpio4 21 0>;
+ };
+ };
++
++&edma {
++ ti,edma-xbar-event-map = <32 12>;
++};
diff --git a/patches/linux-3.8.13/0033-ARM-configs-working-dmaengine-configs-for-da8xx-and-.patch b/patches/linux-3.8.13/0033-ARM-configs-working-dmaengine-configs-for-da8xx-and-.patch
new file mode 100644
index 0000000..e596ed1
--- /dev/null
+++ b/patches/linux-3.8.13/0033-ARM-configs-working-dmaengine-configs-for-da8xx-and-.patch
@@ -0,0 +1,4874 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 9 Jan 2013 16:26:38 -0500
+Subject: [PATCH] ARM: configs: working dmaengine configs for da8xx and am33xx
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/configs/da8xx_omapl_defconfig | 1881 ++++++++++++++++++++++-
+ arch/arm/configs/omap2plus_defconfig | 2640 +++++++++++++++++++++++++++++++-
+ 2 files changed, 4472 insertions(+), 49 deletions(-)
+
+diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig
+index f292239..571445f 100644
+--- a/arch/arm/configs/da8xx_omapl_defconfig
++++ b/arch/arm/configs/da8xx_omapl_defconfig
+@@ -1,132 +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_MACH_DA8XX_DT=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_USE_OF=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_OF_PLATFORM=y
++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/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
+index 82ce8d7..d322dec 100644
+--- a/arch/arm/configs/omap2plus_defconfig
++++ b/arch/arm/configs/omap2plus_defconfig
+@@ -1,250 +1,2840 @@
++#
++# Automatically generated file; DO NOT EDIT.
++# Linux/arm 3.8.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_GENERIC_BUG=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_HAVE_IRQ_WORK=y
++CONFIG_IRQ_WORK=y
++CONFIG_BUILDTIME_EXTABLE_SORT=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=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=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 is not set
++# CONFIG_TASKSTATS is not set
++
++#
++# 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_RCU_NOCB_CPU is not set
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=16
++# 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_EXTRA_PASS=y
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++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=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=y
++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_HAVE_ARCH_SECCOMP_FILTER=y
++CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
++CONFIG_MODULES_USE_ELF_REL=y
++CONFIG_CLONE_BACKWARDS=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 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=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_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_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_SINGLE 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_DEBUG_DEVICES=y
+ 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=y
++CONFIG_ARCH_OMAP2=y
++CONFIG_ARCH_OMAP3=y
++CONFIG_ARCH_OMAP4=y
++CONFIG_SOC_OMAP5=y
++
++#
++# OMAP Core Type
++#
++CONFIG_SOC_OMAP2420=y
++CONFIG_SOC_OMAP2430=y
++CONFIG_SOC_OMAP3430=y
++CONFIG_SOC_TI81XX=y
++CONFIG_SOC_AM33XX=y
++CONFIG_OMAP_PACKAGE_ZAF=y
++CONFIG_OMAP_PACKAGE_ZAC=y
++CONFIG_OMAP_PACKAGE_CBB=y
++CONFIG_OMAP_PACKAGE_CUS=y
++CONFIG_OMAP_PACKAGE_CBP=y
++CONFIG_OMAP_PACKAGE_CBL=y
++CONFIG_OMAP_PACKAGE_CBS=y
++
++#
++# OMAP Board Type
++#
++CONFIG_MACH_OMAP2_TUSB6010=y
++CONFIG_MACH_OMAP_H4=y
++CONFIG_MACH_OMAP_APOLLON=y
++CONFIG_MACH_OMAP_2430SDP=y
++CONFIG_MACH_OMAP3_BEAGLE=y
++CONFIG_MACH_DEVKIT8000=y
++CONFIG_MACH_OMAP_LDP=y
++CONFIG_MACH_OMAP3530_LV_SOM=y
++CONFIG_MACH_OMAP3_TORPEDO=y
++CONFIG_MACH_OVERO=y
++CONFIG_MACH_OMAP3EVM=y
++CONFIG_MACH_OMAP3517EVM=y
++# CONFIG_MACH_CRANEBOARD is not set
++CONFIG_MACH_OMAP3_PANDORA=y
++CONFIG_MACH_TOUCHBOOK=y
++CONFIG_MACH_OMAP_3430SDP=y
++CONFIG_MACH_NOKIA_N800=y
++CONFIG_MACH_NOKIA_N810=y
++CONFIG_MACH_NOKIA_N810_WIMAX=y
++CONFIG_MACH_NOKIA_N8X0=y
++CONFIG_MACH_NOKIA_RM680=y
++CONFIG_MACH_NOKIA_RX51=y
++CONFIG_MACH_OMAP_ZOOM2=y
++CONFIG_MACH_OMAP_ZOOM3=y
++CONFIG_MACH_CM_T35=y
++CONFIG_MACH_CM_T3517=y
++CONFIG_MACH_CM_T3730=y
++CONFIG_MACH_IGEP0020=y
++CONFIG_MACH_IGEP0030=y
++CONFIG_MACH_SBC3530=y
++CONFIG_MACH_OMAP_3630SDP=y
++CONFIG_MACH_TI8168EVM=y
++CONFIG_MACH_TI8148EVM=y
++CONFIG_MACH_OMAP_4430SDP=y
++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
++# CONFIG_ARCH_VT8500 is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_V6=y
++CONFIG_CPU_V7=y
++CONFIG_CPU_32v6=y
++CONFIG_CPU_32v6K=y
++CONFIG_CPU_32v7=y
++CONFIG_CPU_ABRT_EV6=y
++CONFIG_CPU_ABRT_EV7=y
++CONFIG_CPU_PABRT_V6=y
++CONFIG_CPU_PABRT_V7=y
++CONFIG_CPU_CACHE_V6=y
++CONFIG_CPU_CACHE_V7=y
++CONFIG_CPU_CACHE_VIPT=y
++CONFIG_CPU_COPY_V6=y
++CONFIG_CPU_TLB_V6=y
++CONFIG_CPU_TLB_V7=y
++CONFIG_CPU_HAS_ASID=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_ARM_THUMBEE=y
++# CONFIG_ARM_VIRT_EXT is not set
++# 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_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_326103 is not set
+ CONFIG_ARM_ERRATA_411920=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=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_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=y
++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=2
+-CONFIG_LEDS=y
++CONFIG_HOTPLUG_CPU=y
++CONFIG_LOCAL_TIMERS=y
++CONFIG_ARCH_NR_GPIO=512
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=128
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=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=999999
++CONFIG_COMPACTION=y
++CONFIG_MIGRATION=y
++# 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
++
++#
++# 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 is not set
+ CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
++CONFIG_CMDLINE_FROM_BOOTLOADER=y
++# CONFIG_CMDLINE_EXTEND is not set
++# CONFIG_CMDLINE_FORCE is not set
++# CONFIG_XIP_KERNEL is not set
+ CONFIG_KEXEC=y
++CONFIG_ATAGS_PROC=y
++# CONFIG_CRASH_DUMP is not set
++# CONFIG_AUTO_ZRELADDR is not set
++
++#
++# CPU Power Management
++#
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++# CONFIG_CPU_IDLE is not set
++CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
+ CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_VFP=y
++CONFIG_VFPv3=y
++CONFIG_NEON=y
++
++#
++# 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=y
++CONFIG_COREDUMP=y
++
++#
++# 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 is not set
+ CONFIG_UNIX=y
++# CONFIG_UNIX_DIAG is not set
++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_NET_KEY=y
+ CONFIG_NET_KEY_MIGRATE=y
+ CONFIG_INET=y
+ CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER 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 is not set
++# CONFIG_NET_IPGRE_DEMUX is not set
++# CONFIG_IP_MROUTE 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 is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
+ # CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_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 is not set
++# 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
++
++#
++# 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
++# 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_HAVE_NET_DSA=y
++# 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_DNS_RESOLVER=y
++# CONFIG_BATMAN_ADV is not set
++# CONFIG_OPENVSWITCH is not set
++CONFIG_RPS=y
++CONFIG_RFS_ACCEL=y
++CONFIG_XPS=y
++CONFIG_BQL=y
++# CONFIG_BPF_JIT is not set
++
++#
++# 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 is not set
++# CONFIG_IRDA is not set
+ CONFIG_BT=m
++# CONFIG_BT_RFCOMM is not set
++# CONFIG_BT_BNEP is not set
++# CONFIG_BT_HIDP is not set
++
++#
++# Bluetooth device drivers
++#
++# CONFIG_BT_HCIBTUSB is not set
++# CONFIG_BT_HCIBTSDIO is not set
+ CONFIG_BT_HCIUART=m
+ CONFIG_BT_HCIUART_H4=y
+ CONFIG_BT_HCIUART_BCSP=y
++# CONFIG_BT_HCIUART_ATH3K is not set
+ CONFIG_BT_HCIUART_LL=y
++# CONFIG_BT_HCIUART_3WIRE is not set
+ CONFIG_BT_HCIBCM203X=m
+ CONFIG_BT_HCIBPA10X=m
++# CONFIG_BT_HCIBFUSB is not set
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_BT_MRVL is not set
++# CONFIG_AF_RXRPC is not set
++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 is not set
++# CONFIG_CFG80211_INTERNAL_REGDB is not set
++# CONFIG_CFG80211_WEXT is not set
++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 is not set
++# CONFIG_MAC80211_DEBUGFS is not set
++# CONFIG_MAC80211_MESSAGE_TRACING is not set
++# CONFIG_MAC80211_DEBUG_MENU is not set
++# 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_CONNECTOR=y
+ 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_IRQ=y
++# CONFIG_DMA_SHARED_BUFFER is not set
++# CONFIG_CMA is not set
++
++#
++# Bus devices
++#
++# CONFIG_OMAP_OCP2SCP is not set
++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=y
++# 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=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_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_DENALI 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 is not set
++# 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_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_GPEVT=y
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
++# CONFIG_EEPROM_AT24 is not set
++# 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 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
++
++#
++# 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_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_SMSC_PHY=y
+-CONFIG_NET_ETHERNET=y
+-CONFIG_SMC91X=y
+-CONFIG_SMSC911X=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 is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++
++#
++# 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_CADENCE=y
++# CONFIG_ARM_AT91_ETHER is not set
++# CONFIG_MACB is not set
++CONFIG_NET_VENDOR_BROADCOM=y
++# CONFIG_B44 is not set
++# CONFIG_NET_CALXEDA_XGMAC is not set
++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_MVMDIO is not set
++CONFIG_NET_VENDOR_MICREL=y
++# CONFIG_KS8842 is not set
+ CONFIG_KS8851=y
+ CONFIG_KS8851_MLL=y
+-CONFIG_LIBERTAS=m
+-CONFIG_LIBERTAS_USB=m
+-CONFIG_LIBERTAS_SDIO=m
+-CONFIG_LIBERTAS_DEBUG=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 is not set
++CONFIG_TI_DAVINCI_MDIO=y
++CONFIG_TI_DAVINCI_CPDMA=y
++CONFIG_TI_CPSW=y
++# CONFIG_TI_CPTS 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_AT803X_PHY is not set
++# 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_GPIO is not set
++# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
++# CONFIG_MICREL_KS8995MA is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++
++#
++# 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_CDC_MBIM is not set
++# 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_NET_INT51X1 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_CARDS 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
++
++#
++# 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 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_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 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_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_SERIO_ARC_PS2 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_SERIAL_ARC is not set
++# CONFIG_TTY_PRINTK is not set
++# CONFIG_HVC_DCC is not set
++# 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_OMAP=y
++# 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_CBUS_GPIO is not set
++# 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 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
++#
++# CONFIG_PTP_1588_CLOCK is not set
++
++#
++# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
++#
++# CONFIG_PTP_1588_CLOCK_PCH is not set
++CONFIG_PINCTRL=y
++
++#
++# Pin controllers
++#
++CONFIG_PINMUX=y
++CONFIG_PINCONF=y
++CONFIG_DEBUG_PINCTRL=y
+ CONFIG_PINCTRL_SINGLE=y
++# CONFIG_PINCTRL_EXYNOS4 is not set
++# CONFIG_PINCTRL_EXYNOS5440 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
++# CONFIG_GPIO_TS5500 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_GPIO_TPS65910 is not set
++
++#
++# USB GPIO expanders:
++#
+ CONFIG_W1=y
++CONFIG_W1_CON=y
++
++#
++# 1-wire Bus Masters
++#
++# CONFIG_W1_MASTER_DS2490 is not set
++# CONFIG_W1_MASTER_DS2482 is not set
++# CONFIG_W1_MASTER_DS1WM is not set
++# CONFIG_W1_MASTER_GPIO is not set
++# CONFIG_HDQ_MASTER_OMAP is not set
++
++#
++# 1-wire Slaves
++#
++# CONFIG_W1_SLAVE_THERM is not set
++# CONFIG_W1_SLAVE_SMEM is not set
++# CONFIG_W1_SLAVE_DS2408 is not set
++# CONFIG_W1_SLAVE_DS2423 is not set
++# CONFIG_W1_SLAVE_DS2431 is not set
++# CONFIG_W1_SLAVE_DS2433 is not set
++# CONFIG_W1_SLAVE_DS2760 is not set
++# CONFIG_W1_SLAVE_DS2780 is not set
++# CONFIG_W1_SLAVE_DS2781 is not set
++# CONFIG_W1_SLAVE_DS28E04 is not set
++# CONFIG_W1_SLAVE_BQ27000 is not set
+ CONFIG_POWER_SUPPLY=y
++# CONFIG_POWER_SUPPLY_DEBUG is not set
++# CONFIG_PDA_POWER is not set
++# CONFIG_TEST_POWER 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_MAX8903 is not set
++# CONFIG_CHARGER_TWL4030 is not set
++# CONFIG_CHARGER_LP8727 is not set
++# CONFIG_CHARGER_GPIO is not set
++# CONFIG_CHARGER_MANAGER is not set
++# CONFIG_CHARGER_BQ2415X is not set
++# CONFIG_CHARGER_SMB347 is not set
++# CONFIG_POWER_RESET 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 is not set
++# 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 is not set
++# CONFIG_SENSORS_HIH6130 is not set
++# 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 is not set
++# 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 is not set
++# 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 is not set
++# 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 is not set
+ CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_CORE=y
++# 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 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=y
+-CONFIG_REGULATOR_TWL4030=y
++# CONFIG_MFD_TPS6586X is not set
++CONFIG_MFD_TPS65910=y
++# CONFIG_MFD_TPS65912_I2C is not set
++# CONFIG_MFD_TPS65912_SPI is not set
++# CONFIG_MFD_TPS80031 is not set
++CONFIG_MENELAUS=y
++CONFIG_TWL4030_CORE=y
++# CONFIG_TWL4030_MADC is not set
++CONFIG_TWL4030_POWER=y
++CONFIG_MFD_TWL4030_AUDIO=y
++# 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_SYSCON is not set
++# CONFIG_MFD_PALMAS is not set
++# CONFIG_MFD_VIPERBOARD is not set
++# CONFIG_MFD_RETU is not set
++# CONFIG_MFD_AS3711 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_MAX8973 is not set
++# CONFIG_REGULATOR_LP3971 is not set
++# CONFIG_REGULATOR_LP3972 is not set
++# CONFIG_REGULATOR_LP872X is not set
++# CONFIG_REGULATOR_TPS51632 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_TPS65910=y
++CONFIG_REGULATOR_TWL4030=y
++# 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=y
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=m
++CONFIG_FB_CFB_COPYAREA=m
++CONFIG_FB_CFB_IMAGEBLIT=m
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++CONFIG_FB_SYS_FILLRECT=y
++CONFIG_FB_SYS_COPYAREA=y
++CONFIG_FB_SYS_IMAGEBLIT=y
++# CONFIG_FB_FOREIGN_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
+-CONFIG_FB_OMAP_LCD_VGA=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_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_VRFB=y
+ CONFIG_OMAP2_DSS=m
++# CONFIG_OMAP2_DSS_DEBUG is not set
++# CONFIG_OMAP2_DSS_DEBUGFS 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 is not set
++# CONFIG_LCD_TDO24M is not set
++# CONFIG_LCD_VGG2432A4 is not set
+ CONFIG_LCD_PLATFORM=y
+-CONFIG_DISPLAY_SUPPORT=y
++# CONFIG_LCD_S6E63M0 is not set
++# CONFIG_LCD_LD9040 is not set
++# CONFIG_LCD_AMS369FG06 is not set
++CONFIG_BACKLIGHT_CLASS_DEVICE=m
++CONFIG_BACKLIGHT_GENERIC=m
++# CONFIG_BACKLIGHT_ADP8860 is not set
++# CONFIG_BACKLIGHT_ADP8870 is not set
++# CONFIG_BACKLIGHT_LM3630 is not set
++# CONFIG_BACKLIGHT_LM3639 is not set
++# CONFIG_BACKLIGHT_LP855X is not set
++# CONFIG_BACKLIGHT_PANDORA is not set
++# CONFIG_BACKLIGHT_TPS65217 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=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 is not set
++# 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_FB_SSD1307 is not set
+ 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_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_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_SOC_DMAENGINE_PCM=y
++# CONFIG_SND_DESIGNWARE_I2S is not set
+ CONFIG_SND_OMAP_SOC=m
++CONFIG_SND_OMAP_SOC_MCBSP=m
++# CONFIG_SND_OMAP_SOC_N810 is not set
++# CONFIG_SND_OMAP_SOC_RX51 is not set
++# CONFIG_SND_OMAP_SOC_AM3517EVM is not set
++# CONFIG_SND_OMAP_SOC_SDP3430 is not set
+ CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
++# CONFIG_SND_OMAP_SOC_OMAP_HDMI is not set
+ CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
++# CONFIG_SND_OMAP_SOC_ZOOM2 is not set
++CONFIG_SND_SOC_I2C_AND_SPI=m
++# CONFIG_SND_SOC_ALL_CODECS is not set
++CONFIG_SND_SOC_TWL4030=m
++# CONFIG_SND_SIMPLE_CARD is not set
++# CONFIG_SOUND_PRIME is not set
++
++#
++# HID support
++#
++CONFIG_HID=y
++# CONFIG_HID_BATTERY_STRENGTH is not set
++# CONFIG_HIDRAW is not set
++# CONFIG_UHID is not set
++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_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 is not set
++# CONFIG_HID_LOGITECH 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_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_ZEROPLUS is not set
++# CONFIG_HID_ZYDACRON is not set
++# CONFIG_HID_SENSOR_HUB is not set
++
++#
++# USB HID support
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# I2C HID support
++#
++# CONFIG_I2C_HID 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
+-CONFIG_USB_DEVICEFS=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_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_MUSB_HDRC is not set
++# CONFIG_USB_CHIPIDEA is not set
++# CONFIG_USB_RENESAS_USBHS is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
+ CONFIG_USB_WDM=y
++# CONFIG_USB_TMC is not set
++
++#
++# 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_LIBUSUAL=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
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
+ CONFIG_USB_TEST=y
++# CONFIG_USB_ISIGHTFW is not set
++# CONFIG_USB_YUREX is not set
++# CONFIG_USB_EZUSB_FX2 is not set
++
++#
++# USB Physical Layer drivers
++#
++# CONFIG_OMAP_USB2 is not set
++# CONFIG_USB_ISP1301 is not set
++# CONFIG_USB_RCAR_PHY is not set
+ 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_M66592 is not set
++# CONFIG_USB_NET2272 is not set
++# CONFIG_USB_DUMMY_HCD is not set
++CONFIG_USB_LIBCOMPOSITE=m
+ CONFIG_USB_ZERO=m
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_G_NCM is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FUNCTIONFS is not set
++# CONFIG_USB_MASS_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_USB_CDC_COMPOSITE is not set
++# CONFIG_USB_G_ACM_MS is not set
++# CONFIG_USB_G_MULTI is not set
++# CONFIG_USB_G_HID is not set
++# CONFIG_USB_G_DBGP is not set
++
++#
++# OTG and related infrastructure
++#
++# CONFIG_USB_GPIO_VBUS is not set
++# CONFIG_USB_ULPI is not set
++# CONFIG_NOP_USB_XCEIV 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=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 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_PCF8523 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_TWL92330=y
+ CONFIG_RTC_DRV_TWL4030=y
++# CONFIG_RTC_DRV_TPS65910 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 is not set
++# CONFIG_RTC_DRV_SNVS is not set
+ 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=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 is not set
++
++#
++# Virtio drivers
++#
++# CONFIG_VIRTIO_MMIO is not set
++
++#
++# Microsoft Hyper-V guest support
++#
++# CONFIG_STAGING is not set
++CONFIG_CLKDEV_LOOKUP=y
++CONFIG_HAVE_CLK_PREPARE=y
++CONFIG_COMMON_CLK=y
++
++#
++# Common Clock Framework
++#
++# CONFIG_COMMON_CLK_DEBUG is not set
++
++#
++# Hardware Spinlock drivers
++#
++# CONFIG_HWSPINLOCK_OMAP is not set
++CONFIG_CLKSRC_MMIO=y
++CONFIG_IOMMU_SUPPORT=y
++CONFIG_OF_IOMMU=y
++# CONFIG_OMAP_IOMMU is not set
++
++#
++# 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
++# CONFIG_IPACK_BUS is not set
++
++#
++# 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_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 is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS 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=y
++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 is not set
++# 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_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 is not set
++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 is not set
++# CONFIG_NFS_V4_1 is not set
+ CONFIG_ROOT_NFS=y
+-CONFIG_PARTITION_ADVANCED=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_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 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=y
++CONFIG_DEBUG_MUTEXES=y
++CONFIG_DEBUG_LOCK_ALLOC=y
+ CONFIG_PROVE_LOCKING=y
+-CONFIG_DEBUG_SPINLOCK_SLEEP=y
++# CONFIG_PROVE_RCU is not set
++# CONFIG_SPARSE_RCU_POINTER is not set
++CONFIG_LOCKDEP=y
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_LOCKDEP is not set
++CONFIG_TRACE_IRQFLAGS=y
++# 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 is not set
+ CONFIG_DEBUG_INFO=y
+-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_DEBUG_INFO_REDUCED 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_CPU_STALL_TIMEOUT=21
++# 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 is not set
++# 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 is not set
++# CONFIG_SECURITY_NETWORK is not set
++# CONFIG_SECURITY_PATH is not set
++# CONFIG_SECURITY_SMACK 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_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=m
++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 is not set
++CONFIG_CRYPTO_WORKQUEUE=y
++# 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=m
++# 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=y
++# CONFIG_CRYPTO_GHASH is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
+ 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 is not set
++# CONFIG_CRYPTO_SHA1_ARM is not set
++CONFIG_CRYPTO_SHA256=m
++# 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=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 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=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 is not set
++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_PERCPU_RWSEM=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_SOC_OMAP5=y
+-CONFIG_TI_DAVINCI_MDIO=y
+-CONFIG_TI_DAVINCI_CPDMA=y
+-CONFIG_TI_CPSW=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_GENERIC_ATOMIC64=y
++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
++CONFIG_AVERAGE=y
++# CONFIG_CORDIC is not set
++# CONFIG_DDR is not set
diff --git a/patches/linux-3.8.13/0034-ARM-dts-Add-UART4-support-to-BeagleBone.patch b/patches/linux-3.8.13/0034-ARM-dts-Add-UART4-support-to-BeagleBone.patch
new file mode 100644
index 0000000..e840c25
--- /dev/null
+++ b/patches/linux-3.8.13/0034-ARM-dts-Add-UART4-support-to-BeagleBone.patch
@@ -0,0 +1,24 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 9 Jan 2013 16:57:15 -0500
+Subject: [PATCH] ARM: dts: Add UART4 support to BeagleBone
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 8f35a81..b338f5b 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -65,6 +65,10 @@
+ status = "okay";
+ };
+
++ uart5: serial@481a8000 {
++ status = "okay";
++ };
++
+ i2c1: i2c@44e0b000 {
+ status = "okay";
+ clock-frequency = <400000>;
diff --git a/patches/linux-3.8.13/0035-gpevnt-Remove-__devinit.patch b/patches/linux-3.8.13/0035-gpevnt-Remove-__devinit.patch
new file mode 100644
index 0000000..b771629
--- /dev/null
+++ b/patches/linux-3.8.13/0035-gpevnt-Remove-__devinit.patch
@@ -0,0 +1,42 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 16:45:10 +0300
+Subject: [PATCH] gpevnt: Remove __devinit
+
+__devinit is gone now; remove it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/gpevt.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/misc/gpevt.c b/drivers/misc/gpevt.c
+index 4fe256c..aabcd48 100644
+--- a/drivers/misc/gpevt.c
++++ b/drivers/misc/gpevt.c
+@@ -41,7 +41,7 @@ static void gpevt_callback(void *data)
+ dev_info(dev, "*** DMA transfer failed ***\n");
+ }
+
+-static int __devinit gpevt_probe (struct platform_device *pdev)
++static int gpevt_probe (struct platform_device *pdev)
+ {
+ struct device_node *np = pdev->dev.of_node;
+ struct pinctrl *pinctrl;
+@@ -132,7 +132,7 @@ static int __devinit gpevt_probe (struct platform_device *pdev)
+ return 0;
+ }
+
+-static int __devexit gpevt_remove(struct platform_device *pdev)
++static int gpevt_remove(struct platform_device *pdev)
+ {
+ return 0;
+ }
+@@ -149,7 +149,7 @@ static struct platform_driver gpevt_driver = {
+ .of_match_table = gpevt_dt_ids,
+ },
+ .probe = gpevt_probe,
+- .remove = __devexit_p(gpevt_remove),
++ .remove = gpevt_remove,
+ };
+
+ static int __init gpevt_init(void)
diff --git a/patches/linux-3.8.13/0036-ARM-OMAP2-am33xx-hwmod-Fix-register-offset-NULL-chec.patch b/patches/linux-3.8.13/0036-ARM-OMAP2-am33xx-hwmod-Fix-register-offset-NULL-chec.patch
new file mode 100644
index 0000000..710a94b
--- /dev/null
+++ b/patches/linux-3.8.13/0036-ARM-OMAP2-am33xx-hwmod-Fix-register-offset-NULL-chec.patch
@@ -0,0 +1,42 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Wed, 30 Jan 2013 14:39:20 +0000
+Subject: [PATCH] ARM: OMAP2: am33xx-hwmod: Fix "register offset NULL check"
+ bug
+
+am33xx_cm_wait_module_ready() checks if register offset is NULL.
+
+int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+ int i = 0;
+
+ if (!clkctrl_offs)
+ return 0;
+
+In case of AM33xx, CLKCTRL register offset for different clock domains
+are not uniformly placed. An example of this would be the RTC clock
+domain with CLKCTRL offset at 0x00.
+In such cases the module ready check is skipped which leads to a data
+abort during boot-up when RTC registers is accessed.
+
+Remove this check here to avoid checking module readiness for modules
+with clkctrl register offset at 0x00.
+
+Signed-off-by: Hebbar Gururaja <gururaja.hebbar@ti.com>
+---
+ arch/arm/mach-omap2/cm33xx.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
+index 058ce3c..325a515 100644
+--- a/arch/arm/mach-omap2/cm33xx.c
++++ b/arch/arm/mach-omap2/cm33xx.c
+@@ -241,9 +241,6 @@ int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+ {
+ int i = 0;
+
+- if (!clkctrl_offs)
+- return 0;
+-
+ omap_test_timeout(_is_module_ready(inst, cdoffs, clkctrl_offs),
+ MAX_MODULE_READY_TIME, i);
+
diff --git a/patches/linux-3.8.13/0037-rtc-OMAP-Add-system-pm_power_off-to-rtc-driver.patch b/patches/linux-3.8.13/0037-rtc-OMAP-Add-system-pm_power_off-to-rtc-driver.patch
new file mode 100644
index 0000000..1a1ce75
--- /dev/null
+++ b/patches/linux-3.8.13/0037-rtc-OMAP-Add-system-pm_power_off-to-rtc-driver.patch
@@ -0,0 +1,170 @@
+From: Colin Foe-Parker <colin.foeparker@logicpd.com>
+Date: Mon, 15 Oct 2012 20:12:19 +0530
+Subject: [PATCH] rtc: OMAP: Add system pm_power_off to rtc driver
+
+Add system power off control to rtc driver which is the in-charge
+of controlling the BeagleBone system power. The power_off routine
+can be hooked up to "pm_power_off" system call.
+
+System power off sequence:-
+* Set PMIC STATUS_OFF when PMIC_POWER_EN is pulled low
+* Enable PMIC_POWER_EN in rtc module
+* Set rtc ALARM2 time
+* Enable ALARM2 interrupt
+
+Signed-off-by: Colin Foe-Parker <colin.foeparker@logicpd.com>
+[anilkumar@ti.com: move poweroff additions to rtc driver]
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ Documentation/devicetree/bindings/rtc/rtc-omap.txt | 5 ++
+ drivers/rtc/rtc-omap.c | 74 +++++++++++++++++++-
+ 2 files changed, 78 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
+index b47aa41..8d9f4f9 100644
+--- a/Documentation/devicetree/bindings/rtc/rtc-omap.txt
++++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
+@@ -6,6 +6,10 @@ Required properties:
+ - interrupts: rtc timer, alarm interrupts in order
+ - interrupt-parent: phandle for the interrupt controller
+
++Optional properties:
++- ti,system-power-controller: Telling whether or not rtc is controlling
++ the system power.
++
+ Example:
+
+ rtc@1c23000 {
+@@ -14,4 +18,5 @@ rtc@1c23000 {
+ interrupts = <19
+ 19>;
+ interrupt-parent = <&intc>;
++ ti,system-power-controller;
+ };
+diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
+index 6009714..e6d4878 100644
+--- a/drivers/rtc/rtc-omap.c
++++ b/drivers/rtc/rtc-omap.c
+@@ -72,6 +72,14 @@
+ #define OMAP_RTC_KICK0_REG 0x6c
+ #define OMAP_RTC_KICK1_REG 0x70
+
++#define OMAP_RTC_ALARM2_SECONDS_REG 0x80
++#define OMAP_RTC_ALARM2_MINUTES_REG 0x84
++#define OMAP_RTC_ALARM2_HOURS_REG 0x88
++#define OMAP_RTC_ALARM2_DAYS_REG 0x8c
++#define OMAP_RTC_ALARM2_MONTHS_REG 0x90
++#define OMAP_RTC_ALARM2_YEARS_REG 0x94
++#define OMAP_RTC_PMIC_REG 0x98
++
+ /* OMAP_RTC_CTRL_REG bit fields: */
+ #define OMAP_RTC_CTRL_SPLIT (1<<7)
+ #define OMAP_RTC_CTRL_DISABLE (1<<6)
+@@ -93,15 +101,21 @@
+ #define OMAP_RTC_STATUS_BUSY (1<<0)
+
+ /* OMAP_RTC_INTERRUPTS_REG bit fields: */
++#define OMAP_RTC_INTERRUPTS_IT_ALARM2 (1<<4)
+ #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3)
+ #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2)
+
++/* OMAP_RTC_PMIC_REG bit fields: */
++#define OMAP_RTC_PMIC_POWER_EN_EN (1<<16)
++
+ /* OMAP_RTC_KICKER values */
+ #define KICK0_VALUE 0x83e70b13
+ #define KICK1_VALUE 0x95a4f1e0
+
+ #define OMAP_RTC_HAS_KICKER 0x1
+
++#define SHUTDOWN_TIME_SEC 2
++
+ static void __iomem *rtc_base;
+
+ #define rtc_read(addr) readb(rtc_base + (addr))
+@@ -290,6 +304,56 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+ return 0;
+ }
+
++/*
++ * rtc_power_off: Set the pmic power off sequence. The RTC generates
++ * pmic_pwr_enable control, which can be used to control an external
++ * PMIC.
++ */
++static void rtc_power_off(void)
++{
++ u32 val;
++ struct rtc_time tm;
++ unsigned long time;
++
++ /* Set PMIC power enable */
++ val = readl(rtc_base + OMAP_RTC_PMIC_REG);
++ writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + OMAP_RTC_PMIC_REG);
++
++ /* Read rtc time */
++ omap_rtc_read_time(NULL, &tm);
++
++ /* Convert Gregorian date to seconds since 01-01-1970 00:00:00 */
++ rtc_tm_to_time(&tm, &time);
++
++ /* Add shutdown time to the current value */
++ time += SHUTDOWN_TIME_SEC;
++
++ /* Convert seconds since 01-01-1970 00:00:00 to Gregorian date */
++ rtc_time_to_tm(time, &tm);
++
++ if (tm2bcd(&tm) < 0)
++ return;
++
++ pr_info("System will go to power_off state in approx. %d secs\n",
++ SHUTDOWN_TIME_SEC);
++
++ /*
++ * pmic_pwr_enable is controlled by means of ALARM2 event. So here
++ * programming alarm2 expiry time and enabling alarm2 interrupt
++ */
++ rtc_write(tm.tm_sec, OMAP_RTC_ALARM2_SECONDS_REG);
++ rtc_write(tm.tm_min, OMAP_RTC_ALARM2_MINUTES_REG);
++ rtc_write(tm.tm_hour, OMAP_RTC_ALARM2_HOURS_REG);
++ rtc_write(tm.tm_mday, OMAP_RTC_ALARM2_DAYS_REG);
++ rtc_write(tm.tm_mon, OMAP_RTC_ALARM2_MONTHS_REG);
++ rtc_write(tm.tm_year, OMAP_RTC_ALARM2_YEARS_REG);
++
++ /* Enable alarm2 interrupt */
++ val = readl(rtc_base + OMAP_RTC_INTERRUPTS_REG);
++ writel(val | OMAP_RTC_INTERRUPTS_IT_ALARM2,
++ rtc_base + OMAP_RTC_INTERRUPTS_REG);
++}
++
+ static struct rtc_class_ops omap_rtc_ops = {
+ .read_time = omap_rtc_read_time,
+ .set_time = omap_rtc_set_time,
+@@ -327,12 +391,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
+ struct resource *res, *mem;
+ struct rtc_device *rtc;
+ u8 reg, new_ctrl;
++ bool pm_off = false;
+ const struct platform_device_id *id_entry;
+ const struct of_device_id *of_id;
+
+ of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
+- if (of_id)
++ if (of_id) {
+ pdev->id_entry = of_id->data;
++ pm_off = of_property_read_bool(pdev->dev.of_node,
++ "ti,system-power-controller");
++ }
+
+ omap_rtc_timer = platform_get_irq(pdev, 0);
+ if (omap_rtc_timer <= 0) {
+@@ -385,6 +453,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, rtc);
+ dev_set_drvdata(&rtc->dev, mem);
+
++ /* RTC power off */
++ if (pm_off && !pm_power_off)
++ pm_power_off = rtc_power_off;
++
+ /* clear pending irqs, and set 1/second periodic,
+ * which we'll use instead of update irqs
+ */
diff --git a/patches/linux-3.8.13/0038-ARM-dts-AM33XX-Set-pmic-shutdown-controller-for-Beag.patch b/patches/linux-3.8.13/0038-ARM-dts-AM33XX-Set-pmic-shutdown-controller-for-Beag.patch
new file mode 100644
index 0000000..f15d2d8
--- /dev/null
+++ b/patches/linux-3.8.13/0038-ARM-dts-AM33XX-Set-pmic-shutdown-controller-for-Beag.patch
@@ -0,0 +1,27 @@
+From: AnilKumar Ch <anilkumar@ti.com>
+Date: Wed, 31 Oct 2012 12:23:27 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Set pmic-shutdown-controller for
+ BeagleBone
+
+Set ti,pmic-shutdown-controller for BeagleBone in am335x-bone.dts
+file, this flag is used by the driver to set tps65217 PMIC status
+to OFF when PWR_EN toggle.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ 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 b338f5b..feeebdd 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -121,6 +121,8 @@
+ /include/ "tps65217.dtsi"
+
+ &tps {
++ ti,pmic-shutdown-controller;
++
+ regulators {
+ dcdc1_reg: regulator@0 {
+ regulator-always-on;
diff --git a/patches/linux-3.8.13/0039-ARM-dts-AM33XX-Enable-system-power-off-control-in-am.patch b/patches/linux-3.8.13/0039-ARM-dts-AM33XX-Enable-system-power-off-control-in-am.patch
new file mode 100644
index 0000000..f95a4b0
--- /dev/null
+++ b/patches/linux-3.8.13/0039-ARM-dts-AM33XX-Enable-system-power-off-control-in-am.patch
@@ -0,0 +1,29 @@
+From: AnilKumar Ch <anilkumar@ti.com>
+Date: Wed, 31 Oct 2012 13:23:14 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Enable system power off control in
+ am335x-bone
+
+Enable system power off control for BeagleBone in am335x-bone.dts file
+under rtc node. RTC is the incharge of controlling the system power.
+This flag is used by the driver to hook up the pm_power_off system call.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index feeebdd..a92d7d1 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -85,6 +85,10 @@
+ dma-names = "gpioevt";
+ gpio-evt = <&gpio3 2 0>;
+ };
++
++ rtc@44e3e000 {
++ ti,system-power-controller;
++ };
+ };
+
+ leds {
diff --git a/patches/linux-3.8.13/0040-i2c-pinctrl-ify-i2c-omap.c.patch b/patches/linux-3.8.13/0040-i2c-pinctrl-ify-i2c-omap.c.patch
new file mode 100644
index 0000000..3ebeae1
--- /dev/null
+++ b/patches/linux-3.8.13/0040-i2c-pinctrl-ify-i2c-omap.c.patch
@@ -0,0 +1,44 @@
+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 | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index 4cc2f05..0d55dbd 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -44,6 +44,7 @@
+ #include <linux/i2c-omap.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ /* I2C controller revisions */
+ #define OMAP_I2C_OMAP1_REV_2 0x20
+@@ -1083,6 +1084,7 @@ omap_i2c_probe(struct platform_device *pdev)
+ int r;
+ u32 rev;
+ u16 minor, major, scheme;
++ struct pinctrl *pinctrl;
+
+ /* NOTE: driver uses the static register mapping */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -1252,6 +1254,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.8.13/0041-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch b/patches/linux-3.8.13/0041-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
new file mode 100644
index 0000000..1270795
--- /dev/null
+++ b/patches/linux-3.8.13/0041-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
@@ -0,0 +1,69 @@
+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 a92d7d1..4738e3f 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -58,6 +58,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 {
+@@ -69,6 +77,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.8.13/0042-beaglebone-DT-set-default-triggers-for-LEDS.patch b/patches/linux-3.8.13/0042-beaglebone-DT-set-default-triggers-for-LEDS.patch
new file mode 100644
index 0000000..f1d09d8
--- /dev/null
+++ b/patches/linux-3.8.13/0042-beaglebone-DT-set-default-triggers-for-LEDS.patch
@@ -0,0 +1,28 @@
+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 4738e3f..800cd75b 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -85,12 +85,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.8.13/0043-beaglebone-add-a-cpu-led-trigger.patch b/patches/linux-3.8.13/0043-beaglebone-add-a-cpu-led-trigger.patch
new file mode 100644
index 0000000..672ae73
--- /dev/null
+++ b/patches/linux-3.8.13/0043-beaglebone-add-a-cpu-led-trigger.patch
@@ -0,0 +1,21 @@
+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 800cd75b..6dbeff6 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -99,6 +99,7 @@
+ led2 {
+ label = "beaglebone:green:usr2";
+ gpios = <&gpio2 23 0>;
++ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+
diff --git a/patches/linux-3.8.13/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch b/patches/linux-3.8.13/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch
new file mode 100644
index 0000000..549050e
--- /dev/null
+++ b/patches/linux-3.8.13/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch
@@ -0,0 +1,24 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 6 Dec 2012 11:55:52 +0100
+Subject: [PATCH] am33xx DT: add commented out OPP values for ES2.0
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 8fd3648..9059cfc 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -34,6 +34,10 @@
+ */
+ operating-points = <
+ /* kHz uV */
++ /* ES 2.0 Nitro and Turbo OPPs"
++ 1000000 1350000
++ 800000 1300000
++ */
+ 720000 1285000
+ 600000 1225000
+ 500000 1125000
diff --git a/patches/linux-3.8.13/0045-mfd-input-iio-ti_am335x_adc-use-one-structure-for-ti.patch b/patches/linux-3.8.13/0045-mfd-input-iio-ti_am335x_adc-use-one-structure-for-ti.patch
new file mode 100644
index 0000000..6415224
--- /dev/null
+++ b/patches/linux-3.8.13/0045-mfd-input-iio-ti_am335x_adc-use-one-structure-for-ti.patch
@@ -0,0 +1,136 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 12 Jun 2013 18:58:02 +0200
+Subject: [PATCH] mfd: input: iio: ti_am335x_adc: use one structure for
+ ti_tscadc_dev
+
+The mfd driver creates platform data for the child devices and it is the
+ti_tscadc_dev struct. This struct is copied for the two devices.
+The copy of the structure makes a common lock in this structure a little
+less usefull. Therefore the platform data is not a pointer to the
+structure and the same structure is used.
+While doing the change I noticed that the suspend/resume code assumes
+the wrong pointer for ti_tscadc_dev and this has been fixed as well.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 5 +++--
+ drivers/input/touchscreen/ti_am335x_tsc.c | 16 +++++++++-------
+ drivers/mfd/ti_am335x_tscadc.c | 8 ++++----
+ include/linux/mfd/ti_am335x_tscadc.h | 7 +++++++
+ 4 files changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index cd030e1..fde3822 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -140,7 +140,7 @@ static int 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 ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
+ struct mfd_tscadc_board *pdata;
+ int err;
+
+@@ -205,9 +205,10 @@ 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;
++ struct ti_tscadc_dev *tscadc_dev;
+ unsigned int idle;
+
++ tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
+ if (!device_may_wakeup(tscadc_dev->dev)) {
+ idle = tiadc_readl(adc_dev, REG_CTRL);
+ idle &= ~(CNTRLREG_TSCSSENB);
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 51e7b87..16077d3 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -262,7 +262,7 @@ static int titsc_probe(struct platform_device *pdev)
+ {
+ struct titsc *ts_dev;
+ struct input_dev *input_dev;
+- struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
++ struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
+ struct mfd_tscadc_board *pdata;
+ int err;
+
+@@ -329,8 +329,8 @@ err_free_mem:
+
+ static int titsc_remove(struct platform_device *pdev)
+ {
+- struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
+- struct titsc *ts_dev = tscadc_dev->tsc;
++ struct titsc *ts_dev = platform_get_drvdata(pdev);
++ u32 steps;
+
+ free_irq(ts_dev->irq, ts_dev);
+
+@@ -344,10 +344,11 @@ static int titsc_remove(struct platform_device *pdev)
+ #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;
++ struct titsc *ts_dev = dev_get_drvdata(dev);
++ struct ti_tscadc_dev *tscadc_dev;
+ unsigned int idle;
+
++ tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
+ if (device_may_wakeup(tscadc_dev->dev)) {
+ idle = titsc_readl(ts_dev, REG_IRQENABLE);
+ titsc_writel(ts_dev, REG_IRQENABLE,
+@@ -359,9 +360,10 @@ static int titsc_suspend(struct device *dev)
+
+ static int titsc_resume(struct device *dev)
+ {
+- struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
+- struct titsc *ts_dev = tscadc_dev->tsc;
++ struct titsc *ts_dev = dev_get_drvdata(dev);
++ struct ti_tscadc_dev *tscadc_dev;
+
++ tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
+ if (device_may_wakeup(tscadc_dev->dev)) {
+ titsc_writel(ts_dev, REG_IRQWAKEUP,
+ 0x00);
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index e9f3fb5..772ea2a 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -176,14 +176,14 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ /* TSC Cell */
+ cell = &tscadc->cells[TSC_CELL];
+ cell->name = "tsc";
+- cell->platform_data = tscadc;
+- cell->pdata_size = sizeof(*tscadc);
++ 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);
++ cell->platform_data = &tscadc;
++ cell->pdata_size = sizeof(tscadc);
+
+ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+ TSCADC_CELLS, NULL, 0, NULL);
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index c79ad5d..8114e4e 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -149,4 +149,11 @@ struct ti_tscadc_dev {
+ struct adc_device *adc;
+ };
+
++static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
++{
++ struct ti_tscadc_dev **tscadc_dev = p->dev.platform_data;
++
++ return *tscadc_dev;
++}
++
+ #endif
diff --git a/patches/linux-3.8.13/0046-input-ti_am33x_tsc-Step-enable-bits-made-configurabl.patch b/patches/linux-3.8.13/0046-input-ti_am33x_tsc-Step-enable-bits-made-configurabl.patch
new file mode 100644
index 0000000..6091b4c
--- /dev/null
+++ b/patches/linux-3.8.13/0046-input-ti_am33x_tsc-Step-enable-bits-made-configurabl.patch
@@ -0,0 +1,215 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Wed, 12 Jun 2013 18:58:03 +0200
+Subject: [PATCH] input: ti_am33x_tsc: Step enable bits made 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.
+
+Sebastian added the common lock and moved the code, that manipulates the
+steps, from into the mfd module.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 20 ++++++++++++++++++--
+ drivers/input/touchscreen/ti_am335x_tsc.c | 12 ++++++++++--
+ drivers/mfd/ti_am335x_tscadc.c | 29 ++++++++++++++++++++++++++++-
+ include/linux/mfd/ti_am335x_tscadc.h | 8 ++++++--
+ 4 files changed, 62 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index fde3822..b47594d 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -42,10 +42,20 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
+ writel(val, adc->mfd_tscadc->tscadc_base + reg);
+ }
+
++static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
++{
++ u32 step_en;
++
++ step_en = ((1 << adc_dev->channels) - 1);
++ step_en <<= TOTAL_STEPS - adc_dev->channels + 1;
++ return step_en;
++}
++
+ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ {
+ unsigned int stepconfig;
+ int i, channels = 0, steps;
++ u32 step_en;
+
+ /*
+ * There are 16 configurable steps and 8 analog input
+@@ -69,7 +79,8 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ STEPCONFIG_OPENDLY);
+ channels++;
+ }
+- tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
++ step_en = get_adc_step_mask(adc_dev);
++ am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+ }
+
+ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+@@ -127,7 +138,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ if (i == chan->channel)
+ *val = readx1 & 0xfff;
+ }
+- tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
++ am335x_tsc_se_update(adc_dev->mfd_tscadc);
+
+ return IIO_VAL_INT;
+ }
+@@ -191,10 +202,15 @@ err_ret:
+ static int tiadc_remove(struct platform_device *pdev)
+ {
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
++ u32 step_en;
+
+ iio_device_unregister(indio_dev);
+ tiadc_channels_remove(indio_dev);
+
++ step_en = get_adc_step_mask(adc_dev);
++ am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
++
+ iio_device_free(indio_dev);
+
+ return 0;
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 16077d3..23d6a4d 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -57,6 +57,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 +129,9 @@ 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);
++ /* The steps1 … end and bit 0 for TS_Charge */
++ stepenable = (1 << (total_steps + 2)) - 1;
++ am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
+ }
+
+ static void titsc_read_coordinates(struct titsc *ts_dev,
+@@ -250,7 +253,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);
++ am335x_tsc_se_update(ts_dev->mfd_tscadc);
+ return IRQ_HANDLED;
+ }
+
+@@ -334,6 +337,11 @@ static int titsc_remove(struct platform_device *pdev)
+
+ free_irq(ts_dev->irq, ts_dev);
+
++ /* total steps followed by the enable mask */
++ steps = 2 * ts_dev->steps_to_configure + 2;
++ steps = (1 << steps) - 1;
++ am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
++
+ input_unregister_device(ts_dev->input);
+
+ platform_set_drvdata(pdev, NULL);
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index 772ea2a..90ccfc0 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -48,6 +48,32 @@ static const struct regmap_config tscadc_regmap_config = {
+ .val_bits = 32,
+ };
+
++void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
++{
++ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
++}
++EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
++
++void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
++{
++ spin_lock(&tsadc->reg_lock);
++ tsadc->reg_se_cache |= val;
++ spin_unlock(&tsadc->reg_lock);
++
++ am335x_tsc_se_update(tsadc);
++}
++EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
++
++void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
++{
++ spin_lock(&tsadc->reg_lock);
++ tsadc->reg_se_cache &= ~val;
++ spin_unlock(&tsadc->reg_lock);
++
++ am335x_tsc_se_update(tsadc);
++}
++EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
++
+ static void tscadc_idle_config(struct ti_tscadc_dev *config)
+ {
+ unsigned int idleconfig;
+@@ -129,6 +155,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ goto ret;
+ }
+
++ spin_lock_init(&tscadc->reg_lock);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+
+@@ -239,7 +266,7 @@ static int tscadc_resume(struct device *dev)
+ CNTRLREG_STEPID | CNTRLREG_4WIRE;
+ tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
+ tscadc_idle_config(tscadc_dev);
+- tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB);
++ am335x_tsc_se_update(tscadc_dev);
+ restore = tscadc_readl(tscadc_dev, REG_CTRL);
+ tscadc_writel(tscadc_dev, REG_CTRL,
+ (restore | CNTRLREG_TSCSSENB));
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index 8114e4e..4258627 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -46,8 +46,6 @@
+ /* Step Enable */
+ #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)
+@@ -141,6 +139,8 @@ struct ti_tscadc_dev {
+ void __iomem *tscadc_base;
+ int irq;
+ struct mfd_cell cells[TSCADC_CELLS];
++ u32 reg_se_cache;
++ spinlock_t reg_lock;
+
+ /* tsc device */
+ struct titsc *tsc;
+@@ -156,4 +156,8 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
+ return *tscadc_dev;
+ }
+
++void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc);
++void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val);
++void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
++
+ #endif
diff --git a/patches/linux-3.8.13/0047-input-ti_am33x_tsc-Order-of-TSC-wires-made-configura.patch b/patches/linux-3.8.13/0047-input-ti_am33x_tsc-Order-of-TSC-wires-made-configura.patch
new file mode 100644
index 0000000..c3c2e22
--- /dev/null
+++ b/patches/linux-3.8.13/0047-input-ti_am33x_tsc-Order-of-TSC-wires-made-configura.patch
@@ -0,0 +1,257 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Wed, 12 Jun 2013 18:58:04 +0200
+Subject: [PATCH] input: ti_am33x_tsc: Order of TSC wires, made configurable
+
+The current driver expected touchscreen input
+wires(XP,XN,YP,YN) to be connected in a particular order.
+Making changes to accept this as platform data.
+
+Sebastian reworked the original patch and removed a lot of the not
+required pieces.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 102 ++++++++++++++++++++++++-----
+ include/linux/input/ti_am335x_tsc.h | 12 ++++
+ include/linux/mfd/ti_am335x_tscadc.h | 3 -
+ 3 files changed, 98 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 23d6a4d..2bdd66c 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -33,6 +33,13 @@
+ #define SEQ_SETTLE 275
+ #define MAX_12BIT ((1 << 12) - 1)
+
++static const int config_pins[] = {
++ STEPCONFIG_XPP,
++ STEPCONFIG_XNN,
++ STEPCONFIG_YPP,
++ STEPCONFIG_YNN,
++};
++
+ struct titsc {
+ struct input_dev *input;
+ struct ti_tscadc_dev *mfd_tscadc;
+@@ -41,6 +48,9 @@ struct titsc {
+ unsigned int x_plate_resistance;
+ bool pen_down;
+ int steps_to_configure;
++ u32 config_inp[4];
++ u32 bit_xp, bit_xn, bit_yp, bit_yn;
++ u32 inp_xp, inp_xn, inp_yp, inp_yn;
+ };
+
+ static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+@@ -54,6 +64,58 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ writel(val, tsc->mfd_tscadc->tscadc_base + reg);
+ }
+
++static int titsc_config_wires(struct titsc *ts_dev)
++{
++ u32 analog_line[4];
++ u32 wire_order[4];
++ int i, bit_cfg;
++
++ 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) >> 4;
++ wire_order[i] = ts_dev->config_inp[i] & 0x0F;
++ if (WARN_ON(analog_line[i] > 7))
++ return -EINVAL;
++ if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
++ return -EINVAL;
++ }
++
++ for (i = 0; i < 4; i++) {
++ int an_line;
++ int wi_order;
++
++ an_line = analog_line[i];
++ wi_order = wire_order[i];
++ bit_cfg = config_pins[wi_order];
++ if (bit_cfg == 0)
++ return -EINVAL;
++ switch (wi_order) {
++ case 0:
++ ts_dev->bit_xp = bit_cfg;
++ ts_dev->inp_xp = an_line;
++ break;
++
++ case 1:
++ ts_dev->bit_xn = bit_cfg;
++ ts_dev->inp_xn = an_line;
++ break;
++
++ case 2:
++ ts_dev->bit_yp = bit_cfg;
++ ts_dev->inp_yp = an_line;
++ break;
++ case 3:
++ ts_dev->bit_yn = bit_cfg;
++ ts_dev->inp_yn = an_line;
++ break;
++ }
++ }
++ return 0;
++}
++
+ static void titsc_step_config(struct titsc *ts_dev)
+ {
+ unsigned int config;
+@@ -64,18 +126,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;
+ }
+
+@@ -86,18 +148,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;
+ }
+
+@@ -108,9 +170,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);
+@@ -118,13 +180,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);
+@@ -292,6 +355,8 @@ static int 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);
+@@ -301,6 +366,11 @@ static int 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);
+
+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 4258627..e36ae41 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -71,8 +71,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)
+@@ -94,7 +92,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)
diff --git a/patches/linux-3.8.13/0048-input-ti_am33x_tsc-remove-unwanted-fifo-flush.patch b/patches/linux-3.8.13/0048-input-ti_am33x_tsc-remove-unwanted-fifo-flush.patch
new file mode 100644
index 0000000..0f1364d
--- /dev/null
+++ b/patches/linux-3.8.13/0048-input-ti_am33x_tsc-remove-unwanted-fifo-flush.patch
@@ -0,0 +1,42 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Wed, 12 Jun 2013 18:58:05 +0200
+Subject: [PATCH] input: ti_am33x_tsc: remove unwanted fifo flush
+
+When touchscreen and ADC are used together, this
+unwanted fifo flush leads to loss of ADC data.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 2bdd66c..7b7de60 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -252,8 +252,6 @@ 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) {
+@@ -262,14 +260,6 @@ 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
diff --git a/patches/linux-3.8.13/0049-input-ti_am33x_tsc-Add-DT-support.patch b/patches/linux-3.8.13/0049-input-ti_am33x_tsc-Add-DT-support.patch
new file mode 100644
index 0000000..2224465
--- /dev/null
+++ b/patches/linux-3.8.13/0049-input-ti_am33x_tsc-Add-DT-support.patch
@@ -0,0 +1,312 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Wed, 12 Jun 2013 18:58:06 +0200
+Subject: [PATCH] input: ti_am33x_tsc: Add DT support
+
+This patch adds DT support to touch driver. It also provides a binding
+document which is used by the MFD and IIO part of the device.
+This patch also renames steps_to_configure to coordinate_readouts
+because the original name misleads the purpose of the variable.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ .../bindings/input/touchscreen/ti-tsc-adc.txt | 44 ++++++++
+ drivers/input/touchscreen/ti_am335x_tsc.c | 105 +++++++++++++++-----
+ drivers/mfd/ti_am335x_tscadc.c | 1 +
+ include/linux/input/ti_am335x_tsc.h | 2 +-
+ 4 files changed, 128 insertions(+), 24 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
+
+diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
+new file mode 100644
+index 0000000..6a69af6
+--- /dev/null
++++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
+@@ -0,0 +1,44 @@
++* TI - TSC ADC (Touschscreen and analog digital converter)
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++
++Required properties:
++- child "tsc"
++ ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen
++ support on the platform.
++ ti,x-plate-resistance: X plate resistance
++ ti,coordinate-readouts: The sequencer supports a total of 16
++ programmable steps each step is used to
++ read a single coordinate. A single
++ readout is enough but multiple reads can
++ increase the quality.
++ A value of 5 means, 5 reads for X, 5 for
++ Y and 2 for Z (always). This utilises 12
++ of the 16 software steps available. The
++ remaining 4 can be used by the ADC.
++ ti,wire-config: Different boards 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.
++- child "adc"
++ ti,adc-channels: List of analog inputs available for ADC.
++ AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
++
++Example:
++ tscadc: tscadc@44e0d000 {
++ compatible = "ti,ti-tscadc";
++ tsc {
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,coordinate-readouts = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
++ };
++
++ adc {
++ ti,adc-channels = <4 5 6 7>;
++ };
++ }
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 7b7de60..ae8a1ce 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -26,6 +26,8 @@
+ #include <linux/io.h>
+ #include <linux/input/ti_am335x_tsc.h>
+ #include <linux/delay.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+
+@@ -47,7 +49,7 @@ struct titsc {
+ unsigned int wires;
+ unsigned int x_plate_resistance;
+ bool pen_down;
+- int steps_to_configure;
++ int coordinate_readouts;
+ u32 config_inp[4];
+ u32 bit_xp, bit_xn, bit_yp, bit_yn;
+ u32 inp_xp, inp_xn, inp_yp, inp_yn;
+@@ -123,7 +125,7 @@ static void titsc_step_config(struct titsc *ts_dev)
+ int i, total_steps;
+
+ /* Configure the Step registers */
+- total_steps = 2 * ts_dev->steps_to_configure;
++ total_steps = 2 * ts_dev->coordinate_readouts;
+
+ config = STEPCONFIG_MODE_HWSYNC |
+ STEPCONFIG_AVG_16 | ts_dev->bit_xp;
+@@ -141,7 +143,7 @@ static void titsc_step_config(struct titsc *ts_dev)
+ break;
+ }
+
+- for (i = 1; i <= ts_dev->steps_to_configure; i++) {
++ for (i = 1; i <= ts_dev->coordinate_readouts; i++) {
+ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+@@ -163,7 +165,7 @@ static void titsc_step_config(struct titsc *ts_dev)
+ break;
+ }
+
+- for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
++ for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) {
+ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+@@ -218,7 +220,7 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
+ read = titsc_readl(ts_dev, REG_FIFO0);
+ channel = read & 0xf0000;
+ channel = channel >> 0x10;
+- if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
++ if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) {
+ read &= 0xfff;
+ diff = abs(read - prev_val_x);
+ if (diff < prev_diff_x) {
+@@ -231,8 +233,8 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
+ 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))) {
++ if ((channel >= ts_dev->coordinate_readouts) &&
++ (channel < (2 * ts_dev->coordinate_readouts - 1))) {
+ read &= 0xfff;
+ diff = abs(read - prev_val_y);
+ if (diff < prev_diff_y) {
+@@ -310,6 +312,59 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ return IRQ_HANDLED;
+ }
+
++static int titsc_parse_dt(struct platform_device *pdev,
++ struct titsc *ts_dev)
++{
++ struct device_node *node = pdev->dev.of_node;
++ int err;
++
++ if (!node)
++ return -EINVAL;
++
++ err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
++ if (err < 0)
++ return err;
++ switch (ts_dev->wires) {
++ case 4:
++ case 5:
++ case 8:
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ err = of_property_read_u32(node, "ti,x-plate-resistance",
++ &ts_dev->x_plate_resistance);
++ if (err < 0)
++ return err;
++
++ err = of_property_read_u32(node, "ti,coordinate-readouts",
++ &ts_dev->coordinate_readouts);
++ if (err < 0)
++ return err;
++
++ return of_property_read_u32_array(node, "ti,wire-config",
++ ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
++}
++
++static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev,
++ struct titsc *ts_dev)
++{
++ struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data;
++
++ if (!pdata)
++ return -EINVAL;
++
++ ts_dev->wires = pdata->tsc_init->wires;
++ ts_dev->x_plate_resistance =
++ pdata->tsc_init->x_plate_resistance;
++ ts_dev->coordinate_readouts =
++ pdata->tsc_init->coordinate_readouts;
++ memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
++ sizeof(pdata->tsc_init->wire_config));
++ return 0;
++}
++
+ /*
+ * The functions for inserting/removing driver as a module.
+ */
+@@ -319,16 +374,8 @@ static int titsc_probe(struct platform_device *pdev)
+ struct titsc *ts_dev;
+ struct input_dev *input_dev;
+ struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
+- struct mfd_tscadc_board *pdata;
+ int err;
+
+- pdata = tscadc_dev->dev->platform_data;
+-
+- if (!pdata) {
+- dev_err(&pdev->dev, "Could not find platform data\n");
+- return -EINVAL;
+- }
+-
+ /* Allocate memory for device */
+ ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
+ input_dev = input_allocate_device();
+@@ -342,11 +389,16 @@ static int titsc_probe(struct platform_device *pdev)
+ ts_dev->mfd_tscadc = tscadc_dev;
+ ts_dev->input = input_dev;
+ 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;
+- memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
+- sizeof(pdata->tsc_init->wire_config));
++
++ if (tscadc_dev->dev->platform_data)
++ err = titsc_parse_pdata(tscadc_dev, ts_dev);
++ else
++ err = titsc_parse_dt(pdev, ts_dev);
++
++ if (err) {
++ dev_err(&pdev->dev, "Could not find valid DT data.\n");
++ goto err_free_mem;
++ }
+
+ err = request_irq(ts_dev->irq, titsc_irq,
+ 0, pdev->dev.driver->name, ts_dev);
+@@ -362,7 +414,7 @@ static int titsc_probe(struct platform_device *pdev)
+ goto err_free_irq;
+ }
+ titsc_step_config(ts_dev);
+- titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
++ titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts);
+
+ input_dev->name = "ti-tsc";
+ input_dev->dev.parent = &pdev->dev;
+@@ -398,7 +450,7 @@ static int titsc_remove(struct platform_device *pdev)
+ free_irq(ts_dev->irq, ts_dev);
+
+ /* total steps followed by the enable mask */
+- steps = 2 * ts_dev->steps_to_configure + 2;
++ steps = 2 * ts_dev->coordinate_readouts + 2;
+ steps = (1 << steps) - 1;
+ am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
+
+@@ -439,7 +491,7 @@ static int titsc_resume(struct device *dev)
+ }
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR,
+- ts_dev->steps_to_configure);
++ ts_dev->coordinate_readouts);
+ return 0;
+ }
+
+@@ -452,6 +504,12 @@ static const struct dev_pm_ops titsc_pm_ops = {
+ #define TITSC_PM_OPS NULL
+ #endif
+
++static const struct of_device_id ti_tsc_dt_ids[] = {
++ { .compatible = "ti,ti-tscadc", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
++
+ static struct platform_driver ti_tsc_driver = {
+ .probe = titsc_probe,
+ .remove = titsc_remove,
+@@ -459,6 +517,7 @@ static struct platform_driver ti_tsc_driver = {
+ .name = "tsc",
+ .owner = THIS_MODULE,
+ .pm = TITSC_PM_OPS,
++ .of_match_table = of_match_ptr(ti_tsc_dt_ids),
+ },
+ };
+ module_platform_driver(ti_tsc_driver);
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index 90ccfc0..ebce3d39 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -203,6 +203,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ /* TSC Cell */
+ cell = &tscadc->cells[TSC_CELL];
+ cell->name = "tsc";
++ cell->of_compatible = "ti,ti-tscadc";
+ cell->platform_data = &tscadc;
+ cell->pdata_size = sizeof(tscadc);
+
+diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
+index 6a66b4d..c0bf08b 100644
+--- a/include/linux/input/ti_am335x_tsc.h
++++ b/include/linux/input/ti_am335x_tsc.h
+@@ -28,7 +28,7 @@
+ struct tsc_data {
+ int wires;
+ int x_plate_resistance;
+- int steps_to_configure;
++ int coordinate_readouts;
+ int wire_config[10];
+ };
+
diff --git a/patches/linux-3.8.13/0050-iio-ti_am335x_adc-Add-DT-support.patch b/patches/linux-3.8.13/0050-iio-ti_am335x_adc-Add-DT-support.patch
new file mode 100644
index 0000000..80b44a4
--- /dev/null
+++ b/patches/linux-3.8.13/0050-iio-ti_am335x_adc-Add-DT-support.patch
@@ -0,0 +1,96 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Wed, 12 Jun 2013 18:58:08 +0200
+Subject: [PATCH] iio: ti_am335x_adc: Add DT support
+
+Add DT support for client ADC driver.
+
+Acked-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 29 ++++++++++++++++++++++++-----
+ drivers/mfd/ti_am335x_tscadc.c | 1 +
+ 2 files changed, 25 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index b47594d..4f4c82e 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -22,6 +22,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/iio/iio.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/platform_data/ti_am335x_adc.h>
+@@ -152,11 +154,12 @@ static int tiadc_probe(struct platform_device *pdev)
+ struct iio_dev *indio_dev;
+ struct tiadc_device *adc_dev;
+ struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
+- struct mfd_tscadc_board *pdata;
++ struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data;
++ struct device_node *node = tscadc_dev->dev->of_node;
+ int err;
++ u32 val32;
+
+- pdata = tscadc_dev->dev->platform_data;
+- if (!pdata || !pdata->adc_init) {
++ if (!pdata && !node) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+@@ -169,8 +172,17 @@ static int tiadc_probe(struct platform_device *pdev)
+ }
+ adc_dev = iio_priv(indio_dev);
+
+- adc_dev->mfd_tscadc = tscadc_dev;
+- adc_dev->channels = pdata->adc_init->adc_channels;
++ adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
++
++ if (pdata)
++ adc_dev->channels = pdata->adc_init->adc_channels;
++ else {
++ err = of_property_read_u32(node,
++ "ti,adc-channels", &val32);
++ if (err < 0)
++ goto err_free_device;
++ adc_dev->channels = val32;
++ }
+
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->name = dev_name(&pdev->dev);
+@@ -260,11 +272,18 @@ static const struct dev_pm_ops tiadc_pm_ops = {
+ #define TIADC_PM_OPS NULL
+ #endif
+
++static const struct of_device_id ti_adc_dt_ids[] = {
++ { .compatible = "ti,ti-tscadc", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
++
+ static struct platform_driver tiadc_driver = {
+ .driver = {
+ .name = "tiadc",
+ .owner = THIS_MODULE,
+ .pm = TIADC_PM_OPS,
++ .of_match_table = of_match_ptr(ti_adc_dt_ids),
+ },
+ .probe = tiadc_probe,
+ .remove = tiadc_remove,
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index ebce3d39..cca6a6c 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -210,6 +210,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ /* ADC Cell */
+ cell = &tscadc->cells[ADC_CELL];
+ cell->name = "tiadc";
++ cell->of_compatible = "ti,ti-tscadc";
+ cell->platform_data = &tscadc;
+ cell->pdata_size = sizeof(tscadc);
+
diff --git a/patches/linux-3.8.13/0051-arm-dts-AM335x-evm-Add-TSC-ADC-MFD-device-support.patch b/patches/linux-3.8.13/0051-arm-dts-AM335x-evm-Add-TSC-ADC-MFD-device-support.patch
new file mode 100644
index 0000000..00d8350
--- /dev/null
+++ b/patches/linux-3.8.13/0051-arm-dts-AM335x-evm-Add-TSC-ADC-MFD-device-support.patch
@@ -0,0 +1,52 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Thu, 24 Jan 2013 03:45:12 +0000
+Subject: [PATCH] arm/dts: AM335x-evm: Add TSC/ADC MFD device support
+
+Add support for core multifunctional device along
+with its clients touchscreen and ADC.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ arch/arm/boot/dts/am335x-evm.dts | 13 +++++++++++++
+ arch/arm/boot/dts/am33xx.dtsi | 8 ++++++++
+ 2 files changed, 21 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 0dda333..b1aeefb 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -270,3 +270,16 @@
+ reg = <0>;
+ };
+ };
++
++&tscadc {
++ tsc {
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,steps-to-configure = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
++ };
++
++ adc {
++ ti,adc-channels = <4>;
++ };
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 9059cfc..47ac3d2 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -447,5 +447,13 @@
+ mac-address = [ 00 00 00 00 00 00 ];
+ };
+ };
++
++ tscadc: tscadc@44e0d000 {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0052-mfd-ti_am335x_tscadc-Add-DT-support.patch b/patches/linux-3.8.13/0052-mfd-ti_am335x_tscadc-Add-DT-support.patch
new file mode 100644
index 0000000..32760dd
--- /dev/null
+++ b/patches/linux-3.8.13/0052-mfd-ti_am335x_tscadc-Add-DT-support.patch
@@ -0,0 +1,86 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Wed, 12 Jun 2013 18:58:10 +0200
+Subject: [PATCH] mfd: ti_am335x_tscadc: Add DT support
+
+Add DT support in the MFD core driver. The node name is "am3359" because
+it was tested on this platform.
+
+Zubair Lutfullah: Reversed the change to am3359-tsc to ti-tscadc to keep from further changes in DT
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/mfd/ti_am335x_tscadc.c | 30 +++++++++++++++++++++++++-----
+ 1 file changed, 25 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index cca6a6c..0fc5867 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -22,6 +22,8 @@
+ #include <linux/regmap.h>
+ #include <linux/mfd/core.h>
+ #include <linux/pm_runtime.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/input/ti_am335x_tsc.h>
+@@ -90,20 +92,31 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ struct resource *res;
+ struct clk *clk;
+ struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
++ struct device_node *node = pdev->dev.of_node;
+ struct mfd_cell *cell;
+ 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) {
++ if (!pdata && !pdev->dev.of_node) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+
+- if (pdata->adc_init)
+- adc_channels = pdata->adc_init->adc_channels;
++ if (pdev->dev.platform_data) {
++ if (pdata->tsc_init)
++ tsc_wires = pdata->tsc_init->wires;
++
++ if (pdata->adc_init)
++ adc_channels = pdata->adc_init->adc_channels;
++ } else {
++ node = of_get_child_by_name(pdev->dev.of_node, "tsc");
++ of_property_read_u32(node, "ti,wires", &tsc_wires);
++
++ node = of_get_child_by_name(pdev->dev.of_node, "adc");
++ of_property_read_u32(node, "ti,adc-channels", &adc_channels);
++ }
+
+- tsc_wires = pdata->tsc_init->wires;
+ total_channels = tsc_wires + adc_channels;
+
+ if (total_channels > 8) {
+@@ -285,11 +298,18 @@ static const struct dev_pm_ops tscadc_pm_ops = {
+ #define TSCADC_PM_OPS NULL
+ #endif
+
++static const struct of_device_id ti_tscadc_dt_ids[] = {
++ { .compatible = "ti,ti-tscadc", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
++
+ static struct platform_driver ti_tscadc_driver = {
+ .driver = {
+ .name = "ti_tscadc",
+ .owner = THIS_MODULE,
+ .pm = TSCADC_PM_OPS,
++ .of_match_table = of_match_ptr(ti_tscadc_dt_ids),
+ },
+ .probe = ti_tscadc_probe,
+ .remove = ti_tscadc_remove,
diff --git a/patches/linux-3.8.13/0053-iio-ti_tscadc-provide-datasheet_name-and-scan_type.patch b/patches/linux-3.8.13/0053-iio-ti_tscadc-provide-datasheet_name-and-scan_type.patch
new file mode 100644
index 0000000..8345713
--- /dev/null
+++ b/patches/linux-3.8.13/0053-iio-ti_tscadc-provide-datasheet_name-and-scan_type.patch
@@ -0,0 +1,85 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 12 Jun 2013 18:58:12 +0200
+Subject: [PATCH] iio: ti_tscadc: provide datasheet_name and scan_type
+
+This patch provides the members "datasheet_name" and scan_type. This is
+the remaining part of the earlier patch where I (bigeasy) removed iio_map
+because it is now supplied by the device tree. It also static names as
+suggested by Jonathan.
+
+ZubairLK. Channel Info mask tweaked to fit the old IIO usage.
+Tweaked surrounding code to patch the 3.8 tree.
+
+Acked-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 29 ++++++++++++++++++++++++-----
+ 1 file changed, 24 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index 4f4c82e..25feb62 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -24,6 +24,8 @@
+ #include <linux/iio/iio.h>
+ #include <linux/of.h>
+ #include <linux/of_device.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>
+@@ -85,29 +87,46 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+ }
+
++static const char * const chan_name_ain[] = {
++ "AIN0",
++ "AIN1",
++ "AIN2",
++ "AIN3",
++ "AIN4",
++ "AIN5",
++ "AIN6",
++ "AIN7",
++};
++
+ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+ {
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ struct iio_chan_spec *chan_array;
++ struct iio_chan_spec *chan;
+ int i;
+
+ indio_dev->num_channels = channels;
+- chan_array = kcalloc(indio_dev->num_channels,
++ chan_array = kcalloc(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 = chan_array;
++ for (i = 0; i < channels; i++, chan++) {
++
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+ chan->channel = i;
+ chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
++ chan->datasheet_name = chan_name_ain[i];
++ chan->scan_type.sign = 'u';
++ chan->scan_type.realbits = 12;
++ chan->scan_type.storagebits = 32;
+ }
+
+ indio_dev->channels = chan_array;
+
+- return indio_dev->num_channels;
++ return 0;
+ }
+
+ static void tiadc_channels_remove(struct iio_dev *indio_dev)
diff --git a/patches/linux-3.8.13/0054-mfd-ti_tscadc-deal-with-partial-activation.patch b/patches/linux-3.8.13/0054-mfd-ti_tscadc-deal-with-partial-activation.patch
new file mode 100644
index 0000000..132ab96
--- /dev/null
+++ b/patches/linux-3.8.13/0054-mfd-ti_tscadc-deal-with-partial-activation.patch
@@ -0,0 +1,110 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 12 Jun 2013 18:58:13 +0200
+Subject: [PATCH] mfd: ti_tscadc: deal with partial activation
+
+Fix the mfd device in the case where a subdevice might not be activated.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/mfd/ti_am335x_tscadc.c | 38 ++++++++++++++++++++++------------
+ include/linux/mfd/ti_am335x_tscadc.h | 8 +++----
+ 2 files changed, 28 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index 0fc5867..58f0860 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -118,11 +118,14 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ }
+
+ 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;
+ }
++ if (total_channels == 0) {
++ dev_err(&pdev->dev, "Need atleast one channel.\n");
++ return -EINVAL;
++ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+@@ -213,28 +216,37 @@ static int 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->of_compatible = "ti,ti-tscadc";
+- 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->of_compatible = "ti,ti-tscadc";
++ cell->platform_data = &tscadc;
++ cell->pdata_size = sizeof(tscadc);
++ }
+
+ /* ADC Cell */
+- cell = &tscadc->cells[ADC_CELL];
+- cell->name = "tiadc";
+- cell->of_compatible = "ti,ti-tscadc";
+- 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->of_compatible = "ti,ti-tscadc";
++ 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);
+-
+ return 0;
+
+ err_disable_clk:
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index e36ae41..fe54ba4 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -120,11 +120,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;
+@@ -135,6 +130,9 @@ struct ti_tscadc_dev {
+ struct regmap *regmap_tscadc;
+ void __iomem *tscadc_base;
+ int irq;
++ int used_cells; /* 1-2 */
++ int tsc_cell; /* -1 if not used */
++ int adc_cell; /* -1 if not used */
+ struct mfd_cell cells[TSCADC_CELLS];
+ u32 reg_se_cache;
+ spinlock_t reg_lock;
diff --git a/patches/linux-3.8.13/0055-input-ti_am335x_adc-use-only-FIFO0-and-clean-up-a-li.patch b/patches/linux-3.8.13/0055-input-ti_am335x_adc-use-only-FIFO0-and-clean-up-a-li.patch
new file mode 100644
index 0000000..491482b
--- /dev/null
+++ b/patches/linux-3.8.13/0055-input-ti_am335x_adc-use-only-FIFO0-and-clean-up-a-li.patch
@@ -0,0 +1,261 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 12 Jun 2013 18:58:18 +0200
+Subject: [PATCH] input: ti_am335x_adc: use only FIFO0 and clean up a little
+
+The driver programs a threshold of "coordinate_readouts" say 5. The
+REG_FIFO0THR registers says it should it be programmed to "threshold
+minus one". The driver does not expect just 5 coordinates but 5 * 2 + 2.
+Multiplied by two because 5 for X and 5 for Y and plus 2 because we have
+two Z.
+The whole thing kind of works because It reads the 5 coordinates for X
+and Y from FIFO0 and FIFO1 and the last element in each FIFO is ignored
+within the loop and read later.
+Nothing guaranties that FIFO1 is ready by the time it is read. In fact I
+could see that that FIFO1 reaturns for Y channels 8,9, 10, 12, 6 and for
+Y channel 7 for Z. The problem is that channel 7 and channel 12 got
+somehow mixed up.
+The other Problem is that FIFO1 is also used by the IIO part leading to
+wrong results if both (tsc & adc) are used.
+
+The patch tries to clean up the whole thing a little:
+- Remove the +1 and -1 in REG_STEPCONFIG, REG_STEPDELAY and its counter
+ part in the for loop. This is just confusing.
+
+- Use only FIFO0 in TSC. The fifo has space for 64 entries so should be
+ fine.
+
+- Read the whole FIFO in one function and check the channel.
+
+- in case we dawdle around, make sure we only read a multiple of our
+ coordinate set. On the second interrupt we will cleanup the remaining
+ enties.
+
+Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 2 +-
+ drivers/input/touchscreen/ti_am335x_tsc.c | 78 +++++++++++++++--------------
+ include/linux/mfd/ti_am335x_tscadc.h | 4 +-
+ 3 files changed, 44 insertions(+), 40 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index 25feb62..c4682d6 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -76,7 +76,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+
+ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+
+- for (i = (steps + 1); i <= TOTAL_STEPS; i++) {
++ for (i = steps; i < TOTAL_STEPS; i++) {
+ tiadc_writel(adc_dev, REG_STEPCONFIG(i),
+ stepconfig | STEPCONFIG_INP(channels));
+ tiadc_writel(adc_dev, REG_STEPDELAY(i),
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index ae8a1ce..6c333af 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -121,11 +121,9 @@ static int titsc_config_wires(struct titsc *ts_dev)
+ static void titsc_step_config(struct titsc *ts_dev)
+ {
+ unsigned int config;
+- unsigned int stepenable = 0;
+- int i, total_steps;
+-
+- /* Configure the Step registers */
+- total_steps = 2 * ts_dev->coordinate_readouts;
++ int i;
++ int end_step;
++ u32 stepenable;
+
+ config = STEPCONFIG_MODE_HWSYNC |
+ STEPCONFIG_AVG_16 | ts_dev->bit_xp;
+@@ -143,7 +141,9 @@ static void titsc_step_config(struct titsc *ts_dev)
+ break;
+ }
+
+- for (i = 1; i <= ts_dev->coordinate_readouts; i++) {
++ /* 1 … coordinate_readouts is for X */
++ end_step = ts_dev->coordinate_readouts;
++ for (i = 0; i < end_step; i++) {
+ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+@@ -151,7 +151,7 @@ static void titsc_step_config(struct titsc *ts_dev)
+ config = 0;
+ config = STEPCONFIG_MODE_HWSYNC |
+ STEPCONFIG_AVG_16 | ts_dev->bit_yn |
+- STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
++ STEPCONFIG_INM_ADCREFM;
+ switch (ts_dev->wires) {
+ case 4:
+ config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
+@@ -165,12 +165,13 @@ static void titsc_step_config(struct titsc *ts_dev)
+ break;
+ }
+
+- for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) {
++ /* coordinate_readouts … coordinate_readouts * 2 is for Y */
++ end_step = ts_dev->coordinate_readouts * 2;
++ for (i = ts_dev->coordinate_readouts; i < end_step; i++) {
+ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+
+- config = 0;
+ /* Charge step configuration */
+ config = ts_dev->bit_xp | ts_dev->bit_yn |
+ STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
+@@ -179,35 +180,39 @@ static void titsc_step_config(struct titsc *ts_dev)
+ titsc_writel(ts_dev, REG_CHARGECONFIG, config);
+ titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+
+- config = 0;
+- /* Configure to calculate pressure */
++ /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
+ config = STEPCONFIG_MODE_HWSYNC |
+ 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),
++ titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(end_step),
+ STEPCONFIG_OPENDLY);
+
+- 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),
++ end_step++;
++ config |= STEPCONFIG_INP(ts_dev->inp_yn);
++ titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(end_step),
+ STEPCONFIG_OPENDLY);
+
+ /* The steps1 … end and bit 0 for TS_Charge */
+- stepenable = (1 << (total_steps + 2)) - 1;
++ stepenable = (1 << (end_step + 2)) - 1;
+ am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
+ }
+
+ static void titsc_read_coordinates(struct titsc *ts_dev,
+- unsigned int *x, unsigned int *y)
++ u32 *x, u32 *y, u32 *z1, u32 *z2)
+ {
+ 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, channel;
++ unsigned int creads = ts_dev->coordinate_readouts;
+
++ *z1 = *z2 = 0;
++ if (fifocount % (creads * 2 + 2))
++ fifocount -= fifocount % (creads * 2 + 2);
+ /*
+ * Delta filter is used to remove large variations in sampled
+ * values from ADC. The filter tries to predict where the next
+@@ -216,32 +221,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
+ * 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++) {
++ for (i = 0; i < fifocount; i++) {
+ read = titsc_readl(ts_dev, REG_FIFO0);
+- channel = read & 0xf0000;
+- channel = channel >> 0x10;
+- if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) {
+- read &= 0xfff;
++
++ channel = (read & 0xf0000) >> 16;
++ read &= 0xfff;
++ if (channel < creads) {
+ 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);
+- channel = read & 0xf0000;
+- channel = channel >> 0x10;
+- if ((channel >= ts_dev->coordinate_readouts) &&
+- (channel < (2 * ts_dev->coordinate_readouts - 1))) {
+- read &= 0xfff;
++ } else if (channel < creads * 2) {
+ diff = abs(read - prev_val_y);
+ if (diff < prev_diff_y) {
+ prev_diff_y = diff;
+ *y = read;
+ }
+ prev_val_y = read;
++
++ } else if (channel < creads * 2 + 1) {
++ *z1 = read;
++
++ } else if (channel < creads * 2 + 2) {
++ *z2 = read;
+ }
+ }
+ }
+@@ -257,10 +262,8 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+
+ 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;
++ titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
+
+ if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
+ /*
+@@ -268,10 +271,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ * Resistance(touch) = x plate resistance *
+ * x postion/4096 * ((z2 / z1) - 1)
+ */
+- z = z2 - z1;
++ z = z1 - z2;
+ z *= x;
+ z *= ts_dev->x_plate_resistance;
+- z /= z1;
++ z /= z2;
+ z = (z + 2047) >> 12;
+
+ if (z <= MAX_12BIT) {
+@@ -414,7 +417,8 @@ static int titsc_probe(struct platform_device *pdev)
+ goto err_free_irq;
+ }
+ titsc_step_config(ts_dev);
+- titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts);
++ titsc_writel(ts_dev, REG_FIFO0THR,
++ ts_dev->coordinate_readouts * 2 + 2 - 1);
+
+ input_dev->name = "ti-tsc";
+ input_dev->dev.parent = &pdev->dev;
+@@ -491,7 +495,7 @@ static int titsc_resume(struct device *dev)
+ }
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR,
+- ts_dev->coordinate_readouts);
++ ts_dev->coordinate_readouts * 2 + 2 - 1);
+ return 0;
+ }
+
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index fe54ba4..9598360 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -30,8 +30,8 @@
+ #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_STEPCONFIG(n) (0x64 + ((n) * 8))
++#define REG_STEPDELAY(n) (0x68 + ((n) * 8))
+ #define REG_FIFO0CNT 0xE4
+ #define REG_FIFO0THR 0xE8
+ #define REG_FIFO1CNT 0xF0
diff --git a/patches/linux-3.8.13/0056-input-ti_am335x_tsc-ACK-the-HW_PEN-irq-in-ISR.patch b/patches/linux-3.8.13/0056-input-ti_am335x_tsc-ACK-the-HW_PEN-irq-in-ISR.patch
new file mode 100644
index 0000000..5fb73ed
--- /dev/null
+++ b/patches/linux-3.8.13/0056-input-ti_am335x_tsc-ACK-the-HW_PEN-irq-in-ISR.patch
@@ -0,0 +1,32 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 12 Jun 2013 18:58:19 +0200
+Subject: [PATCH] input: ti_am335x_tsc: ACK the HW_PEN irq in ISR
+
+The interrupt source IRQENB_HW_PEN is enabled in suspend and suposed to
+be used as a wake up source. Once this interrupt source is unmaksed, the
+devices ends up in ISR and never continues.
+This change ACKs the interrupt and disables it so the system does not
+freeze.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 6c333af..2e9a247 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -309,6 +309,12 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ irqclr |= IRQENB_PENUP;
+ }
+
++ if (status & IRQENB_HW_PEN) {
++
++ titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
++ titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
++ }
++
+ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+
+ am335x_tsc_se_update(ts_dev->mfd_tscadc);
diff --git a/patches/linux-3.8.13/0057-input-ti_am335x_tsc-return-IRQ_NONE-if-there-was-no-.patch b/patches/linux-3.8.13/0057-input-ti_am335x_tsc-return-IRQ_NONE-if-there-was-no-.patch
new file mode 100644
index 0000000..31ea1d3
--- /dev/null
+++ b/patches/linux-3.8.13/0057-input-ti_am335x_tsc-return-IRQ_NONE-if-there-was-no-.patch
@@ -0,0 +1,37 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 12 Jun 2013 18:58:20 +0200
+Subject: [PATCH] input: ti_am335x_tsc: return IRQ_NONE if there was no IRQ
+ for us
+
+The previous patch ("input/ti_am335x_tsc: ACK the HW_PEN irq in ISR")
+acked the interrupt so we don't freeze if we don't handle an enabled
+interrupt source. The interrupt core has a mechanism for this and to get
+it work one should only say that it handled an interrupt if it is
+actually the case.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 2e9a247..5f9801c 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -315,10 +315,12 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
+ }
+
+- titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+-
+- am335x_tsc_se_update(ts_dev->mfd_tscadc);
+- return IRQ_HANDLED;
++ if (irqclr) {
++ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
++ am335x_tsc_se_update(ts_dev->mfd_tscadc);
++ return IRQ_HANDLED;
++ }
++ return IRQ_NONE;
+ }
+
+ static int titsc_parse_dt(struct platform_device *pdev,
diff --git a/patches/linux-3.8.13/0058-iio-ti_am335x_adc-Allow-to-specify-input-line.patch b/patches/linux-3.8.13/0058-iio-ti_am335x_adc-Allow-to-specify-input-line.patch
new file mode 100644
index 0000000..1e2e82a
--- /dev/null
+++ b/patches/linux-3.8.13/0058-iio-ti_am335x_adc-Allow-to-specify-input-line.patch
@@ -0,0 +1,213 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 12 Jun 2013 18:58:21 +0200
+Subject: [PATCH] iio: ti_am335x_adc: Allow to specify input line
+
+The TSC part allows to specify the input lines. The IIO part assumes
+that it usues always the last few, that means if IIO has adc-channels
+set to 2 it will use channel 6 and 7. However it might make sense to use
+only 6.
+This patch changes the device property (which was introduced recently
+and was never in an official release) in a way that the user can specify
+which of the AIN lines should be used. In Addition to this, the name is
+now AINx where x is the channel number i.e. for AIN6 we would have 6.
+Prior this, it always started counting at 0 which is confusing. In
+addition to this, it also checks for correct step number during reading
+and does not rely on proper FIFO depth.
+
+ZubairLK Tweaked channel info mask for old iio. Tweaked surrounding
+code to make it patch the 3.8 tree
+
+Acked-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/arm/boot/dts/am335x-evm.dts | 2 +-
+ drivers/iio/adc/ti_am335x_adc.c | 58 +++++++++++++++++++++++++-------------
+ drivers/mfd/ti_am335x_tscadc.c | 19 ++++++++++++-
+ 3 files changed, 57 insertions(+), 22 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index b1aeefb..5483e09 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -280,6 +280,6 @@
+ };
+
+ adc {
+- ti,adc-channels = <4>;
++ ti,adc-channels = <4 5 6 7>;
+ };
+ };
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index c4682d6..a2b6ebd 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -33,6 +33,8 @@
+ struct tiadc_device {
+ struct ti_tscadc_dev *mfd_tscadc;
+ int channels;
++ u8 channel_line[8];
++ u8 channel_step[8];
+ };
+
+ static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
+@@ -58,7 +60,7 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
+ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ {
+ unsigned int stepconfig;
+- int i, channels = 0, steps;
++ int i, steps;
+ u32 step_en;
+
+ /*
+@@ -72,16 +74,18 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ */
+
+ steps = TOTAL_STEPS - adc_dev->channels;
+- channels = TOTAL_CHANNELS - adc_dev->channels;
+-
+ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+
+- for (i = steps; i < TOTAL_STEPS; i++) {
+- tiadc_writel(adc_dev, REG_STEPCONFIG(i),
+- stepconfig | STEPCONFIG_INP(channels));
+- tiadc_writel(adc_dev, REG_STEPDELAY(i),
++ for (i = 0; i < adc_dev->channels; i++) {
++ int chan;
++
++ chan = adc_dev->channel_line[i];
++ tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
++ stepconfig | STEPCONFIG_INP(chan));
++ tiadc_writel(adc_dev, REG_STEPDELAY(steps),
+ STEPCONFIG_OPENDLY);
+- channels++;
++ adc_dev->channel_step[i] = steps;
++ steps++;
+ }
+ step_en = get_adc_step_mask(adc_dev);
+ am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+@@ -116,9 +120,9 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+- chan->channel = i;
++ chan->channel = adc_dev->channel_line[i];
+ chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+- chan->datasheet_name = chan_name_ain[i];
++ chan->datasheet_name = chan_name_ain[chan->channel];
+ chan->scan_type.sign = 'u';
+ chan->scan_type.realbits = 12;
+ chan->scan_type.storagebits = 32;
+@@ -140,7 +144,8 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ {
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ int i;
+- unsigned int fifo1count, readx1;
++ unsigned int fifo1count, read;
++ u32 step = UINT_MAX;
+
+ /*
+ * When the sub-system is first enabled,
+@@ -153,11 +158,20 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ * Hence we need to flush out this data.
+ */
+
++ for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
++ if (chan->channel == adc_dev->channel_line[i]) {
++ step = adc_dev->channel_step[i];
++ break;
++ }
++ }
++ if (WARN_ON_ONCE(step == UINT_MAX))
++ return -EINVAL;
++
+ 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;
++ read = tiadc_readl(adc_dev, REG_FIFO1);
++ if (read >> 16 == step)
++ *val = read & 0xfff;
+ }
+ am335x_tsc_se_update(adc_dev->mfd_tscadc);
+
+@@ -175,8 +189,11 @@ static int tiadc_probe(struct platform_device *pdev)
+ struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
+ struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data;
+ struct device_node *node = tscadc_dev->dev->of_node;
++ struct property *prop;
++ const __be32 *cur;
+ int err;
+- u32 val32;
++ u32 val;
++ int channels = 0;
+
+ if (!pdata && !node) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+@@ -196,11 +213,12 @@ static int tiadc_probe(struct platform_device *pdev)
+ if (pdata)
+ adc_dev->channels = pdata->adc_init->adc_channels;
+ else {
+- err = of_property_read_u32(node,
+- "ti,adc-channels", &val32);
+- if (err < 0)
+- goto err_free_device;
+- adc_dev->channels = val32;
++ node = of_get_child_by_name(node, "adc");
++ of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
++ adc_dev->channel_line[channels] = val;
++ channels++;
++ }
++ adc_dev->channels = channels;
+ }
+
+ indio_dev->dev.parent = &pdev->dev;
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index 58f0860..640fe10 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -94,9 +94,13 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
+ struct device_node *node = pdev->dev.of_node;
+ struct mfd_cell *cell;
++ struct property *prop;
++ const __be32 *cur;
++ u32 val;
+ int err, ctrl;
+ int clk_value, clock_rate;
+ int tsc_wires = 0, adc_channels = 0, total_channels;
++ int readouts = 0;
+
+ if (!pdata && !pdev->dev.of_node) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+@@ -112,9 +116,17 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ } else {
+ node = of_get_child_by_name(pdev->dev.of_node, "tsc");
+ of_property_read_u32(node, "ti,wires", &tsc_wires);
++ of_property_read_u32(node, "ti,coordinate-readouts", &readouts);
+
+ node = of_get_child_by_name(pdev->dev.of_node, "adc");
+- of_property_read_u32(node, "ti,adc-channels", &adc_channels);
++ of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
++ adc_channels++;
++ if (val > 7) {
++ dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
++ val);
++ return -EINVAL;
++ }
++ }
+ }
+
+ total_channels = tsc_wires + adc_channels;
+@@ -127,6 +139,11 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+ return -EINVAL;
+ }
+
++ if (readouts * 2 + 2 + adc_channels > 16) {
++ dev_err(&pdev->dev, "Too many step configurations requested\n");
++ return -EINVAL;
++ }
++
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no memory resource defined.\n");
diff --git a/patches/linux-3.8.13/0059-iio-ti_am335x_adc-check-if-we-found-the-value.patch b/patches/linux-3.8.13/0059-iio-ti_am335x_adc-check-if-we-found-the-value.patch
new file mode 100644
index 0000000..f904553
--- /dev/null
+++ b/patches/linux-3.8.13/0059-iio-ti_am335x_adc-check-if-we-found-the-value.patch
@@ -0,0 +1,43 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 12 Jun 2013 18:58:22 +0200
+Subject: [PATCH] iio: ti_am335x_adc: check if we found the value
+
+Usually we get all the values we wanted but it is possible, that te ADC
+unit is busy performing the conversation for the HW events. In that case
+-EBUSY is returned and the user may re-call the function.
+
+Acked-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index a2b6ebd..624935c 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -146,6 +146,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ int i;
+ unsigned int fifo1count, read;
+ u32 step = UINT_MAX;
++ bool found = false;
+
+ /*
+ * When the sub-system is first enabled,
+@@ -170,11 +171,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ for (i = 0; i < fifo1count; i++) {
+ read = tiadc_readl(adc_dev, REG_FIFO1);
+- if (read >> 16 == step)
++ if (read >> 16 == step) {
+ *val = read & 0xfff;
++ found = true;
++ }
+ }
+ am335x_tsc_se_update(adc_dev->mfd_tscadc);
+-
++ if (found == false)
++ return -EBUSY;
+ return IIO_VAL_INT;
+ }
+
diff --git a/patches/linux-3.8.13/0060-MFD-ti_tscadc-disable-TSC-control.patch b/patches/linux-3.8.13/0060-MFD-ti_tscadc-disable-TSC-control.patch
new file mode 100644
index 0000000..165455a
--- /dev/null
+++ b/patches/linux-3.8.13/0060-MFD-ti_tscadc-disable-TSC-control.patch
@@ -0,0 +1,59 @@
+From: ZubairLK <zubair.lutfullah@gmail.com>
+Date: Thu, 27 Jun 2013 22:47:13 +0100
+Subject: [PATCH] MFD: ti_tscadc: disable TSC control
+
+Register bits when TSC not in use
+
+AFE Pen Ctrl and TouchScreen transistors enabling is not
+
+required when only ADC mode is being used, so check for availability of
+
+TSC driver before accessing control register.
+Original Commit No in Arago tree 2c67698139cceee19d2205ad34d11c74e758b307
+ZubairLK. Forward ported the changes to 3.8
+
+Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
+---
+ drivers/mfd/ti_am335x_tscadc.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index 640fe10..408e859 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -220,13 +220,14 @@ static int ti_tscadc_probe(struct platform_device *pdev)
+
+ /* Set the control register bits */
+ ctrl = CNTRLREG_STEPCONFIGWRT |
+- CNTRLREG_TSCENB |
+- CNTRLREG_STEPID |
+- CNTRLREG_4WIRE;
++ CNTRLREG_STEPID;
++ if (tsc_wires > 0)
++ ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
+ tscadc_writel(tscadc, REG_CTRL, ctrl);
+
+ /* Set register bits for Idle Config Mode */
+- tscadc_idle_config(tscadc);
++ if (tsc_wires > 0)
++ tscadc_idle_config(tscadc);
+
+ /* Enable the TSC module enable bit */
+ ctrl = tscadc_readl(tscadc, REG_CTRL);
+@@ -306,10 +307,13 @@ static int tscadc_resume(struct device *dev)
+ pm_runtime_get_sync(dev);
+
+ /* context restore */
+- ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB |
+- CNTRLREG_STEPID | CNTRLREG_4WIRE;
++ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID;
++ if (tscadc_dev->tsc_cell != -1)
++ ctrl |= CNTRLREG_TSCENB | CNTRLREG_4WIRE;
+ tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
+- tscadc_idle_config(tscadc_dev);
++
++ if (tscadc_dev->tsc_cell != -1)
++ tscadc_idle_config(tscadc_dev);
+ am335x_tsc_se_update(tscadc_dev);
+ restore = tscadc_readl(tscadc_dev, REG_CTRL);
+ tscadc_writel(tscadc_dev, REG_CTRL,
diff --git a/patches/linux-3.8.13/0061-IIO-ADC-ti_adc-Fix-1st-sample-read.patch b/patches/linux-3.8.13/0061-IIO-ADC-ti_adc-Fix-1st-sample-read.patch
new file mode 100644
index 0000000..f0b9604
--- /dev/null
+++ b/patches/linux-3.8.13/0061-IIO-ADC-ti_adc-Fix-1st-sample-read.patch
@@ -0,0 +1,119 @@
+From: ZubairLK <zubair.lutfullah@gmail.com>
+Date: Thu, 27 Jun 2013 23:49:41 +0100
+Subject: [PATCH] IIO: ADC: ti_adc: Fix 1st sample read
+
+Previously we tried to read data form ADC even before ADC sequencer
+
+finished sampling. This led to wrong samples.
+
+We now wait on ADC status register idle bit to be set.
+
+Original Commit in Arago tree : 663aa2e74f36a5a8000224b37a74c11ee729550d
+ZubairLK Forward ported the changes to 3.8
+
+Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 29 +++++++++++++++++++++--------
+ include/linux/mfd/ti_am335x_tscadc.h | 17 +++++++++++++++++
+ 2 files changed, 38 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index 624935c..f78d2c1 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -61,7 +61,6 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ {
+ unsigned int stepconfig;
+ int i, steps;
+- u32 step_en;
+
+ /*
+ * There are 16 configurable steps and 8 analog input
+@@ -87,8 +86,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ adc_dev->channel_step[i] = steps;
+ steps++;
+ }
+- step_en = get_adc_step_mask(adc_dev);
+- am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
++
+ }
+
+ static const char * const chan_name_ain[] = {
+@@ -143,11 +141,22 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ int *val, int *val2, long mask)
+ {
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+- int i;
+- unsigned int fifo1count, read;
++ int i, map_val;
++ unsigned int fifo1count, read, stepid;
+ u32 step = UINT_MAX;
+ bool found = false;
++ u32 step_en;
++ unsigned long timeout = jiffies + usecs_to_jiffies
++ (IDLE_TIMEOUT * adc_dev->channels);
++ step_en = get_adc_step_mask(adc_dev);
++ am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+
++ /* Wait for ADC sequencer to complete sampling */
++ while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
++ if (time_after(jiffies, timeout))
++ return -EAGAIN;
++ }
++ map_val = chan->channel + TOTAL_CHANNELS;
+ /*
+ * When the sub-system is first enabled,
+ * the sequencer will always start with the
+@@ -171,12 +180,16 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ for (i = 0; i < fifo1count; i++) {
+ read = tiadc_readl(adc_dev, REG_FIFO1);
+- if (read >> 16 == step) {
+- *val = read & 0xfff;
++ stepid = read & FIFOREAD_CHNLID_MASK;
++ stepid = stepid >> 0x10;
++
++ if (stepid == map_val) {
++ read = read & FIFOREAD_DATA_MASK;
+ found = true;
++ *val = read;
+ }
+ }
+- am335x_tsc_se_update(adc_dev->mfd_tscadc);
++
+ if (found == false)
+ return -EBUSY;
+ return IIO_VAL_INT;
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index 9598360..17c0cba 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -113,11 +113,28 @@
+ #define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
+ #define CNTRLREG_TSCENB BIT(7)
+
++/* FIFO READ Register */
++#define FIFOREAD_DATA_MASK (0xfff << 0)
++#define FIFOREAD_CHNLID_MASK (0xf << 16)
++
++/* Sequencer Status */
++#define SEQ_STATUS BIT(5)
++
+ #define ADC_CLK 3000000
+ #define MAX_CLK_DIV 7
+ #define TOTAL_STEPS 16
+ #define TOTAL_CHANNELS 8
+
++/*
++* ADC runs at 3MHz, and it takes
++* 15 cycles to latch one data output.
++* Hence the idle time for ADC to
++* process one sample data would be
++* around 5 micro seconds.
++*/
++#define IDLE_TIMEOUT 5 /* microsec */
++
++
+ #define TSCADC_CELLS 2
+
+ struct mfd_tscadc_board {
diff --git a/patches/linux-3.8.13/0062-input-ti_tsc-Enable-shared-IRQ-TSC.patch b/patches/linux-3.8.13/0062-input-ti_tsc-Enable-shared-IRQ-TSC.patch
new file mode 100644
index 0000000..6aa870c
--- /dev/null
+++ b/patches/linux-3.8.13/0062-input-ti_tsc-Enable-shared-IRQ-TSC.patch
@@ -0,0 +1,61 @@
+From: ZubairLK <zubairlk@zubairlk-HP-G62-Notebook-PC.(none)>
+Date: Fri, 28 Jun 2013 00:45:20 +0100
+Subject: [PATCH] input : ti_tsc : Enable shared IRQ TSC
+
+Touchscreen and ADC share the same IRQ line from parent MFD core.
+
+Previously only Touchscreen was interrupt based.
+
+With continuous mode support added in ADC driver, now driver requires
+
+interrupt to process the ADC samples, so enable shared IRQ flag bit for
+
+touchscreen.
+
+Original Commit in Arago tree : 09597d7a244a8e6f5ea79da3c5dced3a5ea620c4
+ZubairLK Forward ported the changes to 3.8
+
+Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>S
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 5f9801c..fd6a7b9 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -261,7 +261,15 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ unsigned int fsm;
+
+ status = titsc_readl(ts_dev, REG_IRQSTATUS);
+- if (status & IRQENB_FIFO0THRES) {
++ /*
++ * ADC and touchscreen share the IRQ line.
++ * FIFO1 threshold interrupt is used by ADC,
++ * hence return from touchscreen IRQ handler if FIFO1
++ * threshold interrupt occurred.
++ */
++ if (status & IRQENB_FIFO1THRES)
++ return IRQ_NONE;
++ else if (status & IRQENB_FIFO0THRES) {
+
+ titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
+
+@@ -316,7 +324,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ }
+
+ if (irqclr) {
+- titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
++ titsc_writel(ts_dev, REG_IRQSTATUS, (status | irqclr));
+ am335x_tsc_se_update(ts_dev->mfd_tscadc);
+ return IRQ_HANDLED;
+ }
+@@ -412,7 +420,7 @@ static int titsc_probe(struct platform_device *pdev)
+ }
+
+ err = request_irq(ts_dev->irq, titsc_irq,
+- 0, pdev->dev.driver->name, ts_dev);
++ IRQF_SHARED, pdev->dev.driver->name, ts_dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to allocate irq.\n");
+ goto err_free_mem;
diff --git a/patches/linux-3.8.13/0063-Revert.-Backport-IIO.patch b/patches/linux-3.8.13/0063-Revert.-Backport-IIO.patch
new file mode 100644
index 0000000..e2dab7f
--- /dev/null
+++ b/patches/linux-3.8.13/0063-Revert.-Backport-IIO.patch
@@ -0,0 +1,49 @@
+From: ZubairLK <zubair.lutfullah@gmail.com>
+Date: Sat, 29 Jun 2013 00:07:44 +0100
+Subject: [PATCH] Revert. Backport IIO
+
+Touchscreen side of things reverted to 3.8 compatible iio.
+
+Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index fd6a7b9..f498211 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -331,15 +331,15 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ return IRQ_NONE;
+ }
+
+-static int titsc_parse_dt(struct platform_device *pdev,
++static int titsc_parse_dt(struct ti_tscadc_dev *tscadc_dev,
+ struct titsc *ts_dev)
+ {
+- struct device_node *node = pdev->dev.of_node;
++ struct device_node *node = tscadc_dev->dev->of_node;
+ int err;
+
+ if (!node)
+ return -EINVAL;
+-
++ node = of_get_child_by_name(node, "tsc");
+ err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
+ if (err < 0)
+ return err;
+@@ -409,10 +409,10 @@ static int titsc_probe(struct platform_device *pdev)
+ ts_dev->input = input_dev;
+ ts_dev->irq = tscadc_dev->irq;
+
+- if (tscadc_dev->dev->platform_data)
+- err = titsc_parse_pdata(tscadc_dev, ts_dev);
+- else
+- err = titsc_parse_dt(pdev, ts_dev);
++ //if (tscadc_dev->dev->platform_data)
++ // err = titsc_parse_pdata(tscadc_dev, ts_dev);
++ //else
++ err = titsc_parse_dt(tscadc_dev, ts_dev);
+
+ if (err) {
+ dev_err(&pdev->dev, "Could not find valid DT data.\n");
diff --git a/patches/linux-3.8.13/0064-iio-ti_am335x_adc-Added-iio_voltageX_scale.patch b/patches/linux-3.8.13/0064-iio-ti_am335x_adc-Added-iio_voltageX_scale.patch
new file mode 100644
index 0000000..0d8e7e7
--- /dev/null
+++ b/patches/linux-3.8.13/0064-iio-ti_am335x_adc-Added-iio_voltageX_scale.patch
@@ -0,0 +1,60 @@
+From: ZubairLK <zubair.lutfullah@gmail.com>
+Date: Sat, 29 Jun 2013 19:05:54 +0100
+Subject: [PATCH] iio: ti_am335x_adc: Added iio_voltageX_scale
+
+The bone-helper driver tried to display the voltage in the range 1800mV
+which represents the actual ADC range of the BBB. This feature is available
+in the IIO system. in_voltageX_raw points to unscaled raw values
+which give the output of the ADC register directly.
+
+in_voltageX_scale is supposed to give scaled voltages. This was
+missing in the TI driver and has been added.
+
+Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index f78d2c1..c030078 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -26,6 +26,7 @@
+ #include <linux/of_device.h>
+ #include <linux/iio/machine.h>
+ #include <linux/iio/driver.h>
++#include <linux/math64.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/platform_data/ti_am335x_adc.h>
+@@ -119,7 +120,8 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+ chan->channel = adc_dev->channel_line[i];
+- chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
++ chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT
++ | IIO_CHAN_INFO_SCALE_SEPARATE_BIT;
+ chan->datasheet_name = chan_name_ain[chan->channel];
+ chan->scan_type.sign = 'u';
+ chan->scan_type.realbits = 12;
+@@ -189,7 +191,19 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
+ *val = read;
+ }
+ }
+-
++
++ switch (mask){
++ case IIO_CHAN_INFO_RAW : /*Do nothing. Above code works fine.*/
++ break;
++ case IIO_CHAN_INFO_SCALE : {
++ /*12 Bit adc. Scale value for 1800mV AVDD. Ideally
++ AVDD should come from DT.*/
++ *val = div_u64( (u64)(*val) * 1800 , 4096);
++ break;
++ }
++ default: break;
++ }
++
+ if (found == false)
+ return -EBUSY;
+ return IIO_VAL_INT;
diff --git a/patches/linux-3.8.13/0065-iio-ti_am335x_adc-Add-the-in-kernel-IIO-map-interfac.patch b/patches/linux-3.8.13/0065-iio-ti_am335x_adc-Add-the-in-kernel-IIO-map-interfac.patch
new file mode 100644
index 0000000..7ade689
--- /dev/null
+++ b/patches/linux-3.8.13/0065-iio-ti_am335x_adc-Add-the-in-kernel-IIO-map-interfac.patch
@@ -0,0 +1,122 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Jul 2013 20:53:00 +0300
+Subject: [PATCH] iio: ti_am335x_adc: Add the in-kernel IIO map interface back
+ in.
+
+Without an IIO map the in-kernel users cannot find their
+AINx named ADC channels. So reintroduce.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/iio/adc/ti_am335x_adc.c | 53 +++++++++++++++++++++++++++++++++++----
+ 1 file changed, 48 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index c030078..83180fc 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -34,6 +34,7 @@
+ struct tiadc_device {
+ struct ti_tscadc_dev *mfd_tscadc;
+ int channels;
++ struct iio_map *map;
+ u8 channel_line[8];
+ u8 channel_step[8];
+ };
+@@ -106,13 +107,16 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ struct iio_chan_spec *chan_array;
+ struct iio_chan_spec *chan;
+- int i;
++ struct iio_map *map;
++ int i, ret;
+
+ indio_dev->num_channels = channels;
+ chan_array = kcalloc(channels,
+ sizeof(struct iio_chan_spec), GFP_KERNEL);
+- if (chan_array == NULL)
+- return -ENOMEM;
++ if (chan_array == NULL) {
++ ret = -ENOMEM;
++ goto err_no_chan_array;
++ }
+
+ chan = chan_array;
+ for (i = 0; i < channels; i++, chan++) {
+@@ -130,12 +134,43 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+
+ indio_dev->channels = chan_array;
+
++ map = kcalloc(channels + 1, sizeof(struct iio_map), GFP_KERNEL);
++ if (map == NULL) {
++ ret = -ENOMEM;
++ goto err_no_iio_map;
++ }
++ adc_dev->map = map;
++
++ for (i = 0, chan = chan_array; i < channels; i++, chan++, map++) {
++ map->adc_channel_label = chan->datasheet_name;
++ map->consumer_dev_name = "any";
++ map->consumer_channel = chan->datasheet_name;
++ }
++ map->adc_channel_label = NULL;
++ map->consumer_dev_name = NULL;
++ map->consumer_channel = NULL;
++
++ ret = iio_map_array_register(indio_dev, adc_dev->map);
++ if (ret != 0)
++ goto err_iio_map_register_fail;
++
+ return 0;
++
++err_iio_map_register_fail:
++ kfree(adc_dev->map);
++ adc_dev->map = NULL;
++err_no_iio_map:
++ kfree(chan_array);
++ indio_dev->channels = NULL;
++err_no_chan_array:
++ return ret;
+ }
+
+ static void tiadc_channels_remove(struct iio_dev *indio_dev)
+ {
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ kfree(indio_dev->channels);
++ kfree(adc_dev->map);
+ }
+
+ static int tiadc_read_raw(struct iio_dev *indio_dev,
+@@ -252,6 +287,8 @@ static int tiadc_probe(struct platform_device *pdev)
+ adc_dev->channels = channels;
+ }
+
++ dev_info(&pdev->dev, "channels=%d\n", adc_dev->channels);
++
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+@@ -260,15 +297,21 @@ static int tiadc_probe(struct platform_device *pdev)
+ tiadc_step_config(adc_dev);
+
+ err = tiadc_channel_init(indio_dev, adc_dev->channels);
+- if (err < 0)
++ if (err < 0) {
++ dev_err(&pdev->dev, "tiadc_channel_init() failed\n");
+ goto err_free_device;
++ }
+
+ err = iio_device_register(indio_dev);
+- if (err)
++ if (err) {
++ dev_err(&pdev->dev, "iio_device_register() failed\n");
+ goto err_free_channels;
++ }
+
+ platform_set_drvdata(pdev, indio_dev);
+
++ dev_info(&pdev->dev, "loaded OK\n");
++
+ return 0;
+
+ err_free_channels:
diff --git a/patches/linux-3.8.13/0066-pinctrl-pinctrl-single-must-be-initialized-early.patch b/patches/linux-3.8.13/0066-pinctrl-pinctrl-single-must-be-initialized-early.patch
new file mode 100644
index 0000000..2a85976
--- /dev/null
+++ b/patches/linux-3.8.13/0066-pinctrl-pinctrl-single-must-be-initialized-early.patch
@@ -0,0 +1,34 @@
+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 5c32e88..e75d107 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.8.13/0067-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch b/patches/linux-3.8.13/0067-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
new file mode 100644
index 0000000..8636924
--- /dev/null
+++ b/patches/linux-3.8.13/0067-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
@@ -0,0 +1,93 @@
+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 6dbeff6..813ac04 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -66,6 +66,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 {
+@@ -110,16 +116,6 @@
+ };
+ };
+
+- i2c1: i2c@44e0b000 {
+- status = "okay";
+- clock-frequency = <400000>;
+-
+- tps: tps@24 {
+- reg = <0x24>;
+- };
+-
+- };
+-
+ gpevt {
+ compatible = "gpevt";
+ dmas = <&edma 12>;
+@@ -163,6 +159,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.8.13/0068-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch b/patches/linux-3.8.13/0068-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
new file mode 100644
index 0000000..d4041e5
--- /dev/null
+++ b/patches/linux-3.8.13/0068-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
@@ -0,0 +1,104 @@
+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 813ac04..874997b 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -66,7 +66,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 */
+@@ -159,7 +159,7 @@
+ };
+ };
+
+-&i2c1 {
++&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+@@ -174,10 +174,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 5483e09..7ef38f6 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -61,7 +61,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 47ac3d2..bfae98b 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -209,31 +209,31 @@
+ 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>;
+ 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>;
+ 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>;
+ interrupts = <30>;
+ status = "disabled";
diff --git a/patches/linux-3.8.13/0069-am335x-evm-hack-around-i2c-node-names.patch b/patches/linux-3.8.13/0069-am335x-evm-hack-around-i2c-node-names.patch
new file mode 100644
index 0000000..cf73bec
--- /dev/null
+++ b/patches/linux-3.8.13/0069-am335x-evm-hack-around-i2c-node-names.patch
@@ -0,0 +1,36 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 13 Dec 2012 14:13:31 +0100
+Subject: [PATCH] am335x-evm*: hack around i2c node names
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-evm.dts | 2 +-
+ arch/arm/boot/dts/am335x-evmsk.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 7ef38f6..f4a07f8 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -70,7 +70,7 @@
+ };
+ };
+
+- i2c2: i2c@4802a000 {
++ i2c20: i2c@4802a000 {
+ status = "okay";
+ clock-frequency = <100000>;
+
+diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
+index f050c46..2546724 100644
+--- a/arch/arm/boot/dts/am335x-evmsk.dts
++++ b/arch/arm/boot/dts/am335x-evmsk.dts
+@@ -58,7 +58,7 @@
+ status = "okay";
+ };
+
+- i2c1: i2c@44e0b000 {
++ i2c10: i2c@44e0b000 {
+ status = "okay";
+ clock-frequency = <400000>;
+
diff --git a/patches/linux-3.8.13/0070-tsl2550-fix-lux1_input-error-in-low-light.patch b/patches/linux-3.8.13/0070-tsl2550-fix-lux1_input-error-in-low-light.patch
new file mode 100644
index 0000000..ea180e9
--- /dev/null
+++ b/patches/linux-3.8.13/0070-tsl2550-fix-lux1_input-error-in-low-light.patch
@@ -0,0 +1,31 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Mon, 3 Jun 2013 22:38:49 +0000
+Subject: [PATCH] tsl2550: fix lux1_input error in low light
+
+ADC channel 0 photodiode detects both infrared + visible light,
+but ADC channel 1 just detects infrared. However, the latter is a bit
+more sensitive in that range so complete darkness or low light causes
+a error condition in which the chan0 - chan1 is negative that
+results in a -EAGAIN.
+
+This patch changes the resulting lux1_input sysfs attribute message from
+"Resource temporarily unavailable" to a user-grokable lux value of 0.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/misc/tsl2550.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
+index 1e7bc0e..9255074 100644
+--- a/drivers/misc/tsl2550.c
++++ b/drivers/misc/tsl2550.c
+@@ -178,7 +178,7 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
+ } else
+ lux = 0;
+ else
+- return -EAGAIN;
++ return 0;
+
+ /* LUX range check */
+ return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
diff --git a/patches/linux-3.8.13/0071-viafb-rename-display_timing-to-via_display_timing.patch b/patches/linux-3.8.13/0071-viafb-rename-display_timing-to-via_display_timing.patch
new file mode 100644
index 0000000..99bb651
--- /dev/null
+++ b/patches/linux-3.8.13/0071-viafb-rename-display_timing-to-via_display_timing.patch
@@ -0,0 +1,137 @@
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Wed, 19 Dec 2012 16:28:08 +0530
+Subject: [PATCH] viafb: rename display_timing to via_display_timing
+
+The struct display_timing is specific to the via subsystem. The naming leads to
+collisions with the new struct display_timing, which is supposed to be a shared
+struct between different subsystems.
+To clean this up, prepend the existing struct with the subsystem it is specific
+to.
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+---
+ drivers/video/via/hw.c | 6 +++---
+ drivers/video/via/hw.h | 2 +-
+ drivers/video/via/lcd.c | 2 +-
+ drivers/video/via/share.h | 2 +-
+ drivers/video/via/via_modesetting.c | 8 ++++----
+ drivers/video/via/via_modesetting.h | 6 +++---
+ 6 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
+index 80233da..22450908 100644
+--- a/drivers/video/via/hw.c
++++ b/drivers/video/via/hw.c
+@@ -1467,10 +1467,10 @@ void viafb_set_vclock(u32 clk, int set_iga)
+ via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
+ }
+
+-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
++struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
+ u16 cxres, u16 cyres)
+ {
+- struct display_timing timing;
++ struct via_display_timing timing;
+ u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
+
+ timing.hor_addr = cxres;
+@@ -1491,7 +1491,7 @@ struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
+ void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
+ u16 cxres, u16 cyres, int iga)
+ {
+- struct display_timing crt_reg = var_to_timing(var,
++ struct via_display_timing crt_reg = var_to_timing(var,
+ cxres ? cxres : var->xres, cyres ? cyres : var->yres);
+
+ if (iga == IGA1)
+diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
+index a820575..3be073c 100644
+--- a/drivers/video/via/hw.h
++++ b/drivers/video/via/hw.h
+@@ -637,7 +637,7 @@ extern int viafb_LCD_ON;
+ extern int viafb_DVI_ON;
+ extern int viafb_hotplug;
+
+-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
++struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
+ u16 cxres, u16 cyres);
+ void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
+ u16 cxres, u16 cyres, int iga);
+diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
+index 980ee1b..5d21ff4 100644
+--- a/drivers/video/via/lcd.c
++++ b/drivers/video/via/lcd.c
+@@ -549,7 +549,7 @@ void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
+ int panel_hres = plvds_setting_info->lcd_panel_hres;
+ int panel_vres = plvds_setting_info->lcd_panel_vres;
+ u32 clock;
+- struct display_timing timing;
++ struct via_display_timing timing;
+ struct fb_var_screeninfo panel_var;
+ const struct fb_videomode *mode_crt_table, *panel_crt_table;
+
+diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
+index 3158dfc..65c65c6 100644
+--- a/drivers/video/via/share.h
++++ b/drivers/video/via/share.h
+@@ -319,7 +319,7 @@ struct crt_mode_table {
+ int refresh_rate;
+ int h_sync_polarity;
+ int v_sync_polarity;
+- struct display_timing crtc;
++ struct via_display_timing crtc;
+ };
+
+ struct io_reg {
+diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
+index 0e431ae..0b414b0 100644
+--- a/drivers/video/via/via_modesetting.c
++++ b/drivers/video/via/via_modesetting.c
+@@ -30,9 +30,9 @@
+ #include "debug.h"
+
+
+-void via_set_primary_timing(const struct display_timing *timing)
++void via_set_primary_timing(const struct via_display_timing *timing)
+ {
+- struct display_timing raw;
++ struct via_display_timing raw;
+
+ raw.hor_total = timing->hor_total / 8 - 5;
+ raw.hor_addr = timing->hor_addr / 8 - 1;
+@@ -88,9 +88,9 @@ void via_set_primary_timing(const struct display_timing *timing)
+ via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
+ }
+
+-void via_set_secondary_timing(const struct display_timing *timing)
++void via_set_secondary_timing(const struct via_display_timing *timing)
+ {
+- struct display_timing raw;
++ struct via_display_timing raw;
+
+ raw.hor_total = timing->hor_total - 1;
+ raw.hor_addr = timing->hor_addr - 1;
+diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
+index 06e09fe..f6a6503 100644
+--- a/drivers/video/via/via_modesetting.h
++++ b/drivers/video/via/via_modesetting.h
+@@ -33,7 +33,7 @@
+ #define VIA_PITCH_MAX 0x3FF8
+
+
+-struct display_timing {
++struct via_display_timing {
+ u16 hor_total;
+ u16 hor_addr;
+ u16 hor_blank_start;
+@@ -49,8 +49,8 @@ struct display_timing {
+ };
+
+
+-void via_set_primary_timing(const struct display_timing *timing);
+-void via_set_secondary_timing(const struct display_timing *timing);
++void via_set_primary_timing(const struct via_display_timing *timing);
++void via_set_secondary_timing(const struct via_display_timing *timing);
+ void via_set_primary_address(u32 addr);
+ void via_set_secondary_address(u32 addr);
+ void via_set_primary_pitch(u32 pitch);
diff --git a/patches/linux-3.8.13/0072-video-add-display_timing-and-videomode.patch b/patches/linux-3.8.13/0072-video-add-display_timing-and-videomode.patch
new file mode 100644
index 0000000..c38b3f2
--- /dev/null
+++ b/patches/linux-3.8.13/0072-video-add-display_timing-and-videomode.patch
@@ -0,0 +1,340 @@
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Wed, 19 Dec 2012 16:36:50 +0530
+Subject: [PATCH] video: add display_timing and videomode
+
+Add display_timing structure and the according helper functions. This allows
+the description of a display via its supported timing parameters.
+
+Also, add helper functions to convert from display timings to a generic videomode
+structure.
+
+The struct display_timing specifies all needed parameters to describe the signal
+properties of a display in one mode. This includes
+ - ranges for signals that may have min-, max- and typical values
+ - single integers for signals that can be on, off or are ignored
+ - booleans for signals that are either on or off
+
+As a display may support multiple modes like this, a struct display_timings is
+added, that holds all given struct display_timing pointers and declares the
+native mode of the display.
+
+Although a display may state that a signal can be in a range, it is driven with
+fixed values that indicate a videomode. Therefore graphic drivers don't need all
+the information of struct display_timing, but would generate a videomode from
+the given set of supported signal timings and work with that.
+
+The video subsystems all define their own structs that describe a mode and work
+with that (e.g. fb_videomode or drm_display_mode). To slowly replace all those
+various structures and allow code reuse across those subsystems, add struct
+videomode as a generic description.
+
+This patch only includes the most basic fields in struct videomode. All missing
+fields that are needed to have a really generic video mode description can be
+added at a later stage.
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/video/Kconfig | 6 ++
+ drivers/video/Makefile | 2 +
+ drivers/video/display_timing.c | 24 ++++++++
+ drivers/video/videomode.c | 39 +++++++++++++
+ include/video/display_timing.h | 124 ++++++++++++++++++++++++++++++++++++++++
+ include/video/videomode.h | 48 ++++++++++++++++
+ 6 files changed, 243 insertions(+)
+ create mode 100644 drivers/video/display_timing.c
+ create mode 100644 drivers/video/videomode.c
+ create mode 100644 include/video/display_timing.h
+ create mode 100644 include/video/videomode.h
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index b532f02..42569d1 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -33,6 +33,12 @@ config VIDEO_OUTPUT_CONTROL
+ This framework adds support for low-level control of the video
+ output switch.
+
++config DISPLAY_TIMING
++ bool
++
++config VIDEOMODE
++ bool
++
+ menuconfig FB
+ tristate "Support for frame buffer devices"
+ ---help---
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 58dbeaf..80c76c7 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -169,3 +169,5 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o
+
+ #video output switch sysfs driver
+ obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
++obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
++obj-$(CONFIG_VIDEOMODE) += videomode.o
+diff --git a/drivers/video/display_timing.c b/drivers/video/display_timing.c
+new file mode 100644
+index 0000000..5e1822c
+--- /dev/null
++++ b/drivers/video/display_timing.c
+@@ -0,0 +1,24 @@
++/*
++ * generic display timing functions
++ *
++ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
++ *
++ * This file is released under the GPLv2
++ */
++
++#include <linux/export.h>
++#include <linux/slab.h>
++#include <video/display_timing.h>
++
++void display_timings_release(struct display_timings *disp)
++{
++ if (disp->timings) {
++ unsigned int i;
++
++ for (i = 0; i < disp->num_timings; i++)
++ kfree(disp->timings[i]);
++ kfree(disp->timings);
++ }
++ kfree(disp);
++}
++EXPORT_SYMBOL_GPL(display_timings_release);
+diff --git a/drivers/video/videomode.c b/drivers/video/videomode.c
+new file mode 100644
+index 0000000..21c47a2
+--- /dev/null
++++ b/drivers/video/videomode.c
+@@ -0,0 +1,39 @@
++/*
++ * generic display timing functions
++ *
++ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
++ *
++ * This file is released under the GPLv2
++ */
++
++#include <linux/errno.h>
++#include <linux/export.h>
++#include <video/display_timing.h>
++#include <video/videomode.h>
++
++int videomode_from_timing(const struct display_timings *disp,
++ struct videomode *vm, unsigned int index)
++{
++ struct display_timing *dt;
++
++ dt = display_timings_get(disp, index);
++ if (!dt)
++ return -EINVAL;
++
++ vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP);
++ vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP);
++ vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP);
++ vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP);
++ vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP);
++
++ vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP);
++ vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP);
++ vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP);
++ vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP);
++
++ vm->dmt_flags = dt->dmt_flags;
++ vm->data_flags = dt->data_flags;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(videomode_from_timing);
+diff --git a/include/video/display_timing.h b/include/video/display_timing.h
+new file mode 100644
+index 0000000..71e9a38
+--- /dev/null
++++ b/include/video/display_timing.h
+@@ -0,0 +1,124 @@
++/*
++ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
++ *
++ * description of display timings
++ *
++ * This file is released under the GPLv2
++ */
++
++#ifndef __LINUX_DISPLAY_TIMING_H
++#define __LINUX_DISPLAY_TIMING_H
++
++#include <linux/bitops.h>
++#include <linux/types.h>
++
++/* VESA display monitor timing parameters */
++#define VESA_DMT_HSYNC_LOW BIT(0)
++#define VESA_DMT_HSYNC_HIGH BIT(1)
++#define VESA_DMT_VSYNC_LOW BIT(2)
++#define VESA_DMT_VSYNC_HIGH BIT(3)
++
++/* display specific flags */
++#define DISPLAY_FLAGS_DE_LOW BIT(0) /* data enable flag */
++#define DISPLAY_FLAGS_DE_HIGH BIT(1)
++#define DISPLAY_FLAGS_PIXDATA_POSEDGE BIT(2) /* drive data on pos. edge */
++#define DISPLAY_FLAGS_PIXDATA_NEGEDGE BIT(3) /* drive data on neg. edge */
++#define DISPLAY_FLAGS_INTERLACED BIT(4)
++#define DISPLAY_FLAGS_DOUBLESCAN BIT(5)
++
++/*
++ * A single signal can be specified via a range of minimal and maximal values
++ * with a typical value, that lies somewhere inbetween.
++ */
++struct timing_entry {
++ u32 min;
++ u32 typ;
++ u32 max;
++};
++
++enum timing_entry_index {
++ TE_MIN = 0,
++ TE_TYP = 1,
++ TE_MAX = 2,
++};
++
++/*
++ * Single "mode" entry. This describes one set of signal timings a display can
++ * have in one setting. This struct can later be converted to struct videomode
++ * (see include/video/videomode.h). As each timing_entry can be defined as a
++ * range, one struct display_timing may become multiple struct videomodes.
++ *
++ * Example: hsync active high, vsync active low
++ *
++ * Active Video
++ * Video ______________________XXXXXXXXXXXXXXXXXXXXXX_____________________
++ * |<- sync ->|<- back ->|<----- active ----->|<- front ->|<- sync..
++ * | | porch | | porch |
++ *
++ * HSync _|¯¯¯¯¯¯¯¯¯¯|___________________________________________|¯¯¯¯¯¯¯¯¯
++ *
++ * VSync ¯|__________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_________
++ */
++struct display_timing {
++ struct timing_entry pixelclock;
++
++ struct timing_entry hactive; /* hor. active video */
++ struct timing_entry hfront_porch; /* hor. front porch */
++ struct timing_entry hback_porch; /* hor. back porch */
++ struct timing_entry hsync_len; /* hor. sync len */
++
++ struct timing_entry vactive; /* ver. active video */
++ struct timing_entry vfront_porch; /* ver. front porch */
++ struct timing_entry vback_porch; /* ver. back porch */
++ struct timing_entry vsync_len; /* ver. sync len */
++
++ unsigned int dmt_flags; /* VESA DMT flags */
++ unsigned int data_flags; /* video data flags */
++};
++
++/*
++ * This describes all timing settings a display provides.
++ * The native_mode is the default setting for this display.
++ * Drivers that can handle multiple videomodes should work with this struct and
++ * convert each entry to the desired end result.
++ */
++struct display_timings {
++ unsigned int num_timings;
++ unsigned int native_mode;
++
++ struct display_timing **timings;
++};
++
++/* get value specified by index from struct timing_entry */
++static inline u32 display_timing_get_value(const struct timing_entry *te,
++ enum timing_entry_index index)
++{
++ switch (index) {
++ case TE_MIN:
++ return te->min;
++ break;
++ case TE_TYP:
++ return te->typ;
++ break;
++ case TE_MAX:
++ return te->max;
++ break;
++ default:
++ return te->typ;
++ }
++}
++
++/* get one entry from struct display_timings */
++static inline struct display_timing *display_timings_get(const struct
++ display_timings *disp,
++ unsigned int index)
++{
++ if (disp->num_timings > index)
++ return disp->timings[index];
++ else
++ return NULL;
++}
++
++void display_timings_release(struct display_timings *disp);
++
++#endif
+diff --git a/include/video/videomode.h b/include/video/videomode.h
+new file mode 100644
+index 0000000..a421562
+--- /dev/null
++++ b/include/video/videomode.h
+@@ -0,0 +1,48 @@
++/*
++ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
++ *
++ * generic videomode description
++ *
++ * This file is released under the GPLv2
++ */
++
++#ifndef __LINUX_VIDEOMODE_H
++#define __LINUX_VIDEOMODE_H
++
++#include <linux/types.h>
++#include <video/display_timing.h>
++
++/*
++ * Subsystem independent description of a videomode.
++ * Can be generated from struct display_timing.
++ */
++struct videomode {
++ unsigned long pixelclock; /* pixelclock in Hz */
++
++ u32 hactive;
++ u32 hfront_porch;
++ u32 hback_porch;
++ u32 hsync_len;
++
++ u32 vactive;
++ u32 vfront_porch;
++ u32 vback_porch;
++ u32 vsync_len;
++
++ unsigned int dmt_flags; /* VESA DMT flags */
++ unsigned int data_flags; /* video data flags */
++};
++
++/**
++ * videomode_from_timing - convert display timing to videomode
++ * @disp: structure with all possible timing entries
++ * @vm: return value
++ * @index: index into the list of display timings in devicetree
++ *
++ * DESCRIPTION:
++ * This function converts a struct display_timing to a struct videomode.
++ */
++int videomode_from_timing(const struct display_timings *disp,
++ struct videomode *vm, unsigned int index);
++
++#endif
diff --git a/patches/linux-3.8.13/0073-video-add-of-helper-for-display-timings-videomode.patch b/patches/linux-3.8.13/0073-video-add-of-helper-for-display-timings-videomode.patch
new file mode 100644
index 0000000..70158b6
--- /dev/null
+++ b/patches/linux-3.8.13/0073-video-add-of-helper-for-display-timings-videomode.patch
@@ -0,0 +1,545 @@
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Wed, 19 Dec 2012 16:36:54 +0530
+Subject: [PATCH] video: add of helper for display timings/videomode
+
+This adds support for reading display timings from DT into a struct
+display_timings. The of_display_timing implementation supports multiple
+subnodes. All children are read into an array, that can be queried.
+
+If no native mode is specified, the first subnode will be used.
+
+For cases where the graphics driver knows there can be only one
+mode description or where the driver only supports one mode, a helper
+function of_get_videomode is added, that gets a struct videomode from DT.
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+Acked-by: Stephen Warren <swarren@nvidia.com>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ .../devicetree/bindings/video/display-timing.txt | 109 +++++++++
+ drivers/video/Kconfig | 15 ++
+ drivers/video/Makefile | 2 +
+ drivers/video/of_display_timing.c | 239 ++++++++++++++++++++
+ drivers/video/of_videomode.c | 54 +++++
+ include/video/of_display_timing.h | 20 ++
+ include/video/of_videomode.h | 18 ++
+ 7 files changed, 457 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/video/display-timing.txt
+ create mode 100644 drivers/video/of_display_timing.c
+ create mode 100644 drivers/video/of_videomode.c
+ create mode 100644 include/video/of_display_timing.h
+ create mode 100644 include/video/of_videomode.h
+
+diff --git a/Documentation/devicetree/bindings/video/display-timing.txt b/Documentation/devicetree/bindings/video/display-timing.txt
+new file mode 100644
+index 0000000..bf9d82b
+--- /dev/null
++++ b/Documentation/devicetree/bindings/video/display-timing.txt
+@@ -0,0 +1,109 @@
++display-timing bindings
++=======================
++
++display-timings node
++--------------------
++
++required properties:
++ - none
++
++optional properties:
++ - native-mode: The native mode for the display, in case multiple modes are
++ provided. When omitted, assume the first node is the native.
++
++timing subnode
++--------------
++
++required properties:
++ - hactive, vactive: display resolution
++ - hfront-porch, hback-porch, hsync-len: horizontal display timing parameters
++ in pixels
++ vfront-porch, vback-porch, vsync-len: vertical display timing parameters in
++ lines
++ - clock-frequency: display clock in Hz
++
++optional properties:
++ - hsync-active: hsync pulse is active low/high/ignored
++ - vsync-active: vsync pulse is active low/high/ignored
++ - de-active: data-enable pulse is active low/high/ignored
++ - pixelclk-active: with
++ - active high = drive pixel data on rising edge/
++ sample data on falling edge
++ - active low = drive pixel data on falling edge/
++ sample data on rising edge
++ - ignored = ignored
++ - interlaced (bool): boolean to enable interlaced mode
++ - doublescan (bool): boolean to enable doublescan mode
++
++All the optional properties that are not bool follow the following logic:
++ <1>: high active
++ <0>: low active
++ omitted: not used on hardware
++
++There are different ways of describing the capabilities of a display. The
++devicetree representation corresponds to the one commonly found in datasheets
++for displays. If a display supports multiple signal timings, the native-mode
++can be specified.
++
++The parameters are defined as:
++
++ +----------+-------------------------------------+----------+-------+
++ | | . | | |
++ | | |vback_porch | | |
++ | | . | | |
++ +----------#######################################----------+-------+
++ | # . # | |
++ | # | # | |
++ | hback # | # hfront | hsync |
++ | porch # | hactive # porch | len |
++ |<-------->#<-------+--------------------------->#<-------->|<----->|
++ | # | # | |
++ | # |vactive # | |
++ | # | # | |
++ | # . # | |
++ +----------#######################################----------+-------+
++ | | . | | |
++ | | |vfront_porch | | |
++ | | . | | |
++ +----------+-------------------------------------+----------+-------+
++ | | . | | |
++ | | |vsync_len | | |
++ | | . | | |
++ +----------+-------------------------------------+----------+-------+
++
++Example:
++
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 1080p24 {
++ /* 1920x1080p24 */
++ clock-frequency = <52000000>;
++ hactive = <1920>;
++ vactive = <1080>;
++ hfront-porch = <25>;
++ hback-porch = <25>;
++ hsync-len = <25>;
++ vback-porch = <2>;
++ vfront-porch = <2>;
++ vsync-len = <2>;
++ hsync-active = <1>;
++ };
++ };
++
++Every required property also supports the use of ranges, so the commonly used
++datasheet description with minimum, typical and maximum values can be used.
++
++Example:
++
++ timing1: timing {
++ /* 1920x1080p24 */
++ clock-frequency = <148500000>;
++ hactive = <1920>;
++ vactive = <1080>;
++ hsync-len = <0 44 60>;
++ hfront-porch = <80 88 95>;
++ hback-porch = <100 148 160>;
++ vfront-porch = <0 4 6>;
++ vback-porch = <0 36 50>;
++ vsync-len = <0 5 6>;
++ };
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 42569d1..4abcf9c 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -39,6 +39,21 @@ config DISPLAY_TIMING
+ config VIDEOMODE
+ bool
+
++config OF_DISPLAY_TIMING
++ bool "Enable device tree display timing support"
++ depends on OF
++ select DISPLAY_TIMING
++ help
++ helper to parse display timings from the devicetree
++
++config OF_VIDEOMODE
++ bool "Enable device tree videomode support"
++ depends on OF
++ select VIDEOMODE
++ select OF_DISPLAY_TIMING
++ help
++ helper to get videomodes from the devicetree
++
+ menuconfig FB
+ tristate "Support for frame buffer devices"
+ ---help---
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 80c76c7..a3ab28c 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -170,4 +170,6 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o
+ #video output switch sysfs driver
+ obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+ obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
++obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o
+ obj-$(CONFIG_VIDEOMODE) += videomode.o
++obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
+diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
+new file mode 100644
+index 0000000..13ecd98
+--- /dev/null
++++ b/drivers/video/of_display_timing.c
+@@ -0,0 +1,239 @@
++/*
++ * OF helpers for parsing display timings
++ *
++ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
++ *
++ * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
++ *
++ * This file is released under the GPLv2
++ */
++#include <linux/export.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <video/display_timing.h>
++#include <video/of_display_timing.h>
++
++/**
++ * parse_timing_property - parse timing_entry from device_node
++ * @np: device_node with the property
++ * @name: name of the property
++ * @result: will be set to the return value
++ *
++ * DESCRIPTION:
++ * Every display_timing can be specified with either just the typical value or
++ * a range consisting of min/typ/max. This function helps handling this
++ **/
++static int parse_timing_property(struct device_node *np, const char *name,
++ struct timing_entry *result)
++{
++ struct property *prop;
++ int length, cells, ret;
++
++ prop = of_find_property(np, name, &length);
++ if (!prop) {
++ pr_err("%s: could not find property %s\n",
++ of_node_full_name(np), name);
++ return -EINVAL;
++ }
++
++ cells = length / sizeof(u32);
++ if (cells == 1) {
++ ret = of_property_read_u32(np, name, &result->typ);
++ result->min = result->typ;
++ result->max = result->typ;
++ } else if (cells == 3) {
++ ret = of_property_read_u32_array(np, name, &result->min, cells);
++ } else {
++ pr_err("%s: illegal timing specification in %s\n",
++ of_node_full_name(np), name);
++ return -EINVAL;
++ }
++
++ return ret;
++}
++
++/**
++ * of_get_display_timing - parse display_timing entry from device_node
++ * @np: device_node with the properties
++ **/
++static struct display_timing *of_get_display_timing(struct device_node *np)
++{
++ struct display_timing *dt;
++ u32 val = 0;
++ int ret = 0;
++
++ dt = kzalloc(sizeof(*dt), GFP_KERNEL);
++ if (!dt) {
++ pr_err("%s: could not allocate display_timing struct\n",
++ of_node_full_name(np));
++ return NULL;
++ }
++
++ ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
++ ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
++ ret |= parse_timing_property(np, "hactive", &dt->hactive);
++ ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
++ ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
++ ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
++ ret |= parse_timing_property(np, "vactive", &dt->vactive);
++ ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
++ ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
++
++ dt->dmt_flags = 0;
++ dt->data_flags = 0;
++ if (!of_property_read_u32(np, "vsync-active", &val))
++ dt->dmt_flags |= val ? VESA_DMT_VSYNC_HIGH :
++ VESA_DMT_VSYNC_LOW;
++ if (!of_property_read_u32(np, "hsync-active", &val))
++ dt->dmt_flags |= val ? VESA_DMT_HSYNC_HIGH :
++ VESA_DMT_HSYNC_LOW;
++ if (!of_property_read_u32(np, "de-active", &val))
++ dt->data_flags |= val ? DISPLAY_FLAGS_DE_HIGH :
++ DISPLAY_FLAGS_DE_LOW;
++ if (!of_property_read_u32(np, "pixelclk-active", &val))
++ dt->data_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
++ DISPLAY_FLAGS_PIXDATA_NEGEDGE;
++
++ if (of_property_read_bool(np, "interlaced"))
++ dt->data_flags |= DISPLAY_FLAGS_INTERLACED;
++ if (of_property_read_bool(np, "doublescan"))
++ dt->data_flags |= DISPLAY_FLAGS_DOUBLESCAN;
++
++ if (ret) {
++ pr_err("%s: error reading timing properties\n",
++ of_node_full_name(np));
++ kfree(dt);
++ return NULL;
++ }
++
++ return dt;
++}
++
++/**
++ * of_get_display_timings - parse all display_timing entries from a device_node
++ * @np: device_node with the subnodes
++ **/
++struct display_timings *of_get_display_timings(struct device_node *np)
++{
++ struct device_node *timings_np;
++ struct device_node *entry;
++ struct device_node *native_mode;
++ struct display_timings *disp;
++
++ if (!np) {
++ pr_err("%s: no devicenode given\n", of_node_full_name(np));
++ return NULL;
++ }
++
++ timings_np = of_find_node_by_name(np, "display-timings");
++ if (!timings_np) {
++ pr_err("%s: could not find display-timings node\n",
++ of_node_full_name(np));
++ return NULL;
++ }
++
++ disp = kzalloc(sizeof(*disp), GFP_KERNEL);
++ if (!disp) {
++ pr_err("%s: could not allocate struct disp'\n",
++ of_node_full_name(np));
++ goto dispfail;
++ }
++
++ entry = of_parse_phandle(timings_np, "native-mode", 0);
++ /* assume first child as native mode if none provided */
++ if (!entry)
++ entry = of_get_next_child(np, NULL);
++ /* if there is no child, it is useless to go on */
++ if (!entry) {
++ pr_err("%s: no timing specifications given\n",
++ of_node_full_name(np));
++ goto entryfail;
++ }
++
++ pr_debug("%s: using %s as default timing\n",
++ of_node_full_name(np), entry->name);
++
++ native_mode = entry;
++
++ disp->num_timings = of_get_child_count(timings_np);
++ if (disp->num_timings == 0) {
++ /* should never happen, as entry was already found above */
++ pr_err("%s: no timings specified\n", of_node_full_name(np));
++ goto entryfail;
++ }
++
++ disp->timings = kzalloc(sizeof(struct display_timing *) *
++ disp->num_timings, GFP_KERNEL);
++ if (!disp->timings) {
++ pr_err("%s: could not allocate timings array\n",
++ of_node_full_name(np));
++ goto entryfail;
++ }
++
++ disp->num_timings = 0;
++ disp->native_mode = 0;
++
++ for_each_child_of_node(timings_np, entry) {
++ struct display_timing *dt;
++
++ dt = of_get_display_timing(entry);
++ if (!dt) {
++ /*
++ * to not encourage wrong devicetrees, fail in case of
++ * an error
++ */
++ pr_err("%s: error in timing %d\n",
++ of_node_full_name(np), disp->num_timings + 1);
++ goto timingfail;
++ }
++
++ if (native_mode == entry)
++ disp->native_mode = disp->num_timings;
++
++ disp->timings[disp->num_timings] = dt;
++ disp->num_timings++;
++ }
++ of_node_put(timings_np);
++ /*
++ * native_mode points to the device_node returned by of_parse_phandle
++ * therefore call of_node_put on it
++ */
++ of_node_put(native_mode);
++
++ pr_debug("%s: got %d timings. Using timing #%d as default\n",
++ of_node_full_name(np), disp->num_timings,
++ disp->native_mode + 1);
++
++ return disp;
++
++timingfail:
++ if (native_mode)
++ of_node_put(native_mode);
++ display_timings_release(disp);
++entryfail:
++ kfree(disp);
++dispfail:
++ of_node_put(timings_np);
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(of_get_display_timings);
++
++/**
++ * of_display_timings_exist - check if a display-timings node is provided
++ * @np: device_node with the timing
++ **/
++int of_display_timings_exist(struct device_node *np)
++{
++ struct device_node *timings_np;
++
++ if (!np)
++ return -EINVAL;
++
++ timings_np = of_parse_phandle(np, "display-timings", 0);
++ if (!timings_np)
++ return -EINVAL;
++
++ of_node_put(timings_np);
++ return 1;
++}
++EXPORT_SYMBOL_GPL(of_display_timings_exist);
+diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c
+new file mode 100644
+index 0000000..5b8066c
+--- /dev/null
++++ b/drivers/video/of_videomode.c
+@@ -0,0 +1,54 @@
++/*
++ * generic videomode helper
++ *
++ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
++ *
++ * This file is released under the GPLv2
++ */
++#include <linux/errno.h>
++#include <linux/export.h>
++#include <linux/of.h>
++#include <video/display_timing.h>
++#include <video/of_display_timing.h>
++#include <video/of_videomode.h>
++#include <video/videomode.h>
++
++/**
++ * of_get_videomode - get the videomode #<index> from devicetree
++ * @np - devicenode with the display_timings
++ * @vm - set to return value
++ * @index - index into list of display_timings
++ * (Set this to OF_USE_NATIVE_MODE to use whatever mode is
++ * specified as native mode in the DT.)
++ *
++ * DESCRIPTION:
++ * Get a list of all display timings and put the one
++ * specified by index into *vm. This function should only be used, if
++ * only one videomode is to be retrieved. A driver that needs to work
++ * with multiple/all videomodes should work with
++ * of_get_display_timings instead.
++ **/
++int of_get_videomode(struct device_node *np, struct videomode *vm,
++ int index)
++{
++ struct display_timings *disp;
++ int ret;
++
++ disp = of_get_display_timings(np);
++ if (!disp) {
++ pr_err("%s: no timings specified\n", of_node_full_name(np));
++ return -EINVAL;
++ }
++
++ if (index == OF_USE_NATIVE_MODE)
++ index = disp->native_mode;
++
++ ret = videomode_from_timing(disp, vm, index);
++ if (ret)
++ return ret;
++
++ display_timings_release(disp);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(of_get_videomode);
+diff --git a/include/video/of_display_timing.h b/include/video/of_display_timing.h
+new file mode 100644
+index 0000000..8016eb7
+--- /dev/null
++++ b/include/video/of_display_timing.h
+@@ -0,0 +1,20 @@
++/*
++ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
++ *
++ * display timings of helpers
++ *
++ * This file is released under the GPLv2
++ */
++
++#ifndef __LINUX_OF_DISPLAY_TIMING_H
++#define __LINUX_OF_DISPLAY_TIMING_H
++
++struct device_node;
++struct display_timings;
++
++#define OF_USE_NATIVE_MODE -1
++
++struct display_timings *of_get_display_timings(struct device_node *np);
++int of_display_timings_exist(struct device_node *np);
++
++#endif
+diff --git a/include/video/of_videomode.h b/include/video/of_videomode.h
+new file mode 100644
+index 0000000..a07efcc
+--- /dev/null
++++ b/include/video/of_videomode.h
+@@ -0,0 +1,18 @@
++/*
++ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
++ *
++ * videomode of-helpers
++ *
++ * This file is released under the GPLv2
++ */
++
++#ifndef __LINUX_OF_VIDEOMODE_H
++#define __LINUX_OF_VIDEOMODE_H
++
++struct device_node;
++struct videomode;
++
++int of_get_videomode(struct device_node *np, struct videomode *vm,
++ int index);
++
++#endif /* __LINUX_OF_VIDEOMODE_H */
diff --git a/patches/linux-3.8.13/0074-fbmon-add-videomode-helpers.patch b/patches/linux-3.8.13/0074-fbmon-add-videomode-helpers.patch
new file mode 100644
index 0000000..b0a1dda
--- /dev/null
+++ b/patches/linux-3.8.13/0074-fbmon-add-videomode-helpers.patch
@@ -0,0 +1,110 @@
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Wed, 19 Dec 2012 16:36:57 +0530
+Subject: [PATCH] fbmon: add videomode helpers
+
+Add a function to convert from the generic videomode to a fb_videomode.
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/video/fbmon.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/fb.h | 4 ++++
+ 2 files changed, 56 insertions(+)
+
+diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
+index cef6557..17ce135 100644
+--- a/drivers/video/fbmon.c
++++ b/drivers/video/fbmon.c
+@@ -31,6 +31,7 @@
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include <video/edid.h>
++#include <video/videomode.h>
+ #ifdef CONFIG_PPC_OF
+ #include <asm/prom.h>
+ #include <asm/pci-bridge.h>
+@@ -1373,6 +1374,57 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
+ kfree(timings);
+ return err;
+ }
++
++#if IS_ENABLED(CONFIG_VIDEOMODE)
++int fb_videomode_from_videomode(const struct videomode *vm,
++ struct fb_videomode *fbmode)
++{
++ unsigned int htotal, vtotal;
++
++ fbmode->xres = vm->hactive;
++ fbmode->left_margin = vm->hback_porch;
++ fbmode->right_margin = vm->hfront_porch;
++ fbmode->hsync_len = vm->hsync_len;
++
++ fbmode->yres = vm->vactive;
++ fbmode->upper_margin = vm->vback_porch;
++ fbmode->lower_margin = vm->vfront_porch;
++ fbmode->vsync_len = vm->vsync_len;
++
++ /* prevent division by zero in KHZ2PICOS macro */
++ fbmode->pixclock = vm->pixelclock ?
++ KHZ2PICOS(vm->pixelclock / 1000) : 0;
++
++ fbmode->sync = 0;
++ fbmode->vmode = 0;
++ if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
++ fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
++ if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
++ fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
++ if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
++ fbmode->vmode |= FB_VMODE_INTERLACED;
++ if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
++ fbmode->vmode |= FB_VMODE_DOUBLE;
++ fbmode->flag = 0;
++
++ htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
++ vm->hsync_len;
++ vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
++ vm->vsync_len;
++ /* prevent division by zero */
++ if (htotal && vtotal) {
++ fbmode->refresh = vm->pixelclock / (htotal * vtotal);
++ /* a mode must have htotal and vtotal != 0 or it is invalid */
++ } else {
++ fbmode->refresh = 0;
++ return -EINVAL;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
++#endif
++
+ #else
+ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+ {
+diff --git a/include/linux/fb.h b/include/linux/fb.h
+index c7a9571..100a176 100644
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -19,6 +19,7 @@ struct vm_area_struct;
+ struct fb_info;
+ struct device;
+ struct file;
++struct videomode;
+
+ /* Definitions below are used in the parsed monitor specs */
+ #define FB_DPMS_ACTIVE_OFF 1
+@@ -714,6 +715,9 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
+ extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
+ extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
+
++extern int fb_videomode_from_videomode(const struct videomode *vm,
++ struct fb_videomode *fbmode);
++
+ /* drivers/video/modedb.c */
+ #define VESA_MODEDB_SIZE 34
+ extern void fb_var_to_videomode(struct fb_videomode *mode,
diff --git a/patches/linux-3.8.13/0075-fbmon-add-of_videomode-helpers.patch b/patches/linux-3.8.13/0075-fbmon-add-of_videomode-helpers.patch
new file mode 100644
index 0000000..f6034f5
--- /dev/null
+++ b/patches/linux-3.8.13/0075-fbmon-add-of_videomode-helpers.patch
@@ -0,0 +1,100 @@
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Wed, 19 Dec 2012 16:37:00 +0530
+Subject: [PATCH] fbmon: add of_videomode helpers
+
+Add helper to get fb_videomode from devicetree.
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/video/fbmon.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ include/linux/fb.h | 4 ++++
+ 2 files changed, 46 insertions(+)
+
+diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
+index 17ce135..94ad0f7 100644
+--- a/drivers/video/fbmon.c
++++ b/drivers/video/fbmon.c
+@@ -31,6 +31,7 @@
+ #include <linux/pci.h>
+ #include <linux/slab.h>
+ #include <video/edid.h>
++#include <video/of_videomode.h>
+ #include <video/videomode.h>
+ #ifdef CONFIG_PPC_OF
+ #include <asm/prom.h>
+@@ -1425,6 +1426,47 @@ int fb_videomode_from_videomode(const struct videomode *vm,
+ EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
+ #endif
+
++#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
++static inline void dump_fb_videomode(const struct fb_videomode *m)
++{
++ pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
++ m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
++ m->right_margin, m->upper_margin, m->lower_margin,
++ m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
++}
++
++/**
++ * of_get_fb_videomode - get a fb_videomode from devicetree
++ * @np: device_node with the timing specification
++ * @fb: will be set to the return value
++ * @index: index into the list of display timings in devicetree
++ *
++ * DESCRIPTION:
++ * This function is expensive and should only be used, if only one mode is to be
++ * read from DT. To get multiple modes start with of_get_display_timings ond
++ * work with that instead.
++ */
++int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
++ int index)
++{
++ struct videomode vm;
++ int ret;
++
++ ret = of_get_videomode(np, &vm, index);
++ if (ret)
++ return ret;
++
++ fb_videomode_from_videomode(&vm, fb);
++
++ pr_debug("%s: got %dx%d display mode from %s\n",
++ of_node_full_name(np), vm.hactive, vm.vactive, np->name);
++ dump_fb_videomode(fb);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(of_get_fb_videomode);
++#endif
++
+ #else
+ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+ {
+diff --git a/include/linux/fb.h b/include/linux/fb.h
+index 100a176..58b9860 100644
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -20,6 +20,7 @@ struct fb_info;
+ struct device;
+ struct file;
+ struct videomode;
++struct device_node;
+
+ /* Definitions below are used in the parsed monitor specs */
+ #define FB_DPMS_ACTIVE_OFF 1
+@@ -715,6 +716,9 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
+ extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
+ extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
+
++extern int of_get_fb_videomode(struct device_node *np,
++ struct fb_videomode *fb,
++ int index);
+ extern int fb_videomode_from_videomode(const struct videomode *vm,
+ struct fb_videomode *fbmode);
+
diff --git a/patches/linux-3.8.13/0076-drm_modes-add-videomode-helpers.patch b/patches/linux-3.8.13/0076-drm_modes-add-videomode-helpers.patch
new file mode 100644
index 0000000..c1da52f
--- /dev/null
+++ b/patches/linux-3.8.13/0076-drm_modes-add-videomode-helpers.patch
@@ -0,0 +1,96 @@
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Wed, 19 Dec 2012 16:37:03 +0530
+Subject: [PATCH] drm_modes: add videomode helpers
+
+Add conversion from videomode to drm_display_mode
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/gpu/drm/drm_modes.c | 37 +++++++++++++++++++++++++++++++++++++
+ include/drm/drmP.h | 5 +++++
+ 2 files changed, 42 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
+index d8da30e..9f3f20b 100644
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -35,6 +35,7 @@
+ #include <linux/export.h>
+ #include <drm/drmP.h>
+ #include <drm/drm_crtc.h>
++#include <video/videomode.h>
+
+ /**
+ * drm_mode_debug_printmodeline - debug print a mode
+@@ -504,6 +505,42 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
+ }
+ EXPORT_SYMBOL(drm_gtf_mode);
+
++#if IS_ENABLED(CONFIG_VIDEOMODE)
++int drm_display_mode_from_videomode(const struct videomode *vm,
++ struct drm_display_mode *dmode)
++{
++ dmode->hdisplay = vm->hactive;
++ dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
++ dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
++ dmode->htotal = dmode->hsync_end + vm->hback_porch;
++
++ dmode->vdisplay = vm->vactive;
++ dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
++ dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
++ dmode->vtotal = dmode->vsync_end + vm->vback_porch;
++
++ dmode->clock = vm->pixelclock / 1000;
++
++ dmode->flags = 0;
++ if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
++ dmode->flags |= DRM_MODE_FLAG_PHSYNC;
++ else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW)
++ dmode->flags |= DRM_MODE_FLAG_NHSYNC;
++ if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH)
++ dmode->flags |= DRM_MODE_FLAG_PVSYNC;
++ else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW)
++ dmode->flags |= DRM_MODE_FLAG_NVSYNC;
++ if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
++ dmode->flags |= DRM_MODE_FLAG_INTERLACE;
++ if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
++ dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
++ drm_mode_set_name(dmode);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
++#endif
++
+ /**
+ * drm_mode_set_name - set the name on a mode
+ * @mode: name will be set in this mode
+diff --git a/include/drm/drmP.h b/include/drm/drmP.h
+index 881fb15..24ef0cf 100644
+--- a/include/drm/drmP.h
++++ b/include/drm/drmP.h
+@@ -85,6 +85,8 @@ struct module;
+ struct drm_file;
+ struct drm_device;
+
++struct videomode;
++
+ #include <drm/drm_os_linux.h>
+ #include <drm/drm_hashtab.h>
+ #include <drm/drm_mm.h>
+@@ -1456,6 +1458,9 @@ extern struct drm_display_mode *
+ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
+ struct drm_cmdline_mode *cmd);
+
++extern int drm_display_mode_from_videomode(const struct videomode *vm,
++ struct drm_display_mode *dmode);
++
+ /* Modesetting support */
+ extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
+ extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
diff --git a/patches/linux-3.8.13/0077-drm_modes-add-of_videomode-helpers.patch b/patches/linux-3.8.13/0077-drm_modes-add-of_videomode-helpers.patch
new file mode 100644
index 0000000..b1091d8
--- /dev/null
+++ b/patches/linux-3.8.13/0077-drm_modes-add-of_videomode-helpers.patch
@@ -0,0 +1,91 @@
+From: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Date: Wed, 19 Dec 2012 16:37:06 +0530
+Subject: [PATCH] drm_modes: add of_videomode helpers
+
+Add helper to get drm_display_mode from devicetree.
+
+Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
+Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/gpu/drm/drm_modes.c | 33 +++++++++++++++++++++++++++++++++
+ include/drm/drmP.h | 4 ++++
+ 2 files changed, 37 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
+index 9f3f20b..04fa6f1 100644
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -35,6 +35,7 @@
+ #include <linux/export.h>
+ #include <drm/drmP.h>
+ #include <drm/drm_crtc.h>
++#include <video/of_videomode.h>
+ #include <video/videomode.h>
+
+ /**
+@@ -541,6 +542,38 @@ int drm_display_mode_from_videomode(const struct videomode *vm,
+ EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
+ #endif
+
++#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
++/**
++ * of_get_drm_display_mode - get a drm_display_mode from devicetree
++ * @np: device_node with the timing specification
++ * @dmode: will be set to the return value
++ * @index: index into the list of display timings in devicetree
++ *
++ * This function is expensive and should only be used, if only one mode is to be
++ * read from DT. To get multiple modes start with of_get_display_timings and
++ * work with that instead.
++ */
++int of_get_drm_display_mode(struct device_node *np,
++ struct drm_display_mode *dmode, int index)
++{
++ struct videomode vm;
++ int ret;
++
++ ret = of_get_videomode(np, &vm, index);
++ if (ret)
++ return ret;
++
++ drm_display_mode_from_videomode(&vm, dmode);
++
++ pr_debug("%s: got %dx%d display mode from %s\n",
++ of_node_full_name(np), vm.hactive, vm.vactive, np->name);
++ drm_mode_debug_printmodeline(dmode);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
++#endif
++
+ /**
+ * drm_mode_set_name - set the name on a mode
+ * @mode: name will be set in this mode
+diff --git a/include/drm/drmP.h b/include/drm/drmP.h
+index 24ef0cf..98efdde 100644
+--- a/include/drm/drmP.h
++++ b/include/drm/drmP.h
+@@ -85,6 +85,7 @@ struct module;
+ struct drm_file;
+ struct drm_device;
+
++struct device_node;
+ struct videomode;
+
+ #include <drm/drm_os_linux.h>
+@@ -1460,6 +1461,9 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
+
+ extern int drm_display_mode_from_videomode(const struct videomode *vm,
+ struct drm_display_mode *dmode);
++extern int of_get_drm_display_mode(struct device_node *np,
++ struct drm_display_mode *dmode,
++ int index);
+
+ /* Modesetting support */
+ extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
diff --git a/patches/linux-3.8.13/0078-fbmon-fix-build-error.patch b/patches/linux-3.8.13/0078-fbmon-fix-build-error.patch
new file mode 100644
index 0000000..d462dbe
--- /dev/null
+++ b/patches/linux-3.8.13/0078-fbmon-fix-build-error.patch
@@ -0,0 +1,33 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Wed, 2 Jan 2013 19:16:40 +0530
+Subject: [PATCH] fbmon: fix build error
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ include/linux/fb.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/include/linux/fb.h b/include/linux/fb.h
+index 58b9860..0ce30d1 100644
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -716,9 +716,19 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
+ extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
+ extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
+
++#if defined(CONFIG_OF_VIDEOMODE) && defined(CONFIG_FB_MODE_HELPERS)
+ extern int of_get_fb_videomode(struct device_node *np,
+ struct fb_videomode *fb,
+ int index);
++#else
++static inline int of_get_fb_videomode(struct device_node *np,
++ struct fb_videomode *fb,
++ int index)
++{
++ return -EINVAL;
++}
++#endif
++
+ extern int fb_videomode_from_videomode(const struct videomode *vm,
+ struct fb_videomode *fbmode);
+
diff --git a/patches/linux-3.8.13/0079-of-display-timings-use-of_get_child_by_name.patch b/patches/linux-3.8.13/0079-of-display-timings-use-of_get_child_by_name.patch
new file mode 100644
index 0000000..61f6fb9
--- /dev/null
+++ b/patches/linux-3.8.13/0079-of-display-timings-use-of_get_child_by_name.patch
@@ -0,0 +1,22 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 28 Jan 2013 16:36:45 +0100
+Subject: [PATCH] of display timings: use of_get_child_by_name
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/video/of_display_timing.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
+index 13ecd98..c0ea594 100644
+--- a/drivers/video/of_display_timing.c
++++ b/drivers/video/of_display_timing.c
+@@ -125,7 +125,7 @@ struct display_timings *of_get_display_timings(struct device_node *np)
+ return NULL;
+ }
+
+- timings_np = of_find_node_by_name(np, "display-timings");
++ timings_np = of_get_child_by_name(np, "display-timings");
+ if (!timings_np) {
+ pr_err("%s: could not find display-timings node\n",
+ of_node_full_name(np));
diff --git a/patches/linux-3.8.13/0080-da8xx-Allow-use-by-am33xx-based-devices.patch b/patches/linux-3.8.13/0080-da8xx-Allow-use-by-am33xx-based-devices.patch
new file mode 100644
index 0000000..bd6a211
--- /dev/null
+++ b/patches/linux-3.8.13/0080-da8xx-Allow-use-by-am33xx-based-devices.patch
@@ -0,0 +1,24 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 17 Dec 2012 15:32:48 +0530
+Subject: [PATCH] da8xx: Allow use by am33xx based devices
+
+This driver can be used for AM33xx devices, like the popular beaglebone.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/video/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 4abcf9c..f8f0a41 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2225,7 +2225,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.8.13/0081-video-da8xx-fb-fb_check_var-enhancement.patch b/patches/linux-3.8.13/0081-video-da8xx-fb-fb_check_var-enhancement.patch
new file mode 100644
index 0000000..26b4d1f
--- /dev/null
+++ b/patches/linux-3.8.13/0081-video-da8xx-fb-fb_check_var-enhancement.patch
@@ -0,0 +1,52 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Wed, 28 Nov 2012 19:21:51 +0530
+Subject: [PATCH] video: da8xx-fb: fb_check_var enhancement
+
+Check whether "struct fb_var_screeninfo" fields are sane, if not
+update it to be within allowed limits.
+
+If user sends down buggy "var" values, this will bring those within
+allowable limits. And fb_set_par is not supposed to change "var"
+values, fb_check_var has to ensure that values are proper.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 0810939..d00dd17 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -888,6 +888,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+ {
+ int err = 0;
++ struct da8xx_fb_par *par = info->par;
++ int bpp = var->bits_per_pixel >> 3;
++ unsigned long line_size = var->xres_virtual * bpp;
+
+ if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
+ return -EINVAL;
+@@ -955,6 +958,21 @@ static int fb_check_var(struct fb_var_screeninfo *var,
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
++
++ if (line_size * var->yres_virtual > par->vram_size)
++ var->yres_virtual = par->vram_size / line_size;
++
++ if (var->yres > var->yres_virtual)
++ var->yres = var->yres_virtual;
++
++ if (var->xres > var->xres_virtual)
++ var->xres = var->xres_virtual;
++
++ if (var->xres + var->xoffset > var->xres_virtual)
++ var->xoffset = var->xres_virtual - var->xres;
++ if (var->yres + var->yoffset > var->yres_virtual)
++ var->yoffset = var->yres_virtual - var->yres;
++
+ return err;
+ }
+
diff --git a/patches/linux-3.8.13/0082-video-da8xx-fb-simplify-lcd_reset.patch b/patches/linux-3.8.13/0082-video-da8xx-fb-simplify-lcd_reset.patch
new file mode 100644
index 0000000..fe37dfb
--- /dev/null
+++ b/patches/linux-3.8.13/0082-video-da8xx-fb-simplify-lcd_reset.patch
@@ -0,0 +1,33 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Thu, 6 Dec 2012 21:54:58 +0530
+Subject: [PATCH] video: da8xx-fb: simplify lcd_reset
+
+lcd_reset function doesn't require any arguement, remove it.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index d00dd17..52977b1 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -681,7 +681,7 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ }
+ #undef CNVT_TOHW
+
+-static void lcd_reset(struct da8xx_fb_par *par)
++static void da8xx_fb_lcd_reset(void)
+ {
+ /* Disable the Raster if previously Enabled */
+ lcd_disable_raster(false);
+@@ -721,7 +721,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
+ u32 bpp;
+ int ret = 0;
+
+- lcd_reset(par);
++ da8xx_fb_lcd_reset();
+
+ /* Calculate the divider */
+ lcd_calc_clk_divider(par);
diff --git a/patches/linux-3.8.13/0083-video-da8xx-fb-use-modedb-helper-to-update-var.patch b/patches/linux-3.8.13/0083-video-da8xx-fb-use-modedb-helper-to-update-var.patch
new file mode 100644
index 0000000..79f1767
--- /dev/null
+++ b/patches/linux-3.8.13/0083-video-da8xx-fb-use-modedb-helper-to-update-var.patch
@@ -0,0 +1,58 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Thu, 6 Dec 2012 22:46:32 +0530
+Subject: [PATCH] video: da8xx-fb: use modedb helper to update var
+
+modedb structure is now used to store panel information, run modedb
+helper over it for initial update of "var" information instead of
+equating each fields.
+
+While at it, remove redundant update of bits_per_pixel.
+
+Note: pixclock is overridden with proper value using an existing code
+as currently modedb is having it in Hz instead of ps, this would be
+fixed in a later change and this overide would be removed.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 52977b1..a1f6544 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1329,6 +1329,8 @@ static int fb_probe(struct platform_device *device)
+ par->panel_power_ctrl(1);
+ }
+
++ fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
++
+ if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
+ dev_err(&device->dev, "lcd_init failed\n");
+ ret = -EFAULT;
+@@ -1381,25 +1383,9 @@ static int fb_probe(struct platform_device *device)
+ goto err_release_pl_mem;
+ }
+
+- /* Initialize par */
+- da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
+-
+- da8xx_fb_var.xres = lcdc_info->xres;
+- da8xx_fb_var.xres_virtual = lcdc_info->xres;
+-
+- da8xx_fb_var.yres = lcdc_info->yres;
+- da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
+-
+ da8xx_fb_var.grayscale =
+ lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
+ da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
+-
+- da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
+- da8xx_fb_var.vsync_len = lcdc_info->vsync_len;
+- da8xx_fb_var.right_margin = lcdc_info->right_margin;
+- da8xx_fb_var.left_margin = lcdc_info->left_margin;
+- da8xx_fb_var.lower_margin = lcdc_info->lower_margin;
+- da8xx_fb_var.upper_margin = lcdc_info->upper_margin;
+ da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
+
+ /* Initialize fbinfo */
diff --git a/patches/linux-3.8.13/0084-video-da8xx-fb-remove-unneeded-var-initialization.patch b/patches/linux-3.8.13/0084-video-da8xx-fb-remove-unneeded-var-initialization.patch
new file mode 100644
index 0000000..2c704f1
--- /dev/null
+++ b/patches/linux-3.8.13/0084-video-da8xx-fb-remove-unneeded-var-initialization.patch
@@ -0,0 +1,52 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Thu, 6 Dec 2012 22:46:32 +0530
+Subject: [PATCH] video: da8xx-fb: remove unneeded "var" initialization
+
+modedb helper now updates "var" information based on the detected
+panel, remove the unnecessary initialization.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 22 +---------------------
+ 1 file changed, 1 insertion(+), 21 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index a1f6544..18834fa 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -131,10 +131,6 @@
+
+ #define WSI_TIMEOUT 50
+ #define PALETTE_SIZE 256
+-#define LEFT_MARGIN 64
+-#define RIGHT_MARGIN 64
+-#define UPPER_MARGIN 32
+-#define LOWER_MARGIN 32
+
+ static void __iomem *da8xx_fb_reg_base;
+ static struct resource *lcdc_regs;
+@@ -184,23 +180,7 @@ struct da8xx_fb_par {
+ u32 pseudo_palette[16];
+ };
+
+-/* Variable Screen Information */
+-static struct fb_var_screeninfo da8xx_fb_var = {
+- .xoffset = 0,
+- .yoffset = 0,
+- .transp = {0, 0, 0},
+- .nonstd = 0,
+- .activate = 0,
+- .height = -1,
+- .width = -1,
+- .accel_flags = 0,
+- .left_margin = LEFT_MARGIN,
+- .right_margin = RIGHT_MARGIN,
+- .upper_margin = UPPER_MARGIN,
+- .lower_margin = LOWER_MARGIN,
+- .sync = 0,
+- .vmode = FB_VMODE_NONINTERLACED
+-};
++static struct fb_var_screeninfo da8xx_fb_var;
+
+ static struct fb_fix_screeninfo da8xx_fb_fix = {
+ .id = "DA8xx FB Drv",
diff --git a/patches/linux-3.8.13/0085-video-da8xx-fb-store-current-display-information.patch b/patches/linux-3.8.13/0085-video-da8xx-fb-store-current-display-information.patch
new file mode 100644
index 0000000..bed8d30
--- /dev/null
+++ b/patches/linux-3.8.13/0085-video-da8xx-fb-store-current-display-information.patch
@@ -0,0 +1,40 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Thu, 6 Dec 2012 23:18:07 +0530
+Subject: [PATCH] video: da8xx-fb: store current display information
+
+store current videomode and controller data so that reconfiguring can
+be done easily. Reconfiguring would be required in fb_set_par, which
+is going to be added soon.
+
+If these details are not stored, the work probe does to retrieve these
+information would have to repeated at the place of reconfiguring and
+modifying platform data would be necessary to handle controller data
+changes like bpp.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 18834fa..d060f14 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -178,6 +178,8 @@ struct da8xx_fb_par {
+ #endif
+ void (*panel_power_ctrl)(int);
+ u32 pseudo_palette[16];
++ struct fb_videomode mode;
++ struct lcd_ctrl_config cfg;
+ };
+
+ static struct fb_var_screeninfo da8xx_fb_var;
+@@ -1310,6 +1312,8 @@ static int fb_probe(struct platform_device *device)
+ }
+
+ fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
++ fb_var_to_videomode(&par->mode, &da8xx_fb_var);
++ par->cfg = *lcd_cfg;
+
+ if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
+ dev_err(&device->dev, "lcd_init failed\n");
diff --git a/patches/linux-3.8.13/0086-video-da8xx-fb-store-clk-rate-even-if-CPUFREQ.patch b/patches/linux-3.8.13/0086-video-da8xx-fb-store-clk-rate-even-if-CPUFREQ.patch
new file mode 100644
index 0000000..bca2443
--- /dev/null
+++ b/patches/linux-3.8.13/0086-video-da8xx-fb-store-clk-rate-even-if-CPUFREQ.patch
@@ -0,0 +1,37 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Fri, 7 Dec 2012 02:00:23 +0530
+Subject: [PATCH] video: da8xx-fb: store clk rate even if !CPUFREQ
+
+store lcd clk rate always, i.e. irrespective of whether CPUFREQ is
+enabled or not. This can be used to get clk rate directly instead of
+enquiring with clock framework with clk handle every time.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index d060f14..f1d88ac 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -174,8 +174,8 @@ struct da8xx_fb_par {
+ unsigned int which_dma_channel_done;
+ #ifdef CONFIG_CPU_FREQ
+ struct notifier_block freq_transition;
+- unsigned int lcd_fck_rate;
+ #endif
++ unsigned int lcd_fck_rate;
+ void (*panel_power_ctrl)(int);
+ u32 pseudo_palette[16];
+ struct fb_videomode mode;
+@@ -1302,9 +1302,7 @@ static int fb_probe(struct platform_device *device)
+
+ par = da8xx_fb_info->par;
+ par->lcdc_clk = fb_clk;
+-#ifdef CONFIG_CPU_FREQ
+ par->lcd_fck_rate = clk_get_rate(fb_clk);
+-#endif
+ par->pxl_clk = lcdc_info->pixclock;
+ if (fb_pdata->panel_power_ctrl) {
+ par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
diff --git a/patches/linux-3.8.13/0087-video-da8xx-fb-pix-clk-and-clk-div-handling-cleanup.patch b/patches/linux-3.8.13/0087-video-da8xx-fb-pix-clk-and-clk-div-handling-cleanup.patch
new file mode 100644
index 0000000..5eabb6a
--- /dev/null
+++ b/patches/linux-3.8.13/0087-video-da8xx-fb-pix-clk-and-clk-div-handling-cleanup.patch
@@ -0,0 +1,150 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Tue, 4 Dec 2012 17:34:03 +0530
+Subject: [PATCH] video: da8xx-fb: pix clk and clk div handling cleanup
+
+Use the new modedb field to store pix clk. Reorganize existing clock
+divider functions with names now corresponding to what they do, add
+common function prefix.
+
+Fix existing panel modedb pixclock to be in ps instead of Hz. This
+needed a change in the way clock divider is calculated. As modedb
+pixclock information is now in ps, override on "var" pixclock over
+modedb to var conversion is removed.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 48 +++++++++++++++++-----------------------------
+ 1 file changed, 18 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index f1d88ac..7f08644 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -160,7 +160,6 @@ struct da8xx_fb_par {
+ struct clk *lcdc_clk;
+ int irq;
+ unsigned int palette_sz;
+- unsigned int pxl_clk;
+ int blank;
+ wait_queue_head_t vsync_wait;
+ int vsync_flag;
+@@ -201,7 +200,7 @@ static struct fb_videomode known_lcd_panels[] = {
+ .name = "Sharp_LCD035Q3DG01",
+ .xres = 320,
+ .yres = 240,
+- .pixclock = 4608000,
++ .pixclock = 217014,
+ .left_margin = 6,
+ .right_margin = 8,
+ .upper_margin = 2,
+@@ -216,7 +215,7 @@ static struct fb_videomode known_lcd_panels[] = {
+ .name = "Sharp_LK043T1DG01",
+ .xres = 480,
+ .yres = 272,
+- .pixclock = 7833600,
++ .pixclock = 127655,
+ .left_margin = 2,
+ .right_margin = 2,
+ .upper_margin = 2,
+@@ -231,7 +230,7 @@ static struct fb_videomode known_lcd_panels[] = {
+ .name = "SP10Q010",
+ .xres = 320,
+ .yres = 240,
+- .pixclock = 7833600,
++ .pixclock = 127655,
+ .left_margin = 10,
+ .right_margin = 10,
+ .upper_margin = 10,
+@@ -680,13 +679,14 @@ static void da8xx_fb_lcd_reset(void)
+ }
+ }
+
+-static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
++static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
++ unsigned pixclock)
+ {
+- unsigned int lcd_clk, div;
+-
+- lcd_clk = clk_get_rate(par->lcdc_clk);
+- div = lcd_clk / par->pxl_clk;
++ return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
++}
+
++static inline void da8xx_fb_config_clk_divider(unsigned div)
++{
+ /* Configure the LCD clock divisor. */
+ lcdc_write(LCD_CLK_DIVISOR(div) |
+ (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+@@ -694,7 +694,14 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
+ if (lcd_revision == LCD_VERSION_2)
+ lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
+ LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
++}
++
++static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
++ struct fb_videomode *mode)
++{
++ unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock);
+
++ da8xx_fb_config_clk_divider(div);
+ }
+
+ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
+@@ -705,8 +712,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
+
+ da8xx_fb_lcd_reset();
+
+- /* Calculate the divider */
+- lcd_calc_clk_divider(par);
++ da8xx_fb_calc_config_clk_divider(par, panel);
+
+ if (panel->sync & FB_SYNC_CLK_INVERT)
+ lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
+@@ -969,7 +975,7 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
+ if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
+ par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
+ lcd_disable_raster(true);
+- lcd_calc_clk_divider(par);
++ da8xx_fb_calc_config_clk_divider(par, &par->mode);
+ if (par->blank == FB_BLANK_UNBLANK)
+ lcd_enable_raster();
+ }
+@@ -1195,22 +1201,6 @@ static struct fb_ops da8xx_fb_ops = {
+ .fb_blank = cfb_blank,
+ };
+
+-/* Calculate and return pixel clock period in pico seconds */
+-static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par)
+-{
+- unsigned int lcd_clk, div;
+- unsigned int configured_pix_clk;
+- unsigned long long pix_clk_period_picosec = 1000000000000ULL;
+-
+- lcd_clk = clk_get_rate(par->lcdc_clk);
+- div = lcd_clk / par->pxl_clk;
+- configured_pix_clk = (lcd_clk / div);
+-
+- do_div(pix_clk_period_picosec, configured_pix_clk);
+-
+- return pix_clk_period_picosec;
+-}
+-
+ static int fb_probe(struct platform_device *device)
+ {
+ struct da8xx_lcdc_platform_data *fb_pdata =
+@@ -1303,7 +1293,6 @@ static int fb_probe(struct platform_device *device)
+ par = da8xx_fb_info->par;
+ par->lcdc_clk = fb_clk;
+ par->lcd_fck_rate = clk_get_rate(fb_clk);
+- par->pxl_clk = lcdc_info->pixclock;
+ if (fb_pdata->panel_power_ctrl) {
+ par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
+ par->panel_power_ctrl(1);
+@@ -1368,7 +1357,6 @@ static int fb_probe(struct platform_device *device)
+ da8xx_fb_var.grayscale =
+ lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
+ da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
+- da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
+
+ /* Initialize fbinfo */
+ da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
diff --git a/patches/linux-3.8.13/0088-video-da8xx-fb-store-struct-device.patch b/patches/linux-3.8.13/0088-video-da8xx-fb-store-struct-device.patch
new file mode 100644
index 0000000..a22c61c
--- /dev/null
+++ b/patches/linux-3.8.13/0088-video-da8xx-fb-store-struct-device.patch
@@ -0,0 +1,32 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Wed, 5 Dec 2012 12:16:17 +0530
+Subject: [PATCH] video: da8xx-fb: store struct device *
+
+store struct device pointer so that dev_dbg/err can be used outside
+of probe.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 7f08644..a5341d0 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -150,6 +150,7 @@ static inline void lcdc_write(unsigned int val, unsigned int addr)
+ }
+
+ struct da8xx_fb_par {
++ struct device *dev;
+ resource_size_t p_palette_base;
+ unsigned char *v_palette_base;
+ dma_addr_t vram_phys;
+@@ -1291,6 +1292,7 @@ static int fb_probe(struct platform_device *device)
+ }
+
+ par = da8xx_fb_info->par;
++ par->dev = &device->dev;
+ par->lcdc_clk = fb_clk;
+ par->lcd_fck_rate = clk_get_rate(fb_clk);
+ if (fb_pdata->panel_power_ctrl) {
diff --git a/patches/linux-3.8.13/0089-video-da8xx-fb-report-correct-pixclock.patch b/patches/linux-3.8.13/0089-video-da8xx-fb-report-correct-pixclock.patch
new file mode 100644
index 0000000..cc5abcf
--- /dev/null
+++ b/patches/linux-3.8.13/0089-video-da8xx-fb-report-correct-pixclock.patch
@@ -0,0 +1,41 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Tue, 4 Dec 2012 18:40:45 +0530
+Subject: [PATCH] video: da8xx-fb: report correct pixclock
+
+Update "var" pixclock with the value that is configurable in hardware.
+This lets user know the actual pixclock.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index a5341d0..0f73c76 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -686,6 +686,15 @@ static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
+ return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
+ }
+
++static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
++ unsigned pixclock)
++{
++ unsigned div;
++
++ div = da8xx_fb_calc_clk_divider(par, pixclock);
++ return KHZ2PICOS(par->lcd_fck_rate / (1000 * div));
++}
++
+ static inline void da8xx_fb_config_clk_divider(unsigned div)
+ {
+ /* Configure the LCD clock divisor. */
+@@ -962,6 +971,8 @@ static int fb_check_var(struct fb_var_screeninfo *var,
+ if (var->yres + var->yoffset > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+
++ var->pixclock = da8xx_fb_round_clk(par, var->pixclock);
++
+ return err;
+ }
+
diff --git a/patches/linux-3.8.13/0090-video-da8xx-fb-fb_set_par-support.patch b/patches/linux-3.8.13/0090-video-da8xx-fb-fb_set_par-support.patch
new file mode 100644
index 0000000..dbfdc1c
--- /dev/null
+++ b/patches/linux-3.8.13/0090-video-da8xx-fb-fb_set_par-support.patch
@@ -0,0 +1,123 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Wed, 28 Nov 2012 20:08:50 +0530
+Subject: [PATCH] video: da8xx-fb: fb_set_par support
+
+fb_set_par helps in runtime configuration of lcd controller like
+changing resolution, pixel clock etc. (eg. using fbset utility)
+
+Reconfigure lcd controller based on information passed by framework.
+Enable raster back if it was already enabled.
+
+As fb_set_par would get invoked indirectly from probe via fb_set_var,
+remove existing lcdc initialization in probe and do lcdc reset in
+probe so that reset happens only at the begining.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 60 +++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 49 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 0f73c76..720604c 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -243,6 +243,11 @@ static struct fb_videomode known_lcd_panels[] = {
+ },
+ };
+
++static inline bool da8xx_fb_is_raster_enabled(void)
++{
++ return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE);
++}
++
+ /* Enable the Raster Engine of the LCD Controller */
+ static inline void lcd_enable_raster(void)
+ {
+@@ -665,9 +670,6 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+
+ static void da8xx_fb_lcd_reset(void)
+ {
+- /* Disable the Raster if previously Enabled */
+- lcd_disable_raster(false);
+-
+ /* DMA has to be disabled */
+ lcdc_write(0, LCD_DMA_CTRL_REG);
+ lcdc_write(0, LCD_RASTER_CTRL_REG);
+@@ -720,8 +722,6 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
+ u32 bpp;
+ int ret = 0;
+
+- da8xx_fb_lcd_reset();
+-
+ da8xx_fb_calc_config_clk_divider(par, panel);
+
+ if (panel->sync & FB_SYNC_CLK_INVERT)
+@@ -1201,9 +1201,52 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
+ return ret;
+ }
+
++static int da8xxfb_set_par(struct fb_info *info)
++{
++ struct da8xx_fb_par *par = info->par;
++ int ret;
++ bool raster = da8xx_fb_is_raster_enabled();
++
++ if (raster)
++ lcd_disable_raster(true);
++ else
++ lcd_disable_raster(false);
++
++ fb_var_to_videomode(&par->mode, &info->var);
++
++ par->cfg.bpp = info->var.bits_per_pixel;
++
++ info->fix.visual = (par->cfg.bpp <= 8) ?
++ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
++ info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8;
++
++ ret = lcd_init(par, &par->cfg, &par->mode);
++ if (ret < 0) {
++ dev_err(par->dev, "lcd init failed\n");
++ return ret;
++ }
++
++ par->dma_start = info->fix.smem_start +
++ info->var.yoffset * info->fix.line_length +
++ info->var.xoffset * info->var.bits_per_pixel / 8;
++ par->dma_end = par->dma_start +
++ info->var.yres * info->fix.line_length - 1;
++
++ lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
++ lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
++ lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
++ lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
++
++ if (raster)
++ lcd_enable_raster();
++
++ return 0;
++}
++
+ static struct fb_ops da8xx_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = fb_check_var,
++ .fb_set_par = da8xxfb_set_par,
+ .fb_setcolreg = fb_setcolreg,
+ .fb_pan_display = da8xx_pan_display,
+ .fb_ioctl = fb_ioctl,
+@@ -1312,14 +1355,9 @@ static int fb_probe(struct platform_device *device)
+ }
+
+ fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
+- fb_var_to_videomode(&par->mode, &da8xx_fb_var);
+ par->cfg = *lcd_cfg;
+
+- if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
+- dev_err(&device->dev, "lcd_init failed\n");
+- ret = -EFAULT;
+- goto err_release_fb;
+- }
++ da8xx_fb_lcd_reset();
+
+ /* allocate frame buffer */
+ par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
diff --git a/patches/linux-3.8.13/0091-ARM-dts-AM33XX-Add-lcdc-node.patch b/patches/linux-3.8.13/0091-ARM-dts-AM33XX-Add-lcdc-node.patch
new file mode 100644
index 0000000..69a4c8c
--- /dev/null
+++ b/patches/linux-3.8.13/0091-ARM-dts-AM33XX-Add-lcdc-node.patch
@@ -0,0 +1,29 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 17 Dec 2012 15:27:44 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add lcdc node
+
+Add lcdc node.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index bfae98b..7a9c357 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -455,5 +455,13 @@
+ interrupts = <16>;
+ ti,hwmods = "adc_tsc";
+ };
++
++ lcdc: lcdc@4830e000 {
++ compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupts = <36>;
++ status = "disabled";
++ ti,hwmods = "lcdc";
++ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0092-ARM-dts-AM33XX-Add-am335x-evm-lcdc-panel-timings.patch b/patches/linux-3.8.13/0092-ARM-dts-AM33XX-Add-am335x-evm-lcdc-panel-timings.patch
new file mode 100644
index 0000000..db26925
--- /dev/null
+++ b/patches/linux-3.8.13/0092-ARM-dts-AM33XX-Add-am335x-evm-lcdc-panel-timings.patch
@@ -0,0 +1,39 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 31 Dec 2012 14:08:54 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add am335x-evm lcdc panel timings
+
+Update lcdc node with panel timings (typical) for AM335X-EVM.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/boot/dts/am335x-evm.dts | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index f4a07f8..d1a34cc 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -283,3 +283,23 @@
+ ti,adc-channels = <4 5 6 7>;
+ };
+ };
++
++&lcdc {
++ status = "okay";
++
++ display-timings {
++ 800x480p62 {
++ clock-frequency = <30000000>;
++ hactive = <800>;
++ vactive = <480>;
++ hfront-porch = <39>;
++ hback-porch = <39>;
++ hsync-len = <47>;
++ vback-porch = <29>;
++ vfront-porch = <13>;
++ vsync-len = <2>;
++ hsync-active = <1>;
++ vsync-active = <1>;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0093-ARM-dts-AM33XX-Add-am335x-evm-lcdc-pincontrol-info.patch b/patches/linux-3.8.13/0093-ARM-dts-AM33XX-Add-am335x-evm-lcdc-pincontrol-info.patch
new file mode 100644
index 0000000..cec6999
--- /dev/null
+++ b/patches/linux-3.8.13/0093-ARM-dts-AM33XX-Add-am335x-evm-lcdc-pincontrol-info.patch
@@ -0,0 +1,66 @@
+From: "Manjunathappa, Prakash" <prakash.pm@ti.com>
+Date: Mon, 17 Dec 2012 15:29:44 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add am335x-evm lcdc pincontrol info
+
+Update pin mux information for lcd panel on AM335X-EVM
+
+[afzal@ti.com: comment specifying user understandable pinmux details]
+
+Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/boot/dts/am335x-evm.dts | 34 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 33 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index d1a34cc..5eadd1e 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -26,7 +26,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &spi0_pins_s0>;
++ pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &lcd_pins_s0>;
+
+ matrix_keypad_s0: matrix_keypad_s0 {
+ pinctrl-single,pins = <
+@@ -54,6 +54,38 @@
+ >;
+ };
+
++ lcd_pins_s0: lcd_pins_s0 {
++ pinctrl-single,pins = <
++ 0x20 0x01 /* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
++ 0x24 0x01 /* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
++ 0x28 0x01 /* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
++ 0x2c 0x01 /* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
++ 0x30 0x01 /* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
++ 0x34 0x01 /* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
++ 0x38 0x01 /* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
++ 0x3c 0x01 /* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
++ 0xa0 0x00 /* lcd_data0.lcd_data0, OUTPUT | MODE0 */
++ 0xa4 0x00 /* lcd_data1.lcd_data1, OUTPUT | MODE0 */
++ 0xa8 0x00 /* lcd_data2.lcd_data2, OUTPUT | MODE0 */
++ 0xac 0x00 /* lcd_data3.lcd_data3, OUTPUT | MODE0 */
++ 0xb0 0x00 /* lcd_data4.lcd_data4, OUTPUT | MODE0 */
++ 0xb4 0x00 /* lcd_data5.lcd_data5, OUTPUT | MODE0 */
++ 0xb8 0x00 /* lcd_data6.lcd_data6, OUTPUT | MODE0 */
++ 0xbc 0x00 /* lcd_data7.lcd_data7, OUTPUT | MODE0 */
++ 0xc0 0x00 /* lcd_data8.lcd_data8, OUTPUT | MODE0 */
++ 0xc4 0x00 /* lcd_data9.lcd_data9, OUTPUT | MODE0 */
++ 0xc8 0x00 /* lcd_data10.lcd_data10, OUTPUT | MODE0 */
++ 0xcc 0x00 /* lcd_data11.lcd_data11, OUTPUT | MODE0 */
++ 0xd0 0x00 /* lcd_data12.lcd_data12, OUTPUT | MODE0 */
++ 0xd4 0x00 /* lcd_data13.lcd_data13, OUTPUT | MODE0 */
++ 0xd8 0x00 /* lcd_data14.lcd_data14, OUTPUT | MODE0 */
++ 0xdc 0x00 /* lcd_data15.lcd_data15, OUTPUT | MODE0 */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
++ >;
++ };
+ };
+
+ ocp {
diff --git a/patches/linux-3.8.13/0094-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-panel-timings.patch b/patches/linux-3.8.13/0094-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-panel-timings.patch
new file mode 100644
index 0000000..a3abf05
--- /dev/null
+++ b/patches/linux-3.8.13/0094-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-panel-timings.patch
@@ -0,0 +1,39 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Thu, 3 Jan 2013 16:08:59 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add am335x-evmsk lcdc panel timings
+
+Update lcdc node with panel timings (typical) for AM335X-EVMSK.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/boot/dts/am335x-evmsk.dts | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
+index 2546724..ba1c805 100644
+--- a/arch/arm/boot/dts/am335x-evmsk.dts
++++ b/arch/arm/boot/dts/am335x-evmsk.dts
+@@ -255,3 +255,23 @@
+ status = "okay";
+ vmmc-supply = <&vmmc_reg>;
+ };
++
++&lcdc {
++ status = "okay";
++
++ display-timings {
++ 480x272p57 {
++ clock-frequency = <9000000>;
++ hactive = <480>;
++ vactive = <272>;
++ hfront-porch = <8>;
++ hback-porch = <43>;
++ hsync-len = <4>;
++ vback-porch = <12>;
++ vfront-porch = <4>;
++ vsync-len = <10>;
++ hsync-active = <1>;
++ vsync-active = <1>;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0095-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-pincontrol-info.patch b/patches/linux-3.8.13/0095-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-pincontrol-info.patch
new file mode 100644
index 0000000..33b7c72
--- /dev/null
+++ b/patches/linux-3.8.13/0095-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-pincontrol-info.patch
@@ -0,0 +1,64 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Thu, 3 Jan 2013 16:24:39 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add am335x-evmsk lcdc pincontrol info
+
+Update pin mux information for lcd panel on AM335X-EVMSK.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/boot/dts/am335x-evmsk.dts | 35 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 34 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
+index ba1c805..f684704 100644
+--- a/arch/arm/boot/dts/am335x-evmsk.dts
++++ b/arch/arm/boot/dts/am335x-evmsk.dts
+@@ -32,7 +32,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&user_leds_s0 &gpio_keys_s0>;
++ pinctrl-0 = <&user_leds_s0 &gpio_keys_s0 &lcd_pins_s0>;
+
+ user_leds_s0: user_leds_s0 {
+ pinctrl-single,pins = <
+@@ -51,6 +51,39 @@
+ 0x9c 0x27 /* gpmc_ben0_cle.gpio2_5, INPUT | MODE7 */
+ >;
+ };
++
++ lcd_pins_s0: lcd_pins_s0 {
++ pinctrl-single,pins = <
++ 0x20 0x01 /* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
++ 0x24 0x01 /* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
++ 0x28 0x01 /* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
++ 0x2c 0x01 /* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
++ 0x30 0x01 /* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
++ 0x34 0x01 /* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
++ 0x38 0x01 /* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
++ 0x3c 0x01 /* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
++ 0xa0 0x00 /* lcd_data0.lcd_data0, OUTPUT | MODE0 */
++ 0xa4 0x00 /* lcd_data1.lcd_data1, OUTPUT | MODE0 */
++ 0xa8 0x00 /* lcd_data2.lcd_data2, OUTPUT | MODE0 */
++ 0xac 0x00 /* lcd_data3.lcd_data3, OUTPUT | MODE0 */
++ 0xb0 0x00 /* lcd_data4.lcd_data4, OUTPUT | MODE0 */
++ 0xb4 0x00 /* lcd_data5.lcd_data5, OUTPUT | MODE0 */
++ 0xb8 0x00 /* lcd_data6.lcd_data6, OUTPUT | MODE0 */
++ 0xbc 0x00 /* lcd_data7.lcd_data7, OUTPUT | MODE0 */
++ 0xc0 0x00 /* lcd_data8.lcd_data8, OUTPUT | MODE0 */
++ 0xc4 0x00 /* lcd_data9.lcd_data9, OUTPUT | MODE0 */
++ 0xc8 0x00 /* lcd_data10.lcd_data10, OUTPUT | MODE0 */
++ 0xcc 0x00 /* lcd_data11.lcd_data11, OUTPUT | MODE0 */
++ 0xd0 0x00 /* lcd_data12.lcd_data12, OUTPUT | MODE0 */
++ 0xd4 0x00 /* lcd_data13.lcd_data13, OUTPUT | MODE0 */
++ 0xd8 0x00 /* lcd_data14.lcd_data14, OUTPUT | MODE0 */
++ 0xdc 0x00 /* lcd_data15.lcd_data15, OUTPUT | MODE0 */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
++ >;
++ };
+ };
+
+ ocp {
diff --git a/patches/linux-3.8.13/0096-ARM-OMAP-AM33xx-hwmod-Corrects-PWM-subsystem-HWMOD-e.patch b/patches/linux-3.8.13/0096-ARM-OMAP-AM33xx-hwmod-Corrects-PWM-subsystem-HWMOD-e.patch
new file mode 100644
index 0000000..3a567b2
--- /dev/null
+++ b/patches/linux-3.8.13/0096-ARM-OMAP-AM33xx-hwmod-Corrects-PWM-subsystem-HWMOD-e.patch
@@ -0,0 +1,250 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 16 Oct 2012 14:50:58 +0530
+Subject: [PATCH] ARM: OMAP: AM33xx hwmod: Corrects PWM subsystem HWMOD
+ entries
+
+EQEP entry is HWMOD entry is not present in HWMOD entry. Also address
+ranges specified for EACP & EHRPWM is not correct & HWMOD flags of
+ADDR_TYPE_RT is added to PWM subsystem register address space. This
+patch
+1. Corrects register address mapping for ECAP & EHRPWM
+2. Removes HWMOD flags in PWM submodule register address space.
+3. Adds EQEP HWMOD entries.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 158 +++++++++++++++++++++++++---
+ 1 file changed, 145 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index 646c14d..60d4c3e 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -784,7 +784,7 @@ static struct omap_hwmod am33xx_elm_hwmod = {
+ };
+
+ /*
+- * 'epwmss' class: ecap0,1,2, ehrpwm0,1,2
++ * 'epwmss' class: ehrpwm0,1,2 eqep0,1,2 ecap0,1,2
+ */
+ static struct omap_hwmod_class_sysconfig am33xx_epwmss_sysc = {
+ .rev_offs = 0x0,
+@@ -864,6 +864,66 @@ static struct omap_hwmod am33xx_ehrpwm2_hwmod = {
+ },
+ };
+
++/* eqep0 */
++static struct omap_hwmod_irq_info am33xx_eqep0_irqs[] = {
++ { .irq = 79 + OMAP_INTC_START, },
++ { .irq = -1 },
++};
++
++static struct omap_hwmod am33xx_eqep0_hwmod = {
++ .name = "eqep0",
++ .class = &am33xx_epwmss_hwmod_class,
++ .clkdm_name = "l4ls_clkdm",
++ .mpu_irqs = am33xx_eqep0_irqs,
++ .main_clk = "l4ls_gclk",
++ .prcm = {
++ .omap4 = {
++ .clkctrl_offs = AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
++ .modulemode = MODULEMODE_SWCTRL,
++ },
++ },
++};
++
++/* eqep1 */
++static struct omap_hwmod_irq_info am33xx_eqep1_irqs[] = {
++ { .irq = 88 + OMAP_INTC_START, },
++ { .irq = -1 },
++};
++
++static struct omap_hwmod am33xx_eqep1_hwmod = {
++ .name = "eqep1",
++ .class = &am33xx_epwmss_hwmod_class,
++ .clkdm_name = "l4ls_clkdm",
++ .mpu_irqs = am33xx_eqep1_irqs,
++ .main_clk = "l4ls_gclk",
++ .prcm = {
++ .omap4 = {
++ .clkctrl_offs = AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
++ .modulemode = MODULEMODE_SWCTRL,
++ },
++ },
++};
++
++/* eqep2 */
++static struct omap_hwmod_irq_info am33xx_eqep2_irqs[] = {
++ { .irq = 89 + OMAP_INTC_START, },
++ { .irq = -1 },
++};
++
++static struct omap_hwmod am33xx_eqep2_hwmod = {
++ .name = "eqep2",
++ .class = &am33xx_epwmss_hwmod_class,
++ .clkdm_name = "l4ls_clkdm",
++ .mpu_irqs = am33xx_eqep2_irqs,
++ .main_clk = "l4ls_gclk",
++ .prcm = {
++ .omap4 = {
++ .clkctrl_offs = AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
++ .modulemode = MODULEMODE_SWCTRL,
++ },
++ },
++};
++
+ /* ecap0 */
+ static struct omap_hwmod_irq_info am33xx_ecap0_irqs[] = {
+ { .irq = 31 + OMAP_INTC_START, },
+@@ -2559,8 +2619,7 @@ static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
+ },
+ {
+ .pa_start = 0x48300200,
+- .pa_end = 0x48300200 + SZ_256 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_end = 0x48300200 + SZ_128 - 1,
+ },
+ { }
+ };
+@@ -2585,8 +2644,7 @@ static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
+ },
+ {
+ .pa_start = 0x48302200,
+- .pa_end = 0x48302200 + SZ_256 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_end = 0x48302200 + SZ_128 - 1,
+ },
+ { }
+ };
+@@ -2611,8 +2669,7 @@ static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
+ },
+ {
+ .pa_start = 0x48304200,
+- .pa_end = 0x48304200 + SZ_256 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_end = 0x48304200 + SZ_128 - 1,
+ },
+ { }
+ };
+@@ -2629,6 +2686,81 @@ 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
+ */
++static struct omap_hwmod_addr_space am33xx_eqep0_addr_space[] = {
++ {
++ .pa_start = 0x48300000,
++ .pa_end = 0x48300000 + SZ_16 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ {
++ .pa_start = 0x48300180,
++ .pa_end = 0x48300180 + SZ_128 - 1,
++ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_l4_ls__eqep0 = {
++ .master = &am33xx_l4_ls_hwmod,
++ .slave = &am33xx_eqep0_hwmod,
++ .clk = "l4ls_gclk",
++ .addr = am33xx_eqep0_addr_space,
++ .user = OCP_USER_MPU,
++};
++
++/*
++ * Splitting the resources to handle access of PWMSS config space
++ * and module specific part independently
++ */
++static struct omap_hwmod_addr_space am33xx_eqep1_addr_space[] = {
++ {
++ .pa_start = 0x48302000,
++ .pa_end = 0x48302000 + SZ_16 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ {
++ .pa_start = 0x48302180,
++ .pa_end = 0x48302180 + SZ_128 - 1,
++ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_l4_ls__eqep1 = {
++ .master = &am33xx_l4_ls_hwmod,
++ .slave = &am33xx_eqep1_hwmod,
++ .clk = "l4ls_gclk",
++ .addr = am33xx_eqep1_addr_space,
++ .user = OCP_USER_MPU,
++};
++
++/*
++ * Splitting the resources to handle access of PWMSS config space
++ * and module specific part independently
++ */
++static struct omap_hwmod_addr_space am33xx_eqep2_addr_space[] = {
++ {
++ .pa_start = 0x48304000,
++ .pa_end = 0x48304000 + SZ_16 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ {
++ .pa_start = 0x48304180,
++ .pa_end = 0x48304180 + SZ_128 - 1,
++ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_l4_ls__eqep2 = {
++ .master = &am33xx_l4_ls_hwmod,
++ .slave = &am33xx_eqep2_hwmod,
++ .clk = "l4ls_gclk",
++ .addr = am33xx_eqep2_addr_space,
++ .user = OCP_USER_MPU,
++};
++
++/*
++ * Splitting the resources to handle access of PWMSS config space
++ * and module specific part independently
++ */
+ static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
+ {
+ .pa_start = 0x48300000,
+@@ -2637,8 +2769,7 @@ static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
+ },
+ {
+ .pa_start = 0x48300100,
+- .pa_end = 0x48300100 + SZ_256 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_end = 0x48300100 + SZ_128 - 1,
+ },
+ { }
+ };
+@@ -2663,8 +2794,7 @@ static struct omap_hwmod_addr_space am33xx_ecap1_addr_space[] = {
+ },
+ {
+ .pa_start = 0x48302100,
+- .pa_end = 0x48302100 + SZ_256 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_end = 0x48302100 + SZ_128 - 1,
+ },
+ { }
+ };
+@@ -2689,8 +2819,7 @@ static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
+ },
+ {
+ .pa_start = 0x48304100,
+- .pa_end = 0x48304100 + SZ_256 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_end = 0x48304100 + SZ_128 - 1,
+ },
+ { }
+ };
+@@ -3388,6 +3517,9 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l4_ls__ehrpwm0,
+ &am33xx_l4_ls__ehrpwm1,
+ &am33xx_l4_ls__ehrpwm2,
++ &am33xx_l4_ls__eqep0,
++ &am33xx_l4_ls__eqep1,
++ &am33xx_l4_ls__eqep2,
+ &am33xx_l4_ls__ecap0,
+ &am33xx_l4_ls__ecap1,
+ &am33xx_l4_ls__ecap2,
diff --git a/patches/linux-3.8.13/0097-ARM-OMAP-AM33xx-hwmod-Add-parent-child-relationship-.patch b/patches/linux-3.8.13/0097-ARM-OMAP-AM33xx-hwmod-Add-parent-child-relationship-.patch
new file mode 100644
index 0000000..7beb98d
--- /dev/null
+++ b/patches/linux-3.8.13/0097-ARM-OMAP-AM33xx-hwmod-Add-parent-child-relationship-.patch
@@ -0,0 +1,654 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 16 Oct 2012 14:50:58 +0530
+Subject: [PATCH] ARM: OMAP: AM33xx hwmod: Add parent-child relationship for
+ PWM subsystem
+
+As part of PWM subsystem integration, PWM subsystem are sharing
+resources like clock across submodules (ECAP, EQEP & EHRPWM). To handle
+resource sharing & IP integration rework on parent child relation
+between PWMSS and ECAP, EQEP & EHRPWM child devices to support runtime PM.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 434 +++++++++++++---------------
+ 1 file changed, 203 insertions(+), 231 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index 60d4c3e..e54e7a1 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -783,9 +783,7 @@ static struct omap_hwmod am33xx_elm_hwmod = {
+ },
+ };
+
+-/*
+- * 'epwmss' class: ehrpwm0,1,2 eqep0,1,2 ecap0,1,2
+- */
++/* pwmss */
+ static struct omap_hwmod_class_sysconfig am33xx_epwmss_sysc = {
+ .rev_offs = 0x0,
+ .sysc_offs = 0x4,
+@@ -801,67 +799,44 @@ static struct omap_hwmod_class am33xx_epwmss_hwmod_class = {
+ .sysc = &am33xx_epwmss_sysc,
+ };
+
+-/* ehrpwm0 */
+-static struct omap_hwmod_irq_info am33xx_ehrpwm0_irqs[] = {
+- { .name = "int", .irq = 86 + OMAP_INTC_START, },
+- { .name = "tzint", .irq = 58 + OMAP_INTC_START, },
+- { .irq = -1 },
++static struct omap_hwmod_class am33xx_ecap_hwmod_class = {
++ .name = "ecap",
+ };
+
+-static struct omap_hwmod am33xx_ehrpwm0_hwmod = {
+- .name = "ehrpwm0",
+- .class = &am33xx_epwmss_hwmod_class,
+- .clkdm_name = "l4ls_clkdm",
+- .mpu_irqs = am33xx_ehrpwm0_irqs,
+- .main_clk = "l4ls_gclk",
+- .prcm = {
+- .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
+- .modulemode = MODULEMODE_SWCTRL,
+- },
+- },
++static struct omap_hwmod_class am33xx_eqep_hwmod_class = {
++ .name = "eqep",
+ };
+
+-/* ehrpwm1 */
+-static struct omap_hwmod_irq_info am33xx_ehrpwm1_irqs[] = {
+- { .name = "int", .irq = 87 + OMAP_INTC_START, },
+- { .name = "tzint", .irq = 59 + OMAP_INTC_START, },
+- { .irq = -1 },
++static struct omap_hwmod_class am33xx_ehrpwm_hwmod_class = {
++ .name = "ehrpwm",
+ };
+
+-static struct omap_hwmod am33xx_ehrpwm1_hwmod = {
+- .name = "ehrpwm1",
++/* epwmss0 */
++static struct omap_hwmod am33xx_epwmss0_hwmod = {
++ .name = "epwmss0",
+ .class = &am33xx_epwmss_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
+- .mpu_irqs = am33xx_ehrpwm1_irqs,
+ .main_clk = "l4ls_gclk",
+ .prcm = {
+ .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
++ .clkctrl_offs = AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+ };
+
+-/* ehrpwm2 */
+-static struct omap_hwmod_irq_info am33xx_ehrpwm2_irqs[] = {
+- { .name = "int", .irq = 39 + OMAP_INTC_START, },
+- { .name = "tzint", .irq = 60 + OMAP_INTC_START, },
++/* ecap0 */
++static struct omap_hwmod_irq_info am33xx_ecap0_irqs[] = {
++ { .irq = 31 + OMAP_INTC_START, },
+ { .irq = -1 },
+ };
+
+-static struct omap_hwmod am33xx_ehrpwm2_hwmod = {
+- .name = "ehrpwm2",
+- .class = &am33xx_epwmss_hwmod_class,
++static struct omap_hwmod am33xx_ecap0_hwmod = {
++ .name = "ecap0",
++ .class = &am33xx_ecap_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
+- .mpu_irqs = am33xx_ehrpwm2_irqs,
++ .mpu_irqs = am33xx_ecap0_irqs,
+ .main_clk = "l4ls_gclk",
+- .prcm = {
+- .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
+- .modulemode = MODULEMODE_SWCTRL,
+- },
+- },
+ };
+
+ /* eqep0 */
+@@ -872,29 +847,32 @@ static struct omap_hwmod_irq_info am33xx_eqep0_irqs[] = {
+
+ static struct omap_hwmod am33xx_eqep0_hwmod = {
+ .name = "eqep0",
+- .class = &am33xx_epwmss_hwmod_class,
++ .class = &am33xx_eqep_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
+ .mpu_irqs = am33xx_eqep0_irqs,
+ .main_clk = "l4ls_gclk",
+- .prcm = {
+- .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
+- .modulemode = MODULEMODE_SWCTRL,
+- },
+- },
+ };
+
+-/* eqep1 */
+-static struct omap_hwmod_irq_info am33xx_eqep1_irqs[] = {
+- { .irq = 88 + OMAP_INTC_START, },
++/* ehrpwm0 */
++static struct omap_hwmod_irq_info am33xx_ehrpwm0_irqs[] = {
++ { .name = "int", .irq = 86 + OMAP_INTC_START, },
++ { .name = "tzint", .irq = 58 + OMAP_INTC_START, },
+ { .irq = -1 },
+ };
+
+-static struct omap_hwmod am33xx_eqep1_hwmod = {
+- .name = "eqep1",
++static struct omap_hwmod am33xx_ehrpwm0_hwmod = {
++ .name = "ehrpwm0",
++ .class = &am33xx_ehrpwm_hwmod_class,
++ .clkdm_name = "l4ls_clkdm",
++ .mpu_irqs = am33xx_ehrpwm0_irqs,
++ .main_clk = "l4ls_gclk",
++};
++
++/* epwmss1 */
++static struct omap_hwmod am33xx_epwmss1_hwmod = {
++ .name = "epwmss1",
+ .class = &am33xx_epwmss_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
+- .mpu_irqs = am33xx_eqep1_irqs,
+ .main_clk = "l4ls_gclk",
+ .prcm = {
+ .omap4 = {
+@@ -904,61 +882,58 @@ static struct omap_hwmod am33xx_eqep1_hwmod = {
+ },
+ };
+
+-/* eqep2 */
+-static struct omap_hwmod_irq_info am33xx_eqep2_irqs[] = {
+- { .irq = 89 + OMAP_INTC_START, },
++/* ecap1 */
++static struct omap_hwmod_irq_info am33xx_ecap1_irqs[] = {
++ { .irq = 47 + OMAP_INTC_START, },
+ { .irq = -1 },
+ };
+
+-static struct omap_hwmod am33xx_eqep2_hwmod = {
+- .name = "eqep2",
+- .class = &am33xx_epwmss_hwmod_class,
++static struct omap_hwmod am33xx_ecap1_hwmod = {
++ .name = "ecap1",
++ .class = &am33xx_ecap_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
+- .mpu_irqs = am33xx_eqep2_irqs,
++ .mpu_irqs = am33xx_ecap1_irqs,
+ .main_clk = "l4ls_gclk",
+- .prcm = {
+- .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
+- .modulemode = MODULEMODE_SWCTRL,
+- },
+- },
+ };
+
+-/* ecap0 */
+-static struct omap_hwmod_irq_info am33xx_ecap0_irqs[] = {
+- { .irq = 31 + OMAP_INTC_START, },
++/* eqep1 */
++static struct omap_hwmod_irq_info am33xx_eqep1_irqs[] = {
++ { .irq = 88 + OMAP_INTC_START, },
+ { .irq = -1 },
+ };
+
+-static struct omap_hwmod am33xx_ecap0_hwmod = {
+- .name = "ecap0",
+- .class = &am33xx_epwmss_hwmod_class,
++static struct omap_hwmod am33xx_eqep1_hwmod = {
++ .name = "eqep1",
++ .class = &am33xx_eqep_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
+- .mpu_irqs = am33xx_ecap0_irqs,
++ .mpu_irqs = am33xx_eqep1_irqs,
+ .main_clk = "l4ls_gclk",
+- .prcm = {
+- .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
+- .modulemode = MODULEMODE_SWCTRL,
+- },
+- },
+ };
+
+-/* ecap1 */
+-static struct omap_hwmod_irq_info am33xx_ecap1_irqs[] = {
+- { .irq = 47 + OMAP_INTC_START, },
++/* ehrpwm1 */
++static struct omap_hwmod_irq_info am33xx_ehrpwm1_irqs[] = {
++ { .name = "int", .irq = 87 + OMAP_INTC_START, },
++ { .name = "tzint", .irq = 59 + OMAP_INTC_START, },
+ { .irq = -1 },
+ };
+
+-static struct omap_hwmod am33xx_ecap1_hwmod = {
+- .name = "ecap1",
++static struct omap_hwmod am33xx_ehrpwm1_hwmod = {
++ .name = "ehrpwm1",
++ .class = &am33xx_ehrpwm_hwmod_class,
++ .clkdm_name = "l4ls_clkdm",
++ .mpu_irqs = am33xx_ehrpwm1_irqs,
++ .main_clk = "l4ls_gclk",
++};
++
++/* epwmss2 */
++static struct omap_hwmod am33xx_epwmss2_hwmod = {
++ .name = "epwmss2",
+ .class = &am33xx_epwmss_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
+- .mpu_irqs = am33xx_ecap1_irqs,
+ .main_clk = "l4ls_gclk",
+ .prcm = {
+ .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
++ .clkctrl_offs = AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+@@ -972,16 +947,39 @@ static struct omap_hwmod_irq_info am33xx_ecap2_irqs[] = {
+
+ static struct omap_hwmod am33xx_ecap2_hwmod = {
+ .name = "ecap2",
++ .class = &am33xx_ecap_hwmod_class,
++ .clkdm_name = "l4ls_clkdm",
+ .mpu_irqs = am33xx_ecap2_irqs,
+- .class = &am33xx_epwmss_hwmod_class,
++ .main_clk = "l4ls_gclk",
++};
++
++/* eqep2 */
++static struct omap_hwmod_irq_info am33xx_eqep2_irqs[] = {
++ { .irq = 89 + OMAP_INTC_START, },
++ { .irq = -1 },
++};
++
++static struct omap_hwmod am33xx_eqep2_hwmod = {
++ .name = "eqep2",
++ .class = &am33xx_eqep_hwmod_class,
+ .clkdm_name = "l4ls_clkdm",
++ .mpu_irqs = am33xx_eqep2_irqs,
++ .main_clk = "l4ls_gclk",
++};
++
++/* ehrpwm2 */
++static struct omap_hwmod_irq_info am33xx_ehrpwm2_irqs[] = {
++ { .name = "int", .irq = 39 + OMAP_INTC_START, },
++ { .name = "tzint", .irq = 60 + OMAP_INTC_START, },
++ { .irq = -1 },
++};
++
++static struct omap_hwmod am33xx_ehrpwm2_hwmod = {
++ .name = "ehrpwm2",
++ .class = &am33xx_ehrpwm_hwmod_class,
++ .clkdm_name = "l4ls_clkdm",
++ .mpu_irqs = am33xx_ehrpwm2_irqs,
+ .main_clk = "l4ls_gclk",
+- .prcm = {
+- .omap4 = {
+- .clkctrl_offs = AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
+- .modulemode = MODULEMODE_SWCTRL,
+- },
+- },
+ };
+
+ /*
+@@ -2607,116 +2605,106 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
++static struct omap_hwmod_addr_space am33xx_epwmss0_addr_space[] = {
+ {
+ .pa_start = 0x48300000,
+ .pa_end = 0x48300000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+- {
+- .pa_start = 0x48300200,
+- .pa_end = 0x48300200 + SZ_128 - 1,
+- },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm0 = {
++static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0 = {
+ .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_ehrpwm0_hwmod,
++ .slave = &am33xx_epwmss0_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_ehrpwm0_addr_space,
++ .addr = am33xx_epwmss0_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
+- {
+- .pa_start = 0x48302000,
+- .pa_end = 0x48302000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
++static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
+ {
+- .pa_start = 0x48302200,
+- .pa_end = 0x48302200 + SZ_128 - 1,
++ .pa_start = 0x48300100,
++ .pa_end = 0x48300100 + SZ_128 - 1,
+ },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm1 = {
+- .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_ehrpwm1_hwmod,
++static struct omap_hwmod_ocp_if am33xx_epwmss0__ecap0 = {
++ .master = &am33xx_epwmss0_hwmod,
++ .slave = &am33xx_ecap0_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_ehrpwm1_addr_space,
++ .addr = am33xx_ecap0_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
++static struct omap_hwmod_addr_space am33xx_eqep0_addr_space[] = {
+ {
+- .pa_start = 0x48304000,
+- .pa_end = 0x48304000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_start = 0x48300180,
++ .pa_end = 0x48300180 + SZ_128 - 1,
+ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_epwmss0__eqep0 = {
++ .master = &am33xx_epwmss0_hwmod,
++ .slave = &am33xx_eqep0_hwmod,
++ .clk = "l4ls_gclk",
++ .addr = am33xx_eqep0_addr_space,
++ .user = OCP_USER_MPU,
++};
++
++static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
+ {
+- .pa_start = 0x48304200,
+- .pa_end = 0x48304200 + SZ_128 - 1,
++ .pa_start = 0x48300200,
++ .pa_end = 0x48300200 + SZ_128 - 1,
+ },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm2 = {
+- .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_ehrpwm2_hwmod,
++static struct omap_hwmod_ocp_if am33xx_epwmss0__ehrpwm0 = {
++ .master = &am33xx_epwmss0_hwmod,
++ .slave = &am33xx_ehrpwm0_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_ehrpwm2_addr_space,
++ .addr = am33xx_ehrpwm0_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_eqep0_addr_space[] = {
++
++static struct omap_hwmod_addr_space am33xx_epwmss1_addr_space[] = {
+ {
+- .pa_start = 0x48300000,
+- .pa_end = 0x48300000 + SZ_16 - 1,
++ .pa_start = 0x48302000,
++ .pa_end = 0x48302000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+- {
+- .pa_start = 0x48300180,
+- .pa_end = 0x48300180 + SZ_128 - 1,
+- },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__eqep0 = {
++static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1 = {
+ .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_eqep0_hwmod,
++ .slave = &am33xx_epwmss1_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_eqep0_addr_space,
++ .addr = am33xx_epwmss1_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_eqep1_addr_space[] = {
++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_128 - 1,
+ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_epwmss1__ecap1 = {
++ .master = &am33xx_epwmss1_hwmod,
++ .slave = &am33xx_ecap1_hwmod,
++ .clk = "l4ls_gclk",
++ .addr = am33xx_ecap1_addr_space,
++ .user = OCP_USER_MPU,
++};
++
++static struct omap_hwmod_addr_space am33xx_eqep1_addr_space[] = {
+ {
+ .pa_start = 0x48302180,
+ .pa_end = 0x48302180 + SZ_128 - 1,
+@@ -2724,111 +2712,92 @@ static struct omap_hwmod_addr_space am33xx_eqep1_addr_space[] = {
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__eqep1 = {
+- .master = &am33xx_l4_ls_hwmod,
++static struct omap_hwmod_ocp_if am33xx_epwmss1__eqep1 = {
++ .master = &am33xx_epwmss1_hwmod,
+ .slave = &am33xx_eqep1_hwmod,
+ .clk = "l4ls_gclk",
+ .addr = am33xx_eqep1_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_eqep2_addr_space[] = {
+- {
+- .pa_start = 0x48304000,
+- .pa_end = 0x48304000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
++static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
+ {
+- .pa_start = 0x48304180,
+- .pa_end = 0x48304180 + SZ_128 - 1,
++ .pa_start = 0x48302200,
++ .pa_end = 0x48302200 + SZ_128 - 1,
+ },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__eqep2 = {
+- .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_eqep2_hwmod,
++static struct omap_hwmod_ocp_if am33xx_epwmss1__ehrpwm1 = {
++ .master = &am33xx_epwmss1_hwmod,
++ .slave = &am33xx_ehrpwm1_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_eqep2_addr_space,
++ .addr = am33xx_ehrpwm1_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
++static struct omap_hwmod_addr_space am33xx_epwmss2_addr_space[] = {
+ {
+- .pa_start = 0x48300000,
+- .pa_end = 0x48300000 + SZ_16 - 1,
++ .pa_start = 0x48304000,
++ .pa_end = 0x48304000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+- {
+- .pa_start = 0x48300100,
+- .pa_end = 0x48300100 + SZ_128 - 1,
+- },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap0 = {
++static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2 = {
+ .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_ecap0_hwmod,
++ .slave = &am33xx_epwmss2_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_ecap0_addr_space,
++ .addr = am33xx_epwmss2_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_ecap1_addr_space[] = {
+- {
+- .pa_start = 0x48302000,
+- .pa_end = 0x48302000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
++static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
+ {
+- .pa_start = 0x48302100,
+- .pa_end = 0x48302100 + SZ_128 - 1,
++ .pa_start = 0x48304100,
++ .pa_end = 0x48304100 + SZ_128 - 1,
+ },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap1 = {
+- .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_ecap1_hwmod,
++static struct omap_hwmod_ocp_if am33xx_epwmss2__ecap2 = {
++ .master = &am33xx_epwmss2_hwmod,
++ .slave = &am33xx_ecap2_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_ecap1_addr_space,
++ .addr = am33xx_ecap2_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+-/*
+- * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
+- */
+-static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
++static struct omap_hwmod_addr_space am33xx_eqep2_addr_space[] = {
+ {
+- .pa_start = 0x48304000,
+- .pa_end = 0x48304000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
++ .pa_start = 0x48304180,
++ .pa_end = 0x48304180 + SZ_128 - 1,
+ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_epwmss2__eqep2 = {
++ .master = &am33xx_epwmss2_hwmod,
++ .slave = &am33xx_eqep2_hwmod,
++ .clk = "l4ls_gclk",
++ .addr = am33xx_eqep2_addr_space,
++ .user = OCP_USER_MPU,
++};
++
++static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
+ {
+- .pa_start = 0x48304100,
+- .pa_end = 0x48304100 + SZ_128 - 1,
++ .pa_start = 0x48304200,
++ .pa_end = 0x48304200 + SZ_128 - 1,
+ },
+ { }
+ };
+
+-static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap2 = {
+- .master = &am33xx_l4_ls_hwmod,
+- .slave = &am33xx_ecap2_hwmod,
++static struct omap_hwmod_ocp_if am33xx_epwmss2__ehrpwm2 = {
++ .master = &am33xx_epwmss2_hwmod,
++ .slave = &am33xx_ehrpwm2_hwmod,
+ .clk = "l4ls_gclk",
+- .addr = am33xx_ecap2_addr_space,
++ .addr = am33xx_ehrpwm2_addr_space,
+ .user = OCP_USER_MPU,
+ };
+
+@@ -3514,15 +3483,18 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l4_ls__uart6,
+ &am33xx_l4_ls__spinlock,
+ &am33xx_l4_ls__elm,
+- &am33xx_l4_ls__ehrpwm0,
+- &am33xx_l4_ls__ehrpwm1,
+- &am33xx_l4_ls__ehrpwm2,
+- &am33xx_l4_ls__eqep0,
+- &am33xx_l4_ls__eqep1,
+- &am33xx_l4_ls__eqep2,
+- &am33xx_l4_ls__ecap0,
+- &am33xx_l4_ls__ecap1,
+- &am33xx_l4_ls__ecap2,
++ &am33xx_l4_ls__epwmss0,
++ &am33xx_epwmss0__ecap0,
++ &am33xx_epwmss0__eqep0,
++ &am33xx_epwmss0__ehrpwm0,
++ &am33xx_l4_ls__epwmss1,
++ &am33xx_epwmss1__ecap1,
++ &am33xx_epwmss1__eqep1,
++ &am33xx_epwmss1__ehrpwm1,
++ &am33xx_l4_ls__epwmss2,
++ &am33xx_epwmss2__ecap2,
++ &am33xx_epwmss2__eqep2,
++ &am33xx_epwmss2__ehrpwm2,
+ &am33xx_l3_s__gpmc,
+ &am33xx_l3_main__lcdc,
+ &am33xx_l4_ls__mcspi0,
diff --git a/patches/linux-3.8.13/0098-ARM-dts-AM33XX-Add-PWMSS-device-tree-nodes.patch b/patches/linux-3.8.13/0098-ARM-dts-AM33XX-Add-PWMSS-device-tree-nodes.patch
new file mode 100644
index 0000000..d19f5d7
--- /dev/null
+++ b/patches/linux-3.8.13/0098-ARM-dts-AM33XX-Add-PWMSS-device-tree-nodes.patch
@@ -0,0 +1,113 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Wed, 11 Jul 2012 11:01:33 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add PWMSS device tree nodes
+
+Add PWMSS device tree nodes in relation with ECAP & EHRPWM DT nodes to
+AM33XX SoC family. Also populates device tree nodes for ECAP & EHRPWM by
+adding necessary properties like pwm-cells, base reg & set disabled as
+status.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+
+Conflicts:
+
+ arch/arm/boot/dts/am33xx.dtsi
+---
+ arch/arm/boot/dts/am33xx.dtsi | 84 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 84 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 7a9c357..e832be8 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -463,5 +463,89 @@
+ status = "disabled";
+ ti,hwmods = "lcdc";
+ };
++
++ epwmss0: epwmss@48300000 {
++ compatible = "ti,am33xx-pwmss";
++ reg = <0x48300000 0x10>;
++ ti,hwmods = "epwmss0";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ status = "disabled";
++ ranges = <0x48300100 0x48300100 0x80 /* ECAP */
++ 0x48300180 0x48300180 0x80 /* EQEP */
++ 0x48300200 0x48300200 0x80>; /* EHRPWM */
++
++ ecap0: ecap@48300100 {
++ compatible = "ti,am33xx-ecap";
++ #pwm-cells = <3>;
++ reg = <0x48300100 0x80>;
++ ti,hwmods = "ecap0";
++ status = "disabled";
++ };
++
++ ehrpwm0: ehrpwm@48300200 {
++ compatible = "ti,am33xx-ehrpwm";
++ #pwm-cells = <3>;
++ reg = <0x48300200 0x80>;
++ ti,hwmods = "ehrpwm0";
++ status = "disabled";
++ };
++ };
++
++ epwmss1: epwmss@48302000 {
++ compatible = "ti,am33xx-pwmss";
++ reg = <0x48302000 0x10>;
++ ti,hwmods = "epwmss1";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ status = "disabled";
++ ranges = <0x48302100 0x48302100 0x80 /* ECAP */
++ 0x48302180 0x48302180 0x80 /* EQEP */
++ 0x48302200 0x48302200 0x80>; /* EHRPWM */
++
++ ecap1: ecap@48302100 {
++ compatible = "ti,am33xx-ecap";
++ #pwm-cells = <3>;
++ reg = <0x48302100 0x80>;
++ ti,hwmods = "ecap1";
++ status = "disabled";
++ };
++
++ ehrpwm1: ehrpwm@48302200 {
++ compatible = "ti,am33xx-ehrpwm";
++ #pwm-cells = <3>;
++ reg = <0x48302200 0x80>;
++ ti,hwmods = "ehrpwm1";
++ status = "disabled";
++ };
++ };
++
++ epwmss2: epwmss@48304000 {
++ compatible = "ti,am33xx-pwmss";
++ reg = <0x48304000 0x10>;
++ ti,hwmods = "epwmss2";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ status = "disabled";
++ ranges = <0x48304100 0x48304100 0x80 /* ECAP */
++ 0x48304180 0x48304180 0x80 /* EQEP */
++ 0x48304200 0x48304200 0x80>; /* EHRPWM */
++
++ ecap2: ecap@48304100 {
++ compatible = "ti,am33xx-ecap";
++ #pwm-cells = <3>;
++ reg = <0x48304100 0x80>;
++ ti,hwmods = "ecap2";
++ status = "disabled";
++ };
++
++ ehrpwm2: ehrpwm@48304200 {
++ compatible = "ti,am33xx-ehrpwm";
++ #pwm-cells = <3>;
++ reg = <0x48304200 0x80>;
++ ti,hwmods = "ehrpwm2";
++ status = "disabled";
++ };
++ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0099-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch b/patches/linux-3.8.13/0099-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch
new file mode 100644
index 0000000..9ac684d
--- /dev/null
+++ b/patches/linux-3.8.13/0099-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch
@@ -0,0 +1,65 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 16 Jul 2012 14:57:33 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add PWM backlight DT data to am335x-evm
+
+PWM output from ecap0 uses as backlight source. Also adds low threshold
+value to have a uniform divisions in brightness-levels scales.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+
+Conflicts:
+
+ arch/arm/boot/dts/am335x-evm.dts
+---
+ arch/arm/boot/dts/am335x-evm.dts | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 5eadd1e..65ae57f 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -86,6 +86,12 @@
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
+ >;
+ };
++
++ ecap0_pins: backlight_pins {
++ pinctrl-single,pins = <
++ 0x164 0x0 /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -144,6 +150,16 @@
+ reg = <0x48>;
+ };
+ };
++
++ epwmss0: epwmss@48300000 {
++ status = "okay";
++
++ ecap0: ecap@48300100 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&ecap0_pins>;
++ };
++ };
+ };
+
+ vbat: fixedregulator@0 {
+@@ -200,6 +216,13 @@
+ gpio-key,wakeup;
+ };
+ };
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&ecap0 0 50000 0>;
++ brightness-levels = <0 51 53 56 62 75 101 152 255>;
++ default-brightness-level = <8>;
++ };
+ };
+
+ /include/ "tps65910.dtsi"
diff --git a/patches/linux-3.8.13/0100-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch b/patches/linux-3.8.13/0100-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch
new file mode 100644
index 0000000..bd95a08
--- /dev/null
+++ b/patches/linux-3.8.13/0100-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch
@@ -0,0 +1,66 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 16 Jul 2012 14:57:33 +0530
+Subject: [PATCH] ARM: dts: AM33XX: Add PWM backlight DT data to am335x-evmsk
+
+PWM output from ecap2 uses as backlight source. Also adds low threshold
+value to have a uniform divisions in brightness-levels scales with
+inverse polarity.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
+
+Conflicts:
+
+ arch/arm/boot/dts/am335x-evmsk.dts
+---
+ arch/arm/boot/dts/am335x-evmsk.dts | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
+index f684704..7a87803 100644
+--- a/arch/arm/boot/dts/am335x-evmsk.dts
++++ b/arch/arm/boot/dts/am335x-evmsk.dts
+@@ -84,6 +84,12 @@
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
+ >;
+ };
++
++ ecap2_pins: backlight_pins {
++ pinctrl-single,pins = <
++ 0x19c 0x4 /* mcasp0_ahclkr.ecap2_in_pwm2_out MODE4 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -127,6 +133,16 @@
+ st,max-limit-z = <750>;
+ };
+ };
++
++ epwmss2: epwmss@48304000 {
++ status = "okay";
++
++ ecap2: ecap@48304100 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&ecap2_pins>;
++ };
++ };
+ };
+
+ vbat: fixedregulator@0 {
+@@ -203,6 +219,13 @@
+ gpios = <&gpio3 5 0>;
+ };
+ };
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&ecap2 0 50000 1>;
++ brightness-levels = <0 58 61 66 75 90 125 170 255>;
++ default-brightness-level = <8>;
++ };
+ };
+
+ /include/ "tps65910.dtsi"
diff --git a/patches/linux-3.8.13/0101-clk-divider-prepare-for-minimum-divider.patch b/patches/linux-3.8.13/0101-clk-divider-prepare-for-minimum-divider.patch
new file mode 100644
index 0000000..8614dd6
--- /dev/null
+++ b/patches/linux-3.8.13/0101-clk-divider-prepare-for-minimum-divider.patch
@@ -0,0 +1,165 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Thu, 17 Jan 2013 17:11:53 +0530
+Subject: [PATCH] clk: divider: prepare for minimum divider
+
+Some of clocks can have a limit on minimum divider value that can be
+programmed, prepare for such a support.
+
+Add a new field min_div for the basic divider clock and a new dynamic
+clock divider registration function where minimum divider value can
+be specified. Keep behaviour of existing divider clock registration
+functions, static initialization helpers as was earlier.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/clk/clk-divider.c | 37 ++++++++++++++++++++++++++++++++++---
+ include/linux/clk-private.h | 6 +++++-
+ include/linux/clk-provider.h | 7 +++++++
+ 3 files changed, 46 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
+index a9204c6..4025c5a 100644
+--- a/drivers/clk/clk-divider.c
++++ b/drivers/clk/clk-divider.c
+@@ -236,7 +236,7 @@ EXPORT_SYMBOL_GPL(clk_divider_ops);
+
+ static struct clk *_register_divider(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+- void __iomem *reg, u8 shift, u8 width,
++ void __iomem *reg, u8 shift, u8 width, u8 min_div,
+ u8 clk_divider_flags, const struct clk_div_table *table,
+ spinlock_t *lock)
+ {
+@@ -244,6 +244,11 @@ static struct clk *_register_divider(struct device *dev, const char *name,
+ struct clk *clk;
+ struct clk_init_data init;
+
++ if (!min_div) {
++ pr_err("%s: minimum divider cannot be zero\n", __func__);
++ return ERR_PTR(-EINVAL);
++ }
++
+ /* allocate the divider */
+ div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+ if (!div) {
+@@ -261,6 +266,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
+ div->reg = reg;
+ div->shift = shift;
+ div->width = width;
++ div->min_div = min_div;
+ div->flags = clk_divider_flags;
+ div->lock = lock;
+ div->hw.init = &init;
+@@ -276,6 +282,29 @@ static struct clk *_register_divider(struct device *dev, const char *name,
+ }
+
+ /**
++ * clk_register_min_divider - register a divider clock having minimum divider
++ * constraints with clock framework
++ * @dev: device registering this clock
++ * @name: name of this clock
++ * @parent_name: name of clock's parent
++ * @flags: framework-specific flags
++ * @reg: register address to adjust divider
++ * @shift: number of bits to shift the bitfield
++ * @width: width of the bitfield
++ * @min_div: minimum allowable divider
++ * @clk_divider_flags: divider-specific flags for this clock
++ * @lock: shared register lock for this clock
++ */
++struct clk *clk_register_min_divider(struct device *dev, const char *name,
++ const char *parent_name, unsigned long flags,
++ void __iomem *reg, u8 shift, u8 width, u8 min_div,
++ u8 clk_divider_flags, spinlock_t *lock)
++{
++ return _register_divider(dev, name, parent_name, flags, reg, shift,
++ width, min_div, clk_divider_flags, NULL, lock);
++}
++
++/**
+ * clk_register_divider - register a divider clock with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+@@ -293,7 +322,8 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
+ u8 clk_divider_flags, spinlock_t *lock)
+ {
+ return _register_divider(dev, name, parent_name, flags, reg, shift,
+- width, clk_divider_flags, NULL, lock);
++ width, CLK_DIVIDER_MIN_DIV_DEFAULT, clk_divider_flags,
++ NULL, lock);
+ }
+
+ /**
+@@ -317,5 +347,6 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
+ spinlock_t *lock)
+ {
+ return _register_divider(dev, name, parent_name, flags, reg, shift,
+- width, clk_divider_flags, table, lock);
++ width, CLK_DIVIDER_MIN_DIV_DEFAULT, clk_divider_flags,
++ table, lock);
+ }
+diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
+index 9c7f580..942a1be 100644
+--- a/include/linux/clk-private.h
++++ b/include/linux/clk-private.h
+@@ -105,7 +105,8 @@ struct clk {
+
+ #define _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
+ _flags, _reg, _shift, _width, \
+- _divider_flags, _table, _lock) \
++ _min_div, _divider_flags, \
++ _table, _lock) \
+ static struct clk _name; \
+ static const char *_name##_parent_names[] = { \
+ _parent_name, \
+@@ -120,6 +121,7 @@ struct clk {
+ .reg = _reg, \
+ .shift = _shift, \
+ .width = _width, \
++ .min_div = _min_div, \
+ .flags = _divider_flags, \
+ .table = _table, \
+ .lock = _lock, \
+@@ -132,6 +134,7 @@ struct clk {
+ _divider_flags, _lock) \
+ _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
+ _flags, _reg, _shift, _width, \
++ CLK_DIVIDER_MIN_DIV_DEFAULT, \
+ _divider_flags, NULL, _lock)
+
+ #define DEFINE_CLK_DIVIDER_TABLE(_name, _parent_name, \
+@@ -140,6 +143,7 @@ struct clk {
+ _table, _lock) \
+ _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
+ _flags, _reg, _shift, _width, \
++ CLK_DIVIDER_MIN_DIV_DEFAULT, \
+ _divider_flags, _table, _lock) \
+
+ #define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags, \
+diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
+index 4989b8a..1c09481 100644
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -248,15 +248,22 @@ struct clk_divider {
+ void __iomem *reg;
+ u8 shift;
+ u8 width;
++ u8 min_div;
+ u8 flags;
+ const struct clk_div_table *table;
+ spinlock_t *lock;
+ };
+
++#define CLK_DIVIDER_MIN_DIV_DEFAULT 1
++
+ #define CLK_DIVIDER_ONE_BASED BIT(0)
+ #define CLK_DIVIDER_POWER_OF_TWO BIT(1)
+
+ extern const struct clk_ops clk_divider_ops;
++struct clk *clk_register_min_divider(struct device *dev, const char *name,
++ const char *parent_name, unsigned long flags,
++ void __iomem *reg, u8 shift, u8 width, u8 min_div,
++ u8 clk_divider_flags, spinlock_t *lock);
+ struct clk *clk_register_divider(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
diff --git a/patches/linux-3.8.13/0102-clk-divider-handle-minimum-divider.patch b/patches/linux-3.8.13/0102-clk-divider-handle-minimum-divider.patch
new file mode 100644
index 0000000..5fabb56
--- /dev/null
+++ b/patches/linux-3.8.13/0102-clk-divider-handle-minimum-divider.patch
@@ -0,0 +1,58 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Tue, 22 Jan 2013 20:33:56 +0530
+Subject: [PATCH] clk: divider: handle minimum divider
+
+Some of clocks can have a limit on minimum divider value that can be
+programmed. Modify basic clock divider to take care of this aspect.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/clk/clk-divider.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
+index 4025c5a..ee648dc 100644
+--- a/drivers/clk/clk-divider.c
++++ b/drivers/clk/clk-divider.c
+@@ -32,6 +32,11 @@
+ #define div_mask(d) ((1 << (d->width)) - 1)
+ #define is_power_of_two(i) !(i & ~i)
+
++static unsigned int _get_mindiv(struct clk_divider *divider)
++{
++ return divider->min_div;
++}
++
+ static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
+ {
+ unsigned int maxdiv = 0;
+@@ -148,17 +153,18 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+ {
+ struct clk_divider *divider = to_clk_divider(hw);
+ int i, bestdiv = 0;
+- unsigned long parent_rate, best = 0, now, maxdiv;
++ unsigned long parent_rate, best = 0, now, maxdiv, mindiv;
+
+ if (!rate)
+ rate = 1;
+
+ maxdiv = _get_maxdiv(divider);
++ mindiv = _get_mindiv(divider);
+
+ if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+ parent_rate = *best_parent_rate;
+ bestdiv = DIV_ROUND_UP(parent_rate, rate);
+- bestdiv = bestdiv == 0 ? 1 : bestdiv;
++ bestdiv = bestdiv == 0 ? mindiv : bestdiv;
+ bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+ return bestdiv;
+ }
+@@ -169,7 +175,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+ */
+ maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+- for (i = 1; i <= maxdiv; i++) {
++ for (i = mindiv; i <= maxdiv; i++) {
+ if (!_is_valid_div(divider, i))
+ continue;
+ parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
diff --git a/patches/linux-3.8.13/0103-ARM-OMAP2-dpll-round-rate-to-closest-value.patch b/patches/linux-3.8.13/0103-ARM-OMAP2-dpll-round-rate-to-closest-value.patch
new file mode 100644
index 0000000..d3db493
--- /dev/null
+++ b/patches/linux-3.8.13/0103-ARM-OMAP2-dpll-round-rate-to-closest-value.patch
@@ -0,0 +1,58 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 21 Jan 2013 18:24:00 +0530
+Subject: [PATCH] ARM: OMAP2+: dpll: round rate to closest value
+
+Currently round rate function would return proper rate iff requested
+rate exactly matches the PLL lockable rate. This causes set_rate to
+fail if exact rate could not be set. Instead round rate may return
+closest rate possible (less than the requested). And if any user is
+badly in need of exact rate, then return value of round rate could
+be used to decide whether to invoke set rate or not.
+
+Modify round rate so that it return closest possible rate.
+
+This was required to get display working on am335x. Without this
+display rate could not be set (taking help of SET_RATE_PARENT). Couple
+of the downstream clocks of display PLL are basic clock dividers and
+they do MULT_ROUND_UP before requesting rate on PLL causing values
+that mostly could not be locked by PLL. And even otherwise, if
+requested rate for a particular pixel clock could not be satisfied by
+PLL, display would not work. This change will resolve the issue.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/mach-omap2/clkt_dpll.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
+index 924c230..15e6d41 100644
+--- a/arch/arm/mach-omap2/clkt_dpll.c
++++ b/arch/arm/mach-omap2/clkt_dpll.c
+@@ -345,20 +345,22 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+ pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
+ clk_name, m, n, new_rate);
+
+- if (target_rate == new_rate) {
++ if ((new_rate <= target_rate) &&
++ (new_rate > dd->last_rounded_rate)) {
+ dd->last_rounded_m = m;
+ dd->last_rounded_n = n;
+- dd->last_rounded_rate = target_rate;
+- break;
++ dd->last_rounded_rate = new_rate;
++ if (new_rate == target_rate)
++ break;
+ }
+ }
+
+- if (target_rate != new_rate) {
++ if (!dd->last_rounded_rate) {
+ pr_debug("clock: %s: cannot round to rate %ld\n",
+ clk_name, target_rate);
+ return ~0;
+ }
+
+- return target_rate;
++ return dd->last_rounded_rate;
+ }
+
diff --git a/patches/linux-3.8.13/0104-ARM-OMAP2-dpll-am335x-avoid-freqsel.patch b/patches/linux-3.8.13/0104-ARM-OMAP2-dpll-am335x-avoid-freqsel.patch
new file mode 100644
index 0000000..3faefaa
--- /dev/null
+++ b/patches/linux-3.8.13/0104-ARM-OMAP2-dpll-am335x-avoid-freqsel.patch
@@ -0,0 +1,27 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 21 Jan 2013 17:13:37 +0530
+Subject: [PATCH] ARM: OMAP2+: dpll: am335x - avoid freqsel
+
+am335x does not have freqsel, avoid it.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/mach-omap2/dpll3xxx.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
+index 0a02aab5..3aed4b0 100644
+--- a/arch/arm/mach-omap2/dpll3xxx.c
++++ b/arch/arm/mach-omap2/dpll3xxx.c
+@@ -500,8 +500,9 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+ if (dd->last_rounded_rate == 0)
+ return -EINVAL;
+
+- /* No freqsel on OMAP4 and OMAP3630 */
+- if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
++ /* No freqsel on AM335x, OMAP4 and OMAP3630 */
++ if (!soc_is_am33xx() && !cpu_is_omap44xx() &&
++ !cpu_is_omap3630()) {
+ freqsel = _omap3_dpll_compute_freqsel(clk,
+ dd->last_rounded_n);
+ WARN_ON(!freqsel);
diff --git a/patches/linux-3.8.13/0105-ARM-OMAP2-clock-DEFINE_STRUCT_CLK_FLAGS-helper.patch b/patches/linux-3.8.13/0105-ARM-OMAP2-clock-DEFINE_STRUCT_CLK_FLAGS-helper.patch
new file mode 100644
index 0000000..4feb473
--- /dev/null
+++ b/patches/linux-3.8.13/0105-ARM-OMAP2-clock-DEFINE_STRUCT_CLK_FLAGS-helper.patch
@@ -0,0 +1,35 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Tue, 22 Jan 2013 15:42:00 +0530
+Subject: [PATCH] ARM: OMAP2+: clock: DEFINE_STRUCT_CLK_FLAGS helper
+
+DEFINE_STRUCT_CLK does not have the capability to set flags, define
+DEFINE_STRUCT_CLK_FLAGS to handle flags. This is needed to add
+SET_RATE_PARENT flag in statically defined lcd clock in am335x.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/mach-omap2/clock.h | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
+index b402048..60ddd86 100644
+--- a/arch/arm/mach-omap2/clock.h
++++ b/arch/arm/mach-omap2/clock.h
+@@ -65,6 +65,17 @@ struct clockdomain;
+ .ops = &_clkops_name, \
+ };
+
++#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name, \
++ _clkops_name, _flags) \
++ static struct clk _name = { \
++ .name = #_name, \
++ .hw = &_name##_hw.hw, \
++ .parent_names = _parent_array_name, \
++ .num_parents = ARRAY_SIZE(_parent_array_name), \
++ .ops = &_clkops_name, \
++ .flags = _flags, \
++ };
++
+ #define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
+ static struct clk_hw_omap _name##_hw = { \
+ .hw = { \
diff --git a/patches/linux-3.8.13/0106-ARM-AM33XX-clock-SET_RATE_PARENT-in-lcd-path.patch b/patches/linux-3.8.13/0106-ARM-AM33XX-clock-SET_RATE_PARENT-in-lcd-path.patch
new file mode 100644
index 0000000..63850ab
--- /dev/null
+++ b/patches/linux-3.8.13/0106-ARM-AM33XX-clock-SET_RATE_PARENT-in-lcd-path.patch
@@ -0,0 +1,54 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Wed, 9 Jan 2013 11:38:11 +0530
+Subject: [PATCH] ARM: AM33XX: clock: SET_RATE_PARENT in lcd path
+
+LCDC clock node is a one that does not have set rate capability. It
+just passes on the rate that is sent downstream by it's parent. While
+lcdc clock parent and it's grand parent - dpll_disp_m2_ck and
+dpll_disp_ck has the capability to configure rate.
+
+And the default rates provided by LCDC clock's ancestors are not
+sufficient to obtain pixel clock for current LCDC use cases, hence
+currently display would not work on AM335x SoC's (with driver
+modifications in platfrom independent way).
+
+Hence inform clock framework to propogate set rate for LCDC clock as
+well as it's parent - dpll_disp_m2_ck. With this change, set rate on
+LCDC clock would get propogated till dpll_disp_ck via dpll_disp_m2_ck,
+hence allowing the driver (same driver is used in DaVinci too) to set
+rates using LCDC clock without worrying about platform dependent clock
+details.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ arch/arm/mach-omap2/cclock33xx_data.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
+index a09d6d7..8dd9ecd 100644
+--- a/arch/arm/mach-omap2/cclock33xx_data.c
++++ b/arch/arm/mach-omap2/cclock33xx_data.c
+@@ -284,9 +284,10 @@ DEFINE_STRUCT_CLK(dpll_disp_ck, dpll_core_ck_parents, dpll_ddr_ck_ops);
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+-DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck, 0x0,
+- AM33XX_CM_DIV_M2_DPLL_DISP, AM33XX_DPLL_CLKOUT_DIV_SHIFT,
+- AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
++DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck,
++ CLK_SET_RATE_PARENT, AM33XX_CM_DIV_M2_DPLL_DISP,
++ AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH,
++ CLK_DIVIDER_ONE_BASED, NULL);
+
+ /* DPLL_PER */
+ static struct dpll_data dpll_per_dd = {
+@@ -723,7 +724,8 @@ static struct clk_hw_omap lcd_gclk_hw = {
+ .clksel_mask = AM33XX_CLKSEL_0_1_MASK,
+ };
+
+-DEFINE_STRUCT_CLK(lcd_gclk, lcd_ck_parents, gpio_fck_ops);
++DEFINE_STRUCT_CLK_FLAGS(lcd_gclk, lcd_ck_parents,
++ gpio_fck_ops, CLK_SET_RATE_PARENT);
+
+ DEFINE_CLK_FIXED_FACTOR(mmc_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, 2);
+
diff --git a/patches/linux-3.8.13/0107-video-da8xx-fb-make-io-operations-safe.patch b/patches/linux-3.8.13/0107-video-da8xx-fb-make-io-operations-safe.patch
new file mode 100644
index 0000000..1c89df5
--- /dev/null
+++ b/patches/linux-3.8.13/0107-video-da8xx-fb-make-io-operations-safe.patch
@@ -0,0 +1,31 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Fri, 11 Jan 2013 10:43:59 +0530
+Subject: [PATCH] video: da8xx-fb: make io operations safe
+
+Replace __raw_readl/__raw_writel with readl/writel; this driver is
+reused on ARMv7 (AM335x SoC).
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 720604c..35a33ca 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -141,12 +141,12 @@ static int frame_done_flag;
+
+ static inline unsigned int lcdc_read(unsigned int addr)
+ {
+- return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
++ return (unsigned int)readl(da8xx_fb_reg_base + (addr));
+ }
+
+ static inline void lcdc_write(unsigned int val, unsigned int addr)
+ {
+- __raw_writel(val, da8xx_fb_reg_base + (addr));
++ writel(val, da8xx_fb_reg_base + (addr));
+ }
+
+ struct da8xx_fb_par {
diff --git a/patches/linux-3.8.13/0108-video-da8xx-fb-fix-24bpp-raster-configuration.patch b/patches/linux-3.8.13/0108-video-da8xx-fb-fix-24bpp-raster-configuration.patch
new file mode 100644
index 0000000..a2e8581
--- /dev/null
+++ b/patches/linux-3.8.13/0108-video-da8xx-fb-fix-24bpp-raster-configuration.patch
@@ -0,0 +1,33 @@
+From: "Manjunathappa, Prakash" <prakash.pm@ti.com>
+Date: Tue, 27 Nov 2012 13:07:59 +0530
+Subject: [PATCH] video: da8xx-fb: fix 24bpp raster configuration
+
+Set only LCD_V2_TFT_24BPP_MODE bit for 24bpp and LCD_V2_TFT_24BPP_UNPACK
+bit along with LCD_V2_TFT_24BPP_MODE for 32bpp configuration.
+
+Patch is tested on am335x-evm for 24bpp and da850-evm for 16bpp
+configurations.
+
+Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 35a33ca..7f92f37 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -550,10 +550,10 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
+ case 4:
+ case 16:
+ break;
+- case 24:
+- reg |= LCD_V2_TFT_24BPP_MODE;
+ case 32:
+ reg |= LCD_V2_TFT_24BPP_UNPACK;
++ case 24:
++ reg |= LCD_V2_TFT_24BPP_MODE;
+ break;
+
+ case 8:
diff --git a/patches/linux-3.8.13/0109-video-da8xx-fb-enable-sync-lost-intr-for-v2-ip.patch b/patches/linux-3.8.13/0109-video-da8xx-fb-enable-sync-lost-intr-for-v2-ip.patch
new file mode 100644
index 0000000..f5bcedc
--- /dev/null
+++ b/patches/linux-3.8.13/0109-video-da8xx-fb-enable-sync-lost-intr-for-v2-ip.patch
@@ -0,0 +1,25 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 17 Dec 2012 19:37:46 +0530
+Subject: [PATCH] video: da8xx-fb: enable sync lost intr for v2 ip
+
+interrupt handler is checking for sync lost interrupt, but it was not
+enabled, enable it.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 7f92f37..ca69e01 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -318,7 +318,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
+ reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+ LCD_V2_END_OF_FRAME0_INT_ENA |
+ LCD_V2_END_OF_FRAME1_INT_ENA |
+- LCD_FRAME_DONE;
++ LCD_FRAME_DONE | LCD_SYNC_LOST;
+ lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+ }
+ reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
diff --git a/patches/linux-3.8.13/0110-video-da8xx-fb-use-devres.patch b/patches/linux-3.8.13/0110-video-da8xx-fb-use-devres.patch
new file mode 100644
index 0000000..51e0aa4
--- /dev/null
+++ b/patches/linux-3.8.13/0110-video-da8xx-fb-use-devres.patch
@@ -0,0 +1,94 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Sun, 30 Dec 2012 18:56:21 +0530
+Subject: [PATCH] video: da8xx-fb: use devres
+
+Replace existing resource handling in the driver with managed device
+resource.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 35 ++++++-----------------------------
+ 1 file changed, 6 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index ca69e01..7a32e83 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1036,12 +1036,9 @@ static int fb_remove(struct platform_device *dev)
+ par->p_palette_base);
+ dma_free_coherent(NULL, par->vram_size, par->vram_virt,
+ par->vram_phys);
+- free_irq(par->irq, par);
+ pm_runtime_put_sync(&dev->dev);
+ pm_runtime_disable(&dev->dev);
+ framebuffer_release(info);
+- iounmap(da8xx_fb_reg_base);
+- release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
+
+ }
+ return 0;
+@@ -1265,7 +1262,6 @@ static int fb_probe(struct platform_device *device)
+ struct fb_info *da8xx_fb_info;
+ struct clk *fb_clk = NULL;
+ struct da8xx_fb_par *par;
+- resource_size_t len;
+ int ret, i;
+ unsigned long ulcm;
+
+@@ -1275,29 +1271,16 @@ static int fb_probe(struct platform_device *device)
+ }
+
+ lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
+- if (!lcdc_regs) {
+- dev_err(&device->dev,
+- "Can not get memory resource for LCD controller\n");
+- return -ENOENT;
+- }
+-
+- len = resource_size(lcdc_regs);
+-
+- lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name);
+- if (!lcdc_regs)
+- return -EBUSY;
+-
+- da8xx_fb_reg_base = ioremap(lcdc_regs->start, len);
++ da8xx_fb_reg_base = devm_request_and_ioremap(&device->dev, lcdc_regs);
+ if (!da8xx_fb_reg_base) {
+- ret = -EBUSY;
+- goto err_request_mem;
++ dev_err(&device->dev, "memory resource setup failed\n");
++ return -EADDRNOTAVAIL;
+ }
+
+- fb_clk = clk_get(&device->dev, "fck");
++ fb_clk = devm_clk_get(&device->dev, "fck");
+ if (IS_ERR(fb_clk)) {
+ dev_err(&device->dev, "Can not get device clock\n");
+- ret = -ENODEV;
+- goto err_ioremap;
++ return -ENODEV;
+ }
+
+ pm_runtime_enable(&device->dev);
+@@ -1458,7 +1441,7 @@ static int fb_probe(struct platform_device *device)
+ lcdc_irq_handler = lcdc_irq_handler_rev02;
+ }
+
+- ret = request_irq(par->irq, lcdc_irq_handler, 0,
++ ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
+ DRIVER_NAME, par);
+ if (ret)
+ goto irq_freq;
+@@ -1488,12 +1471,6 @@ err_pm_runtime_disable:
+ pm_runtime_put_sync(&device->dev);
+ pm_runtime_disable(&device->dev);
+
+-err_ioremap:
+- iounmap(da8xx_fb_reg_base);
+-
+-err_request_mem:
+- release_mem_region(lcdc_regs->start, len);
+-
+ return ret;
+ }
+
diff --git a/patches/linux-3.8.13/0111-video-da8xx-fb-ensure-non-null-cfg-in-pdata.patch b/patches/linux-3.8.13/0111-video-da8xx-fb-ensure-non-null-cfg-in-pdata.patch
new file mode 100644
index 0000000..90b6022
--- /dev/null
+++ b/patches/linux-3.8.13/0111-video-da8xx-fb-ensure-non-null-cfg-in-pdata.patch
@@ -0,0 +1,27 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 31 Dec 2012 01:03:41 +0530
+Subject: [PATCH] video: da8xx-fb: ensure non-null cfg in pdata
+
+Ensure that platform data contains pointer for lcd_ctrl_config.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 7a32e83..3b146bc 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1320,6 +1320,11 @@ static int fb_probe(struct platform_device *device)
+
+ lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+
++ if (!lcd_cfg) {
++ ret = -EINVAL;
++ goto err_pm_runtime_disable;
++ }
++
+ da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
+ &device->dev);
+ if (!da8xx_fb_info) {
diff --git a/patches/linux-3.8.13/0112-video-da8xx-fb-reorganize-panel-detection.patch b/patches/linux-3.8.13/0112-video-da8xx-fb-reorganize-panel-detection.patch
new file mode 100644
index 0000000..253344b
--- /dev/null
+++ b/patches/linux-3.8.13/0112-video-da8xx-fb-reorganize-panel-detection.patch
@@ -0,0 +1,86 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Sun, 30 Dec 2012 23:49:36 +0530
+Subject: [PATCH] video: da8xx-fb: reorganize panel detection
+
+Move panel detection to a separate function, this helps in readability
+as well as makes DT support cleaner.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 42 ++++++++++++++++++++++++++----------------
+ 1 file changed, 26 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 3b146bc..b6ea5e9 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1253,6 +1253,27 @@ static struct fb_ops da8xx_fb_ops = {
+ .fb_blank = cfb_blank,
+ };
+
++static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
++{
++ struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
++ struct fb_videomode *lcdc_info;
++ int i;
++
++ for (i = 0, lcdc_info = known_lcd_panels;
++ i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
++ if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
++ break;
++ }
++
++ if (i == ARRAY_SIZE(known_lcd_panels)) {
++ dev_err(&dev->dev, "no panel found\n");
++ return NULL;
++ }
++ dev_info(&dev->dev, "found %s panel\n", lcdc_info->name);
++
++ return lcdc_info;
++}
++
+ static int fb_probe(struct platform_device *device)
+ {
+ struct da8xx_lcdc_platform_data *fb_pdata =
+@@ -1262,7 +1283,7 @@ static int fb_probe(struct platform_device *device)
+ struct fb_info *da8xx_fb_info;
+ struct clk *fb_clk = NULL;
+ struct da8xx_fb_par *par;
+- int ret, i;
++ int ret;
+ unsigned long ulcm;
+
+ if (fb_pdata == NULL) {
+@@ -1270,6 +1291,10 @@ static int fb_probe(struct platform_device *device)
+ return -ENOENT;
+ }
+
++ lcdc_info = da8xx_fb_get_videomode(device);
++ if (lcdc_info == NULL)
++ return -ENODEV;
++
+ lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
+ da8xx_fb_reg_base = devm_request_and_ioremap(&device->dev, lcdc_regs);
+ if (!da8xx_fb_reg_base) {
+@@ -1303,21 +1328,6 @@ static int fb_probe(struct platform_device *device)
+ break;
+ }
+
+- for (i = 0, lcdc_info = known_lcd_panels;
+- i < ARRAY_SIZE(known_lcd_panels);
+- i++, lcdc_info++) {
+- if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
+- break;
+- }
+-
+- if (i == ARRAY_SIZE(known_lcd_panels)) {
+- dev_err(&device->dev, "GLCD: No valid panel found\n");
+- ret = -ENODEV;
+- goto err_pm_runtime_disable;
+- } else
+- dev_info(&device->dev, "GLCD: Found %s panel\n",
+- fb_pdata->type);
+-
+ lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+
+ if (!lcd_cfg) {
diff --git a/patches/linux-3.8.13/0113-video-da8xx-fb-minimal-dt-support.patch b/patches/linux-3.8.13/0113-video-da8xx-fb-minimal-dt-support.patch
new file mode 100644
index 0000000..a17826f
--- /dev/null
+++ b/patches/linux-3.8.13/0113-video-da8xx-fb-minimal-dt-support.patch
@@ -0,0 +1,60 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Sun, 30 Dec 2012 19:11:08 +0530
+Subject: [PATCH] video: da8xx-fb: minimal dt support
+
+Driver is provided a means to have the probe triggered by DT.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ Documentation/devicetree/bindings/video/fb-da8xx.txt | 16 ++++++++++++++++
+ drivers/video/da8xx-fb.c | 7 +++++++
+ 2 files changed, 23 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/video/fb-da8xx.txt
+
+diff --git a/Documentation/devicetree/bindings/video/fb-da8xx.txt b/Documentation/devicetree/bindings/video/fb-da8xx.txt
+new file mode 100644
+index 0000000..581e014
+--- /dev/null
++++ b/Documentation/devicetree/bindings/video/fb-da8xx.txt
+@@ -0,0 +1,16 @@
++TI LCD Controller on DA830/DA850/AM335x SoC's
++
++Required properties:
++- compatible:
++ DA830 - "ti,da830-lcdc"
++ AM335x SoC's - "ti,am3352-lcdc", "ti,da830-lcdc"
++- reg: Address range of lcdc register set
++- interrupts: lcdc interrupt
++
++Example:
++
++lcdc@4830e000 {
++ compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupts = <36>;
++};
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index b6ea5e9..08ee8eb 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1595,6 +1595,12 @@ static int fb_resume(struct platform_device *dev)
+ #define fb_resume NULL
+ #endif
+
++static const struct of_device_id da8xx_fb_of_match[] = {
++ {.compatible = "ti,da830-lcdc", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, da8xx_fb_of_match);
++
+ static struct platform_driver da8xx_fb_driver = {
+ .probe = fb_probe,
+ .remove = fb_remove,
+@@ -1603,6 +1609,7 @@ static struct platform_driver da8xx_fb_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(da8xx_fb_of_match),
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0114-video-da8xx-fb-invoke-platform-callback-safely.patch b/patches/linux-3.8.13/0114-video-da8xx-fb-invoke-platform-callback-safely.patch
new file mode 100644
index 0000000..e5fa674
--- /dev/null
+++ b/patches/linux-3.8.13/0114-video-da8xx-fb-invoke-platform-callback-safely.patch
@@ -0,0 +1,27 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 31 Dec 2012 00:02:32 +0530
+Subject: [PATCH] video: da8xx-fb: invoke platform callback safely
+
+Ensure that platform data is present before checking whether platform
+callback is present (the one used to control backlight). So far this
+was not an issue as driver was purely non-DT triggered, but now DT
+support has been added.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 08ee8eb..0beed20 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1347,7 +1347,7 @@ static int fb_probe(struct platform_device *device)
+ par->dev = &device->dev;
+ par->lcdc_clk = fb_clk;
+ par->lcd_fck_rate = clk_get_rate(fb_clk);
+- if (fb_pdata->panel_power_ctrl) {
++ if (fb_pdata && fb_pdata->panel_power_ctrl) {
+ par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
+ par->panel_power_ctrl(1);
+ }
diff --git a/patches/linux-3.8.13/0115-video-da8xx-fb-obtain-fb_videomode-info-from-dt.patch b/patches/linux-3.8.13/0115-video-da8xx-fb-obtain-fb_videomode-info-from-dt.patch
new file mode 100644
index 0000000..4276bbb
--- /dev/null
+++ b/patches/linux-3.8.13/0115-video-da8xx-fb-obtain-fb_videomode-info-from-dt.patch
@@ -0,0 +1,87 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 31 Dec 2012 00:31:14 +0530
+Subject: [PATCH] video: da8xx-fb: obtain fb_videomode info from dt
+
+Obtain fb_videomode details for the connected lcd panel using the
+display timing details present in DT.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ .../devicetree/bindings/video/fb-da8xx.txt | 21 ++++++++++++++++++++
+ drivers/video/da8xx-fb.c | 17 ++++++++++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/video/fb-da8xx.txt b/Documentation/devicetree/bindings/video/fb-da8xx.txt
+index 581e014..0741f78 100644
+--- a/Documentation/devicetree/bindings/video/fb-da8xx.txt
++++ b/Documentation/devicetree/bindings/video/fb-da8xx.txt
+@@ -6,6 +6,12 @@ Required properties:
+ AM335x SoC's - "ti,am3352-lcdc", "ti,da830-lcdc"
+ - reg: Address range of lcdc register set
+ - interrupts: lcdc interrupt
++- display-timings: typical videomode of lcd panel, represented as child.
++ Refer Documentation/devicetree/bindings/video/display-timing.txt for
++ display timing binding details. If multiple videomodes are mentioned
++ in display timings node, typical videomode has to be mentioned as the
++ native mode or it has to be first child (driver cares only for native
++ videomode).
+
+ Example:
+
+@@ -13,4 +19,19 @@ lcdc@4830e000 {
+ compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupts = <36>;
++ display-timings {
++ 800x480p62 {
++ clock-frequency = <30000000>;
++ hactive = <800>;
++ vactive = <480>;
++ hfront-porch = <39>;
++ hback-porch = <39>;
++ hsync-len = <47>;
++ vback-porch = <29>;
++ vfront-porch = <13>;
++ vsync-len = <2>;
++ hsync-active = <1>;
++ vsync-active = <1>;
++ };
++ };
+ };
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 0beed20..0c68712 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -36,6 +36,7 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/lcm.h>
++#include <video/of_display_timing.h>
+ #include <video/da8xx-fb.h>
+ #include <asm/div64.h>
+
+@@ -1257,8 +1258,24 @@ static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
+ {
+ struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
+ struct fb_videomode *lcdc_info;
++ struct device_node *np = dev->dev.of_node;
+ int i;
+
++ if (np) {
++ lcdc_info = devm_kzalloc(&dev->dev,
++ sizeof(struct fb_videomode),
++ GFP_KERNEL);
++ if (!lcdc_info) {
++ dev_err(&dev->dev, "memory allocation failed\n");
++ return NULL;
++ }
++ if (of_get_fb_videomode(np, lcdc_info, OF_USE_NATIVE_MODE)) {
++ dev_err(&dev->dev, "timings not available in DT\n");
++ return NULL;
++ }
++ return lcdc_info;
++ }
++
+ for (i = 0, lcdc_info = known_lcd_panels;
+ i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
+ if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
diff --git a/patches/linux-3.8.13/0116-video-da8xx-fb-ensure-pdata-only-for-non-dt.patch b/patches/linux-3.8.13/0116-video-da8xx-fb-ensure-pdata-only-for-non-dt.patch
new file mode 100644
index 0000000..d0aa079
--- /dev/null
+++ b/patches/linux-3.8.13/0116-video-da8xx-fb-ensure-pdata-only-for-non-dt.patch
@@ -0,0 +1,25 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 31 Dec 2012 14:37:16 +0530
+Subject: [PATCH] video: da8xx-fb: ensure pdata only for non-dt
+
+This driver is DT probe-able, hence ensure presence of platform data
+only for non-DT boot.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 0c68712..1c1a616 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1303,7 +1303,7 @@ static int fb_probe(struct platform_device *device)
+ int ret;
+ unsigned long ulcm;
+
+- if (fb_pdata == NULL) {
++ if (fb_pdata == NULL && !device->dev.of_node) {
+ dev_err(&device->dev, "Can not get platform data\n");
+ return -ENOENT;
+ }
diff --git a/patches/linux-3.8.13/0117-video-da8xx-fb-setup-struct-lcd_ctrl_config-for-dt.patch b/patches/linux-3.8.13/0117-video-da8xx-fb-setup-struct-lcd_ctrl_config-for-dt.patch
new file mode 100644
index 0000000..48c97ea
--- /dev/null
+++ b/patches/linux-3.8.13/0117-video-da8xx-fb-setup-struct-lcd_ctrl_config-for-dt.patch
@@ -0,0 +1,66 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Mon, 31 Dec 2012 15:03:12 +0530
+Subject: [PATCH] video: da8xx-fb: setup struct lcd_ctrl_config for dt
+
+strcut lcd_ctrl_config information required for driver is currently
+obtained via platform data. To handle DT probing, create
+lcd_ctrl_config and populate it with default values, these values are
+sufficient for the panels so far used with this controller to work.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 34 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 33 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 1c1a616..5455682 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1254,6 +1254,35 @@ static struct fb_ops da8xx_fb_ops = {
+ .fb_blank = cfb_blank,
+ };
+
++static struct lcd_ctrl_config *da8xx_fb_create_cfg(struct platform_device *dev)
++{
++ struct lcd_ctrl_config *cfg;
++
++ cfg = devm_kzalloc(&dev->dev, sizeof(struct fb_videomode), GFP_KERNEL);
++ if (!cfg) {
++ dev_err(&dev->dev, "memory allocation failed\n");
++ return NULL;
++ }
++
++ /* default values */
++
++ if (lcd_revision == LCD_VERSION_1)
++ cfg->bpp = 16;
++ else
++ cfg->bpp = 32;
++
++ /*
++ * For panels so far used with this LCDC, below statement is sufficient.
++ * For new panels, if required, struct lcd_ctrl_cfg fields to be updated
++ * with additional/modified values. Those values would have to be then
++ * obtained from dt(requiring new dt bindings).
++ */
++
++ cfg->panel_shade = COLOR_ACTIVE;
++
++ return cfg;
++}
++
+ static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
+ {
+ struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
+@@ -1345,7 +1374,10 @@ static int fb_probe(struct platform_device *device)
+ break;
+ }
+
+- lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
++ if (device->dev.of_node)
++ lcd_cfg = da8xx_fb_create_cfg(device);
++ else
++ lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+
+ if (!lcd_cfg) {
+ ret = -EINVAL;
diff --git a/patches/linux-3.8.13/0118-video-da8xx-fb-CCF-clock-divider-handling.patch b/patches/linux-3.8.13/0118-video-da8xx-fb-CCF-clock-divider-handling.patch
new file mode 100644
index 0000000..5495935
--- /dev/null
+++ b/patches/linux-3.8.13/0118-video-da8xx-fb-CCF-clock-divider-handling.patch
@@ -0,0 +1,164 @@
+From: Afzal Mohammed <afzal@ti.com>
+Date: Wed, 16 Jan 2013 18:14:31 +0530
+Subject: [PATCH] video: da8xx-fb: CCF clock divider handling
+
+Common clock framework provides a basic clock divider. Make use of it
+to handle clock configuration in the LCDC IP, wherever applicable;
+out of two platforms having this IP, only am335x is converted to use
+CCF, DaVinci is not yet converted. Hence wrap the modification such
+that it will come into effect only if CCF is selected, otherwise,
+prgram dividers as earlier. Once DaVinci is converted to use CCF,
+this ifdef'ery can be removed.
+
+Divider clock instantiated is made as a one that allows the rate
+propogation to it's parent, that provides more options w.r.t pixel
+clock rates that could be configured.
+
+Signed-off-by: Afzal Mohammed <afzal@ti.com>
+---
+ drivers/video/da8xx-fb.c | 72 ++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 70 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 5455682..6723683 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -36,6 +36,7 @@
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/lcm.h>
++#include <linux/clk-provider.h>
+ #include <video/of_display_timing.h>
+ #include <video/da8xx-fb.h>
+ #include <asm/div64.h>
+@@ -133,6 +134,10 @@
+ #define WSI_TIMEOUT 50
+ #define PALETTE_SIZE 256
+
++#define LCD_CLK_SHIFT 8
++#define LCD_CLK_WIDTH 8
++#define LCD_CLK_MIN_DIV 2
++
+ static void __iomem *da8xx_fb_reg_base;
+ static struct resource *lcdc_regs;
+ static unsigned int lcd_revision;
+@@ -181,6 +186,9 @@ struct da8xx_fb_par {
+ u32 pseudo_palette[16];
+ struct fb_videomode mode;
+ struct lcd_ctrl_config cfg;
++#ifdef CONFIG_COMMON_CLK
++ struct clk *child_clk;
++#endif
+ };
+
+ static struct fb_var_screeninfo da8xx_fb_var;
+@@ -683,12 +691,27 @@ static void da8xx_fb_lcd_reset(void)
+ }
+ }
+
++#ifndef CONFIG_COMMON_CLK
+ static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
+ unsigned pixclock)
+ {
+ return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
+ }
++#endif
+
++#ifdef CONFIG_COMMON_CLK
++static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
++ unsigned pixclock)
++{
++ unsigned long rate;
++
++ rate = PICOS2KHZ(pixclock) * 1000;
++ rate = clk_round_rate(par->child_clk, rate);
++ rate = KHZ2PICOS(rate / 1000);
++
++ return rate;
++}
++#else
+ static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+ unsigned pixclock)
+ {
+@@ -703,19 +726,43 @@ static inline void da8xx_fb_config_clk_divider(unsigned div)
+ /* Configure the LCD clock divisor. */
+ lcdc_write(LCD_CLK_DIVISOR(div) |
+ (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
++}
++#endif
+
++static inline void da8xx_fb_clkc_enable(void)
++{
+ if (lcd_revision == LCD_VERSION_2)
+ lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
+ LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
+ }
+
+-static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
++#ifdef CONFIG_COMMON_CLK
++static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
++ struct fb_videomode *mode)
++{
++ int ret;
++
++ ret = clk_set_rate(par->child_clk, PICOS2KHZ(mode->pixclock) * 1000);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(par->dev, "unable to setup pixel clock of %u ps",
++ mode->pixclock);
++ return ret;
++ }
++ da8xx_fb_clkc_enable();
++ return 0;
++}
++#else
++static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+ struct fb_videomode *mode)
+ {
+ unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock);
+
+ da8xx_fb_config_clk_divider(div);
++ da8xx_fb_clkc_enable();
++
++ return 0;
+ }
++#endif
+
+ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
+ struct fb_videomode *panel)
+@@ -723,7 +770,9 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
+ u32 bpp;
+ int ret = 0;
+
+- da8xx_fb_calc_config_clk_divider(par, panel);
++ ret = da8xx_fb_calc_config_clk_divider(par, panel);
++ if (IS_ERR_VALUE(ret))
++ return ret;
+
+ if (panel->sync & FB_SYNC_CLK_INVERT)
+ lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
+@@ -1406,6 +1455,25 @@ static int fb_probe(struct platform_device *device)
+
+ da8xx_fb_lcd_reset();
+
++#ifdef CONFIG_COMMON_CLK
++ /* set sane divisor value to begin along with the mode */
++ lcdc_write(LCD_RASTER_MODE | LCD_CLK_DIVISOR(LCD_CLK_MIN_DIV),
++ LCD_CTRL_REG);
++
++ par->child_clk = clk_register_min_divider(NULL, "da8xx_fb_clk",
++ __clk_get_name(fb_clk),
++ CLK_SET_RATE_PARENT,
++ da8xx_fb_reg_base + LCD_CTRL_REG,
++ LCD_CLK_SHIFT, LCD_CLK_WIDTH,
++ LCD_CLK_MIN_DIV,
++ CLK_DIVIDER_ONE_BASED, NULL);
++ if (IS_ERR(par->child_clk)) {
++ dev_err(&device->dev, "error registering clk\n");
++ ret = -ENODEV;
++ goto err_release_fb;
++ }
++#endif
++
+ /* allocate frame buffer */
+ par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
+ ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
diff --git a/patches/linux-3.8.13/0119-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch b/patches/linux-3.8.13/0119-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
new file mode 100644
index 0000000..8e5d982
--- /dev/null
+++ b/patches/linux-3.8.13/0119-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
@@ -0,0 +1,67 @@
+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.8.13/0120-Control-module-EHRPWM-clk-enabling.patch b/patches/linux-3.8.13/0120-Control-module-EHRPWM-clk-enabling.patch
new file mode 100644
index 0000000..667f0d2
--- /dev/null
+++ b/patches/linux-3.8.13/0120-Control-module-EHRPWM-clk-enabling.patch
@@ -0,0 +1,42 @@
+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 626f3ea..8ca1520 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -446,6 +446,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
+ *
+@@ -732,6 +746,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.8.13/0121-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch b/patches/linux-3.8.13/0121-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
new file mode 100644
index 0000000..119cfe2
--- /dev/null
+++ b/patches/linux-3.8.13/0121-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
@@ -0,0 +1,369 @@
+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 e513cd9..74f5084 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -191,4 +191,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 62a2963..8ddb432 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -16,3 +16,4 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o
+ obj-$(CONFIG_PWM_TWL) += pwm-twl.o
+ obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.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.8.13/0122-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch b/patches/linux-3.8.13/0122-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch
new file mode 100644
index 0000000..800f770
--- /dev/null
+++ b/patches/linux-3.8.13/0122-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch
@@ -0,0 +1,26 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 27 Nov 2012 10:53:23 -0600
+Subject: [PATCH] ARM: OMAP2: PWM: limit am33xx_register_ehrpwm to
+ soc_is_am33xx, fixes boot on Beagle/Panda
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/devices.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index 8ca1520..f5c71ac 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -745,8 +745,9 @@ static int __init omap2_init_devices(void)
+ omap_init_aes();
+ omap_init_vout();
+ omap_init_ocp2scp();
+-
+- am33xx_register_ehrpwm();
++ if (soc_is_am33xx()) {
++ am33xx_register_ehrpwm();
++ }
+ return 0;
+ }
+ arch_initcall(omap2_init_devices);
diff --git a/patches/linux-3.8.13/0123-pwm-export-of_pwm_request.patch b/patches/linux-3.8.13/0123-pwm-export-of_pwm_request.patch
new file mode 100644
index 0000000..70e84e4
--- /dev/null
+++ b/patches/linux-3.8.13/0123-pwm-export-of_pwm_request.patch
@@ -0,0 +1,71 @@
+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 of_pwm_request, it's useful to other in-kernel users.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+
+Conflicts:
+ include/linux/pwm.h
+---
+ 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 903138b..0478442 100644
+--- a/drivers/pwm/core.c
++++ b/drivers/pwm/core.c
+@@ -486,7 +486,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;
+@@ -495,6 +495,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)
+@@ -545,6 +548,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 6d661f3..b21c020 100644
+--- a/include/linux/pwm.h
++++ b/include/linux/pwm.h
+@@ -174,6 +174,7 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc,
+ const struct of_phandle_args *args);
+
++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);
+
+@@ -207,6 +208,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.8.13/0124-pwm-pwm-tiehrpwm-Update-the-clock-handling-of-pwm-ti.patch b/patches/linux-3.8.13/0124-pwm-pwm-tiehrpwm-Update-the-clock-handling-of-pwm-ti.patch
new file mode 100644
index 0000000..b1eaa79
--- /dev/null
+++ b/patches/linux-3.8.13/0124-pwm-pwm-tiehrpwm-Update-the-clock-handling-of-pwm-ti.patch
@@ -0,0 +1,38 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Wed, 2 Jan 2013 13:24:50 +0000
+Subject: [PATCH] pwm: pwm-tiehrpwm: Update the clock handling of pwm-tiehrpwm
+ driver
+
+The clock framework has changed and it's now better to invoke
+clock_prepare_enable() and clk_disable_unprepare() rather than the
+legacy clk_enable() and clk_disable() calls. This patch converts the
+pwm-tiehrpwm driver to the new framework.
+
+Signed-off-by: Philip Avinash <avinashphilip@ti.com>
+Cc: Thierry Reding <thierry.reding@avionic-design.de>
+---
+ drivers/pwm/pwm-tiehrpwm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index 72a6dd4..af6f162 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -341,7 +341,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+ configure_polarity(pc, pwm->hwpwm);
+
+ /* Enable TBCLK before enabling PWM device */
+- clk_enable(pc->tbclk);
++ clk_prepare_enable(pc->tbclk);
+
+ /* Enable time counter for free_run */
+ ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
+@@ -372,7 +372,7 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+ ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
+
+ /* Disabling TBCLK on PWM disable */
+- clk_disable(pc->tbclk);
++ clk_disable_unprepare(pc->tbclk);
+
+ /* Stop Time base counter */
+ ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
diff --git a/patches/linux-3.8.13/0125-ARM-AM33XX-clk-Add-clock-node-for-EHRPWM-TBCLK.patch b/patches/linux-3.8.13/0125-ARM-AM33XX-clk-Add-clock-node-for-EHRPWM-TBCLK.patch
new file mode 100644
index 0000000..8620ad3
--- /dev/null
+++ b/patches/linux-3.8.13/0125-ARM-AM33XX-clk-Add-clock-node-for-EHRPWM-TBCLK.patch
@@ -0,0 +1,80 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Wed, 2 Jan 2013 13:24:51 +0000
+Subject: [PATCH] ARM: AM33XX: clk: Add clock node for EHRPWM TBCLK
+
+EHRPWM module requires explicit clock gating of TBCLK from control
+module. Hence add TBCLK clock node in clock tree for EHRPWM modules.
+
+Signed-off-by: Philip Avinash <avinashphilip@ti.com>
+---
+ arch/arm/mach-omap2/cclock33xx_data.c | 30 ++++++++++++++++++++++++++++++
+ arch/arm/mach-omap2/control.h | 8 ++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
+index 8dd9ecd..2e2d579 100644
+--- a/arch/arm/mach-omap2/cclock33xx_data.c
++++ b/arch/arm/mach-omap2/cclock33xx_data.c
+@@ -834,6 +834,33 @@ static struct clk_hw_omap wdt1_fck_hw = {
+
+ DEFINE_STRUCT_CLK(wdt1_fck, wdt_ck_parents, gpio_fck_ops);
+
++static const char *pwmss_clk_parents[] = {
++ "dpll_per_m2_ck",
++};
++
++static const struct clk_ops ehrpwm_tbclk_ops = {
++ .enable = &omap2_dflt_clk_enable,
++ .disable = &omap2_dflt_clk_disable,
++};
++
++DEFINE_CLK_OMAP_MUX_GATE(ehrpwm0_tbclk, "l4ls_clkdm",
++ 0, NULL, 0,
++ AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
++ AM33XX_PWMSS0_TBCLKEN_SHIFT,
++ NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
++
++DEFINE_CLK_OMAP_MUX_GATE(ehrpwm1_tbclk, "l4ls_clkdm",
++ 0, NULL, 0,
++ AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
++ AM33XX_PWMSS1_TBCLKEN_SHIFT,
++ NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
++
++DEFINE_CLK_OMAP_MUX_GATE(ehrpwm2_tbclk, "l4ls_clkdm",
++ 0, NULL, 0,
++ AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
++ AM33XX_PWMSS2_TBCLKEN_SHIFT,
++ NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
++
+ /*
+ * clkdev
+ */
+@@ -912,6 +939,9 @@ static struct omap_clk am33xx_clks[] = {
+ CLK(NULL, "clkout2_div_ck", &clkout2_div_ck, CK_AM33XX),
+ CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX),
+ CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX),
++ CLK("48300200.ehrpwm", "tbclk", &ehrpwm0_tbclk, CK_AM33XX),
++ CLK("48302200.ehrpwm", "tbclk", &ehrpwm1_tbclk, CK_AM33XX),
++ CLK("48304200.ehrpwm", "tbclk", &ehrpwm2_tbclk, CK_AM33XX),
+ };
+
+
+diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
+index e6c3281..35d17a6 100644
+--- a/arch/arm/mach-omap2/control.h
++++ b/arch/arm/mach-omap2/control.h
+@@ -358,6 +358,14 @@
+ #define AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH 0x2
+ #define AM33XX_CONTROL_STATUS_SYSBOOT1_MASK (0x3 << 22)
+
++/* AM33XX PWMSS Control register */
++#define AM33XX_PWMSS_TBCLK_CLKCTRL 0x664
++
++/* AM33XX PWMSS Control bitfields */
++#define AM33XX_PWMSS0_TBCLKEN_SHIFT 0
++#define AM33XX_PWMSS1_TBCLKEN_SHIFT 1
++#define AM33XX_PWMSS2_TBCLKEN_SHIFT 2
++
+ /* CONTROL OMAP STATUS register to identify OMAP3 features */
+ #define OMAP3_CONTROL_OMAP_STATUS 0x044c
+
diff --git a/patches/linux-3.8.13/0126-HACK-am33xx.dtsi-turn-on-all-PWMs.patch b/patches/linux-3.8.13/0126-HACK-am33xx.dtsi-turn-on-all-PWMs.patch
new file mode 100644
index 0000000..58a7027
--- /dev/null
+++ b/patches/linux-3.8.13/0126-HACK-am33xx.dtsi-turn-on-all-PWMs.patch
@@ -0,0 +1,94 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 28 Jan 2013 18:15:29 +0100
+Subject: [PATCH] HACK: am33xx.dtsi: turn on all PWMs
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index e832be8..c0d9c5b 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -470,7 +470,7 @@
+ ti,hwmods = "epwmss0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- status = "disabled";
++ //status = "disabled";
+ ranges = <0x48300100 0x48300100 0x80 /* ECAP */
+ 0x48300180 0x48300180 0x80 /* EQEP */
+ 0x48300200 0x48300200 0x80>; /* EHRPWM */
+@@ -480,7 +480,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48300100 0x80>;
+ ti,hwmods = "ecap0";
+- status = "disabled";
++ //status = "disabled";
+ };
+
+ ehrpwm0: ehrpwm@48300200 {
+@@ -488,7 +488,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48300200 0x80>;
+ ti,hwmods = "ehrpwm0";
+- status = "disabled";
++ //status = "disabled";
+ };
+ };
+
+@@ -498,7 +498,7 @@
+ ti,hwmods = "epwmss1";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- status = "disabled";
++ //status = "disabled";
+ ranges = <0x48302100 0x48302100 0x80 /* ECAP */
+ 0x48302180 0x48302180 0x80 /* EQEP */
+ 0x48302200 0x48302200 0x80>; /* EHRPWM */
+@@ -508,7 +508,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48302100 0x80>;
+ ti,hwmods = "ecap1";
+- status = "disabled";
++ //status = "disabled";
+ };
+
+ ehrpwm1: ehrpwm@48302200 {
+@@ -516,7 +516,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48302200 0x80>;
+ ti,hwmods = "ehrpwm1";
+- status = "disabled";
++ //status = "disabled";
+ };
+ };
+
+@@ -526,7 +526,7 @@
+ ti,hwmods = "epwmss2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- status = "disabled";
++ //status = "disabled";
+ ranges = <0x48304100 0x48304100 0x80 /* ECAP */
+ 0x48304180 0x48304180 0x80 /* EQEP */
+ 0x48304200 0x48304200 0x80>; /* EHRPWM */
+@@ -536,7 +536,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48304100 0x80>;
+ ti,hwmods = "ecap2";
+- status = "disabled";
++ //status = "disabled";
+ };
+
+ ehrpwm2: ehrpwm@48304200 {
+@@ -544,7 +544,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48304200 0x80>;
+ ti,hwmods = "ehrpwm2";
+- status = "disabled";
++ //status = "disabled";
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0127-pwm-add-sysfs-interface.patch b/patches/linux-3.8.13/0127-pwm-add-sysfs-interface.patch
new file mode 100644
index 0000000..61f2992
--- /dev/null
+++ b/patches/linux-3.8.13/0127-pwm-add-sysfs-interface.patch
@@ -0,0 +1,790 @@
+From: Lars Poeschel <poeschel@lemonage.de>
+Date: Wed, 3 Apr 2013 15:58:55 +0200
+Subject: [PATCH] pwm: add sysfs interface
+
+This adds a simple sysfs interface to the pwm subsystem. It is
+heavily inspired by the gpio sysfs interface.
+
+ /sys/class/pwm
+ /export ... asks the kernel to export a PWM to userspace
+ /unexport ... to return a PWM to the kernel
+ /pwmN ... for each exported PWM #N
+ /duty_ns ... r/w, length of duty portion
+ /period_ns ... r/w, length of the pwm period
+ /polarity ... r/w, normal(0) or inverse(1) polarity
+ only created if driver supports it
+ /run ... r/w, write 1 to start and 0 to stop the pwm
+ /pwmchipN ... for each pwmchip; #N is its first PWM
+ /base ... (r/o) same as N
+ /ngpio ... (r/o) number of PWM; numbered N .. MAX_PWMS
+
+Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
+
+--
+---
+ Documentation/ABI/testing/sysfs-class-pwm | 37 +++
+ Documentation/pwm.txt | 46 +++
+ drivers/pwm/Kconfig | 12 +
+ drivers/pwm/core.c | 494 ++++++++++++++++++++++++++++-
+ include/linux/pwm.h | 27 +-
+ 5 files changed, 610 insertions(+), 6 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-class-pwm
+
+diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm
+new file mode 100644
+index 0000000..e9be1a3
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-class-pwm
+@@ -0,0 +1,37 @@
++What: /sys/class/pwm/
++Date: March 2013
++KernelVersion: 3.11
++Contact: Lars Poeschel <poeschel@lemonage.de>
++Description:
++
++ The sysfs interface for PWM is selectable as a Kconfig option.
++ If a driver successfully probed a pwm chip, it appears at
++ /sys/class/pwm/pwmchipN/ where N is the number of it's first PWM channel. A
++ single driver may probe multiple chips. PWMs are identified as they are
++ inside the kernel, using integers in the range 0..MAX_PWMS. To use an
++ individual PWM, you have to explicitly export it by writing it's kernel
++ global number into the /sys/class/pwm/export file. Write it's number to
++ /sys/class/pwm/unexport to make the pwm available for other uses.
++ After a PWM channel is exported, it is available under
++ /sys/class/pwm/pwmN/. Under this directory you can set the parameters for
++ this PWM channel and at least let it start running.
++ See below for the parameters.
++ It is recommended to set the period_ns at first and the duty_ns after that.
++
++ See Documentation/pwm.txt for more information.
++
++Directory structure:
++
++ /sys/class/pwm
++ /export ... asks the kernel to export a PWM to userspace
++ /unexport ... to return a PWM to the kernel
++ /pwmN ... for each exported PWM #N
++ /duty_ns ... r/w, length of duty portion
++ /period_ns ... r/w, length of the pwm period
++ /polarity ... r/w, normal(0) or inverse(1) polarity
++ only created if driver supports it
++ /run ... r/w, write 1 to start and 0 to stop the pwm
++ /pwmchipN ... for each pwmchip; #N is its first PWM
++ /base ... (r/o) same as N
++ /ngpio ... (r/o) number of PWM; numbered N .. MAX_PWMS
++
+diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
+index 7d2b4c9..b349d16 100644
+--- a/Documentation/pwm.txt
++++ b/Documentation/pwm.txt
+@@ -45,6 +45,52 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
+
+ To start/stop toggling the PWM output use pwm_enable()/pwm_disable().
+
++Using PWMs with the sysfs interface
++-----------------------------------
++
++You have to enable CONFIG_PWM_SYSFS in your kernel configuration to use
++the sysfs interface. It is exposed at /sys/class/pwm/. If there are pwm
++drivers loaded and these drivers successfully probed a chip, this chip
++is exported as pwmchipX . Note that a single driver can probe multiple chips.
++Inside the directory you can read these properties:
++
++base - This is the linux global start where the chips pwm channels get
++exposed.
++
++npwm - This is the number of pwm channels this chip supports.
++
++If you want to start using a pwm channel with sysfs first you have to
++export it. If you are finished with it and want to free the pwm for other
++uses, you can unexport it:
++
++export - Write the global pwm channel number to this file to start using
++the channel with sysfs.
++
++unexport - Write the global pwm channel number of the channel you are finshed
++with to this file to make the channel available for other uses.
++
++Once a pwm is exported a pwmX (X ranging from 0 to MAX_PWMS) directory appears
++with the following read/write properties inside to control the pwm:
++
++duty_ns - Write the number of nanoseconds the active portion of the pwm period
++should last to this file. This can not be longer than the period_ns.
++
++period_ns - Write the length of the pwm period in nanoseconds to this file.
++This includes the active and inactive portion of the pwm period and can not
++be smaller than duty_ns.
++
++polarity - The normal behaviour is to put out a high for the active portion of
++the pwm period. Write a 1 to this file to inverse the signal and output a low
++on the active portion. Write a 0 to switch back to the normal behaviour. The
++polarity can only be changed if the pwm is not running. This file is only
++visible if the underlying driver/device supports changing the polarity.
++
++run - Write a 1 to this file to start the pwm signal generation, write a 0 to
++stop it. Set your desired period_ns, duty_ns and polarity before starting the
++pwm.
++
++It is recommend to set the period_ns at first and duty_ns after that.
++
+ Implementing a PWM driver
+ -------------------------
+
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index 74f5084..6755f2b 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -28,6 +28,18 @@ menuconfig PWM
+
+ if PWM
+
++config PWM_SYSFS
++ bool "/sys/class/pwm/... (sysfs interface)"
++ depends on SYSFS
++ help
++ Say Y here to use a sysfs interface to control PWMs.
++
++ For every instance of an PWM capable device there is a pwmchipX
++ directory exported to /sys/class/pwm. If you want to use a PWM, you
++ have to export it to sysfs, which is done by writing the number into
++ /sys/class/pwm/export. After that /sys/class/pwm/pwmX is ready to be
++ used.
++
+ config PWM_AB8500
+ tristate "AB8500 PWM support"
+ depends on AB8500_CORE && ARCH_U8500
+diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
+index 0478442..7d13e67 100644
+--- a/drivers/pwm/core.c
++++ b/drivers/pwm/core.c
+@@ -30,8 +30,6 @@
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+
+-#define MAX_PWMS 1024
+-
+ /* flags in the third cell of the DT PWM specifier */
+ #define PWM_SPEC_POLARITY (1 << 0)
+
+@@ -42,6 +40,465 @@ static LIST_HEAD(pwm_chips);
+ static DECLARE_BITMAP(allocated_pwms, MAX_PWMS);
+ static RADIX_TREE(pwm_tree, GFP_KERNEL);
+
++
++#ifdef CONFIG_PWM_SYSFS
++
++/* lock protects against unexport_pwm() being called while
++ * sysfs files are active.
++ */
++static DEFINE_MUTEX(sysfs_lock);
++static struct class pwm_class;
++static struct pwm_device *pwm_table[MAX_PWMS];
++
++/*
++ * /sys/class/pwm/pwm... only for PWMs that are exported
++ * /polarity
++ * * only visible if the underlying driver has registered a
++ * set_polarity function
++ * * always readable
++ * * may be written as "1" for inverted polarity or "0" for
++ * normal polarity
++ * * can only be written if PWM is not running
++ * /period_ns
++ * * always readable
++ * * write with desired pwm period in nanoseconds
++ * * may return with error depending on duty_ns
++ * /duty_ns
++ * * always readable
++ * * write with desired duty portion in nanoseconds
++ * * may return with error depending on period_ns
++ * /run
++ * * always readable
++ * * write with "1" to start generating pwm signal, "0" to stop it
++ */
++static ssize_t pwm_polarity_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ const struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else
++ status = sprintf(buf, "%d\n", pwm->polarity);
++
++ mutex_unlock(&sysfs_lock);
++
++ return status;
++}
++
++static ssize_t pwm_polarity_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else {
++ long value;
++
++ status = kstrtol(buf, 0, &value);
++ if (status == 0) {
++ if (value == 0) {
++ if (pwm->polarity == PWM_POLARITY_NORMAL)
++ goto fail_unlock;
++ status = pwm_set_polarity(pwm,
++ PWM_POLARITY_NORMAL);
++ } else {
++ if (pwm->polarity == PWM_POLARITY_INVERSED)
++ goto fail_unlock;
++ status = pwm_set_polarity(pwm,
++ PWM_POLARITY_INVERSED);
++ }
++ }
++ }
++
++fail_unlock:
++ mutex_unlock(&sysfs_lock);
++ return status ? : size;
++}
++
++static const DEVICE_ATTR(polarity, 0644,
++ pwm_polarity_show, pwm_polarity_store);
++
++
++static ssize_t pwm_period_ns_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ const struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else
++ status = sprintf(buf, "%d\n", pwm->period);
++
++ mutex_unlock(&sysfs_lock);
++
++ return status;
++}
++
++static ssize_t pwm_period_ns_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else {
++ long value;
++
++ status = kstrtol(buf, 0, &value);
++ if (status == 0) {
++ if (pwm->duty < 0)
++ pwm->period = value;
++ else
++ status = pwm_config(pwm, pwm->duty, value);
++ }
++ }
++
++ mutex_unlock(&sysfs_lock);
++
++ return status ? : size;
++}
++
++static ssize_t pwm_duty_ns_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ const struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else
++ status = sprintf(buf, "%d\n", pwm->duty);
++
++ mutex_unlock(&sysfs_lock);
++
++ return status;
++}
++
++static ssize_t pwm_duty_ns_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else {
++ long value;
++
++ status = kstrtol(buf, 0, &value);
++ if (status == 0) {
++ if (pwm->period <= 0)
++ pwm->duty = value;
++ else
++ status = pwm_config(pwm, value, pwm->period);
++ }
++ }
++
++ mutex_unlock(&sysfs_lock);
++
++ return status ? : size;
++}
++
++static ssize_t pwm_run_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ const struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else
++ status = sprintf(buf, "%d\n",
++ !!test_bit(PWMF_ENABLED, &pwm->flags));
++
++ mutex_unlock(&sysfs_lock);
++
++ return status;
++}
++
++static ssize_t pwm_run_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct pwm_device *pwm = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_EXPORT, &pwm->flags))
++ status = -EIO;
++ else {
++ long value;
++
++ status = kstrtol(buf, 0, &value);
++ if (status == 0) {
++ if (value)
++ status = pwm_enable(pwm);
++ else
++ pwm_disable(pwm);
++ }
++ }
++
++ mutex_unlock(&sysfs_lock);
++
++ return status ? : size;
++}
++
++static struct device_attribute pwm_dev_attrs[] = {
++ __ATTR(period_ns, 0644, pwm_period_ns_show, pwm_period_ns_store),
++ __ATTR(duty_ns, 0644, pwm_duty_ns_show, pwm_duty_ns_store),
++ __ATTR(run, 0644, pwm_run_show, pwm_run_store),
++ __ATTR_NULL,
++};
++
++/*
++ * /sys/class/pwm/pwmchipN/
++ * /base ... matching pwm_chip.base (N)
++ * /ngpio ... matching pwm_chip.npwm
++ */
++
++static ssize_t chip_base_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ const struct pwm_chip *chip = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%d\n", chip->base);
++}
++
++static ssize_t chip_npwm_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ const struct pwm_chip *chip = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%u\n", chip->npwm);
++}
++
++static int pwm_export(struct pwm_device *pwm)
++{
++ struct device *dev;
++ int status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(PWMF_REQUESTED, &pwm->flags) ||
++ test_bit(PWMF_EXPORT, &pwm->flags)) {
++ pr_debug("pwm %d unavailable (requested=%d, exported=%d)\n",
++ pwm->pwm,
++ test_bit(PWMF_REQUESTED, &pwm->flags),
++ test_bit(PWMF_EXPORT, &pwm->flags));
++
++ status = -EPERM;
++ goto fail_unlock;
++ }
++
++ pwm_class.class_attrs = NULL;
++ pwm_class.dev_attrs = pwm_dev_attrs;
++ dev = device_create(&pwm_class, pwm->chip->dev, MKDEV(0, 0),
++ pwm, "pwm%u", pwm->pwm);
++ if (IS_ERR(dev)) {
++ status = PTR_ERR(dev);
++ goto fail_unlock;
++ }
++
++ if (pwm->chip->ops->set_polarity) {
++ status = device_create_file(dev, &dev_attr_polarity);
++ if (status)
++ goto fail_unregister_device;
++ }
++
++ set_bit(PWMF_EXPORT, &pwm->flags);
++ mutex_unlock(&sysfs_lock);
++ return 0;
++
++fail_unregister_device:
++ device_unregister(dev);
++fail_unlock:
++ mutex_unlock(&sysfs_lock);
++ return status;
++}
++
++static int match_export(struct device *dev, void *data)
++{
++ return dev_get_drvdata(dev) == data;
++}
++
++/*
++ * /sys/class/pwm/export ... write-only
++ * integer N ... number of pwm to export (full access)
++ * /sys/class/pwm/unexport ... write-only
++ * integer N ... number of pwm to unexport
++ */
++static ssize_t export_store(struct class *class,
++ struct class_attribute *attr,
++ const char *buf, size_t len)
++{
++ long pwm;
++ int status;
++ struct pwm_device *dev;
++ struct pwm_chip *chip;
++
++ status = kstrtol(buf, 0, &pwm);
++ if (status < 0)
++ goto done;
++
++ if (!pwm_is_valid(pwm) || !pwm_table[pwm]) {
++ status = -ENODEV;
++ goto done;
++ }
++ chip = pwm_table[pwm]->chip;
++ if (!chip) {
++ status = -ENODEV;
++ goto done;
++ }
++ dev = pwm_request_from_chip(chip, pwm - chip->base, "sysfs");
++ if (IS_ERR(dev)) {
++ status = -ENODEV;
++ goto done;
++ }
++ status = pwm_export(dev);
++ if (status < 0)
++ pwm_free(dev);
++done:
++ if (status)
++ pr_debug("%s: status %d\n", __func__, status);
++ return status ? : len;
++}
++
++static ssize_t unexport_store(struct class *class,
++ struct class_attribute *attr,
++ const char *buf, size_t len)
++{
++ long pwm;
++ int status;
++ struct pwm_device *dev;
++ struct device *d;
++
++ status = kstrtol(buf, 0, &pwm);
++ if (status < 0)
++ goto done;
++
++ status = -EINVAL;
++
++ /* reject bogus pwms */
++ if (!pwm_is_valid(pwm))
++ goto done;
++
++ dev = pwm_table[pwm];
++ if (dev && test_and_clear_bit(PWMF_EXPORT, &dev->flags)) {
++ d = class_find_device(&pwm_class, NULL, dev, match_export);
++ if (d)
++ device_unregister(d);
++ status = 0;
++ pwm_put(dev);
++ }
++done:
++ if (status)
++ pr_debug("%s: status %d\n", __func__, status);
++ return status ? : len;
++}
++
++static struct class_attribute pwmchip_class_attrs[] = {
++ __ATTR(export, 0200, NULL, export_store),
++ __ATTR(unexport, 0200, NULL, unexport_store),
++ __ATTR_NULL,
++};
++
++static struct device_attribute pwmchip_dev_attrs[] = {
++ __ATTR(base, 0444, chip_base_show, NULL),
++ __ATTR(npwm, 0444, chip_npwm_show, NULL),
++ __ATTR_NULL,
++};
++
++static struct class pwm_class = {
++ .name = "pwm",
++ .owner = THIS_MODULE,
++ .class_attrs = pwmchip_class_attrs,
++ .dev_attrs = pwmchip_dev_attrs,
++};
++
++static int pwmchip_export(struct pwm_chip *chip)
++{
++ struct device *dev;
++
++ mutex_lock(&sysfs_lock);
++ pwm_class.class_attrs = pwmchip_class_attrs;
++ pwm_class.dev_attrs = pwmchip_dev_attrs;
++ dev = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
++ "pwmchip%d", chip->base);
++
++ chip->exported = (!IS_ERR(dev));
++ mutex_unlock(&sysfs_lock);
++
++ if (chip->exported)
++ return 0;
++
++ return PTR_ERR(dev);
++}
++
++static void pwmchip_unexport(struct pwm_chip *chip)
++{
++ int status, i;
++ struct device *dev;
++
++ mutex_lock(&sysfs_lock);
++ dev = class_find_device(&pwm_class, NULL, chip, match_export);
++ if (dev) {
++ put_device(dev);
++ device_unregister(dev);
++ for (i = chip->base; i < chip->base + chip->npwm; i++)
++ pwm_table[i] = NULL;
++ chip->exported = 0;
++ status = 0;
++ } else
++ status = -ENODEV;
++ mutex_unlock(&sysfs_lock);
++
++ if (status)
++ pr_debug("%s: pwm chip status %d\n", __func__, status);
++}
++
++static int __init pwmlib_sysfs_init(void)
++{
++ int status;
++
++ status = class_register(&pwm_class);
++
++ return status;
++}
++postcore_initcall(pwmlib_sysfs_init);
++
++#else
++static inline int pwmchip_export(struct pwm_chip *chip)
++{
++ return 0;
++}
++
++static inline void pwmchip_unexport(struct pwm_chip *chip)
++{
++}
++
++#endif /* CONFIG_PWM_SYSFS */
++
++
+ static struct pwm_device *pwm_to_device(unsigned int pwm)
+ {
+ return radix_tree_lookup(&pwm_tree, pwm);
+@@ -77,8 +534,10 @@ static void free_pwms(struct pwm_chip *chip)
+ for (i = 0; i < chip->npwm; i++) {
+ struct pwm_device *pwm = &chip->pwms[i];
+ radix_tree_delete(&pwm_tree, pwm->pwm);
++#ifdef CONFIG_PWM_SYSFS
++ pwm_table[i + chip->base]->chip = NULL;
++#endif
+ }
+-
+ bitmap_clear(allocated_pwms, chip->base, chip->npwm);
+
+ kfree(chip->pwms);
+@@ -258,6 +717,9 @@ int pwmchip_add(struct pwm_chip *chip)
+ pwm->chip = chip;
+ pwm->pwm = chip->base + i;
+ pwm->hwpwm = i;
++#ifdef CONFIG_PWM_SYSFS
++ pwm_table[i + chip->base] = pwm;
++#endif
+
+ radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
+ }
+@@ -272,6 +734,8 @@ int pwmchip_add(struct pwm_chip *chip)
+ if (IS_ENABLED(CONFIG_OF))
+ of_pwmchip_add(chip);
+
++ ret = pwmchip_export(chip);
++
+ out:
+ mutex_unlock(&pwm_lock);
+ return ret;
+@@ -307,6 +771,7 @@ int pwmchip_remove(struct pwm_chip *chip)
+ of_pwmchip_remove(chip);
+
+ free_pwms(chip);
++ pwmchip_unexport(chip);
+
+ out:
+ mutex_unlock(&pwm_lock);
+@@ -400,10 +865,19 @@ EXPORT_SYMBOL_GPL(pwm_free);
+ */
+ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+ {
++ int status;
++
+ if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns)
+ return -EINVAL;
+
+- return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
++ status = pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
++#ifdef CONFIG_PWM_SYSFS
++ if (status == 0) {
++ pwm->period = period_ns;
++ pwm->duty = duty_ns;
++ }
++#endif
++ return status;
+ }
+ EXPORT_SYMBOL_GPL(pwm_config);
+
+@@ -416,6 +890,8 @@ EXPORT_SYMBOL_GPL(pwm_config);
+ */
+ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
+ {
++ int status;
++
+ if (!pwm || !pwm->chip->ops)
+ return -EINVAL;
+
+@@ -425,7 +901,12 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
+ if (test_bit(PWMF_ENABLED, &pwm->flags))
+ return -EBUSY;
+
+- return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
++ status = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
++#ifdef CONFIG_PWM_SYSFS
++ if (!status)
++ pwm->polarity = polarity;
++#endif
++ return status;
+ }
+ EXPORT_SYMBOL_GPL(pwm_set_polarity);
+
+@@ -753,6 +1234,9 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
+ if (test_bit(PWMF_ENABLED, &pwm->flags))
+ seq_printf(s, " enabled");
+
++ if (test_bit(PWMF_EXPORT, &pwm->flags))
++ seq_printf(s, " sysfs_exported");
++
+ seq_printf(s, "\n");
+ }
+ }
+diff --git a/include/linux/pwm.h b/include/linux/pwm.h
+index b21c020..9165922 100644
+--- a/include/linux/pwm.h
++++ b/include/linux/pwm.h
+@@ -4,10 +4,27 @@
+ #include <linux/err.h>
+ #include <linux/of.h>
+
++#define MAX_PWMS 1024
++
+ struct pwm_device;
+ struct seq_file;
+
+ #if IS_ENABLED(CONFIG_PWM) || IS_ENABLED(CONFIG_HAVE_PWM)
++
++/*
++ * "valid" PWM numbers are nonnegative and may be passed to
++ * setup routines like pwm_get(). only some valid numbers
++ * can successfully be requested and used.
++ *
++ * Invalid PWM numbers are useful for indicating no-such-PWM in
++ * platform data and other tables.
++ */
++
++static inline bool pwm_is_valid(int number)
++{
++ return number >= 0 && number < MAX_PWMS;
++}
++
+ /*
+ * pwm_request - request a PWM device
+ */
+@@ -75,7 +92,8 @@ enum pwm_polarity {
+
+ enum {
+ PWMF_REQUESTED = 1 << 0,
+- PWMF_ENABLED = 1 << 1,
++ PWMF_ENABLED = 1 << 1, /* set running via /sys/class/pwm/pwmX/run */
++ PWMF_EXPORT = 1 << 2, /* exported via /sys/class/pwm/export */
+ };
+
+ struct pwm_device {
+@@ -87,6 +105,10 @@ struct pwm_device {
+ void *chip_data;
+
+ unsigned int period; /* in nanoseconds */
++#ifdef CONFIG_PWM_SYSFS
++ unsigned int duty; /* in nanoseconds */
++ enum pwm_polarity polarity;
++#endif
+ };
+
+ static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period)
+@@ -159,6 +181,9 @@ struct pwm_chip {
+ struct pwm_device * (*of_xlate)(struct pwm_chip *pc,
+ const struct of_phandle_args *args);
+ unsigned int of_pwm_n_cells;
++#ifdef CONFIG_PWM_SYSFS
++ unsigned exported:1;
++#endif
+ };
+
+ #if IS_ENABLED(CONFIG_PWM)
diff --git a/patches/linux-3.8.13/0128-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch b/patches/linux-3.8.13/0128-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
new file mode 100644
index 0000000..29bb1c5
--- /dev/null
+++ b/patches/linux-3.8.13/0128-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
@@ -0,0 +1,37 @@
+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 c0d9c5b..0087b13 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -244,6 +244,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";
+@@ -254,6 +255,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";
+@@ -264,6 +266,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.8.13/0129-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch b/patches/linux-3.8.13/0129-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
new file mode 100644
index 0000000..d17a3f2
--- /dev/null
+++ b/patches/linux-3.8.13/0129-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
@@ -0,0 +1,30 @@
+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 | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index f74bd69..e30c1ee 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1878,6 +1878,16 @@ static int 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 = of_node_get(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.8.13/0130-ARM-OMAP2xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch b/patches/linux-3.8.13/0130-ARM-OMAP2xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch
new file mode 100644
index 0000000..22f0d01
--- /dev/null
+++ b/patches/linux-3.8.13/0130-ARM-OMAP2xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch
@@ -0,0 +1,211 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Mon, 1 Oct 2012 21:03:04 -0700
+Subject: [PATCH] ARM: OMAP2xxx: hwmod: Convert SHAM crypto device data to
+ hwmod
+
+Convert the device data for the OMAP2 SHAM crypto IP from
+explicit platform_data to hwmod.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/cclock2430_data.c | 1 +
+ arch/arm/mach-omap2/devices.c | 32 ++++++-----------
+ arch/arm/mach-omap2/omap_hwmod_2420_data.c | 1 +
+ arch/arm/mach-omap2/omap_hwmod_2430_data.c | 1 +
+ .../mach-omap2/omap_hwmod_2xxx_interconnect_data.c | 18 ++++++++++
+ arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 37 ++++++++++++++++++++
+ arch/arm/mach-omap2/omap_hwmod_common_data.h | 2 ++
+ 7 files changed, 71 insertions(+), 21 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
+index eb3dab6..ff8b83f 100644
+--- a/arch/arm/mach-omap2/cclock2430_data.c
++++ b/arch/arm/mach-omap2/cclock2430_data.c
+@@ -1992,6 +1992,7 @@ static struct omap_clk omap2430_clks[] = {
+ CLK(NULL, "sdrc_ick", &sdrc_ick, CK_243X),
+ CLK(NULL, "des_ick", &des_ick, CK_243X),
+ CLK("omap-sham", "ick", &sha_ick, CK_243X),
++ CLK(NULL, "sha_ick", &sha_ick, CK_243X),
+ CLK("omap_rng", "ick", &rng_ick, CK_243X),
+ CLK(NULL, "rng_ick", &rng_ick, CK_243X),
+ CLK("omap-aes", "ick", &aes_ick, CK_243X),
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index f5c71ac..fc93642 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -480,24 +480,6 @@ static void omap_init_rng(void)
+
+ #if defined(CONFIG_CRYPTO_DEV_OMAP_SHAM) || defined(CONFIG_CRYPTO_DEV_OMAP_SHAM_MODULE)
+
+-#ifdef CONFIG_ARCH_OMAP2
+-static struct resource omap2_sham_resources[] = {
+- {
+- .start = OMAP24XX_SEC_SHA1MD5_BASE,
+- .end = OMAP24XX_SEC_SHA1MD5_BASE + 0x64,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = 51 + OMAP_INTC_START,
+- .flags = IORESOURCE_IRQ,
+- }
+-};
+-static int omap2_sham_resources_sz = ARRAY_SIZE(omap2_sham_resources);
+-#else
+-#define omap2_sham_resources NULL
+-#define omap2_sham_resources_sz 0
+-#endif
+-
+ #ifdef CONFIG_ARCH_OMAP3
+ static struct resource omap3_sham_resources[] = {
+ {
+@@ -528,16 +510,24 @@ static struct platform_device sham_device = {
+ static void omap_init_sham(void)
+ {
+ if (cpu_is_omap24xx()) {
+- sham_device.resource = omap2_sham_resources;
+- sham_device.num_resources = omap2_sham_resources_sz;
++ struct omap_hwmod *oh;
++ struct platform_device *pdev;
++
++ oh = omap_hwmod_lookup("sham");
++ if (!oh)
++ return;
++
++ pdev = omap_device_build("omap-sham", -1, oh, NULL, 0, NULL,
++ 0, 0);
++ WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
+ } else if (cpu_is_omap34xx()) {
+ sham_device.resource = omap3_sham_resources;
+ sham_device.num_resources = omap3_sham_resources_sz;
++ platform_device_register(&sham_device);
+ } else {
+ pr_err("%s: platform not supported\n", __func__);
+ return;
+ }
+- platform_device_register(&sham_device);
+ }
+ #else
+ static inline void omap_init_sham(void) { }
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+index b5efe58..b718167 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+@@ -605,6 +605,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
+ &omap2420_l4_core__mcbsp2,
+ &omap2420_l4_core__msdi1,
+ &omap2xxx_l4_core__rng,
++ &omap2xxx_l4_core__sham,
+ &omap2420_l4_core__hdq1w,
+ &omap2420_l4_wkup__counter_32k,
+ &omap2420_l3__gpmc,
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+index d2d3840..3c19b08 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+@@ -963,6 +963,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
+ &omap2430_l4_core__mcbsp5,
+ &omap2430_l4_core__hdq1w,
+ &omap2xxx_l4_core__rng,
++ &omap2xxx_l4_core__sham,
+ &omap2430_l4_wkup__counter_32k,
+ &omap2430_l3__gpmc,
+ NULL,
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+index 47901a5..8a9b67a 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+@@ -138,6 +138,15 @@ static struct omap_hwmod_addr_space omap2_rng_addr_space[] = {
+ { }
+ };
+
++struct omap_hwmod_addr_space omap2xxx_sham_addrs[] = {
++ {
++ .pa_start = 0x480a4000,
++ .pa_end = 0x480a4000 + 0x64 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ { }
++};
++
+ /*
+ * Common interconnect data
+ */
+@@ -389,3 +398,12 @@ struct omap_hwmod_ocp_if omap2xxx_l4_core__rng = {
+ .addr = omap2_rng_addr_space,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ };
++
++/* l4 core -> sham interface */
++struct omap_hwmod_ocp_if omap2xxx_l4_core__sham = {
++ .master = &omap2xxx_l4_core_hwmod,
++ .slave = &omap2xxx_sham_hwmod,
++ .clk = "sha_ick",
++ .addr = omap2xxx_sham_addrs,
++ .user = OCP_USER_MPU,
++};
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+index e596117..e72132d 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+@@ -864,3 +864,40 @@ struct omap_hwmod omap2xxx_rng_hwmod = {
+ .flags = HWMOD_INIT_NO_RESET,
+ .class = &omap2_rng_hwmod_class,
+ };
++
++/* SHAM */
++
++static struct omap_hwmod_class_sysconfig omap2_sham_sysc = {
++ .rev_offs = 0x5c,
++ .sysc_offs = 0x60,
++ .syss_offs = 0x64,
++ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
++ SYSS_HAS_RESET_STATUS),
++ .sysc_fields = &omap_hwmod_sysc_type1,
++};
++
++static struct omap_hwmod_class omap2xxx_sham_class = {
++ .name = "sham",
++ .sysc = &omap2_sham_sysc,
++};
++
++struct omap_hwmod_irq_info omap2_sham_mpu_irqs[] = {
++ { .irq = 51 + OMAP_INTC_START, },
++ { .irq = -1 }
++};
++
++struct omap_hwmod omap2xxx_sham_hwmod = {
++ .name = "sham",
++ .mpu_irqs = omap2_sham_mpu_irqs,
++ .main_clk = "l4_ck",
++ .prcm = {
++ .omap2 = {
++ .module_offs = CORE_MOD,
++ .prcm_reg_id = 4,
++ .module_bit = OMAP24XX_EN_SHA_SHIFT,
++ .idlest_reg_id = 4,
++ .idlest_idle_bit = OMAP24XX_ST_SHA_SHIFT,
++ },
++ },
++ .class = &omap2xxx_sham_class,
++};
+diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
+index cfcce29..928acd5 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
++++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
+@@ -78,6 +78,7 @@ extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
+ extern struct omap_hwmod omap2xxx_counter_32k_hwmod;
+ extern struct omap_hwmod omap2xxx_gpmc_hwmod;
+ extern struct omap_hwmod omap2xxx_rng_hwmod;
++extern struct omap_hwmod omap2xxx_sham_hwmod;
+
+ /* Common interface data across OMAP2xxx */
+ extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
+@@ -105,6 +106,7 @@ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_dispc;
+ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi;
+ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc;
+ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__rng;
++extern struct omap_hwmod_ocp_if omap2xxx_l4_core__sham;
+
+ /* Common IP block data */
+ extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
diff --git a/patches/linux-3.8.13/0131-ARM-OMAP2xxx-hwmod-Add-DMA-support-for-SHAM-module.patch b/patches/linux-3.8.13/0131-ARM-OMAP2xxx-hwmod-Add-DMA-support-for-SHAM-module.patch
new file mode 100644
index 0000000..1298783
--- /dev/null
+++ b/patches/linux-3.8.13/0131-ARM-OMAP2xxx-hwmod-Add-DMA-support-for-SHAM-module.patch
@@ -0,0 +1,45 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Fri, 19 Oct 2012 14:10:34 -0700
+Subject: [PATCH] ARM: OMAP2xxx: hwmod: Add DMA support for SHAM module
+
+The current OMAP2 SHAM support doesn't enable DMA
+so add that support so it can use DMA just like OMAP3.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c | 2 +-
+ arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 6 ++++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+index 8a9b67a..510f584 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+@@ -405,5 +405,5 @@ struct omap_hwmod_ocp_if omap2xxx_l4_core__sham = {
+ .slave = &omap2xxx_sham_hwmod,
+ .clk = "sha_ick",
+ .addr = omap2xxx_sham_addrs,
+- .user = OCP_USER_MPU,
++ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ };
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+index e72132d..ab3305b 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+@@ -886,9 +886,15 @@ struct omap_hwmod_irq_info omap2_sham_mpu_irqs[] = {
+ { .irq = -1 }
+ };
+
++struct omap_hwmod_dma_info omap2_sham_sdma_chs[] = {
++ { .name = "rx", .dma_req = 13 },
++ { .dma_req = -1 }
++};
++
+ struct omap_hwmod omap2xxx_sham_hwmod = {
+ .name = "sham",
+ .mpu_irqs = omap2_sham_mpu_irqs,
++ .sdma_reqs = omap2_sham_sdma_chs,
+ .main_clk = "l4_ck",
+ .prcm = {
+ .omap2 = {
diff --git a/patches/linux-3.8.13/0132-ARM-OMAP3xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch b/patches/linux-3.8.13/0132-ARM-OMAP3xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch
new file mode 100644
index 0000000..4396efd
--- /dev/null
+++ b/patches/linux-3.8.13/0132-ARM-OMAP3xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch
@@ -0,0 +1,176 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Tue, 2 Oct 2012 19:54:00 -0700
+Subject: [PATCH] ARM: OMAP3xxx: hwmod: Convert SHAM crypto device data to
+ hwmod
+
+Convert the device data for the OMAP3 SHAM2 (SHA1/MD5) crypto IP
+from explicit platform_data to hwmod.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/cclock3xxx_data.c | 1 +
+ arch/arm/mach-omap2/devices.c | 41 +----------------
+ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 66 ++++++++++++++++++++++++++++
+ 3 files changed, 69 insertions(+), 39 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
+index 6ef8758..2853d72 100644
+--- a/arch/arm/mach-omap2/cclock3xxx_data.c
++++ b/arch/arm/mach-omap2/cclock3xxx_data.c
+@@ -3336,6 +3336,7 @@ static struct omap_clk omap3xxx_clks[] = {
+ CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
+ CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
+ CLK("omap-sham", "ick", &sha12_ick, CK_34XX | CK_36XX),
++ CLK(NULL, "sha12_ick", &sha12_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "des2_ick", &des2_ick, CK_34XX | CK_36XX),
+ CLK("omap_hsmmc.1", "ick", &mmchs2_ick, CK_3XXX),
+ CLK("omap_hsmmc.0", "ick", &mmchs1_ick, CK_3XXX),
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index fc93642..3d1693b 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -478,38 +478,9 @@ static void omap_init_rng(void)
+ WARN(IS_ERR(pdev), "Can't build omap_device for omap_rng\n");
+ }
+
+-#if defined(CONFIG_CRYPTO_DEV_OMAP_SHAM) || defined(CONFIG_CRYPTO_DEV_OMAP_SHAM_MODULE)
+-
+-#ifdef CONFIG_ARCH_OMAP3
+-static struct resource omap3_sham_resources[] = {
+- {
+- .start = OMAP34XX_SEC_SHA1MD5_BASE,
+- .end = OMAP34XX_SEC_SHA1MD5_BASE + 0x64,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = 49 + OMAP_INTC_START,
+- .flags = IORESOURCE_IRQ,
+- },
+- {
+- .start = OMAP34XX_DMA_SHA1MD5_RX,
+- .flags = IORESOURCE_DMA,
+- }
+-};
+-static int omap3_sham_resources_sz = ARRAY_SIZE(omap3_sham_resources);
+-#else
+-#define omap3_sham_resources NULL
+-#define omap3_sham_resources_sz 0
+-#endif
+-
+-static struct platform_device sham_device = {
+- .name = "omap-sham",
+- .id = -1,
+-};
+-
+-static void omap_init_sham(void)
++static void __init omap_init_sham(void)
+ {
+- if (cpu_is_omap24xx()) {
++ if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+ struct omap_hwmod *oh;
+ struct platform_device *pdev;
+
+@@ -520,18 +491,10 @@ static void omap_init_sham(void)
+ pdev = omap_device_build("omap-sham", -1, oh, NULL, 0, NULL,
+ 0, 0);
+ WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
+- } else if (cpu_is_omap34xx()) {
+- sham_device.resource = omap3_sham_resources;
+- sham_device.num_resources = omap3_sham_resources_sz;
+- platform_device_register(&sham_device);
+ } else {
+ pr_err("%s: platform not supported\n", __func__);
+- return;
+ }
+ }
+-#else
+-static inline void omap_init_sham(void) { }
+-#endif
+
+ #if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+index 8bb2628..122b4dc6 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+@@ -3540,6 +3540,71 @@ static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = {
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ };
+
++/* l4_core -> SHAM2 (SHA1/MD5) (similar to omap24xx) */
++static struct omap_hwmod_sysc_fields omap3_sham_sysc_fields = {
++ .sidle_shift = 4,
++ .srst_shift = 1,
++ .autoidle_shift = 0,
++};
++
++static struct omap_hwmod_class_sysconfig omap3_sham_sysc = {
++ .rev_offs = 0x5c,
++ .sysc_offs = 0x60,
++ .syss_offs = 0x64,
++ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
++ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
++ .sysc_fields = &omap3_sham_sysc_fields,
++};
++
++static struct omap_hwmod_class omap3xxx_sham_class = {
++ .name = "sham",
++ .sysc = &omap3_sham_sysc,
++};
++
++struct omap_hwmod_irq_info omap3_sham_mpu_irqs[] = {
++ { .irq = 49 + OMAP_INTC_START, },
++ { .irq = -1 }
++};
++
++struct omap_hwmod_dma_info omap3_sham_sdma_reqs[] = {
++ { .name = "rx", .dma_req = OMAP34XX_DMA_SHA1MD5_RX, },
++ { .dma_req = -1 }
++};
++
++struct omap_hwmod omap3xxx_sham_hwmod = {
++ .name = "sham",
++ .mpu_irqs = omap3_sham_mpu_irqs,
++ .sdma_reqs = omap3_sham_sdma_reqs,
++ .main_clk = "sha12_ick",
++ .prcm = {
++ .omap2 = {
++ .module_offs = CORE_MOD,
++ .prcm_reg_id = 1,
++ .module_bit = OMAP3430_EN_SHA12_SHIFT,
++ .idlest_reg_id = 1,
++ .idlest_idle_bit = OMAP3430_ST_SHA12_SHIFT,
++ },
++ },
++ .class = &omap3xxx_sham_class,
++};
++
++static struct omap_hwmod_addr_space omap3xxx_sham_addrs[] = {
++ {
++ .pa_start = 0x480c3000,
++ .pa_end = 0x480c3000 + 0x64 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if omap3xxx_l4_core__sham = {
++ .master = &omap3xxx_l4_core_hwmod,
++ .slave = &omap3xxx_sham_hwmod,
++ .clk = "sha12_ick",
++ .addr = omap3xxx_sham_addrs,
++ .user = OCP_USER_MPU | OCP_USER_SDMA,
++};
++
+ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l3_main__l4_core,
+ &omap3xxx_l3_main__l4_per,
+@@ -3593,6 +3658,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
+ /* GP-only hwmod links */
+ static struct omap_hwmod_ocp_if *omap3xxx_gp_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l4_sec__timer12,
++ &omap3xxx_l4_core__sham,
+ NULL
+ };
+
diff --git a/patches/linux-3.8.13/0133-ARM-OMAP2-Remove-unnecessary-message-when-no-SHA-IP-.patch b/patches/linux-3.8.13/0133-ARM-OMAP2-Remove-unnecessary-message-when-no-SHA-IP-.patch
new file mode 100644
index 0000000..1fac8e7
--- /dev/null
+++ b/patches/linux-3.8.13/0133-ARM-OMAP2-Remove-unnecessary-message-when-no-SHA-IP-.patch
@@ -0,0 +1,46 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Fri, 19 Oct 2012 08:45:26 -0700
+Subject: [PATCH] ARM: OMAP2+: Remove unnecessary message when no SHA IP is
+ present
+
+Remove the error message that prints when there is no SHA IP
+present to make it consistent with all the other IPs.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/devices.c | 19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index 3d1693b..8e89bad 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -480,20 +480,15 @@ static void omap_init_rng(void)
+
+ static void __init omap_init_sham(void)
+ {
+- if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+- struct omap_hwmod *oh;
+- struct platform_device *pdev;
++ struct omap_hwmod *oh;
++ struct platform_device *pdev;
+
+- oh = omap_hwmod_lookup("sham");
+- if (!oh)
+- return;
++ oh = omap_hwmod_lookup("sham");
++ if (!oh)
++ return;
+
+- pdev = omap_device_build("omap-sham", -1, oh, NULL, 0, NULL,
+- 0, 0);
+- WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
+- } else {
+- pr_err("%s: platform not supported\n", __func__);
+- }
++ pdev = omap_device_build("omap-sham", -1, oh, NULL, 0, NULL, 0, 0);
++ WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
+ }
+
+ #if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
diff --git a/patches/linux-3.8.13/0134-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch b/patches/linux-3.8.13/0134-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch
new file mode 100644
index 0000000..11e178e
--- /dev/null
+++ b/patches/linux-3.8.13/0134-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch
@@ -0,0 +1,29 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Mon, 17 Dec 2012 16:01:15 -0700
+Subject: [PATCH] ARM: OMAP2+: Only manually add hwmod data when DT not used.
+
+The omap_init_sham() routine in devices.c only needs to be
+called when there is no device tree present.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/devices.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index 8e89bad..62300ec 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -686,10 +686,10 @@ static int __init omap2_init_devices(void)
+ omap_init_dmic();
+ omap_init_mcpdm();
+ omap_init_mcspi();
++ omap_init_sham();
+ }
+ omap_init_sti();
+ omap_init_rng();
+- omap_init_sham();
+ omap_init_aes();
+ omap_init_vout();
+ omap_init_ocp2scp();
diff --git a/patches/linux-3.8.13/0135-ARM-AM33XX-Add-sha0-crypto-clock-data.patch b/patches/linux-3.8.13/0135-ARM-AM33XX-Add-sha0-crypto-clock-data.patch
new file mode 100644
index 0000000..1b1ed2d
--- /dev/null
+++ b/patches/linux-3.8.13/0135-ARM-AM33XX-Add-sha0-crypto-clock-data.patch
@@ -0,0 +1,36 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Mon, 17 Dec 2012 15:57:48 -0700
+Subject: [PATCH] ARM: AM33XX: Add sha0 crypto clock data
+
+Add clock data for for the SHA0 crypto module
+on the am33xx SoC.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/cclock33xx_data.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
+index 2e2d579..e69155d 100644
+--- a/arch/arm/mach-omap2/cclock33xx_data.c
++++ b/arch/arm/mach-omap2/cclock33xx_data.c
+@@ -413,6 +413,10 @@ static struct clk smartreflex1_fck;
+ DEFINE_STRUCT_CLK_HW_OMAP(smartreflex1_fck, NULL);
+ DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null);
+
++static struct clk sha0_fck;
++DEFINE_STRUCT_CLK_HW_OMAP(sha0_fck, NULL);
++DEFINE_STRUCT_CLK(sha0_fck, dpll_core_ck_parents, clk_ops_null);
++
+ /*
+ * Modules clock nodes
+ *
+@@ -905,6 +909,7 @@ static struct omap_clk am33xx_clks[] = {
+ CLK(NULL, "mmu_fck", &mmu_fck, CK_AM33XX),
+ CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX),
+ CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX),
++ CLK(NULL, "sha0_fck", &sha0_fck, CK_AM33XX),
+ CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX),
+ CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX),
+ CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX),
diff --git a/patches/linux-3.8.13/0136-ARM-AM33XX-hwmod-Update-and-uncomment-SHA0-module-da.patch b/patches/linux-3.8.13/0136-ARM-AM33XX-hwmod-Update-and-uncomment-SHA0-module-da.patch
new file mode 100644
index 0000000..2e5a0da
--- /dev/null
+++ b/patches/linux-3.8.13/0136-ARM-AM33XX-hwmod-Update-and-uncomment-SHA0-module-da.patch
@@ -0,0 +1,109 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Mon, 17 Dec 2012 15:55:45 -0700
+Subject: [PATCH] ARM: AM33XX: hwmod: Update and uncomment SHA0 module data
+
+Update the SHA0 HIB2 module's hwmod data for the am33xx SoC.
+Also, remove it from the '#if 0' block that its currently
+inside so the data is actually available for use.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 43 ++++++++++++++++++++++++----
+ 1 file changed, 37 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 e54e7a1..87c7dee 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -417,7 +417,6 @@ static struct omap_hwmod am33xx_adc_tsc_hwmod = {
+ * - ocmc ram
+ * - ocp watch point
+ * - aes0
+- * - sha0
+ */
+ #if 0
+ /*
+@@ -543,22 +542,37 @@ static struct omap_hwmod am33xx_aes0_hwmod = {
+ },
+ },
+ };
++#endif
++
++/* sha0 HIB2 (the 'P' (public) device) */
++static struct omap_hwmod_class_sysconfig am33xx_sha0_sysc = {
++ .rev_offs = 0x100,
++ .sysc_offs = 0x110,
++ .syss_offs = 0x114,
++ .sysc_flags = SYSS_HAS_RESET_STATUS,
++};
+
+-/* sha0 */
+ static struct omap_hwmod_class am33xx_sha0_hwmod_class = {
+ .name = "sha0",
++ .sysc = &am33xx_sha0_sysc,
+ };
+
+ static struct omap_hwmod_irq_info am33xx_sha0_irqs[] = {
+- { .irq = 108 + OMAP_INTC_START, },
++ { .irq = 109 + OMAP_INTC_START, },
+ { .irq = -1 },
+ };
+
++struct omap_hwmod_dma_info am33xx_sha0_edma_reqs[] = {
++ { .name = "rx", .dma_req = 36, },
++ { .dma_req = -1 }
++};
++
+ static struct omap_hwmod am33xx_sha0_hwmod = {
+- .name = "sha0",
++ .name = "sham",
+ .class = &am33xx_sha0_hwmod_class,
+ .clkdm_name = "l3_clkdm",
+ .mpu_irqs = am33xx_sha0_irqs,
++ .sdma_reqs = am33xx_sha0_edma_reqs,
+ .main_clk = "l3_gclk",
+ .prcm = {
+ .omap4 = {
+@@ -568,8 +582,6 @@ static struct omap_hwmod am33xx_sha0_hwmod = {
+ },
+ };
+
+-#endif
+-
+ /* 'smartreflex' class */
+ static struct omap_hwmod_class am33xx_smartreflex_hwmod_class = {
+ .name = "smartreflex",
+@@ -3426,6 +3438,24 @@ static struct omap_hwmod_ocp_if am33xx_l3_s__usbss = {
+ .flags = OCPIF_SWSUP_IDLE,
+ };
+
++/* l3 main -> sha0 HIB2 */
++static struct omap_hwmod_addr_space am33xx_sha0_addrs[] = {
++ {
++ .pa_start = 0x53100000,
++ .pa_end = 0x53100000 + SZ_512 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_l3_main__sha0 = {
++ .master = &am33xx_l3_main_hwmod,
++ .slave = &am33xx_sha0_hwmod,
++ .clk = "sha0_fck",
++ .addr = am33xx_sha0_addrs,
++ .user = OCP_USER_MPU | OCP_USER_SDMA,
++};
++
+ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l4_fw__emif_fw,
+ &am33xx_l3_main__emif,
+@@ -3505,6 +3535,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l3_s__usbss,
+ &am33xx_l4_hs__cpgmac0,
+ &am33xx_cpgmac0__mdio,
++ &am33xx_l3_main__sha0,
+ NULL,
+ };
+
diff --git a/patches/linux-3.8.13/0137-ARM-dts-Add-SHAM-data-and-documentation-for-AM33XX.patch b/patches/linux-3.8.13/0137-ARM-dts-Add-SHAM-data-and-documentation-for-AM33XX.patch
new file mode 100644
index 0000000..b56faae
--- /dev/null
+++ b/patches/linux-3.8.13/0137-ARM-dts-Add-SHAM-data-and-documentation-for-AM33XX.patch
@@ -0,0 +1,119 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Mon, 17 Dec 2012 16:16:27 -0700
+Subject: [PATCH] ARM: dts: Add SHAM data and documentation for AM33XX
+
+Add the generic AM33XX SHAM module's device tree data and
+enable it for the am335x-evm, am335x-evmsk, and am335x-bone
+platforms. Also add Documentation file describing the data
+for the SHAM module.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ .../devicetree/bindings/crypto/omap-sham.txt | 35 ++++++++++++++++++++
+ arch/arm/boot/dts/am335x-bone.dts | 4 +++
+ arch/arm/boot/dts/am335x-evm.dts | 4 +++
+ arch/arm/boot/dts/am335x-evmsk.dts | 4 +++
+ arch/arm/boot/dts/am33xx.dtsi | 12 +++++++
+ 5 files changed, 59 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/crypto/omap-sham.txt
+
+diff --git a/Documentation/devicetree/bindings/crypto/omap-sham.txt b/Documentation/devicetree/bindings/crypto/omap-sham.txt
+new file mode 100644
+index 0000000..53839cc
+--- /dev/null
++++ b/Documentation/devicetree/bindings/crypto/omap-sham.txt
+@@ -0,0 +1,35 @@
++OMAP SoC SHA crypto Module
++
++Required properties:
++
++- compatible : Should contain entries for this and backward compatible
++ SHAM versions:
++ - "ti,omap2-sham" for OMAP2 & OMAP3.
++ - "ti,omap4-sham" for OMAP4 and AM33XX.
++ Note that these two versions are incompatible.
++- ti,hwmods: Name of the hwmod associated with the SHAM module
++- reg : Offset and length of the register set for the module
++- interrupt-parent : the phandle for the interrupt controller that
++ services interrupts for this module.
++- interrupts : the interrupt number for the SHAM module.
++
++Optional properties:
++- dmas: DMA controller phandle and DMA request ordered pair.
++ Only one rx pair is valid per SHAM module.
++- dma-names: DMA request name. This string corresponds 1:1 with
++ the ordered pair in dmas. The string naming is to be
++ "rx" for RX request.
++
++Example:
++ /* AM335x */
++ sham: sham@53100000 {
++ compatible = "ti,omap4-sham";
++ ti,hwmods = "sham";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x53100000 0x200>;
++ interrupt-parent = <&intc>;
++ interrupts = <109>;
++ dmas = <&edma 36>;
++ dma-names = "rx";
++ };
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 874997b..5254b64 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -281,3 +281,7 @@
+ &edma {
+ ti,edma-xbar-event-map = <32 12>;
+ };
++
++&sham {
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 65ae57f..5d33c20 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -358,3 +358,7 @@
+ };
+ };
+ };
++
++&sham {
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
+index 7a87803..a7e1659 100644
+--- a/arch/arm/boot/dts/am335x-evmsk.dts
++++ b/arch/arm/boot/dts/am335x-evmsk.dts
+@@ -331,3 +331,7 @@
+ };
+ };
+ };
++
++&sham {
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 0087b13..fa94f6e 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -550,5 +550,17 @@
+ //status = "disabled";
+ };
+ };
++
++ sham: sham@53100000 {
++ compatible = "ti,omap4-sham";
++ ti,hwmods = "sham";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x53100000 0x200>;
++ interrupt-parent = <&intc>;
++ interrupts = <109>;
++ dmas = <&edma 36>;
++ dma-names = "rx";
++ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0138-ARM-OMAP2xxx-hwmod-Convert-AES-crypto-devcie-data-to.patch b/patches/linux-3.8.13/0138-ARM-OMAP2xxx-hwmod-Convert-AES-crypto-devcie-data-to.patch
new file mode 100644
index 0000000..b6b70b1
--- /dev/null
+++ b/patches/linux-3.8.13/0138-ARM-OMAP2xxx-hwmod-Convert-AES-crypto-devcie-data-to.patch
@@ -0,0 +1,218 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 7 Nov 2012 12:16:49 -0700
+Subject: [PATCH] ARM: OMAP2xxx: hwmod: Convert AES crypto devcie data to
+ hwmod
+
+Convert the device data for the OMAP2 AES crypto IP from
+explicit platform_data to hwmod.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/cclock2430_data.c | 3 +-
+ arch/arm/mach-omap2/devices.c | 36 ++++++-------------
+ arch/arm/mach-omap2/omap_hwmod_2420_data.c | 1 +
+ arch/arm/mach-omap2/omap_hwmod_2430_data.c | 1 +
+ .../mach-omap2/omap_hwmod_2xxx_interconnect_data.c | 18 ++++++++++
+ arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 38 ++++++++++++++++++++
+ arch/arm/mach-omap2/omap_hwmod_common_data.h | 2 ++
+ 7 files changed, 73 insertions(+), 26 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
+index ff8b83f..89f6ed8 100644
+--- a/arch/arm/mach-omap2/cclock2430_data.c
++++ b/arch/arm/mach-omap2/cclock2430_data.c
+@@ -1995,7 +1995,8 @@ static struct omap_clk omap2430_clks[] = {
+ CLK(NULL, "sha_ick", &sha_ick, CK_243X),
+ CLK("omap_rng", "ick", &rng_ick, CK_243X),
+ CLK(NULL, "rng_ick", &rng_ick, CK_243X),
+- CLK("omap-aes", "ick", &aes_ick, CK_243X),
++ CLK("omap-aes", "ick", &aes_ick, CK_243X),
++ CLK(NULL, "aes_ick", &aes_ick, CK_243X),
+ CLK(NULL, "pka_ick", &pka_ick, CK_243X),
+ CLK(NULL, "usb_fck", &usb_fck, CK_243X),
+ CLK("musb-omap2430", "ick", &usbhs_ick, CK_243X),
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index 62300ec..fe5e6a2 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -493,28 +493,6 @@ static void __init omap_init_sham(void)
+
+ #if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
+
+-#ifdef CONFIG_ARCH_OMAP2
+-static struct resource omap2_aes_resources[] = {
+- {
+- .start = OMAP24XX_SEC_AES_BASE,
+- .end = OMAP24XX_SEC_AES_BASE + 0x4C,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = OMAP24XX_DMA_AES_TX,
+- .flags = IORESOURCE_DMA,
+- },
+- {
+- .start = OMAP24XX_DMA_AES_RX,
+- .flags = IORESOURCE_DMA,
+- }
+-};
+-static int omap2_aes_resources_sz = ARRAY_SIZE(omap2_aes_resources);
+-#else
+-#define omap2_aes_resources NULL
+-#define omap2_aes_resources_sz 0
+-#endif
+-
+ #ifdef CONFIG_ARCH_OMAP3
+ static struct resource omap3_aes_resources[] = {
+ {
+@@ -545,16 +523,24 @@ static struct platform_device aes_device = {
+ static void omap_init_aes(void)
+ {
+ if (cpu_is_omap24xx()) {
+- aes_device.resource = omap2_aes_resources;
+- aes_device.num_resources = omap2_aes_resources_sz;
++ struct omap_hwmod *oh;
++ struct platform_device *pdev;
++
++ oh = omap_hwmod_lookup("aes");
++ if (!oh)
++ return;
++
++ pdev = omap_device_build("omap-aes", -1, oh, NULL, 0, NULL,
++ 0, 0);
++ WARN(IS_ERR(pdev), "Can't build omap_device for omap-aes\n");
+ } else if (cpu_is_omap34xx()) {
+ aes_device.resource = omap3_aes_resources;
+ aes_device.num_resources = omap3_aes_resources_sz;
++ platform_device_register(&aes_device);
+ } else {
+ pr_err("%s: platform not supported\n", __func__);
+ return;
+ }
+- platform_device_register(&aes_device);
+ }
+
+ #else
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+index b718167..2a73d4b 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+@@ -606,6 +606,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
+ &omap2420_l4_core__msdi1,
+ &omap2xxx_l4_core__rng,
+ &omap2xxx_l4_core__sham,
++ &omap2xxx_l4_core__aes,
+ &omap2420_l4_core__hdq1w,
+ &omap2420_l4_wkup__counter_32k,
+ &omap2420_l3__gpmc,
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+index 3c19b08..4ce999e 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+@@ -964,6 +964,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
+ &omap2430_l4_core__hdq1w,
+ &omap2xxx_l4_core__rng,
+ &omap2xxx_l4_core__sham,
++ &omap2xxx_l4_core__aes,
+ &omap2430_l4_wkup__counter_32k,
+ &omap2430_l3__gpmc,
+ NULL,
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+index 510f584..8d4d53d5 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+@@ -147,6 +147,15 @@ struct omap_hwmod_addr_space omap2xxx_sham_addrs[] = {
+ { }
+ };
+
++struct omap_hwmod_addr_space omap2xxx_aes_addrs[] = {
++ {
++ .pa_start = 0x480a6000,
++ .pa_end = 0x480a6000 + 0x50 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ { }
++};
++
+ /*
+ * Common interconnect data
+ */
+@@ -407,3 +416,12 @@ struct omap_hwmod_ocp_if omap2xxx_l4_core__sham = {
+ .addr = omap2xxx_sham_addrs,
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ };
++
++/* l4 core -> aes interface */
++struct omap_hwmod_ocp_if omap2xxx_l4_core__aes = {
++ .master = &omap2xxx_l4_core_hwmod,
++ .slave = &omap2xxx_aes_hwmod,
++ .clk = "aes_ick",
++ .addr = omap2xxx_aes_addrs,
++ .user = OCP_USER_MPU | OCP_USER_SDMA,
++};
+diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+index ab3305b..da5b790 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+@@ -907,3 +907,41 @@ struct omap_hwmod omap2xxx_sham_hwmod = {
+ },
+ .class = &omap2xxx_sham_class,
+ };
++
++/* AES */
++
++static struct omap_hwmod_class_sysconfig omap2_aes_sysc = {
++ .rev_offs = 0x44,
++ .sysc_offs = 0x48,
++ .syss_offs = 0x4c,
++ .sysc_flags = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
++ SYSS_HAS_RESET_STATUS),
++ .sysc_fields = &omap_hwmod_sysc_type1,
++};
++
++static struct omap_hwmod_class omap2xxx_aes_class = {
++ .name = "aes",
++ .sysc = &omap2_aes_sysc,
++};
++
++struct omap_hwmod_dma_info omap2_aes_sdma_chs[] = {
++ { .name = "tx", .dma_req = 9 },
++ { .name = "rx", .dma_req = 10 },
++ { .dma_req = -1 }
++};
++
++struct omap_hwmod omap2xxx_aes_hwmod = {
++ .name = "aes",
++ .sdma_reqs = omap2_aes_sdma_chs,
++ .main_clk = "l4_ck",
++ .prcm = {
++ .omap2 = {
++ .module_offs = CORE_MOD,
++ .prcm_reg_id = 4,
++ .module_bit = OMAP24XX_EN_AES_SHIFT,
++ .idlest_reg_id = 4,
++ .idlest_idle_bit = OMAP24XX_ST_AES_SHIFT,
++ },
++ },
++ .class = &omap2xxx_aes_class,
++};
+diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
+index 928acd5..6e04ff7 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
++++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
+@@ -79,6 +79,7 @@ extern struct omap_hwmod omap2xxx_counter_32k_hwmod;
+ extern struct omap_hwmod omap2xxx_gpmc_hwmod;
+ extern struct omap_hwmod omap2xxx_rng_hwmod;
+ extern struct omap_hwmod omap2xxx_sham_hwmod;
++extern struct omap_hwmod omap2xxx_aes_hwmod;
+
+ /* Common interface data across OMAP2xxx */
+ extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
+@@ -107,6 +108,7 @@ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi;
+ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc;
+ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__rng;
+ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__sham;
++extern struct omap_hwmod_ocp_if omap2xxx_l4_core__aes;
+
+ /* Common IP block data */
+ extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
diff --git a/patches/linux-3.8.13/0139-ARM-OMAP3xxx-hwmod-Convert-AES-crypto-device-data-to.patch b/patches/linux-3.8.13/0139-ARM-OMAP3xxx-hwmod-Convert-AES-crypto-device-data-to.patch
new file mode 100644
index 0000000..6373016
--- /dev/null
+++ b/patches/linux-3.8.13/0139-ARM-OMAP3xxx-hwmod-Convert-AES-crypto-device-data-to.patch
@@ -0,0 +1,176 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Sun, 11 Nov 2012 19:08:24 -0700
+Subject: [PATCH] ARM: OMAP3xxx: hwmod: Convert AES crypto device data to
+ hwmod
+
+Convert the device data for the OMAP3 AES crypto IP
+from explicit platform_data to hwmod.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/cclock3xxx_data.c | 3 +-
+ arch/arm/mach-omap2/devices.c | 42 +------------------
+ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 62 ++++++++++++++++++++++++++++
+ 3 files changed, 66 insertions(+), 41 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
+index 2853d72..6cbd801 100644
+--- a/arch/arm/mach-omap2/cclock3xxx_data.c
++++ b/arch/arm/mach-omap2/cclock3xxx_data.c
+@@ -3334,7 +3334,8 @@ static struct omap_clk omap3xxx_clks[] = {
+ CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "mmchs3_ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+ CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
+- CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
++ CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
++ CLK(NULL, "aes2_ick", &aes2_ick, CK_34XX | CK_36XX),
+ CLK("omap-sham", "ick", &sha12_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "sha12_ick", &sha12_ick, CK_34XX | CK_36XX),
+ CLK(NULL, "des2_ick", &des2_ick, CK_34XX | CK_36XX),
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index fe5e6a2..91e5a21 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -491,38 +491,9 @@ static void __init omap_init_sham(void)
+ WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
+ }
+
+-#if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
+-
+-#ifdef CONFIG_ARCH_OMAP3
+-static struct resource omap3_aes_resources[] = {
+- {
+- .start = OMAP34XX_SEC_AES_BASE,
+- .end = OMAP34XX_SEC_AES_BASE + 0x4C,
+- .flags = IORESOURCE_MEM,
+- },
+- {
+- .start = OMAP34XX_DMA_AES2_TX,
+- .flags = IORESOURCE_DMA,
+- },
+- {
+- .start = OMAP34XX_DMA_AES2_RX,
+- .flags = IORESOURCE_DMA,
+- }
+-};
+-static int omap3_aes_resources_sz = ARRAY_SIZE(omap3_aes_resources);
+-#else
+-#define omap3_aes_resources NULL
+-#define omap3_aes_resources_sz 0
+-#endif
+-
+-static struct platform_device aes_device = {
+- .name = "omap-aes",
+- .id = -1,
+-};
+-
+-static void omap_init_aes(void)
++static void __init omap_init_aes(void)
+ {
+- if (cpu_is_omap24xx()) {
++ if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+ struct omap_hwmod *oh;
+ struct platform_device *pdev;
+
+@@ -533,20 +504,11 @@ static void omap_init_aes(void)
+ pdev = omap_device_build("omap-aes", -1, oh, NULL, 0, NULL,
+ 0, 0);
+ WARN(IS_ERR(pdev), "Can't build omap_device for omap-aes\n");
+- } else if (cpu_is_omap34xx()) {
+- aes_device.resource = omap3_aes_resources;
+- aes_device.num_resources = omap3_aes_resources_sz;
+- platform_device_register(&aes_device);
+ } else {
+ pr_err("%s: platform not supported\n", __func__);
+- return;
+ }
+ }
+
+-#else
+-static inline void omap_init_aes(void) { }
+-#endif
+-
+ /*-------------------------------------------------------------------------*/
+
+ #if defined(CONFIG_VIDEO_OMAP2_VOUT) || \
+diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+index 122b4dc6..85d1b08 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+@@ -3605,6 +3605,67 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__sham = {
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ };
+
++/* l4_core -> AES */
++static struct omap_hwmod_sysc_fields omap3xxx_aes_sysc_fields = {
++ .sidle_shift = 6,
++ .srst_shift = 1,
++ .autoidle_shift = 0,
++};
++
++static struct omap_hwmod_class_sysconfig omap3_aes_sysc = {
++ .rev_offs = 0x44,
++ .sysc_offs = 0x48,
++ .syss_offs = 0x4c,
++ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
++ SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
++ .sysc_fields = &omap3xxx_aes_sysc_fields,
++};
++
++static struct omap_hwmod_class omap3xxx_aes_class = {
++ .name = "aes",
++ .sysc = &omap3_aes_sysc,
++};
++
++struct omap_hwmod_dma_info omap3_aes_sdma_reqs[] = {
++ { .name = "tx", .dma_req = OMAP34XX_DMA_AES2_TX, },
++ { .name = "rx", .dma_req = OMAP34XX_DMA_AES2_RX, },
++ { .dma_req = -1 }
++};
++
++struct omap_hwmod omap3xxx_aes_hwmod = {
++ .name = "aes",
++ .sdma_reqs = omap3_aes_sdma_reqs,
++ .main_clk = "aes2_ick",
++ .prcm = {
++ .omap2 = {
++ .module_offs = CORE_MOD,
++ .prcm_reg_id = 1,
++ .module_bit = OMAP3430_EN_AES2_SHIFT,
++ .idlest_reg_id = 1,
++ .idlest_idle_bit = OMAP3430_ST_AES2_SHIFT,
++ },
++ },
++ .class = &omap3xxx_aes_class,
++};
++
++static struct omap_hwmod_addr_space omap3xxx_aes_addrs[] = {
++ {
++ .pa_start = 0x480c5000,
++ .pa_end = 0x480c5000 + 0x50 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if omap3xxx_l4_core__aes = {
++ .master = &omap3xxx_l4_core_hwmod,
++ .slave = &omap3xxx_aes_hwmod,
++ .clk = "aes2_ick",
++ .addr = omap3xxx_aes_addrs,
++ .user = OCP_USER_MPU | OCP_USER_SDMA,
++};
++
+ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l3_main__l4_core,
+ &omap3xxx_l3_main__l4_per,
+@@ -3659,6 +3720,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
+ static struct omap_hwmod_ocp_if *omap3xxx_gp_hwmod_ocp_ifs[] __initdata = {
+ &omap3xxx_l4_sec__timer12,
+ &omap3xxx_l4_core__sham,
++ &omap3xxx_l4_core__aes,
+ NULL
+ };
+
diff --git a/patches/linux-3.8.13/0140-ARM-OMAP2-Remove-unnecessary-message-when-no-AES-IP-.patch b/patches/linux-3.8.13/0140-ARM-OMAP2-Remove-unnecessary-message-when-no-AES-IP-.patch
new file mode 100644
index 0000000..45e47cc
--- /dev/null
+++ b/patches/linux-3.8.13/0140-ARM-OMAP2-Remove-unnecessary-message-when-no-AES-IP-.patch
@@ -0,0 +1,48 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Sun, 11 Nov 2012 19:56:28 -0700
+Subject: [PATCH] ARM: OMAP2+: Remove unnecessary message when no AES IP is
+ present
+
+Remove the error message that prints when there is no AES IP
+present to make it consistent with all the other IPs.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/devices.c | 23 +++++++++--------------
+ 1 file changed, 9 insertions(+), 14 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index 91e5a21..5f873c2 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -493,20 +493,15 @@ static void __init omap_init_sham(void)
+
+ static void __init omap_init_aes(void)
+ {
+- if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+- struct omap_hwmod *oh;
+- struct platform_device *pdev;
+-
+- oh = omap_hwmod_lookup("aes");
+- if (!oh)
+- return;
+-
+- pdev = omap_device_build("omap-aes", -1, oh, NULL, 0, NULL,
+- 0, 0);
+- WARN(IS_ERR(pdev), "Can't build omap_device for omap-aes\n");
+- } else {
+- pr_err("%s: platform not supported\n", __func__);
+- }
++ struct omap_hwmod *oh;
++ struct platform_device *pdev;
++
++ oh = omap_hwmod_lookup("aes");
++ if (!oh)
++ return;
++
++ pdev = omap_device_build("omap-aes", -1, oh, NULL, 0, NULL, 0, 0);
++ WARN(IS_ERR(pdev), "Can't build omap_device for omap-aes\n");
+ }
+
+ /*-------------------------------------------------------------------------*/
diff --git a/patches/linux-3.8.13/0141-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch b/patches/linux-3.8.13/0141-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch
new file mode 100644
index 0000000..551a982
--- /dev/null
+++ b/patches/linux-3.8.13/0141-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch
@@ -0,0 +1,29 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 19 Dec 2012 20:53:38 -0700
+Subject: [PATCH] ARM: OMAP2+: Only manually add hwmod data when DT not used.
+
+The omap_init_aes() routine in devices.c only needs to be
+called when there is no device tree present.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/devices.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index 5f873c2..a6d8070 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -630,10 +630,10 @@ static int __init omap2_init_devices(void)
+ omap_init_mcpdm();
+ omap_init_mcspi();
+ omap_init_sham();
++ omap_init_aes();
+ }
+ omap_init_sti();
+ omap_init_rng();
+- omap_init_aes();
+ omap_init_vout();
+ omap_init_ocp2scp();
+ if (soc_is_am33xx()) {
diff --git a/patches/linux-3.8.13/0142-ARM-AM33XX-Add-aes0-crypto-clock-data.patch b/patches/linux-3.8.13/0142-ARM-AM33XX-Add-aes0-crypto-clock-data.patch
new file mode 100644
index 0000000..4391020
--- /dev/null
+++ b/patches/linux-3.8.13/0142-ARM-AM33XX-Add-aes0-crypto-clock-data.patch
@@ -0,0 +1,36 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 19 Dec 2012 21:05:46 -0700
+Subject: [PATCH] ARM: AM33XX: Add aes0 crypto clock data
+
+Add clock data for for the SHA0 crypto module
+on the am33xx SoC.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/cclock33xx_data.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
+index e69155d..743dce4 100644
+--- a/arch/arm/mach-omap2/cclock33xx_data.c
++++ b/arch/arm/mach-omap2/cclock33xx_data.c
+@@ -417,6 +417,10 @@ static struct clk sha0_fck;
+ DEFINE_STRUCT_CLK_HW_OMAP(sha0_fck, NULL);
+ DEFINE_STRUCT_CLK(sha0_fck, dpll_core_ck_parents, clk_ops_null);
+
++static struct clk aes0_fck;
++DEFINE_STRUCT_CLK_HW_OMAP(aes0_fck, NULL);
++DEFINE_STRUCT_CLK(aes0_fck, dpll_core_ck_parents, clk_ops_null);
++
+ /*
+ * Modules clock nodes
+ *
+@@ -910,6 +914,7 @@ static struct omap_clk am33xx_clks[] = {
+ CLK(NULL, "smartreflex0_fck", &smartreflex0_fck, CK_AM33XX),
+ CLK(NULL, "smartreflex1_fck", &smartreflex1_fck, CK_AM33XX),
+ CLK(NULL, "sha0_fck", &sha0_fck, CK_AM33XX),
++ CLK(NULL, "aes0_fck", &aes0_fck, CK_AM33XX),
+ CLK(NULL, "timer1_fck", &timer1_fck, CK_AM33XX),
+ CLK(NULL, "timer2_fck", &timer2_fck, CK_AM33XX),
+ CLK(NULL, "timer3_fck", &timer3_fck, CK_AM33XX),
diff --git a/patches/linux-3.8.13/0143-ARM-AM33XX-hwmod-Update-and-uncomment-AES0-module-da.patch b/patches/linux-3.8.13/0143-ARM-AM33XX-hwmod-Update-and-uncomment-AES0-module-da.patch
new file mode 100644
index 0000000..cc11b2f
--- /dev/null
+++ b/patches/linux-3.8.13/0143-ARM-AM33XX-hwmod-Update-and-uncomment-AES0-module-da.patch
@@ -0,0 +1,116 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 19 Dec 2012 21:17:07 -0700
+Subject: [PATCH] ARM: AM33XX: hwmod: Update and uncomment AES0 module data
+
+Update the AES0 HIB2 module's hwmod data for the am33xx SoC.
+Also, remove it from the '#if 0' block that its currently
+inside so the data is actually available for use.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 51 +++++++++++++++++++++++-----
+ 1 file changed, 42 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index 87c7dee..a180336 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -416,7 +416,6 @@ static struct omap_hwmod am33xx_adc_tsc_hwmod = {
+ * - debugss
+ * - ocmc ram
+ * - ocp watch point
+- * - aes0
+ */
+ #if 0
+ /*
+@@ -516,25 +515,41 @@ static struct omap_hwmod am33xx_ocpwp_hwmod = {
+ },
+ },
+ };
++#endif
+
+ /*
+- * 'aes' class
++ * 'aes0' class
+ */
+-static struct omap_hwmod_class am33xx_aes_hwmod_class = {
+- .name = "aes",
++static struct omap_hwmod_class_sysconfig am33xx_aes0_sysc = {
++ .rev_offs = 0x80,
++ .sysc_offs = 0x84,
++ .syss_offs = 0x88,
++ .sysc_flags = SYSS_HAS_RESET_STATUS,
++};
++
++static struct omap_hwmod_class am33xx_aes0_hwmod_class = {
++ .name = "aes0",
++ .sysc = &am33xx_aes0_sysc,
+ };
+
+ static struct omap_hwmod_irq_info am33xx_aes0_irqs[] = {
+- { .irq = 102 + OMAP_INTC_START, },
++ { .irq = 103 + OMAP_INTC_START, },
+ { .irq = -1 },
+ };
+
++struct omap_hwmod_dma_info am33xx_aes0_edma_reqs[] = {
++ { .name = "tx", .dma_req = 6, },
++ { .name = "rx", .dma_req = 5, },
++ { .dma_req = -1 }
++};
++
+ static struct omap_hwmod am33xx_aes0_hwmod = {
+- .name = "aes0",
+- .class = &am33xx_aes_hwmod_class,
++ .name = "aes",
++ .class = &am33xx_aes0_hwmod_class,
+ .clkdm_name = "l3_clkdm",
+ .mpu_irqs = am33xx_aes0_irqs,
+- .main_clk = "l3_gclk",
++ .sdma_reqs = am33xx_aes0_edma_reqs,
++ .main_clk = "aes0_fck",
+ .prcm = {
+ .omap4 = {
+ .clkctrl_offs = AM33XX_CM_PER_AES0_CLKCTRL_OFFSET,
+@@ -542,7 +557,6 @@ static struct omap_hwmod am33xx_aes0_hwmod = {
+ },
+ },
+ };
+-#endif
+
+ /* sha0 HIB2 (the 'P' (public) device) */
+ static struct omap_hwmod_class_sysconfig am33xx_sha0_sysc = {
+@@ -3456,6 +3470,24 @@ static struct omap_hwmod_ocp_if am33xx_l3_main__sha0 = {
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+ };
+
++/* l3 main -> AES0 HIB2 */
++static struct omap_hwmod_addr_space am33xx_aes0_addrs[] = {
++ {
++ .pa_start = 0x53500000,
++ .pa_end = 0x53500000 + SZ_1M - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ { }
++};
++
++static struct omap_hwmod_ocp_if am33xx_l3_main__aes0 = {
++ .master = &am33xx_l3_main_hwmod,
++ .slave = &am33xx_aes0_hwmod,
++ .clk = "aes0_fck",
++ .addr = am33xx_aes0_addrs,
++ .user = OCP_USER_MPU | OCP_USER_SDMA,
++};
++
+ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l4_fw__emif_fw,
+ &am33xx_l3_main__emif,
+@@ -3536,6 +3568,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l4_hs__cpgmac0,
+ &am33xx_cpgmac0__mdio,
+ &am33xx_l3_main__sha0,
++ &am33xx_l3_main__aes0,
+ NULL,
+ };
+
diff --git a/patches/linux-3.8.13/0144-ARM-dts-Add-AES-data-and-documentation-for-AM33XX.patch b/patches/linux-3.8.13/0144-ARM-dts-Add-AES-data-and-documentation-for-AM33XX.patch
new file mode 100644
index 0000000..65d2784
--- /dev/null
+++ b/patches/linux-3.8.13/0144-ARM-dts-Add-AES-data-and-documentation-for-AM33XX.patch
@@ -0,0 +1,122 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 20 Dec 2012 09:46:13 -0700
+Subject: [PATCH] ARM: dts: Add AES data and documentation for AM33XX
+
+Add the generic AM33XX AES module's device tree data and
+enable it for the am335x-evm, am335x-evmsk, and am335x-bone
+platforms. Also add Documentation file describing the data
+for the AES module.
+
+CC: Paul Walmsley <paul@pwsan.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ .../devicetree/bindings/crypto/omap-aes.txt | 37 ++++++++++++++++++++
+ arch/arm/boot/dts/am335x-bone.dts | 4 +++
+ arch/arm/boot/dts/am335x-evm.dts | 4 +++
+ arch/arm/boot/dts/am335x-evmsk.dts | 4 +++
+ arch/arm/boot/dts/am33xx.dtsi | 13 +++++++
+ 5 files changed, 62 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/crypto/omap-aes.txt
+
+diff --git a/Documentation/devicetree/bindings/crypto/omap-aes.txt b/Documentation/devicetree/bindings/crypto/omap-aes.txt
+new file mode 100644
+index 0000000..6b21256
+--- /dev/null
++++ b/Documentation/devicetree/bindings/crypto/omap-aes.txt
+@@ -0,0 +1,37 @@
++OMAP SoC AES crypto Module
++
++Required properties:
++
++- compatible : Should contain entries for this and backward compatible
++ AES versions:
++ - "ti,omap2-aes" for OMAP2.
++ - "ti,omap3-aes" for OMAP3.
++ - "ti,omap4-aes" for OMAP4 and AM33XX.
++ Note that the OMAP2 and 3 versions are compatible (OMAP3 supports
++ more algorithms) but they are incompatible with OMAP4.
++- ti,hwmods: Name of the hwmod associated with the AES odule
++- reg : Offset and length of the register set for the module
++- interrupt-parent : the phandle for the interrupt controller that
++ services interrupts for this module.
++- interrupts : the interrupt number for the AES odule.
++
++Optional properties:
++- dmas: DMA controller phandle and DMA request ordered pairs.
++- dma-names: DMA request names. This string corresponds 1:1 with
++ the ordered pairs in dmas. The string naming is to be
++ "tx" for TX request and "rx" for RX request.
++
++Example:
++ /* AM335x */
++ aes: aes@53500000 {
++ compatible = "ti,omap4-aes";
++ ti,hwmods = "aes";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x53500000 0xa0>;
++ interrupt-parent = <&intc>;
++ interrupts = <102>;
++ dmas = <&edma 6
++ &edma 5>;
++ dma-names = "tx", "rx";
++ };
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 5254b64..bf87ceb 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -285,3 +285,7 @@
+ &sham {
+ status = "okay";
+ };
++
++&aes {
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 5d33c20..d83be11 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -362,3 +362,7 @@
+ &sham {
+ status = "okay";
+ };
++
++&aes {
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
+index a7e1659..5aa07e7 100644
+--- a/arch/arm/boot/dts/am335x-evmsk.dts
++++ b/arch/arm/boot/dts/am335x-evmsk.dts
+@@ -335,3 +335,7 @@
+ &sham {
+ status = "okay";
+ };
++
++&aes {
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index fa94f6e..6dcd42a 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -562,5 +562,18 @@
+ dmas = <&edma 36>;
+ dma-names = "rx";
+ };
++
++ aes: aes@53500000 {
++ compatible = "ti,omap4-aes";
++ ti,hwmods = "aes";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x53500000 0xa0>;
++ interrupt-parent = <&intc>;
++ interrupts = <102>;
++ dmas = <&edma 6
++ &edma 5>;
++ dma-names = "tx", "rx";
++ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0145-crypto-omap-sham-Remove-unnecessary-pr_info-noise.patch b/patches/linux-3.8.13/0145-crypto-omap-sham-Remove-unnecessary-pr_info-noise.patch
new file mode 100644
index 0000000..7c53b4e
--- /dev/null
+++ b/patches/linux-3.8.13/0145-crypto-omap-sham-Remove-unnecessary-pr_info-noise.patch
@@ -0,0 +1,25 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Mon, 17 Dec 2012 11:21:46 -0700
+Subject: [PATCH] crypto: omap-sham - Remove unnecessary pr_info noise
+
+Remove the unnecessary pr_info() call in omap_sham_mod_init().
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index 90d34ad..344f713 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -1286,8 +1286,6 @@ static struct platform_driver omap_sham_driver = {
+
+ static int __init omap_sham_mod_init(void)
+ {
+- pr_info("loading %s driver\n", "omap-sham");
+-
+ return platform_driver_register(&omap_sham_driver);
+ }
+
diff --git a/patches/linux-3.8.13/0146-crypto-omap-sham-Convert-to-use-pm_runtime-API.patch b/patches/linux-3.8.13/0146-crypto-omap-sham-Convert-to-use-pm_runtime-API.patch
new file mode 100644
index 0000000..9153e7d
--- /dev/null
+++ b/patches/linux-3.8.13/0146-crypto-omap-sham-Convert-to-use-pm_runtime-API.patch
@@ -0,0 +1,111 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 10 Oct 2012 10:12:13 -0700
+Subject: [PATCH] crypto: omap-sham - Convert to use pm_runtime API
+
+Convert the omap-sham crypto driver to use the
+pm_runtime API instead of the clk API.
+
+CC: Kevin Hilman <khilman@deeprootsystems.com>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 28 +++++++++++-----------------
+ 1 file changed, 11 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index 344f713..4a228c5 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -22,12 +22,12 @@
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
+ #include <linux/kernel.h>
+-#include <linux/clk.h>
+ #include <linux/irq.h>
+ #include <linux/io.h>
+ #include <linux/platform_device.h>
+ #include <linux/scatterlist.h>
+ #include <linux/dma-mapping.h>
++#include <linux/pm_runtime.h>
+ #include <linux/delay.h>
+ #include <linux/crypto.h>
+ #include <linux/cryptohash.h>
+@@ -140,7 +140,6 @@ struct omap_sham_dev {
+ struct device *dev;
+ void __iomem *io_base;
+ int irq;
+- struct clk *iclk;
+ spinlock_t lock;
+ int err;
+ int dma;
+@@ -237,7 +236,7 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
+
+ static int omap_sham_hw_init(struct omap_sham_dev *dd)
+ {
+- clk_enable(dd->iclk);
++ pm_runtime_get_sync(dd->dev);
+
+ if (!test_bit(FLAGS_INIT, &dd->flags)) {
+ omap_sham_write_mask(dd, SHA_REG_MASK,
+@@ -652,7 +651,8 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
+ /* atomic operation is not needed here */
+ dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
+ BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
+- clk_disable(dd->iclk);
++
++ pm_runtime_put_sync(dd->dev);
+
+ if (req->base.complete)
+ req->base.complete(&req->base, err);
+@@ -1197,14 +1197,6 @@ static int omap_sham_probe(struct platform_device *pdev)
+ if (err)
+ goto dma_err;
+
+- /* Initializing the clock */
+- dd->iclk = clk_get(dev, "ick");
+- if (IS_ERR(dd->iclk)) {
+- dev_err(dev, "clock intialization failed.\n");
+- err = PTR_ERR(dd->iclk);
+- goto clk_err;
+- }
+-
+ dd->io_base = ioremap(dd->phys_base, SZ_4K);
+ if (!dd->io_base) {
+ dev_err(dev, "can't ioremap\n");
+@@ -1212,11 +1204,14 @@ static int omap_sham_probe(struct platform_device *pdev)
+ goto io_err;
+ }
+
+- clk_enable(dd->iclk);
++ pm_runtime_enable(dev);
++ pm_runtime_get_sync(dev);
++
+ dev_info(dev, "hw accel on OMAP rev %u.%u\n",
+ (omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MAJOR) >> 4,
+ omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MINOR);
+- clk_disable(dd->iclk);
++
++ pm_runtime_put_sync(&pdev->dev);
+
+ spin_lock(&sham.lock);
+ list_add_tail(&dd->list, &sham.dev_list);
+@@ -1234,9 +1229,8 @@ err_algs:
+ for (j = 0; j < i; j++)
+ crypto_unregister_ahash(&algs[j]);
+ iounmap(dd->io_base);
++ pm_runtime_disable(dev);
+ io_err:
+- clk_put(dd->iclk);
+-clk_err:
+ omap_sham_dma_cleanup(dd);
+ dma_err:
+ if (dd->irq >= 0)
+@@ -1265,7 +1259,7 @@ static int omap_sham_remove(struct platform_device *pdev)
+ crypto_unregister_ahash(&algs[i]);
+ tasklet_kill(&dd->done_task);
+ iounmap(dd->io_base);
+- clk_put(dd->iclk);
++ pm_runtime_disable(&pdev->dev);
+ omap_sham_dma_cleanup(dd);
+ if (dd->irq >= 0)
+ free_irq(dd->irq, dd);
diff --git a/patches/linux-3.8.13/0147-crypto-omap-sham-Add-suspend-resume-support.patch b/patches/linux-3.8.13/0147-crypto-omap-sham-Add-suspend-resume-support.patch
new file mode 100644
index 0000000..76342ff
--- /dev/null
+++ b/patches/linux-3.8.13/0147-crypto-omap-sham-Add-suspend-resume-support.patch
@@ -0,0 +1,48 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Fri, 14 Dec 2012 12:50:15 -0700
+Subject: [PATCH] crypto: omap-sham - Add suspend/resume support
+
+Add suspend/resume support to the OMAP SHAM driver.
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index 4a228c5..b7949a0 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -1269,12 +1269,31 @@ static int omap_sham_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++#ifdef CONFIG_PM_SLEEP
++static int omap_sham_suspend(struct device *dev)
++{
++ pm_runtime_put_sync(dev);
++ return 0;
++}
++
++static int omap_sham_resume(struct device *dev)
++{
++ pm_runtime_get_sync(dev);
++ return 0;
++}
++#endif
++
++static const struct dev_pm_ops omap_sham_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(omap_sham_suspend, omap_sham_resume)
++};
++
+ static struct platform_driver omap_sham_driver = {
+ .probe = omap_sham_probe,
+ .remove = omap_sham_remove,
+ .driver = {
+ .name = "omap-sham",
+ .owner = THIS_MODULE,
++ .pm = &omap_sham_pm_ops,
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0148-crypto-omap-sham-Add-code-to-use-dmaengine-API.patch b/patches/linux-3.8.13/0148-crypto-omap-sham-Add-code-to-use-dmaengine-API.patch
new file mode 100644
index 0000000..a71dcbb
--- /dev/null
+++ b/patches/linux-3.8.13/0148-crypto-omap-sham-Add-code-to-use-dmaengine-API.patch
@@ -0,0 +1,369 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Fri, 12 Oct 2012 11:47:09 -0700
+Subject: [PATCH] crypto: omap-sham - Add code to use dmaengine API
+
+Add code to use the new dmaengine API alongside
+the existing DMA code that uses the private
+OMAP DMA API. The API to use is chosen by
+defining or undefining 'OMAP_SHAM_DMA_PRIVATE'.
+
+This is a transitional change and the code that uses
+the private DMA API will be removed in an upcoming
+commit.
+
+CC: Russell King <rmk+kernel@arm.linux.org.uk>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 154 +++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 145 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index b7949a0..57cb76a 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -13,6 +13,8 @@
+ * Some ideas are from old omap-sha1-md5.c driver.
+ */
+
++#define OMAP_SHAM_DMA_PRIVATE
++
+ #define pr_fmt(fmt) "%s: " fmt, __func__
+
+ #include <linux/err.h>
+@@ -27,6 +29,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/scatterlist.h>
+ #include <linux/dma-mapping.h>
++#include <linux/dmaengine.h>
++#include <linux/omap-dma.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/delay.h>
+ #include <linux/crypto.h>
+@@ -37,15 +41,15 @@
+ #include <crypto/hash.h>
+ #include <crypto/internal/hash.h>
+
+-#include <linux/omap-dma.h>
+-#include <mach/irqs.h>
+-
+ #define SHA_REG_DIGEST(x) (0x00 + ((x) * 0x04))
+ #define SHA_REG_DIN(x) (0x1C + ((x) * 0x04))
+
+ #define SHA1_MD5_BLOCK_SIZE SHA1_BLOCK_SIZE
+ #define MD5_DIGEST_SIZE 16
+
++#define DST_MAXBURST 16
++#define DMA_MIN (DST_MAXBURST * sizeof(u32))
++
+ #define SHA_REG_DIGCNT 0x14
+
+ #define SHA_REG_CTRL 0x18
+@@ -109,6 +113,9 @@ struct omap_sham_reqctx {
+
+ /* walk state */
+ struct scatterlist *sg;
++#ifndef OMAP_SHAM_DMA_PRIVATE
++ struct scatterlist sgl;
++#endif
+ unsigned int offset; /* offset in current sg */
+ unsigned int total; /* total request */
+
+@@ -142,8 +149,12 @@ struct omap_sham_dev {
+ int irq;
+ spinlock_t lock;
+ int err;
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ int dma;
+ int dma_lch;
++#else
++ struct dma_chan *dma_lch;
++#endif
+ struct tasklet_struct done_task;
+
+ unsigned long flags;
+@@ -313,15 +324,32 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
+ return -EINPROGRESS;
+ }
+
++#ifndef OMAP_SHAM_DMA_PRIVATE
++static void omap_sham_dma_callback(void *param)
++{
++ struct omap_sham_dev *dd = param;
++
++ set_bit(FLAGS_DMA_READY, &dd->flags);
++ tasklet_schedule(&dd->done_task);
++}
++#endif
++
+ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+- size_t length, int final)
++ size_t length, int final, int is_sg)
+ {
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ int len32;
++#else
++ struct dma_async_tx_descriptor *tx;
++ struct dma_slave_config cfg;
++ int len32, ret;
++#endif
+
+ dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n",
+ ctx->digcnt, length, final);
+
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ len32 = DIV_ROUND_UP(length, sizeof(u32));
+
+ omap_set_dma_transfer_params(dd->dma_lch, OMAP_DMA_DATA_TYPE_S32, len32,
+@@ -331,6 +359,50 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+ omap_set_dma_src_params(dd->dma_lch, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_addr, 0, 0);
+
++#else
++ memset(&cfg, 0, sizeof(cfg));
++
++ cfg.dst_addr = dd->phys_base + SHA_REG_DIN(0);
++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ cfg.dst_maxburst = DST_MAXBURST;
++
++ ret = dmaengine_slave_config(dd->dma_lch, &cfg);
++ if (ret) {
++ pr_err("omap-sham: can't configure dmaengine slave: %d\n", ret);
++ return ret;
++ }
++
++ len32 = DIV_ROUND_UP(length, DMA_MIN) * DMA_MIN;
++
++ if (is_sg) {
++ /*
++ * The SG entry passed in may not have the 'length' member
++ * set correctly so use a local SG entry (sgl) with the
++ * proper value for 'length' instead. If this is not done,
++ * the dmaengine may try to DMA the incorrect amount of data.
++ */
++ sg_init_table(&ctx->sgl, 1);
++ ctx->sgl.page_link = ctx->sg->page_link;
++ ctx->sgl.offset = ctx->sg->offset;
++ sg_dma_len(&ctx->sgl) = len32;
++ sg_dma_address(&ctx->sgl) = sg_dma_address(ctx->sg);
++
++ tx = dmaengine_prep_slave_sg(dd->dma_lch, &ctx->sgl, 1,
++ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ } else {
++ tx = dmaengine_prep_slave_single(dd->dma_lch, dma_addr, len32,
++ DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ }
++
++ if (!tx) {
++ dev_err(dd->dev, "prep_slave_sg/single() failed\n");
++ return -EINVAL;
++ }
++
++ tx->callback = omap_sham_dma_callback;
++ tx->callback_param = dd;
++#endif
++
+ omap_sham_write_ctrl(dd, length, final, 1);
+
+ ctx->digcnt += length;
+@@ -340,7 +412,12 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+
+ set_bit(FLAGS_DMA_ACTIVE, &dd->flags);
+
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ omap_start_dma(dd->dma_lch);
++#else
++ dmaengine_submit(tx);
++ dma_async_issue_pending(dd->dma_lch);
++#endif
+
+ return -EINPROGRESS;
+ }
+@@ -387,6 +464,8 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
+ struct omap_sham_reqctx *ctx,
+ size_t length, int final)
+ {
++ int ret;
++
+ ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, ctx->buflen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
+@@ -396,8 +475,12 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
+
+ ctx->flags &= ~BIT(FLAGS_SG);
+
+- /* next call does not fail... so no unmap in the case of error */
+- return omap_sham_xmit_dma(dd, ctx->dma_addr, length, final);
++ ret = omap_sham_xmit_dma(dd, ctx->dma_addr, length, final, 0);
++ if (ret)
++ dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen,
++ DMA_TO_DEVICE);
++
++ return ret;
+ }
+
+ static int omap_sham_update_dma_slow(struct omap_sham_dev *dd)
+@@ -432,6 +515,7 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
+ unsigned int length, final, tail;
+ struct scatterlist *sg;
++ int ret;
+
+ if (!ctx->total)
+ return 0;
+@@ -439,6 +523,17 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
+ if (ctx->bufcnt || ctx->offset)
+ return omap_sham_update_dma_slow(dd);
+
++#ifndef OMAP_SHAM_DMA_PRIVATE
++ /*
++ * Don't use the sg interface when the transfer size is less
++ * than the number of elements in a DMA frame. Otherwise,
++ * the dmaengine infrastructure will calculate that it needs
++ * to transfer 0 frames which ultimately fails.
++ */
++ if (ctx->total < (DST_MAXBURST * sizeof(u32)))
++ return omap_sham_update_dma_slow(dd);
++#endif
++
+ dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n",
+ ctx->digcnt, ctx->bufcnt, ctx->total);
+
+@@ -476,8 +571,11 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
+
+ final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
+
+- /* next call does not fail... so no unmap in the case of error */
+- return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final);
++ ret = omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final, 1);
++ if (ret)
++ dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
++
++ return ret;
+ }
+
+ static int omap_sham_update_cpu(struct omap_sham_dev *dd)
+@@ -496,7 +594,12 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
+ {
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
+
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ omap_stop_dma(dd->dma_lch);
++#else
++ dmaengine_terminate_all(dd->dma_lch);
++#endif
++
+ if (ctx->flags & BIT(FLAGS_SG)) {
+ dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
+ if (ctx->sg->length == ctx->offset) {
+@@ -583,7 +686,7 @@ static int omap_sham_final_req(struct omap_sham_dev *dd)
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+ int err = 0, use_dma = 1;
+
+- if (ctx->bufcnt <= 64)
++ if (ctx->bufcnt <= DMA_MIN)
+ /* faster to handle last block with cpu */
+ use_dma = 0;
+
+@@ -699,6 +802,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
+ if (err)
+ goto err1;
+
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ omap_set_dma_dest_params(dd->dma_lch, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ dd->phys_base + SHA_REG_DIN(0), 0, 16);
+@@ -708,6 +812,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
+
+ omap_set_dma_src_burst_mode(dd->dma_lch,
+ OMAP_DMA_DATA_BURST_4);
++#endif
+
+ if (ctx->digcnt)
+ /* request has changed - restore hash */
+@@ -1099,6 +1204,7 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ static void omap_sham_dma_callback(int lch, u16 ch_status, void *data)
+ {
+ struct omap_sham_dev *dd = data;
+@@ -1136,12 +1242,17 @@ static void omap_sham_dma_cleanup(struct omap_sham_dev *dd)
+ dd->dma_lch = -1;
+ }
+ }
++#endif
+
+ static int omap_sham_probe(struct platform_device *pdev)
+ {
+ struct omap_sham_dev *dd;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
++#ifndef OMAP_SHAM_DMA_PRIVATE
++ dma_cap_mask_t mask;
++ unsigned dma_chan;
++#endif
+ int err, i, j;
+
+ dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL);
+@@ -1176,7 +1287,11 @@ static int omap_sham_probe(struct platform_device *pdev)
+ err = -ENODEV;
+ goto res_err;
+ }
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ dd->dma = res->start;
++#else
++ dma_chan = res->start;
++#endif
+
+ /* Get the IRQ */
+ dd->irq = platform_get_irq(pdev, 0);
+@@ -1193,9 +1308,22 @@ static int omap_sham_probe(struct platform_device *pdev)
+ goto res_err;
+ }
+
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ err = omap_sham_dma_init(dd);
+ if (err)
+ goto dma_err;
++#else
++ dma_cap_zero(mask);
++ dma_cap_set(DMA_SLAVE, mask);
++
++ dd->dma_lch = dma_request_channel(mask, omap_dma_filter_fn, &dma_chan);
++ if (!dd->dma_lch) {
++ dev_err(dev, "unable to obtain RX DMA engine channel %u\n",
++ dma_chan);
++ err = -ENXIO;
++ goto dma_err;
++ }
++#endif
+
+ dd->io_base = ioremap(dd->phys_base, SZ_4K);
+ if (!dd->io_base) {
+@@ -1231,7 +1359,11 @@ err_algs:
+ iounmap(dd->io_base);
+ pm_runtime_disable(dev);
+ io_err:
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ omap_sham_dma_cleanup(dd);
++#else
++ dma_release_channel(dd->dma_lch);
++#endif
+ dma_err:
+ if (dd->irq >= 0)
+ free_irq(dd->irq, dd);
+@@ -1260,7 +1392,11 @@ static int omap_sham_remove(struct platform_device *pdev)
+ tasklet_kill(&dd->done_task);
+ iounmap(dd->io_base);
+ pm_runtime_disable(&pdev->dev);
++#ifdef OMAP_SHAM_DMA_PRIVATE
+ omap_sham_dma_cleanup(dd);
++#else
++ dma_release_channel(dd->dma_lch);
++#endif
+ if (dd->irq >= 0)
+ free_irq(dd->irq, dd);
+ kfree(dd);
diff --git a/patches/linux-3.8.13/0149-crypto-omap-sham-Remove-usage-of-private-DMA-API.patch b/patches/linux-3.8.13/0149-crypto-omap-sham-Remove-usage-of-private-DMA-API.patch
new file mode 100644
index 0000000..f9371b6
--- /dev/null
+++ b/patches/linux-3.8.13/0149-crypto-omap-sham-Remove-usage-of-private-DMA-API.patch
@@ -0,0 +1,273 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 17 Oct 2012 22:03:37 -0700
+Subject: [PATCH] crypto: omap-sham - Remove usage of private DMA API
+
+Remove usage of the private OMAP DMA API.
+The dmaengine API will be used instead.
+
+CC: Russell King <rmk+kernel@arm.linux.org.uk>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 109 --------------------------------------------
+ 1 file changed, 109 deletions(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index 57cb76a..1c752a2 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -13,8 +13,6 @@
+ * Some ideas are from old omap-sha1-md5.c driver.
+ */
+
+-#define OMAP_SHAM_DMA_PRIVATE
+-
+ #define pr_fmt(fmt) "%s: " fmt, __func__
+
+ #include <linux/err.h>
+@@ -113,9 +111,7 @@ struct omap_sham_reqctx {
+
+ /* walk state */
+ struct scatterlist *sg;
+-#ifndef OMAP_SHAM_DMA_PRIVATE
+ struct scatterlist sgl;
+-#endif
+ unsigned int offset; /* offset in current sg */
+ unsigned int total; /* total request */
+
+@@ -149,12 +145,7 @@ struct omap_sham_dev {
+ int irq;
+ spinlock_t lock;
+ int err;
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- int dma;
+- int dma_lch;
+-#else
+ struct dma_chan *dma_lch;
+-#endif
+ struct tasklet_struct done_task;
+
+ unsigned long flags;
+@@ -324,7 +315,6 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
+ return -EINPROGRESS;
+ }
+
+-#ifndef OMAP_SHAM_DMA_PRIVATE
+ static void omap_sham_dma_callback(void *param)
+ {
+ struct omap_sham_dev *dd = param;
+@@ -332,34 +322,18 @@ static void omap_sham_dma_callback(void *param)
+ set_bit(FLAGS_DMA_READY, &dd->flags);
+ tasklet_schedule(&dd->done_task);
+ }
+-#endif
+
+ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+ size_t length, int final, int is_sg)
+ {
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- int len32;
+-#else
+ struct dma_async_tx_descriptor *tx;
+ struct dma_slave_config cfg;
+ int len32, ret;
+-#endif
+
+ dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n",
+ ctx->digcnt, length, final);
+
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- len32 = DIV_ROUND_UP(length, sizeof(u32));
+-
+- omap_set_dma_transfer_params(dd->dma_lch, OMAP_DMA_DATA_TYPE_S32, len32,
+- 1, OMAP_DMA_SYNC_PACKET, dd->dma,
+- OMAP_DMA_DST_SYNC_PREFETCH);
+-
+- omap_set_dma_src_params(dd->dma_lch, 0, OMAP_DMA_AMODE_POST_INC,
+- dma_addr, 0, 0);
+-
+-#else
+ memset(&cfg, 0, sizeof(cfg));
+
+ cfg.dst_addr = dd->phys_base + SHA_REG_DIN(0);
+@@ -401,7 +375,6 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+
+ tx->callback = omap_sham_dma_callback;
+ tx->callback_param = dd;
+-#endif
+
+ omap_sham_write_ctrl(dd, length, final, 1);
+
+@@ -412,12 +385,8 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+
+ set_bit(FLAGS_DMA_ACTIVE, &dd->flags);
+
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- omap_start_dma(dd->dma_lch);
+-#else
+ dmaengine_submit(tx);
+ dma_async_issue_pending(dd->dma_lch);
+-#endif
+
+ return -EINPROGRESS;
+ }
+@@ -523,7 +492,6 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
+ if (ctx->bufcnt || ctx->offset)
+ return omap_sham_update_dma_slow(dd);
+
+-#ifndef OMAP_SHAM_DMA_PRIVATE
+ /*
+ * Don't use the sg interface when the transfer size is less
+ * than the number of elements in a DMA frame. Otherwise,
+@@ -532,7 +500,6 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
+ */
+ if (ctx->total < (DST_MAXBURST * sizeof(u32)))
+ return omap_sham_update_dma_slow(dd);
+-#endif
+
+ dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n",
+ ctx->digcnt, ctx->bufcnt, ctx->total);
+@@ -594,11 +561,7 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
+ {
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
+
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- omap_stop_dma(dd->dma_lch);
+-#else
+ dmaengine_terminate_all(dd->dma_lch);
+-#endif
+
+ if (ctx->flags & BIT(FLAGS_SG)) {
+ dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
+@@ -802,18 +765,6 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
+ if (err)
+ goto err1;
+
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- omap_set_dma_dest_params(dd->dma_lch, 0,
+- OMAP_DMA_AMODE_CONSTANT,
+- dd->phys_base + SHA_REG_DIN(0), 0, 16);
+-
+- omap_set_dma_dest_burst_mode(dd->dma_lch,
+- OMAP_DMA_DATA_BURST_16);
+-
+- omap_set_dma_src_burst_mode(dd->dma_lch,
+- OMAP_DMA_DATA_BURST_4);
+-#endif
+-
+ if (ctx->digcnt)
+ /* request has changed - restore hash */
+ omap_sham_copy_hash(req, 0);
+@@ -1204,55 +1155,13 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+-static void omap_sham_dma_callback(int lch, u16 ch_status, void *data)
+-{
+- struct omap_sham_dev *dd = data;
+-
+- if (ch_status != OMAP_DMA_BLOCK_IRQ) {
+- pr_err("omap-sham DMA error status: 0x%hx\n", ch_status);
+- dd->err = -EIO;
+- clear_bit(FLAGS_INIT, &dd->flags);/* request to re-initialize */
+- }
+-
+- set_bit(FLAGS_DMA_READY, &dd->flags);
+- tasklet_schedule(&dd->done_task);
+-}
+-
+-static int omap_sham_dma_init(struct omap_sham_dev *dd)
+-{
+- int err;
+-
+- dd->dma_lch = -1;
+-
+- err = omap_request_dma(dd->dma, dev_name(dd->dev),
+- omap_sham_dma_callback, dd, &dd->dma_lch);
+- if (err) {
+- dev_err(dd->dev, "Unable to request DMA channel\n");
+- return err;
+- }
+-
+- return 0;
+-}
+-
+-static void omap_sham_dma_cleanup(struct omap_sham_dev *dd)
+-{
+- if (dd->dma_lch >= 0) {
+- omap_free_dma(dd->dma_lch);
+- dd->dma_lch = -1;
+- }
+-}
+-#endif
+-
+ static int omap_sham_probe(struct platform_device *pdev)
+ {
+ struct omap_sham_dev *dd;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+-#ifndef OMAP_SHAM_DMA_PRIVATE
+ dma_cap_mask_t mask;
+ unsigned dma_chan;
+-#endif
+ int err, i, j;
+
+ dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL);
+@@ -1287,11 +1196,7 @@ static int omap_sham_probe(struct platform_device *pdev)
+ err = -ENODEV;
+ goto res_err;
+ }
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- dd->dma = res->start;
+-#else
+ dma_chan = res->start;
+-#endif
+
+ /* Get the IRQ */
+ dd->irq = platform_get_irq(pdev, 0);
+@@ -1308,11 +1213,6 @@ static int omap_sham_probe(struct platform_device *pdev)
+ goto res_err;
+ }
+
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- err = omap_sham_dma_init(dd);
+- if (err)
+- goto dma_err;
+-#else
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+@@ -1323,7 +1223,6 @@ static int omap_sham_probe(struct platform_device *pdev)
+ err = -ENXIO;
+ goto dma_err;
+ }
+-#endif
+
+ dd->io_base = ioremap(dd->phys_base, SZ_4K);
+ if (!dd->io_base) {
+@@ -1359,11 +1258,7 @@ err_algs:
+ iounmap(dd->io_base);
+ pm_runtime_disable(dev);
+ io_err:
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- omap_sham_dma_cleanup(dd);
+-#else
+ dma_release_channel(dd->dma_lch);
+-#endif
+ dma_err:
+ if (dd->irq >= 0)
+ free_irq(dd->irq, dd);
+@@ -1392,11 +1287,7 @@ static int omap_sham_remove(struct platform_device *pdev)
+ tasklet_kill(&dd->done_task);
+ iounmap(dd->io_base);
+ pm_runtime_disable(&pdev->dev);
+-#ifdef OMAP_SHAM_DMA_PRIVATE
+- omap_sham_dma_cleanup(dd);
+-#else
+ dma_release_channel(dd->dma_lch);
+-#endif
+ if (dd->irq >= 0)
+ free_irq(dd->irq, dd);
+ kfree(dd);
diff --git a/patches/linux-3.8.13/0150-crypto-omap-sham-Add-Device-Tree-Support.patch b/patches/linux-3.8.13/0150-crypto-omap-sham-Add-Device-Tree-Support.patch
new file mode 100644
index 0000000..acfd815
--- /dev/null
+++ b/patches/linux-3.8.13/0150-crypto-omap-sham-Add-Device-Tree-Support.patch
@@ -0,0 +1,231 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Tue, 18 Dec 2012 10:03:02 -0700
+Subject: [PATCH] crypto: omap-sham - Add Device Tree Support
+
+Add Device Tree suport to the omap-sham crypto
+driver. Currently, only support for OMAP2 and
+OMAP3 is being added but support for OMAP4 will
+be added in a subsequent patch.
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 139 +++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 106 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index 1c752a2..797c905 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -30,6 +30,10 @@
+ #include <linux/dmaengine.h>
+ #include <linux/omap-dma.h>
+ #include <linux/pm_runtime.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
+ #include <linux/delay.h>
+ #include <linux/crypto.h>
+ #include <linux/cryptohash.h>
+@@ -145,6 +149,7 @@ struct omap_sham_dev {
+ int irq;
+ spinlock_t lock;
+ int err;
++ unsigned int dma;
+ struct dma_chan *dma_lch;
+ struct tasklet_struct done_task;
+
+@@ -1155,13 +1160,99 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
++#ifdef CONFIG_OF
++static const struct of_device_id omap_sham_of_match[] = {
++ {
++ .compatible = "ti,omap2-sham",
++ },
++ {},
++};
++MODULE_DEVICE_TABLE(of, omap_sham_of_match);
++
++static int omap_sham_get_res_of(struct omap_sham_dev *dd,
++ struct device *dev, struct resource *res)
++{
++ struct device_node *node = dev->of_node;
++ const struct of_device_id *match;
++ int err = 0;
++
++ match = of_match_device(of_match_ptr(omap_sham_of_match), dev);
++ if (!match) {
++ dev_err(dev, "no compatible OF match\n");
++ err = -EINVAL;
++ goto err;
++ }
++
++ err = of_address_to_resource(node, 0, res);
++ if (err < 0) {
++ dev_err(dev, "can't translate OF node address\n");
++ err = -EINVAL;
++ goto err;
++ }
++
++ dd->irq = of_irq_to_resource(node, 0, NULL);
++ if (!dd->irq) {
++ dev_err(dev, "can't translate OF irq value\n");
++ err = -EINVAL;
++ goto err;
++ }
++
++ dd->dma = -1; /* Dummy value that's unused */
++
++err:
++ return err;
++}
++#else
++static int omap_sham_get_res_dev(struct omap_sham_dev *dd,
++ struct device *dev, struct resource *res)
++{
++ return -EINVAL;
++}
++#endif
++
++static int omap_sham_get_res_pdev(struct omap_sham_dev *dd,
++ struct platform_device *pdev, struct resource *res)
++{
++ struct device *dev = &pdev->dev;
++ struct resource *r;
++ int err = 0;
++
++ /* Get the base address */
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!r) {
++ dev_err(dev, "no MEM resource info\n");
++ err = -ENODEV;
++ goto err;
++ }
++ memcpy(res, r, sizeof(*res));
++
++ /* Get the IRQ */
++ dd->irq = platform_get_irq(pdev, 0);
++ if (dd->irq < 0) {
++ dev_err(dev, "no IRQ resource info\n");
++ err = dd->irq;
++ goto err;
++ }
++
++ /* Get the DMA */
++ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
++ if (!r) {
++ dev_err(dev, "no DMA resource info\n");
++ err = -ENODEV;
++ goto err;
++ }
++ dd->dma = r->start;
++
++err:
++ return err;
++}
++
+ static int omap_sham_probe(struct platform_device *pdev)
+ {
+ struct omap_sham_dev *dd;
+ struct device *dev = &pdev->dev;
+- struct resource *res;
++ struct resource res;
+ dma_cap_mask_t mask;
+- unsigned dma_chan;
+ int err, i, j;
+
+ dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL);
+@@ -1178,33 +1269,18 @@ static int omap_sham_probe(struct platform_device *pdev)
+ tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd);
+ crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH);
+
+- dd->irq = -1;
+-
+- /* Get the base address */
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- dev_err(dev, "no MEM resource info\n");
+- err = -ENODEV;
+- goto res_err;
+- }
+- dd->phys_base = res->start;
+-
+- /* Get the DMA */
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+- if (!res) {
+- dev_err(dev, "no DMA resource info\n");
+- err = -ENODEV;
++ err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) :
++ omap_sham_get_res_pdev(dd, pdev, &res);
++ if (err)
+ goto res_err;
+- }
+- dma_chan = res->start;
+
+- /* Get the IRQ */
+- dd->irq = platform_get_irq(pdev, 0);
+- if (dd->irq < 0) {
+- dev_err(dev, "no IRQ resource info\n");
+- err = dd->irq;
++ dd->io_base = devm_request_and_ioremap(dev, &res);
++ if (!dd->io_base) {
++ dev_err(dev, "can't ioremap\n");
++ err = -ENOMEM;
+ goto res_err;
+ }
++ dd->phys_base = res.start;
+
+ err = request_irq(dd->irq, omap_sham_irq,
+ IRQF_TRIGGER_LOW, dev_name(dev), dd);
+@@ -1216,10 +1292,10 @@ static int omap_sham_probe(struct platform_device *pdev)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+- dd->dma_lch = dma_request_channel(mask, omap_dma_filter_fn, &dma_chan);
++ dd->dma_lch = dma_request_channel(mask, omap_dma_filter_fn, &dd->dma);
+ if (!dd->dma_lch) {
+ dev_err(dev, "unable to obtain RX DMA engine channel %u\n",
+- dma_chan);
++ dd->dma);
+ err = -ENXIO;
+ goto dma_err;
+ }
+@@ -1255,13 +1331,11 @@ static int omap_sham_probe(struct platform_device *pdev)
+ err_algs:
+ for (j = 0; j < i; j++)
+ crypto_unregister_ahash(&algs[j]);
+- iounmap(dd->io_base);
+ pm_runtime_disable(dev);
+ io_err:
+ dma_release_channel(dd->dma_lch);
+ dma_err:
+- if (dd->irq >= 0)
+- free_irq(dd->irq, dd);
++ free_irq(dd->irq, dd);
+ res_err:
+ kfree(dd);
+ dd = NULL;
+@@ -1285,11 +1359,9 @@ static int omap_sham_remove(struct platform_device *pdev)
+ for (i = 0; i < ARRAY_SIZE(algs); i++)
+ crypto_unregister_ahash(&algs[i]);
+ tasklet_kill(&dd->done_task);
+- iounmap(dd->io_base);
+ pm_runtime_disable(&pdev->dev);
+ dma_release_channel(dd->dma_lch);
+- if (dd->irq >= 0)
+- free_irq(dd->irq, dd);
++ free_irq(dd->irq, dd);
+ kfree(dd);
+ dd = NULL;
+
+@@ -1321,6 +1393,7 @@ static struct platform_driver omap_sham_driver = {
+ .name = "omap-sham",
+ .owner = THIS_MODULE,
+ .pm = &omap_sham_pm_ops,
++ .of_match_table = omap_sham_of_match,
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0151-crypto-omap-sham-Convert-to-dma_request_slave_channe.patch b/patches/linux-3.8.13/0151-crypto-omap-sham-Convert-to-dma_request_slave_channe.patch
new file mode 100644
index 0000000..43d76b6
--- /dev/null
+++ b/patches/linux-3.8.13/0151-crypto-omap-sham-Convert-to-dma_request_slave_channe.patch
@@ -0,0 +1,29 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Tue, 18 Dec 2012 20:35:20 -0700
+Subject: [PATCH] crypto: omap-sham - Convert to
+ dma_request_slave_channel_compat()
+
+Use the dma_request_slave_channel_compat() call instead of
+the dma_request_channel() call to request a DMA channel.
+This allows the omap-sham driver use different DMA engines.
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index 797c905..0814bd6 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -1292,7 +1292,8 @@ static int omap_sham_probe(struct platform_device *pdev)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+- dd->dma_lch = dma_request_channel(mask, omap_dma_filter_fn, &dd->dma);
++ dd->dma_lch = dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &dd->dma, dev, "rx");
+ if (!dd->dma_lch) {
+ dev_err(dev, "unable to obtain RX DMA engine channel %u\n",
+ dd->dma);
diff --git a/patches/linux-3.8.13/0152-crypto-omap-sham-Add-OMAP4-AM33XX-SHAM-Support.patch b/patches/linux-3.8.13/0152-crypto-omap-sham-Add-OMAP4-AM33XX-SHAM-Support.patch
new file mode 100644
index 0000000..a6308b5
--- /dev/null
+++ b/patches/linux-3.8.13/0152-crypto-omap-sham-Add-OMAP4-AM33XX-SHAM-Support.patch
@@ -0,0 +1,761 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Tue, 18 Dec 2012 20:55:48 -0700
+Subject: [PATCH] crypto: omap-sham - Add OMAP4/AM33XX SHAM Support
+
+Add support for the OMAP4 version of the SHAM module
+that is present on OMAP4 and AM33xx SoCs.
+
+The modules have several differences including register
+offsets, hardware XORing, and how DMA is triggered.
+To handle these differences, a platform_data structure
+is defined and contains routine pointers, register offsets,
+bit shifts within registers, and flags to indicate whether
+the hardware supports XORing and provides SHA1 results in
+big or little endian. OMAP2/OMAP3-specific routines are
+suffixed with '_omap2' and OMAP4/AM33xx routines are suffixed
+with '_omap4'.
+
+Note: The code being integrated is from the TI AM33xx SDK
+and was written by Greg Turner <gkmturner@gmail.com> and
+Herman Schuurman (current email unknown) while at TI.
+
+CC: Greg Turner <gkmturner@gmail.com>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 416 +++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 332 insertions(+), 84 deletions(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index 0814bd6..c8bfe71 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (c) 2010 Nokia Corporation
+ * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
++ * Copyright (c) 2011 Texas Instruments Incorporated
+ *
+ * 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
+@@ -43,16 +44,17 @@
+ #include <crypto/hash.h>
+ #include <crypto/internal/hash.h>
+
+-#define SHA_REG_DIGEST(x) (0x00 + ((x) * 0x04))
+-#define SHA_REG_DIN(x) (0x1C + ((x) * 0x04))
+-
+ #define SHA1_MD5_BLOCK_SIZE SHA1_BLOCK_SIZE
+ #define MD5_DIGEST_SIZE 16
+
+ #define DST_MAXBURST 16
+ #define DMA_MIN (DST_MAXBURST * sizeof(u32))
+
+-#define SHA_REG_DIGCNT 0x14
++#define SHA_REG_IDIGEST(dd, x) ((dd)->pdata->idigest_ofs + ((x)*0x04))
++#define SHA_REG_DIN(dd, x) ((dd)->pdata->din_ofs + ((x) * 0x04))
++#define SHA_REG_DIGCNT(dd) ((dd)->pdata->digcnt_ofs)
++
++#define SHA_REG_ODIGEST(x) (0x00 + ((x) * 0x04))
+
+ #define SHA_REG_CTRL 0x18
+ #define SHA_REG_CTRL_LENGTH (0xFFFFFFFF << 5)
+@@ -62,19 +64,40 @@
+ #define SHA_REG_CTRL_INPUT_READY (1 << 1)
+ #define SHA_REG_CTRL_OUTPUT_READY (1 << 0)
+
+-#define SHA_REG_REV 0x5C
+-#define SHA_REG_REV_MAJOR 0xF0
+-#define SHA_REG_REV_MINOR 0x0F
++#define SHA_REG_REV(dd) ((dd)->pdata->rev_ofs)
+
+-#define SHA_REG_MASK 0x60
++#define SHA_REG_MASK(dd) ((dd)->pdata->mask_ofs)
+ #define SHA_REG_MASK_DMA_EN (1 << 3)
+ #define SHA_REG_MASK_IT_EN (1 << 2)
+ #define SHA_REG_MASK_SOFTRESET (1 << 1)
+ #define SHA_REG_AUTOIDLE (1 << 0)
+
+-#define SHA_REG_SYSSTATUS 0x64
++#define SHA_REG_SYSSTATUS(dd) ((dd)->pdata->sysstatus_ofs)
+ #define SHA_REG_SYSSTATUS_RESETDONE (1 << 0)
+
++#define SHA_REG_MODE 0x44
++#define SHA_REG_MODE_HMAC_OUTER_HASH (1 << 7)
++#define SHA_REG_MODE_HMAC_KEY_PROC (1 << 5)
++#define SHA_REG_MODE_CLOSE_HASH (1 << 4)
++#define SHA_REG_MODE_ALGO_CONSTANT (1 << 3)
++#define SHA_REG_MODE_ALGO_MASK (3 << 1)
++#define SHA_REG_MODE_ALGO_MD5_128 (0 << 1)
++#define SHA_REG_MODE_ALGO_SHA1_160 (1 << 1)
++
++#define SHA_REG_LENGTH 0x48
++
++#define SHA_REG_IRQSTATUS 0x118
++#define SHA_REG_IRQSTATUS_CTX_RDY (1 << 3)
++#define SHA_REG_IRQSTATUS_PARTHASH_RDY (1 << 2)
++#define SHA_REG_IRQSTATUS_INPUT_RDY (1 << 1)
++#define SHA_REG_IRQSTATUS_OUTPUT_RDY (1 << 0)
++
++#define SHA_REG_IRQENA 0x11C
++#define SHA_REG_IRQENA_CTX_RDY (1 << 3)
++#define SHA_REG_IRQENA_PARTHASH_RDY (1 << 2)
++#define SHA_REG_IRQENA_INPUT_RDY (1 << 1)
++#define SHA_REG_IRQENA_OUTPUT_RDY (1 << 0)
++
+ #define DEFAULT_TIMEOUT_INTERVAL HZ
+
+ /* mostly device flags */
+@@ -85,20 +108,29 @@
+ #define FLAGS_INIT 4
+ #define FLAGS_CPU 5
+ #define FLAGS_DMA_READY 6
++#define FLAGS_AUTO_XOR 7
++#define FLAGS_BE32_SHA1 8
+ /* context flags */
+ #define FLAGS_FINUP 16
+ #define FLAGS_SG 17
+-#define FLAGS_SHA1 18
+-#define FLAGS_HMAC 19
+-#define FLAGS_ERROR 20
+
+-#define OP_UPDATE 1
+-#define OP_FINAL 2
++#define FLAGS_MODE_SHIFT 18
++#define FLAGS_MODE_MASK (SHA_REG_MODE_ALGO_MASK \
++ << (FLAGS_MODE_SHIFT - 1))
++#define FLAGS_MODE_MD5 (SHA_REG_MODE_ALGO_MD5_128 \
++ << (FLAGS_MODE_SHIFT - 1))
++#define FLAGS_MODE_SHA1 (SHA_REG_MODE_ALGO_SHA1_160 \
++ << (FLAGS_MODE_SHIFT - 1))
++#define FLAGS_HMAC 20
++#define FLAGS_ERROR 21
++
++#define OP_UPDATE 1
++#define OP_FINAL 2
+
+ #define OMAP_ALIGN_MASK (sizeof(u32)-1)
+ #define OMAP_ALIGNED __attribute__((aligned(sizeof(u32))))
+
+-#define BUFLEN PAGE_SIZE
++#define BUFLEN PAGE_SIZE
+
+ struct omap_sham_dev;
+
+@@ -107,7 +139,7 @@ struct omap_sham_reqctx {
+ unsigned long flags;
+ unsigned long op;
+
+- u8 digest[SHA1_DIGEST_SIZE] OMAP_ALIGNED;
++ u8 digest[SHA256_DIGEST_SIZE] OMAP_ALIGNED;
+ size_t digcnt;
+ size_t bufcnt;
+ size_t buflen;
+@@ -124,8 +156,8 @@ struct omap_sham_reqctx {
+
+ struct omap_sham_hmac_ctx {
+ struct crypto_shash *shash;
+- u8 ipad[SHA1_MD5_BLOCK_SIZE];
+- u8 opad[SHA1_MD5_BLOCK_SIZE];
++ u8 ipad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
++ u8 opad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
+ };
+
+ struct omap_sham_ctx {
+@@ -141,6 +173,31 @@ struct omap_sham_ctx {
+
+ #define OMAP_SHAM_QUEUE_LENGTH 1
+
++struct omap_sham_pdata {
++ unsigned long flags;
++ int digest_size;
++
++ void (*copy_hash)(struct ahash_request *req, int out);
++ void (*write_ctrl)(struct omap_sham_dev *dd, size_t length,
++ int final, int dma);
++ void (*trigger)(struct omap_sham_dev *dd, size_t length);
++ int (*poll_irq)(struct omap_sham_dev *dd);
++ irqreturn_t (*intr_hdlr)(int irq, void *dev_id);
++
++ u32 odigest_ofs;
++ u32 idigest_ofs;
++ u32 din_ofs;
++ u32 digcnt_ofs;
++ u32 rev_ofs;
++ u32 mask_ofs;
++ u32 sysstatus_ofs;
++
++ u32 major_mask;
++ u32 major_shift;
++ u32 minor_mask;
++ u32 minor_shift;
++};
++
+ struct omap_sham_dev {
+ struct list_head list;
+ unsigned long phys_base;
+@@ -156,6 +213,8 @@ struct omap_sham_dev {
+ unsigned long flags;
+ struct crypto_queue queue;
+ struct ahash_request *req;
++
++ const struct omap_sham_pdata *pdata;
+ };
+
+ struct omap_sham_drv {
+@@ -203,21 +262,44 @@ static inline int omap_sham_wait(struct omap_sham_dev *dd, u32 offset, u32 bit)
+ return 0;
+ }
+
+-static void omap_sham_copy_hash(struct ahash_request *req, int out)
++static void omap_sham_copy_hash_omap2(struct ahash_request *req, int out)
+ {
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
++ struct omap_sham_dev *dd = ctx->dd;
+ u32 *hash = (u32 *)ctx->digest;
+ int i;
+
+- /* MD5 is almost unused. So copy sha1 size to reduce code */
+- for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) {
++ for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
+ if (out)
+- hash[i] = omap_sham_read(ctx->dd,
+- SHA_REG_DIGEST(i));
++ hash[i] = omap_sham_read(dd, SHA_REG_IDIGEST(dd, i));
+ else
+- omap_sham_write(ctx->dd,
+- SHA_REG_DIGEST(i), hash[i]);
++ omap_sham_write(dd, SHA_REG_IDIGEST(dd, i), hash[i]);
++ }
++}
++
++static void omap_sham_copy_hash_omap4(struct ahash_request *req, int out)
++{
++ struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
++ struct omap_sham_dev *dd = ctx->dd;
++ int i;
++
++ if (ctx->flags & BIT(FLAGS_HMAC)) {
++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
++ struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
++ struct omap_sham_hmac_ctx *bctx = tctx->base;
++ u32 *opad = (u32 *)bctx->opad;
++
++ for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
++ if (out)
++ opad[i] = omap_sham_read(dd,
++ SHA_REG_ODIGEST(i));
++ else
++ omap_sham_write(dd, SHA_REG_ODIGEST(i),
++ opad[i]);
++ }
+ }
++
++ omap_sham_copy_hash_omap2(req, out);
+ }
+
+ static void omap_sham_copy_ready_hash(struct ahash_request *req)
+@@ -225,20 +307,31 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+ u32 *in = (u32 *)ctx->digest;
+ u32 *hash = (u32 *)req->result;
+- int i;
++ int i, d, big_endian = 0;
+
+ if (!hash)
+ return;
+
+- if (likely(ctx->flags & BIT(FLAGS_SHA1))) {
+- /* SHA1 results are in big endian */
+- for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
++ switch (ctx->flags & FLAGS_MODE_MASK) {
++ case FLAGS_MODE_MD5:
++ d = MD5_DIGEST_SIZE / sizeof(u32);
++ break;
++ case FLAGS_MODE_SHA1:
++ /* OMAP2 SHA1 is big endian */
++ if (test_bit(FLAGS_BE32_SHA1, &ctx->dd->flags))
++ big_endian = 1;
++ d = SHA1_DIGEST_SIZE / sizeof(u32);
++ break;
++ default:
++ d = 0;
++ }
++
++ if (big_endian)
++ for (i = 0; i < d; i++)
+ hash[i] = be32_to_cpu(in[i]);
+- } else {
+- /* MD5 results are in little endian */
+- for (i = 0; i < MD5_DIGEST_SIZE / sizeof(u32); i++)
++ else
++ for (i = 0; i < d; i++)
+ hash[i] = le32_to_cpu(in[i]);
+- }
+ }
+
+ static int omap_sham_hw_init(struct omap_sham_dev *dd)
+@@ -246,13 +339,6 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
+ pm_runtime_get_sync(dd->dev);
+
+ if (!test_bit(FLAGS_INIT, &dd->flags)) {
+- omap_sham_write_mask(dd, SHA_REG_MASK,
+- SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
+-
+- if (omap_sham_wait(dd, SHA_REG_SYSSTATUS,
+- SHA_REG_SYSSTATUS_RESETDONE))
+- return -ETIMEDOUT;
+-
+ set_bit(FLAGS_INIT, &dd->flags);
+ dd->err = 0;
+ }
+@@ -260,23 +346,23 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
+ return 0;
+ }
+
+-static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
++static void omap_sham_write_ctrl_omap2(struct omap_sham_dev *dd, size_t length,
+ int final, int dma)
+ {
+ struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
+ u32 val = length << 5, mask;
+
+ if (likely(ctx->digcnt))
+- omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt);
++ omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt);
+
+- omap_sham_write_mask(dd, SHA_REG_MASK,
++ omap_sham_write_mask(dd, SHA_REG_MASK(dd),
+ SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0),
+ SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
+ /*
+ * Setting ALGO_CONST only for the first iteration
+ * and CLOSE_HASH only for the last one.
+ */
+- if (ctx->flags & BIT(FLAGS_SHA1))
++ if ((ctx->flags & FLAGS_MODE_MASK) == FLAGS_MODE_SHA1)
+ val |= SHA_REG_CTRL_ALGO;
+ if (!ctx->digcnt)
+ val |= SHA_REG_CTRL_ALGO_CONST;
+@@ -289,6 +375,81 @@ static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
+ omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask);
+ }
+
++static void omap_sham_trigger_omap2(struct omap_sham_dev *dd, size_t length)
++{
++}
++
++static int omap_sham_poll_irq_omap2(struct omap_sham_dev *dd)
++{
++ return omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY);
++}
++
++static void omap_sham_write_n(struct omap_sham_dev *dd, u32 offset,
++ u32 *value, int count)
++{
++ for (; count--; value++, offset += 4)
++ omap_sham_write(dd, offset, *value);
++}
++
++static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
++ int final, int dma)
++{
++ struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
++ u32 val, mask;
++
++ /*
++ * Setting ALGO_CONST only for the first iteration and
++ * CLOSE_HASH only for the last one. Note that flags mode bits
++ * correspond to algorithm encoding in mode register.
++ */
++ val = (ctx->flags & FLAGS_MODE_MASK) >> (FLAGS_MODE_SHIFT - 1);
++ if (!ctx->digcnt) {
++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
++ struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
++ struct omap_sham_hmac_ctx *bctx = tctx->base;
++
++ val |= SHA_REG_MODE_ALGO_CONSTANT;
++
++ if (ctx->flags & BIT(FLAGS_HMAC)) {
++ val |= SHA_REG_MODE_HMAC_KEY_PROC;
++ omap_sham_write_n(dd, SHA_REG_ODIGEST(0),
++ (u32 *)bctx->ipad,
++ SHA1_BLOCK_SIZE / sizeof(u32));
++ ctx->digcnt += SHA1_BLOCK_SIZE;
++ }
++ }
++
++ if (final) {
++ val |= SHA_REG_MODE_CLOSE_HASH;
++
++ if (ctx->flags & BIT(FLAGS_HMAC))
++ val |= SHA_REG_MODE_HMAC_OUTER_HASH;
++ }
++
++ mask = SHA_REG_MODE_ALGO_CONSTANT | SHA_REG_MODE_CLOSE_HASH |
++ SHA_REG_MODE_ALGO_MASK | SHA_REG_MODE_HMAC_OUTER_HASH |
++ SHA_REG_MODE_HMAC_KEY_PROC;
++
++ dev_dbg(dd->dev, "ctrl: %08x, flags: %08lx\n", val, ctx->flags);
++ omap_sham_write_mask(dd, SHA_REG_MODE, val, mask);
++ omap_sham_write(dd, SHA_REG_IRQENA, SHA_REG_IRQENA_OUTPUT_RDY);
++ omap_sham_write_mask(dd, SHA_REG_MASK(dd),
++ SHA_REG_MASK_IT_EN |
++ (dma ? SHA_REG_MASK_DMA_EN : 0),
++ SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
++}
++
++static void omap_sham_trigger_omap4(struct omap_sham_dev *dd, size_t length)
++{
++ omap_sham_write(dd, SHA_REG_LENGTH, length);
++}
++
++static int omap_sham_poll_irq_omap4(struct omap_sham_dev *dd)
++{
++ return omap_sham_wait(dd, SHA_REG_IRQSTATUS,
++ SHA_REG_IRQSTATUS_INPUT_RDY);
++}
++
+ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
+ size_t length, int final)
+ {
+@@ -299,12 +460,13 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
+ dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
+ ctx->digcnt, length, final);
+
+- omap_sham_write_ctrl(dd, length, final, 0);
++ dd->pdata->write_ctrl(dd, length, final, 0);
++ dd->pdata->trigger(dd, length);
+
+ /* should be non-zero before next lines to disable clocks later */
+ ctx->digcnt += length;
+
+- if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY))
++ if (dd->pdata->poll_irq(dd))
+ return -ETIMEDOUT;
+
+ if (final)
+@@ -315,7 +477,7 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
+ len32 = DIV_ROUND_UP(length, sizeof(u32));
+
+ for (count = 0; count < len32; count++)
+- omap_sham_write(dd, SHA_REG_DIN(count), buffer[count]);
++ omap_sham_write(dd, SHA_REG_DIN(dd, count), buffer[count]);
+
+ return -EINPROGRESS;
+ }
+@@ -341,7 +503,7 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+
+ memset(&cfg, 0, sizeof(cfg));
+
+- cfg.dst_addr = dd->phys_base + SHA_REG_DIN(0);
++ cfg.dst_addr = dd->phys_base + SHA_REG_DIN(dd, 0);
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cfg.dst_maxburst = DST_MAXBURST;
+
+@@ -381,7 +543,7 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+ tx->callback = omap_sham_dma_callback;
+ tx->callback_param = dd;
+
+- omap_sham_write_ctrl(dd, length, final, 1);
++ dd->pdata->write_ctrl(dd, length, final, 1);
+
+ ctx->digcnt += length;
+
+@@ -393,6 +555,8 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
+ dmaengine_submit(tx);
+ dma_async_issue_pending(dd->dma_lch);
+
++ dd->pdata->trigger(dd, length);
++
+ return -EINPROGRESS;
+ }
+
+@@ -450,7 +614,7 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
+ ctx->flags &= ~BIT(FLAGS_SG);
+
+ ret = omap_sham_xmit_dma(dd, ctx->dma_addr, length, final, 0);
+- if (ret)
++ if (ret != -EINPROGRESS)
+ dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen,
+ DMA_TO_DEVICE);
+
+@@ -544,7 +708,7 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
+ final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
+
+ ret = omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final, 1);
+- if (ret)
++ if (ret != -EINPROGRESS)
+ dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
+
+ return ret;
+@@ -609,18 +773,27 @@ static int omap_sham_init(struct ahash_request *req)
+ dev_dbg(dd->dev, "init: digest size: %d\n",
+ crypto_ahash_digestsize(tfm));
+
+- if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE)
+- ctx->flags |= BIT(FLAGS_SHA1);
++ switch (crypto_ahash_digestsize(tfm)) {
++ case MD5_DIGEST_SIZE:
++ ctx->flags |= FLAGS_MODE_MD5;
++ break;
++ case SHA1_DIGEST_SIZE:
++ ctx->flags |= FLAGS_MODE_SHA1;
++ break;
++ }
+
+ ctx->bufcnt = 0;
+ ctx->digcnt = 0;
+ ctx->buflen = BUFLEN;
+
+ if (tctx->flags & BIT(FLAGS_HMAC)) {
+- struct omap_sham_hmac_ctx *bctx = tctx->base;
++ if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
++ struct omap_sham_hmac_ctx *bctx = tctx->base;
++
++ memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
++ ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
++ }
+
+- memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
+- ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
+ ctx->flags |= BIT(FLAGS_HMAC);
+ }
+
+@@ -697,7 +870,8 @@ static int omap_sham_finish(struct ahash_request *req)
+
+ if (ctx->digcnt) {
+ omap_sham_copy_ready_hash(req);
+- if (ctx->flags & BIT(FLAGS_HMAC))
++ if ((ctx->flags & BIT(FLAGS_HMAC)) &&
++ !test_bit(FLAGS_AUTO_XOR, &dd->flags))
+ err = omap_sham_finish_hmac(req);
+ }
+
+@@ -712,7 +886,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
+ struct omap_sham_dev *dd = ctx->dd;
+
+ if (!err) {
+- omap_sham_copy_hash(req, 1);
++ dd->pdata->copy_hash(req, 1);
+ if (test_bit(FLAGS_FINAL, &dd->flags))
+ err = omap_sham_finish(req);
+ } else {
+@@ -772,7 +946,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
+
+ if (ctx->digcnt)
+ /* request has changed - restore hash */
+- omap_sham_copy_hash(req, 0);
++ dd->pdata->copy_hash(req, 0);
+
+ if (ctx->op == OP_UPDATE) {
+ err = omap_sham_update_req(dd);
+@@ -911,7 +1085,21 @@ static int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
+ struct omap_sham_hmac_ctx *bctx = tctx->base;
+ int bs = crypto_shash_blocksize(bctx->shash);
+ int ds = crypto_shash_digestsize(bctx->shash);
++ struct omap_sham_dev *dd = NULL, *tmp;
+ int err, i;
++
++ spin_lock_bh(&sham.lock);
++ if (!tctx->dd) {
++ list_for_each_entry(tmp, &sham.dev_list, list) {
++ dd = tmp;
++ break;
++ }
++ tctx->dd = dd;
++ } else {
++ dd = tctx->dd;
++ }
++ spin_unlock_bh(&sham.lock);
++
+ err = crypto_shash_setkey(tctx->fallback, key, keylen);
+ if (err)
+ return err;
+@@ -928,11 +1116,14 @@ static int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
+ }
+
+ memset(bctx->ipad + keylen, 0, bs - keylen);
+- memcpy(bctx->opad, bctx->ipad, bs);
+
+- for (i = 0; i < bs; i++) {
+- bctx->ipad[i] ^= 0x36;
+- bctx->opad[i] ^= 0x5c;
++ if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
++ memcpy(bctx->opad, bctx->ipad, bs);
++
++ for (i = 0; i < bs; i++) {
++ bctx->ipad[i] ^= 0x36;
++ bctx->opad[i] ^= 0x5c;
++ }
+ }
+
+ return err;
+@@ -1137,7 +1328,19 @@ finish:
+ omap_sham_finish_req(dd->req, err);
+ }
+
+-static irqreturn_t omap_sham_irq(int irq, void *dev_id)
++static irqreturn_t omap_sham_irq_common(struct omap_sham_dev *dd)
++{
++ if (!test_bit(FLAGS_BUSY, &dd->flags)) {
++ dev_warn(dd->dev, "Interrupt when no active requests.\n");
++ } else {
++ set_bit(FLAGS_OUTPUT_READY, &dd->flags);
++ tasklet_schedule(&dd->done_task);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t omap_sham_irq_omap2(int irq, void *dev_id)
+ {
+ struct omap_sham_dev *dd = dev_id;
+
+@@ -1149,21 +1352,67 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
+ SHA_REG_CTRL_OUTPUT_READY);
+ omap_sham_read(dd, SHA_REG_CTRL);
+
+- if (!test_bit(FLAGS_BUSY, &dd->flags)) {
+- dev_warn(dd->dev, "Interrupt when no active requests.\n");
+- return IRQ_HANDLED;
+- }
++ return omap_sham_irq_common(dd);
++}
+
+- set_bit(FLAGS_OUTPUT_READY, &dd->flags);
+- tasklet_schedule(&dd->done_task);
++static irqreturn_t omap_sham_irq_omap4(int irq, void *dev_id)
++{
++ struct omap_sham_dev *dd = dev_id;
+
+- return IRQ_HANDLED;
++ omap_sham_write_mask(dd, SHA_REG_MASK(dd), 0, SHA_REG_MASK_IT_EN);
++
++ return omap_sham_irq_common(dd);
+ }
+
++static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
++ .flags = BIT(FLAGS_BE32_SHA1),
++ .digest_size = SHA1_DIGEST_SIZE,
++ .copy_hash = omap_sham_copy_hash_omap2,
++ .write_ctrl = omap_sham_write_ctrl_omap2,
++ .trigger = omap_sham_trigger_omap2,
++ .poll_irq = omap_sham_poll_irq_omap2,
++ .intr_hdlr = omap_sham_irq_omap2,
++ .idigest_ofs = 0x00,
++ .din_ofs = 0x1c,
++ .digcnt_ofs = 0x14,
++ .rev_ofs = 0x5c,
++ .mask_ofs = 0x60,
++ .sysstatus_ofs = 0x64,
++ .major_mask = 0xf0,
++ .major_shift = 4,
++ .minor_mask = 0x0f,
++ .minor_shift = 0,
++};
++
+ #ifdef CONFIG_OF
++static const struct omap_sham_pdata omap_sham_pdata_omap4 = {
++ .flags = BIT(FLAGS_AUTO_XOR),
++ .digest_size = SHA256_DIGEST_SIZE,
++ .copy_hash = omap_sham_copy_hash_omap4,
++ .write_ctrl = omap_sham_write_ctrl_omap4,
++ .trigger = omap_sham_trigger_omap4,
++ .poll_irq = omap_sham_poll_irq_omap4,
++ .intr_hdlr = omap_sham_irq_omap4,
++ .idigest_ofs = 0x020,
++ .din_ofs = 0x080,
++ .digcnt_ofs = 0x040,
++ .rev_ofs = 0x100,
++ .mask_ofs = 0x110,
++ .sysstatus_ofs = 0x114,
++ .major_mask = 0x0700,
++ .major_shift = 8,
++ .minor_mask = 0x003f,
++ .minor_shift = 0,
++};
++
+ static const struct of_device_id omap_sham_of_match[] = {
+ {
+ .compatible = "ti,omap2-sham",
++ .data = &omap_sham_pdata_omap2,
++ },
++ {
++ .compatible = "ti,omap4-sham",
++ .data = &omap_sham_pdata_omap4,
+ },
+ {},
+ };
+@@ -1198,6 +1447,7 @@ static int omap_sham_get_res_of(struct omap_sham_dev *dd,
+ }
+
+ dd->dma = -1; /* Dummy value that's unused */
++ dd->pdata = match->data;
+
+ err:
+ return err;
+@@ -1243,6 +1493,9 @@ static int omap_sham_get_res_pdev(struct omap_sham_dev *dd,
+ }
+ dd->dma = r->start;
+
++ /* Only OMAP2/3 can be non-DT */
++ dd->pdata = &omap_sham_pdata_omap2;
++
+ err:
+ return err;
+ }
+@@ -1254,6 +1507,7 @@ static int omap_sham_probe(struct platform_device *pdev)
+ struct resource res;
+ dma_cap_mask_t mask;
+ int err, i, j;
++ u32 rev;
+
+ dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL);
+ if (dd == NULL) {
+@@ -1282,8 +1536,8 @@ static int omap_sham_probe(struct platform_device *pdev)
+ }
+ dd->phys_base = res.start;
+
+- err = request_irq(dd->irq, omap_sham_irq,
+- IRQF_TRIGGER_LOW, dev_name(dev), dd);
++ err = request_irq(dd->irq, dd->pdata->intr_hdlr, IRQF_TRIGGER_LOW,
++ dev_name(dev), dd);
+ if (err) {
+ dev_err(dev, "unable to request irq.\n");
+ goto res_err;
+@@ -1301,21 +1555,16 @@ static int omap_sham_probe(struct platform_device *pdev)
+ goto dma_err;
+ }
+
+- dd->io_base = ioremap(dd->phys_base, SZ_4K);
+- if (!dd->io_base) {
+- dev_err(dev, "can't ioremap\n");
+- err = -ENOMEM;
+- goto io_err;
+- }
++ dd->flags |= dd->pdata->flags;
+
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
++ rev = omap_sham_read(dd, SHA_REG_REV(dd));
++ pm_runtime_put_sync(&pdev->dev);
+
+ dev_info(dev, "hw accel on OMAP rev %u.%u\n",
+- (omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MAJOR) >> 4,
+- omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MINOR);
+-
+- pm_runtime_put_sync(&pdev->dev);
++ (rev & dd->pdata->major_mask) >> dd->pdata->major_shift,
++ (rev & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
+
+ spin_lock(&sham.lock);
+ list_add_tail(&dd->list, &sham.dev_list);
+@@ -1333,7 +1582,6 @@ err_algs:
+ for (j = 0; j < i; j++)
+ crypto_unregister_ahash(&algs[j]);
+ pm_runtime_disable(dev);
+-io_err:
+ dma_release_channel(dd->dma_lch);
+ dma_err:
+ free_irq(dd->irq, dd);
diff --git a/patches/linux-3.8.13/0153-crypto-omap-sham-Add-SHA224-and-SHA256-Support.patch b/patches/linux-3.8.13/0153-crypto-omap-sham-Add-SHA224-and-SHA256-Support.patch
new file mode 100644
index 0000000..b695641
--- /dev/null
+++ b/patches/linux-3.8.13/0153-crypto-omap-sham-Add-SHA224-and-SHA256-Support.patch
@@ -0,0 +1,310 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Tue, 18 Dec 2012 21:50:08 -0700
+Subject: [PATCH] crypto: omap-sham - Add SHA224 and SHA256 Support
+
+The OMAP4/AM33xx version of the SHAM crypto module
+supports SHA224 and SHA256 in addition to MD5 and
+SHA1 that the OMAP2 version of the module supports.
+
+To add this support, use the platform_data introduced
+in an ealier commit to hold the list of algorithms
+supported by the current module. The probe routine
+will use that list to register the correct algorithms.
+
+Note: The code being integrated is from the TI AM33xx SDK
+and was written by Greg Turner <gkmturner@gmail.com> and
+Herman Schuurman (current email unknown) while at TI.
+
+CC: Greg Turner <gkmturner@gmail.com>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-sham.c | 183 +++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 173 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
+index c8bfe71..696a7d5 100644
+--- a/drivers/crypto/omap-sham.c
++++ b/drivers/crypto/omap-sham.c
+@@ -83,6 +83,8 @@
+ #define SHA_REG_MODE_ALGO_MASK (3 << 1)
+ #define SHA_REG_MODE_ALGO_MD5_128 (0 << 1)
+ #define SHA_REG_MODE_ALGO_SHA1_160 (1 << 1)
++#define SHA_REG_MODE_ALGO_SHA2_224 (2 << 1)
++#define SHA_REG_MODE_ALGO_SHA2_256 (3 << 1)
+
+ #define SHA_REG_LENGTH 0x48
+
+@@ -121,6 +123,10 @@
+ << (FLAGS_MODE_SHIFT - 1))
+ #define FLAGS_MODE_SHA1 (SHA_REG_MODE_ALGO_SHA1_160 \
+ << (FLAGS_MODE_SHIFT - 1))
++#define FLAGS_MODE_SHA224 (SHA_REG_MODE_ALGO_SHA2_224 \
++ << (FLAGS_MODE_SHIFT - 1))
++#define FLAGS_MODE_SHA256 (SHA_REG_MODE_ALGO_SHA2_256 \
++ << (FLAGS_MODE_SHIFT - 1))
+ #define FLAGS_HMAC 20
+ #define FLAGS_ERROR 21
+
+@@ -173,7 +179,15 @@ struct omap_sham_ctx {
+
+ #define OMAP_SHAM_QUEUE_LENGTH 1
+
++struct omap_sham_algs_info {
++ struct ahash_alg *algs_list;
++ unsigned int size;
++ unsigned int registered;
++};
++
+ struct omap_sham_pdata {
++ struct omap_sham_algs_info *algs_info;
++ unsigned int algs_info_size;
+ unsigned long flags;
+ int digest_size;
+
+@@ -322,6 +336,12 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
+ big_endian = 1;
+ d = SHA1_DIGEST_SIZE / sizeof(u32);
+ break;
++ case FLAGS_MODE_SHA224:
++ d = SHA224_DIGEST_SIZE / sizeof(u32);
++ break;
++ case FLAGS_MODE_SHA256:
++ d = SHA256_DIGEST_SIZE / sizeof(u32);
++ break;
+ default:
+ d = 0;
+ }
+@@ -780,6 +800,12 @@ static int omap_sham_init(struct ahash_request *req)
+ case SHA1_DIGEST_SIZE:
+ ctx->flags |= FLAGS_MODE_SHA1;
+ break;
++ case SHA224_DIGEST_SIZE:
++ ctx->flags |= FLAGS_MODE_SHA224;
++ break;
++ case SHA256_DIGEST_SIZE:
++ ctx->flags |= FLAGS_MODE_SHA256;
++ break;
+ }
+
+ ctx->bufcnt = 0;
+@@ -1173,6 +1199,16 @@ static int omap_sham_cra_sha1_init(struct crypto_tfm *tfm)
+ return omap_sham_cra_init_alg(tfm, "sha1");
+ }
+
++static int omap_sham_cra_sha224_init(struct crypto_tfm *tfm)
++{
++ return omap_sham_cra_init_alg(tfm, "sha224");
++}
++
++static int omap_sham_cra_sha256_init(struct crypto_tfm *tfm)
++{
++ return omap_sham_cra_init_alg(tfm, "sha256");
++}
++
+ static int omap_sham_cra_md5_init(struct crypto_tfm *tfm)
+ {
+ return omap_sham_cra_init_alg(tfm, "md5");
+@@ -1191,7 +1227,7 @@ static void omap_sham_cra_exit(struct crypto_tfm *tfm)
+ }
+ }
+
+-static struct ahash_alg algs[] = {
++static struct ahash_alg algs_sha1_md5[] = {
+ {
+ .init = omap_sham_init,
+ .update = omap_sham_update,
+@@ -1290,6 +1326,102 @@ static struct ahash_alg algs[] = {
+ }
+ };
+
++/* OMAP4 has some algs in addition to what OMAP2 has */
++static struct ahash_alg algs_sha224_sha256[] = {
++{
++ .init = omap_sham_init,
++ .update = omap_sham_update,
++ .final = omap_sham_final,
++ .finup = omap_sham_finup,
++ .digest = omap_sham_digest,
++ .halg.digestsize = SHA224_DIGEST_SIZE,
++ .halg.base = {
++ .cra_name = "sha224",
++ .cra_driver_name = "omap-sha224",
++ .cra_priority = 100,
++ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_NEED_FALLBACK,
++ .cra_blocksize = SHA224_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct omap_sham_ctx),
++ .cra_alignmask = 0,
++ .cra_module = THIS_MODULE,
++ .cra_init = omap_sham_cra_init,
++ .cra_exit = omap_sham_cra_exit,
++ }
++},
++{
++ .init = omap_sham_init,
++ .update = omap_sham_update,
++ .final = omap_sham_final,
++ .finup = omap_sham_finup,
++ .digest = omap_sham_digest,
++ .halg.digestsize = SHA256_DIGEST_SIZE,
++ .halg.base = {
++ .cra_name = "sha256",
++ .cra_driver_name = "omap-sha256",
++ .cra_priority = 100,
++ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_NEED_FALLBACK,
++ .cra_blocksize = SHA256_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct omap_sham_ctx),
++ .cra_alignmask = 0,
++ .cra_module = THIS_MODULE,
++ .cra_init = omap_sham_cra_init,
++ .cra_exit = omap_sham_cra_exit,
++ }
++},
++{
++ .init = omap_sham_init,
++ .update = omap_sham_update,
++ .final = omap_sham_final,
++ .finup = omap_sham_finup,
++ .digest = omap_sham_digest,
++ .setkey = omap_sham_setkey,
++ .halg.digestsize = SHA224_DIGEST_SIZE,
++ .halg.base = {
++ .cra_name = "hmac(sha224)",
++ .cra_driver_name = "omap-hmac-sha224",
++ .cra_priority = 100,
++ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_NEED_FALLBACK,
++ .cra_blocksize = SHA224_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct omap_sham_ctx) +
++ sizeof(struct omap_sham_hmac_ctx),
++ .cra_alignmask = OMAP_ALIGN_MASK,
++ .cra_module = THIS_MODULE,
++ .cra_init = omap_sham_cra_sha224_init,
++ .cra_exit = omap_sham_cra_exit,
++ }
++},
++{
++ .init = omap_sham_init,
++ .update = omap_sham_update,
++ .final = omap_sham_final,
++ .finup = omap_sham_finup,
++ .digest = omap_sham_digest,
++ .setkey = omap_sham_setkey,
++ .halg.digestsize = SHA256_DIGEST_SIZE,
++ .halg.base = {
++ .cra_name = "hmac(sha256)",
++ .cra_driver_name = "omap-hmac-sha256",
++ .cra_priority = 100,
++ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_NEED_FALLBACK,
++ .cra_blocksize = SHA256_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct omap_sham_ctx) +
++ sizeof(struct omap_sham_hmac_ctx),
++ .cra_alignmask = OMAP_ALIGN_MASK,
++ .cra_module = THIS_MODULE,
++ .cra_init = omap_sham_cra_sha256_init,
++ .cra_exit = omap_sham_cra_exit,
++ }
++},
++};
++
+ static void omap_sham_done_task(unsigned long data)
+ {
+ struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
+@@ -1364,7 +1496,16 @@ static irqreturn_t omap_sham_irq_omap4(int irq, void *dev_id)
+ return omap_sham_irq_common(dd);
+ }
+
++static struct omap_sham_algs_info omap_sham_algs_info_omap2[] = {
++ {
++ .algs_list = algs_sha1_md5,
++ .size = ARRAY_SIZE(algs_sha1_md5),
++ },
++};
++
+ static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
++ .algs_info = omap_sham_algs_info_omap2,
++ .algs_info_size = ARRAY_SIZE(omap_sham_algs_info_omap2),
+ .flags = BIT(FLAGS_BE32_SHA1),
+ .digest_size = SHA1_DIGEST_SIZE,
+ .copy_hash = omap_sham_copy_hash_omap2,
+@@ -1385,7 +1526,20 @@ static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
+ };
+
+ #ifdef CONFIG_OF
++static struct omap_sham_algs_info omap_sham_algs_info_omap4[] = {
++ {
++ .algs_list = algs_sha1_md5,
++ .size = ARRAY_SIZE(algs_sha1_md5),
++ },
++ {
++ .algs_list = algs_sha224_sha256,
++ .size = ARRAY_SIZE(algs_sha224_sha256),
++ },
++};
++
+ static const struct omap_sham_pdata omap_sham_pdata_omap4 = {
++ .algs_info = omap_sham_algs_info_omap4,
++ .algs_info_size = ARRAY_SIZE(omap_sham_algs_info_omap4),
+ .flags = BIT(FLAGS_AUTO_XOR),
+ .digest_size = SHA256_DIGEST_SIZE,
+ .copy_hash = omap_sham_copy_hash_omap4,
+@@ -1570,17 +1724,24 @@ static int omap_sham_probe(struct platform_device *pdev)
+ list_add_tail(&dd->list, &sham.dev_list);
+ spin_unlock(&sham.lock);
+
+- for (i = 0; i < ARRAY_SIZE(algs); i++) {
+- err = crypto_register_ahash(&algs[i]);
+- if (err)
+- goto err_algs;
++ for (i = 0; i < dd->pdata->algs_info_size; i++) {
++ for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
++ err = crypto_register_ahash(
++ &dd->pdata->algs_info[i].algs_list[j]);
++ if (err)
++ goto err_algs;
++
++ dd->pdata->algs_info[i].registered++;
++ }
+ }
+
+ return 0;
+
+ err_algs:
+- for (j = 0; j < i; j++)
+- crypto_unregister_ahash(&algs[j]);
++ for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
++ for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
++ crypto_unregister_ahash(
++ &dd->pdata->algs_info[i].algs_list[j]);
+ pm_runtime_disable(dev);
+ dma_release_channel(dd->dma_lch);
+ dma_err:
+@@ -1597,7 +1758,7 @@ data_err:
+ static int omap_sham_remove(struct platform_device *pdev)
+ {
+ static struct omap_sham_dev *dd;
+- int i;
++ int i, j;
+
+ dd = platform_get_drvdata(pdev);
+ if (!dd)
+@@ -1605,8 +1766,10 @@ static int omap_sham_remove(struct platform_device *pdev)
+ spin_lock(&sham.lock);
+ list_del(&dd->list);
+ spin_unlock(&sham.lock);
+- for (i = 0; i < ARRAY_SIZE(algs); i++)
+- crypto_unregister_ahash(&algs[i]);
++ for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
++ for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
++ crypto_unregister_ahash(
++ &dd->pdata->algs_info[i].algs_list[j]);
+ tasklet_kill(&dd->done_task);
+ pm_runtime_disable(&pdev->dev);
+ dma_release_channel(dd->dma_lch);
diff --git a/patches/linux-3.8.13/0154-crypto-omap-aes-Remmove-unnecessary-pr_info-noise.patch b/patches/linux-3.8.13/0154-crypto-omap-aes-Remmove-unnecessary-pr_info-noise.patch
new file mode 100644
index 0000000..d8be9ee
--- /dev/null
+++ b/patches/linux-3.8.13/0154-crypto-omap-aes-Remmove-unnecessary-pr_info-noise.patch
@@ -0,0 +1,35 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 20 Dec 2012 09:58:48 -0700
+Subject: [PATCH] crypto: omap-aes - Remmove unnecessary pr_info noise
+
+Remove the unnecessary pr_info() calls from omap_aes_probe()
+and omap_aes_mod_init().
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index e66e8ee..481da71 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -880,8 +880,6 @@ static int omap_aes_probe(struct platform_device *pdev)
+ goto err_algs;
+ }
+
+- pr_info("probe() done\n");
+-
+ return 0;
+ err_algs:
+ for (j = 0; j < i; j++)
+@@ -938,8 +936,6 @@ static struct platform_driver omap_aes_driver = {
+
+ static int __init omap_aes_mod_init(void)
+ {
+- pr_info("loading %s driver\n", "omap-aes");
+-
+ return platform_driver_register(&omap_aes_driver);
+ }
+
diff --git a/patches/linux-3.8.13/0155-crypto-omap-aes-Don-t-reset-controller-for-every-ope.patch b/patches/linux-3.8.13/0155-crypto-omap-aes-Don-t-reset-controller-for-every-ope.patch
new file mode 100644
index 0000000..6c07d75
--- /dev/null
+++ b/patches/linux-3.8.13/0155-crypto-omap-aes-Don-t-reset-controller-for-every-ope.patch
@@ -0,0 +1,60 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 28 Nov 2012 15:14:05 -0700
+Subject: [PATCH] crypto: omap-aes - Don't reset controller for every
+ operation
+
+The AES controller only needs to be reset once and that will
+be done by the hwmod infrastructure, if possible. Therefore,
+remove the reset code from the omap-aes driver.
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 27 ---------------------------
+ 1 file changed, 27 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index 481da71..33cd783 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -160,19 +160,6 @@ static void omap_aes_write_n(struct omap_aes_dev *dd, u32 offset,
+ omap_aes_write(dd, offset, *value);
+ }
+
+-static int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit)
+-{
+- unsigned long timeout = jiffies + DEFAULT_TIMEOUT;
+-
+- while (!(omap_aes_read(dd, offset) & bit)) {
+- if (time_is_before_jiffies(timeout)) {
+- dev_err(dd->dev, "omap-aes timeout\n");
+- return -ETIMEDOUT;
+- }
+- }
+- return 0;
+-}
+-
+ static int omap_aes_hw_init(struct omap_aes_dev *dd)
+ {
+ /*
+@@ -183,20 +170,6 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
+ clk_enable(dd->iclk);
+
+ if (!(dd->flags & FLAGS_INIT)) {
+- /* is it necessary to reset before every operation? */
+- omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET,
+- AES_REG_MASK_SOFTRESET);
+- /*
+- * prevent OCP bus error (SRESP) in case an access to the module
+- * is performed while the module is coming out of soft reset
+- */
+- __asm__ __volatile__("nop");
+- __asm__ __volatile__("nop");
+-
+- if (omap_aes_wait(dd, AES_REG_SYSSTATUS,
+- AES_REG_SYSSTATUS_RESETDONE))
+- return -ETIMEDOUT;
+-
+ dd->flags |= FLAGS_INIT;
+ dd->err = 0;
+ }
diff --git a/patches/linux-3.8.13/0156-crypto-omap-aes-Convert-to-use-pm_runtime-API.patch b/patches/linux-3.8.13/0156-crypto-omap-aes-Convert-to-use-pm_runtime-API.patch
new file mode 100644
index 0000000..f962ed6
--- /dev/null
+++ b/patches/linux-3.8.13/0156-crypto-omap-aes-Convert-to-use-pm_runtime-API.patch
@@ -0,0 +1,108 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Sun, 11 Nov 2012 21:00:37 -0700
+Subject: [PATCH] crypto: omap-aes - Convert to use pm_runtime API
+
+Convert the omap-aes crypto driver to use the
+pm_runtime API instead of the clk API.
+
+CC: Kevin Hilman <khilman@deeprootsystems.com>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 29 +++++++++++------------------
+ 1 file changed, 11 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index 33cd783..c229852 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -19,10 +19,10 @@
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/kernel.h>
+-#include <linux/clk.h>
+ #include <linux/platform_device.h>
+ #include <linux/scatterlist.h>
+ #include <linux/dma-mapping.h>
++#include <linux/pm_runtime.h>
+ #include <linux/io.h>
+ #include <linux/crypto.h>
+ #include <linux/interrupt.h>
+@@ -96,7 +96,6 @@ struct omap_aes_dev {
+ struct list_head list;
+ unsigned long phys_base;
+ void __iomem *io_base;
+- struct clk *iclk;
+ struct omap_aes_ctx *ctx;
+ struct device *dev;
+ unsigned long flags;
+@@ -167,7 +166,7 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
+ * It may be long delays between requests.
+ * Device might go to off mode to save power.
+ */
+- clk_enable(dd->iclk);
++ pm_runtime_get_sync(dd->dev);
+
+ if (!(dd->flags & FLAGS_INIT)) {
+ dd->flags |= FLAGS_INIT;
+@@ -518,7 +517,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
+
+ pr_debug("err: %d\n", err);
+
+- clk_disable(dd->iclk);
++ pm_runtime_put_sync(dd->dev);
+ dd->flags &= ~FLAGS_BUSY;
+
+ req->base.complete(&req->base, err);
+@@ -813,26 +812,21 @@ static int omap_aes_probe(struct platform_device *pdev)
+ else
+ dd->dma_in = res->start;
+
+- /* Initializing the clock */
+- dd->iclk = clk_get(dev, "ick");
+- if (IS_ERR(dd->iclk)) {
+- dev_err(dev, "clock intialization failed.\n");
+- err = PTR_ERR(dd->iclk);
+- goto err_res;
+- }
+-
+ dd->io_base = ioremap(dd->phys_base, SZ_4K);
+ if (!dd->io_base) {
+ dev_err(dev, "can't ioremap\n");
+ err = -ENOMEM;
+- goto err_io;
++ goto err_res;
+ }
+
+- clk_enable(dd->iclk);
++ pm_runtime_enable(dev);
++ pm_runtime_get_sync(dev);
++
+ reg = omap_aes_read(dd, AES_REG_REV);
+ dev_info(dev, "OMAP AES hw accel rev: %u.%u\n",
+ (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR);
+- clk_disable(dd->iclk);
++
++ pm_runtime_put_sync(dev);
+
+ tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
+ tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd);
+@@ -862,8 +856,7 @@ err_dma:
+ tasklet_kill(&dd->done_task);
+ tasklet_kill(&dd->queue_task);
+ iounmap(dd->io_base);
+-err_io:
+- clk_put(dd->iclk);
++ pm_runtime_disable(dev);
+ err_res:
+ kfree(dd);
+ dd = NULL;
+@@ -891,7 +884,7 @@ static int omap_aes_remove(struct platform_device *pdev)
+ tasklet_kill(&dd->queue_task);
+ omap_aes_dma_cleanup(dd);
+ iounmap(dd->io_base);
+- clk_put(dd->iclk);
++ pm_runtime_disable(dd->dev);
+ kfree(dd);
+ dd = NULL;
+
diff --git a/patches/linux-3.8.13/0157-crypto-omap-aes-Add-suspend-resume-support.patch b/patches/linux-3.8.13/0157-crypto-omap-aes-Add-suspend-resume-support.patch
new file mode 100644
index 0000000..35c1a40
--- /dev/null
+++ b/patches/linux-3.8.13/0157-crypto-omap-aes-Add-suspend-resume-support.patch
@@ -0,0 +1,48 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 20 Dec 2012 10:24:33 -0700
+Subject: [PATCH] crypto: omap-aes - Add suspend/resume support
+
+Add suspend/resume support to the OMAP AES driver.
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index c229852..3262139 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -891,12 +891,31 @@ static int omap_aes_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++#ifdef CONFIG_PM_SLEEP
++static int omap_aes_suspend(struct device *dev)
++{
++ pm_runtime_put_sync(dev);
++ return 0;
++}
++
++static int omap_aes_resume(struct device *dev)
++{
++ pm_runtime_get_sync(dev);
++ return 0;
++}
++#endif
++
++static const struct dev_pm_ops omap_aes_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(omap_aes_suspend, omap_aes_resume)
++};
++
+ static struct platform_driver omap_aes_driver = {
+ .probe = omap_aes_probe,
+ .remove = omap_aes_remove,
+ .driver = {
+ .name = "omap-aes",
+ .owner = THIS_MODULE,
++ .pm = &omap_aes_pm_ops,
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0158-crypto-omap-aes-Add-code-to-use-dmaengine-API.patch b/patches/linux-3.8.13/0158-crypto-omap-aes-Add-code-to-use-dmaengine-API.patch
new file mode 100644
index 0000000..0df4e50
--- /dev/null
+++ b/patches/linux-3.8.13/0158-crypto-omap-aes-Add-code-to-use-dmaengine-API.patch
@@ -0,0 +1,384 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Wed, 14 Nov 2012 09:30:10 -0700
+Subject: [PATCH] crypto: omap-aes - Add code to use dmaengine API
+
+Add code to use the new dmaengine API alongside
+the existing DMA code that uses the private
+OMAP DMA API. The API to use is chosen by
+defining or undefining 'OMAP_AES_DMA_PRIVATE'.
+
+CC: Russell King <rmk+kernel@arm.linux.org.uk>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 184 ++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 183 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index 3262139..14ec9e2 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -12,6 +12,8 @@
+ *
+ */
+
++#define OMAP_AES_DMA_PRIVATE
++
+ #define pr_fmt(fmt) "%s: " fmt, __func__
+
+ #include <linux/err.h>
+@@ -22,6 +24,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/scatterlist.h>
+ #include <linux/dma-mapping.h>
++#include <linux/dmaengine.h>
++#include <linux/omap-dma.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/io.h>
+ #include <linux/crypto.h>
+@@ -29,7 +33,8 @@
+ #include <crypto/scatterwalk.h>
+ #include <crypto/aes.h>
+
+-#include <linux/omap-dma.h>
++#define DST_MAXBURST 4
++#define DMA_MIN (DST_MAXBURST * sizeof(u32))
+
+ /* OMAP TRM gives bitfields as start:end, where start is the higher bit
+ number. For example 7:0 */
+@@ -110,19 +115,33 @@ struct omap_aes_dev {
+ struct ablkcipher_request *req;
+ size_t total;
+ struct scatterlist *in_sg;
++#ifndef OMAP_AES_DMA_PRIVATE
++ struct scatterlist in_sgl;
++#endif
+ size_t in_offset;
+ struct scatterlist *out_sg;
++#ifndef OMAP_AES_DMA_PRIVATE
++ struct scatterlist out_sgl;
++#endif
+ size_t out_offset;
+
+ size_t buflen;
+ void *buf_in;
+ size_t dma_size;
+ int dma_in;
++#ifdef OMAP_AES_DMA_PRIVATE
+ int dma_lch_in;
++#else
++ struct dma_chan *dma_lch_in;
++#endif
+ dma_addr_t dma_addr_in;
+ void *buf_out;
+ int dma_out;
++#ifdef OMAP_AES_DMA_PRIVATE
+ int dma_lch_out;
++#else
++ struct dma_chan *dma_lch_out;
++#endif
+ dma_addr_t dma_addr_out;
+ };
+
+@@ -187,10 +206,17 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+ return err;
+
+ val = 0;
++#ifdef OMAP_AES_DMA_PRIVATE
+ if (dd->dma_lch_out >= 0)
+ val |= AES_REG_MASK_DMA_OUT_EN;
+ if (dd->dma_lch_in >= 0)
+ val |= AES_REG_MASK_DMA_IN_EN;
++#else
++ if (dd->dma_lch_out != NULL)
++ val |= AES_REG_MASK_DMA_OUT_EN;
++ if (dd->dma_lch_in != NULL)
++ val |= AES_REG_MASK_DMA_IN_EN;
++#endif
+
+ mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN;
+
+@@ -218,6 +244,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+
+ omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ /* IN */
+ omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
+ dd->phys_base + AES_REG_DATA, 0, 4);
+@@ -231,6 +258,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+
+ omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+ omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
++#endif
+
+ return 0;
+ }
+@@ -256,6 +284,7 @@ static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
+ return dd;
+ }
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
+ {
+ struct omap_aes_dev *dd = data;
+@@ -271,13 +300,30 @@ static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
+ /* dma_lch_out - completed */
+ tasklet_schedule(&dd->done_task);
+ }
++#else
++static void omap_aes_dma_out_callback(void *data)
++{
++ struct omap_aes_dev *dd = data;
++
++ /* dma_lch_out - completed */
++ tasklet_schedule(&dd->done_task);
++}
++#endif
+
+ static int omap_aes_dma_init(struct omap_aes_dev *dd)
+ {
+ int err = -ENOMEM;
++#ifndef OMAP_AES_DMA_PRIVATE
++ dma_cap_mask_t mask;
++#endif
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ dd->dma_lch_out = -1;
+ dd->dma_lch_in = -1;
++#else
++ dd->dma_lch_out = NULL;
++ dd->dma_lch_in = NULL;
++#endif
+
+ dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
+ dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
+@@ -306,6 +352,7 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
+ goto err_map_out;
+ }
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ err = omap_request_dma(dd->dma_in, "omap-aes-rx",
+ omap_aes_dma_callback, dd, &dd->dma_lch_in);
+ if (err) {
+@@ -318,11 +365,33 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
+ dev_err(dd->dev, "Unable to request DMA channel\n");
+ goto err_dma_out;
+ }
++#else
++ dma_cap_zero(mask);
++ dma_cap_set(DMA_SLAVE, mask);
++
++ dd->dma_lch_in = dma_request_channel(mask, omap_dma_filter_fn,
++ &dd->dma_in);
++ if (!dd->dma_lch_in) {
++ dev_err(dd->dev, "Unable to request in DMA channel\n");
++ goto err_dma_in;
++ }
++
++ dd->dma_lch_out = dma_request_channel(mask, omap_dma_filter_fn,
++ &dd->dma_out);
++ if (!dd->dma_lch_out) {
++ dev_err(dd->dev, "Unable to request out DMA channel\n");
++ goto err_dma_out;
++ }
++#endif
+
+ return 0;
+
+ err_dma_out:
++#ifdef OMAP_AES_DMA_PRIVATE
+ omap_free_dma(dd->dma_lch_in);
++#else
++ dma_release_channel(dd->dma_lch_in);
++#endif
+ err_dma_in:
+ dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
+ DMA_FROM_DEVICE);
+@@ -339,8 +408,13 @@ err_alloc:
+
+ static void omap_aes_dma_cleanup(struct omap_aes_dev *dd)
+ {
++#ifdef OMAP_AES_DMA_PRIVATE
+ omap_free_dma(dd->dma_lch_out);
+ omap_free_dma(dd->dma_lch_in);
++#else
++ dma_release_channel(dd->dma_lch_out);
++ dma_release_channel(dd->dma_lch_in);
++#endif
+ dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE);
+@@ -398,12 +472,24 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf,
+ return off;
+ }
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
+ dma_addr_t dma_addr_out, int length)
++#else
++static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
++ struct scatterlist *in_sg, struct scatterlist *out_sg)
++#endif
+ {
+ struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct omap_aes_dev *dd = ctx->dd;
++#ifdef OMAP_AES_DMA_PRIVATE
+ int len32;
++#else
++ struct dma_async_tx_descriptor *tx_in, *tx_out;
++ struct dma_slave_config cfg;
++ dma_addr_t dma_addr_in = sg_dma_address(in_sg);
++ int ret, length = sg_dma_len(in_sg);
++#endif
+
+ pr_debug("len: %d\n", length);
+
+@@ -413,6 +499,7 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
+ dma_sync_single_for_device(dd->dev, dma_addr_in, length,
+ DMA_TO_DEVICE);
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ len32 = DIV_ROUND_UP(length, sizeof(u32));
+
+ /* IN */
+@@ -433,6 +520,60 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
+
+ omap_start_dma(dd->dma_lch_in);
+ omap_start_dma(dd->dma_lch_out);
++#else
++ memset(&cfg, 0, sizeof(cfg));
++
++ cfg.src_addr = dd->phys_base + AES_REG_DATA;
++ cfg.dst_addr = dd->phys_base + AES_REG_DATA;
++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ cfg.src_maxburst = DST_MAXBURST;
++ cfg.dst_maxburst = DST_MAXBURST;
++
++ /* IN */
++ ret = dmaengine_slave_config(dd->dma_lch_in, &cfg);
++ if (ret) {
++ dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
++ ret);
++ return ret;
++ }
++
++ tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, 1,
++ DMA_MEM_TO_DEV,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ if (!tx_in) {
++ dev_err(dd->dev, "IN prep_slave_sg() failed\n");
++ return -EINVAL;
++ }
++
++ /* No callback necessary */
++ tx_in->callback_param = dd;
++
++ /* OUT */
++ ret = dmaengine_slave_config(dd->dma_lch_out, &cfg);
++ if (ret) {
++ dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
++ ret);
++ return ret;
++ }
++
++ tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, 1,
++ DMA_DEV_TO_MEM,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ if (!tx_out) {
++ dev_err(dd->dev, "OUT prep_slave_sg() failed\n");
++ return -EINVAL;
++ }
++
++ tx_out->callback = omap_aes_dma_out_callback;
++ tx_out->callback_param = dd;
++
++ dmaengine_submit(tx_in);
++ dmaengine_submit(tx_out);
++
++ dma_async_issue_pending(dd->dma_lch_in);
++ dma_async_issue_pending(dd->dma_lch_out);
++#endif
+
+ /* start DMA or disable idle mode */
+ omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
+@@ -448,6 +589,10 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+ int err, fast = 0, in, out;
+ size_t count;
+ dma_addr_t addr_in, addr_out;
++#ifndef OMAP_AES_DMA_PRIVATE
++ struct scatterlist *in_sg, *out_sg;
++ int len32;
++#endif
+
+ pr_debug("total: %d\n", dd->total);
+
+@@ -486,6 +631,11 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+ addr_in = sg_dma_address(dd->in_sg);
+ addr_out = sg_dma_address(dd->out_sg);
+
++#ifndef OMAP_AES_DMA_PRIVATE
++ in_sg = dd->in_sg;
++ out_sg = dd->out_sg;
++#endif
++
+ dd->flags |= FLAGS_FAST;
+
+ } else {
+@@ -493,6 +643,29 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+ count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in,
+ dd->buflen, dd->total, 0);
+
++#ifndef OMAP_AES_DMA_PRIVATE
++ len32 = DIV_ROUND_UP(count, DMA_MIN) * DMA_MIN;
++
++ /*
++ * The data going into the AES module has been copied
++ * to a local buffer and the data coming out will go
++ * into a local buffer so set up local SG entries for
++ * both.
++ */
++ sg_init_table(&dd->in_sgl, 1);
++ dd->in_sgl.offset = dd->in_offset;
++ sg_dma_len(&dd->in_sgl) = len32;
++ sg_dma_address(&dd->in_sgl) = dd->dma_addr_in;
++
++ sg_init_table(&dd->out_sgl, 1);
++ dd->out_sgl.offset = dd->out_offset;
++ sg_dma_len(&dd->out_sgl) = len32;
++ sg_dma_address(&dd->out_sgl) = dd->dma_addr_out;
++
++ in_sg = &dd->in_sgl;
++ out_sg = &dd->out_sgl;
++#endif
++
+ addr_in = dd->dma_addr_in;
+ addr_out = dd->dma_addr_out;
+
+@@ -502,7 +675,11 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+
+ dd->total -= count;
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count);
++#else
++ err = omap_aes_crypt_dma(tfm, in_sg, out_sg);
++#endif
+ if (err) {
+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
+@@ -532,8 +709,13 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
+
+ omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);
+
++#ifdef OMAP_AES_DMA_PRIVATE
+ omap_stop_dma(dd->dma_lch_in);
+ omap_stop_dma(dd->dma_lch_out);
++#else
++ dmaengine_terminate_all(dd->dma_lch_in);
++ dmaengine_terminate_all(dd->dma_lch_out);
++#endif
+
+ if (dd->flags & FLAGS_FAST) {
+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
diff --git a/patches/linux-3.8.13/0159-crypto-omap-aes-Remove-usage-of-private-DMA-API.patch b/patches/linux-3.8.13/0159-crypto-omap-aes-Remove-usage-of-private-DMA-API.patch
new file mode 100644
index 0000000..1d183ca
--- /dev/null
+++ b/patches/linux-3.8.13/0159-crypto-omap-aes-Remove-usage-of-private-DMA-API.patch
@@ -0,0 +1,327 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 15 Nov 2012 22:11:36 -0700
+Subject: [PATCH] crypto: omap-aes - Remove usage of private DMA API
+
+Remove usage of the private OMAP DMA API.
+The dmaengine API will be used instead.
+
+CC: Russell King <rmk+kernel@arm.linux.org.uk>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 133 ---------------------------------------------
+ 1 file changed, 133 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index 14ec9e2..faf522f 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -12,8 +12,6 @@
+ *
+ */
+
+-#define OMAP_AES_DMA_PRIVATE
+-
+ #define pr_fmt(fmt) "%s: " fmt, __func__
+
+ #include <linux/err.h>
+@@ -115,33 +113,21 @@ struct omap_aes_dev {
+ struct ablkcipher_request *req;
+ size_t total;
+ struct scatterlist *in_sg;
+-#ifndef OMAP_AES_DMA_PRIVATE
+ struct scatterlist in_sgl;
+-#endif
+ size_t in_offset;
+ struct scatterlist *out_sg;
+-#ifndef OMAP_AES_DMA_PRIVATE
+ struct scatterlist out_sgl;
+-#endif
+ size_t out_offset;
+
+ size_t buflen;
+ void *buf_in;
+ size_t dma_size;
+ int dma_in;
+-#ifdef OMAP_AES_DMA_PRIVATE
+- int dma_lch_in;
+-#else
+ struct dma_chan *dma_lch_in;
+-#endif
+ dma_addr_t dma_addr_in;
+ void *buf_out;
+ int dma_out;
+-#ifdef OMAP_AES_DMA_PRIVATE
+- int dma_lch_out;
+-#else
+ struct dma_chan *dma_lch_out;
+-#endif
+ dma_addr_t dma_addr_out;
+ };
+
+@@ -206,17 +192,10 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+ return err;
+
+ val = 0;
+-#ifdef OMAP_AES_DMA_PRIVATE
+- if (dd->dma_lch_out >= 0)
+- val |= AES_REG_MASK_DMA_OUT_EN;
+- if (dd->dma_lch_in >= 0)
+- val |= AES_REG_MASK_DMA_IN_EN;
+-#else
+ if (dd->dma_lch_out != NULL)
+ val |= AES_REG_MASK_DMA_OUT_EN;
+ if (dd->dma_lch_in != NULL)
+ val |= AES_REG_MASK_DMA_IN_EN;
+-#endif
+
+ mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN;
+
+@@ -244,22 +223,6 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+
+ omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+- /* IN */
+- omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
+- dd->phys_base + AES_REG_DATA, 0, 4);
+-
+- omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+- omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+-
+- /* OUT */
+- omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
+- dd->phys_base + AES_REG_DATA, 0, 4);
+-
+- omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+- omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+-#endif
+-
+ return 0;
+ }
+
+@@ -284,23 +247,6 @@ static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
+ return dd;
+ }
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+-static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
+-{
+- struct omap_aes_dev *dd = data;
+-
+- if (ch_status != OMAP_DMA_BLOCK_IRQ) {
+- pr_err("omap-aes DMA error status: 0x%hx\n", ch_status);
+- dd->err = -EIO;
+- dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
+- } else if (lch == dd->dma_lch_in) {
+- return;
+- }
+-
+- /* dma_lch_out - completed */
+- tasklet_schedule(&dd->done_task);
+-}
+-#else
+ static void omap_aes_dma_out_callback(void *data)
+ {
+ struct omap_aes_dev *dd = data;
+@@ -308,22 +254,14 @@ static void omap_aes_dma_out_callback(void *data)
+ /* dma_lch_out - completed */
+ tasklet_schedule(&dd->done_task);
+ }
+-#endif
+
+ static int omap_aes_dma_init(struct omap_aes_dev *dd)
+ {
+ int err = -ENOMEM;
+-#ifndef OMAP_AES_DMA_PRIVATE
+ dma_cap_mask_t mask;
+-#endif
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+- dd->dma_lch_out = -1;
+- dd->dma_lch_in = -1;
+-#else
+ dd->dma_lch_out = NULL;
+ dd->dma_lch_in = NULL;
+-#endif
+
+ dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
+ dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
+@@ -352,20 +290,6 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
+ goto err_map_out;
+ }
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+- err = omap_request_dma(dd->dma_in, "omap-aes-rx",
+- omap_aes_dma_callback, dd, &dd->dma_lch_in);
+- if (err) {
+- dev_err(dd->dev, "Unable to request DMA channel\n");
+- goto err_dma_in;
+- }
+- err = omap_request_dma(dd->dma_out, "omap-aes-tx",
+- omap_aes_dma_callback, dd, &dd->dma_lch_out);
+- if (err) {
+- dev_err(dd->dev, "Unable to request DMA channel\n");
+- goto err_dma_out;
+- }
+-#else
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+@@ -382,16 +306,11 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
+ dev_err(dd->dev, "Unable to request out DMA channel\n");
+ goto err_dma_out;
+ }
+-#endif
+
+ return 0;
+
+ err_dma_out:
+-#ifdef OMAP_AES_DMA_PRIVATE
+- omap_free_dma(dd->dma_lch_in);
+-#else
+ dma_release_channel(dd->dma_lch_in);
+-#endif
+ err_dma_in:
+ dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
+ DMA_FROM_DEVICE);
+@@ -408,13 +327,8 @@ err_alloc:
+
+ static void omap_aes_dma_cleanup(struct omap_aes_dev *dd)
+ {
+-#ifdef OMAP_AES_DMA_PRIVATE
+- omap_free_dma(dd->dma_lch_out);
+- omap_free_dma(dd->dma_lch_in);
+-#else
+ dma_release_channel(dd->dma_lch_out);
+ dma_release_channel(dd->dma_lch_in);
+-#endif
+ dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE);
+@@ -472,24 +386,15 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf,
+ return off;
+ }
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+-static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
+- dma_addr_t dma_addr_out, int length)
+-#else
+ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
+ struct scatterlist *in_sg, struct scatterlist *out_sg)
+-#endif
+ {
+ struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct omap_aes_dev *dd = ctx->dd;
+-#ifdef OMAP_AES_DMA_PRIVATE
+- int len32;
+-#else
+ struct dma_async_tx_descriptor *tx_in, *tx_out;
+ struct dma_slave_config cfg;
+ dma_addr_t dma_addr_in = sg_dma_address(in_sg);
+ int ret, length = sg_dma_len(in_sg);
+-#endif
+
+ pr_debug("len: %d\n", length);
+
+@@ -499,28 +404,6 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
+ dma_sync_single_for_device(dd->dev, dma_addr_in, length,
+ DMA_TO_DEVICE);
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+- len32 = DIV_ROUND_UP(length, sizeof(u32));
+-
+- /* IN */
+- omap_set_dma_transfer_params(dd->dma_lch_in, OMAP_DMA_DATA_TYPE_S32,
+- len32, 1, OMAP_DMA_SYNC_PACKET, dd->dma_in,
+- OMAP_DMA_DST_SYNC);
+-
+- omap_set_dma_src_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_POST_INC,
+- dma_addr_in, 0, 0);
+-
+- /* OUT */
+- omap_set_dma_transfer_params(dd->dma_lch_out, OMAP_DMA_DATA_TYPE_S32,
+- len32, 1, OMAP_DMA_SYNC_PACKET,
+- dd->dma_out, OMAP_DMA_SRC_SYNC);
+-
+- omap_set_dma_dest_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_POST_INC,
+- dma_addr_out, 0, 0);
+-
+- omap_start_dma(dd->dma_lch_in);
+- omap_start_dma(dd->dma_lch_out);
+-#else
+ memset(&cfg, 0, sizeof(cfg));
+
+ cfg.src_addr = dd->phys_base + AES_REG_DATA;
+@@ -573,7 +456,6 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
+
+ dma_async_issue_pending(dd->dma_lch_in);
+ dma_async_issue_pending(dd->dma_lch_out);
+-#endif
+
+ /* start DMA or disable idle mode */
+ omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
+@@ -589,10 +471,8 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+ int err, fast = 0, in, out;
+ size_t count;
+ dma_addr_t addr_in, addr_out;
+-#ifndef OMAP_AES_DMA_PRIVATE
+ struct scatterlist *in_sg, *out_sg;
+ int len32;
+-#endif
+
+ pr_debug("total: %d\n", dd->total);
+
+@@ -631,10 +511,8 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+ addr_in = sg_dma_address(dd->in_sg);
+ addr_out = sg_dma_address(dd->out_sg);
+
+-#ifndef OMAP_AES_DMA_PRIVATE
+ in_sg = dd->in_sg;
+ out_sg = dd->out_sg;
+-#endif
+
+ dd->flags |= FLAGS_FAST;
+
+@@ -643,7 +521,6 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+ count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in,
+ dd->buflen, dd->total, 0);
+
+-#ifndef OMAP_AES_DMA_PRIVATE
+ len32 = DIV_ROUND_UP(count, DMA_MIN) * DMA_MIN;
+
+ /*
+@@ -664,7 +541,6 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+
+ in_sg = &dd->in_sgl;
+ out_sg = &dd->out_sgl;
+-#endif
+
+ addr_in = dd->dma_addr_in;
+ addr_out = dd->dma_addr_out;
+@@ -675,11 +551,7 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
+
+ dd->total -= count;
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+- err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count);
+-#else
+ err = omap_aes_crypt_dma(tfm, in_sg, out_sg);
+-#endif
+ if (err) {
+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
+@@ -709,13 +581,8 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
+
+ omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);
+
+-#ifdef OMAP_AES_DMA_PRIVATE
+- omap_stop_dma(dd->dma_lch_in);
+- omap_stop_dma(dd->dma_lch_out);
+-#else
+ dmaengine_terminate_all(dd->dma_lch_in);
+ dmaengine_terminate_all(dd->dma_lch_out);
+-#endif
+
+ if (dd->flags & FLAGS_FAST) {
+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
diff --git a/patches/linux-3.8.13/0160-crypto-omap-aes-Add-Device-Tree-Support.patch b/patches/linux-3.8.13/0160-crypto-omap-aes-Add-Device-Tree-Support.patch
new file mode 100644
index 0000000..d4dba9f
--- /dev/null
+++ b/patches/linux-3.8.13/0160-crypto-omap-aes-Add-Device-Tree-Support.patch
@@ -0,0 +1,194 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 20 Dec 2012 13:40:47 -0700
+Subject: [PATCH] crypto: omap-aes - Add Device Tree Support
+
+Add Device Tree suport to the omap-aes crypto
+driver. Currently, only support for OMAP2 and
+OMAP3 is being added but support for OMAP4 will
+be added in a subsequent patch.
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 123 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 97 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index faf522f..dfebd40 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -25,6 +25,9 @@
+ #include <linux/dmaengine.h>
+ #include <linux/omap-dma.h>
+ #include <linux/pm_runtime.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_address.h>
+ #include <linux/io.h>
+ #include <linux/crypto.h>
+ #include <linux/interrupt.h>
+@@ -819,11 +822,97 @@ static struct crypto_alg algs[] = {
+ }
+ };
+
++#ifdef CONFIG_OF
++static const struct of_device_id omap_aes_of_match[] = {
++ {
++ .compatible = "ti,omap2-aes",
++ },
++ {},
++};
++MODULE_DEVICE_TABLE(of, omap_aes_of_match);
++
++static int omap_aes_get_res_of(struct omap_aes_dev *dd,
++ struct device *dev, struct resource *res)
++{
++ struct device_node *node = dev->of_node;
++ const struct of_device_id *match;
++ int err = 0;
++
++ match = of_match_device(of_match_ptr(omap_aes_of_match), dev);
++ if (!match) {
++ dev_err(dev, "no compatible OF match\n");
++ err = -EINVAL;
++ goto err;
++ }
++
++ err = of_address_to_resource(node, 0, res);
++ if (err < 0) {
++ dev_err(dev, "can't translate OF node address\n");
++ err = -EINVAL;
++ goto err;
++ }
++
++ dd->dma_out = -1; /* Dummy value that's unused */
++ dd->dma_in = -1; /* Dummy value that's unused */
++
++err:
++ return err;
++}
++#else
++static const struct of_device_id omap_aes_of_match[] = {
++ {},
++};
++
++static int omap_aes_get_res_of(struct omap_aes_dev *dd,
++ struct device *dev, struct resource *res)
++{
++ return -EINVAL;
++}
++#endif
++
++static int omap_aes_get_res_pdev(struct omap_aes_dev *dd,
++ struct platform_device *pdev, struct resource *res)
++{
++ struct device *dev = &pdev->dev;
++ struct resource *r;
++ int err = 0;
++
++ /* Get the base address */
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!r) {
++ dev_err(dev, "no MEM resource info\n");
++ err = -ENODEV;
++ goto err;
++ }
++ memcpy(res, r, sizeof(*res));
++
++ /* Get the DMA out channel */
++ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
++ if (!r) {
++ dev_err(dev, "no DMA out resource info\n");
++ err = -ENODEV;
++ goto err;
++ }
++ dd->dma_out = r->start;
++
++ /* Get the DMA in channel */
++ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
++ if (!r) {
++ dev_err(dev, "no DMA in resource info\n");
++ err = -ENODEV;
++ goto err;
++ }
++ dd->dma_in = r->start;
++
++err:
++ return err;
++}
++
+ static int omap_aes_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct omap_aes_dev *dd;
+- struct resource *res;
++ struct resource res;
+ int err = -ENOMEM, i, j;
+ u32 reg;
+
+@@ -838,35 +927,18 @@ static int omap_aes_probe(struct platform_device *pdev)
+ spin_lock_init(&dd->lock);
+ crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH);
+
+- /* Get the base address */
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- dev_err(dev, "invalid resource type\n");
+- err = -ENODEV;
++ err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) :
++ omap_aes_get_res_pdev(dd, pdev, &res);
++ if (err)
+ goto err_res;
+- }
+- dd->phys_base = res->start;
+-
+- /* Get the DMA */
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+- if (!res)
+- dev_info(dev, "no DMA info\n");
+- else
+- dd->dma_out = res->start;
+-
+- /* Get the DMA */
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+- if (!res)
+- dev_info(dev, "no DMA info\n");
+- else
+- dd->dma_in = res->start;
+-
+- dd->io_base = ioremap(dd->phys_base, SZ_4K);
++
++ dd->io_base = devm_request_and_ioremap(dev, &res);
+ if (!dd->io_base) {
+ dev_err(dev, "can't ioremap\n");
+ err = -ENOMEM;
+ goto err_res;
+ }
++ dd->phys_base = res.start;
+
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+@@ -904,7 +976,6 @@ err_algs:
+ err_dma:
+ tasklet_kill(&dd->done_task);
+ tasklet_kill(&dd->queue_task);
+- iounmap(dd->io_base);
+ pm_runtime_disable(dev);
+ err_res:
+ kfree(dd);
+@@ -932,7 +1003,6 @@ static int omap_aes_remove(struct platform_device *pdev)
+ tasklet_kill(&dd->done_task);
+ tasklet_kill(&dd->queue_task);
+ omap_aes_dma_cleanup(dd);
+- iounmap(dd->io_base);
+ pm_runtime_disable(dd->dev);
+ kfree(dd);
+ dd = NULL;
+@@ -965,6 +1035,7 @@ static struct platform_driver omap_aes_driver = {
+ .name = "omap-aes",
+ .owner = THIS_MODULE,
+ .pm = &omap_aes_pm_ops,
++ .of_match_table = omap_aes_of_match,
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0161-crypto-omap-aes-Convert-to-dma_request_slave_channel.patch b/patches/linux-3.8.13/0161-crypto-omap-aes-Convert-to-dma_request_slave_channel.patch
new file mode 100644
index 0000000..8eebf49
--- /dev/null
+++ b/patches/linux-3.8.13/0161-crypto-omap-aes-Convert-to-dma_request_slave_channel.patch
@@ -0,0 +1,43 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 20 Dec 2012 14:05:57 -0700
+Subject: [PATCH] crypto: omap-aes - Convert to
+ dma_request_slave_channel_compat()
+
+Use the dma_request_slave_channel_compat() call instead of
+the dma_request_channel() call to request a DMA channel.
+This allows the omap-aes driver use different DMA engines.
+
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index dfebd40..d34aa5d 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -296,15 +296,19 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+- dd->dma_lch_in = dma_request_channel(mask, omap_dma_filter_fn,
+- &dd->dma_in);
++ dd->dma_lch_in = dma_request_slave_channel_compat(mask,
++ omap_dma_filter_fn,
++ &dd->dma_in,
++ dd->dev, "rx");
+ if (!dd->dma_lch_in) {
+ dev_err(dd->dev, "Unable to request in DMA channel\n");
+ goto err_dma_in;
+ }
+
+- dd->dma_lch_out = dma_request_channel(mask, omap_dma_filter_fn,
+- &dd->dma_out);
++ dd->dma_lch_out = dma_request_slave_channel_compat(mask,
++ omap_dma_filter_fn,
++ &dd->dma_out,
++ dd->dev, "tx");
+ if (!dd->dma_lch_out) {
+ dev_err(dd->dev, "Unable to request out DMA channel\n");
+ goto err_dma_out;
diff --git a/patches/linux-3.8.13/0162-crypto-omap-aes-Add-OMAP4-AM33XX-AES-Support.patch b/patches/linux-3.8.13/0162-crypto-omap-aes-Add-OMAP4-AM33XX-AES-Support.patch
new file mode 100644
index 0000000..85fa086
--- /dev/null
+++ b/patches/linux-3.8.13/0162-crypto-omap-aes-Add-OMAP4-AM33XX-AES-Support.patch
@@ -0,0 +1,315 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 20 Dec 2012 14:41:15 -0700
+Subject: [PATCH] crypto: omap-aes - Add OMAP4/AM33XX AES Support
+
+Add support for the OMAP4 version of the AES module
+that is present on OMAP4 and AM33xx SoCs.
+
+The modules have several differences including register
+offsets and how DMA is triggered. To handle these
+differences, a platform_data structure is defined and
+contains routine pointers, register offsets, and bit
+offsets within registers. OMAP2/OMAP3-specific routines
+are suffixed with '_omap2' and OMAP4/AM33xx routines are
+suffixed with '_omap4'.
+
+Note: The code being integrated is from the TI AM33xx SDK
+and was written by Greg Turner <gkmturner@gmail.com> and
+Herman Schuurman (current email unknown) while at TI.
+
+CC: Greg Turner <gkmturner@gmail.com>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 158 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 125 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index d34aa5d..bd1ad97 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (c) 2010 Nokia Corporation
+ * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
++ * Copyright (c) 2011 Texas Instruments Incorporated
+ *
+ * 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
+@@ -42,10 +43,11 @@
+ #define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
+ #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+
+-#define AES_REG_KEY(x) (0x1C - ((x ^ 0x01) * 0x04))
+-#define AES_REG_IV(x) (0x20 + ((x) * 0x04))
++#define AES_REG_KEY(dd, x) ((dd)->pdata->key_ofs - \
++ ((x ^ 0x01) * 0x04))
++#define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04))
+
+-#define AES_REG_CTRL 0x30
++#define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs)
+ #define AES_REG_CTRL_CTR_WIDTH (1 << 7)
+ #define AES_REG_CTRL_CTR (1 << 6)
+ #define AES_REG_CTRL_CBC (1 << 5)
+@@ -54,14 +56,11 @@
+ #define AES_REG_CTRL_INPUT_READY (1 << 1)
+ #define AES_REG_CTRL_OUTPUT_READY (1 << 0)
+
+-#define AES_REG_DATA 0x34
+-#define AES_REG_DATA_N(x) (0x34 + ((x) * 0x04))
++#define AES_REG_DATA_N(dd, x) ((dd)->pdata->data_ofs + ((x) * 0x04))
+
+-#define AES_REG_REV 0x44
+-#define AES_REG_REV_MAJOR 0xF0
+-#define AES_REG_REV_MINOR 0x0F
++#define AES_REG_REV(dd) ((dd)->pdata->rev_ofs)
+
+-#define AES_REG_MASK 0x48
++#define AES_REG_MASK(dd) ((dd)->pdata->mask_ofs)
+ #define AES_REG_MASK_SIDLE (1 << 6)
+ #define AES_REG_MASK_START (1 << 5)
+ #define AES_REG_MASK_DMA_OUT_EN (1 << 3)
+@@ -69,8 +68,7 @@
+ #define AES_REG_MASK_SOFTRESET (1 << 1)
+ #define AES_REG_AUTOIDLE (1 << 0)
+
+-#define AES_REG_SYSSTATUS 0x4C
+-#define AES_REG_SYSSTATUS_RESETDONE (1 << 0)
++#define AES_REG_LENGTH_N(x) (0x54 + ((x) * 0x04))
+
+ #define DEFAULT_TIMEOUT (5*HZ)
+
+@@ -98,6 +96,26 @@ struct omap_aes_reqctx {
+ #define OMAP_AES_QUEUE_LENGTH 1
+ #define OMAP_AES_CACHE_SIZE 0
+
++struct omap_aes_pdata {
++ void (*trigger)(struct omap_aes_dev *dd, int length);
++
++ u32 key_ofs;
++ u32 iv_ofs;
++ u32 ctrl_ofs;
++ u32 data_ofs;
++ u32 rev_ofs;
++ u32 mask_ofs;
++
++ u32 dma_enable_in;
++ u32 dma_enable_out;
++ u32 dma_start;
++
++ u32 major_mask;
++ u32 major_shift;
++ u32 minor_mask;
++ u32 minor_shift;
++};
++
+ struct omap_aes_dev {
+ struct list_head list;
+ unsigned long phys_base;
+@@ -132,6 +150,8 @@ struct omap_aes_dev {
+ int dma_out;
+ struct dma_chan *dma_lch_out;
+ dma_addr_t dma_addr_out;
++
++ const struct omap_aes_pdata *pdata;
+ };
+
+ /* keep registered devices data here */
+@@ -194,26 +214,16 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+ if (err)
+ return err;
+
+- val = 0;
+- if (dd->dma_lch_out != NULL)
+- val |= AES_REG_MASK_DMA_OUT_EN;
+- if (dd->dma_lch_in != NULL)
+- val |= AES_REG_MASK_DMA_IN_EN;
+-
+- mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN;
+-
+- omap_aes_write_mask(dd, AES_REG_MASK, val, mask);
+-
+ key32 = dd->ctx->keylen / sizeof(u32);
+
+ /* it seems a key should always be set even if it has not changed */
+ for (i = 0; i < key32; i++) {
+- omap_aes_write(dd, AES_REG_KEY(i),
++ omap_aes_write(dd, AES_REG_KEY(dd, i),
+ __le32_to_cpu(dd->ctx->key[i]));
+ }
+
+ if ((dd->flags & FLAGS_CBC) && dd->req->info)
+- omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4);
++ omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4);
+
+ val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
+ if (dd->flags & FLAGS_CBC)
+@@ -224,11 +234,47 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+ mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
+ AES_REG_CTRL_KEY_SIZE;
+
+- omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);
++ omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
+
+ return 0;
+ }
+
++static void omap_aes_dma_trigger_omap2(struct omap_aes_dev *dd, int length)
++{
++ u32 mask, val;
++
++ val = dd->pdata->dma_start;
++
++ if (dd->dma_lch_out != NULL)
++ val |= dd->pdata->dma_enable_out;
++ if (dd->dma_lch_in != NULL)
++ val |= dd->pdata->dma_enable_in;
++
++ mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
++ dd->pdata->dma_start;
++
++ omap_aes_write_mask(dd, AES_REG_MASK(dd), val, mask);
++
++}
++
++static void omap_aes_dma_trigger_omap4(struct omap_aes_dev *dd, int length)
++{
++ omap_aes_write(dd, AES_REG_LENGTH_N(0), length);
++ omap_aes_write(dd, AES_REG_LENGTH_N(1), 0);
++
++ omap_aes_dma_trigger_omap2(dd, length);
++}
++
++static void omap_aes_dma_stop(struct omap_aes_dev *dd)
++{
++ u32 mask;
++
++ mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
++ dd->pdata->dma_start;
++
++ omap_aes_write_mask(dd, AES_REG_MASK(dd), 0, mask);
++}
++
+ static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
+ {
+ struct omap_aes_dev *dd = NULL, *tmp;
+@@ -413,8 +459,8 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
+
+ memset(&cfg, 0, sizeof(cfg));
+
+- cfg.src_addr = dd->phys_base + AES_REG_DATA;
+- cfg.dst_addr = dd->phys_base + AES_REG_DATA;
++ cfg.src_addr = dd->phys_base + AES_REG_DATA_N(dd, 0);
++ cfg.dst_addr = dd->phys_base + AES_REG_DATA_N(dd, 0);
+ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ cfg.src_maxburst = DST_MAXBURST;
+@@ -464,9 +510,8 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
+ dma_async_issue_pending(dd->dma_lch_in);
+ dma_async_issue_pending(dd->dma_lch_out);
+
+- /* start DMA or disable idle mode */
+- omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
+- AES_REG_MASK_START);
++ /* start DMA */
++ dd->pdata->trigger(dd, length);
+
+ return 0;
+ }
+@@ -586,7 +631,7 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
+
+ pr_debug("total: %d\n", dd->total);
+
+- omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);
++ omap_aes_dma_stop(dd);
+
+ dmaengine_terminate_all(dd->dma_lch_in);
+ dmaengine_terminate_all(dd->dma_lch_out);
+@@ -826,10 +871,48 @@ static struct crypto_alg algs[] = {
+ }
+ };
+
++static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
++ .trigger = omap_aes_dma_trigger_omap2,
++ .key_ofs = 0x1c,
++ .iv_ofs = 0x20,
++ .ctrl_ofs = 0x30,
++ .data_ofs = 0x34,
++ .rev_ofs = 0x44,
++ .mask_ofs = 0x48,
++ .dma_enable_in = BIT(2),
++ .dma_enable_out = BIT(3),
++ .dma_start = BIT(5),
++ .major_mask = 0xf0,
++ .major_shift = 4,
++ .minor_mask = 0x0f,
++ .minor_shift = 0,
++};
++
+ #ifdef CONFIG_OF
++static const struct omap_aes_pdata omap_aes_pdata_omap4 = {
++ .trigger = omap_aes_dma_trigger_omap4,
++ .key_ofs = 0x3c,
++ .iv_ofs = 0x40,
++ .ctrl_ofs = 0x50,
++ .data_ofs = 0x60,
++ .rev_ofs = 0x80,
++ .mask_ofs = 0x84,
++ .dma_enable_in = BIT(5),
++ .dma_enable_out = BIT(6),
++ .major_mask = 0x0700,
++ .major_shift = 8,
++ .minor_mask = 0x003f,
++ .minor_shift = 0,
++};
++
+ static const struct of_device_id omap_aes_of_match[] = {
+ {
+ .compatible = "ti,omap2-aes",
++ .data = &omap_aes_pdata_omap2,
++ },
++ {
++ .compatible = "ti,omap4-aes",
++ .data = &omap_aes_pdata_omap4,
+ },
+ {},
+ };
+@@ -859,6 +942,8 @@ static int omap_aes_get_res_of(struct omap_aes_dev *dd,
+ dd->dma_out = -1; /* Dummy value that's unused */
+ dd->dma_in = -1; /* Dummy value that's unused */
+
++ dd->pdata = match->data;
++
+ err:
+ return err;
+ }
+@@ -908,6 +993,9 @@ static int omap_aes_get_res_pdev(struct omap_aes_dev *dd,
+ }
+ dd->dma_in = r->start;
+
++ /* Only OMAP2/3 can be non-DT */
++ dd->pdata = &omap_aes_pdata_omap2;
++
+ err:
+ return err;
+ }
+@@ -947,12 +1035,16 @@ static int omap_aes_probe(struct platform_device *pdev)
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+
+- reg = omap_aes_read(dd, AES_REG_REV);
+- dev_info(dev, "OMAP AES hw accel rev: %u.%u\n",
+- (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR);
++ omap_aes_dma_stop(dd);
++
++ reg = omap_aes_read(dd, AES_REG_REV(dd));
+
+ pm_runtime_put_sync(dev);
+
++ dev_info(dev, "OMAP AES hw accel rev: %u.%u\n",
++ (reg & dd->pdata->major_mask) >> dd->pdata->major_shift,
++ (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
++
+ tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
+ tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd);
+
diff --git a/patches/linux-3.8.13/0163-crypto-omap-aes-Add-CTR-algorithm-Support.patch b/patches/linux-3.8.13/0163-crypto-omap-aes-Add-CTR-algorithm-Support.patch
new file mode 100644
index 0000000..6e3b33f
--- /dev/null
+++ b/patches/linux-3.8.13/0163-crypto-omap-aes-Add-CTR-algorithm-Support.patch
@@ -0,0 +1,289 @@
+From: "Mark A. Greer" <mgreer@animalcreek.com>
+Date: Thu, 20 Dec 2012 15:28:23 -0700
+Subject: [PATCH] crypto: omap-aes - Add CTR algorithm Support
+
+The OMAP3 and OMAP4/AM33xx versions of the AES crypto
+module support the CTR algorithm in addition to ECB
+and CBC that the OMAP2 version of the module supports.
+
+So, OMAP2 and OMAP3 share a common register set but
+OMAP3 supports CTR while OMAP2 doesn't. OMAP4/AM33XX
+uses a different register set from OMAP2/OMAP3 and
+also supports CTR.
+
+To add this support, use the platform_data introduced
+in an ealier commit to hold the list of algorithms
+supported by the current module. The probe routine
+will use that list to register the correct algorithms.
+
+Note: The code being integrated is from the TI AM33xx SDK
+and was written by Greg Turner <gkmturner@gmail.com> and
+Herman Schuurman (current email unknown) while at TI.
+
+CC: Greg Turner <gkmturner@gmail.com>
+CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
+---
+ drivers/crypto/omap-aes.c | 143 ++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 128 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
+index bd1ad97..6aa425f 100644
+--- a/drivers/crypto/omap-aes.c
++++ b/drivers/crypto/omap-aes.c
+@@ -48,7 +48,11 @@
+ #define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04))
+
+ #define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs)
+-#define AES_REG_CTRL_CTR_WIDTH (1 << 7)
++#define AES_REG_CTRL_CTR_WIDTH_MASK (3 << 7)
++#define AES_REG_CTRL_CTR_WIDTH_32 (0 << 7)
++#define AES_REG_CTRL_CTR_WIDTH_64 (1 << 7)
++#define AES_REG_CTRL_CTR_WIDTH_96 (2 << 7)
++#define AES_REG_CTRL_CTR_WIDTH_128 (3 << 7)
+ #define AES_REG_CTRL_CTR (1 << 6)
+ #define AES_REG_CTRL_CBC (1 << 5)
+ #define AES_REG_CTRL_KEY_SIZE (3 << 3)
+@@ -76,6 +80,7 @@
+ #define FLAGS_ENCRYPT BIT(0)
+ #define FLAGS_CBC BIT(1)
+ #define FLAGS_GIV BIT(2)
++#define FLAGS_CTR BIT(3)
+
+ #define FLAGS_INIT BIT(4)
+ #define FLAGS_FAST BIT(5)
+@@ -96,7 +101,16 @@ struct omap_aes_reqctx {
+ #define OMAP_AES_QUEUE_LENGTH 1
+ #define OMAP_AES_CACHE_SIZE 0
+
++struct omap_aes_algs_info {
++ struct crypto_alg *algs_list;
++ unsigned int size;
++ unsigned int registered;
++};
++
+ struct omap_aes_pdata {
++ struct omap_aes_algs_info *algs_info;
++ unsigned int algs_info_size;
++
+ void (*trigger)(struct omap_aes_dev *dd, int length);
+
+ u32 key_ofs;
+@@ -208,7 +222,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+ {
+ unsigned int key32;
+ int i, err;
+- u32 val, mask;
++ u32 val, mask = 0;
+
+ err = omap_aes_hw_init(dd);
+ if (err)
+@@ -222,16 +236,20 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
+ __le32_to_cpu(dd->ctx->key[i]));
+ }
+
+- if ((dd->flags & FLAGS_CBC) && dd->req->info)
++ if ((dd->flags & (FLAGS_CBC | FLAGS_CTR)) && dd->req->info)
+ omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4);
+
+ val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
+ if (dd->flags & FLAGS_CBC)
+ val |= AES_REG_CTRL_CBC;
++ if (dd->flags & FLAGS_CTR) {
++ val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_32;
++ mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
++ }
+ if (dd->flags & FLAGS_ENCRYPT)
+ val |= AES_REG_CTRL_DIRECTION;
+
+- mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
++ mask |= AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
+ AES_REG_CTRL_KEY_SIZE;
+
+ omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
+@@ -807,6 +825,16 @@ static int omap_aes_cbc_decrypt(struct ablkcipher_request *req)
+ return omap_aes_crypt(req, FLAGS_CBC);
+ }
+
++static int omap_aes_ctr_encrypt(struct ablkcipher_request *req)
++{
++ return omap_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CTR);
++}
++
++static int omap_aes_ctr_decrypt(struct ablkcipher_request *req)
++{
++ return omap_aes_crypt(req, FLAGS_CTR);
++}
++
+ static int omap_aes_cra_init(struct crypto_tfm *tfm)
+ {
+ pr_debug("enter\n");
+@@ -823,7 +851,7 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm)
+
+ /* ********************** ALGS ************************************ */
+
+-static struct crypto_alg algs[] = {
++static struct crypto_alg algs_ecb_cbc[] = {
+ {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-omap",
+@@ -871,7 +899,43 @@ static struct crypto_alg algs[] = {
+ }
+ };
+
++static struct crypto_alg algs_ctr[] = {
++{
++ .cra_name = "ctr(aes)",
++ .cra_driver_name = "ctr-aes-omap",
++ .cra_priority = 100,
++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
++ CRYPTO_ALG_KERN_DRIVER_ONLY |
++ CRYPTO_ALG_ASYNC,
++ .cra_blocksize = AES_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct omap_aes_ctx),
++ .cra_alignmask = 0,
++ .cra_type = &crypto_ablkcipher_type,
++ .cra_module = THIS_MODULE,
++ .cra_init = omap_aes_cra_init,
++ .cra_exit = omap_aes_cra_exit,
++ .cra_u.ablkcipher = {
++ .min_keysize = AES_MIN_KEY_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE,
++ .geniv = "eseqiv",
++ .ivsize = AES_BLOCK_SIZE,
++ .setkey = omap_aes_setkey,
++ .encrypt = omap_aes_ctr_encrypt,
++ .decrypt = omap_aes_ctr_decrypt,
++ }
++} ,
++};
++
++static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc[] = {
++ {
++ .algs_list = algs_ecb_cbc,
++ .size = ARRAY_SIZE(algs_ecb_cbc),
++ },
++};
++
+ static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
++ .algs_info = omap_aes_algs_info_ecb_cbc,
++ .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc),
+ .trigger = omap_aes_dma_trigger_omap2,
+ .key_ofs = 0x1c,
+ .iv_ofs = 0x20,
+@@ -889,7 +953,39 @@ static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
+ };
+
+ #ifdef CONFIG_OF
++static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc_ctr[] = {
++ {
++ .algs_list = algs_ecb_cbc,
++ .size = ARRAY_SIZE(algs_ecb_cbc),
++ },
++ {
++ .algs_list = algs_ctr,
++ .size = ARRAY_SIZE(algs_ctr),
++ },
++};
++
++static const struct omap_aes_pdata omap_aes_pdata_omap3 = {
++ .algs_info = omap_aes_algs_info_ecb_cbc_ctr,
++ .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
++ .trigger = omap_aes_dma_trigger_omap2,
++ .key_ofs = 0x1c,
++ .iv_ofs = 0x20,
++ .ctrl_ofs = 0x30,
++ .data_ofs = 0x34,
++ .rev_ofs = 0x44,
++ .mask_ofs = 0x48,
++ .dma_enable_in = BIT(2),
++ .dma_enable_out = BIT(3),
++ .dma_start = BIT(5),
++ .major_mask = 0xf0,
++ .major_shift = 4,
++ .minor_mask = 0x0f,
++ .minor_shift = 0,
++};
++
+ static const struct omap_aes_pdata omap_aes_pdata_omap4 = {
++ .algs_info = omap_aes_algs_info_ecb_cbc_ctr,
++ .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
+ .trigger = omap_aes_dma_trigger_omap4,
+ .key_ofs = 0x3c,
+ .iv_ofs = 0x40,
+@@ -911,6 +1007,10 @@ static const struct of_device_id omap_aes_of_match[] = {
+ .data = &omap_aes_pdata_omap2,
+ },
+ {
++ .compatible = "ti,omap3-aes",
++ .data = &omap_aes_pdata_omap3,
++ },
++ {
+ .compatible = "ti,omap4-aes",
+ .data = &omap_aes_pdata_omap4,
+ },
+@@ -1004,6 +1104,7 @@ static int omap_aes_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct omap_aes_dev *dd;
++ struct crypto_alg *algp;
+ struct resource res;
+ int err = -ENOMEM, i, j;
+ u32 reg;
+@@ -1057,17 +1158,27 @@ static int omap_aes_probe(struct platform_device *pdev)
+ list_add_tail(&dd->list, &dev_list);
+ spin_unlock(&list_lock);
+
+- for (i = 0; i < ARRAY_SIZE(algs); i++) {
+- pr_debug("i: %d\n", i);
+- err = crypto_register_alg(&algs[i]);
+- if (err)
+- goto err_algs;
++ for (i = 0; i < dd->pdata->algs_info_size; i++) {
++ for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
++ algp = &dd->pdata->algs_info[i].algs_list[j];
++
++ pr_debug("reg alg: %s\n", algp->cra_name);
++ INIT_LIST_HEAD(&algp->cra_list);
++
++ err = crypto_register_alg(algp);
++ if (err)
++ goto err_algs;
++
++ dd->pdata->algs_info[i].registered++;
++ }
+ }
+
+ return 0;
+ err_algs:
+- for (j = 0; j < i; j++)
+- crypto_unregister_alg(&algs[j]);
++ for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
++ for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
++ crypto_unregister_alg(
++ &dd->pdata->algs_info[i].algs_list[j]);
+ omap_aes_dma_cleanup(dd);
+ err_dma:
+ tasklet_kill(&dd->done_task);
+@@ -1084,7 +1195,7 @@ err_data:
+ static int omap_aes_remove(struct platform_device *pdev)
+ {
+ struct omap_aes_dev *dd = platform_get_drvdata(pdev);
+- int i;
++ int i, j;
+
+ if (!dd)
+ return -ENODEV;
+@@ -1093,8 +1204,10 @@ static int omap_aes_remove(struct platform_device *pdev)
+ list_del(&dd->list);
+ spin_unlock(&list_lock);
+
+- for (i = 0; i < ARRAY_SIZE(algs); i++)
+- crypto_unregister_alg(&algs[i]);
++ for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
++ for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
++ crypto_unregister_alg(
++ &dd->pdata->algs_info[i].algs_list[j]);
+
+ tasklet_kill(&dd->done_task);
+ tasklet_kill(&dd->queue_task);
diff --git a/patches/linux-3.8.13/0164-6lowpan-Refactor-packet-delivery-into-a-function.patch b/patches/linux-3.8.13/0164-6lowpan-Refactor-packet-delivery-into-a-function.patch
new file mode 100644
index 0000000..1aaadec
--- /dev/null
+++ b/patches/linux-3.8.13/0164-6lowpan-Refactor-packet-delivery-into-a-function.patch
@@ -0,0 +1,72 @@
+From: Alan Ott <alan@signal11.us>
+Date: Wed, 16 Jan 2013 19:09:47 +0000
+Subject: [PATCH] 6lowpan: Refactor packet delivery into a function
+
+Refactor the handing of the skb's to the individual lowpan devices into a
+function.
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ net/ieee802154/6lowpan.c | 38 ++++++++++++++++++++++++--------------
+ 1 file changed, 24 insertions(+), 14 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 76c3d0a..9d39f5b 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -594,10 +594,32 @@ static int lowpan_header_create(struct sk_buff *skb,
+ }
+ }
+
++static int lowpan_give_skb_to_devices(struct sk_buff *skb)
++{
++ struct lowpan_dev_record *entry;
++ struct sk_buff *skb_cp;
++ int stat = NET_RX_SUCCESS;
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(entry, &lowpan_devices, list)
++ if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
++ skb_cp = skb_copy(skb, GFP_ATOMIC);
++ if (!skb_cp) {
++ stat = -ENOMEM;
++ break;
++ }
++
++ skb_cp->dev = entry->ldev;
++ stat = netif_rx(skb_cp);
++ }
++ rcu_read_unlock();
++
++ return stat;
++}
++
+ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
+ {
+ struct sk_buff *new;
+- struct lowpan_dev_record *entry;
+ int stat = NET_RX_SUCCESS;
+
+ new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
+@@ -614,19 +636,7 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
+ new->protocol = htons(ETH_P_IPV6);
+ new->pkt_type = PACKET_HOST;
+
+- rcu_read_lock();
+- list_for_each_entry_rcu(entry, &lowpan_devices, list)
+- if (lowpan_dev_info(entry->ldev)->real_dev == new->dev) {
+- skb = skb_copy(new, GFP_ATOMIC);
+- if (!skb) {
+- stat = -ENOMEM;
+- break;
+- }
+-
+- skb->dev = entry->ldev;
+- stat = netif_rx(skb);
+- }
+- rcu_read_unlock();
++ stat = lowpan_give_skb_to_devices(new);
+
+ kfree_skb(new);
+
diff --git a/patches/linux-3.8.13/0165-6lowpan-Handle-uncompressed-IPv6-packets-over-6LoWPA.patch b/patches/linux-3.8.13/0165-6lowpan-Handle-uncompressed-IPv6-packets-over-6LoWPA.patch
new file mode 100644
index 0000000..c64fc75
--- /dev/null
+++ b/patches/linux-3.8.13/0165-6lowpan-Handle-uncompressed-IPv6-packets-over-6LoWPA.patch
@@ -0,0 +1,68 @@
+From: Alan Ott <alan@signal11.us>
+Date: Wed, 16 Jan 2013 19:09:48 +0000
+Subject: [PATCH] 6lowpan: Handle uncompressed IPv6 packets over 6LoWPAN
+
+Handle the reception of uncompressed packets (dispatch type = IPv6).
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ net/ieee802154/6lowpan.c | 41 ++++++++++++++++++++++++++++++++---------
+ 1 file changed, 32 insertions(+), 9 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 9d39f5b..f62c3b9 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -1147,19 +1147,42 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
+ goto drop;
+
+ /* check that it's our buffer */
+- switch (skb->data[0] & 0xe0) {
+- case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
+- case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
+- case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */
+- local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
++ /* Copy the packet so that the IPv6 header is
++ * properly aligned.
++ */
++ local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1,
++ skb_tailroom(skb), GFP_ATOMIC);
+ if (!local_skb)
+ goto drop;
+- lowpan_process_data(local_skb);
+
++ local_skb->protocol = htons(ETH_P_IPV6);
++ local_skb->pkt_type = PACKET_HOST;
++
++ /* Pull off the 1-byte of 6lowpan header. */
++ skb_pull(local_skb, 1);
++ skb_reset_network_header(local_skb);
++ skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
++
++ lowpan_give_skb_to_devices(local_skb);
++
++ kfree_skb(local_skb);
+ kfree_skb(skb);
+- break;
+- default:
+- break;
++ } else {
++ switch (skb->data[0] & 0xe0) {
++ case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
++ case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
++ case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */
++ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ goto drop;
++ lowpan_process_data(local_skb);
++
++ kfree_skb(skb);
++ break;
++ default:
++ break;
++ }
+ }
+
+ return NET_RX_SUCCESS;
diff --git a/patches/linux-3.8.13/0166-wpan-whitespace-fix.patch b/patches/linux-3.8.13/0166-wpan-whitespace-fix.patch
new file mode 100644
index 0000000..9a63bbb
--- /dev/null
+++ b/patches/linux-3.8.13/0166-wpan-whitespace-fix.patch
@@ -0,0 +1,23 @@
+From: Alexander Aring <alex.aring@gmail.com>
+Date: Tue, 5 Feb 2013 04:25:35 +0000
+Subject: [PATCH] wpan: whitespace fix
+
+Signed-off-by: Alexander Aring <alex.aring@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ net/mac802154/wpan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
+index 199b922..98c867b 100644
+--- a/net/mac802154/wpan.c
++++ b/net/mac802154/wpan.c
+@@ -41,7 +41,7 @@ static inline int mac802154_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+ return -EINVAL;
+
+ *val = skb->data[0];
+- skb_pull(skb, 1);
++ skb_pull(skb, 1);
+
+ return 0;
+ }
diff --git a/patches/linux-3.8.13/0167-6lowpan-use-stack-buffer-instead-of-heap.patch b/patches/linux-3.8.13/0167-6lowpan-use-stack-buffer-instead-of-heap.patch
new file mode 100644
index 0000000..d02957c
--- /dev/null
+++ b/patches/linux-3.8.13/0167-6lowpan-use-stack-buffer-instead-of-heap.patch
@@ -0,0 +1,50 @@
+From: Alexander Aring <alex.aring@gmail.com>
+Date: Tue, 5 Feb 2013 10:23:43 +0000
+Subject: [PATCH] 6lowpan: use stack buffer instead of heap
+
+head buffer is only temporary available in lowpan_header_create.
+So it's not necessary to put it on the heap.
+
+Also fixed a comment codestyle issue.
+
+Signed-off-by: Alexander Aring <alex.aring@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ net/ieee802154/6lowpan.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index f62c3b9..43b95ca 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -377,17 +377,14 @@ static int lowpan_header_create(struct sk_buff *skb,
+ struct ipv6hdr *hdr;
+ const u8 *saddr = _saddr;
+ const u8 *daddr = _daddr;
+- u8 *head;
++ u8 head[100];
+ struct ieee802154_addr sa, da;
+
++ /* TODO:
++ * if this package isn't ipv6 one, where should it be routed?
++ */
+ if (type != ETH_P_IPV6)
+ return 0;
+- /* TODO:
+- * if this package isn't ipv6 one, where should it be routed?
+- */
+- head = kzalloc(100, GFP_KERNEL);
+- if (head == NULL)
+- return -ENOMEM;
+
+ hdr = ipv6_hdr(skb);
+ hc06_ptr = head + 2;
+@@ -561,8 +558,6 @@ static int lowpan_header_create(struct sk_buff *skb,
+ skb_pull(skb, sizeof(struct ipv6hdr));
+ memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
+
+- kfree(head);
+-
+ lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
+ skb->len);
+
diff --git a/patches/linux-3.8.13/0168-wpan-use-stack-buffer-instead-of-heap.patch b/patches/linux-3.8.13/0168-wpan-use-stack-buffer-instead-of-heap.patch
new file mode 100644
index 0000000..658ca85
--- /dev/null
+++ b/patches/linux-3.8.13/0168-wpan-use-stack-buffer-instead-of-heap.patch
@@ -0,0 +1,43 @@
+From: Alexander Aring <alex.aring@gmail.com>
+Date: Tue, 5 Feb 2013 10:23:44 +0000
+Subject: [PATCH] wpan: use stack buffer instead of heap
+
+head buffer is only temporary available in mac802154_header_create.
+So it's not necessary to put it on the heap.
+
+Signed-off-by: Alexander Aring <alex.aring@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ net/mac802154/wpan.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
+index 98c867b..d20c6d3 100644
+--- a/net/mac802154/wpan.c
++++ b/net/mac802154/wpan.c
+@@ -137,16 +137,12 @@ static int mac802154_header_create(struct sk_buff *skb,
+ struct ieee802154_addr dev_addr;
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ int pos = 2;
+- u8 *head;
++ u8 head[MAC802154_FRAME_HARD_HEADER_LEN];
+ u16 fc;
+
+ if (!daddr)
+ return -EINVAL;
+
+- head = kzalloc(MAC802154_FRAME_HARD_HEADER_LEN, GFP_KERNEL);
+- if (head == NULL)
+- return -ENOMEM;
+-
+ head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
+ fc = mac_cb_type(skb);
+
+@@ -210,7 +206,6 @@ static int mac802154_header_create(struct sk_buff *skb,
+ head[1] = fc >> 8;
+
+ memcpy(skb_push(skb, pos), head, pos);
+- kfree(head);
+
+ return pos;
+ }
diff --git a/patches/linux-3.8.13/0169-mrf24j40-pinctrl-support.patch b/patches/linux-3.8.13/0169-mrf24j40-pinctrl-support.patch
new file mode 100644
index 0000000..1d23e02
--- /dev/null
+++ b/patches/linux-3.8.13/0169-mrf24j40-pinctrl-support.patch
@@ -0,0 +1,43 @@
+From: Alan Ott <alan@signal11.us>
+Date: Mon, 18 Mar 2013 00:39:48 -0400
+Subject: [PATCH] mrf24j40: pinctrl support
+
+Activate pinctrl settings when used with a DT system.
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+---
+ drivers/net/ieee802154/mrf24j40.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
+index 3f2c7aa..3106895 100644
+--- a/drivers/net/ieee802154/mrf24j40.c
++++ b/drivers/net/ieee802154/mrf24j40.c
+@@ -22,6 +22,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
++#include <linux/pinctrl/consumer.h>
+ #include <net/wpan-phy.h>
+ #include <net/mac802154.h>
+
+@@ -623,6 +624,7 @@ static int mrf24j40_probe(struct spi_device *spi)
+ int ret = -ENOMEM;
+ u8 val;
+ struct mrf24j40 *devrec;
++ struct pinctrl *pinctrl;
+
+ printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq);
+
+@@ -633,6 +635,11 @@ static int mrf24j40_probe(struct spi_device *spi)
+ if (!devrec->buf)
+ goto err_buf;
+
++ pinctrl = devm_pinctrl_get_select_default(&spi->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&spi->dev,
++ "pinctrl pins are not configured from the driver");
++
+ spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */
+ if (spi->max_speed_hz > MAX_SPI_SPEED_HZ)
+ spi->max_speed_hz = MAX_SPI_SPEED_HZ;
diff --git a/patches/linux-3.8.13/0170-mrf24j40-Warn-if-transmit-interrupts-timeout.patch b/patches/linux-3.8.13/0170-mrf24j40-Warn-if-transmit-interrupts-timeout.patch
new file mode 100644
index 0000000..0d03705
--- /dev/null
+++ b/patches/linux-3.8.13/0170-mrf24j40-Warn-if-transmit-interrupts-timeout.patch
@@ -0,0 +1,23 @@
+From: Alan Ott <alan@signal11.us>
+Date: Mon, 18 Mar 2013 00:49:02 -0400
+Subject: [PATCH] mrf24j40: Warn if transmit interrupts timeout
+
+Issue a warning if a transmit complete interrupt doesn't happen in time.
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+---
+ drivers/net/ieee802154/mrf24j40.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
+index 3106895..bb7e613 100644
+--- a/drivers/net/ieee802154/mrf24j40.c
++++ b/drivers/net/ieee802154/mrf24j40.c
+@@ -363,6 +363,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
+ goto err;
+ if (ret == 0) {
+ ret = -ETIMEDOUT;
++ dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n");
+ goto err;
+ }
+
diff --git a/patches/linux-3.8.13/0171-mrf24j40-Increase-max-SPI-speed-to-10MHz.patch b/patches/linux-3.8.13/0171-mrf24j40-Increase-max-SPI-speed-to-10MHz.patch
new file mode 100644
index 0000000..54fa7a6
--- /dev/null
+++ b/patches/linux-3.8.13/0171-mrf24j40-Increase-max-SPI-speed-to-10MHz.patch
@@ -0,0 +1,28 @@
+From: Alan Ott <alan@signal11.us>
+Date: Mon, 18 Mar 2013 01:17:05 -0400
+Subject: [PATCH] mrf24j40: Increase max SPI speed to 10MHz
+
+Upon consulting the datasheet further, it does indicates a maximum speed
+for SCK at 10MHz.
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+---
+ drivers/net/ieee802154/mrf24j40.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
+index bb7e613..f6e723e 100644
+--- a/drivers/net/ieee802154/mrf24j40.c
++++ b/drivers/net/ieee802154/mrf24j40.c
+@@ -92,9 +92,8 @@ struct mrf24j40 {
+ #define MRF24J40_READLONG(reg) (1 << 15 | (reg) << 5)
+ #define MRF24J40_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4)
+
+-/* Maximum speed to run the device at. TODO: Get the real max value from
+- * someone at Microchip since it isn't in the datasheet. */
+-#define MAX_SPI_SPEED_HZ 1000000
++/* The datasheet indicates the theoretical maximum for SCK to be 10MHz */
++#define MAX_SPI_SPEED_HZ 10000000
+
+ #define printdev(X) (&X->spi->dev)
+
diff --git a/patches/linux-3.8.13/0172-mrf24j40-Fix-byte-order-of-IEEE-address.patch b/patches/linux-3.8.13/0172-mrf24j40-Fix-byte-order-of-IEEE-address.patch
new file mode 100644
index 0000000..1d79313
--- /dev/null
+++ b/patches/linux-3.8.13/0172-mrf24j40-Fix-byte-order-of-IEEE-address.patch
@@ -0,0 +1,25 @@
+From: Alan Ott <alan@signal11.us>
+Date: Mon, 18 Mar 2013 01:26:01 -0400
+Subject: [PATCH] mrf24j40: Fix byte-order of IEEE address
+
+Load the 64-bit Extended (IEEE) address into the hardware in the proper
+byte order.
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+---
+ drivers/net/ieee802154/mrf24j40.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
+index f6e723e..6481faf 100644
+--- a/drivers/net/ieee802154/mrf24j40.c
++++ b/drivers/net/ieee802154/mrf24j40.c
+@@ -478,7 +478,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
+ int i;
+ for (i = 0; i < 8; i++)
+ write_short_reg(devrec, REG_EADR0+i,
+- filt->ieee_addr[i]);
++ filt->ieee_addr[7-i]);
+
+ #ifdef DEBUG
+ printk(KERN_DEBUG "Set long addr to: ");
diff --git a/patches/linux-3.8.13/0173-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch b/patches/linux-3.8.13/0173-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch
new file mode 100644
index 0000000..7448343
--- /dev/null
+++ b/patches/linux-3.8.13/0173-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch
@@ -0,0 +1,31 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:21 -0400
+Subject: [PATCH] 6lowpan: lowpan_is_iid_16_bit_compressable() does not detect
+ compressible address correctly
+
+The current test is not RFC6282 compliant. The same issue has been found
+and fixed in Contiki. This patch is basically a port of their fix.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.h | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
+index bba5f83..4b8f917 100644
+--- a/net/ieee802154/6lowpan.h
++++ b/net/ieee802154/6lowpan.h
+@@ -92,9 +92,10 @@
+ */
+ #define lowpan_is_iid_16_bit_compressable(a) \
+ ((((a)->s6_addr16[4]) == 0) && \
+- (((a)->s6_addr16[5]) == 0) && \
+- (((a)->s6_addr16[6]) == 0) && \
+- ((((a)->s6_addr[14]) & 0x80) == 0))
++ (((a)->s6_addr[10]) == 0) && \
++ (((a)->s6_addr[11]) == 0xff) && \
++ (((a)->s6_addr[12]) == 0xfe) && \
++ (((a)->s6_addr[13]) == 0))
+
+ /* multicast address */
+ #define is_addr_mcast(a) (((a)->s6_addr[0]) == 0xFF)
diff --git a/patches/linux-3.8.13/0174-6lowpan-next-header-is-not-properly-set-upon-decompr.patch b/patches/linux-3.8.13/0174-6lowpan-next-header-is-not-properly-set-upon-decompr.patch
new file mode 100644
index 0000000..cfe24ef
--- /dev/null
+++ b/patches/linux-3.8.13/0174-6lowpan-next-header-is-not-properly-set-upon-decompr.patch
@@ -0,0 +1,29 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:22 -0400
+Subject: [PATCH] 6lowpan: next header is not properly set upon decompression
+ of a UDP header.
+
+This causes a drop of the UDP packet.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 43b95ca..9f53904 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -918,9 +918,11 @@ lowpan_process_data(struct sk_buff *skb)
+ }
+
+ /* UDP data uncompression */
+- if (iphc0 & LOWPAN_IPHC_NH_C)
++ if (iphc0 & LOWPAN_IPHC_NH_C) {
+ if (lowpan_uncompress_udp_header(skb))
+ goto drop;
++ hdr.nexthdr = UIP_PROTO_UDP;
++ }
+
+ /* Not fragmented package */
+ hdr.payload_len = htons(skb->len);
diff --git a/patches/linux-3.8.13/0175-6lowpan-always-enable-link-layer-acknowledgments.patch b/patches/linux-3.8.13/0175-6lowpan-always-enable-link-layer-acknowledgments.patch
new file mode 100644
index 0000000..989bd60
--- /dev/null
+++ b/patches/linux-3.8.13/0175-6lowpan-always-enable-link-layer-acknowledgments.patch
@@ -0,0 +1,30 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:23 -0400
+Subject: [PATCH] 6lowpan: always enable link-layer acknowledgments
+
+This feature is especially important when using fragmentation, because
+the reassembly mechanism cannot recover from the loss of a fragment.
+
+Note that some hardware ignore this flag and not will not transmit
+acknowledgments even if this is set.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 9f53904..e7f61de 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -584,6 +584,10 @@ static int lowpan_header_create(struct sk_buff *skb,
+
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+
++ /* request acknowledgment when possible */
++ if (!lowpan_is_addr_broadcast(daddr))
++ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
++
+ return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+ type, (void *)&da, (void *)&sa, skb->len);
+ }
diff --git a/patches/linux-3.8.13/0176-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch b/patches/linux-3.8.13/0176-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch
new file mode 100644
index 0000000..a96b6ef
--- /dev/null
+++ b/patches/linux-3.8.13/0176-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch
@@ -0,0 +1,22 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:24 -0400
+Subject: [PATCH] mac802154: turn on ACK when enabled by the upper layers
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/mac802154/wpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
+index d20c6d3..7d3f659 100644
+--- a/net/mac802154/wpan.c
++++ b/net/mac802154/wpan.c
+@@ -145,6 +145,8 @@ static int mac802154_header_create(struct sk_buff *skb,
+
+ head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
+ fc = mac_cb_type(skb);
++ if (mac_cb_is_ackreq(skb))
++ fc |= IEEE802154_FC_ACK_REQ;
+
+ if (!saddr) {
+ spin_lock_bh(&priv->mib_lock);
diff --git a/patches/linux-3.8.13/0177-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch b/patches/linux-3.8.13/0177-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch
new file mode 100644
index 0000000..5e832d8
--- /dev/null
+++ b/patches/linux-3.8.13/0177-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch
@@ -0,0 +1,54 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:25 -0400
+Subject: [PATCH] 6lowpan: use short IEEE 802.15.4 addresses for broadcast
+ destination
+
+The IEEE 802.15.4 standard uses the 0xFFFF short address (2 bytes) for message
+broadcasting.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 23 +++++++++++++++--------
+ 1 file changed, 15 insertions(+), 8 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index e7f61de..0eebb96 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -572,21 +572,28 @@ static int lowpan_header_create(struct sk_buff *skb,
+ * this isn't implemented in mainline yet, so currently we assign 0xff
+ */
+ {
++ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
++
+ /* prepare wpan address data */
+ sa.addr_type = IEEE802154_ADDR_LONG;
+ sa.pan_id = 0xff;
+-
+- da.addr_type = IEEE802154_ADDR_LONG;
+- da.pan_id = 0xff;
+-
+- memcpy(&(da.hwaddr), daddr, 8);
+ memcpy(&(sa.hwaddr), saddr, 8);
+
+- mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
++ da.pan_id = 0xff;
++ /*
++ * if the destination address is the broadcast address, use the
++ * corresponding short address
++ */
++ if (lowpan_is_addr_broadcast(daddr)) {
++ da.addr_type = IEEE802154_ADDR_SHORT;
++ da.short_addr = IEEE802154_ADDR_BROADCAST;
++ } else {
++ da.addr_type = IEEE802154_ADDR_LONG;
++ memcpy(&(da.hwaddr), daddr, 8);
+
+- /* request acknowledgment when possible */
+- if (!lowpan_is_addr_broadcast(daddr))
++ /* request acknowledgment */
+ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
++ }
+
+ return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+ type, (void *)&da, (void *)&sa, skb->len);
diff --git a/patches/linux-3.8.13/0178-6lowpan-fix-first-fragment-FRAG1-handling.patch b/patches/linux-3.8.13/0178-6lowpan-fix-first-fragment-FRAG1-handling.patch
new file mode 100644
index 0000000..cbc0d86
--- /dev/null
+++ b/patches/linux-3.8.13/0178-6lowpan-fix-first-fragment-FRAG1-handling.patch
@@ -0,0 +1,119 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:26 -0400
+Subject: [PATCH] 6lowpan: fix first fragment (FRAG1) handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The first fragment, FRAG1, must contain some payload according to the
+specs. However, as it is currently written, the first fragment will
+remain empty and only contain the 6lowpan headers.
+
+This patch also extracts the transport layer information from the first
+fragment. This information is used later on when uncompressing UDP
+header.
+
+Thanks to Wolf-Bastian Pöttner for noticing that the offset value was
+not properly initialized.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 0eebb96..4a62289 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -661,7 +661,7 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
+ }
+
+ static struct lowpan_fragment *
+-lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag)
++lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
+ {
+ struct lowpan_fragment *frame;
+
+@@ -731,7 +731,7 @@ lowpan_process_data(struct sk_buff *skb)
+ {
+ struct lowpan_fragment *frame;
+ /* slen stores the rightmost 8 bits of the 11 bits length */
+- u8 slen, offset;
++ u8 slen, offset = 0;
+ u16 len, tag;
+ bool found = false;
+
+@@ -742,6 +742,12 @@ lowpan_process_data(struct sk_buff *skb)
+ /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */
+ len = ((iphc0 & 7) << 8) | slen;
+
++ /* FRAGN */
++ if ((iphc0 & LOWPAN_DISPATCH_MASK) != LOWPAN_DISPATCH_FRAG1) {
++ if (lowpan_fetch_skb_u8(skb, &offset))
++ goto unlock_and_drop;
++ }
++
+ /*
+ * check if frame assembling with the same tag is
+ * already in progress
+@@ -761,12 +767,6 @@ lowpan_process_data(struct sk_buff *skb)
+ goto unlock_and_drop;
+ }
+
+- if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1)
+- goto unlock_and_drop;
+-
+- if (lowpan_fetch_skb_u8(skb, &offset)) /* fetch offset */
+- goto unlock_and_drop;
+-
+ /* if payload fits buffer, copy it */
+ if (likely((offset * 8 + skb->len) <= frame->length))
+ skb_copy_to_linear_data_offset(frame->skb, offset * 8,
+@@ -982,13 +982,13 @@ static int lowpan_get_mac_header_length(struct sk_buff *skb)
+
+ static int
+ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
+- int mlen, int plen, int offset)
++ int mlen, int plen, int offset, int type)
+ {
+ struct sk_buff *frag;
+ int hlen, ret;
+
+- /* if payload length is zero, therefore it's a first fragment */
+- hlen = (plen == 0 ? LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE);
++ hlen = (type == LOWPAN_DISPATCH_FRAG1) ?
++ LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE;
+
+ lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen);
+
+@@ -1031,7 +1031,13 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
+ head[2] = tag >> 8;
+ head[3] = tag & 0xff;
+
+- err = lowpan_fragment_xmit(skb, head, header_length, 0, 0);
++ err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE,
++ 0, LOWPAN_DISPATCH_FRAG1);
++
++ if (err)
++ goto exit;
++
++ offset = LOWPAN_FRAG_SIZE;
+
+ /* next fragment header */
+ head[0] &= ~LOWPAN_DISPATCH_FRAG1;
+@@ -1046,10 +1052,14 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
+ len = payload_length - offset;
+
+ err = lowpan_fragment_xmit(skb, head, header_length,
+- len, offset);
++ len, offset, LOWPAN_DISPATCH_FRAGN);
++ if (err)
++ goto exit;
++
+ offset += len;
+ }
+
++exit:
+ return err;
+ }
+
diff --git a/patches/linux-3.8.13/0179-6lowpan-add-debug-messages-for-6LoWPAN-fragmentation.patch b/patches/linux-3.8.13/0179-6lowpan-add-debug-messages-for-6LoWPAN-fragmentation.patch
new file mode 100644
index 0000000..06e0a71
--- /dev/null
+++ b/patches/linux-3.8.13/0179-6lowpan-add-debug-messages-for-6LoWPAN-fragmentation.patch
@@ -0,0 +1,80 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:27 -0400
+Subject: [PATCH] 6lowpan: add debug messages for 6LoWPAN fragmentation
+
+Add pr_debug() call in order to debug 6LoWPAN fragmentation and
+reassembly.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 4a62289..61eee9d 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -742,10 +742,16 @@ lowpan_process_data(struct sk_buff *skb)
+ /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */
+ len = ((iphc0 & 7) << 8) | slen;
+
+- /* FRAGN */
+- if ((iphc0 & LOWPAN_DISPATCH_MASK) != LOWPAN_DISPATCH_FRAG1) {
++ if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1) {
++ pr_debug("%s received a FRAG1 packet (tag: %d, "
++ "size of the entire IP packet: %d)",
++ __func__, tag, len);
++ } else { /* FRAGN */
+ if (lowpan_fetch_skb_u8(skb, &offset))
+ goto unlock_and_drop;
++ pr_debug("%s received a FRAGN packet (tag: %d, "
++ "size of the entire IP packet: %d, "
++ "offset: %d)", __func__, tag, len, offset * 8);
+ }
+
+ /*
+@@ -762,6 +768,8 @@ lowpan_process_data(struct sk_buff *skb)
+
+ /* alloc new frame structure */
+ if (!found) {
++ pr_debug("%s first fragment received for tag %d, "
++ "begin packet reassembly", __func__, tag);
+ frame = lowpan_alloc_new_frame(skb, len, tag);
+ if (!frame)
+ goto unlock_and_drop;
+@@ -784,6 +792,9 @@ lowpan_process_data(struct sk_buff *skb)
+ list_del(&frame->list);
+ spin_unlock_bh(&flist_lock);
+
++ pr_debug("%s successfully reassembled fragment "
++ "(tag %d)", __func__, tag);
++
+ dev_kfree_skb(skb);
+ skb = frame->skb;
+ kfree(frame);
+@@ -1034,8 +1045,11 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
+ err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE,
+ 0, LOWPAN_DISPATCH_FRAG1);
+
+- if (err)
++ if (err) {
++ pr_debug("%s unable to send FRAG1 packet (tag: %d)",
++ __func__, tag);
+ goto exit;
++ }
+
+ offset = LOWPAN_FRAG_SIZE;
+
+@@ -1053,8 +1067,11 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
+
+ err = lowpan_fragment_xmit(skb, head, header_length,
+ len, offset, LOWPAN_DISPATCH_FRAGN);
+- if (err)
++ if (err) {
++ pr_debug("%s unable to send a subsequent FRAGN packet "
++ "(tag: %d, offset: %d", __func__, tag, offset);
+ goto exit;
++ }
+
+ offset += len;
+ }
diff --git a/patches/linux-3.8.13/0180-6lowpan-store-fragment-tag-values-per-device-instead.patch b/patches/linux-3.8.13/0180-6lowpan-store-fragment-tag-values-per-device-instead.patch
new file mode 100644
index 0000000..5248522
--- /dev/null
+++ b/patches/linux-3.8.13/0180-6lowpan-store-fragment-tag-values-per-device-instead.patch
@@ -0,0 +1,64 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:28 -0400
+Subject: [PATCH] 6lowpan: store fragment tag values per device instead of net
+ stack wide
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 61eee9d..f952451 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -104,6 +104,7 @@ static const u8 lowpan_llprefix[] = {0xfe, 0x80};
+ struct lowpan_dev_info {
+ struct net_device *real_dev; /* real WPAN device ptr */
+ struct mutex dev_list_mtx; /* mutex for list ops */
++ unsigned short fragment_tag;
+ };
+
+ struct lowpan_dev_record {
+@@ -120,7 +121,6 @@ struct lowpan_fragment {
+ struct list_head list; /* fragments list */
+ };
+
+-static unsigned short fragment_tag;
+ static LIST_HEAD(lowpan_fragments);
+ static DEFINE_SPINLOCK(flist_lock);
+
+@@ -1027,14 +1027,14 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
+ }
+
+ static int
+-lowpan_skb_fragmentation(struct sk_buff *skb)
++lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev)
+ {
+ int err, header_length, payload_length, tag, offset = 0;
+ u8 head[5];
+
+ header_length = lowpan_get_mac_header_length(skb);
+ payload_length = skb->len - header_length;
+- tag = fragment_tag++;
++ tag = lowpan_dev_info(dev)->fragment_tag++;
+
+ /* first fragment header */
+ head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7);
+@@ -1099,7 +1099,7 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ pr_debug("frame is too big, fragmentation is needed\n");
+- err = lowpan_skb_fragmentation(skb);
++ err = lowpan_skb_fragmentation(skb, dev);
+ error:
+ dev_kfree_skb(skb);
+ out:
+@@ -1243,6 +1243,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
+ return -ENODEV;
+
+ lowpan_dev_info(dev)->real_dev = real_dev;
++ lowpan_dev_info(dev)->fragment_tag = 0;
+ mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
+
+ entry = kzalloc(sizeof(struct lowpan_dev_record), GFP_KERNEL);
diff --git a/patches/linux-3.8.13/0181-mac802154-add-mac802154_dev_get_dsn.patch b/patches/linux-3.8.13/0181-mac802154-add-mac802154_dev_get_dsn.patch
new file mode 100644
index 0000000..e1c8c23
--- /dev/null
+++ b/patches/linux-3.8.13/0181-mac802154-add-mac802154_dev_get_dsn.patch
@@ -0,0 +1,57 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:29 -0400
+Subject: [PATCH] mac802154: add mac802154_dev_get_dsn()
+
+Bring-over mac802154_dev_get_dsn() function that was present in the
+Linux ZigBee kernel. This function is called by the 6LoWPAN code in
+order to properly set the DSN (Data Sequence Number) value in the IEEE
+802.15.4 frame.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/mac802154/mac802154.h | 1 +
+ net/mac802154/mac_cmd.c | 1 +
+ net/mac802154/mib.c | 9 +++++++++
+ 3 files changed, 11 insertions(+)
+
+diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
+index a4dcaf1..21fa386 100644
+--- a/net/mac802154/mac802154.h
++++ b/net/mac802154/mac802154.h
+@@ -114,5 +114,6 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev);
+ u16 mac802154_dev_get_pan_id(const struct net_device *dev);
+ void mac802154_dev_set_pan_id(struct net_device *dev, u16 val);
+ void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
++u8 mac802154_dev_get_dsn(const struct net_device *dev);
+
+ #endif /* MAC802154_H */
+diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
+index d8d2770..a99910d 100644
+--- a/net/mac802154/mac_cmd.c
++++ b/net/mac802154/mac_cmd.c
+@@ -73,4 +73,5 @@ struct ieee802154_mlme_ops mac802154_mlme_wpan = {
+ .start_req = mac802154_mlme_start_req,
+ .get_pan_id = mac802154_dev_get_pan_id,
+ .get_short_addr = mac802154_dev_get_short_addr,
++ .get_dsn = mac802154_dev_get_dsn,
+ };
+diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
+index f47781a..f03e55f 100644
+--- a/net/mac802154/mib.c
++++ b/net/mac802154/mib.c
+@@ -159,6 +159,15 @@ void mac802154_dev_set_pan_id(struct net_device *dev, u16 val)
+ }
+ }
+
++u8 mac802154_dev_get_dsn(const struct net_device *dev)
++{
++ struct mac802154_sub_if_data *priv = netdev_priv(dev);
++
++ BUG_ON(dev->type != ARPHRD_IEEE802154);
++
++ return priv->dsn++;
++}
++
+ static void phy_chan_notify(struct work_struct *work)
+ {
+ struct phy_chan_notify_work *nw = container_of(work,
diff --git a/patches/linux-3.8.13/0182-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch b/patches/linux-3.8.13/0182-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch
new file mode 100644
index 0000000..ac3a3a3
--- /dev/null
+++ b/patches/linux-3.8.13/0182-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch
@@ -0,0 +1,46 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:30 -0400
+Subject: [PATCH] 6lowpan: obtain IEEE802.15.4 sequence number from the MAC
+ layer
+
+Sets the sequence number in the frame format. Without this fix, the sequence
+number is always set to 0. This makes trafic analysis very hard.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index f952451..d1d4ee6 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -573,6 +573,7 @@ static int lowpan_header_create(struct sk_buff *skb,
+ */
+ {
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
++ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+
+ /* prepare wpan address data */
+ sa.addr_type = IEEE802154_ADDR_LONG;
+@@ -1127,6 +1128,12 @@ static u16 lowpan_get_short_addr(const struct net_device *dev)
+ return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev);
+ }
+
++static u8 lowpan_get_dsn(const struct net_device *dev)
++{
++ struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
++ return ieee802154_mlme_ops(real_dev)->get_dsn(real_dev);
++}
++
+ static struct header_ops lowpan_header_ops = {
+ .create = lowpan_header_create,
+ };
+@@ -1140,6 +1147,7 @@ static struct ieee802154_mlme_ops lowpan_mlme = {
+ .get_pan_id = lowpan_get_pan_id,
+ .get_phy = lowpan_get_phy,
+ .get_short_addr = lowpan_get_short_addr,
++ .get_dsn = lowpan_get_dsn,
+ };
+
+ static void lowpan_setup(struct net_device *dev)
diff --git a/patches/linux-3.8.13/0183-6lowpan-use-the-PANID-provided-by-the-device-instead.patch b/patches/linux-3.8.13/0183-6lowpan-use-the-PANID-provided-by-the-device-instead.patch
new file mode 100644
index 0000000..c1b5f8e
--- /dev/null
+++ b/patches/linux-3.8.13/0183-6lowpan-use-the-PANID-provided-by-the-device-instead.patch
@@ -0,0 +1,29 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:31 -0400
+Subject: [PATCH] 6lowpan: use the PANID provided by the device instead of a
+ static value
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index d1d4ee6..276971b 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -577,10 +577,12 @@ static int lowpan_header_create(struct sk_buff *skb,
+
+ /* prepare wpan address data */
+ sa.addr_type = IEEE802154_ADDR_LONG;
+- sa.pan_id = 0xff;
++ sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
++
+ memcpy(&(sa.hwaddr), saddr, 8);
++ /* intra-PAN communications */
++ da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+
+- da.pan_id = 0xff;
+ /*
+ * if the destination address is the broadcast address, use the
+ * corresponding short address
diff --git a/patches/linux-3.8.13/0184-6lowpan-modify-udp-compression-uncompression-to-matc.patch b/patches/linux-3.8.13/0184-6lowpan-modify-udp-compression-uncompression-to-matc.patch
new file mode 100644
index 0000000..2e1a8e7
--- /dev/null
+++ b/patches/linux-3.8.13/0184-6lowpan-modify-udp-compression-uncompression-to-matc.patch
@@ -0,0 +1,86 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Mar 2013 23:59:32 -0400
+Subject: [PATCH] 6lowpan: modify udp compression/uncompression to match the
+ standard
+
+The previous code would just compress the UDP header and send the compressed
+UDP header along with the uncompressed one.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 39 ++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 36 insertions(+), 3 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 276971b..c9c3f3d 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -284,6 +284,9 @@ lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
+ /* checksum is always inline */
+ memcpy(*hc06_ptr, &uh->check, 2);
+ *hc06_ptr += 2;
++
++ /* skip the UDP header */
++ skb_pull(skb, sizeof(struct udphdr));
+ }
+
+ static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+@@ -309,9 +312,8 @@ static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
+ }
+
+ static int
+-lowpan_uncompress_udp_header(struct sk_buff *skb)
++lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
+ {
+- struct udphdr *uh = udp_hdr(skb);
+ u8 tmp;
+
+ if (!uh)
+@@ -358,6 +360,14 @@ lowpan_uncompress_udp_header(struct sk_buff *skb)
+ /* copy checksum */
+ memcpy(&uh->check, &skb->data[0], 2);
+ skb_pull(skb, 2);
++
++ /*
++ * UDP lenght needs to be infered from the lower layers
++ * here, we obtain the hint from the remaining size of the
++ * frame
++ */
++ uh->len = htons(skb->len + sizeof(struct udphdr));
++ pr_debug("uncompressed UDP length: src = %d", uh->len);
+ } else {
+ pr_debug("ERROR: unsupported NH format\n");
+ goto err;
+@@ -944,8 +954,31 @@ lowpan_process_data(struct sk_buff *skb)
+
+ /* UDP data uncompression */
+ if (iphc0 & LOWPAN_IPHC_NH_C) {
+- if (lowpan_uncompress_udp_header(skb))
++ struct udphdr uh;
++ struct sk_buff *new;
++ if (lowpan_uncompress_udp_header(skb, &uh))
+ goto drop;
++
++ /*
++ * replace the compressed UDP head by the uncompressed UDP
++ * header
++ */
++ new = skb_copy_expand(skb, sizeof(struct udphdr),
++ skb_tailroom(skb), GFP_ATOMIC);
++ kfree_skb(skb);
++
++ if (!new)
++ return -ENOMEM;
++
++ skb = new;
++
++ skb_push(skb, sizeof(struct udphdr));
++ skb_reset_transport_header(skb);
++ skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
++
++ lowpan_raw_dump_table(__func__, "raw UDP header dump",
++ (u8 *)&uh, sizeof(uh));
++
+ hdr.nexthdr = UIP_PROTO_UDP;
+ }
+
diff --git a/patches/linux-3.8.13/0185-6lowpan-fix-a-small-formatting-issue.patch b/patches/linux-3.8.13/0185-6lowpan-fix-a-small-formatting-issue.patch
new file mode 100644
index 0000000..6bf3e92
--- /dev/null
+++ b/patches/linux-3.8.13/0185-6lowpan-fix-a-small-formatting-issue.patch
@@ -0,0 +1,25 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Wed, 27 Mar 2013 00:09:24 -0400
+Subject: [PATCH] 6lowpan: fix a small formatting issue
+
+This formatting issue was introduced with commit
+d4ac32365dcbfd341a87eae444c26679f889249a
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index c9c3f3d..f4969d7 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -104,7 +104,7 @@ static const u8 lowpan_llprefix[] = {0xfe, 0x80};
+ struct lowpan_dev_info {
+ struct net_device *real_dev; /* real WPAN device ptr */
+ struct mutex dev_list_mtx; /* mutex for list ops */
+- unsigned short fragment_tag;
++ unsigned short fragment_tag;
+ };
+
+ struct lowpan_dev_record {
diff --git a/patches/linux-3.8.13/0186-6lowpan-use-IEEE802154_ADDR_LEN-instead-of-a-magic-n.patch b/patches/linux-3.8.13/0186-6lowpan-use-IEEE802154_ADDR_LEN-instead-of-a-magic-n.patch
new file mode 100644
index 0000000..866f68a
--- /dev/null
+++ b/patches/linux-3.8.13/0186-6lowpan-use-IEEE802154_ADDR_LEN-instead-of-a-magic-n.patch
@@ -0,0 +1,22 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Wed, 27 Mar 2013 00:09:25 -0400
+Subject: [PATCH] 6lowpan: use IEEE802154_ADDR_LEN instead of a magic number
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index f4969d7..e1b4580 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -602,7 +602,7 @@ static int lowpan_header_create(struct sk_buff *skb,
+ da.short_addr = IEEE802154_ADDR_BROADCAST;
+ } else {
+ da.addr_type = IEEE802154_ADDR_LONG;
+- memcpy(&(da.hwaddr), daddr, 8);
++ memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
+
+ /* request acknowledgment */
+ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
diff --git a/patches/linux-3.8.13/0187-gpio-keys-Pinctrl-fy.patch b/patches/linux-3.8.13/0187-gpio-keys-Pinctrl-fy.patch
new file mode 100644
index 0000000..e9e90c7
--- /dev/null
+++ b/patches/linux-3.8.13/0187-gpio-keys-Pinctrl-fy.patch
@@ -0,0 +1,47 @@
+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 | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index b29ca65..97d7e05 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;
+@@ -692,6 +693,7 @@ static int 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);
+@@ -757,6 +759,18 @@ static int 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];
++ if (gpio_is_valid(bdata->button->gpio))
++ gpio_keys_gpio_report_event(bdata);
++ }
++ input_sync(input);
++
+ device_init_wakeup(&pdev->dev, wakeup);
+
+ return 0;
diff --git a/patches/linux-3.8.13/0188-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch b/patches/linux-3.8.13/0188-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
new file mode 100644
index 0000000..2ae0319
--- /dev/null
+++ b/patches/linux-3.8.13/0188-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
@@ -0,0 +1,194 @@
+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.8.13/0189-pwm-backlight-Pinctrl-fy.patch b/patches/linux-3.8.13/0189-pwm-backlight-Pinctrl-fy.patch
new file mode 100644
index 0000000..c18e0d5
--- /dev/null
+++ b/patches/linux-3.8.13/0189-pwm-backlight-Pinctrl-fy.patch
@@ -0,0 +1,36 @@
+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.8.13/0190-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch b/patches/linux-3.8.13/0190-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
new file mode 100644
index 0000000..57fafa6
--- /dev/null
+++ b/patches/linux-3.8.13/0190-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
@@ -0,0 +1,56 @@
+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 30c443c..cab6681 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)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
+
+diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
+index abfce28..131558f 100644
+--- a/arch/arm/boot/Makefile
++++ b/arch/arm/boot/Makefile
+@@ -55,6 +55,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
+
+ ifneq ($(LOADADDR),)
+@@ -80,6 +83,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.8.13/0191-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch b/patches/linux-3.8.13/0191-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
new file mode 100644
index 0000000..1615a2c
--- /dev/null
+++ b/patches/linux-3.8.13/0191-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
@@ -0,0 +1,640 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 18 Jan 2013 09:19:38 +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 | 290 +++++++++++++++++++++++++++++
+ arch/arm/boot/dts/am335x-bone.dts | 281 +---------------------------
+ arch/arm/boot/dts/am335x-boneblack.dts | 20 ++
+ 4 files changed, 313 insertions(+), 281 deletions(-)
+ create mode 100644 arch/arm/boot/dts/am335x-bone-common.dtsi
+ create mode 100644 arch/arm/boot/dts/am335x-boneblack.dts
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 5ebb44f..8f8c0c8 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -113,7 +113,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
+ omap5-evm.dtb \
+ am335x-evm.dtb \
+ am335x-evmsk.dtb \
+- am335x-bone.dtb
++ am335x-bone.dtb \
++ am335x-boneblack.dtb
+ dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
+ dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+ dtb-$(CONFIG_ARCH_U8500) += snowball.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..9a7be8a
+--- /dev/null
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -0,0 +1,290 @@
++/*
++ * 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 */
++ };
++
++ am33xx_pinmux: pinmux@44e10800 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&user_leds_s0 &spi1_pins_s0 &lcd_pins_s0 &gpevt_pins_s0>;
++
++ user_leds_s0: user_leds_s0 {
++ 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 */
++ >;
++ };
++
++ spi1_pins_s0: spi1_pins_s0 {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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_s0: lcd_pins_s0 {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
++
++ gpevt_pins_s0: gpevt_pins_s0 {
++ 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";
++ };
++
++ uart5: serial@481a8000 {
++ 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";
++ dmas = <&edma 12>;
++ dma-names = "gpioevt";
++ gpio-evt = <&gpio3 2 0>;
++ };
++
++ rtc@44e3e000 {
++ ti,system-power-controller;
++ };
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led@2 {
++ label = "beaglebone:green:heartbeat";
++ gpios = <&gpio2 21 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ led@3 {
++ label = "beaglebone:green:mmc0";
++ gpios = <&gpio2 22 0>;
++ linux,default-trigger = "mmc0";
++ default-state = "off";
++ };
++
++ led@4 {
++ label = "beaglebone:green:usr2";
++ gpios = <&gpio2 23 0>;
++ default-state = "off";
++ };
++
++ led@5 {
++ label = "beaglebone:green:usr3";
++ gpios = <&gpio2 24 0>;
++ default-state = "off";
++ };
++ };
++};
++
++&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 {
++ ti,pmic-shutdown-controller;
++
++ 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;
++ };
++ };
++};
++
++&cpsw_emac0 {
++ phy_id = <&davinci_mdio>, <0>;
++};
++
++&cpsw_emac1 {
++ phy_id = <&davinci_mdio>, <1>;
++};
++
++&mmc1 {
++ status = "okay";
++ vmmc-supply = <&ldo3_reg>;
++};
++
++&spi1 {
++ status = "okay";
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++};
++
++&edma {
++ ti,edma-xbar-event-map = <32 12>;
++};
++
++&sham {
++ status = "okay";
++};
++
++&aes {
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index bf87ceb..9abc1f3 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -9,283 +9,4 @@
+
+ /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 */
+- };
+-
+- am33xx_pinmux: pinmux@44e10800 {
+- pinctrl-names = "default";
+- pinctrl-0 = <&user_leds_s0 &spi1_pins_s0 &lcd_pins_s0 &gpevt_pins_s0>;
+-
+- user_leds_s0: user_leds_s0 {
+- 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 */
+- >;
+- };
+-
+- spi1_pins_s0: spi1_pins_s0 {
+- pinctrl-single,pins = <
+- 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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_s0: lcd_pins_s0 {
+- pinctrl-single,pins = <
+- 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
+- 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+- >;
+- };
+-
+- gpevt_pins_s0: gpevt_pins_s0 {
+- 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";
+- };
+-
+- uart5: serial@481a8000 {
+- 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";
+- dmas = <&edma 12>;
+- dma-names = "gpioevt";
+- gpio-evt = <&gpio3 2 0>;
+- };
+-
+- rtc@44e3e000 {
+- ti,system-power-controller;
+- };
+- };
+-
+- leds {
+- compatible = "gpio-leds";
+-
+- led@2 {
+- label = "beaglebone:green:heartbeat";
+- gpios = <&gpio2 21 0>;
+- linux,default-trigger = "heartbeat";
+- default-state = "off";
+- };
+-
+- led@3 {
+- label = "beaglebone:green:mmc0";
+- gpios = <&gpio2 22 0>;
+- linux,default-trigger = "mmc0";
+- default-state = "off";
+- };
+-
+- led@4 {
+- label = "beaglebone:green:usr2";
+- gpios = <&gpio2 23 0>;
+- default-state = "off";
+- };
+-
+- led@5 {
+- label = "beaglebone:green:usr3";
+- gpios = <&gpio2 24 0>;
+- default-state = "off";
+- };
+- };
+-};
+-
+-&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 {
+- ti,pmic-shutdown-controller;
+-
+- 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;
+- };
+- };
+-};
+-
+-&cpsw_emac0 {
+- phy_id = <&davinci_mdio>, <0>;
+-};
+-
+-&cpsw_emac1 {
+- phy_id = <&davinci_mdio>, <1>;
+-};
+-
+-&mmc1 {
+- status = "okay";
+- vmmc-supply = <&ldo3_reg>;
+-};
+-
+-&spi1 {
+- status = "okay";
+-
+- lcd@0 {
+- compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
+- spi-max-frequency = <8000000>;
+- reg = <0>;
+- spi-cpol;
+- spi-cpha;
+- st7735-rst = <&gpio4 19 0>;
+- st7735-dc = <&gpio4 21 0>;
+- };
+-};
+-
+-&edma {
+- ti,edma-xbar-event-map = <32 12>;
+-};
+-
+-&sham {
+- status = "okay";
+-};
+-
+-&aes {
+- status = "okay";
+-};
++/include/ "am335x-bone-common.dtsi"
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+new file mode 100644
+index 0000000..cdc3dd0
+--- /dev/null
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -0,0 +1,20 @@
++/*
++ * 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/ "am33xx.dtsi"
++
++/include/ "am335x-bone-common.dtsi"
++
++&mmc2 {
++ vmmc-supply = <&ldo3_reg>;
++ bus-width = <4>;
++ ti,non-removable;
++ status = "okay";
++};
++
diff --git a/patches/linux-3.8.13/0192-beaglebone-enable-emmc-for-bonelt.patch b/patches/linux-3.8.13/0192-beaglebone-enable-emmc-for-bonelt.patch
new file mode 100644
index 0000000..ccaaff5
--- /dev/null
+++ b/patches/linux-3.8.13/0192-beaglebone-enable-emmc-for-bonelt.patch
@@ -0,0 +1,48 @@
+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-boneblack.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 9a7be8a..8295b30 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -112,6 +112,7 @@
+ label = "beaglebone:green:usr3";
+ gpios = <&gpio2 24 0>;
+ default-state = "off";
++ linux,default-trigger = "mmc1";
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index cdc3dd0..6cb2a51 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -11,6 +11,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.8.13/0193-Fix-appended-dtb-rule.patch b/patches/linux-3.8.13/0193-Fix-appended-dtb-rule.patch
new file mode 100644
index 0000000..c28db15
--- /dev/null
+++ b/patches/linux-3.8.13/0193-Fix-appended-dtb-rule.patch
@@ -0,0 +1,36 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Sun, 30 Dec 2012 14:53:19 +0100
+Subject: [PATCH] Fix appended dtb rule
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/Makefile | 2 +-
+ arch/arm/boot/Makefile | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index cab6681..da4434d 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -291,7 +291,7 @@ zImage Image xipImage bootpImage uImage: vmlinux
+ zinstall uinstall install: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
+
+-uImage-dtb.%:
++uImage-dtb.%: scripts
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+ %.dtb: scripts
+diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
+index 131558f..e37ebb5 100644
+--- a/arch/arm/boot/Makefile
++++ b/arch/arm/boot/Makefile
+@@ -55,7 +55,7 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+ $(call if_changed,objcopy)
+ @$(kecho) ' Kernel: $@ is ready'
+
+-$(obj)/zImage-dtb.%: $(obj)/%.dtb $(obj)/zImage
++$(obj)/zImage-dtb.%: $(obj)/dts/%.dtb $(obj)/zImage
+ cat $(obj)/zImage $< > $@
+
+ endif
diff --git a/patches/linux-3.8.13/0194-deb-pkg-Simplify-architecture-matching-for-cross-bui.patch b/patches/linux-3.8.13/0194-deb-pkg-Simplify-architecture-matching-for-cross-bui.patch
new file mode 100644
index 0000000..3fc1c21
--- /dev/null
+++ b/patches/linux-3.8.13/0194-deb-pkg-Simplify-architecture-matching-for-cross-bui.patch
@@ -0,0 +1,135 @@
+From: maximilian attems <max@xxxxxxx>
+Date: Thu, 6 Sep 2012 15:22:02 +0200
+Subject: [PATCH] deb-pkg: Simplify architecture matching for cross building
+
+No point in invoking dpkg to get the archticture of the host
+we build on. Instead directly use the logic implemented
+in create_package(). No need anymore to override arch.
+
+While at it fix the linux images to be for the specific
+built arch.
+
+Signed-off-by: maximilian attems <max@xxxxxxx>
+---
+ scripts/package/builddeb | 81 ++++++++++++++++++++++------------------------
+ 1 file changed, 38 insertions(+), 43 deletions(-)
+
+diff --git a/scripts/package/builddeb b/scripts/package/builddeb
+index acb8650..a5f197b 100644
+--- a/scripts/package/builddeb
++++ b/scripts/package/builddeb
+@@ -25,44 +25,8 @@ create_package() {
+ chown -R root:root "$pdir"
+ chmod -R go-w "$pdir"
+
+- # Attempt to find the correct Debian architecture
+- local forcearch="" debarch=""
+- case "$UTS_MACHINE" in
+- i386|ia64|alpha)
+- debarch="$UTS_MACHINE" ;;
+- x86_64)
+- debarch=amd64 ;;
+- sparc*)
+- debarch=sparc ;;
+- s390*)
+- debarch=s390 ;;
+- ppc*)
+- debarch=powerpc ;;
+- parisc*)
+- debarch=hppa ;;
+- mips*)
+- debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
+- arm*)
+- debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
+- *)
+- echo "" >&2
+- echo "** ** ** WARNING ** ** **" >&2
+- echo "" >&2
+- echo "Your architecture doesn't have it's equivalent" >&2
+- echo "Debian userspace architecture defined!" >&2
+- echo "Falling back to using your current userspace instead!" >&2
+- echo "Please add support for $UTS_MACHINE to ${0} ..." >&2
+- echo "" >&2
+- esac
+- if [ -n "$KBUILD_DEBARCH" ] ; then
+- debarch="$KBUILD_DEBARCH"
+- fi
+- if [ -n "$debarch" ] ; then
+- forcearch="-DArchitecture=$debarch"
+- fi
+-
+ # Create the package
+- dpkg-gencontrol -isp $forcearch -p$pname -P"$pdir"
++ dpkg-gencontrol -p$pname -P"$pdir"
+ dpkg --build "$pdir" ..
+ }
+
+@@ -83,6 +47,38 @@ fwpackagename=linux-firmware-image
+ kernel_headers_packagename=linux-headers-$version
+ libc_headers_packagename=linux-libc-dev
+
++# Attempt to find the correct Debian architecture
++case "$UTS_MACHINE" in
++i386|ia64|alpha)
++ debarch="$UTS_MACHINE" ;;
++x86_64)
++ debarch=amd64 ;;
++sparc*)
++ debarch=sparc ;;
++s390*)
++ debarch=s390 ;;
++ppc*)
++ debarch=powerpc ;;
++parisc*)
++ debarch=hppa ;;
++mips*)
++ debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
++arm*)
++ debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
++*)
++ echo "" >&2
++ echo "** ** ** WARNING ** ** **" >&2
++ echo "" >&2
++ echo "Your architecture doesn't have it's equivalent" >&2
++ echo "Debian userspace architecture defined!" >&2
++ echo "Falling back to using your current userspace instead!" >&2
++ echo "Please add support for $UTS_MACHINE to ${0} ..." >&2
++ echo "" >&2
++esac
++if [ -n "$KBUILD_DEBARCH" ] ; then
++ debarch="$KBUILD_DEBARCH"
++fi
++
+ if [ "$ARCH" = "um" ] ; then
+ packagename=user-mode-linux-$version
+ fi
+@@ -234,8 +230,8 @@ else
+ Package: $packagename
+ Provides: linux-image, linux-image-2.6, linux-modules-$version
+ Suggests: $fwpackagename
+-Architecture: any
+-Description: Linux kernel, version $version
++Architecture: $debarch
++Description: Linux kernel, version $version on $debarch
+ This package contains the Linux kernel, modules and corresponding other
+ files, version: $version.
+ EOF
+@@ -252,15 +248,14 @@ mkdir -p "$destdir"
+ (cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -)
+ ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
+ rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
+-arch=$(dpkg --print-architecture)
+
+ cat <<EOF >> debian/control
+
+ Package: $kernel_headers_packagename
++Architecture: $debarch
+ Provides: linux-headers, linux-headers-2.6
+-Architecture: $arch
+-Description: Linux kernel headers for $KERNELRELEASE on $arch
+- This package provides kernel header files for $KERNELRELEASE on $arch
++Description: Linux kernel headers for $KERNELRELEASE on $debarch
++ This package provides kernel header files for $KERNELRELEASE on $debarch
+ .
+ This is useful for people who need to build external modules
+ EOF
diff --git a/patches/linux-3.8.13/0195-Without-MACH_-option-Early-printk-DEBUG_LL.patch b/patches/linux-3.8.13/0195-Without-MACH_-option-Early-printk-DEBUG_LL.patch
new file mode 100644
index 0000000..4f2ae41
--- /dev/null
+++ b/patches/linux-3.8.13/0195-Without-MACH_-option-Early-printk-DEBUG_LL.patch
@@ -0,0 +1,105 @@
+From: "hvaibhav@ti.com" <hvaibhav@ti.com>
+Date: Fri, 31 Aug 2012 16:47:12 +0000
+Subject: [PATCH] Without MACH_ option Early printk (DEBUG_LL)
+
+On Fri, Aug 31, 2012 at 22:07:37, Hiremath, Vaibhav wrote:
+> On Fri, Aug 31, 2012 at 21:41:22, Tony Lindgren wrote:
+> > * Hiremath, Vaibhav <hvaibhav@ti.com> [120831 09:06]:
+> > > On Fri, Aug 31, 2012 at 21:22:26, Tony Lindgren wrote:
+> > > > * Vaibhav Hiremath <hvaibhav@ti.com> [120831 07:55]:
+> > > > > Hi Russell & Tony,
+> > > > >
+> > > > > AM335X EVM (based on AM33XX device) only supports DT boot mode and
+> > > > > doesn't have CONFIG_MACH_AM335XEVM option defined. Some time back during
+> > > > > baseport submission we had aligned that, we won't create separate EVM
+> > > > > options, killing the board file all-together.
+> > > > >
+> > > > > Having said that, the early printk option (DEBUG_LL) is broken, the
+> > > > > auto-generated file "./include/generated/mach-types.h" still refers to
+> > > > > CONFIG_MACH_AM335XEVM option,
+> > > >
+> > > > The way we're heading is that the DEBUG_LL options will only work for
+> > > > one hardcoded machine where you need to select the uart type and address
+> > > > in Kconfig. Or just patch it in.
+> > > >
+> > > > > #ifdef CONFIG_MACH_AM335XEVM
+> > > > > # ifdef machine_arch_type
+> > > > > # undef machine_arch_type
+> > > > > # define machine_arch_type __machine_arch_type
+> > > > > # else
+> > > > > # define machine_arch_type MACH_TYPE_AM335XEVM
+> > > > > # endif
+> > > > > # define machine_is_am335xevm() (machine_arch_type == MACH_TYPE_AM335XEVM)
+> > > > > #else
+> > > > > # define machine_is_am335xevm() (0)
+> > > > > #endif
+> > > > >
+> > > > >
+> > > > > So I am thinking of changing the config_xxx option to SOC_AM33XX or
+> > > > > ARCH_OMAP2PLUS, something like below,
+> > > > >
+> > > > > am335xevm SOC_AM33XX AM335XEVM 3589
+> > > > >
+> > > > > OR
+> > > > >
+> > > > > am335xevm ARCH_OMAP2PLUS AM335XEVM 3589
+> > > > >
+> > > > >
+> > > > > Can you comment on this? Based on that I will submit the patch.
+> > > >
+> > > > I think that would at minimum break things for autogenerated
+> > > > mach-types.h where if only some other non-am335xevm machine is
+> > > > selected (like omap-generic) things don't get optimized out any
+> > > > longer as they currently do.
+> > > >
+> > >
+> > > Agreed. In that case the first option should work here, right?
+> >
+> > It gets messy if we start mixing mach and soc defines there..
+> >
+> > How about just add a hidden Kconfig option to mach-omap2/Kconfig
+> > that always selects MACH_TYPE_AM335XEVM if SOC_AM33XX is set?
+>
+> Great, this is what I had in my mind but since it is hidden option I thought
+> may not be right thing to do.
+> I was just thinking in the direction that, it should be logical and fine if
+> SOC_AM33XX is used for all AM33xx based machines, isn't it?
+>
+> Anyway, I think we are on same page here, I will add it and submit the patch
+> ASAP.
+>
+> > Or does that require that MACHINE_START is there as well?
+> >
+>
+> I do not think so, they are not related to each other, this option is
+> required only during decompression.
+> I have tested it on BeagleBone and it is working.
+>
+
+Can you please review below patch? If you think its ok, I will send the
+patch -
+
+Thanks,
+Vaibhav
+
+Conflicts:
+
+ arch/arm/mach-omap2/Kconfig
+---
+ arch/arm/mach-omap2/Kconfig | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
+index ce05b87..9cbbd2b 100644
+--- a/arch/arm/mach-omap2/Kconfig
++++ b/arch/arm/mach-omap2/Kconfig
+@@ -120,6 +120,9 @@ config SOC_AM33XX
+ select CPU_V7
+ select MULTI_IRQ_HANDLER
+ select COMMON_CLK
++ select MACH_AM335XEVM
++ select MACH_AM335XIAEVM
++ select MACH_TAM335X
+
+ config OMAP_PACKAGE_ZAF
+ bool
diff --git a/patches/linux-3.8.13/0196-ARM-7668-1-fix-memset-related-crashes-caused-by-rece.patch b/patches/linux-3.8.13/0196-ARM-7668-1-fix-memset-related-crashes-caused-by-rece.patch
new file mode 100644
index 0000000..240530a
--- /dev/null
+++ b/patches/linux-3.8.13/0196-ARM-7668-1-fix-memset-related-crashes-caused-by-rece.patch
@@ -0,0 +1,252 @@
+From: Ivan Djelic <ivan.djelic@parrot.com>
+Date: Wed, 6 Mar 2013 20:09:27 +0100
+Subject: [PATCH] ARM: 7668/1: fix memset-related crashes caused by recent GCC
+ (4.7.2) optimizations
+
+Recent GCC versions (e.g. GCC-4.7.2) perform optimizations based on
+assumptions about the implementation of memset and similar functions.
+The current ARM optimized memset code does not return the value of
+its first argument, as is usually expected from standard implementations.
+
+For instance in the following function:
+
+void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter)
+{
+ memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter));
+ waiter->magic = waiter;
+ INIT_LIST_HEAD(&waiter->list);
+}
+
+compiled as:
+
+800554d0 <debug_mutex_lock_common>:
+800554d0: e92d4008 push {r3, lr}
+800554d4: e1a00001 mov r0, r1
+800554d8: e3a02010 mov r2, #16 ; 0x10
+800554dc: e3a01011 mov r1, #17 ; 0x11
+800554e0: eb04426e bl 80165ea0 <memset>
+800554e4: e1a03000 mov r3, r0
+800554e8: e583000c str r0, [r3, #12]
+800554ec: e5830000 str r0, [r3]
+800554f0: e5830004 str r0, [r3, #4]
+800554f4: e8bd8008 pop {r3, pc}
+
+GCC assumes memset returns the value of pointer 'waiter' in register r0; causing
+register/memory corruptions.
+
+This patch fixes the return value of the assembly version of memset.
+It adds a 'mov' instruction and merges an additional load+store into
+existing load/store instructions.
+For ease of review, here is a breakdown of the patch into 4 simple steps:
+
+Step 1
+======
+Perform the following substitutions:
+ip -> r8, then
+r0 -> ip,
+and insert 'mov ip, r0' as the first statement of the function.
+At this point, we have a memset() implementation returning the proper result,
+but corrupting r8 on some paths (the ones that were using ip).
+
+Step 2
+======
+Make sure r8 is saved and restored when (! CALGN(1)+0) == 1:
+
+save r8:
+- str lr, [sp, #-4]!
++ stmfd sp!, {r8, lr}
+
+and restore r8 on both exit paths:
+- ldmeqfd sp!, {pc} @ Now <64 bytes to go.
++ ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
+(...)
+ tst r2, #16
+ stmneia ip!, {r1, r3, r8, lr}
+- ldr lr, [sp], #4
++ ldmfd sp!, {r8, lr}
+
+Step 3
+======
+Make sure r8 is saved and restored when (! CALGN(1)+0) == 0:
+
+save r8:
+- stmfd sp!, {r4-r7, lr}
++ stmfd sp!, {r4-r8, lr}
+
+and restore r8 on both exit paths:
+ bgt 3b
+- ldmeqfd sp!, {r4-r7, pc}
++ ldmeqfd sp!, {r4-r8, pc}
+(...)
+ tst r2, #16
+ stmneia ip!, {r4-r7}
+- ldmfd sp!, {r4-r7, lr}
++ ldmfd sp!, {r4-r8, lr}
+
+Step 4
+======
+Rewrite register list "r4-r7, r8" as "r4-r8".
+
+Signed-off-by: Ivan Djelic <ivan.djelic@parrot.com>
+Reviewed-by: Nicolas Pitre <nico@linaro.org>
+Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ arch/arm/lib/memset.S | 85 +++++++++++++++++++++++++------------------------
+ 1 file changed, 44 insertions(+), 41 deletions(-)
+
+diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
+index 650d592..d912e73 100644
+--- a/arch/arm/lib/memset.S
++++ b/arch/arm/lib/memset.S
+@@ -19,9 +19,9 @@
+ 1: subs r2, r2, #4 @ 1 do we have enough
+ blt 5f @ 1 bytes to align with?
+ cmp r3, #2 @ 1
+- strltb r1, [r0], #1 @ 1
+- strleb r1, [r0], #1 @ 1
+- strb r1, [r0], #1 @ 1
++ strltb r1, [ip], #1 @ 1
++ strleb r1, [ip], #1 @ 1
++ strb r1, [ip], #1 @ 1
+ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
+ /*
+ * The pointer is now aligned and the length is adjusted. Try doing the
+@@ -29,10 +29,14 @@
+ */
+
+ ENTRY(memset)
+- ands r3, r0, #3 @ 1 unaligned?
++/*
++ * Preserve the contents of r0 for the return value.
++ */
++ mov ip, r0
++ ands r3, ip, #3 @ 1 unaligned?
+ bne 1b @ 1
+ /*
+- * we know that the pointer in r0 is aligned to a word boundary.
++ * we know that the pointer in ip is aligned to a word boundary.
+ */
+ orr r1, r1, r1, lsl #8
+ orr r1, r1, r1, lsl #16
+@@ -43,29 +47,28 @@ ENTRY(memset)
+ #if ! CALGN(1)+0
+
+ /*
+- * We need an extra register for this loop - save the return address and
+- * use the LR
++ * We need 2 extra registers for this loop - use r8 and the LR
+ */
+- str lr, [sp, #-4]!
+- mov ip, r1
++ stmfd sp!, {r8, lr}
++ mov r8, r1
+ mov lr, r1
+
+ 2: subs r2, r2, #64
+- stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
+- stmgeia r0!, {r1, r3, ip, lr}
+- stmgeia r0!, {r1, r3, ip, lr}
+- stmgeia r0!, {r1, r3, ip, lr}
++ stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time.
++ stmgeia ip!, {r1, r3, r8, lr}
++ stmgeia ip!, {r1, r3, r8, lr}
++ stmgeia ip!, {r1, r3, r8, lr}
+ bgt 2b
+- ldmeqfd sp!, {pc} @ Now <64 bytes to go.
++ ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
+ /*
+ * No need to correct the count; we're only testing bits from now on
+ */
+ tst r2, #32
+- stmneia r0!, {r1, r3, ip, lr}
+- stmneia r0!, {r1, r3, ip, lr}
++ stmneia ip!, {r1, r3, r8, lr}
++ stmneia ip!, {r1, r3, r8, lr}
+ tst r2, #16
+- stmneia r0!, {r1, r3, ip, lr}
+- ldr lr, [sp], #4
++ stmneia ip!, {r1, r3, r8, lr}
++ ldmfd sp!, {r8, lr}
+
+ #else
+
+@@ -74,54 +77,54 @@ ENTRY(memset)
+ * whole cache lines at once.
+ */
+
+- stmfd sp!, {r4-r7, lr}
++ stmfd sp!, {r4-r8, lr}
+ mov r4, r1
+ mov r5, r1
+ mov r6, r1
+ mov r7, r1
+- mov ip, r1
++ mov r8, r1
+ mov lr, r1
+
+ cmp r2, #96
+- tstgt r0, #31
++ tstgt ip, #31
+ ble 3f
+
+- and ip, r0, #31
+- rsb ip, ip, #32
+- sub r2, r2, ip
+- movs ip, ip, lsl #(32 - 4)
+- stmcsia r0!, {r4, r5, r6, r7}
+- stmmiia r0!, {r4, r5}
+- tst ip, #(1 << 30)
+- mov ip, r1
+- strne r1, [r0], #4
++ and r8, ip, #31
++ rsb r8, r8, #32
++ sub r2, r2, r8
++ movs r8, r8, lsl #(32 - 4)
++ stmcsia ip!, {r4, r5, r6, r7}
++ stmmiia ip!, {r4, r5}
++ tst r8, #(1 << 30)
++ mov r8, r1
++ strne r1, [ip], #4
+
+ 3: subs r2, r2, #64
+- stmgeia r0!, {r1, r3-r7, ip, lr}
+- stmgeia r0!, {r1, r3-r7, ip, lr}
++ stmgeia ip!, {r1, r3-r8, lr}
++ stmgeia ip!, {r1, r3-r8, lr}
+ bgt 3b
+- ldmeqfd sp!, {r4-r7, pc}
++ ldmeqfd sp!, {r4-r8, pc}
+
+ tst r2, #32
+- stmneia r0!, {r1, r3-r7, ip, lr}
++ stmneia ip!, {r1, r3-r8, lr}
+ tst r2, #16
+- stmneia r0!, {r4-r7}
+- ldmfd sp!, {r4-r7, lr}
++ stmneia ip!, {r4-r7}
++ ldmfd sp!, {r4-r8, lr}
+
+ #endif
+
+ 4: tst r2, #8
+- stmneia r0!, {r1, r3}
++ stmneia ip!, {r1, r3}
+ tst r2, #4
+- strne r1, [r0], #4
++ strne r1, [ip], #4
+ /*
+ * When we get here, we've got less than 4 bytes to zero. We
+ * may have an unaligned pointer as well.
+ */
+ 5: tst r2, #2
+- strneb r1, [r0], #1
+- strneb r1, [r0], #1
++ strneb r1, [ip], #1
++ strneb r1, [ip], #1
+ tst r2, #1
+- strneb r1, [r0], #1
++ strneb r1, [ip], #1
+ mov pc, lr
+ ENDPROC(memset)
diff --git a/patches/linux-3.8.13/0197-ARM-7670-1-fix-the-memset-fix.patch b/patches/linux-3.8.13/0197-ARM-7670-1-fix-the-memset-fix.patch
new file mode 100644
index 0000000..b13ef7e
--- /dev/null
+++ b/patches/linux-3.8.13/0197-ARM-7670-1-fix-the-memset-fix.patch
@@ -0,0 +1,79 @@
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+Date: Tue, 12 Mar 2013 13:00:42 +0100
+Subject: [PATCH] ARM: 7670/1: fix the memset fix
+
+Commit 455bd4c430b0 ("ARM: 7668/1: fix memset-related crashes caused by
+recent GCC (4.7.2) optimizations") attempted to fix a compliance issue
+with the memset return value. However the memset itself became broken
+by that patch for misaligned pointers.
+
+This fixes the above by branching over the entry code from the
+misaligned fixup code to avoid reloading the original pointer.
+
+Also, because the function entry alignment is wrong in the Thumb mode
+compilation, that fixup code is moved to the end.
+
+While at it, the entry instructions are slightly reworked to help dual
+issue pipelines.
+
+Signed-off-by: Nicolas Pitre <nico@linaro.org>
+Tested-by: Alexander Holler <holler@ahsoftware.de>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ arch/arm/lib/memset.S | 33 +++++++++++++--------------------
+ 1 file changed, 13 insertions(+), 20 deletions(-)
+
+diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
+index d912e73..94b0650 100644
+--- a/arch/arm/lib/memset.S
++++ b/arch/arm/lib/memset.S
+@@ -14,31 +14,15 @@
+
+ .text
+ .align 5
+- .word 0
+-
+-1: subs r2, r2, #4 @ 1 do we have enough
+- blt 5f @ 1 bytes to align with?
+- cmp r3, #2 @ 1
+- strltb r1, [ip], #1 @ 1
+- strleb r1, [ip], #1 @ 1
+- strb r1, [ip], #1 @ 1
+- add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
+-/*
+- * The pointer is now aligned and the length is adjusted. Try doing the
+- * memset again.
+- */
+
+ ENTRY(memset)
+-/*
+- * Preserve the contents of r0 for the return value.
+- */
+- mov ip, r0
+- ands r3, ip, #3 @ 1 unaligned?
+- bne 1b @ 1
++ ands r3, r0, #3 @ 1 unaligned?
++ mov ip, r0 @ preserve r0 as return value
++ bne 6f @ 1
+ /*
+ * we know that the pointer in ip is aligned to a word boundary.
+ */
+- orr r1, r1, r1, lsl #8
++1: orr r1, r1, r1, lsl #8
+ orr r1, r1, r1, lsl #16
+ mov r3, r1
+ cmp r2, #16
+@@ -127,4 +111,13 @@ ENTRY(memset)
+ tst r2, #1
+ strneb r1, [ip], #1
+ mov pc, lr
++
++6: subs r2, r2, #4 @ 1 do we have enough
++ blt 5b @ 1 bytes to align with?
++ cmp r3, #2 @ 1
++ strltb r1, [ip], #1 @ 1
++ strleb r1, [ip], #1 @ 1
++ strb r1, [ip], #1 @ 1
++ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
++ b 1b
+ ENDPROC(memset)
diff --git a/patches/linux-3.8.13/0198-regulator-core-if-voltage-scaling-fails-restore-orig.patch b/patches/linux-3.8.13/0198-regulator-core-if-voltage-scaling-fails-restore-orig.patch
new file mode 100644
index 0000000..8e274e3
--- /dev/null
+++ b/patches/linux-3.8.13/0198-regulator-core-if-voltage-scaling-fails-restore-orig.patch
@@ -0,0 +1,53 @@
+From: Paolo Pisati <paolo.pisati@canonical.com>
+Date: Wed, 12 Dec 2012 12:45:53 +0100
+Subject: [PATCH] regulator: core: if voltage scaling fails, restore original
+ voltage values
+
+Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
+---
+ drivers/regulator/core.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
+index 5a0f54a..8e7ec07 100644
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -2294,6 +2294,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
+ {
+ struct regulator_dev *rdev = regulator->rdev;
+ int ret = 0;
++ int old_min_uV, old_max_uV;
+
+ mutex_lock(&rdev->mutex);
+
+@@ -2315,18 +2316,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
+ ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
+ if (ret < 0)
+ goto out;
++
++ /* restore original values in case of error */
++ old_min_uV = regulator->min_uV;
++ old_max_uV = regulator->max_uV;
+ regulator->min_uV = min_uV;
+ regulator->max_uV = max_uV;
+
+ ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
+ if (ret < 0)
+- goto out;
++ goto out2;
+
+ ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
++ if (ret < 0)
++ goto out2;
+
+ out:
+ mutex_unlock(&rdev->mutex);
+ return ret;
++out2:
++ regulator->min_uV = old_min_uV;
++ regulator->max_uV = old_max_uV;
++ mutex_unlock(&rdev->mutex);
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(regulator_set_voltage);
+
diff --git a/patches/linux-3.8.13/0199-omap2-twl-common-Add-default-power-configuration.patch b/patches/linux-3.8.13/0199-omap2-twl-common-Add-default-power-configuration.patch
new file mode 100644
index 0000000..32be8ab
--- /dev/null
+++ b/patches/linux-3.8.13/0199-omap2-twl-common-Add-default-power-configuration.patch
@@ -0,0 +1,84 @@
+From: Matthias Brugger <matthias.bgg@gmail.com>
+Date: Wed, 23 Jan 2013 19:50:38 +0100
+Subject: [PATCH] omap2: twl-common: Add default power configuration
+
+This patch adds a generic power script configuration.
+When rebooting an OMAP3530 at 125 MHz, the reboot hangs.
+With the generic power script, TWL4030 will be reset
+when a warm reset occures. This way the OMAP3530 does not
+hang on reboot.
+
+Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
+---
+ arch/arm/mach-omap2/twl-common.c | 38 ++++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-omap2/twl-common.h | 1 +
+ 2 files changed, 39 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
+index e49b40b..f096beb 100644
+--- a/arch/arm/mach-omap2/twl-common.c
++++ b/arch/arm/mach-omap2/twl-common.c
+@@ -120,6 +120,41 @@ static struct twl4030_audio_data omap3_audio_pdata = {
+ .codec = &omap3_codec,
+ };
+
++static struct twl4030_ins wrst_seq[] __initdata = {
++ {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_OFF), 2},
++ {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_WRST), 15},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_WRST), 15},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_WRST), 0x60},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 2},
++ {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_ACTIVE), 2},
++};
++
++static struct twl4030_script wrst_script __initdata = {
++ .script = wrst_seq,
++ .size = ARRAY_SIZE(wrst_seq),
++ .flags = TWL4030_WRST_SCRIPT,
++};
++
++static struct twl4030_script *omap3_power_scripts[] __initdata = {
++ &wrst_script,
++};
++
++static struct twl4030_resconfig omap3_rconfig[] = {
++ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, .type = -1,
++ .type2 = -1 },
++ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1, .type = -1,
++ .type2 = -1 },
++ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1, .type = -1,
++ .type2 = -1 },
++ { 0, 0},
++};
++
++static struct twl4030_power_data omap3_power_pdata = {
++ .scripts = omap3_power_scripts,
++ .num = ARRAY_SIZE(omap3_power_scripts),
++ .resource_config = omap3_rconfig,
++};
++
+ static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = {
+ REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
+ };
+@@ -224,6 +259,9 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
+ if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
+ pmic_data->audio = &omap3_audio_pdata;
+
++ if (pdata_flags & TWL_COMMON_PDATA_POWER && !pmic_data->power)
++ pmic_data->power = &omap3_power_pdata;
++
+ /* Common regulator configurations */
+ if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
+ pmic_data->vdac = &omap3_vdac_idata;
+diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
+index dcfbad5..dbeb905 100644
+--- a/arch/arm/mach-omap2/twl-common.h
++++ b/arch/arm/mach-omap2/twl-common.h
+@@ -7,6 +7,7 @@
+ #define TWL_COMMON_PDATA_BCI (1 << 1)
+ #define TWL_COMMON_PDATA_MADC (1 << 2)
+ #define TWL_COMMON_PDATA_AUDIO (1 << 3)
++#define TWL_COMMON_PDATA_POWER (1 << 4)
+
+ /* Common LDO regulators for TWL4030/TWL6030 */
+ #define TWL_COMMON_REGULATOR_VDAC (1 << 0)
diff --git a/patches/linux-3.8.13/0200-omap2-irq-fix-interrupt-latency.patch b/patches/linux-3.8.13/0200-omap2-irq-fix-interrupt-latency.patch
new file mode 100644
index 0000000..72300bf
--- /dev/null
+++ b/patches/linux-3.8.13/0200-omap2-irq-fix-interrupt-latency.patch
@@ -0,0 +1,22 @@
+From: =?UTF-8?q?H=C3=A5kan=20Engblom?= <hkengblom@gmail.com>
+Date: Wed, 24 Apr 2013 10:53:46 +0200
+Subject: [PATCH] omap2 irq: fix interrupt latency
+
+The problem in my system was that interrutp latency for GPIO interrupts (GPIO used as interrupt source by use of "echo rising > /sys/class/gpio/gpioXX/edge") was _very_ long, probably until somother interrupt made GPIO interrupts "visable". The problem that the patch corrects is that also a AM33XX has four registers to check in the interrupt controller to find out which interrupt that caused the controlled to assert an interrupt.
+---
+ arch/arm/mach-omap2/irq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
+index 3926f37..57d1b7d 100644
+--- a/arch/arm/mach-omap2/irq.c
++++ b/arch/arm/mach-omap2/irq.c
+@@ -233,7 +233,7 @@ static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs
+ goto out;
+
+ irqnr = readl_relaxed(base_addr + 0xd8);
+-#ifdef CONFIG_SOC_TI81XX
++#if defined(CONFIG_SOC_TI81XX) || defined(CONFIG_SOC_AM33XX)
+ if (irqnr)
+ goto out;
+ irqnr = readl_relaxed(base_addr + 0xf8);
diff --git a/patches/linux-3.8.13/0201-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch b/patches/linux-3.8.13/0201-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch
new file mode 100644
index 0000000..7ccd5c3
--- /dev/null
+++ b/patches/linux-3.8.13/0201-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch
@@ -0,0 +1,74 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Tue, 19 Jan 2010 21:19:15 -0800
+Subject: [PATCH] OMAP: DSS2: add bootarg for selecting svideo
+
+ OMAP: DSS2: add bootarg for selecting svideo or composite for tv output
+ also add pal-16 and ntsc-16 omapfb.mode settings for 16bpp
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/video/omap2/dss/venc.c | 22 ++++++++++++++++++++++
+ drivers/video/omap2/omapfb/omapfb-main.c | 10 +++++++++-
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index 006caf3..0e5b3b1 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -86,6 +86,11 @@
+ #define VENC_OUTPUT_TEST 0xC8
+ #define VENC_DAC_B__DAC_C 0xC8
+
++static char *tv_connection;
++
++module_param_named(tvcable, tv_connection, charp, 0);
++MODULE_PARM_DESC(tvcable, "TV connection type (svideo, composite)");
++
+ struct venc_config {
+ u32 f_control;
+ u32 vidout_ctrl;
+@@ -465,6 +470,23 @@ static int venc_power_on(struct omap_dss_device *dssdev)
+ if (r)
+ goto err2;
+
++ /* Allow the TV output to be overriden */
++ if (tv_connection) {
++ if (strcmp(tv_connection, "svideo") == 0) {
++ printk(KERN_INFO
++ "omapdss: tv output is svideo.\n");
++ dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
++ } else if (strcmp(tv_connection, "composite") == 0) {
++ printk(KERN_INFO
++ "omapdss: tv output is composite.\n");
++ dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
++ } else {
++ printk(KERN_INFO
++ "omapdss: unsupported output type'%s'.\n",
++ tv_connection);
++ }
++ }
++
+ return 0;
+
+ err2:
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index ca585ef..f3cfabb 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -2028,7 +2028,15 @@ static int omapfb_mode_to_timings(const char *mode_str,
+ int r;
+
+ #ifdef CONFIG_OMAP2_DSS_VENC
+- if (strcmp(mode_str, "pal") == 0) {
++ if (strcmp(mode_str, "pal-16") == 0) {
++ *timings = omap_dss_pal_timings;
++ *bpp = 16;
++ return 0;
++ } else if (strcmp(mode_str, "ntsc-16") == 0) {
++ *timings = omap_dss_ntsc_timings;
++ *bpp = 16;
++ return 0;
++ } else if (strcmp(mode_str, "pal") == 0) {
+ *timings = omap_dss_pal_timings;
+ *bpp = 24;
+ return 0;
diff --git a/patches/linux-3.8.13/0202-video-add-timings-for-hd720.patch b/patches/linux-3.8.13/0202-video-add-timings-for-hd720.patch
new file mode 100644
index 0000000..9034278
--- /dev/null
+++ b/patches/linux-3.8.13/0202-video-add-timings-for-hd720.patch
@@ -0,0 +1,24 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Sat, 19 Dec 2009 06:52:43 -0800
+Subject: [PATCH] video: add timings for hd720
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/video/modedb.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
+index a9a907c..5b686de 100644
+--- a/drivers/video/modedb.c
++++ b/drivers/video/modedb.c
+@@ -103,6 +103,10 @@ static const struct fb_videomode modedb[] = {
+ { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
+ FB_VMODE_NONINTERLACED },
+
++ /* 1280x720 @ 60 Hz, 45 kHz hsync, CEA 681-E Format 4 */
++ { "hd720", 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5, 0,
++ FB_VMODE_NONINTERLACED },
++
+ /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
+ { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0,
+ FB_VMODE_INTERLACED },
diff --git a/patches/linux-3.8.13/0203-Beagle-expansion-add-buddy-param-for-expansionboard-.patch b/patches/linux-3.8.13/0203-Beagle-expansion-add-buddy-param-for-expansionboard-.patch
new file mode 100644
index 0000000..1626e04
--- /dev/null
+++ b/patches/linux-3.8.13/0203-Beagle-expansion-add-buddy-param-for-expansionboard-.patch
@@ -0,0 +1,58 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:25:27 -0600
+Subject: [PATCH] Beagle: expansion: add buddy param for expansionboard names
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 22c483d..16fd530 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -21,6 +21,7 @@
+ #include <linux/io.h>
+ #include <linux/leds.h>
+ #include <linux/gpio.h>
++#include <linux/irq.h>
+ #include <linux/input.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/opp.h>
+@@ -162,6 +163,8 @@ static void __init omap3_beagle_init_rev(void)
+ }
+ }
+
++char expansionboard_name[16];
++
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+@@ -448,6 +451,18 @@ static struct omap_board_mux board_mux[] __initdata = {
+ };
+ #endif
+
++static int __init expansionboard_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(expansionboard_name, str, 16);
++ pr_info("Beagle expansionboard: %s\n", expansionboard_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -534,6 +549,8 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+ }
+
++early_param("buddy", expansionboard_setup);
++
+ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+ /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
+ .atag_offset = 0x100,
diff --git a/patches/linux-3.8.13/0204-Beagle-expansion-add-zippy.patch b/patches/linux-3.8.13/0204-Beagle-expansion-add-zippy.patch
new file mode 100644
index 0000000..3e36ea6
--- /dev/null
+++ b/patches/linux-3.8.13/0204-Beagle-expansion-add-zippy.patch
@@ -0,0 +1,238 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Mon, 21 Jan 2013 11:47:02 -0600
+Subject: [PATCH] Beagle: expansion: add zippy
+
+v2: add #include <linux/regulator/fixed.h>
+build fix from Pantelis Antoniou <panto@antoniou-consulting.com>
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 164 +++++++++++++++++++++++++++++--
+ 1 file changed, 158 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 16fd530..8f3ba5b 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -33,6 +33,7 @@
+ #include <linux/mmc/host.h>
+
+ #include <linux/regulator/machine.h>
++#include <linux/regulator/fixed.h>
+ #include <linux/i2c/twl.h>
+
+ #include <asm/mach-types.h>
+@@ -165,6 +166,86 @@ static void __init omap3_beagle_init_rev(void)
+
+ char expansionboard_name[16];
+
++enum {
++ EXPANSION_MMC_NONE = 0,
++ EXPANSION_MMC_ZIPPY,
++ EXPANSION_MMC_WIFI,
++};
++
++enum {
++ EXPANSION_I2C_NONE = 0,
++ EXPANSION_I2C_ZIPPY,
++};
++
++static struct {
++ int mmc_settings;
++ int i2c_settings;
++} expansion_config = {
++ .mmc_settings = EXPANSION_MMC_NONE,
++ .i2c_settings = EXPANSION_I2C_NONE,
++};
++
++//rcn-ee: this is just a fake regulator, the zippy hardware provides 3.3/1.8 with jumper..
++static struct fixed_voltage_config beagle_vzippy = {
++ .supply_name = "vzippy",
++ .microvolts = 3300000, /* 3.3V */
++ .startup_delay = 70000, /* 70ms */
++ .enable_high = 1,
++ .enabled_at_boot = 0,
++ .init_data = &beagle_vmmc2,
++};
++
++static struct platform_device omap_zippy_device = {
++ .name = "reg-fixed-voltage",
++ .id = 1,
++ .dev = {
++ .platform_data = &beagle_vzippy,
++ },
++};
++
++#define OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP 141
++#define OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD 162
++
++#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
++#include <linux/platform_data/spi-omap2-mcspi.h>
++#include <linux/spi/spi.h>
++
++#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
++
++static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
++ .turbo_mode = 0,
++};
++
++static struct spi_board_info omap3beagle_zippy_spi_board_info[] __initdata = {
++ {
++ .modalias = "enc28j60",
++ .bus_num = 4,
++ .chip_select = 0,
++ .max_speed_hz = 20000000,
++ .controller_data = &enc28j60_spi_chip_info,
++ },
++};
++
++static void __init omap3beagle_enc28j60_init(void)
++{
++ if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
++ (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
++ gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
++ omap3beagle_zippy_spi_board_info[0].irq = gpio_to_irq(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
++ irq_set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
++ } else {
++ pr_err("Beagle expansionboard: could not obtain gpio for ENC28J60_IRQ\n");
++ return;
++ }
++
++ spi_register_board_info(omap3beagle_zippy_spi_board_info,
++ ARRAY_SIZE(omap3beagle_zippy_spi_board_info));
++}
++
++#else
++static inline void __init omap3beagle_enc28j60_init(void) { return; }
++#endif
++
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+@@ -241,6 +322,23 @@ static struct omap2_hsmmc_info mmc[] = {
+ {} /* Terminator */
+ };
+
++static struct omap2_hsmmc_info mmc_zippy[] = {
++ {
++ .mmc = 1,
++ .caps = MMC_CAP_4_BIT_DATA,
++ .gpio_wp = -EINVAL,
++ .deferred = true,
++ },
++ {
++ .mmc = 2,
++ .caps = MMC_CAP_4_BIT_DATA,
++ .gpio_wp = OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP,
++ .gpio_cd = OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD,
++ .transceiver = true,
++ .deferred = true,
++ },
++ {} /* Terminator */
++};
+ static struct regulator_consumer_supply beagle_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+ };
+@@ -256,10 +354,21 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ {
+ int r;
+
+- mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
+- /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+- mmc[0].gpio_cd = gpio + 0;
+- omap_hsmmc_late_init(mmc);
++ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_ZIPPY:
++ mmc_zippy[0].gpio_wp = beagle_config.mmc1_gpio_wp;
++ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
++ mmc_zippy[0].gpio_cd = gpio + 0;
++
++ omap_hsmmc_late_init(mmc_zippy);
++ break;
++ default:
++ mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
++ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
++ mmc[0].gpio_cd = gpio + 0;
++
++ omap_hsmmc_late_init(mmc);
++ }
+
+ /*
+ * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
+@@ -352,6 +461,14 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+ },
+ };
+
++static struct i2c_board_info __initdata zippy_i2c2_rtc[] = {
++#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE)
++ {
++ I2C_BOARD_INFO("ds1307", 0x68),
++ },
++#endif
++};
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap3_pmic_get_config(&beagle_twldata,
+@@ -362,6 +479,15 @@ static int __init omap3_beagle_i2c_init(void)
+ beagle_twldata.vpll2->constraints.name = "VDVI";
+
+ omap3_pmic_init("twl4030", &beagle_twldata);
++
++ switch (expansion_config.i2c_settings) {
++ case EXPANSION_I2C_ZIPPY:
++ omap_register_i2c_bus(2, 400, zippy_i2c2_rtc, ARRAY_SIZE(zippy_i2c2_rtc));
++ break;
++ default:
++ omap_register_i2c_bus(2, 400, NULL, 0);
++ }
++
+ /* Bus 3 is attached to the DVI port where devices like the pico DLP
+ * projector don't work reliably with 400kHz */
+ omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
+@@ -516,10 +642,30 @@ static void __init omap3_beagle_init(void)
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+ omap3_beagle_init_rev();
+
++ if (!strcmp(expansionboard_name, "zippy"))
++ {
++ pr_info("Beagle expansionboard: initializing zippy mmc\n");
++ platform_device_register(&omap_zippy_device);
++
++ expansion_config.i2c_settings = EXPANSION_I2C_ZIPPY;
++ expansion_config.mmc_settings = EXPANSION_MMC_ZIPPY;
++
++ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP, OMAP_PIN_INPUT);
++ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
++ }
++
+ if (gpio_is_valid(beagle_config.mmc1_gpio_wp))
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+- mmc[0].caps = beagle_config.mmc_caps;
+- omap_hsmmc_init(mmc);
++
++ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_ZIPPY:
++ mmc_zippy[0].caps = beagle_config.mmc_caps;
++ omap_hsmmc_init(mmc_zippy);
++ break;
++ default:
++ mmc[0].caps = beagle_config.mmc_caps;
++ omap_hsmmc_init(mmc);
++ }
+
+ omap3_beagle_i2c_init();
+
+@@ -534,6 +680,12 @@ static void __init omap3_beagle_init(void)
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
+
++ if (!strcmp(expansionboard_name, "zippy"))
++ {
++ pr_info("Beagle expansionboard: initializing enc28j60\n");
++ omap3beagle_enc28j60_init();
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(omap3beagle_nand_partitions,
diff --git a/patches/linux-3.8.13/0205-Beagle-expansion-add-zippy2.patch b/patches/linux-3.8.13/0205-Beagle-expansion-add-zippy2.patch
new file mode 100644
index 0000000..98cc40f
--- /dev/null
+++ b/patches/linux-3.8.13/0205-Beagle-expansion-add-zippy2.patch
@@ -0,0 +1,82 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:32:15 -0600
+Subject: [PATCH] Beagle: expansion: add zippy2
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 48 ++++++++++++++++++++++++++++++-
+ 1 file changed, 47 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 8f3ba5b..5241e6e 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -246,6 +246,46 @@ static void __init omap3beagle_enc28j60_init(void)
+ static inline void __init omap3beagle_enc28j60_init(void) { return; }
+ #endif
+
++#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
++#include <linux/platform_data/spi-omap2-mcspi.h>
++#include <linux/spi/spi.h>
++
++#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157
++
++static struct omap2_mcspi_device_config ks8851_spi_chip_info = {
++ .turbo_mode = 0,
++};
++
++static struct spi_board_info omap3beagle_zippy2_spi_board_info[] __initdata = {
++ {
++ .modalias = "ks8851",
++ .bus_num = 4,
++ .chip_select = 0,
++ .max_speed_hz = 36000000,
++ .controller_data = &ks8851_spi_chip_info,
++ },
++};
++
++static void __init omap3beagle_ks8851_init(void)
++{
++ if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) &&
++ (gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) {
++ gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0);
++ omap3beagle_zippy2_spi_board_info[0].irq = gpio_to_irq(OMAP3BEAGLE_GPIO_KS8851_IRQ);
++ irq_set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
++ } else {
++ pr_err("Beagle expansionboard: could not obtain gpio for KS8851_IRQ\n");
++ return;
++ }
++
++ spi_register_board_info(omap3beagle_zippy2_spi_board_info,
++ ARRAY_SIZE(omap3beagle_zippy2_spi_board_info));
++}
++
++#else
++static inline void __init omap3beagle_ks8851_init(void) { return; }
++#endif
++
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+@@ -642,7 +682,7 @@ static void __init omap3_beagle_init(void)
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+ omap3_beagle_init_rev();
+
+- if (!strcmp(expansionboard_name, "zippy"))
++ if ((!strcmp(expansionboard_name, "zippy")) || (!strcmp(expansionboard_name, "zippy2")))
+ {
+ pr_info("Beagle expansionboard: initializing zippy mmc\n");
+ platform_device_register(&omap_zippy_device);
+@@ -686,6 +726,12 @@ static void __init omap3_beagle_init(void)
+ omap3beagle_enc28j60_init();
+ }
+
++ if (!strcmp(expansionboard_name, "zippy2"))
++ {
++ pr_info("Beagle expansionboard: initializing ks_8851\n");
++ omap3beagle_ks8851_init();
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(omap3beagle_nand_partitions,
diff --git a/patches/linux-3.8.13/0206-Beagle-expansion-add-trainer.patch b/patches/linux-3.8.13/0206-Beagle-expansion-add-trainer.patch
new file mode 100644
index 0000000..ddb2f26
--- /dev/null
+++ b/patches/linux-3.8.13/0206-Beagle-expansion-add-trainer.patch
@@ -0,0 +1,51 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:33:24 -0600
+Subject: [PATCH] Beagle: expansion: add trainer
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 5241e6e..a8ca83d 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -732,6 +732,37 @@ static void __init omap3_beagle_init(void)
+ omap3beagle_ks8851_init();
+ }
+
++ if (!strcmp(expansionboard_name, "trainer"))
++ {
++ pr_info("Beagle expansionboard: exporting GPIOs 130-141,162 to userspace\n");
++ gpio_request(130, "sysfs");
++ gpio_export(130, 1);
++ gpio_request(131, "sysfs");
++ gpio_export(131, 1);
++ gpio_request(132, "sysfs");
++ gpio_export(132, 1);
++ gpio_request(133, "sysfs");
++ gpio_export(133, 1);
++ gpio_request(134, "sysfs");
++ gpio_export(134, 1);
++ gpio_request(135, "sysfs");
++ gpio_export(135, 1);
++ gpio_request(136, "sysfs");
++ gpio_export(136, 1);
++ gpio_request(137, "sysfs");
++ gpio_export(137, 1);
++ gpio_request(138, "sysfs");
++ gpio_export(138, 1);
++ gpio_request(139, "sysfs");
++ gpio_export(139, 1);
++ gpio_request(140, "sysfs");
++ gpio_export(140, 1);
++ gpio_request(141, "sysfs");
++ gpio_export(141, 1);
++ gpio_request(162, "sysfs");
++ gpio_export(162, 1);
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(omap3beagle_nand_partitions,
diff --git a/patches/linux-3.8.13/0207-Beagle-expansion-add-CircuitCo-ulcd-Support.patch b/patches/linux-3.8.13/0207-Beagle-expansion-add-CircuitCo-ulcd-Support.patch
new file mode 100644
index 0000000..0ad8781
--- /dev/null
+++ b/patches/linux-3.8.13/0207-Beagle-expansion-add-CircuitCo-ulcd-Support.patch
@@ -0,0 +1,289 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:42:03 -0600
+Subject: [PATCH] Beagle: expansion: add CircuitCo ulcd Support
+
+This of a cleanup, squashed both ulcd commits into one:
+
+======================================================================
+
+expansion: add ulcd
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+
+======================================================================
+
+beagleboard: fix uLCD7 support
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+
+======================================================================
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 137 ++++++++++++++++++++++
+ drivers/video/omap2/displays/panel-generic-dpi.c | 27 +++++
+ 2 files changed, 164 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index a8ca83d..04f06b2 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -42,6 +42,7 @@
+ #include <asm/mach/flash.h>
+
+ #include <video/omapdss.h>
++#include <video/omap-panel-generic-dpi.h>
+ #include <video/omap-panel-tfp410.h>
+ #include <linux/platform_data/mtd-nand-omap2.h>
+
+@@ -88,12 +89,16 @@ static struct {
+ int dvi_pd_gpio;
+ int usr_button_gpio;
+ int mmc_caps;
++ char *lcd_driver_name;
++ int lcd_pwren;
+ } beagle_config = {
+ .mmc1_gpio_wp = -EINVAL,
+ .usb_pwr_level = GPIOF_OUT_INIT_LOW,
+ .dvi_pd_gpio = -EINVAL,
+ .usr_button_gpio = 4,
+ .mmc_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
++ .lcd_driver_name = "",
++ .lcd_pwren = 156,
+ };
+
+ static struct gpio omap3_beagle_rev_gpios[] __initdata = {
+@@ -165,6 +170,7 @@ static void __init omap3_beagle_init_rev(void)
+ }
+
+ char expansionboard_name[16];
++char expansionboard2_name[16];
+
+ enum {
+ EXPANSION_MMC_NONE = 0,
+@@ -175,6 +181,7 @@ enum {
+ enum {
+ EXPANSION_I2C_NONE = 0,
+ EXPANSION_I2C_ZIPPY,
++ EXPANSION_I2C_7ULCD,
+ };
+
+ static struct {
+@@ -339,9 +346,53 @@ static struct omap_dss_device beagle_tv_device = {
+ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+ };
+
++static int beagle_enable_lcd(struct omap_dss_device *dssdev)
++{
++ if (gpio_is_valid(beagle_config.lcd_pwren)) {
++ pr_info("%s: Enabling LCD\n", __FUNCTION__);
++ gpio_set_value(beagle_config.lcd_pwren, 0);
++ } else {
++ pr_info("%s: Invalid LCD enable GPIO: %d\n",
++ __FUNCTION__, beagle_config.lcd_pwren);
++ }
++
++ return 0;
++}
++
++static void beagle_disable_lcd(struct omap_dss_device *dssdev)
++{
++ if (gpio_is_valid(beagle_config.lcd_pwren)) {
++ pr_info("%s: Disabling LCD\n", __FUNCTION__);
++ gpio_set_value(beagle_config.lcd_pwren, 1);
++ } else {
++ pr_info("%s: Invalid LCD enable GPIO: %d\n",
++ __FUNCTION__, beagle_config.lcd_pwren);
++ }
++
++ return;
++}
++
++static struct panel_generic_dpi_data lcd_panel = {
++ .name = "tfc_s9700rtwv35tr-01b",
++ .platform_enable = beagle_enable_lcd,
++ .platform_disable = beagle_disable_lcd,
++};
++
++static struct omap_dss_device beagle_lcd_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .driver_name = "generic_dpi_panel",
++ .phy.dpi.data_lines = 24,
++ .platform_enable = beagle_enable_lcd,
++ .platform_disable = beagle_disable_lcd,
++ .reset_gpio = -EINVAL,
++ .data = &lcd_panel,
++};
++
+ static struct omap_dss_device *beagle_dss_devices[] = {
+ &beagle_dvi_device,
+ &beagle_tv_device,
++ &beagle_lcd_device,
+ };
+
+ static struct omap_dss_board_info beagle_dss_data = {
+@@ -509,6 +560,53 @@ static struct i2c_board_info __initdata zippy_i2c2_rtc[] = {
+ #endif
+ };
+
++#if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
++/* Touchscreen */
++#include <linux/i2c/tsc2007.h>
++
++#define OMAP3BEAGLE_TSC2007_GPIO 157
++
++static int omap3beagle_tsc2007_get_pendown_state(void)
++{
++ return !gpio_get_value(OMAP3BEAGLE_TSC2007_GPIO);
++}
++
++static struct tsc2007_platform_data tsc2007_info = {
++ .model = 2007,
++ .x_plate_ohms = 180,
++ .get_pendown_state = omap3beagle_tsc2007_get_pendown_state,
++};
++
++static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {
++ {
++ I2C_BOARD_INFO("tlc59108", 0x40),
++ },
++ {
++ I2C_BOARD_INFO("tsc2007", 0x48),
++ .platform_data = &tsc2007_info,
++ },
++};
++
++static void __init omap3beagle_tsc2007_init(void)
++{
++ int r;
++
++ omap_mux_init_gpio(OMAP3BEAGLE_TSC2007_GPIO, OMAP_PIN_INPUT_PULLUP);
++
++ r = gpio_request_one(OMAP3BEAGLE_TSC2007_GPIO, GPIOF_IN, "tsc2007_pen_down");
++ if (r < 0) {
++ pr_err("Beagle expansionboard: failed to request GPIO#%d for "
++ "tsc2007 pen down IRQ\n", OMAP3BEAGLE_TSC2007_GPIO);
++ return;
++ }
++
++ beagle_i2c2_bbtoys_ulcd[0].irq = gpio_to_irq(OMAP3BEAGLE_TSC2007_GPIO);
++ irq_set_irq_type(gpio_to_irq(OMAP3BEAGLE_TSC2007_GPIO), IRQ_TYPE_EDGE_FALLING);
++}
++#else
++static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {};
++#endif
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap3_pmic_get_config(&beagle_twldata,
+@@ -521,6 +619,10 @@ static int __init omap3_beagle_i2c_init(void)
+ omap3_pmic_init("twl4030", &beagle_twldata);
+
+ switch (expansion_config.i2c_settings) {
++ case EXPANSION_I2C_7ULCD:
++ omap_register_i2c_bus(2, 400, beagle_i2c2_bbtoys_ulcd,
++ ARRAY_SIZE(beagle_i2c2_bbtoys_ulcd));
++ break;
+ case EXPANSION_I2C_ZIPPY:
+ omap_register_i2c_bus(2, 400, zippy_i2c2_rtc, ARRAY_SIZE(zippy_i2c2_rtc));
+ break;
+@@ -629,6 +731,18 @@ static int __init expansionboard_setup(char *str)
+ return 0;
+ }
+
++static int __init expansionboard2_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(expansionboard2_name, str, 16);
++ pr_info("Beagle expansionboard2: %s\n", expansionboard2_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -694,6 +808,20 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
+ }
+
++ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
++ {
++ int r;
++ expansion_config.i2c_settings = EXPANSION_I2C_7ULCD;
++
++ /* TODO: set lcd_driver_name by command line or device tree */
++ beagle_config.lcd_driver_name = "tfc_s9700rtwv35tr-01b",
++ lcd_panel.name = beagle_config.lcd_driver_name;
++
++ r = gpio_request_one(beagle_config.lcd_pwren, GPIOF_OUT_INIT_LOW, "LCD power");
++ if (r < 0)
++ pr_err("Beagle expansionboard: Unable to get LCD power enable GPIO\n");
++ }
++
+ if (gpio_is_valid(beagle_config.mmc1_gpio_wp))
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+
+@@ -763,6 +891,14 @@ static void __init omap3_beagle_init(void)
+ gpio_export(162, 1);
+ }
+
++ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
++ {
++ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
++ pr_info("Beagle expansionboard: initializing touchscreen: tsc2007\n");
++ omap3beagle_tsc2007_init();
++ #endif
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(omap3beagle_nand_partitions,
+@@ -779,6 +915,7 @@ static void __init omap3_beagle_init(void)
+ }
+
+ early_param("buddy", expansionboard_setup);
++early_param("buddy2", expansionboard2_setup);
+
+ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+ /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
+diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
+index 54ca8ae..f176003 100644
+--- a/drivers/video/omap2/displays/panel-generic-dpi.c
++++ b/drivers/video/omap2/displays/panel-generic-dpi.c
+@@ -538,6 +538,33 @@ static struct panel_config generic_dpi_panels[] = {
+ },
+ .name = "primeview_pd104slf",
+ },
++
++ /* ThreeFiveCorp S9700RTWV35TR-01B */
++ {
++ {
++ .x_res = 800,
++ .y_res = 480,
++
++ .pixel_clock = 30000,
++
++ .hsw = 49,
++ .hfp = 41,
++ .hbp = 40,
++
++ .vsw = 4,
++ .vfp = 14,
++ .vbp = 29,
++
++ .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
++ .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
++ .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
++ .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
++ .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
++ },
++ .power_on_delay = 50,
++ .power_off_delay = 100,
++ .name = "tfc_s9700rtwv35tr-01b",
++ },
+ };
+
+ struct panel_drv_data {
diff --git a/patches/linux-3.8.13/0208-Beagle-expansion-add-wifi.patch b/patches/linux-3.8.13/0208-Beagle-expansion-add-wifi.patch
new file mode 100644
index 0000000..e49deb2
--- /dev/null
+++ b/patches/linux-3.8.13/0208-Beagle-expansion-add-wifi.patch
@@ -0,0 +1,176 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:48:52 -0600
+Subject: [PATCH] Beagle: expansion: add wifi
+
+build fixes from Pantelis Antoniou <panto@antoniou-consulting.com>
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 119 +++++++++++++++++++++++++++++++
+ 1 file changed, 119 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 04f06b2..f126531 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -192,6 +192,73 @@ static struct {
+ .i2c_settings = EXPANSION_I2C_NONE,
+ };
+
++#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++#include <linux/regulator/fixed.h>
++#include <linux/ti_wilink_st.h>
++#include <linux/wl12xx.h>
++
++#define OMAP_BEAGLE_WLAN_EN_GPIO (139)
++#define OMAP_BEAGLE_BT_EN_GPIO (138)
++#define OMAP_BEAGLE_WLAN_IRQ_GPIO (137)
++#define OMAP_BEAGLE_FM_EN_BT_WU (136)
++
++struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
++ .board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
++};
++
++static struct ti_st_plat_data wilink_platform_data = {
++ .nshutdown_gpio = OMAP_BEAGLE_BT_EN_GPIO,
++ .dev_name = "/dev/ttyO1",
++ .flow_cntrl = 1,
++ .baud_rate = 3000000,
++ .chip_enable = NULL,
++ .suspend = NULL,
++ .resume = NULL,
++};
++
++static struct platform_device wl12xx_device = {
++ .name = "kim",
++ .id = -1,
++ .dev.platform_data = &wilink_platform_data,
++};
++
++static struct platform_device btwilink_device = {
++ .name = "btwilink",
++ .id = -1,
++};
++#endif
++
++static struct regulator_consumer_supply beagle_vmmc2_supply =
++ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
++
++static struct regulator_init_data beagle_vmmc2 = {
++ .constraints = {
++ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vmmc2_supply,
++};
++
++#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++static struct fixed_voltage_config beagle_vwlan = {
++ .supply_name = "vwl1271",
++ .microvolts = 1800000, /* 1.8V */
++ .gpio = OMAP_BEAGLE_WLAN_EN_GPIO,
++ .startup_delay = 70000, /* 70ms */
++ .enable_high = 1,
++ .enabled_at_boot = 0,
++ .init_data = &beagle_vmmc2,
++};
++
++static struct platform_device omap_vwlan_device = {
++ .name = "reg-fixed-voltage",
++ .id = 1,
++ .dev = {
++ .platform_data = &beagle_vwlan,
++ },
++};
++#endif
++
+ //rcn-ee: this is just a fake regulator, the zippy hardware provides 3.3/1.8 with jumper..
+ static struct fixed_voltage_config beagle_vzippy = {
+ .supply_name = "vzippy",
+@@ -430,6 +497,26 @@ static struct omap2_hsmmc_info mmc_zippy[] = {
+ },
+ {} /* Terminator */
+ };
++
++static struct omap2_hsmmc_info mmcbbt[] = {
++ {
++ .mmc = 1,
++ .caps = MMC_CAP_4_BIT_DATA,
++ .gpio_wp = -EINVAL,
++ .deferred = true,
++ },
++ {
++ .name = "wl1271",
++ .mmc = 2,
++ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
++ .gpio_wp = -EINVAL,
++ .gpio_cd = -EINVAL,
++ .ocr_mask = MMC_VDD_165_195,
++ .nonremovable = true,
++ },
++ {} /* Terminator */
++};
++
+ static struct regulator_consumer_supply beagle_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+ };
+@@ -446,6 +533,13 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ int r;
+
+ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_WIFI:
++ mmcbbt[0].gpio_wp = beagle_config.mmc1_gpio_wp;
++ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
++ mmcbbt[0].gpio_cd = gpio + 0;
++
++ omap_hsmmc_late_init(mmcbbt);
++ break;
+ case EXPANSION_MMC_ZIPPY:
+ mmc_zippy[0].gpio_wp = beagle_config.mmc1_gpio_wp;
+ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+@@ -808,6 +902,13 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
+ }
+
++ if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ {
++ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++ expansion_config.mmc_settings = EXPANSION_MMC_WIFI;
++ #endif
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ int r;
+@@ -826,6 +927,10 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+
+ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_WIFI:
++ mmcbbt[0].caps = beagle_config.mmc_caps;
++ omap_hsmmc_init(mmcbbt);
++ break;
+ case EXPANSION_MMC_ZIPPY:
+ mmc_zippy[0].caps = beagle_config.mmc_caps;
+ omap_hsmmc_init(mmc_zippy);
+@@ -891,6 +996,20 @@ static void __init omap3_beagle_init(void)
+ gpio_export(162, 1);
+ }
+
++ if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ {
++ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++ omap_beagle_wlan_data.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
++ if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
++ pr_err("error setting wl12xx data\n");
++ pr_info("Beagle expansionboard: registering wl12xx bt platform device\n");
++ platform_device_register(&wl12xx_device);
++ platform_device_register(&btwilink_device);
++ pr_info("Beagle expansionboard: registering wl12xx wifi platform device\n");
++ platform_device_register(&omap_vwlan_device);
++ #endif
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
diff --git a/patches/linux-3.8.13/0209-Beagle-expansion-add-beaglefpga.patch b/patches/linux-3.8.13/0209-Beagle-expansion-add-beaglefpga.patch
new file mode 100644
index 0000000..c13900c
--- /dev/null
+++ b/patches/linux-3.8.13/0209-Beagle-expansion-add-beaglefpga.patch
@@ -0,0 +1,111 @@
+From: Bas van der Doorn <bas@doornvd.com>
+Date: Tue, 11 Dec 2012 06:52:22 -0600
+Subject: [PATCH] Beagle: expansion: add beaglefpga
+
+Added SPI dev and McBSP 3 mux when FPGA is detected
+
+Signed-off-by: Bas van der Doorn <bas@doornvd.com>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 74 +++++++++++++++++++++++++++++++
+ 1 file changed, 74 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index f126531..3b939eb 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -40,6 +40,7 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/flash.h>
++#include <linux/spi/spi.h>
+
+ #include <video/omapdss.h>
+ #include <video/omap-panel-generic-dpi.h>
+@@ -885,6 +886,68 @@ static int __init beagle_opp_init(void)
+ }
+ device_initcall(beagle_opp_init);
+
++static void __init omap3_beagle_config_mcspi3_mux(void)
++{
++ /* NOTE: Clock pins need to be in input mode */
++ omap_mux_init_signal("sdmmc2_clk.mcspi3_clk", OMAP_PIN_INPUT);
++ omap_mux_init_signal("sdmmc2_cmd.mcspi3_simo", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("sdmmc2_dat0.mcspi3_somi", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat2.mcspi3_cs1", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("sdmmc2_dat3.mcspi3_cs0", OMAP_PIN_OUTPUT);
++}
++
++static void __init omap3_beagle_config_mcspi4_mux(void)
++{
++ /* NOTE: Clock pins need to be in input mode */
++ omap_mux_init_signal("mcbsp1_clkr.mcspi4_clk", OMAP_PIN_INPUT);
++ omap_mux_init_signal("mcbsp1_dx.mcspi4_simo", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("mcbsp1_dr.mcspi4_somi", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("mcbsp1_fsx.mcspi4_cs0", OMAP_PIN_OUTPUT);
++}
++
++static void __init omap3_beagle_config_mcbsp3_mux(void)
++{
++ omap_mux_init_signal("mcbsp3_fsx.uart2_rx", OMAP_PIN_INPUT);
++ omap_mux_init_signal("uart2_cts.mcbsp3_dx", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("uart2_rts.mcbsp3_dr", OMAP_PIN_INPUT);
++ /* NOTE: Clock pins need to be in input mode */
++ omap_mux_init_signal("uart2_tx.mcbsp3_clkx", OMAP_PIN_INPUT);
++}
++
++static void __init omap3_beagle_config_fpga_mux(void)
++{
++ omap3_beagle_config_mcbsp3_mux();
++ omap3_beagle_config_mcspi3_mux();
++ omap3_beagle_config_mcspi4_mux();
++}
++
++static struct spi_board_info beagle_mcspi_board_info[] = {
++ /* spi 3.0 */
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 48000000, //48 Mbps
++ .bus_num = 3,
++ .chip_select = 0,
++ .mode = SPI_MODE_1,
++ },
++ /* spi 3.1 */
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 48000000, //48 Mbps
++ .bus_num = 3,
++ .chip_select = 1,
++ .mode = SPI_MODE_1,
++ },
++ /* spi 4.0 */
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 48000000, //48 Mbps
++ .bus_num = 4,
++ .chip_select = 0,
++ .mode = SPI_MODE_1,
++ },
++};
++
+ static void __init omap3_beagle_init(void)
+ {
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+@@ -1010,6 +1073,17 @@ static void __init omap3_beagle_init(void)
+ #endif
+ }
+
++ if (!strcmp(expansionboard_name, "beaglefpga"))
++ {
++ pr_info("Beagle expansionboard: enabling SPIdev for McSPI3/4 and pin muxing for McBSP3 slave mode\n");
++
++ /* FPGA pin settings configure McSPI 3, McSPI 4 and McBSP 3 */
++ omap3_beagle_config_fpga_mux();
++
++ /* register McSPI 3 and McSPI 4 for FPGA programming and control */
++ spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
diff --git a/patches/linux-3.8.13/0210-Beagle-expansion-add-spidev.patch b/patches/linux-3.8.13/0210-Beagle-expansion-add-spidev.patch
new file mode 100644
index 0000000..fe415e4
--- /dev/null
+++ b/patches/linux-3.8.13/0210-Beagle-expansion-add-spidev.patch
@@ -0,0 +1,29 @@
+From: Russell Hay <russell.hay@gmail.com>
+Date: Tue, 11 Dec 2012 06:53:58 -0600
+Subject: [PATCH] Beagle: expansion: add spidev
+
+Signed-off-by: Russell Hay <russell.hay@gmail.com>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 3b939eb..598e4d6 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -1084,6 +1084,14 @@ static void __init omap3_beagle_init(void)
+ spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
+ }
+
++ if (!strcmp(expansionboard_name, "spidev"))
++ {
++ pr_info("Beagle expansionboard: registering spidev\n");
++ omap3_beagle_config_mcspi3_mux();
++ omap3_beagle_config_mcspi4_mux();
++ spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
diff --git a/patches/linux-3.8.13/0211-Beagle-expansion-add-Aptina-li5m03-camera.patch b/patches/linux-3.8.13/0211-Beagle-expansion-add-Aptina-li5m03-camera.patch
new file mode 100644
index 0000000..aa1debb
--- /dev/null
+++ b/patches/linux-3.8.13/0211-Beagle-expansion-add-Aptina-li5m03-camera.patch
@@ -0,0 +1,223 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:58:15 -0600
+Subject: [PATCH] Beagle: expansion: add Aptina li5m03 camera
+
+Based on:
+https://github.com/Aptina/BeagleBoard-xM/blob/master/tools/0266-Adding-MT9P031-Support-files.patch
+
+And on Max Galemin's patch
+https://github.com/MaxGalemin/buildroot/blob/master/board/beagleboard/xm/kernel-patches/linux-0003-Add-support-for-MT9P031-Aptina-image-sensor-driver.patch
+
+And Koen Kooi Previous work's
+https://github.com/beagleboard/kernel/blob/beagleboard-3.2/patches/camera/0003-beagleboard-fix-i2c2-init.patch
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 152 +++++++++++++++++++++++++++++++
+ 1 file changed, 152 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 598e4d6..3f679b9 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -172,6 +172,7 @@ static void __init omap3_beagle_init_rev(void)
+
+ char expansionboard_name[16];
+ char expansionboard2_name[16];
++char camera_name[16];
+
+ enum {
+ EXPANSION_MMC_NONE = 0,
+@@ -526,6 +527,14 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
+ };
+
++static struct regulator_consumer_supply beagle_vaux3_supply = {
++ .supply = "cam_1v8",
++};
++
++static struct regulator_consumer_supply beagle_vaux4_supply = {
++ .supply = "cam_2v8",
++};
++
+ static struct gpio_led gpio_leds[];
+
+ static int beagle_twl_gpio_setup(struct device *dev,
+@@ -634,11 +643,43 @@ static struct regulator_init_data beagle_vsim = {
+ .consumer_supplies = beagle_vsim_supply,
+ };
+
++/* VAUX3 for CAM_1V8 */
++static struct regulator_init_data beagle_vaux3 = {
++ .constraints = {
++ .min_uV = 1800000,
++ .max_uV = 1800000,
++ .apply_uV = true,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vaux3_supply,
++};
++
++/* VAUX4 for CAM_2V8 */
++static struct regulator_init_data beagle_vaux4 = {
++ .constraints = {
++ .min_uV = 1800000,
++ .max_uV = 1800000,
++ .apply_uV = true,
++ .valid_modes_mask = REGULATOR_MODE_NORMAL
++ | REGULATOR_MODE_STANDBY,
++ .valid_ops_mask = REGULATOR_CHANGE_MODE
++ | REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vaux4_supply,
++};
++
+ static struct twl4030_platform_data beagle_twldata = {
+ /* platform_data for children goes here */
+ .gpio = &beagle_gpio_data,
+ .vmmc1 = &beagle_vmmc1,
+ .vsim = &beagle_vsim,
++ .vaux3 = &beagle_vaux3,
++ .vaux4 = &beagle_vaux4,
+ };
+
+ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+@@ -702,6 +743,71 @@ static void __init omap3beagle_tsc2007_init(void)
+ static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {};
+ #endif
+
++#if defined(CONFIG_VIDEO_MT9P031)
++/* needed for: omap3_beagle_late_initcall */
++#include "devices.h"
++#include <media/omap3isp.h>
++#include <media/mt9p031.h>
++/* needed for: v4l2_dev_to_isp_device */
++#include "../../../drivers/media/platform/omap3isp/isp.h"
++
++#define MT9P031_XCLK ISP_XCLK_A
++
++#define MT9P031_RESET_GPIO 98
++#define MT9P031_EXT_FREQ 21000000
++#define MT9P031_TARGET_FREQ 48000000
++
++#define MT9P031_I2C_ADDR 0x48
++#define MT9P031_I2C_BUS 2
++
++static struct regulator *reg_1v8, *reg_2v8;
++
++static int beagle_cam_set_xclk(struct v4l2_subdev *subdev, int hz)
++{
++ struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);
++
++ return isp->platform_cb.set_xclk(isp, hz, MT9P031_XCLK);
++}
++
++static struct mt9p031_platform_data beagle_mt9p031_platform_data = {
++ .set_xclk = beagle_cam_set_xclk,
++ .reset = MT9P031_RESET_GPIO,
++ .ext_freq = MT9P031_EXT_FREQ,
++ .target_freq = MT9P031_TARGET_FREQ,
++};
++
++static struct i2c_board_info mt9p031_camera_i2c_device = {
++ I2C_BOARD_INFO("mt9p031", MT9P031_I2C_ADDR),
++ .platform_data = &beagle_mt9p031_platform_data,
++};
++
++static struct isp_subdev_i2c_board_info mt9p031_camera_subdevs[] = {
++ {
++ .board_info = &mt9p031_camera_i2c_device,
++ .i2c_adapter_id = MT9P031_I2C_BUS,
++ },
++ { NULL, 0, },
++};
++
++static struct isp_v4l2_subdevs_group beagle_camera_subdevs[] = {
++ {
++ .subdevs = mt9p031_camera_subdevs,
++ .interface = ISP_INTERFACE_PARALLEL,
++ .bus = {
++ .parallel = {
++ .data_lane_shift = 0,
++ .clk_pol = 1,
++ }
++ },
++ },
++ { },
++};
++
++static struct isp_platform_data beagle_isp_platform_data = {
++ .subdevs = beagle_camera_subdevs,
++};
++#endif
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap3_pmic_get_config(&beagle_twldata,
+@@ -838,6 +944,18 @@ static int __init expansionboard2_setup(char *str)
+ return 0;
+ }
+
++static int __init camera_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(camera_name, str, 16);
++ pr_info("Beagle camera: %s\n", camera_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -1115,8 +1233,42 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+ }
+
++static int __init omap3_beagle_late_initcall(void)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!cpu_is_omap3630())
++ return 0;
++
++#if defined(CONFIG_VIDEO_MT9P031)
++ if ((!strcmp(camera_name, "lbcm5m1")) || (!strcmp(camera_name, "li5m03")))
++ {
++ pr_info("Beagle camera: MT9P031 init\n");
++
++ reg_1v8 = regulator_get(NULL, "cam_1v8");
++ if (IS_ERR(reg_1v8))
++ pr_err("%s: cannot get cam_1v8 regulator\n", __func__);
++ else
++ regulator_enable(reg_1v8);
++
++ reg_2v8 = regulator_get(NULL, "cam_2v8");
++ if (IS_ERR(reg_2v8))
++ pr_err("%s: cannot get cam_2v8 regulator\n", __func__);
++ else
++ regulator_enable(reg_2v8);
++
++ omap3_init_camera(&beagle_isp_platform_data);
++ }
++#endif
++ return 0;
++}
++
+ early_param("buddy", expansionboard_setup);
+ early_param("buddy2", expansionboard2_setup);
++early_param("camera", camera_setup);
++
++late_initcall(omap3_beagle_late_initcall);
+
+ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+ /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
diff --git a/patches/linux-3.8.13/0212-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch b/patches/linux-3.8.13/0212-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch
new file mode 100644
index 0000000..54233a3
--- /dev/null
+++ b/patches/linux-3.8.13/0212-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch
@@ -0,0 +1,119 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 07:02:40 -0600
+Subject: [PATCH] Beagle: expansion: add LSR COM6L Adapter Board
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 60 ++++++++++++++++++++++++++++---
+ 1 file changed, 55 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 3f679b9..cdc77c5 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -173,6 +173,7 @@ static void __init omap3_beagle_init_rev(void)
+ char expansionboard_name[16];
+ char expansionboard2_name[16];
+ char camera_name[16];
++char wl12xx_name[16];
+
+ enum {
+ EXPANSION_MMC_NONE = 0,
+@@ -208,6 +209,10 @@ struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
+ .board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
+ };
+
++struct wl12xx_platform_data omap_beagle_wlan_data_26mhz __initdata = {
++ .board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */
++};
++
+ static struct ti_st_plat_data wilink_platform_data = {
+ .nshutdown_gpio = OMAP_BEAGLE_BT_EN_GPIO,
+ .dev_name = "/dev/ttyO1",
+@@ -956,6 +961,18 @@ static int __init camera_setup(char *str)
+ return 0;
+ }
+
++static int __init wl12xx_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(wl12xx_name, str, 16);
++ pr_info("Beagle wl12xx clk: %s\n", wl12xx_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -1083,9 +1100,29 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
+ }
+
+- if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ if ((!strcmp(expansionboard_name, "bbtoys-wifi")) || (!strcmp(expansionboard_name, "lsr-com6l-adpt")))
+ {
+ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++ pr_info("Beagle expansion: wl12xx: setting up gpio pinmux\n");
++
++ omap_mux_init_gpio(OMAP_BEAGLE_FM_EN_BT_WU, OMAP_PIN_OUTPUT);
++ omap_mux_init_gpio(OMAP_BEAGLE_BT_EN_GPIO, OMAP_PIN_OUTPUT);
++ omap_mux_init_gpio(OMAP_BEAGLE_WLAN_EN_GPIO, OMAP_PIN_OUTPUT);
++
++ omap_mux_init_gpio(OMAP_BEAGLE_WLAN_IRQ_GPIO, OMAP_PIN_INPUT_PULLUP);
++
++ /* WLAN SDIO: MMC2 CLK */
++ omap_mux_init_signal("sdmmc2_clk.sdmmc2_clk", OMAP_PIN_INPUT_PULLUP);
++
++ /* WLAN SDIO: MMC2 CMD */
++ omap_mux_init_signal("sdmmc2_cmd.sdmmc2_cmd", OMAP_PIN_INPUT_PULLUP);
++
++ /* WLAN SDIO: MMC2 DAT[0-3] */
++ omap_mux_init_signal("sdmmc2_dat0.sdmmc2_dat0", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat1.sdmmc2_dat1", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat2.sdmmc2_dat2", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat3.sdmmc2_dat3", OMAP_PIN_INPUT_PULLUP);
++
+ expansion_config.mmc_settings = EXPANSION_MMC_WIFI;
+ #endif
+ }
+@@ -1177,12 +1214,24 @@ static void __init omap3_beagle_init(void)
+ gpio_export(162, 1);
+ }
+
+- if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ if ((!strcmp(expansionboard_name, "bbtoys-wifi")) || (!strcmp(expansionboard_name, "lsr-com6l-adpt")))
+ {
+ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+- omap_beagle_wlan_data.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
+- if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
+- pr_err("error setting wl12xx data\n");
++ pr_info("Beagle expansionboard: initializing wl12xx platform\n");
++
++ if (!strcmp(wl12xx_name, "wl12xx_26mhz")) {
++ pr_info("wl12xx: 26Mhz reference clock (TiWi5)\n");
++ omap_beagle_wlan_data_26mhz.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
++ if (wl12xx_set_platform_data(&omap_beagle_wlan_data_26mhz))
++ pr_err("error setting wl12xx data\n");
++ } else {
++ pr_info("wl12xx: 38.4Mhz reference clock (TiWi2/TiWi-BLE)\n");
++ pr_info("wl12xx: for (TiWi5) support pass kernel [wl12xx_clk=wl12xx_26mhz]\n");
++ omap_beagle_wlan_data.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
++ if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
++ pr_err("error setting wl12xx data\n");
++ }
++
+ pr_info("Beagle expansionboard: registering wl12xx bt platform device\n");
+ platform_device_register(&wl12xx_device);
+ platform_device_register(&btwilink_device);
+@@ -1267,6 +1316,7 @@ static int __init omap3_beagle_late_initcall(void)
+ early_param("buddy", expansionboard_setup);
+ early_param("buddy2", expansionboard2_setup);
+ early_param("camera", camera_setup);
++early_param("wl12xx_clk", wl12xx_setup);
+
+ late_initcall(omap3_beagle_late_initcall);
+
diff --git a/patches/linux-3.8.13/0213-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch b/patches/linux-3.8.13/0213-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch
new file mode 100644
index 0000000..2e4e312
--- /dev/null
+++ b/patches/linux-3.8.13/0213-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch
@@ -0,0 +1,26 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Wed, 23 Mar 2011 08:37:54 -0500
+Subject: [PATCH] meego: modedb add Toshiba LTA070B220F 800x480 support
+
+ from http://wiki.meego.com/ARM/Meego_on_Beagleboard_from_scratch
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/video/modedb.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
+index 5b686de..69ad1ec 100644
+--- a/drivers/video/modedb.c
++++ b/drivers/video/modedb.c
+@@ -293,6 +293,10 @@ static const struct fb_videomode modedb[] = {
+ /* 864x480 @ 60 Hz, 35.15 kHz hsync */
+ { NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
+ 0, FB_VMODE_NONINTERLACED },
++
++ /* 800x480 @ 60 Hz, Toshiba LTA070B220F 7 inch LCD */
++ { NULL, 60, 800, 480, 32787, 48, 80, 33, 31, 32, 2,
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ };
+
+ #ifdef CONFIG_FB_MODE_HELPERS
diff --git a/patches/linux-3.8.13/0214-backlight-Add-TLC59108-backlight-control-driver.patch b/patches/linux-3.8.13/0214-backlight-Add-TLC59108-backlight-control-driver.patch
new file mode 100644
index 0000000..4ae5392
--- /dev/null
+++ b/patches/linux-3.8.13/0214-backlight-Add-TLC59108-backlight-control-driver.patch
@@ -0,0 +1,212 @@
+From: "Manjunathappa, Prakash" <prakash.pm@ti.com>
+Date: Mon, 1 Aug 2011 18:25:11 +0530
+Subject: [PATCH] backlight: Add TLC59108 backlight control driver
+
+This patch adds support for I2C configurable TLC59108 backlight
+control driver.
+
+Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ drivers/video/backlight/Kconfig | 8 ++
+ drivers/video/backlight/Makefile | 1 +
+ drivers/video/backlight/tlc59108.c | 160 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 169 insertions(+)
+ create mode 100644 drivers/video/backlight/tlc59108.c
+
+diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
+index 765a945..50c9e35 100644
+--- a/drivers/video/backlight/Kconfig
++++ b/drivers/video/backlight/Kconfig
+@@ -390,6 +390,14 @@ config BACKLIGHT_TPS65217
+ If you have a Texas Instruments TPS65217 say Y to enable the
+ backlight driver.
+
++config BACKLIGHT_TLC59108
++ tristate "TLC59108 LCD Backlight Driver"
++ depends on I2C && BACKLIGHT_CLASS_DEVICE
++ default n
++ help
++ If you have an LCD Panel with backlight control via TLC59108,
++ say Y to enable its LCD control driver.
++
+ endif # BACKLIGHT_CLASS_DEVICE
+
+ endif # BACKLIGHT_LCD_SUPPORT
+diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
+index e7ce729..2f4711d 100644
+--- a/drivers/video/backlight/Makefile
++++ b/drivers/video/backlight/Makefile
+@@ -43,5 +43,6 @@ obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
+ obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
+ obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
+ obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
++obj-$(CONFIG_BACKLIGHT_TLC59108) += tlc59108.o
+ obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
+ obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
+diff --git a/drivers/video/backlight/tlc59108.c b/drivers/video/backlight/tlc59108.c
+new file mode 100644
+index 0000000..4f4ea34
+--- /dev/null
++++ b/drivers/video/backlight/tlc59108.c
+@@ -0,0 +1,160 @@
++/*
++ * ti81xxhdmi_tlc59108.c
++ *
++ * Copyright (C) 2011 Texas Instruments
++ * Author: Senthil Natarajan
++ *
++ * tlc59108 HDMI Driver
++ *
++ * 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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ * History:
++ *
++ * Senthil Natarajan<senthil.n@ti.com> July 2011 I2C driver for tlc59108
++ * backlight control
++ */
++
++#include <linux/i2c.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/backlight.h>
++#include <linux/fb.h>
++
++#define tlc59108_MODULE_NAME "tlc59108"
++#define TLC59108_MODE1 0x00
++#define TLC59108_PWM2 0x04
++#define TLC59108_LEDOUT0 0x0c
++#define TLC59108_LEDOUT1 0x0d
++#define TLC59108_MAX_BRIGHTNESS 0xFF
++
++struct tlc59108_bl {
++ struct i2c_client *client;
++ struct backlight_device *bl;
++};
++
++static void tlc59108_bl_set_backlight(struct tlc59108_bl *data, int brightness)
++{
++ /* Set Mode1 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_MODE1, 0x00);
++
++ /* Set LEDOUT0 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x21);
++
++ /* Set Backlight Duty Cycle*/
++ i2c_smbus_write_byte_data(data->client, TLC59108_PWM2,
++ brightness & 0xff);
++}
++
++static int tlc59108_bl_get_brightness(struct backlight_device *dev)
++{
++ struct backlight_properties *props = &dev->props;
++
++ return props->brightness;
++}
++
++static int tlc59108_bl_update_status(struct backlight_device *dev)
++{
++ struct backlight_properties *props = &dev->props;
++ struct tlc59108_bl *data = dev_get_drvdata(&dev->dev);
++ int brightness = props->brightness;
++
++ tlc59108_bl_set_backlight(data, brightness);
++
++ return 0;
++}
++
++static const struct backlight_ops bl_ops = {
++ .get_brightness = tlc59108_bl_get_brightness,
++ .update_status = tlc59108_bl_update_status,
++};
++
++static int tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
++{
++ struct backlight_properties props;
++ struct tlc59108_bl *data = kzalloc(sizeof(struct tlc59108_bl),
++ GFP_KERNEL);
++ int ret = 0;
++
++ if (!data)
++ return -ENOMEM;
++
++ i2c_set_clientdata(c, data);
++ data->client = c;
++
++ memset(&props, 0, sizeof(struct backlight_properties));
++ props.max_brightness = TLC59108_MAX_BRIGHTNESS;
++ props.type = BACKLIGHT_RAW;
++ data->bl = backlight_device_register("tlc59108-bl", &c->dev, data,
++ &bl_ops, &props);
++ if (IS_ERR(data->bl)) {
++ ret = PTR_ERR(data->bl);
++ goto err_reg;
++ }
++
++ data->bl->props.brightness = TLC59108_MAX_BRIGHTNESS;
++
++ backlight_update_status(data->bl);
++
++ return 0;
++
++err_reg:
++ data->bl = NULL;
++ kfree(data);
++ return ret;
++}
++
++static int tlc59108_remove(struct i2c_client *c)
++{
++ struct tlc59108_bl *data = i2c_get_clientdata(c);
++
++ backlight_device_unregister(data->bl);
++ data->bl = NULL;
++
++ kfree(data);
++
++ return 0;
++}
++
++/* I2C Device ID table */
++static const struct i2c_device_id tlc59108_id[] = {
++ { "tlc59108", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, tlc59108_id);
++
++/* I2C driver data */
++static struct i2c_driver tlc59108_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = tlc59108_MODULE_NAME,
++ },
++ .probe = tlc59108_probe,
++ .remove = tlc59108_remove,
++ .id_table = tlc59108_id,
++};
++
++static int __init tlc59108_init(void)
++{
++ return i2c_add_driver(&tlc59108_driver);
++}
++
++static void __exit tlc59108_exit(void)
++{
++ i2c_del_driver(&tlc59108_driver);
++}
++
++module_init(tlc59108_init);
++module_exit(tlc59108_exit);
++
++MODULE_DESCRIPTION("LCD/Backlight control for TLC59108");
++MODULE_AUTHOR("Senthil Natarajan <senthil.n@ti.com>");
++MODULE_LICENSE("GPL v2");
diff --git a/patches/linux-3.8.13/0215-tlc59108-adjust-for-beagleboard-uLCD7.patch b/patches/linux-3.8.13/0215-tlc59108-adjust-for-beagleboard-uLCD7.patch
new file mode 100644
index 0000000..2e14b13
--- /dev/null
+++ b/patches/linux-3.8.13/0215-tlc59108-adjust-for-beagleboard-uLCD7.patch
@@ -0,0 +1,120 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 27 Apr 2012 21:30:00 +0200
+Subject: [PATCH] tlc59108: adjust for beagleboard+uLCD7
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/video/backlight/tlc59108.c | 46 ++++++++++++++++++++++++------------
+ 1 file changed, 31 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/video/backlight/tlc59108.c b/drivers/video/backlight/tlc59108.c
+index 4f4ea34..40a21e7 100644
+--- a/drivers/video/backlight/tlc59108.c
++++ b/drivers/video/backlight/tlc59108.c
+@@ -29,9 +29,16 @@
+ #include <linux/backlight.h>
+ #include <linux/fb.h>
+
+-#define tlc59108_MODULE_NAME "tlc59108"
+ #define TLC59108_MODE1 0x00
+-#define TLC59108_PWM2 0x04
++#define TLC59108_MODE2 0x01
++#define TLC59108_PWM0 0x02
++#define TLC59108_PWM1 0x03
++#define TLC59108_PWM2 0x04
++#define TLC59108_PWM3 0x05
++#define TLC59108_PWM4 0x06
++#define TLC59108_PWM5 0x07
++#define TLC59108_PWM6 0x08
++#define TLC59108_PWM7 0x09
+ #define TLC59108_LEDOUT0 0x0c
+ #define TLC59108_LEDOUT1 0x0d
+ #define TLC59108_MAX_BRIGHTNESS 0xFF
+@@ -43,15 +50,9 @@ struct tlc59108_bl {
+
+ static void tlc59108_bl_set_backlight(struct tlc59108_bl *data, int brightness)
+ {
+- /* Set Mode1 Register */
+- i2c_smbus_write_byte_data(data->client, TLC59108_MODE1, 0x00);
+-
+- /* Set LEDOUT0 Register */
+- i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x21);
+-
+ /* Set Backlight Duty Cycle*/
+ i2c_smbus_write_byte_data(data->client, TLC59108_PWM2,
+- brightness & 0xff);
++ 0xff - brightness );
+ }
+
+ static int tlc59108_bl_get_brightness(struct backlight_device *dev)
+@@ -65,8 +66,18 @@ static int tlc59108_bl_update_status(struct backlight_device *dev)
+ {
+ struct backlight_properties *props = &dev->props;
+ struct tlc59108_bl *data = dev_get_drvdata(&dev->dev);
++
+ int brightness = props->brightness;
+
++ if (dev->props.state & BL_CORE_FBBLANK) {
++ brightness = 0;
++ /* Set LEDOUT0 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x10);
++ } else {
++ /* Set LEDOUT0 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x30);
++ }
++
+ tlc59108_bl_set_backlight(data, brightness);
+
+ return 0;
+@@ -77,7 +88,7 @@ static const struct backlight_ops bl_ops = {
+ .update_status = tlc59108_bl_update_status,
+ };
+
+-static int tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
++static int __devinit tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
+ {
+ struct backlight_properties props;
+ struct tlc59108_bl *data = kzalloc(sizeof(struct tlc59108_bl),
+@@ -104,6 +115,11 @@ static int tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
+
+ backlight_update_status(data->bl);
+
++ i2c_smbus_write_byte_data(data->client, TLC59108_MODE1, 0x00);
++ i2c_smbus_write_byte_data(data->client, TLC59108_PWM2, 0x80);
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT1, 0x05);
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT1, 0x15);
++
+ return 0;
+
+ err_reg:
+@@ -125,7 +141,7 @@ static int tlc59108_remove(struct i2c_client *c)
+ }
+
+ /* I2C Device ID table */
+-static const struct i2c_device_id tlc59108_id[] = {
++static struct i2c_device_id tlc59108_id[] = {
+ { "tlc59108", 0 },
+ { }
+ };
+@@ -134,12 +150,12 @@ MODULE_DEVICE_TABLE(i2c, tlc59108_id);
+ /* I2C driver data */
+ static struct i2c_driver tlc59108_driver = {
+ .driver = {
+- .owner = THIS_MODULE,
+- .name = tlc59108_MODULE_NAME,
++ .owner = THIS_MODULE,
++ .name = "tlc59108"
+ },
++ .id_table = tlc59108_id,
+ .probe = tlc59108_probe,
+ .remove = tlc59108_remove,
+- .id_table = tlc59108_id,
+ };
+
+ static int __init tlc59108_init(void)
+@@ -157,4 +173,4 @@ module_exit(tlc59108_exit);
+
+ MODULE_DESCRIPTION("LCD/Backlight control for TLC59108");
+ MODULE_AUTHOR("Senthil Natarajan <senthil.n@ti.com>");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.8.13/0216-zeroMAP-Open-your-eyes.patch b/patches/linux-3.8.13/0216-zeroMAP-Open-your-eyes.patch
new file mode 100644
index 0000000..c1fb323
--- /dev/null
+++ b/patches/linux-3.8.13/0216-zeroMAP-Open-your-eyes.patch
@@ -0,0 +1,27 @@
+From: Alexander Holler <holler@ahsoftware.de>
+Date: Wed, 4 Jul 2012 00:03:04 +0200
+Subject: [PATCH] zeroMAP: Open your eyes!
+
+Signed-off-by: Alexander Holler <holler@ahsoftware.de>
+---
+ kernel/printk.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/kernel/printk.c b/kernel/printk.c
+index 267ce780..0ca8ffe 100644
+--- a/kernel/printk.c
++++ b/kernel/printk.c
+@@ -1756,6 +1756,13 @@ static int __init console_setup(char *str)
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
++#ifdef CONFIG_SERIAL_OMAP
++ if (!strncmp(str, "tty0", 4) && '0' <= str[4] && '9' >= str[4]) {
++ str[3] = 'O';
++ pr_warn("We are opening your eyes, assuming you want to use an OMAP based serial driver and not a zeroMAP based one! ;)\n");
++ pr_warn("Which means 'tty0%s' was changed to 'ttyO%s' automagically for your pleasure.\n", str+4, str+4);
++ }
++#endif
+ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
+ if (!memcmp(str, "brl,", 4)) {
+ brl_options = "";
diff --git a/patches/linux-3.8.13/0217-ARM-OMAP-Beagle-use-TWL4030-generic-reset-script.patch b/patches/linux-3.8.13/0217-ARM-OMAP-Beagle-use-TWL4030-generic-reset-script.patch
new file mode 100644
index 0000000..146f454
--- /dev/null
+++ b/patches/linux-3.8.13/0217-ARM-OMAP-Beagle-use-TWL4030-generic-reset-script.patch
@@ -0,0 +1,25 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Thu, 24 Jan 2013 09:43:51 -0600
+Subject: [PATCH] ARM: OMAP: Beagle: use TWL4030 generic reset script
+
+Enable TWL_COMMON_PDATA_POWER such that OMAP3530 revisions of the
+Beagle (Bx/Cx) will not hang on reboot when running at 125 Mhz.
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index cdc77c5..20b4e1b 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -817,7 +817,7 @@ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap3_pmic_get_config(&beagle_twldata,
+ TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+- TWL_COMMON_PDATA_AUDIO,
++ TWL_COMMON_PDATA_AUDIO | TWL_COMMON_PDATA_POWER,
+ TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
+
+ beagle_twldata.vpll2->constraints.name = "VDVI";
diff --git a/patches/linux-3.8.13/0218-panda-fix-wl12xx-regulator.patch b/patches/linux-3.8.13/0218-panda-fix-wl12xx-regulator.patch
new file mode 100644
index 0000000..151ce40
--- /dev/null
+++ b/patches/linux-3.8.13/0218-panda-fix-wl12xx-regulator.patch
@@ -0,0 +1,23 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 2 Aug 2011 21:55:34 -0500
+Subject: [PATCH] panda: fix wl12xx regulator
+
+pulled from: http://elinux.org/Panda_How_to_kernel_3_0_rel
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/twl-common.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
+index f096beb..4b2b254 100644
+--- a/arch/arm/mach-omap2/twl-common.c
++++ b/arch/arm/mach-omap2/twl-common.c
+@@ -398,6 +398,7 @@ static struct regulator_init_data omap4_vusb_idata = {
+ static struct regulator_init_data omap4_clk32kg_idata = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
++ .always_on = true,
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0219-ti-st-st-kim-fixing-firmware-path.patch b/patches/linux-3.8.13/0219-ti-st-st-kim-fixing-firmware-path.patch
new file mode 100644
index 0000000..0edaa92
--- /dev/null
+++ b/patches/linux-3.8.13/0219-ti-st-st-kim-fixing-firmware-path.patch
@@ -0,0 +1,32 @@
+From: Ricardo Salveti de Araujo <ricardo.salveti@linaro.org>
+Date: Tue, 25 Oct 2011 10:06:39 +0200
+Subject: [PATCH] ti-st/st-kim: fixing firmware path
+
+Signed-off-by: Ricardo Salveti de Araujo <ricardo.salveti@linaro.org>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/misc/ti-st/st_kim.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
+index 83269f1..d48b9e0 100644
+--- a/drivers/misc/ti-st/st_kim.c
++++ b/drivers/misc/ti-st/st_kim.c
+@@ -244,7 +244,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
+ if (version & 0x8000)
+ maj_ver |= 0x0008;
+
+- sprintf(bts_scr_name, "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
++ sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
+
+ /* to be accessed later via sysfs entry */
+ kim_gdata->version.full = version;
+@@ -287,7 +287,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
+ long len = 0;
+ unsigned char *ptr = NULL;
+ unsigned char *action_ptr = NULL;
+- unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */
++ unsigned char bts_scr_name[50] = { 0 }; /* 50 char long bts scr name? */
+ int wr_room_space;
+ int cmd_size;
+ unsigned long timeout;
diff --git a/patches/linux-3.8.13/0220-am33xx-cpsw-default-to-ethernet-hwaddr-from-efuse-if.patch b/patches/linux-3.8.13/0220-am33xx-cpsw-default-to-ethernet-hwaddr-from-efuse-if.patch
new file mode 100644
index 0000000..d17d9ec
--- /dev/null
+++ b/patches/linux-3.8.13/0220-am33xx-cpsw-default-to-ethernet-hwaddr-from-efuse-if.patch
@@ -0,0 +1,151 @@
+From: Peter Korsgaard <jacmet@sunsite.dk>
+Date: Wed, 16 Jan 2013 21:01:13 +0000
+Subject: [PATCH] am33xx: cpsw: default to ethernet hwaddr from efuse if not
+ defined in dt
+
+When booting with CONFIG_ARM_APPENDED_DTB (either because of using an old
+U-Boot, not wanting the hassle of 2 files or when using Falcon fast boot
+mode in U-Boot), nothing updates the ethernet hwaddr specified for the
+CPSW slaves, causing the driver to use a random hwaddr, which is some times
+troublesome.
+
+The am33xx has unique ethernet hwaddrs programmed in the efuse, so it makes
+more sense to default to these rather than random ones. Add a fixup step
+which adds mac-address dt properties using the efuse addresses if the DTB
+didn't contain valid ones.
+
+Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
+---
+ arch/arm/mach-omap2/Makefile | 3 ++
+ arch/arm/mach-omap2/am33xx-cpsw.c | 94 +++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-omap2/control.h | 4 ++
+ 3 files changed, 101 insertions(+)
+ create mode 100644 arch/arm/mach-omap2/am33xx-cpsw.c
+
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index 947cafe..6cde196 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -295,4 +295,7 @@ endif
+ emac-$(CONFIG_TI_DAVINCI_EMAC) := am35xx-emac.o
+ obj-y += $(emac-m) $(emac-y)
+
++cpsw-$(CONFIG_TI_CPSW) := am33xx-cpsw.o
++obj-y += $(cpsw-m) $(cpsw-y)
++
+ obj-y += common-board-devices.o twl-common.o dss-common.o
+diff --git a/arch/arm/mach-omap2/am33xx-cpsw.c b/arch/arm/mach-omap2/am33xx-cpsw.c
+new file mode 100644
+index 0000000..5a674d9
+--- /dev/null
++++ b/arch/arm/mach-omap2/am33xx-cpsw.c
+@@ -0,0 +1,94 @@
++/*
++ * am335x specific cpsw dt fixups
++ *
++ * 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/kernel.h>
++#include <linux/init.h>
++#include <linux/etherdevice.h>
++#include <linux/of.h>
++#include <linux/of_net.h>
++
++#include "soc.h"
++#include "control.h"
++
++/**
++ * am33xx_dt_cpsw_set_mac_from_efuse - Add mac-address property using
++ * ethernet hwaddr from efuse
++ * @np: Pointer to the cpsw slave to set mac address of
++ * @idx: Mac address index to use from efuse
++ */
++static void am33xx_dt_cpsw_set_mac_from_efuse(struct device_node *np, int idx)
++{
++ struct property *prop;
++ u32 lo, hi;
++ u8 *mac;
++
++ switch (idx) {
++ case 0:
++ lo = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID0_LOW);
++ hi = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID0_HIGH);
++ break;
++
++ case 1:
++ lo = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID1_LOW);
++ hi = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID1_HIGH);
++ break;
++
++ default:
++ pr_err("cpsw.%d: too many slaves found\n", idx);
++ return;
++ }
++
++ prop = kzalloc(sizeof(*prop) + ETH_ALEN, GFP_KERNEL);
++ if (!prop)
++ return;
++
++ prop->value = prop + 1;
++ prop->length = ETH_ALEN;
++ prop->name = kstrdup("mac-address", GFP_KERNEL);
++ if (!prop->name) {
++ kfree(prop);
++ return;
++ }
++
++ mac = prop->value;
++
++ mac[0] = hi;
++ mac[1] = hi >> 8;
++ mac[2] = hi >> 16;
++ mac[3] = hi >> 24;
++ mac[4] = lo;
++ mac[5] = lo >> 8;
++
++ of_update_property(np, prop);
++
++ pr_info("cpsw.%d: No hwaddr in dt. Using %pM from efuse\n", idx, mac);
++}
++
++static int __init am33xx_dt_cpsw_mac_fixup(void)
++{
++ struct device_node *np, *slave;
++ int idx = 0;
++
++ if (!soc_is_am33xx())
++ return -ENODEV;
++
++ for_each_compatible_node(np, NULL, "ti,cpsw")
++ for_each_node_by_name(slave, "slave") {
++ if (!of_get_mac_address(slave))
++ am33xx_dt_cpsw_set_mac_from_efuse(slave, idx);
++ idx++;
++ }
++
++ return 0;
++}
++arch_initcall(am33xx_dt_cpsw_mac_fixup);
+diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
+index 35d17a6..12d8468 100644
+--- a/arch/arm/mach-omap2/control.h
++++ b/arch/arm/mach-omap2/control.h
+@@ -352,6 +352,10 @@
+ /* AM33XX CONTROL_STATUS register */
+ #define AM33XX_CONTROL_STATUS 0x040
+ #define AM33XX_CONTROL_SEC_CLK_CTRL 0x1bc
++#define AM33XX_CONTROL_MAC_ID0_LOW 0x630
++#define AM33XX_CONTROL_MAC_ID0_HIGH 0x634
++#define AM33XX_CONTROL_MAC_ID1_LOW 0x638
++#define AM33XX_CONTROL_MAC_ID1_HIGH 0x63c
+
+ /* AM33XX CONTROL_STATUS bitfields (partial) */
+ #define AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT 22
diff --git a/patches/linux-3.8.13/0221-Attempted-SMC911x-BQL-patch.patch b/patches/linux-3.8.13/0221-Attempted-SMC911x-BQL-patch.patch
new file mode 100644
index 0000000..9e34e76
--- /dev/null
+++ b/patches/linux-3.8.13/0221-Attempted-SMC911x-BQL-patch.patch
@@ -0,0 +1,56 @@
+From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Date: Thu, 29 Nov 2012 11:17:05 +0100
+Subject: [PATCH] Attempted SMC911x BQL patch
+
+First attempt at BQL on smsc911x.
+
+Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+---
+ drivers/net/ethernet/smsc/smsc911x.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
+index e112877..8907fde7 100644
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -1107,6 +1107,7 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
+ {
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int tx_stat;
++ unsigned int bytes_compl = 0, pkts_compl = 0;
+
+ while ((tx_stat = smsc911x_tx_get_txstatus(pdata)) != 0) {
+ if (unlikely(tx_stat & 0x80000000)) {
+@@ -1124,6 +1125,8 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
+ } else {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += (tx_stat >> 16);
++ pkts_compl++;
++ bytes_compl += (tx_stat >> 16);
+ }
+ if (unlikely(tx_stat & TX_STS_EXCESS_COL_)) {
+ dev->stats.collisions += 16;
+@@ -1140,6 +1143,7 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
+ }
+ }
+ }
++ netdev_completed_queue(dev, pkts_compl, bytes_compl);
+ }
+
+ /* Increments the Rx error counters */
+@@ -1602,6 +1606,7 @@ static int smsc911x_stop(struct net_device *dev)
+ /* At this point all Rx and Tx activity is stopped */
+ dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
+ smsc911x_tx_update_txcounters(dev);
++ netdev_reset_queue(dev);
+
+ /* Bring the PHY down */
+ if (pdata->phy_dev)
+@@ -1645,6 +1650,7 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ wrsz >>= 2;
+
+ pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
++ netdev_sent_queue(dev, skb->len);
+ freespace -= (skb->len + 32);
+ skb_tx_timestamp(skb);
+ dev_kfree_skb(skb);
diff --git a/patches/linux-3.8.13/0222-cpsw-Fix-interrupt-storm-among-other-things.patch b/patches/linux-3.8.13/0222-cpsw-Fix-interrupt-storm-among-other-things.patch
new file mode 100644
index 0000000..84f5118
--- /dev/null
+++ b/patches/linux-3.8.13/0222-cpsw-Fix-interrupt-storm-among-other-things.patch
@@ -0,0 +1,419 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 17 Jan 2013 20:18:32 +0200
+Subject: [PATCH] cpsw: Fix interrupt storm among other things
+
+Fix interrupt storm on bone A4 cause by non-by-the-book interrupt handling.
+While at it, added a non-NAPI mode (which is easier to debug), plus
+some general fixes.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ Documentation/devicetree/bindings/net/cpsw.txt | 1 +
+ drivers/net/ethernet/ti/cpsw.c | 222 ++++++++++++++++++++----
+ drivers/net/ethernet/ti/davinci_cpdma.c | 4 +-
+ drivers/net/ethernet/ti/davinci_cpdma.h | 2 +-
+ include/linux/platform_data/cpsw.h | 1 +
+ 5 files changed, 194 insertions(+), 36 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
+index 6ddd028..d46b293 100644
+--- a/Documentation/devicetree/bindings/net/cpsw.txt
++++ b/Documentation/devicetree/bindings/net/cpsw.txt
+@@ -20,6 +20,7 @@ Required properties:
+ - cpts_clock_shift : Denominator to convert input clock ticks into nanoseconds
+ - phy_id : Specifies slave phy id
+ - mac-address : Specifies slave MAC address
++- disable-napi : Disables driver NAPI
+
+ Optional properties:
+ - ti,hwmods : Must be "cpgmac0"
+diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
+index 3b1be52..21ba53e 100644
+--- a/drivers/net/ethernet/ti/cpsw.c
++++ b/drivers/net/ethernet/ti/cpsw.c
+@@ -148,10 +148,37 @@ struct cpsw_wr_regs {
+ u32 soft_reset;
+ u32 control;
+ u32 int_control;
+- u32 rx_thresh_en;
+- u32 rx_en;
+- u32 tx_en;
+- u32 misc_en;
++ u32 c0_rx_thresh_en;
++ u32 c0_rx_en;
++ u32 c0_tx_en;
++ u32 c0_misc_en;
++ u32 c1_rx_thresh_en;
++ u32 c1_rx_en;
++ u32 c1_tx_en;
++ u32 c1_misc_en;
++ u32 c2_rx_thresh_en;
++ u32 c2_rx_en;
++ u32 c2_tx_en;
++ u32 c2_misc_en;
++ u32 c0_rx_thresh_stat;
++ u32 c0_rx_stat;
++ u32 c0_tx_stat;
++ u32 c0_misc_stat;
++ u32 c1_rx_thresh_stat;
++ u32 c1_rx_stat;
++ u32 c1_tx_stat;
++ u32 c1_misc_stat;
++ u32 c2_rx_thresh_stat;
++ u32 c2_rx_stat;
++ u32 c2_tx_stat;
++ u32 c2_misc_stat;
++ u32 c0_rx_imax;
++ u32 c0_tx_imax;
++ u32 c1_rx_imax;
++ u32 c1_tx_imax;
++ u32 c2_rx_imax;
++ u32 c2_tx_imax;
++ u32 rgmii_ctl;
+ };
+
+ struct cpsw_ss_regs {
+@@ -352,8 +379,8 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+
+ static void cpsw_intr_enable(struct cpsw_priv *priv)
+ {
+- __raw_writel(0xFF, &priv->wr_regs->tx_en);
+- __raw_writel(0xFF, &priv->wr_regs->rx_en);
++ __raw_writel(0xFF, &priv->wr_regs->c0_tx_en);
++ __raw_writel(0xFF, &priv->wr_regs->c0_rx_en);
+
+ cpdma_ctlr_int_ctrl(priv->dma, true);
+ return;
+@@ -361,8 +388,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)
+
+ static void cpsw_intr_disable(struct cpsw_priv *priv)
+ {
+- __raw_writel(0, &priv->wr_regs->tx_en);
+- __raw_writel(0, &priv->wr_regs->rx_en);
++ __raw_writel(0, &priv->wr_regs->c0_tx_en);
++ __raw_writel(0, &priv->wr_regs->c0_rx_en);
+
+ cpdma_ctlr_int_ctrl(priv->dma, false);
+ return;
+@@ -399,7 +426,10 @@ void cpsw_rx_handler(void *token, int len, int status)
+ skb_put(skb, len);
+ cpts_rx_timestamp(&priv->cpts, skb);
+ skb->protocol = eth_type_trans(skb, ndev);
+- netif_receive_skb(skb);
++ if (priv->data.disable_napi)
++ netif_rx(skb);
++ else
++ netif_receive_skb(skb);
+ priv->stats.rx_bytes += len;
+ priv->stats.rx_packets++;
+ skb = NULL;
+@@ -431,6 +461,7 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
+ cpsw_disable_irq(priv);
+ napi_schedule(&priv->napi);
+ }
++
+ return IRQ_HANDLED;
+ }
+
+@@ -445,23 +476,104 @@ static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+ static int cpsw_poll(struct napi_struct *napi, int budget)
+ {
+ struct cpsw_priv *priv = napi_to_priv(napi);
+- int num_tx, num_rx;
++ int num_tx, num_rx, num_total_tx, num_total_rx;
++ int budget_left;
++
++ budget_left = budget;
+
+- num_tx = cpdma_chan_process(priv->txch, 128);
+- num_rx = cpdma_chan_process(priv->rxch, budget);
++ /* read status and throw away */
++ (void)__raw_readl(&priv->wr_regs->c0_tx_stat);
++
++ /* handle all transmits */
++ num_total_tx = 0;
++ while (budget_left > 0 &&
++ (num_tx = cpdma_chan_process(priv->txch, 128)) > 0) {
++ budget_left -= num_tx;
++ num_total_tx += num_tx;
++ }
+
+- if (num_rx || num_tx)
+- cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
+- num_rx, num_tx);
++ if (num_total_tx > 0 && budget_left > 0)
++ cpdma_ctlr_eoi(priv->dma, 0x02);
++
++ /* read status and throw away */
++ (void)__raw_readl(&priv->wr_regs->c0_rx_stat);
++
++ /* handle all receives */
++ num_total_rx = 0;
++ while (budget_left > 0 &&
++ (num_rx = cpdma_chan_process(priv->rxch, budget_left)) > 0) {
++ budget_left -= num_rx;
++ num_total_rx += num_rx;
++ }
+
+- if (num_rx < budget) {
++ if (num_total_rx > 0 && budget_left > 0)
++ cpdma_ctlr_eoi(priv->dma, 0x01);
++
++ if ((num_total_rx + num_total_tx) < budget) {
+ napi_complete(napi);
+ cpsw_intr_enable(priv);
+- cpdma_ctlr_eoi(priv->dma);
+ cpsw_enable_irq(priv);
+ }
+
+- return num_rx;
++ return num_total_rx + num_total_rx;
++}
++
++static irqreturn_t cpsw_rx_thresh_pend_irq(int irq, void *dev_id)
++{
++ struct cpsw_priv *priv = dev_id;
++
++ (void)priv;
++
++ /* not handling this interrupt yet */
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t cpsw_rx_pend_irq(int irq, void *dev_id)
++{
++ struct cpsw_priv *priv = dev_id;
++ int num_rx, total_rx;
++ u32 rx_stat;
++
++ rx_stat = __raw_readl(&priv->wr_regs->c0_rx_stat) & 0xff;
++ if (rx_stat == 0)
++ return IRQ_NONE;
++
++ total_rx = 0;
++ while ((num_rx = cpdma_chan_process(priv->rxch,
++ priv->data.rx_descs)) > 0)
++ total_rx += num_rx;
++
++ cpdma_ctlr_eoi(priv->dma, 0x01);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t cpsw_tx_pend_irq(int irq, void *dev_id)
++{
++ struct cpsw_priv *priv = dev_id;
++ int num_tx, total_tx;
++ u32 tx_stat;
++
++ tx_stat = __raw_readl(&priv->wr_regs->c0_tx_stat) & 0xff;
++ if (tx_stat == 0)
++ return IRQ_NONE;
++
++ total_tx = 0;
++ while ((num_tx = cpdma_chan_process(priv->txch, 128)) > 0)
++ total_tx += num_tx;
++
++ cpdma_ctlr_eoi(priv->dma, 0x02);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t cpsw_misc_pend_irq(int irq, void *dev_id)
++{
++ struct cpsw_priv *priv = dev_id;
++
++ (void)priv;
++ /* not handling this interrupt yet */
++ return IRQ_HANDLED;
+ }
+
+ static inline void soft_reset(const char *module, void __iomem *reg)
+@@ -678,8 +790,10 @@ static int cpsw_ndo_open(struct net_device *ndev)
+
+ cpdma_ctlr_start(priv->dma);
+ cpsw_intr_enable(priv);
+- napi_enable(&priv->napi);
+- cpdma_ctlr_eoi(priv->dma);
++ if (!priv->data.disable_napi)
++ napi_enable(&priv->napi);
++ cpdma_ctlr_eoi(priv->dma, 0x01);
++ cpdma_ctlr_eoi(priv->dma, 0x02);
+
+ return 0;
+ }
+@@ -698,8 +812,10 @@ static int cpsw_ndo_stop(struct net_device *ndev)
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ cpsw_info(priv, ifdown, "shutting down cpsw device\n");
++ cpsw_disable_irq(priv);
+ netif_stop_queue(priv->ndev);
+- napi_disable(&priv->napi);
++ if (!priv->data.disable_napi)
++ napi_disable(&priv->napi);
+ netif_carrier_off(priv->ndev);
+ cpsw_intr_disable(priv);
+ cpdma_ctlr_int_ctrl(priv->dma, false);
+@@ -901,7 +1017,8 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)
+ cpdma_chan_start(priv->txch);
+ cpdma_ctlr_int_ctrl(priv->dma, true);
+ cpsw_intr_enable(priv);
+- cpdma_ctlr_eoi(priv->dma);
++ cpdma_ctlr_eoi(priv->dma, 0x01);
++ cpdma_ctlr_eoi(priv->dma, 0x02);
+ }
+
+ static struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev)
+@@ -917,14 +1034,21 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
+
+ cpsw_intr_disable(priv);
+ cpdma_ctlr_int_ctrl(priv->dma, false);
+- cpsw_interrupt(ndev->irq, priv);
++ if (!priv->data.disable_napi)
++ cpsw_interrupt(ndev->irq, priv);
++ else {
++ /* bah! */
++ cpsw_rx_pend_irq(ndev->irq, priv);
++ cpsw_tx_pend_irq(ndev->irq, priv);
++ }
+ cpdma_ctlr_int_ctrl(priv->dma, true);
+ cpsw_intr_enable(priv);
+- cpdma_ctlr_eoi(priv->dma);
++ cpdma_ctlr_eoi(priv->dma, 0x01);
++ cpdma_ctlr_eoi(priv->dma, 0x02);
+ }
+ #endif
+
+-static const struct net_device_ops cpsw_netdev_ops = {
++static struct net_device_ops cpsw_netdev_ops = {
+ .ndo_open = cpsw_ndo_open,
+ .ndo_stop = cpsw_ndo_stop,
+ .ndo_start_xmit = cpsw_ndo_start_xmit,
+@@ -1079,6 +1203,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
+ }
+ data->bd_ram_size = prop;
+
++ if (of_property_read_bool(node, "disable-napi"))
++ data->disable_napi = 1;
++
+ if (of_property_read_u32(node, "rx_descs", &prop)) {
+ pr_err("Missing rx_descs property in the DT.\n");
+ ret = -EINVAL;
+@@ -1136,6 +1263,22 @@ error_ret:
+ return ret;
+ }
+
++static irq_handler_t cpsw_get_irq_handler(struct cpsw_priv *priv, int irq_idx)
++{
++ static const irq_handler_t non_napi_irq_tab[4] = {
++ cpsw_rx_thresh_pend_irq, cpsw_rx_pend_irq,
++ cpsw_tx_pend_irq, cpsw_misc_pend_irq
++ };
++
++ if ((unsigned int)irq_idx >= 4)
++ return NULL;
++
++ if (!priv->data.disable_napi)
++ return cpsw_interrupt;
++
++ return non_napi_irq_tab[irq_idx];
++}
++
+ static int cpsw_probe(struct platform_device *pdev)
+ {
+ struct cpsw_platform_data *data = pdev->dev.platform_data;
+@@ -1146,7 +1289,8 @@ static int cpsw_probe(struct platform_device *pdev)
+ void __iomem *ss_regs, *wr_regs;
+ struct resource *res;
+ u32 slave_offset, sliver_offset, slave_size;
+- int ret = 0, i, k = 0;
++ irq_handler_t irqh;
++ int ret = 0, i, j, k = 0;
+
+ ndev = alloc_etherdev(sizeof(struct cpsw_priv));
+ if (!ndev) {
+@@ -1333,24 +1477,36 @@ static int cpsw_probe(struct platform_device *pdev)
+ goto clean_ale_ret;
+ }
+
+- while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
+- for (i = res->start; i <= res->end; i++) {
+- if (request_irq(i, cpsw_interrupt, IRQF_DISABLED,
++ dev_info(&pdev->dev, "NAPI %s\n", priv->data.disable_napi ?
++ "disabled" : "enabled");
++
++ /* get interrupts */
++ j = k = 0;
++ while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, j++))) {
++ for (i = res->start; k < 4 && i <= res->end; i++) {
++ irqh = cpsw_get_irq_handler(priv, k);
++ if (irqh == NULL) {
++ dev_err(&pdev->dev, "Unable to get handler "
++ "for #%d (%d)\n", k, i);
++ goto clean_ale_ret;
++ }
++ if (request_irq(i, irqh, IRQF_DISABLED,
+ dev_name(&pdev->dev), priv)) {
+ dev_err(priv->dev, "error attaching irq\n");
+ goto clean_ale_ret;
+ }
+- priv->irqs_table[k] = i;
+- priv->num_irqs = k;
++ priv->irqs_table[k++] = i;
+ }
+- k++;
+ }
++ priv->num_irqs = k;
+
+ ndev->flags |= IFF_ALLMULTI; /* see cpsw_ndo_change_rx_flags() */
+
+ ndev->netdev_ops = &cpsw_netdev_ops;
+ SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
+- netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
++
++ if (!priv->data.disable_napi)
++ netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
+
+ /* register the network device */
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
+index 4995673..6effab2 100644
+--- a/drivers/net/ethernet/ti/davinci_cpdma.c
++++ b/drivers/net/ethernet/ti/davinci_cpdma.c
+@@ -474,9 +474,9 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
+ return 0;
+ }
+
+-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
++void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value)
+ {
+- dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
++ dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, value);
+ }
+
+ struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
+diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
+index afa19a0..b7c097d 100644
+--- a/drivers/net/ethernet/ti/davinci_cpdma.h
++++ b/drivers/net/ethernet/ti/davinci_cpdma.h
+@@ -86,7 +86,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
+ int cpdma_chan_process(struct cpdma_chan *chan, int quota);
+
+ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
+-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
++void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value);
+ int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
+
+ enum cpdma_control {
+diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
+index 24368a2..be5b27e 100644
+--- a/include/linux/platform_data/cpsw.h
++++ b/include/linux/platform_data/cpsw.h
+@@ -35,6 +35,7 @@ struct cpsw_platform_data {
+ u32 bd_ram_size; /*buffer descriptor ram size */
+ u32 rx_descs; /* Number of Rx Descriptios */
+ u32 mac_control; /* Mac control register */
++ int disable_napi; /* disable NAPI */
+ };
+
+ #endif /* __CPSW_H__ */
diff --git a/patches/linux-3.8.13/0223-beaglebone-TT3201-MCP2515-fixes.patch b/patches/linux-3.8.13/0223-beaglebone-TT3201-MCP2515-fixes.patch
new file mode 100644
index 0000000..cb9b159
--- /dev/null
+++ b/patches/linux-3.8.13/0223-beaglebone-TT3201-MCP2515-fixes.patch
@@ -0,0 +1,162 @@
+From: Alessandro Zummo <a.zummo@towertech.it>
+Date: Thu, 23 May 2013 20:57:04 +0200
+Subject: [PATCH] beaglebone: TT3201 MCP2515 fixes
+
+Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
+---
+ drivers/net/can/mcp251x.c | 47 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 37 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
+index 42b6d69..3555ef44 100644
+--- a/drivers/net/can/mcp251x.c
++++ b/drivers/net/can/mcp251x.c
+@@ -98,8 +98,9 @@
+ # define CANCTRL_REQOP_LOOPBACK 0x40
+ # define CANCTRL_REQOP_SLEEP 0x20
+ # define CANCTRL_REQOP_NORMAL 0x00
+-# define CANCTRL_OSM 0x08
+ # define CANCTRL_ABAT 0x10
++# define CANCTRL_OSM 0x08
++# define CANCTRL_CLKEN 0x04
+ #define TEC 0x1c
+ #define REC 0x1d
+ #define CNF1 0x2a
+@@ -292,7 +293,7 @@ static void mcp251x_clean(struct net_device *net)
+ /*
+ * Note about handling of error return of mcp251x_spi_trans: accessing
+ * registers via SPI is not really different conceptually than using
+- * normal I/O assembler instructions, although it's much more
++ * normal I/O assembly instructions, although it's much more
+ * complicated from a practical POV. So it's not advisable to always
+ * check the return value of this function. Imagine that every
+ * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
+@@ -499,7 +500,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
+
+ static void mcp251x_hw_sleep(struct spi_device *spi)
+ {
+- mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
++// mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
+ }
+
+ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
+@@ -556,13 +557,16 @@ static int mcp251x_set_normal_mode(struct spi_device *spi)
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+ /* Put device into loopback mode */
+- mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK);
++ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK | CANCTRL_CLKEN);
+ } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
+ /* Put device into listen-only mode */
+- mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY);
++ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY | CANCTRL_CLKEN);
+ } else {
+ /* Put device into normal mode */
+- mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
++ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL | CANCTRL_CLKEN);
++
++ netdev_info(priv->net, "CANCTRL: 0x%02x\n",
++ mcp251x_read_reg(spi, CANCTRL));
+
+ /* Wait for the device to enter normal mode */
+ timeout = jiffies + HZ;
+@@ -594,11 +598,15 @@ static int mcp251x_do_set_bittiming(struct net_device *net)
+ (bt->prop_seg - 1));
+ mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK,
+ (bt->phase_seg2 - 1));
+- dev_info(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n",
++
++ netdev_info(net, "CNF: 0x%02x 0x%02x 0x%02x\n",
+ mcp251x_read_reg(spi, CNF1),
+ mcp251x_read_reg(spi, CNF2),
+ mcp251x_read_reg(spi, CNF3));
+
++ netdev_info(net, "CANCTRL: 0x%02x\n",
++ mcp251x_read_reg(spi, CANCTRL));
++
+ return 0;
+ }
+
+@@ -609,6 +617,7 @@ static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,
+
+ mcp251x_write_reg(spi, RXBCTRL(0),
+ RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1);
++
+ mcp251x_write_reg(spi, RXBCTRL(1),
+ RXBCTRL_RXM0 | RXBCTRL_RXM1);
+ return 0;
+@@ -736,7 +745,9 @@ static void mcp251x_tx_work_handler(struct work_struct *ws)
+ mutex_lock(&priv->mcp_lock);
+ if (priv->tx_skb) {
+ if (priv->can.state == CAN_STATE_BUS_OFF) {
++
+ mcp251x_clean(net);
++
+ } else {
+ frame = (struct can_frame *)priv->tx_skb->data;
+
+@@ -835,21 +846,37 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
+
+ /* Update can state */
+ if (eflag & EFLG_TXBO) {
++
++ netdev_err(net, "err: bus off\n");
++
+ new_state = CAN_STATE_BUS_OFF;
+ can_id |= CAN_ERR_BUSOFF;
+ } else if (eflag & EFLG_TXEP) {
++
++ netdev_err(net, "err: txep\n");
++
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ can_id |= CAN_ERR_CRTL;
+ data1 |= CAN_ERR_CRTL_TX_PASSIVE;
++
+ } else if (eflag & EFLG_RXEP) {
++
++ netdev_err(net, "err: rxep\n");
++
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ can_id |= CAN_ERR_CRTL;
+ data1 |= CAN_ERR_CRTL_RX_PASSIVE;
+ } else if (eflag & EFLG_TXWAR) {
++
++ netdev_err(net, "err: txwar\n");
++
+ new_state = CAN_STATE_ERROR_WARNING;
+ can_id |= CAN_ERR_CRTL;
+ data1 |= CAN_ERR_CRTL_TX_WARNING;
+ } else if (eflag & EFLG_RXWAR) {
++
++ netdev_err(net, "err: rxwar\n");
++
+ new_state = CAN_STATE_ERROR_WARNING;
+ can_id |= CAN_ERR_CRTL;
+ data1 |= CAN_ERR_CRTL_RX_WARNING;
+@@ -927,7 +954,7 @@ static int mcp251x_open(struct net_device *net)
+
+ ret = open_candev(net);
+ if (ret) {
+- dev_err(&spi->dev, "unable to set initial baudrate!\n");
++ netdev_err(net, "failed to open can device\n");
+ return ret;
+ }
+
+@@ -948,7 +975,7 @@ static int mcp251x_open(struct net_device *net)
+ ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
+ flags, DEVICE_NAME, priv);
+ if (ret) {
+- dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
++ netdev_err(net, "failed to acquire irq %d\n", spi->irq);
+ if (pdata->transceiver_enable)
+ pdata->transceiver_enable(0);
+ close_candev(net);
+@@ -1084,7 +1111,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
+
+ ret = register_candev(net);
+ if (!ret) {
+- dev_info(&spi->dev, "probed\n");
++ netdev_info(priv->net, "probed\n");
+ return ret;
+ }
+ error_probe:
diff --git a/patches/linux-3.8.13/0224-add-proper-db.txt-for-CRDA.patch b/patches/linux-3.8.13/0224-add-proper-db.txt-for-CRDA.patch
new file mode 100644
index 0000000..4adc542
--- /dev/null
+++ b/patches/linux-3.8.13/0224-add-proper-db.txt-for-CRDA.patch
@@ -0,0 +1,830 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 28 Mar 2013 11:10:40 +0100
+Subject: [PATCH] add proper db.txt for CRDA
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ net/wireless/db.txt | 816 +++++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 799 insertions(+), 17 deletions(-)
+
+diff --git a/net/wireless/db.txt b/net/wireless/db.txt
+index a2fc3a0..c5861b8 100644
+--- a/net/wireless/db.txt
++++ b/net/wireless/db.txt
+@@ -1,17 +1,799 @@
+-#
+-# This file is a placeholder to prevent accidental build breakage if someone
+-# enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to
+-# enable that build option.
+-#
+-# You should be using CRDA instead. It is even better if you use the CRDA
+-# package provided by your distribution, since they will probably keep it
+-# up-to-date on your behalf.
+-#
+-# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will
+-# need to replace this file with one containing appropriately formatted
+-# regulatory rules that cover the regulatory domains you will be using. Your
+-# best option is to extract the db.txt file from the wireless-regdb git
+-# repository:
+-#
+-# git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
+-#
++# This is the world regulatory domain
++country 00:
++ (2402 - 2472 @ 40), (3, 20)
++ # Channel 12 - 13.
++ (2457 - 2482 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
++ # Channel 14. Only JP enables this and for 802.11b only
++ (2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
++ # Channel 36 - 48
++ (5170 - 5250 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
++ # NB: 5260 MHz - 5700 MHz requies DFS
++ # Channel 149 - 165
++ (5735 - 5835 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
++
++
++country AD:
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country AE:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country AL:
++ (2402 - 2482 @ 20), (N/A, 20)
++
++country AM:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (N/A, 18)
++ (5250 - 5330 @ 20), (N/A, 18), DFS
++
++country AN:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country AR:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country AT: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country AU:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 23)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country AW:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country AZ:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 18)
++ (5250 - 5330 @ 40), (N/A, 18), DFS
++
++country BA: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country BB:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 23)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country BD:
++ (2402 - 2482 @ 40), (N/A, 20)
++
++country BE: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country BG: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 23)
++ (5250 - 5290 @ 40), (N/A, 23), DFS
++ (5490 - 5710 @ 40), (N/A, 30), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country BH:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (N/A, 20)
++ (5250 - 5330 @ 20), (N/A, 20), DFS
++ (5735 - 5835 @ 20), (N/A, 20)
++
++country BL:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 18)
++ (5250 - 5330 @ 40), (N/A, 18), DFS
++
++country BN:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country BO:
++ (2402 - 2482 @ 40), (N/A, 30)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country BR:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country BY:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country BZ:
++ (2402 - 2482 @ 40), (N/A, 30)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country CA:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country CH: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country CL:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5735 - 5835 @ 40), (N/A, 20)
++
++country CN:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++ # 60 gHz band channels 1,4: 28dBm, channels 2,3: 44dBm
++ # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf
++ (57240 - 59400 @ 2160), (N/A, 28)
++ (59400 - 63720 @ 2160), (N/A, 44)
++ (63720 - 65880 @ 2160), (N/A, 28)
++
++country CO:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country CR:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (3, 17)
++ (5250 - 5330 @ 20), (3, 23), DFS
++ (5735 - 5835 @ 20), (3, 30)
++
++country CS:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country CY: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
++# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
++# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
++# implemented.
++country CZ: DFS-ETSI
++ (2400 - 2483.5 @ 40), (N/A, 100 mW)
++ (5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
++ (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
++ (5470 - 5725 @ 40), (N/A, 500 mW), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
++# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
++# For the 5GHz range also see
++# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
++# The values have been reduced by a factor of 2 (3db) for non TPC devices
++# (in other words: devices with TPC can use twice the tx power of this table).
++# Note that the docs do not require TPC for 5150--5250; the reduction to
++# 100mW thus is not strictly required -- however the conservative 100mW
++# limit is used here as the non-interference with radar and satellite
++# apps relies on the attenuation by the building walls only in the
++# absence of DFS; the neighbour countries have 100mW limit here as well.
++
++country DE: DFS-ETSI
++ # entries 279004 and 280006
++ (2400 - 2483.5 @ 40), (N/A, 100 mW)
++ # entry 303005
++ (5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
++ # entries 304002 and 305002
++ (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
++ # entries 308002, 309001 and 310003
++ (5470 - 5725 @ 40), (N/A, 500 mW), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country DK: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country DO:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country DZ:
++ (2402 - 2482 @ 40), (N/A, 20)
++
++country EC:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (3, 17)
++ (5250 - 5330 @ 20), (3, 23), DFS
++ (5735 - 5835 @ 20), (3, 30)
++
++country EE: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country EG:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (N/A, 20)
++ (5250 - 5330 @ 20), (N/A, 20), DFS
++
++country ES: DFS-ETSI
++ (2400 - 2483.5 @ 40), (N/A, 100 mW)
++ (5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
++ (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
++ (5470 - 5725 @ 40), (N/A, 500 mW), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country FI: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country FR: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country GE:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 18)
++ (5250 - 5330 @ 40), (N/A, 18), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country GB: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country GD:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country GR: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country GL: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (N/A, 20)
++ (5250 - 5330 @ 20), (N/A, 20), DFS
++ (5490 - 5710 @ 20), (N/A, 27), DFS
++
++country GT:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country GU:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 20), (3, 17)
++ (5250 - 5330 @ 20), (3, 23), DFS
++ (5735 - 5835 @ 20), (3, 30)
++
++country HN:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country HK:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country HR: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country HT:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country HU: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country ID:
++ (2402 - 2482 @ 40), (N/A, 20)
++
++country IE: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country IL:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
++ (5250 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR, DFS
++
++country IN:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5735 - 5835 @ 40), (N/A, 20)
++
++country IS: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country IR:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country IT: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country JM:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country JP:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (2474 - 2494 @ 20), (N/A, 20), NO-OFDM
++ (4910 - 4990 @ 40), (N/A, 23)
++ (5030 - 5090 @ 40), (N/A, 23)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 23), DFS
++
++country JO:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 18)
++
++country KE:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country KH:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country KP:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5330 @ 40), (3, 20)
++ (5160 - 5250 @ 40), (3, 20), DFS
++ (5490 - 5630 @ 40), (3, 30), DFS
++ (5735 - 5815 @ 40), (3, 30)
++
++country KR:
++ (2402 - 2482 @ 20), (N/A, 20)
++ (5170 - 5250 @ 20), (3, 20)
++ (5250 - 5330 @ 20), (3, 20), DFS
++ (5490 - 5630 @ 20), (3, 30), DFS
++ (5735 - 5815 @ 20), (3, 30)
++
++country KW:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++
++country KZ:
++ (2402 - 2482 @ 40), (N/A, 20)
++
++country LB:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country LI: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++
++country LK:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (3, 17)
++ (5250 - 5330 @ 20), (3, 20), DFS
++ (5490 - 5710 @ 20), (3, 20), DFS
++ (5735 - 5835 @ 20), (3, 30)
++
++country LT: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country LU: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country LV: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country MC: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 18)
++ (5250 - 5330 @ 40), (N/A, 18), DFS
++
++country MA:
++ (2402 - 2482 @ 40), (N/A, 20)
++
++country MO:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 23)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country MK: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country MT: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country MY:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 30), DFS
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country MX:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country NL: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20), NO-OUTDOOR
++ (5250 - 5330 @ 40), (N/A, 20), NO-OUTDOOR, DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country NO: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country NP:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country NZ:
++ (2402 - 2482 @ 40), (N/A, 30)
++ (5170 - 5250 @ 20), (3, 23)
++ (5250 - 5330 @ 20), (3, 23), DFS
++ (5735 - 5835 @ 20), (3, 30)
++
++country OM:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country PA:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country PE:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country PG:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country PH:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country PK:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country PL: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country PT: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country PR:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 23), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country QA:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country RO: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++
++# Source:
++# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
++country RS:
++ (2400 - 2483.5 @ 40), (N/A, 100 mW)
++ (5150 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR
++ (5470 - 5725 @ 20), (3, 1000 mW), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country RU:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 20), (N/A, 30)
++
++country RW:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5835 @ 40), (N/A, 30)
++
++country SA:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (3, 23)
++ (5250 - 5330 @ 20), (3, 23), DFS
++ (5735 - 5835 @ 20), (3, 30)
++
++country SE: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country SG:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5735 - 5835 @ 40), (N/A, 20)
++
++country SI: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country SK: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++ (5490 - 5710 @ 40), (N/A, 27), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country SV:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (3, 17)
++ (5250 - 5330 @ 20), (3, 23), DFS
++ (5735 - 5835 @ 20), (3, 30)
++
++country SY:
++ (2402 - 2482 @ 40), (N/A, 20)
++
++country TW:
++ (2402 - 2472 @ 40), (3, 27)
++ (5270 - 5330 @ 40), (3, 17), DFS
++ (5735 - 5815 @ 40), (3, 30)
++
++country TH:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country TT:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country TN:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (N/A, 20)
++ (5250 - 5330 @ 20), (N/A, 20), DFS
++
++country TR: DFS-ETSI
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 20), (N/A, 20)
++ (5250 - 5330 @ 20), (N/A, 20), DFS
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++# Source:
++# #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874
++# #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361
++# (appendix 8)
++# Listed 5GHz range is a lowest common denominator for all related
++# rules in the referenced laws. Such a range is used because of
++# disputable definitions there.
++country UA:
++ (2400 - 2483.5 @ 40), (N/A, 20), NO-OUTDOOR
++ (5150 - 5350 @ 40), (N/A, 20), NO-OUTDOOR
++ # 60 gHz band channels 1-4, ref: Etsi En 302 567
++ (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
++
++country US: DFS-FCC
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5600 @ 40), (3, 20), DFS
++ (5650 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++ # 60g band
++ # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
++ # channels 1,2,3, EIRP=40dBm(43dBm peak)
++ (57240 - 63720 @ 2160), (N/A, 40)
++
++country UY:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country UZ:
++ (2402 - 2472 @ 40), (3, 27)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country VE:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5735 - 5815 @ 40), (N/A, 23)
++
++country VN:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (N/A, 20)
++ (5250 - 5330 @ 40), (N/A, 20), DFS
++
++country YE:
++ (2402 - 2482 @ 40), (N/A, 20)
++
++country ZA:
++ (2402 - 2482 @ 40), (N/A, 20)
++ (5170 - 5250 @ 40), (3, 17)
++ (5250 - 5330 @ 40), (3, 20), DFS
++ (5490 - 5710 @ 40), (3, 20), DFS
++ (5735 - 5835 @ 40), (3, 30)
++
++country ZW:
++ (2402 - 2482 @ 40), (N/A, 20)
++
diff --git a/patches/linux-3.8.13/0225-mcp251x-add-device-tree-support.patch b/patches/linux-3.8.13/0225-mcp251x-add-device-tree-support.patch
new file mode 100644
index 0000000..6b8eb7c
--- /dev/null
+++ b/patches/linux-3.8.13/0225-mcp251x-add-device-tree-support.patch
@@ -0,0 +1,349 @@
+From: Alessandro Zummo <a.zummo@towertech.it>
+Date: Sat, 25 May 2013 18:20:33 +0200
+Subject: [PATCH] mcp251x: add device tree support
+
+ drivers/net/can/mcp251x.c | 133 +++++++++++++++++++++++++++-------
+ include/linux/can/platform/mcp251x.h | 4 +
+ 2 files changed, 110 insertions(+), 27 deletions(-)
+---
+ drivers/net/can/mcp251x.c | 133 +++++++++++++++++++++++++++-------
+ include/linux/can/platform/mcp251x.h | 4 +
+ 2 files changed, 110 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
+index 3555ef44..a7f2418 100644
+--- a/drivers/net/can/mcp251x.c
++++ b/drivers/net/can/mcp251x.c
+@@ -1,6 +1,9 @@
+ /*
+ * CAN bus driver for Microchip 251x CAN Controller with SPI Interface
+ *
++ * Copyright (C) 2013 Tower Technologies
++ * Device Tree by Alessandro Zummo <a.zummo@towertech.it>
++ *
+ * MCP2510 support and bug fixes by Christian Pellegrin
+ * <chripell@evolware.org>
+ *
+@@ -72,6 +75,10 @@
+ #include <linux/module.h>
+ #include <linux/netdevice.h>
+ #include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_platform.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
+ #include <linux/slab.h>
+ #include <linux/spi/spi.h>
+ #include <linux/uaccess.h>
+@@ -238,9 +245,13 @@ enum mcp251x_model {
+ };
+
+ struct mcp251x_priv {
++
+ struct can_priv can;
+ struct net_device *net;
+ struct spi_device *spi;
++
++ struct mcp251x_platform_data *pdata;
++
+ enum mcp251x_model model;
+
+ struct mutex mcp_lock; /* SPI device lock */
+@@ -500,7 +511,10 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
+
+ static void mcp251x_hw_sleep(struct spi_device *spi)
+ {
+-// mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
++ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
++
++ if (!priv->pdata->stay_awake)
++ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
+ }
+
+ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
+@@ -557,16 +571,18 @@ static int mcp251x_set_normal_mode(struct spi_device *spi)
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+ /* Put device into loopback mode */
+- mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK | CANCTRL_CLKEN);
++ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK | (priv->pdata->enable_clkout ? CANCTRL_CLKEN : 0));
++
+ } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
+ /* Put device into listen-only mode */
+- mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY | CANCTRL_CLKEN);
++ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY | (priv->pdata->enable_clkout ? CANCTRL_CLKEN : 0));
++
+ } else {
+ /* Put device into normal mode */
+- mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL | CANCTRL_CLKEN);
++ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL | (priv->pdata->enable_clkout ? CANCTRL_CLKEN : 0));
+
+- netdev_info(priv->net, "CANCTRL: 0x%02x\n",
+- mcp251x_read_reg(spi, CANCTRL));
++ netdev_info(priv->net, "CANCTRL: 0x%02x\n",
++ mcp251x_read_reg(spi, CANCTRL));
+
+ /* Wait for the device to enter normal mode */
+ timeout = jiffies + HZ;
+@@ -676,7 +692,7 @@ static void mcp251x_open_clean(struct net_device *net)
+ {
+ struct mcp251x_priv *priv = netdev_priv(net);
+ struct spi_device *spi = priv->spi;
+- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
++ struct mcp251x_platform_data *pdata = priv->pdata;
+
+ free_irq(spi->irq, priv);
+ mcp251x_hw_sleep(spi);
+@@ -689,7 +705,7 @@ static int mcp251x_stop(struct net_device *net)
+ {
+ struct mcp251x_priv *priv = netdev_priv(net);
+ struct spi_device *spi = priv->spi;
+- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
++ struct mcp251x_platform_data *pdata = priv->pdata;
+
+ close_candev(net);
+
+@@ -847,13 +863,13 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
+ /* Update can state */
+ if (eflag & EFLG_TXBO) {
+
+- netdev_err(net, "err: bus off\n");
++ netdev_err(net, "err: bus off\n");
+
+ new_state = CAN_STATE_BUS_OFF;
+ can_id |= CAN_ERR_BUSOFF;
+ } else if (eflag & EFLG_TXEP) {
+
+- netdev_err(net, "err: txep\n");
++ netdev_err(net, "err: txep\n");
+
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ can_id |= CAN_ERR_CRTL;
+@@ -861,21 +877,21 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
+
+ } else if (eflag & EFLG_RXEP) {
+
+- netdev_err(net, "err: rxep\n");
++ netdev_err(net, "err: rxep\n");
+
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ can_id |= CAN_ERR_CRTL;
+ data1 |= CAN_ERR_CRTL_RX_PASSIVE;
+ } else if (eflag & EFLG_TXWAR) {
+
+- netdev_err(net, "err: txwar\n");
++ netdev_err(net, "err: txwar\n");
+
+ new_state = CAN_STATE_ERROR_WARNING;
+ can_id |= CAN_ERR_CRTL;
+ data1 |= CAN_ERR_CRTL_TX_WARNING;
+ } else if (eflag & EFLG_RXWAR) {
+
+- netdev_err(net, "err: rxwar\n");
++ netdev_err(net, "err: rxwar\n");
+
+ new_state = CAN_STATE_ERROR_WARNING;
+ can_id |= CAN_ERR_CRTL;
+@@ -948,8 +964,8 @@ static int mcp251x_open(struct net_device *net)
+ {
+ struct mcp251x_priv *priv = netdev_priv(net);
+ struct spi_device *spi = priv->spi;
+- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+- unsigned long flags;
++ struct mcp251x_platform_data *pdata = priv->pdata;
++ unsigned long flags = 0;
+ int ret;
+
+ ret = open_candev(net);
+@@ -966,14 +982,13 @@ static int mcp251x_open(struct net_device *net)
+ priv->tx_skb = NULL;
+ priv->tx_len = 0;
+
+- flags = IRQF_ONESHOT;
+ if (pdata->irq_flags)
+ flags |= pdata->irq_flags;
+ else
+ flags |= IRQF_TRIGGER_FALLING;
+
+ ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
+- flags, DEVICE_NAME, priv);
++ IRQF_ONESHOT | flags, dev_name(&net->dev), priv);
+ if (ret) {
+ netdev_err(net, "failed to acquire irq %d\n", spi->irq);
+ if (pdata->transceiver_enable)
+@@ -1014,21 +1029,79 @@ static const struct net_device_ops mcp251x_netdev_ops = {
+ .ndo_start_xmit = mcp251x_hard_start_xmit,
+ };
+
++static struct mcp251x_platform_data *
++mcp251x_platform_data_dt_get(struct device *dev)
++{
++ struct device_node *np = dev->of_node;
++ struct mcp251x_platform_data *pd;
++
++ u32 tmp;
++ int err, gpio;
++
++ dev_dbg(dev, "reading device tree\n");
++
++ if (!np) {
++ dev_err(dev, "no device tree node defined\n");
++ return NULL;
++ }
++
++ pd = devm_kzalloc(dev, sizeof(struct mcp251x_platform_data), GFP_KERNEL);
++ if (!pd) {
++ dev_err(dev, "cannot allocate platform data memory\n");
++ return NULL;
++ }
++
++ of_property_read_u32(np, "mcp251x,oscillator-frequency", &tmp);
++ pd->oscillator_frequency = tmp;
++
++ pd->stay_awake = of_property_read_bool(np, "mcp251x,stay-awake");
++ pd->enable_clkout = of_property_read_bool(np, "mcp251x,enable-clkout");
++
++ gpio = of_get_named_gpio(np, "mcp251x,irq-gpios", 0);
++ if (gpio_is_valid(gpio)) {
++ err = devm_gpio_request_one(dev, gpio, GPIOF_DIR_IN, "mcp251x-irq");
++ if (err) {
++ dev_err(dev, "cannot request gpio %d\n", gpio);
++ return NULL;
++ }
++ } else {
++ dev_warn(dev, "mcp251x,irq-gpios missing or invalid\n");
++ }
++
++ return pd;
++}
++
+ static int mcp251x_can_probe(struct spi_device *spi)
+ {
+ struct net_device *net;
+ struct mcp251x_priv *priv;
+ struct mcp251x_platform_data *pdata = spi->dev.platform_data;
++ struct pinctrl *pinctrl;
+ int ret = -ENODEV;
+
+- if (!pdata)
++ dev_dbg(&spi->dev, "probing\n");
++
++ if (!pdata && IS_ENABLED(CONFIG_OF))
++ pdata = mcp251x_platform_data_dt_get(&spi->dev);
++
++ if (!pdata) {
+ /* Platform data is required for osc freq */
++ dev_err(&spi->dev, "missing platform data\n");
+ goto error_out;
++ }
++
++ dev_info(&spi->dev, "mode %d, irq %d, awake %d, clkout %d, oscillator freq %ld\n",
++ spi->mode, spi->irq, pdata->stay_awake, pdata->enable_clkout, pdata->oscillator_frequency);
++
++ pinctrl = devm_pinctrl_get_select_default(&spi->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&spi->dev, "pinctrl pins are not configured from the driver");
+
+ /* Allocate can/net device */
+ net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
+ if (!net) {
+ ret = -ENOMEM;
++ dev_err(&spi->dev, "alloc_candev failed\n");
+ goto error_alloc;
+ }
+
+@@ -1036,16 +1109,22 @@ static int mcp251x_can_probe(struct spi_device *spi)
+ net->flags |= IFF_ECHO;
+
+ priv = netdev_priv(net);
+- priv->can.bittiming_const = &mcp251x_bittiming_const;
++
++ priv->net = net;
++ priv->spi = spi;
++ priv->pdata = pdata;
++
++ priv->model = spi_get_device_id(spi)->driver_data;
++
+ priv->can.do_set_mode = mcp251x_do_set_mode;
+ priv->can.clock.freq = pdata->oscillator_frequency / 2;
++ priv->can.bittiming_const = &mcp251x_bittiming_const;
++
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
+ CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
+- priv->model = spi_get_device_id(spi)->driver_data;
+- priv->net = net;
++
+ dev_set_drvdata(&spi->dev, priv);
+
+- priv->spi = spi;
+ mutex_init(&priv->mcp_lock);
+
+ /* If requested, allocate DMA buffers */
+@@ -1095,13 +1174,13 @@ static int mcp251x_can_probe(struct spi_device *spi)
+ SET_NETDEV_DEV(net, &spi->dev);
+
+ /* Configure the SPI bus */
+- spi->mode = SPI_MODE_0;
++ //spi->mode = SPI_MODE_0;
+ spi->bits_per_word = 8;
+ spi_setup(spi);
+
+ /* Here is OK to not lock the MCP, no one knows about it yet */
+ if (!mcp251x_hw_probe(spi)) {
+- dev_info(&spi->dev, "Probe failed\n");
++ dev_info(&spi->dev, "hw probe failed\n");
+ goto error_probe;
+ }
+ mcp251x_hw_sleep(spi);
+@@ -1135,8 +1214,8 @@ error_out:
+
+ static int mcp251x_can_remove(struct spi_device *spi)
+ {
+- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
++ struct mcp251x_platform_data *pdata = priv->pdata;
+ struct net_device *net = priv->net;
+
+ unregister_candev(net);
+@@ -1159,8 +1238,8 @@ static int mcp251x_can_remove(struct spi_device *spi)
+ #ifdef CONFIG_PM
+ static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
+ {
+- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
++ struct mcp251x_platform_data *pdata = priv->pdata;
+ struct net_device *net = priv->net;
+
+ priv->force_quit = 1;
+@@ -1190,8 +1269,8 @@ static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
+
+ static int mcp251x_can_resume(struct spi_device *spi)
+ {
+- struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
++ struct mcp251x_platform_data *pdata = priv->pdata;
+
+ if (priv->after_suspend & AFTER_SUSPEND_POWER) {
+ pdata->power_enable(1);
+diff --git a/include/linux/can/platform/mcp251x.h b/include/linux/can/platform/mcp251x.h
+index 089fe43..c017922 100644
+--- a/include/linux/can/platform/mcp251x.h
++++ b/include/linux/can/platform/mcp251x.h
+@@ -13,6 +13,8 @@
+ * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
+ * @oscillator_frequency: - oscillator frequency in Hz
+ * @irq_flags: - IRQF configuration flags
++ * @stay_awake: - avoid entering sleep mode
++ * @enable_clkout: - enable clock output
+ * @board_specific_setup: - called before probing the chip (power,reset)
+ * @transceiver_enable: - called to power on/off the transceiver
+ * @power_enable: - called to power on/off the mcp *and* the
+@@ -26,6 +28,8 @@
+ struct mcp251x_platform_data {
+ unsigned long oscillator_frequency;
+ unsigned long irq_flags;
++ bool stay_awake;
++ bool enable_clkout;
+ int (*board_specific_setup)(struct spi_device *spi);
+ int (*transceiver_enable)(int enable);
+ int (*power_enable) (int enable);
diff --git a/patches/linux-3.8.13/0226-am33xx-Add-clock-for-the-lcdc-DRM-driver.patch b/patches/linux-3.8.13/0226-am33xx-Add-clock-for-the-lcdc-DRM-driver.patch
new file mode 100644
index 0000000..07c4c02
--- /dev/null
+++ b/patches/linux-3.8.13/0226-am33xx-Add-clock-for-the-lcdc-DRM-driver.patch
@@ -0,0 +1,23 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 8 Jan 2013 20:01:09 +0200
+Subject: [PATCH] am33xx: Add clock for the lcdc DRM driver
+
+Update the clocks with the lcdc DRM's driver definition.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/cclock33xx_data.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
+index 743dce4..7e29317 100644
+--- a/arch/arm/mach-omap2/cclock33xx_data.c
++++ b/arch/arm/mach-omap2/cclock33xx_data.c
+@@ -952,6 +952,7 @@ static struct omap_clk am33xx_clks[] = {
+ CLK("48300200.ehrpwm", "tbclk", &ehrpwm0_tbclk, CK_AM33XX),
+ CLK("48302200.ehrpwm", "tbclk", &ehrpwm1_tbclk, CK_AM33XX),
+ CLK("48304200.ehrpwm", "tbclk", &ehrpwm2_tbclk, CK_AM33XX),
++ CLK("4830e000.fb", "fck", &lcd_gclk, CK_AM33XX),
+ };
+
+
diff --git a/patches/linux-3.8.13/0227-drm-small-fix-in-drm_send_vblank_event.patch b/patches/linux-3.8.13/0227-drm-small-fix-in-drm_send_vblank_event.patch
new file mode 100644
index 0000000..5da4786
--- /dev/null
+++ b/patches/linux-3.8.13/0227-drm-small-fix-in-drm_send_vblank_event.patch
@@ -0,0 +1,25 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Mon, 10 Dec 2012 10:49:46 -0600
+Subject: [PATCH] drm: small fix in drm_send_vblank_event()
+
+Initialize e->pipe.. some drivers set this themselves, others do not.
+Setting it in drm_send_vblank_event() should help ensure more consistent
+behavior with the different drivers.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/drm_irq.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
+index 19c01ca..9bb83a5 100644
+--- a/drivers/gpu/drm/drm_irq.c
++++ b/drivers/gpu/drm/drm_irq.c
+@@ -863,6 +863,7 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc,
+
+ now = get_drm_timestamp();
+ }
++ e->pipe = crtc;
+ send_vblank_event(dev, e, seq, &now);
+ }
+ EXPORT_SYMBOL(drm_send_vblank_event);
diff --git a/patches/linux-3.8.13/0228-drm-cma-add-debugfs-helpers.patch b/patches/linux-3.8.13/0228-drm-cma-add-debugfs-helpers.patch
new file mode 100644
index 0000000..4b2e193
--- /dev/null
+++ b/patches/linux-3.8.13/0228-drm-cma-add-debugfs-helpers.patch
@@ -0,0 +1,144 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Mon, 10 Dec 2012 10:46:43 -0600
+Subject: [PATCH] drm/cma: add debugfs helpers
+
+Add helper to display fb's which can be used directly in drm_info_list:
+
+static struct drm_info_list foo_debugfs_list[] = {
+ ...
+ { "fb", drm_fb_cma_debugfs_show, 0 },
+};
+
+to display information about CMA fb objects, as well as a
+drm_gem_cma_describe() which can be used if the driver bothers to keep
+a list of CMA GEM objects.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/drm_fb_cma_helper.c | 53 ++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/drm_gem_cma_helper.c | 21 ++++++++++++++
+ include/drm/drm_fb_cma_helper.h | 5 ++++
+ include/drm/drm_gem_cma_helper.h | 4 +++
+ 4 files changed, 83 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
+index fd9d0af..18866ee 100644
+--- a/drivers/gpu/drm/drm_fb_cma_helper.c
++++ b/drivers/gpu/drm/drm_fb_cma_helper.c
+@@ -180,6 +180,59 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
+ }
+ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
+
++#ifdef CONFIG_DEBUG_FS
++/**
++ * drm_fb_cma_describe() - Helper to dump information about a single
++ * CMA framebuffer object
++ */
++void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
++{
++ struct drm_fb_cma *fb_cma = to_fb_cma(fb);
++ int i, n = drm_format_num_planes(fb->pixel_format);
++
++ seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
++ (char *)&fb->pixel_format);
++
++ for (i = 0; i < n; i++) {
++ seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
++ i, fb->offsets[i], fb->pitches[i]);
++ drm_gem_cma_describe(fb_cma->obj[i], m);
++ }
++}
++EXPORT_SYMBOL_GPL(drm_fb_cma_describe);
++
++/**
++ * drm_fb_cma_debugfs_show() - Helper to list CMA framebuffer objects
++ * in debugfs.
++ */
++int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg)
++{
++ struct drm_info_node *node = (struct drm_info_node *) m->private;
++ struct drm_device *dev = node->minor->dev;
++ struct drm_framebuffer *fb;
++ int ret;
++
++ ret = mutex_lock_interruptible(&dev->mode_config.mutex);
++ if (ret)
++ return ret;
++
++ ret = mutex_lock_interruptible(&dev->struct_mutex);
++ if (ret) {
++ mutex_unlock(&dev->mode_config.mutex);
++ return ret;
++ }
++
++ list_for_each_entry(fb, &dev->mode_config.fb_list, head)
++ drm_fb_cma_describe(fb, m);
++
++ mutex_unlock(&dev->struct_mutex);
++ mutex_unlock(&dev->mode_config.mutex);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
++#endif
++
+ static struct fb_ops drm_fbdev_cma_ops = {
+ .owner = THIS_MODULE,
+ .fb_fillrect = sys_fillrect,
+diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
+index 1aa8fee..0a7e011 100644
+--- a/drivers/gpu/drm/drm_gem_cma_helper.c
++++ b/drivers/gpu/drm/drm_gem_cma_helper.c
+@@ -249,3 +249,24 @@ int drm_gem_cma_dumb_destroy(struct drm_file *file_priv,
+ return drm_gem_handle_delete(file_priv, handle);
+ }
+ EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy);
++
++#ifdef CONFIG_DEBUG_FS
++void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m)
++{
++ struct drm_gem_object *obj = &cma_obj->base;
++ struct drm_device *dev = obj->dev;
++ uint64_t off = 0;
++
++ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
++
++ if (obj->map_list.map)
++ off = (uint64_t)obj->map_list.hash.key;
++
++ seq_printf(m, "%2d (%2d) %08llx %08Zx %p %d",
++ obj->name, obj->refcount.refcount.counter,
++ off, cma_obj->paddr, cma_obj->vaddr, obj->size);
++
++ seq_printf(m, "\n");
++}
++EXPORT_SYMBOL_GPL(drm_gem_cma_describe);
++#endif
+diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
+index 76c7098..4a3fc24 100644
+--- a/include/drm/drm_fb_cma_helper.h
++++ b/include/drm/drm_fb_cma_helper.h
+@@ -23,5 +23,10 @@ struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
+ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
+ unsigned int plane);
+
++#ifdef CONFIG_DEBUG_FS
++void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m);
++int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg);
++#endif
++
+ #endif
+
+diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
+index f0f6b1a..63397ce 100644
+--- a/include/drm/drm_gem_cma_helper.h
++++ b/include/drm/drm_gem_cma_helper.h
+@@ -41,4 +41,8 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
+
+ extern const struct vm_operations_struct drm_gem_cma_vm_ops;
+
++#ifdef CONFIG_DEBUG_FS
++void drm_gem_cma_describe(struct drm_gem_cma_object *obj, struct seq_file *m);
++#endif
++
+ #endif /* __DRM_GEM_CMA_HELPER_H__ */
diff --git a/patches/linux-3.8.13/0229-drm-i2c-encoder-helper-wrappers.patch b/patches/linux-3.8.13/0229-drm-i2c-encoder-helper-wrappers.patch
new file mode 100644
index 0000000..20b4185
--- /dev/null
+++ b/patches/linux-3.8.13/0229-drm-i2c-encoder-helper-wrappers.patch
@@ -0,0 +1,114 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Tue, 8 Jan 2013 17:50:48 -0600
+Subject: [PATCH] drm: i2c encoder helper wrappers
+
+Simplify life for drivers using an encoder-slave, so that they can make
+their drm_encoder_helper_funcs const, rather than needing to dynamically
+allocate and populate them.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/drm_encoder_slave.c | 63 +++++++++++++++++++++++++++++++++++
+ include/drm/drm_encoder_slave.h | 20 +++++++++++
+ 2 files changed, 83 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c
+index 63e7334..48c52f7 100644
+--- a/drivers/gpu/drm/drm_encoder_slave.c
++++ b/drivers/gpu/drm/drm_encoder_slave.c
+@@ -123,3 +123,66 @@ void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
+ module_put(module);
+ }
+ EXPORT_SYMBOL(drm_i2c_encoder_destroy);
++
++/*
++ * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
++ */
++
++static inline struct drm_encoder_slave_funcs *
++get_slave_funcs(struct drm_encoder *enc)
++{
++ return to_encoder_slave(enc)->slave_funcs;
++}
++
++void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode)
++{
++ get_slave_funcs(encoder)->dpms(encoder, mode);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_dpms);
++
++bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
++ const struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup);
++
++void drm_i2c_encoder_prepare(struct drm_encoder *encoder)
++{
++ drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_prepare);
++
++void drm_i2c_encoder_commit(struct drm_encoder *encoder)
++{
++ drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_commit);
++
++void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
++ struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_mode_set);
++
++enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
++ struct drm_connector *connector)
++{
++ return get_slave_funcs(encoder)->detect(encoder, connector);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_detect);
++
++void drm_i2c_encoder_save(struct drm_encoder *encoder)
++{
++ get_slave_funcs(encoder)->save(encoder);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_save);
++
++void drm_i2c_encoder_restore(struct drm_encoder *encoder)
++{
++ get_slave_funcs(encoder)->restore(encoder);
++}
++EXPORT_SYMBOL(drm_i2c_encoder_restore);
+diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
+index b0c11a7..8b9cc36 100644
+--- a/include/drm/drm_encoder_slave.h
++++ b/include/drm/drm_encoder_slave.h
+@@ -159,4 +159,24 @@ static inline void drm_i2c_encoder_unregister(struct drm_i2c_encoder_driver *dri
+
+ void drm_i2c_encoder_destroy(struct drm_encoder *encoder);
+
++
++/*
++ * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
++ */
++
++void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode);
++bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
++ const struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode);
++void drm_i2c_encoder_prepare(struct drm_encoder *encoder);
++void drm_i2c_encoder_commit(struct drm_encoder *encoder);
++void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
++ struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode);
++enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
++ struct drm_connector *connector);
++void drm_i2c_encoder_save(struct drm_encoder *encoder);
++void drm_i2c_encoder_restore(struct drm_encoder *encoder);
++
++
+ #endif
diff --git a/patches/linux-3.8.13/0230-drm-nouveau-use-i2c-encoder-helper-wrappers.patch b/patches/linux-3.8.13/0230-drm-nouveau-use-i2c-encoder-helper-wrappers.patch
new file mode 100644
index 0000000..3947e61
--- /dev/null
+++ b/patches/linux-3.8.13/0230-drm-nouveau-use-i2c-encoder-helper-wrappers.patch
@@ -0,0 +1,90 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Tue, 8 Jan 2013 19:19:13 -0600
+Subject: [PATCH] drm/nouveau: use i2c encoder helper wrappers
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/nouveau/nv04_tv.c | 39 +++++++++++++------------------------
+ 1 file changed, 13 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
+index 62e826a..4a69ccd 100644
+--- a/drivers/gpu/drm/nouveau/nv04_tv.c
++++ b/drivers/gpu/drm/nouveau/nv04_tv.c
+@@ -184,14 +184,23 @@ static const struct drm_encoder_funcs nv04_tv_funcs = {
+ .destroy = nv04_tv_destroy,
+ };
+
++static const struct drm_encoder_helper_funcs nv04_tv_helper_funcs = {
++ .dpms = nv04_tv_dpms,
++ .save = drm_i2c_encoder_save,
++ .restore = drm_i2c_encoder_restore,
++ .mode_fixup = drm_i2c_encoder_mode_fixup,
++ .prepare = nv04_tv_prepare,
++ .commit = nv04_tv_commit,
++ .mode_set = nv04_tv_mode_set,
++ .detect = drm_i2c_encoder_detect,
++};
++
+ int
+ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
+ {
+ struct nouveau_encoder *nv_encoder;
+ struct drm_encoder *encoder;
+ struct drm_device *dev = connector->dev;
+- struct drm_encoder_helper_funcs *hfuncs;
+- struct drm_encoder_slave_funcs *sfuncs;
+ struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
+ struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index);
+@@ -207,17 +216,11 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
+ if (!nv_encoder)
+ return -ENOMEM;
+
+- hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL);
+- if (!hfuncs) {
+- ret = -ENOMEM;
+- goto fail_free;
+- }
+-
+ /* Initialize the common members */
+ encoder = to_drm_encoder(nv_encoder);
+
+ drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
+- drm_encoder_helper_add(encoder, hfuncs);
++ drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs);
+
+ encoder->possible_crtcs = entry->heads;
+ encoder->possible_clones = 0;
+@@ -230,30 +233,14 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
+ if (ret < 0)
+ goto fail_cleanup;
+
+- /* Fill the function pointers */
+- sfuncs = get_slave_funcs(encoder);
+-
+- *hfuncs = (struct drm_encoder_helper_funcs) {
+- .dpms = nv04_tv_dpms,
+- .save = sfuncs->save,
+- .restore = sfuncs->restore,
+- .mode_fixup = sfuncs->mode_fixup,
+- .prepare = nv04_tv_prepare,
+- .commit = nv04_tv_commit,
+- .mode_set = nv04_tv_mode_set,
+- .detect = sfuncs->detect,
+- };
+-
+ /* Attach it to the specified connector. */
+- sfuncs->create_resources(encoder, connector);
++ get_slave_funcs(encoder)->create_resources(encoder, connector);
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ return 0;
+
+ fail_cleanup:
+ drm_encoder_cleanup(encoder);
+- kfree(hfuncs);
+-fail_free:
+ kfree(nv_encoder);
+ return ret;
+ }
diff --git a/patches/linux-3.8.13/0231-drm-i2c-give-i2c-it-s-own-Kconfig.patch b/patches/linux-3.8.13/0231-drm-i2c-give-i2c-it-s-own-Kconfig.patch
new file mode 100644
index 0000000..0bcc67a
--- /dev/null
+++ b/patches/linux-3.8.13/0231-drm-i2c-give-i2c-it-s-own-Kconfig.patch
@@ -0,0 +1,88 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Thu, 24 Jan 2013 15:39:19 -0600
+Subject: [PATCH] drm/i2c: give i2c it's own Kconfig
+
+Move this out of nouveau directory. As we start to add more encoder
+slaves used by other drivers, it makes sense to put the Kconfig bits in
+one place.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/Kconfig | 2 ++
+ drivers/gpu/drm/i2c/Kconfig | 22 ++++++++++++++++++++++
+ drivers/gpu/drm/nouveau/Kconfig | 23 -----------------------
+ 3 files changed, 24 insertions(+), 23 deletions(-)
+ create mode 100644 drivers/gpu/drm/i2c/Kconfig
+
+diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
+index 983201b..99b09e1 100644
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -69,6 +69,8 @@ config DRM_KMS_CMA_HELPER
+ help
+ Choose this if you need the KMS CMA helper functions
+
++source "drivers/gpu/drm/i2c/Kconfig"
++
+ config DRM_TDFX
+ tristate "3dfx Banshee/Voodoo3+"
+ depends on DRM && PCI
+diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
+new file mode 100644
+index 0000000..1611836
+--- /dev/null
++++ b/drivers/gpu/drm/i2c/Kconfig
+@@ -0,0 +1,22 @@
++menu "I2C encoder or helper chips"
++ depends on DRM && DRM_KMS_HELPER && I2C
++
++config DRM_I2C_CH7006
++ tristate "Chrontel ch7006 TV encoder"
++ default m if DRM_NOUVEAU
++ help
++ Support for Chrontel ch7006 and similar TV encoders, found
++ on some nVidia video cards.
++
++ This driver is currently only useful if you're also using
++ the nouveau driver.
++
++config DRM_I2C_SIL164
++ tristate "Silicon Image sil164 TMDS transmitter"
++ default m if DRM_NOUVEAU
++ help
++ Support for sil164 and similar single-link (or dual-link
++ when used in pairs) TMDS transmitters, used in some nVidia
++ video cards.
++
++endmenu
+diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
+index 8a55bee..47ccc1a 100644
+--- a/drivers/gpu/drm/nouveau/Kconfig
++++ b/drivers/gpu/drm/nouveau/Kconfig
+@@ -52,26 +52,3 @@ config DRM_NOUVEAU_BACKLIGHT
+ help
+ Say Y here if you want to control the backlight of your display
+ (e.g. a laptop panel).
+-
+-menu "I2C encoder or helper chips"
+- depends on DRM && DRM_KMS_HELPER && I2C
+-
+-config DRM_I2C_CH7006
+- tristate "Chrontel ch7006 TV encoder"
+- default m if DRM_NOUVEAU
+- help
+- Support for Chrontel ch7006 and similar TV encoders, found
+- on some nVidia video cards.
+-
+- This driver is currently only useful if you're also using
+- the nouveau driver.
+-
+-config DRM_I2C_SIL164
+- tristate "Silicon Image sil164 TMDS transmitter"
+- default m if DRM_NOUVEAU
+- help
+- Support for sil164 and similar single-link (or dual-link
+- when used in pairs) TMDS transmitters, used in some nVidia
+- video cards.
+-
+-endmenu
diff --git a/patches/linux-3.8.13/0232-drm-tilcdc-add-TI-LCD-Controller-DRM-driver-v4.patch b/patches/linux-3.8.13/0232-drm-tilcdc-add-TI-LCD-Controller-DRM-driver-v4.patch
new file mode 100644
index 0000000..95c1426
--- /dev/null
+++ b/patches/linux-3.8.13/0232-drm-tilcdc-add-TI-LCD-Controller-DRM-driver-v4.patch
@@ -0,0 +1,2089 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Tue, 8 Jan 2013 15:04:28 -0600
+Subject: [PATCH] drm/tilcdc: add TI LCD Controller DRM driver (v4)
+
+A simple DRM/KMS driver for the TI LCD Controller found in various
+smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the
+CMA helpers. Currently only the TFP410 DVI encoder is supported
+(tested with beaglebone + DVI cape). There are also various LCD
+displays, for which support can be added (as I get hw to test on),
+and an external i2c HDMI encoder found on some boards.
+
+The display controller supports a single CRTC. And the encoder+
+connector are split out into sub-devices. Depending on which LCD
+or external encoder is actually present, the appropriate output
+module(s) will be loaded.
+
+v1: original
+v2: fix fb refcnting and few other cleanups
+v3: get +/- vsync/hsync from timings rather than panel-info, add
+ option DT max-bandwidth field so driver doesn't attempt to
+ pick a display mode with too high memory bandwidth, and other
+ small cleanups
+v4: remove some unneeded stuff from panel-info struct, properly
+ set high bits for hfp/hsw/hbp for rev 2
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/Kconfig | 2 +
+ drivers/gpu/drm/Makefile | 1 +
+ drivers/gpu/drm/tilcdc/Kconfig | 10 +
+ drivers/gpu/drm/tilcdc/Makefile | 8 +
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 602 +++++++++++++++++++++++++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 605 ++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 150 ++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_regs.h | 154 ++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 419 ++++++++++++++++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.h | 26 ++
+ 10 files changed, 1977 insertions(+)
+ create mode 100644 drivers/gpu/drm/tilcdc/Kconfig
+ create mode 100644 drivers/gpu/drm/tilcdc/Makefile
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.c
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_drv.h
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_regs.h
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.h
+
+diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
+index 99b09e1..6c322d6 100644
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -214,3 +214,5 @@ source "drivers/gpu/drm/cirrus/Kconfig"
+ source "drivers/gpu/drm/shmobile/Kconfig"
+
+ source "drivers/gpu/drm/tegra/Kconfig"
++
++source "drivers/gpu/drm/tilcdc/Kconfig"
+diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
+index 6f58c81..3af934d 100644
+--- a/drivers/gpu/drm/Makefile
++++ b/drivers/gpu/drm/Makefile
+@@ -50,4 +50,5 @@ obj-$(CONFIG_DRM_UDL) += udl/
+ obj-$(CONFIG_DRM_AST) += ast/
+ obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
+ obj-$(CONFIG_DRM_TEGRA) += tegra/
++obj-$(CONFIG_DRM_TILCDC) += tilcdc/
+ obj-y += i2c/
+diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
+new file mode 100644
+index 0000000..ee9b592
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/Kconfig
+@@ -0,0 +1,10 @@
++config DRM_TILCDC
++ tristate "DRM Support for TI LCDC Display Controller"
++ depends on DRM && OF
++ select DRM_KMS_HELPER
++ select DRM_KMS_CMA_HELPER
++ select DRM_GEM_CMA_HELPER
++ help
++ Choose this option if you have an TI SoC with LCDC display
++ controller, for example AM33xx in beagle-bone, DA8xx, or
++ OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver.
+diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile
+new file mode 100644
+index 0000000..1359cc2
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/Makefile
+@@ -0,0 +1,8 @@
++ccflags-y := -Iinclude/drm -Werror
++
++tilcdc-y := \
++ tilcdc_crtc.o \
++ tilcdc_tfp410.o \
++ tilcdc_drv.o
++
++obj-$(CONFIG_DRM_TILCDC) += tilcdc.o
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+new file mode 100644
+index 0000000..5dd3c7d
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -0,0 +1,602 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/kfifo.h>
++
++#include "tilcdc_drv.h"
++#include "tilcdc_regs.h"
++
++struct tilcdc_crtc {
++ struct drm_crtc base;
++
++ const struct tilcdc_panel_info *info;
++ uint32_t dirty;
++ dma_addr_t start, end;
++ struct drm_pending_vblank_event *event;
++ int dpms;
++ wait_queue_head_t frame_done_wq;
++ bool frame_done;
++
++ /* fb currently set to scanout 0/1: */
++ struct drm_framebuffer *scanout[2];
++
++ /* for deferred fb unref's: */
++ DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *);
++ struct work_struct work;
++};
++#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
++
++static void unref_worker(struct work_struct *work)
++{
++ struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work);
++ struct drm_device *dev = tilcdc_crtc->base.dev;
++ struct drm_framebuffer *fb;
++
++ mutex_lock(&dev->mode_config.mutex);
++ while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb))
++ drm_framebuffer_unreference(fb);
++ mutex_unlock(&dev->mode_config.mutex);
++}
++
++static void set_scanout(struct drm_crtc *crtc, int n)
++{
++ static const uint32_t base_reg[] = {
++ LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG,
++ };
++ static const uint32_t ceil_reg[] = {
++ LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG,
++ };
++ static const uint32_t stat[] = {
++ LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1,
++ };
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++
++ pm_runtime_get_sync(dev->dev);
++ tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
++ tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
++ if (tilcdc_crtc->scanout[n]) {
++ if (kfifo_put(&tilcdc_crtc->unref_fifo,
++ (const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) {
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ queue_work(priv->wq, &tilcdc_crtc->work);
++ } else {
++ dev_err(dev->dev, "unref fifo full!\n");
++ drm_framebuffer_unreference(tilcdc_crtc->scanout[n]);
++ }
++ }
++ tilcdc_crtc->scanout[n] = crtc->fb;
++ drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
++ tilcdc_crtc->dirty &= ~stat[n];
++ pm_runtime_put_sync(dev->dev);
++}
++
++static void update_scanout(struct drm_crtc *crtc)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct drm_framebuffer *fb = crtc->fb;
++ struct drm_gem_cma_object *gem;
++ unsigned int depth, bpp;
++
++ drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
++ gem = drm_fb_cma_get_gem_obj(fb, 0);
++
++ tilcdc_crtc->start = gem->paddr + fb->offsets[0] +
++ (crtc->y * fb->pitches[0]) + (crtc->x * bpp/8);
++
++ tilcdc_crtc->end = tilcdc_crtc->start +
++ (crtc->mode.vdisplay * fb->pitches[0]);
++
++ if (tilcdc_crtc->dpms == DRM_MODE_DPMS_ON) {
++ /* already enabled, so just mark the frames that need
++ * updating and they will be updated on vblank:
++ */
++ tilcdc_crtc->dirty |= LCDC_END_OF_FRAME0 | LCDC_END_OF_FRAME1;
++ drm_vblank_get(dev, 0);
++ } else {
++ /* not enabled yet, so update registers immediately: */
++ set_scanout(crtc, 0);
++ set_scanout(crtc, 1);
++ }
++}
++
++static void start(struct drm_crtc *crtc)
++{
++ struct drm_device *dev = crtc->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++
++ if (priv->rev == 2) {
++ tilcdc_set(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
++ msleep(1);
++ tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
++ msleep(1);
++ }
++
++ tilcdc_set(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
++ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY));
++ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
++}
++
++static void stop(struct drm_crtc *crtc)
++{
++ struct drm_device *dev = crtc->dev;
++
++ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
++}
++
++static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++
++ WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
++
++ drm_crtc_cleanup(crtc);
++ WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo));
++ kfifo_free(&tilcdc_crtc->unref_fifo);
++ kfree(tilcdc_crtc);
++}
++
++static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
++ struct drm_framebuffer *fb,
++ struct drm_pending_vblank_event *event)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++
++ if (tilcdc_crtc->event) {
++ dev_err(dev->dev, "already pending page flip!\n");
++ return -EBUSY;
++ }
++
++ crtc->fb = fb;
++ tilcdc_crtc->event = event;
++ update_scanout(crtc);
++
++ return 0;
++}
++
++static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++
++ /* we really only care about on or off: */
++ if (mode != DRM_MODE_DPMS_ON)
++ mode = DRM_MODE_DPMS_OFF;
++
++ if (tilcdc_crtc->dpms == mode)
++ return;
++
++ tilcdc_crtc->dpms = mode;
++
++ pm_runtime_get_sync(dev->dev);
++
++ if (mode == DRM_MODE_DPMS_ON) {
++ pm_runtime_forbid(dev->dev);
++ start(crtc);
++ } else {
++ tilcdc_crtc->frame_done = false;
++ stop(crtc);
++
++ /* if necessary wait for framedone irq which will still come
++ * before putting things to sleep..
++ */
++ if (priv->rev == 2) {
++ int ret = wait_event_timeout(
++ tilcdc_crtc->frame_done_wq,
++ tilcdc_crtc->frame_done,
++ msecs_to_jiffies(50));
++ if (ret == 0)
++ dev_err(dev->dev, "timeout waiting for framedone\n");
++ }
++ pm_runtime_allow(dev->dev);
++ }
++
++ pm_runtime_put_sync(dev->dev);
++}
++
++static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
++ const struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ return true;
++}
++
++static void tilcdc_crtc_prepare(struct drm_crtc *crtc)
++{
++ tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
++}
++
++static void tilcdc_crtc_commit(struct drm_crtc *crtc)
++{
++ tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
++}
++
++static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
++ struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode,
++ int x, int y,
++ struct drm_framebuffer *old_fb)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ const struct tilcdc_panel_info *info = tilcdc_crtc->info;
++ uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
++ int ret;
++
++ ret = tilcdc_crtc_mode_valid(crtc, mode);
++ if (WARN_ON(ret))
++ return ret;
++
++ if (WARN_ON(!info))
++ return -EINVAL;
++
++ pm_runtime_get_sync(dev->dev);
++
++ /* Configure the Burst Size and fifo threshold of DMA: */
++ reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
++ switch (info->dma_burst_sz) {
++ case 1:
++ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1);
++ break;
++ case 2:
++ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2);
++ break;
++ case 4:
++ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4);
++ break;
++ case 8:
++ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8);
++ break;
++ case 16:
++ reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16);
++ break;
++ default:
++ return -EINVAL;
++ }
++ reg |= (info->fifo_th << 8);
++ tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg);
++
++ /* Configure timings: */
++ hbp = mode->htotal - mode->hsync_end;
++ hfp = mode->hsync_start - mode->hdisplay;
++ hsw = mode->hsync_end - mode->hsync_start;
++ vbp = mode->vtotal - mode->vsync_end;
++ vfp = mode->vsync_start - mode->vdisplay;
++ vsw = mode->vsync_end - mode->vsync_start;
++
++ DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u",
++ mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);
++
++ /* Configure the AC Bias Period and Number of Transitions per Interrupt: */
++ reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
++ reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
++ LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
++ if (priv->rev == 2) {
++ reg |= (hfp & 0x300) >> 8;
++ reg |= (hbp & 0x300) >> 4;
++ reg |= (hsw & 0x3c0) << 21;
++ }
++ tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
++
++ reg = (((mode->hdisplay >> 4) - 1) << 4) |
++ ((hbp & 0xff) << 24) |
++ ((hfp & 0xff) << 16) |
++ ((hsw & 0x3f) << 10);
++ if (priv->rev == 2)
++ reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
++ tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
++
++ reg = ((mode->vdisplay - 1) & 0x3ff) |
++ ((vbp & 0xff) << 24) |
++ ((vfp & 0xff) << 16) |
++ ((vsw & 0x3f) << 10);
++ tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
++
++ /* Configure display type: */
++ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
++ ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
++ LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000);
++ reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
++ if (info->tft_alt_mode)
++ reg |= LCDC_TFT_ALT_ENABLE;
++ if (priv->rev == 2) {
++ unsigned int depth, bpp;
++
++ drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp);
++ switch (bpp) {
++ case 16:
++ break;
++ case 32:
++ reg |= LCDC_V2_TFT_24BPP_UNPACK;
++ /* fallthrough */
++ case 24:
++ reg |= LCDC_V2_TFT_24BPP_MODE;
++ break;
++ default:
++ dev_err(dev->dev, "invalid pixel format\n");
++ return -EINVAL;
++ }
++ }
++ reg |= info->fdd < 12;
++ tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg);
++
++ if (info->invert_pxl_clk)
++ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
++ else
++ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
++
++ if (info->sync_ctrl)
++ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
++ else
++ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
++
++ if (info->sync_edge)
++ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
++ else
++ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
++
++ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
++ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
++ else
++ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
++
++ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
++ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
++ else
++ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
++
++ if (info->raster_order)
++ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
++ else
++ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
++
++
++ update_scanout(crtc);
++ tilcdc_crtc_update_clk(crtc);
++
++ pm_runtime_put_sync(dev->dev);
++
++ return 0;
++}
++
++static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
++ struct drm_framebuffer *old_fb)
++{
++ update_scanout(crtc);
++ return 0;
++}
++
++static void tilcdc_crtc_load_lut(struct drm_crtc *crtc)
++{
++}
++
++static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
++ .destroy = tilcdc_crtc_destroy,
++ .set_config = drm_crtc_helper_set_config,
++ .page_flip = tilcdc_crtc_page_flip,
++};
++
++static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
++ .dpms = tilcdc_crtc_dpms,
++ .mode_fixup = tilcdc_crtc_mode_fixup,
++ .prepare = tilcdc_crtc_prepare,
++ .commit = tilcdc_crtc_commit,
++ .mode_set = tilcdc_crtc_mode_set,
++ .mode_set_base = tilcdc_crtc_mode_set_base,
++ .load_lut = tilcdc_crtc_load_lut,
++};
++
++int tilcdc_crtc_max_width(struct drm_crtc *crtc)
++{
++ struct drm_device *dev = crtc->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ int max_width = 0;
++
++ if (priv->rev == 1)
++ max_width = 1024;
++ else if (priv->rev == 2)
++ max_width = 2048;
++
++ return max_width;
++}
++
++int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
++{
++ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
++ unsigned int bandwidth;
++
++ if (mode->hdisplay > tilcdc_crtc_max_width(crtc))
++ return MODE_VIRTUAL_X;
++
++ /* width must be multiple of 16 */
++ if (mode->hdisplay & 0xf)
++ return MODE_VIRTUAL_X;
++
++ if (mode->vdisplay > 2048)
++ return MODE_VIRTUAL_Y;
++
++ /* filter out modes that would require too much memory bandwidth: */
++ bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode);
++ if (bandwidth > priv->max_bandwidth)
++ return MODE_BAD;
++
++ return MODE_OK;
++}
++
++void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
++ const struct tilcdc_panel_info *info)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ tilcdc_crtc->info = info;
++}
++
++void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ int dpms = tilcdc_crtc->dpms;
++ unsigned int lcd_clk, div;
++ int ret;
++
++ pm_runtime_get_sync(dev->dev);
++
++ if (dpms == DRM_MODE_DPMS_ON)
++ tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
++
++ /* in raster mode, minimum divisor is 2: */
++ ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2);
++ if (ret) {
++ dev_err(dev->dev, "failed to set display clock rate to: %d\n",
++ crtc->mode.clock);
++ goto out;
++ }
++
++ lcd_clk = clk_get_rate(priv->clk);
++ div = lcd_clk / (crtc->mode.clock * 1000);
++
++ DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode.clock, div);
++ DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk));
++
++ /* Configure the LCD clock divisor. */
++ tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) |
++ LCDC_RASTER_MODE);
++
++ if (priv->rev == 2)
++ tilcdc_set(dev, LCDC_CLK_ENABLE_REG,
++ LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN |
++ LCDC_V2_CORE_CLK_EN);
++
++ if (dpms == DRM_MODE_DPMS_ON)
++ tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
++
++out:
++ pm_runtime_put_sync(dev->dev);
++}
++
++irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_device *dev = crtc->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ uint32_t stat = tilcdc_read_irqstatus(dev);
++
++ if ((stat & LCDC_SYNC_LOST) && (stat & LCDC_FIFO_UNDERFLOW)) {
++ stop(crtc);
++ dev_err(dev->dev, "error: %08x\n", stat);
++ tilcdc_clear_irqstatus(dev, stat);
++ start(crtc);
++ } else if (stat & LCDC_PL_LOAD_DONE) {
++ tilcdc_clear_irqstatus(dev, stat);
++ } else {
++ struct drm_pending_vblank_event *event;
++ unsigned long flags;
++ uint32_t dirty = tilcdc_crtc->dirty & stat;
++
++ tilcdc_clear_irqstatus(dev, stat);
++
++ if (dirty & LCDC_END_OF_FRAME0)
++ set_scanout(crtc, 0);
++
++ if (dirty & LCDC_END_OF_FRAME1)
++ set_scanout(crtc, 1);
++
++ drm_handle_vblank(dev, 0);
++
++ spin_lock_irqsave(&dev->event_lock, flags);
++ event = tilcdc_crtc->event;
++ tilcdc_crtc->event = NULL;
++ if (event)
++ drm_send_vblank_event(dev, 0, event);
++ spin_unlock_irqrestore(&dev->event_lock, flags);
++
++ if (dirty && !tilcdc_crtc->dirty)
++ drm_vblank_put(dev, 0);
++ }
++
++ if (priv->rev == 2) {
++ if (stat & LCDC_FRAME_DONE) {
++ tilcdc_crtc->frame_done = true;
++ wake_up(&tilcdc_crtc->frame_done_wq);
++ }
++ tilcdc_write(dev, LCDC_END_OF_INT_IND_REG, 0);
++ }
++
++ return IRQ_HANDLED;
++}
++
++void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
++{
++ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
++ struct drm_pending_vblank_event *event;
++ struct drm_device *dev = crtc->dev;
++ unsigned long flags;
++
++ /* Destroy the pending vertical blanking event associated with the
++ * pending page flip, if any, and disable vertical blanking interrupts.
++ */
++ spin_lock_irqsave(&dev->event_lock, flags);
++ event = tilcdc_crtc->event;
++ if (event && event->base.file_priv == file) {
++ tilcdc_crtc->event = NULL;
++ event->base.destroy(&event->base);
++ drm_vblank_put(dev, 0);
++ }
++ spin_unlock_irqrestore(&dev->event_lock, flags);
++}
++
++struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
++{
++ struct tilcdc_crtc *tilcdc_crtc;
++ struct drm_crtc *crtc;
++ int ret;
++
++ tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL);
++ if (!tilcdc_crtc) {
++ dev_err(dev->dev, "allocation failed\n");
++ return NULL;
++ }
++
++ crtc = &tilcdc_crtc->base;
++
++ tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
++ init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
++
++ ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL);
++ if (ret) {
++ dev_err(dev->dev, "could not allocate unref FIFO\n");
++ goto fail;
++ }
++
++ INIT_WORK(&tilcdc_crtc->work, unref_worker);
++
++ ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
++ if (ret < 0)
++ goto fail;
++
++ drm_crtc_helper_add(crtc, &tilcdc_crtc_helper_funcs);
++
++ return crtc;
++
++fail:
++ tilcdc_crtc_destroy(crtc);
++ return NULL;
++}
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+new file mode 100644
+index 0000000..f6defbf
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -0,0 +1,605 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++/* LCDC DRM driver, based on da8xx-fb */
++
++#include "tilcdc_drv.h"
++#include "tilcdc_regs.h"
++#include "tilcdc_tfp410.h"
++
++#include "drm_fb_helper.h"
++
++static LIST_HEAD(module_list);
++
++void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
++ const struct tilcdc_module_ops *funcs)
++{
++ mod->name = name;
++ mod->funcs = funcs;
++ INIT_LIST_HEAD(&mod->list);
++ list_add(&mod->list, &module_list);
++}
++
++void tilcdc_module_cleanup(struct tilcdc_module *mod)
++{
++ list_del(&mod->list);
++}
++
++static struct of_device_id tilcdc_of_match[];
++
++static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
++ struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
++{
++ return drm_fb_cma_create(dev, file_priv, mode_cmd);
++}
++
++static void tilcdc_fb_output_poll_changed(struct drm_device *dev)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ if (priv->fbdev)
++ drm_fbdev_cma_hotplug_event(priv->fbdev);
++}
++
++static const struct drm_mode_config_funcs mode_config_funcs = {
++ .fb_create = tilcdc_fb_create,
++ .output_poll_changed = tilcdc_fb_output_poll_changed,
++};
++
++static int modeset_init(struct drm_device *dev)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ struct tilcdc_module *mod;
++
++ drm_mode_config_init(dev);
++
++ priv->crtc = tilcdc_crtc_create(dev);
++
++ list_for_each_entry(mod, &module_list, list) {
++ DBG("loading module: %s", mod->name);
++ mod->funcs->modeset_init(mod, dev);
++ }
++
++ if ((priv->num_encoders = 0) || (priv->num_connectors == 0)) {
++ /* oh nos! */
++ dev_err(dev->dev, "no encoders/connectors found\n");
++ return -ENXIO;
++ }
++
++ dev->mode_config.min_width = 0;
++ dev->mode_config.min_height = 0;
++ dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc);
++ dev->mode_config.max_height = 2048;
++ dev->mode_config.funcs = &mode_config_funcs;
++
++ return 0;
++}
++
++#ifdef CONFIG_CPU_FREQ
++static int cpufreq_transition(struct notifier_block *nb,
++ unsigned long val, void *data)
++{
++ struct tilcdc_drm_private *priv = container_of(nb,
++ struct tilcdc_drm_private, freq_transition);
++ if (val == CPUFREQ_POSTCHANGE) {
++ if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) {
++ priv->lcd_fck_rate = clk_get_rate(priv->clk);
++ tilcdc_crtc_update_clk(priv->crtc);
++ }
++ }
++
++ return 0;
++}
++#endif
++
++/*
++ * DRM operations:
++ */
++
++static int tilcdc_unload(struct drm_device *dev)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ struct tilcdc_module *mod, *cur;
++
++ drm_kms_helper_poll_fini(dev);
++ drm_mode_config_cleanup(dev);
++ drm_vblank_cleanup(dev);
++
++ pm_runtime_get_sync(dev->dev);
++ drm_irq_uninstall(dev);
++ pm_runtime_put_sync(dev->dev);
++
++#ifdef CONFIG_CPU_FREQ
++ cpufreq_unregister_notifier(&priv->freq_transition,
++ CPUFREQ_TRANSITION_NOTIFIER);
++#endif
++
++ if (priv->clk)
++ clk_put(priv->clk);
++
++ if (priv->mmio)
++ iounmap(priv->mmio);
++
++ flush_workqueue(priv->wq);
++ destroy_workqueue(priv->wq);
++
++ dev->dev_private = NULL;
++
++ pm_runtime_disable(dev->dev);
++
++ list_for_each_entry_safe(mod, cur, &module_list, list) {
++ DBG("destroying module: %s", mod->name);
++ mod->funcs->destroy(mod);
++ }
++
++ kfree(priv);
++
++ return 0;
++}
++
++static int tilcdc_load(struct drm_device *dev, unsigned long flags)
++{
++ struct platform_device *pdev = dev->platformdev;
++ struct device_node *node = pdev->dev.of_node;
++ struct tilcdc_drm_private *priv;
++ struct resource *res;
++ int ret;
++
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv) {
++ dev_err(dev->dev, "failed to allocate private data\n");
++ return -ENOMEM;
++ }
++
++ dev->dev_private = priv;
++
++ priv->wq = alloc_ordered_workqueue("tilcdc", 0);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(dev->dev, "failed to get memory resource\n");
++ ret = -EINVAL;
++ goto fail;
++ }
++
++ priv->mmio = ioremap_nocache(res->start, resource_size(res));
++ if (!priv->mmio) {
++ dev_err(dev->dev, "failed to ioremap\n");
++ ret = -ENOMEM;
++ goto fail;
++ }
++
++ priv->clk = clk_get(dev->dev, "fck");
++ if (IS_ERR(priv->clk)) {
++ dev_err(dev->dev, "failed to get functional clock\n");
++ ret = -ENODEV;
++ goto fail;
++ }
++
++ priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck");
++ if (IS_ERR(priv->clk)) {
++ dev_err(dev->dev, "failed to get display clock\n");
++ ret = -ENODEV;
++ goto fail;
++ }
++
++#ifdef CONFIG_CPU_FREQ
++ priv->lcd_fck_rate = clk_get_rate(priv->clk);
++ priv->freq_transition.notifier_call = cpufreq_transition;
++ ret = cpufreq_register_notifier(&priv->freq_transition,
++ CPUFREQ_TRANSITION_NOTIFIER);
++ if (ret) {
++ dev_err(dev->dev, "failed to register cpufreq notifier\n");
++ goto fail;
++ }
++#endif
++
++ if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth))
++ priv->max_bandwidth = 1280 * 1024 * 60;
++
++ pm_runtime_enable(dev->dev);
++
++ /* Determine LCD IP Version */
++ pm_runtime_get_sync(dev->dev);
++ switch (tilcdc_read(dev, LCDC_PID_REG)) {
++ case 0x4c100102:
++ priv->rev = 1;
++ break;
++ case 0x4f200800:
++ case 0x4f201000:
++ priv->rev = 2;
++ break;
++ default:
++ dev_warn(dev->dev, "Unknown PID Reg value 0x%08x, "
++ "defaulting to LCD revision 1\n",
++ tilcdc_read(dev, LCDC_PID_REG));
++ priv->rev = 1;
++ break;
++ }
++
++ pm_runtime_put_sync(dev->dev);
++
++ ret = modeset_init(dev);
++ if (ret < 0) {
++ dev_err(dev->dev, "failed to initialize mode setting\n");
++ goto fail;
++ }
++
++ ret = drm_vblank_init(dev, 1);
++ if (ret < 0) {
++ dev_err(dev->dev, "failed to initialize vblank\n");
++ goto fail;
++ }
++
++ pm_runtime_get_sync(dev->dev);
++ ret = drm_irq_install(dev);
++ pm_runtime_put_sync(dev->dev);
++ if (ret < 0) {
++ dev_err(dev->dev, "failed to install IRQ handler\n");
++ goto fail;
++ }
++
++ platform_set_drvdata(pdev, dev);
++
++ priv->fbdev = drm_fbdev_cma_init(dev, 16,
++ dev->mode_config.num_crtc,
++ dev->mode_config.num_connector);
++
++ drm_kms_helper_poll_init(dev);
++
++ return 0;
++
++fail:
++ tilcdc_unload(dev);
++ return ret;
++}
++
++static void tilcdc_preclose(struct drm_device *dev, struct drm_file *file)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++
++ tilcdc_crtc_cancel_page_flip(priv->crtc, file);
++}
++
++static void tilcdc_lastclose(struct drm_device *dev)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ drm_fbdev_cma_restore_mode(priv->fbdev);
++}
++
++static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS)
++{
++ struct drm_device *dev = arg;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ return tilcdc_crtc_irq(priv->crtc);
++}
++
++static void tilcdc_irq_preinstall(struct drm_device *dev)
++{
++ tilcdc_clear_irqstatus(dev, 0xffffffff);
++}
++
++static int tilcdc_irq_postinstall(struct drm_device *dev)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++
++ /* enable FIFO underflow irq: */
++ if (priv->rev == 1) {
++ tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_UNDERFLOW_INT_ENA);
++ } else {
++ tilcdc_set(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_UNDERFLOW_INT_ENA);
++ }
++
++ return 0;
++}
++
++static void tilcdc_irq_uninstall(struct drm_device *dev)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++
++ /* disable irqs that we might have enabled: */
++ if (priv->rev == 1) {
++ tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
++ LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA);
++ tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_V1_END_OF_FRAME_INT_ENA);
++ } else {
++ tilcdc_clear(dev, LCDC_INT_ENABLE_SET_REG,
++ LCDC_V2_UNDERFLOW_INT_ENA | LCDC_V2_PL_INT_ENA |
++ LCDC_V2_END_OF_FRAME0_INT_ENA | LCDC_V2_END_OF_FRAME1_INT_ENA |
++ LCDC_FRAME_DONE);
++ }
++
++}
++
++static void enable_vblank(struct drm_device *dev, bool enable)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ u32 reg, mask;
++
++ if (priv->rev == 1) {
++ reg = LCDC_DMA_CTRL_REG;
++ mask = LCDC_V1_END_OF_FRAME_INT_ENA;
++ } else {
++ reg = LCDC_INT_ENABLE_SET_REG;
++ mask = LCDC_V2_END_OF_FRAME0_INT_ENA |
++ LCDC_V2_END_OF_FRAME1_INT_ENA | LCDC_FRAME_DONE;
++ }
++
++ if (enable)
++ tilcdc_set(dev, reg, mask);
++ else
++ tilcdc_clear(dev, reg, mask);
++}
++
++static int tilcdc_enable_vblank(struct drm_device *dev, int crtc)
++{
++ enable_vblank(dev, true);
++ return 0;
++}
++
++static void tilcdc_disable_vblank(struct drm_device *dev, int crtc)
++{
++ enable_vblank(dev, false);
++}
++
++#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_PM_SLEEP)
++static const struct {
++ const char *name;
++ uint8_t rev;
++ uint8_t save;
++ uint32_t reg;
++} registers[] = {
++#define REG(rev, save, reg) { #reg, rev, save, reg }
++ /* exists in revision 1: */
++ REG(1, false, LCDC_PID_REG),
++ REG(1, true, LCDC_CTRL_REG),
++ REG(1, false, LCDC_STAT_REG),
++ REG(1, true, LCDC_RASTER_CTRL_REG),
++ REG(1, true, LCDC_RASTER_TIMING_0_REG),
++ REG(1, true, LCDC_RASTER_TIMING_1_REG),
++ REG(1, true, LCDC_RASTER_TIMING_2_REG),
++ REG(1, true, LCDC_DMA_CTRL_REG),
++ REG(1, true, LCDC_DMA_FB_BASE_ADDR_0_REG),
++ REG(1, true, LCDC_DMA_FB_CEILING_ADDR_0_REG),
++ REG(1, true, LCDC_DMA_FB_BASE_ADDR_1_REG),
++ REG(1, true, LCDC_DMA_FB_CEILING_ADDR_1_REG),
++ /* new in revision 2: */
++ REG(2, false, LCDC_RAW_STAT_REG),
++ REG(2, false, LCDC_MASKED_STAT_REG),
++ REG(2, false, LCDC_INT_ENABLE_SET_REG),
++ REG(2, false, LCDC_INT_ENABLE_CLR_REG),
++ REG(2, false, LCDC_END_OF_INT_IND_REG),
++ REG(2, true, LCDC_CLK_ENABLE_REG),
++ REG(2, true, LCDC_INT_ENABLE_SET_REG),
++#undef REG
++};
++#endif
++
++#ifdef CONFIG_DEBUG_FS
++static int tilcdc_regs_show(struct seq_file *m, void *arg)
++{
++ struct drm_info_node *node = (struct drm_info_node *) m->private;
++ struct drm_device *dev = node->minor->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ unsigned i;
++
++ pm_runtime_get_sync(dev->dev);
++
++ seq_printf(m, "revision: %d\n", priv->rev);
++
++ for (i = 0; i < ARRAY_SIZE(registers); i++)
++ if (priv->rev >= registers[i].rev)
++ seq_printf(m, "%s:\t %08x\n", registers[i].name,
++ tilcdc_read(dev, registers[i].reg));
++
++ pm_runtime_put_sync(dev->dev);
++
++ return 0;
++}
++
++static int tilcdc_mm_show(struct seq_file *m, void *arg)
++{
++ struct drm_info_node *node = (struct drm_info_node *) m->private;
++ struct drm_device *dev = node->minor->dev;
++ return drm_mm_dump_table(m, dev->mm_private);
++}
++
++static struct drm_info_list tilcdc_debugfs_list[] = {
++ { "regs", tilcdc_regs_show, 0 },
++ { "mm", tilcdc_mm_show, 0 },
++ { "fb", drm_fb_cma_debugfs_show, 0 },
++};
++
++static int tilcdc_debugfs_init(struct drm_minor *minor)
++{
++ struct drm_device *dev = minor->dev;
++ struct tilcdc_module *mod;
++ int ret;
++
++ ret = drm_debugfs_create_files(tilcdc_debugfs_list,
++ ARRAY_SIZE(tilcdc_debugfs_list),
++ minor->debugfs_root, minor);
++
++ list_for_each_entry(mod, &module_list, list)
++ if (mod->funcs->debugfs_init)
++ mod->funcs->debugfs_init(mod, minor);
++
++ if (ret) {
++ dev_err(dev->dev, "could not install tilcdc_debugfs_list\n");
++ return ret;
++ }
++
++ return ret;
++}
++
++static void tilcdc_debugfs_cleanup(struct drm_minor *minor)
++{
++ struct tilcdc_module *mod;
++ drm_debugfs_remove_files(tilcdc_debugfs_list,
++ ARRAY_SIZE(tilcdc_debugfs_list), minor);
++
++ list_for_each_entry(mod, &module_list, list)
++ if (mod->funcs->debugfs_cleanup)
++ mod->funcs->debugfs_cleanup(mod, minor);
++}
++#endif
++
++static const struct file_operations fops = {
++ .owner = THIS_MODULE,
++ .open = drm_open,
++ .release = drm_release,
++ .unlocked_ioctl = drm_ioctl,
++#ifdef CONFIG_COMPAT
++ .compat_ioctl = drm_compat_ioctl,
++#endif
++ .poll = drm_poll,
++ .read = drm_read,
++ .fasync = drm_fasync,
++ .llseek = no_llseek,
++ .mmap = drm_gem_cma_mmap,
++};
++
++static struct drm_driver tilcdc_driver = {
++ .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET,
++ .load = tilcdc_load,
++ .unload = tilcdc_unload,
++ .preclose = tilcdc_preclose,
++ .lastclose = tilcdc_lastclose,
++ .irq_handler = tilcdc_irq,
++ .irq_preinstall = tilcdc_irq_preinstall,
++ .irq_postinstall = tilcdc_irq_postinstall,
++ .irq_uninstall = tilcdc_irq_uninstall,
++ .get_vblank_counter = drm_vblank_count,
++ .enable_vblank = tilcdc_enable_vblank,
++ .disable_vblank = tilcdc_disable_vblank,
++ .gem_free_object = drm_gem_cma_free_object,
++ .gem_vm_ops = &drm_gem_cma_vm_ops,
++ .dumb_create = drm_gem_cma_dumb_create,
++ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
++ .dumb_destroy = drm_gem_cma_dumb_destroy,
++#ifdef CONFIG_DEBUG_FS
++ .debugfs_init = tilcdc_debugfs_init,
++ .debugfs_cleanup = tilcdc_debugfs_cleanup,
++#endif
++ .fops = &fops,
++ .name = "tilcdc",
++ .desc = "TI LCD Controller DRM",
++ .date = "20121205",
++ .major = 1,
++ .minor = 0,
++};
++
++/*
++ * Power management:
++ */
++
++#ifdef CONFIG_PM_SLEEP
++static int tilcdc_pm_suspend(struct device *dev)
++{
++ struct drm_device *ddev = dev_get_drvdata(dev);
++ struct tilcdc_drm_private *priv = ddev->dev_private;
++ unsigned i, n = 0;
++
++ drm_kms_helper_poll_disable(ddev);
++
++ /* Save register state: */
++ for (i = 0; i < ARRAY_SIZE(registers); i++)
++ if (registers[i].save && (priv->rev >= registers[i].rev))
++ priv->saved_register[n++] = tilcdc_read(ddev, registers[i].reg);
++
++ return 0;
++}
++
++static int tilcdc_pm_resume(struct device *dev)
++{
++ struct drm_device *ddev = dev_get_drvdata(dev);
++ struct tilcdc_drm_private *priv = ddev->dev_private;
++ unsigned i, n = 0;
++
++ /* Restore register state: */
++ for (i = 0; i < ARRAY_SIZE(registers); i++)
++ if (registers[i].save && (priv->rev >= registers[i].rev))
++ tilcdc_write(ddev, registers[i].reg, priv->saved_register[n++]);
++
++ drm_kms_helper_poll_enable(ddev);
++
++ return 0;
++}
++#endif
++
++static const struct dev_pm_ops tilcdc_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(tilcdc_pm_suspend, tilcdc_pm_resume)
++};
++
++/*
++ * Platform driver:
++ */
++
++static int tilcdc_pdev_probe(struct platform_device *pdev)
++{
++ /* bail out early if no DT data: */
++ if (!pdev->dev.of_node) {
++ dev_err(&pdev->dev, "device-tree data is missing\n");
++ return -ENXIO;
++ }
++
++ return drm_platform_init(&tilcdc_driver, pdev);
++}
++
++static int tilcdc_pdev_remove(struct platform_device *pdev)
++{
++ drm_platform_exit(&tilcdc_driver, pdev);
++
++ return 0;
++}
++
++static struct of_device_id tilcdc_of_match[] = {
++ { .compatible = "ti,am33xx-tilcdc", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, tilcdc_of_match);
++
++static struct platform_driver tilcdc_platform_driver = {
++ .probe = tilcdc_pdev_probe,
++ .remove = tilcdc_pdev_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "tilcdc",
++ .pm = &tilcdc_pm_ops,
++ .of_match_table = tilcdc_of_match,
++ },
++};
++
++static int __init tilcdc_drm_init(void)
++{
++ DBG("init");
++ tilcdc_tfp410_init();
++ return platform_driver_register(&tilcdc_platform_driver);
++}
++
++static void __exit tilcdc_drm_fini(void)
++{
++ DBG("fini");
++ tilcdc_tfp410_fini();
++ platform_driver_unregister(&tilcdc_platform_driver);
++}
++
++module_init(tilcdc_drm_init);
++module_exit(tilcdc_drm_fini);
++
++MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
++MODULE_DESCRIPTION("TI LCD Controller DRM Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+new file mode 100644
+index 0000000..8242b5a
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -0,0 +1,150 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __TILCDC_DRV_H__
++#define __TILCDC_DRV_H__
++
++#include <linux/clk.h>
++#include <linux/cpufreq.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/pm_runtime.h>
++#include <linux/slab.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/list.h>
++
++#include <drm/drmP.h>
++#include <drm/drm_crtc_helper.h>
++#include <drm/drm_gem_cma_helper.h>
++#include <drm/drm_fb_cma_helper.h>
++
++struct tilcdc_drm_private {
++ void __iomem *mmio;
++
++ struct clk *disp_clk; /* display dpll */
++ struct clk *clk; /* functional clock */
++ int rev; /* IP revision */
++
++ /* don't attempt resolutions w/ higher W * H * Hz: */
++ uint32_t max_bandwidth;
++
++ /* register contents saved across suspend/resume: */
++ u32 saved_register[12];
++
++#ifdef CONFIG_CPU_FREQ
++ struct notifier_block freq_transition;
++ unsigned int lcd_fck_rate;
++#endif
++
++ struct workqueue_struct *wq;
++
++ struct drm_fbdev_cma *fbdev;
++
++ struct drm_crtc *crtc;
++
++ unsigned int num_encoders;
++ struct drm_encoder *encoders[8];
++
++ unsigned int num_connectors;
++ struct drm_connector *connectors[8];
++};
++
++/* Sub-module for display. Since we don't know at compile time what panels
++ * or display adapter(s) might be present (for ex, off chip dvi/tfp410,
++ * hdmi encoder, various lcd panels), the connector/encoder(s) are split into
++ * separate drivers. If they are probed and found to be present, they
++ * register themselves with tilcdc_register_module().
++ */
++struct tilcdc_module;
++
++struct tilcdc_module_ops {
++ /* create appropriate encoders/connectors: */
++ int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev);
++ void (*destroy)(struct tilcdc_module *mod);
++#ifdef CONFIG_DEBUG_FS
++ /* create debugfs nodes (can be NULL): */
++ int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor);
++ /* cleanup debugfs nodes (can be NULL): */
++ void (*debugfs_cleanup)(struct tilcdc_module *mod, struct drm_minor *minor);
++#endif
++};
++
++struct tilcdc_module {
++ const char *name;
++ struct list_head list;
++ const struct tilcdc_module_ops *funcs;
++};
++
++void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
++ const struct tilcdc_module_ops *funcs);
++void tilcdc_module_cleanup(struct tilcdc_module *mod);
++
++
++/* Panel config that needs to be set in the crtc, but is not coming from
++ * the mode timings. The display module is expected to call
++ * tilcdc_crtc_set_panel_info() to set this during modeset.
++ */
++struct tilcdc_panel_info {
++
++ /* AC Bias Pin Frequency */
++ uint32_t ac_bias;
++
++ /* AC Bias Pin Transitions per Interrupt */
++ uint32_t ac_bias_intrpt;
++
++ /* DMA burst size */
++ uint32_t dma_burst_sz;
++
++ /* Bits per pixel */
++ uint32_t bpp;
++
++ /* FIFO DMA Request Delay */
++ uint32_t fdd;
++
++ /* TFT Alternative Signal Mapping (Only for active) */
++ bool tft_alt_mode;
++
++ /* Invert pixel clock */
++ bool invert_pxl_clk;
++
++ /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
++ uint32_t sync_edge;
++
++ /* Horizontal and Vertical Sync: Control: 0=ignore */
++ uint32_t sync_ctrl;
++
++ /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
++ uint32_t raster_order;
++
++ /* DMA FIFO threshold */
++ uint32_t fifo_th;
++};
++
++#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
++
++struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev);
++void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
++irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc);
++void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
++void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
++ const struct tilcdc_panel_info *info);
++int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
++int tilcdc_crtc_max_width(struct drm_crtc *crtc);
++
++#endif /* __TILCDC_DRV_H__ */
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
+new file mode 100644
+index 0000000..17fd1b4
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
+@@ -0,0 +1,154 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __TILCDC_REGS_H__
++#define __TILCDC_REGS_H__
++
++/* LCDC register definitions, based on da8xx-fb */
++
++#include <linux/bitops.h>
++
++#include "tilcdc_drv.h"
++
++/* LCDC Status Register */
++#define LCDC_END_OF_FRAME1 BIT(9)
++#define LCDC_END_OF_FRAME0 BIT(8)
++#define LCDC_PL_LOAD_DONE BIT(6)
++#define LCDC_FIFO_UNDERFLOW BIT(5)
++#define LCDC_SYNC_LOST BIT(2)
++#define LCDC_FRAME_DONE BIT(0)
++
++/* LCDC DMA Control Register */
++#define LCDC_DMA_BURST_SIZE(x) ((x) << 4)
++#define LCDC_DMA_BURST_1 0x0
++#define LCDC_DMA_BURST_2 0x1
++#define LCDC_DMA_BURST_4 0x2
++#define LCDC_DMA_BURST_8 0x3
++#define LCDC_DMA_BURST_16 0x4
++#define LCDC_V1_END_OF_FRAME_INT_ENA BIT(2)
++#define LCDC_V2_END_OF_FRAME0_INT_ENA BIT(8)
++#define LCDC_V2_END_OF_FRAME1_INT_ENA BIT(9)
++#define LCDC_DUAL_FRAME_BUFFER_ENABLE BIT(0)
++
++/* LCDC Control Register */
++#define LCDC_CLK_DIVISOR(x) ((x) << 8)
++#define LCDC_RASTER_MODE 0x01
++
++/* LCDC Raster Control Register */
++#define LCDC_PALETTE_LOAD_MODE(x) ((x) << 20)
++#define PALETTE_AND_DATA 0x00
++#define PALETTE_ONLY 0x01
++#define DATA_ONLY 0x02
++
++#define LCDC_MONO_8BIT_MODE BIT(9)
++#define LCDC_RASTER_ORDER BIT(8)
++#define LCDC_TFT_MODE BIT(7)
++#define LCDC_V1_UNDERFLOW_INT_ENA BIT(6)
++#define LCDC_V2_UNDERFLOW_INT_ENA BIT(5)
++#define LCDC_V1_PL_INT_ENA BIT(4)
++#define LCDC_V2_PL_INT_ENA BIT(6)
++#define LCDC_MONOCHROME_MODE BIT(1)
++#define LCDC_RASTER_ENABLE BIT(0)
++#define LCDC_TFT_ALT_ENABLE BIT(23)
++#define LCDC_STN_565_ENABLE BIT(24)
++#define LCDC_V2_DMA_CLK_EN BIT(2)
++#define LCDC_V2_LIDD_CLK_EN BIT(1)
++#define LCDC_V2_CORE_CLK_EN BIT(0)
++#define LCDC_V2_LPP_B10 26
++#define LCDC_V2_TFT_24BPP_MODE BIT(25)
++#define LCDC_V2_TFT_24BPP_UNPACK BIT(26)
++
++/* LCDC Raster Timing 2 Register */
++#define LCDC_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
++#define LCDC_AC_BIAS_FREQUENCY(x) ((x) << 8)
++#define LCDC_SYNC_CTRL BIT(25)
++#define LCDC_SYNC_EDGE BIT(24)
++#define LCDC_INVERT_PIXEL_CLOCK BIT(22)
++#define LCDC_INVERT_HSYNC BIT(21)
++#define LCDC_INVERT_VSYNC BIT(20)
++
++/* LCDC Block */
++#define LCDC_PID_REG 0x0
++#define LCDC_CTRL_REG 0x4
++#define LCDC_STAT_REG 0x8
++#define LCDC_RASTER_CTRL_REG 0x28
++#define LCDC_RASTER_TIMING_0_REG 0x2c
++#define LCDC_RASTER_TIMING_1_REG 0x30
++#define LCDC_RASTER_TIMING_2_REG 0x34
++#define LCDC_DMA_CTRL_REG 0x40
++#define LCDC_DMA_FB_BASE_ADDR_0_REG 0x44
++#define LCDC_DMA_FB_CEILING_ADDR_0_REG 0x48
++#define LCDC_DMA_FB_BASE_ADDR_1_REG 0x4c
++#define LCDC_DMA_FB_CEILING_ADDR_1_REG 0x50
++
++/* Interrupt Registers available only in Version 2 */
++#define LCDC_RAW_STAT_REG 0x58
++#define LCDC_MASKED_STAT_REG 0x5c
++#define LCDC_INT_ENABLE_SET_REG 0x60
++#define LCDC_INT_ENABLE_CLR_REG 0x64
++#define LCDC_END_OF_INT_IND_REG 0x68
++
++/* Clock registers available only on Version 2 */
++#define LCDC_CLK_ENABLE_REG 0x6c
++#define LCDC_CLK_RESET_REG 0x70
++#define LCDC_CLK_MAIN_RESET BIT(3)
++
++
++/*
++ * Helpers:
++ */
++
++static inline void tilcdc_write(struct drm_device *dev, u32 reg, u32 data)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ iowrite32(data, priv->mmio + reg);
++}
++
++static inline u32 tilcdc_read(struct drm_device *dev, u32 reg)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ return ioread32(priv->mmio + reg);
++}
++
++static inline void tilcdc_set(struct drm_device *dev, u32 reg, u32 mask)
++{
++ tilcdc_write(dev, reg, tilcdc_read(dev, reg) | mask);
++}
++
++static inline void tilcdc_clear(struct drm_device *dev, u32 reg, u32 mask)
++{
++ tilcdc_write(dev, reg, tilcdc_read(dev, reg) & ~mask);
++}
++
++/* the register to read/clear irqstatus differs between v1 and v2 of the IP */
++static inline u32 tilcdc_irqstatus_reg(struct drm_device *dev)
++{
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ return (priv->rev == 2) ? LCDC_MASKED_STAT_REG : LCDC_STAT_REG;
++}
++
++static inline u32 tilcdc_read_irqstatus(struct drm_device *dev)
++{
++ return tilcdc_read(dev, tilcdc_irqstatus_reg(dev));
++}
++
++static inline void tilcdc_clear_irqstatus(struct drm_device *dev, u32 mask)
++{
++ tilcdc_write(dev, tilcdc_irqstatus_reg(dev), mask);
++}
++
++#endif /* __TILCDC_REGS_H__ */
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+new file mode 100644
+index 0000000..10444ee
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+@@ -0,0 +1,419 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/i2c.h>
++#include <linux/of_i2c.h>
++#include <linux/gpio.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++
++#include "tilcdc_drv.h"
++
++struct tfp410_module {
++ struct tilcdc_module base;
++ struct i2c_adapter *i2c;
++ int gpio;
++};
++#define to_tfp410_module(x) container_of(x, struct tfp410_module, base)
++
++
++static const struct tilcdc_panel_info dvi_info = {
++ .ac_bias = 255,
++ .ac_bias_intrpt = 0,
++ .dma_burst_sz = 16,
++ .bpp = 16,
++ .fdd = 0x80,
++ .tft_alt_mode = 0,
++ .sync_edge = 0,
++ .sync_ctrl = 1,
++ .raster_order = 0,
++};
++
++/*
++ * Encoder:
++ */
++
++struct tfp410_encoder {
++ struct drm_encoder base;
++ struct tfp410_module *mod;
++ int dpms;
++};
++#define to_tfp410_encoder(x) container_of(x, struct tfp410_encoder, base)
++
++
++static void tfp410_encoder_destroy(struct drm_encoder *encoder)
++{
++ struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
++ drm_encoder_cleanup(encoder);
++ kfree(tfp410_encoder);
++}
++
++static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode)
++{
++ struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
++
++ if (tfp410_encoder->dpms == mode)
++ return;
++
++ if (mode == DRM_MODE_DPMS_ON) {
++ DBG("Power on");
++ gpio_direction_output(tfp410_encoder->mod->gpio, 1);
++ } else {
++ DBG("Power off");
++ gpio_direction_output(tfp410_encoder->mod->gpio, 0);
++ }
++
++ tfp410_encoder->dpms = mode;
++}
++
++static bool tfp410_encoder_mode_fixup(struct drm_encoder *encoder,
++ const struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ /* nothing needed */
++ return true;
++}
++
++static void tfp410_encoder_prepare(struct drm_encoder *encoder)
++{
++ tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
++ tilcdc_crtc_set_panel_info(encoder->crtc, &dvi_info);
++}
++
++static void tfp410_encoder_commit(struct drm_encoder *encoder)
++{
++ tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
++}
++
++static void tfp410_encoder_mode_set(struct drm_encoder *encoder,
++ struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ /* nothing needed */
++}
++
++static const struct drm_encoder_funcs tfp410_encoder_funcs = {
++ .destroy = tfp410_encoder_destroy,
++};
++
++static const struct drm_encoder_helper_funcs tfp410_encoder_helper_funcs = {
++ .dpms = tfp410_encoder_dpms,
++ .mode_fixup = tfp410_encoder_mode_fixup,
++ .prepare = tfp410_encoder_prepare,
++ .commit = tfp410_encoder_commit,
++ .mode_set = tfp410_encoder_mode_set,
++};
++
++static struct drm_encoder *tfp410_encoder_create(struct drm_device *dev,
++ struct tfp410_module *mod)
++{
++ struct tfp410_encoder *tfp410_encoder;
++ struct drm_encoder *encoder;
++ int ret;
++
++ tfp410_encoder = kzalloc(sizeof(*tfp410_encoder), GFP_KERNEL);
++ if (!tfp410_encoder) {
++ dev_err(dev->dev, "allocation failed\n");
++ return NULL;
++ }
++
++ tfp410_encoder->dpms = DRM_MODE_DPMS_OFF;
++ tfp410_encoder->mod = mod;
++
++ encoder = &tfp410_encoder->base;
++ encoder->possible_crtcs = 1;
++
++ ret = drm_encoder_init(dev, encoder, &tfp410_encoder_funcs,
++ DRM_MODE_ENCODER_TMDS);
++ if (ret < 0)
++ goto fail;
++
++ drm_encoder_helper_add(encoder, &tfp410_encoder_helper_funcs);
++
++ return encoder;
++
++fail:
++ tfp410_encoder_destroy(encoder);
++ return NULL;
++}
++
++/*
++ * Connector:
++ */
++
++struct tfp410_connector {
++ struct drm_connector base;
++
++ struct drm_encoder *encoder; /* our connected encoder */
++ struct tfp410_module *mod;
++};
++#define to_tfp410_connector(x) container_of(x, struct tfp410_connector, base)
++
++
++static void tfp410_connector_destroy(struct drm_connector *connector)
++{
++ struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
++ drm_connector_cleanup(connector);
++ kfree(tfp410_connector);
++}
++
++static enum drm_connector_status tfp410_connector_detect(
++ struct drm_connector *connector,
++ bool force)
++{
++ struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
++
++ if (drm_probe_ddc(tfp410_connector->mod->i2c))
++ return connector_status_connected;
++
++ return connector_status_unknown;
++}
++
++static int tfp410_connector_get_modes(struct drm_connector *connector)
++{
++ struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
++ struct edid *edid;
++ int ret = 0;
++
++ edid = drm_get_edid(connector, tfp410_connector->mod->i2c);
++
++ drm_mode_connector_update_edid_property(connector, edid);
++
++ if (edid) {
++ ret = drm_add_edid_modes(connector, edid);
++ kfree(edid);
++ }
++
++ return ret;
++}
++
++static int tfp410_connector_mode_valid(struct drm_connector *connector,
++ struct drm_display_mode *mode)
++{
++ struct tilcdc_drm_private *priv = connector->dev->dev_private;
++ /* our only constraints are what the crtc can generate: */
++ return tilcdc_crtc_mode_valid(priv->crtc, mode);
++}
++
++static struct drm_encoder *tfp410_connector_best_encoder(
++ struct drm_connector *connector)
++{
++ struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
++ return tfp410_connector->encoder;
++}
++
++static const struct drm_connector_funcs tfp410_connector_funcs = {
++ .destroy = tfp410_connector_destroy,
++ .dpms = drm_helper_connector_dpms,
++ .detect = tfp410_connector_detect,
++ .fill_modes = drm_helper_probe_single_connector_modes,
++};
++
++static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = {
++ .get_modes = tfp410_connector_get_modes,
++ .mode_valid = tfp410_connector_mode_valid,
++ .best_encoder = tfp410_connector_best_encoder,
++};
++
++static struct drm_connector *tfp410_connector_create(struct drm_device *dev,
++ struct tfp410_module *mod, struct drm_encoder *encoder)
++{
++ struct tfp410_connector *tfp410_connector;
++ struct drm_connector *connector;
++ int ret;
++
++ tfp410_connector = kzalloc(sizeof(*tfp410_connector), GFP_KERNEL);
++ if (!tfp410_connector) {
++ dev_err(dev->dev, "allocation failed\n");
++ return NULL;
++ }
++
++ tfp410_connector->encoder = encoder;
++ tfp410_connector->mod = mod;
++
++ connector = &tfp410_connector->base;
++
++ drm_connector_init(dev, connector, &tfp410_connector_funcs,
++ DRM_MODE_CONNECTOR_DVID);
++ drm_connector_helper_add(connector, &tfp410_connector_helper_funcs);
++
++ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
++ DRM_CONNECTOR_POLL_DISCONNECT;
++
++ connector->interlace_allowed = 0;
++ connector->doublescan_allowed = 0;
++
++ ret = drm_mode_connector_attach_encoder(connector, encoder);
++ if (ret)
++ goto fail;
++
++ drm_sysfs_connector_add(connector);
++
++ return connector;
++
++fail:
++ tfp410_connector_destroy(connector);
++ return NULL;
++}
++
++/*
++ * Module:
++ */
++
++static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
++{
++ struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ struct drm_encoder *encoder;
++ struct drm_connector *connector;
++
++ encoder = tfp410_encoder_create(dev, tfp410_mod);
++ if (!encoder)
++ return -ENOMEM;
++
++ connector = tfp410_connector_create(dev, tfp410_mod, encoder);
++ if (!connector)
++ return -ENOMEM;
++
++ priv->encoders[priv->num_encoders++] = encoder;
++ priv->connectors[priv->num_connectors++] = connector;
++
++ return 0;
++}
++
++static void tfp410_destroy(struct tilcdc_module *mod)
++{
++ struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
++
++ if (tfp410_mod->i2c)
++ i2c_put_adapter(tfp410_mod->i2c);
++
++ if (!IS_ERR_VALUE(tfp410_mod->gpio))
++ gpio_free(tfp410_mod->gpio);
++
++ tilcdc_module_cleanup(mod);
++ kfree(tfp410_mod);
++}
++
++static const struct tilcdc_module_ops tfp410_module_ops = {
++ .modeset_init = tfp410_modeset_init,
++ .destroy = tfp410_destroy,
++};
++
++/*
++ * Device:
++ */
++
++static struct of_device_id tfp410_of_match[];
++
++static int tfp410_probe(struct platform_device *pdev)
++{
++ struct device_node *node = pdev->dev.of_node;
++ struct device_node *i2c_node;
++ struct tfp410_module *tfp410_mod;
++ struct tilcdc_module *mod;
++ struct pinctrl *pinctrl;
++ uint32_t i2c_phandle;
++ int ret = -EINVAL;
++
++ /* bail out early if no DT data: */
++ if (!node) {
++ dev_err(&pdev->dev, "device-tree data is missing\n");
++ return -ENXIO;
++ }
++
++ tfp410_mod = kzalloc(sizeof(*tfp410_mod), GFP_KERNEL);
++ if (!tfp410_mod)
++ return -ENOMEM;
++
++ mod = &tfp410_mod->base;
++
++ tilcdc_module_init(mod, "tfp410", &tfp410_module_ops);
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "pins are not configured\n");
++
++ if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
++ dev_err(&pdev->dev, "could not get i2c bus phandle\n");
++ goto fail;
++ }
++
++ i2c_node = of_find_node_by_phandle(i2c_phandle);
++ if (!i2c_node) {
++ dev_err(&pdev->dev, "could not get i2c bus node\n");
++ goto fail;
++ }
++
++ tfp410_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
++ if (!tfp410_mod->i2c) {
++ dev_err(&pdev->dev, "could not get i2c\n");
++ goto fail;
++ }
++
++ of_node_put(i2c_node);
++
++ tfp410_mod->gpio = of_get_named_gpio_flags(node, "powerdn-gpio",
++ 0, NULL);
++ if (IS_ERR_VALUE(tfp410_mod->gpio)) {
++ dev_warn(&pdev->dev, "No power down GPIO\n");
++ } else {
++ ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
++ if (ret) {
++ dev_err(&pdev->dev, "could not get DVI_PDn gpio\n");
++ goto fail;
++ }
++ }
++
++ return 0;
++
++fail:
++ tfp410_destroy(mod);
++ return ret;
++}
++
++static int tfp410_remove(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static struct of_device_id tfp410_of_match[] = {
++ { .compatible = "tilcdc,tfp410", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, tfp410_of_match);
++
++struct platform_driver tfp410_driver = {
++ .probe = tfp410_probe,
++ .remove = tfp410_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "tfp410",
++ .of_match_table = tfp410_of_match,
++ },
++};
++
++int __init tilcdc_tfp410_init(void)
++{
++ return platform_driver_register(&tfp410_driver);
++}
++
++void __exit tilcdc_tfp410_fini(void)
++{
++ platform_driver_unregister(&tfp410_driver);
++}
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h
+new file mode 100644
+index 0000000..5b800f1
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __TILCDC_TFP410_H__
++#define __TILCDC_TFP410_H__
++
++/* sub-module for tfp410 dvi adaptor */
++
++int tilcdc_tfp410_init(void);
++void tilcdc_tfp410_fini(void);
++
++#endif /* __TILCDC_TFP410_H__ */
diff --git a/patches/linux-3.8.13/0233-drm-i2c-nxp-tda998x-v3.patch b/patches/linux-3.8.13/0233-drm-i2c-nxp-tda998x-v3.patch
new file mode 100644
index 0000000..baf650e
--- /dev/null
+++ b/patches/linux-3.8.13/0233-drm-i2c-nxp-tda998x-v3.patch
@@ -0,0 +1,956 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Tue, 8 Jan 2013 19:21:02 -0600
+Subject: [PATCH] drm/i2c: nxp-tda998x (v3)
+
+Driver for the NXP TDA998X i2c hdmi encoder slave.
+
+v1: original
+v2: fix npix/nline programming
+v3: add Kconfig, fix dup'd MODULE_DESCRIPTION
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/i2c/Kconfig | 6 +
+ drivers/gpu/drm/i2c/Makefile | 3 +
+ drivers/gpu/drm/i2c/tda998x_drv.c | 906 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 915 insertions(+)
+ create mode 100644 drivers/gpu/drm/i2c/tda998x_drv.c
+
+diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
+index 1611836..4d341db 100644
+--- a/drivers/gpu/drm/i2c/Kconfig
++++ b/drivers/gpu/drm/i2c/Kconfig
+@@ -19,4 +19,10 @@ config DRM_I2C_SIL164
+ when used in pairs) TMDS transmitters, used in some nVidia
+ video cards.
+
++config DRM_I2C_NXP_TDA998X
++ tristate "NXP Semiconductors TDA998X HDMI encoder"
++ default m if DRM_TILCDC
++ help
++ Support for NXP Semiconductors TDA998X HDMI encoders.
++
+ endmenu
+diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
+index 9286256..43aa33b 100644
+--- a/drivers/gpu/drm/i2c/Makefile
++++ b/drivers/gpu/drm/i2c/Makefile
+@@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
+
+ sil164-y := sil164_drv.o
+ obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
++
++tda998x-y := tda998x_drv.o
++obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+new file mode 100644
+index 0000000..e68b58a
+--- /dev/null
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -0,0 +1,906 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++
++
++#include <linux/module.h>
++
++#include <drm/drmP.h>
++#include <drm/drm_crtc_helper.h>
++#include <drm/drm_encoder_slave.h>
++#include <drm/drm_edid.h>
++
++
++#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
++
++struct tda998x_priv {
++ struct i2c_client *cec;
++ uint16_t rev;
++ uint8_t current_page;
++ int dpms;
++};
++
++#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
++
++/* The TDA9988 series of devices use a paged register scheme.. to simplify
++ * things we encode the page # in upper bits of the register #. To read/
++ * write a given register, we need to make sure CURPAGE register is set
++ * appropriately. Which implies reads/writes are not atomic. Fun!
++ */
++
++#define REG(page, addr) (((page) << 8) | (addr))
++#define REG2ADDR(reg) ((reg) & 0xff)
++#define REG2PAGE(reg) (((reg) >> 8) & 0xff)
++
++#define REG_CURPAGE 0xff /* write */
++
++
++/* Page 00h: General Control */
++#define REG_VERSION_LSB REG(0x00, 0x00) /* read */
++#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */
++# define MAIN_CNTRL0_SR (1 << 0)
++# define MAIN_CNTRL0_DECS (1 << 1)
++# define MAIN_CNTRL0_DEHS (1 << 2)
++# define MAIN_CNTRL0_CECS (1 << 3)
++# define MAIN_CNTRL0_CEHS (1 << 4)
++# define MAIN_CNTRL0_SCALER (1 << 7)
++#define REG_VERSION_MSB REG(0x00, 0x02) /* read */
++#define REG_SOFTRESET REG(0x00, 0x0a) /* write */
++# define SOFTRESET_AUDIO (1 << 0)
++# define SOFTRESET_I2C_MASTER (1 << 1)
++#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */
++#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */
++#define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */
++# define I2C_MASTER_DIS_MM (1 << 0)
++# define I2C_MASTER_DIS_FILT (1 << 1)
++# define I2C_MASTER_APP_STRT_LAT (1 << 2)
++#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */
++#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */
++#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */
++# define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
++#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */
++#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */
++#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */
++#define REG_ENA_AP REG(0x00, 0x1e) /* read/write */
++#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */
++# define VIP_CNTRL_0_MIRR_A (1 << 7)
++# define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4)
++# define VIP_CNTRL_0_MIRR_B (1 << 3)
++# define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0)
++#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */
++# define VIP_CNTRL_1_MIRR_C (1 << 7)
++# define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4)
++# define VIP_CNTRL_1_MIRR_D (1 << 3)
++# define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0)
++#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */
++# define VIP_CNTRL_2_MIRR_E (1 << 7)
++# define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4)
++# define VIP_CNTRL_2_MIRR_F (1 << 3)
++# define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0)
++#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */
++# define VIP_CNTRL_3_X_TGL (1 << 0)
++# define VIP_CNTRL_3_H_TGL (1 << 1)
++# define VIP_CNTRL_3_V_TGL (1 << 2)
++# define VIP_CNTRL_3_EMB (1 << 3)
++# define VIP_CNTRL_3_SYNC_DE (1 << 4)
++# define VIP_CNTRL_3_SYNC_HS (1 << 5)
++# define VIP_CNTRL_3_DE_INT (1 << 6)
++# define VIP_CNTRL_3_EDGE (1 << 7)
++#define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */
++# define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0)
++# define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2)
++# define VIP_CNTRL_4_CCIR656 (1 << 4)
++# define VIP_CNTRL_4_656_ALT (1 << 5)
++# define VIP_CNTRL_4_TST_656 (1 << 6)
++# define VIP_CNTRL_4_TST_PAT (1 << 7)
++#define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
++# define VIP_CNTRL_5_CKCASE (1 << 0)
++# define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
++#define REG_MAT_CONTRL REG(0x00, 0x80) /* write */
++# define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0)
++# define MAT_CONTRL_MAT_BP (1 << 2)
++#define REG_VIDFORMAT REG(0x00, 0xa0) /* write */
++#define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */
++#define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */
++#define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */
++#define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */
++#define REG_NPIX_MSB REG(0x00, 0xa5) /* write */
++#define REG_NPIX_LSB REG(0x00, 0xa6) /* write */
++#define REG_NLINE_MSB REG(0x00, 0xa7) /* write */
++#define REG_NLINE_LSB REG(0x00, 0xa8) /* write */
++#define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */
++#define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */
++#define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */
++#define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */
++#define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */
++#define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */
++#define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */
++#define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */
++#define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */
++#define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */
++#define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */
++#define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */
++#define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */
++#define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */
++#define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */
++#define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */
++#define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */
++#define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */
++#define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */
++#define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */
++#define REG_DE_START_MSB REG(0x00, 0xc5) /* write */
++#define REG_DE_START_LSB REG(0x00, 0xc6) /* write */
++#define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */
++#define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */
++#define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */
++# define TBG_CNTRL_0_FRAME_DIS (1 << 5)
++# define TBG_CNTRL_0_SYNC_MTHD (1 << 6)
++# define TBG_CNTRL_0_SYNC_ONCE (1 << 7)
++#define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */
++# define TBG_CNTRL_1_VH_TGL_0 (1 << 0)
++# define TBG_CNTRL_1_VH_TGL_1 (1 << 1)
++# define TBG_CNTRL_1_VH_TGL_2 (1 << 2)
++# define TBG_CNTRL_1_VHX_EXT_DE (1 << 3)
++# define TBG_CNTRL_1_VHX_EXT_HS (1 << 4)
++# define TBG_CNTRL_1_VHX_EXT_VS (1 << 5)
++# define TBG_CNTRL_1_DWIN_DIS (1 << 6)
++#define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */
++#define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */
++# define HVF_CNTRL_0_SM (1 << 7)
++# define HVF_CNTRL_0_RWB (1 << 6)
++# define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2)
++# define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0)
++#define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */
++# define HVF_CNTRL_1_FOR (1 << 0)
++# define HVF_CNTRL_1_YUVBLK (1 << 1)
++# define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2)
++# define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4)
++# define HVF_CNTRL_1_SEMI_PLANAR (1 << 6)
++#define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */
++
++
++/* Page 02h: PLL settings */
++#define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */
++# define PLL_SERIAL_1_SRL_FDN (1 << 0)
++# define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1)
++# define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6)
++#define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */
++# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0)
++# define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4)
++#define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */
++# define PLL_SERIAL_3_SRL_CCIR (1 << 0)
++# define PLL_SERIAL_3_SRL_DE (1 << 2)
++# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4)
++#define REG_SERIALIZER REG(0x02, 0x03) /* read/write */
++#define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */
++#define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */
++#define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */
++#define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */
++#define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */
++#define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */
++#define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */
++#define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */
++#define REG_SEL_CLK REG(0x02, 0x11) /* read/write */
++# define SEL_CLK_SEL_CLK1 (1 << 0)
++# define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1)
++# define SEL_CLK_ENA_SC_CLK (1 << 3)
++#define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */
++
++
++/* Page 09h: EDID Control */
++#define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */
++/* next 127 successive registers are the EDID block */
++#define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */
++#define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */
++#define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */
++#define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */
++#define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */
++
++
++/* Page 10h: information frames and packets */
++
++
++/* Page 11h: audio settings and content info packets */
++#define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */
++# define AIP_CNTRL_0_RST_FIFO (1 << 0)
++# define AIP_CNTRL_0_SWAP (1 << 1)
++# define AIP_CNTRL_0_LAYOUT (1 << 2)
++# define AIP_CNTRL_0_ACR_MAN (1 << 5)
++# define AIP_CNTRL_0_RST_CTS (1 << 6)
++#define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */
++# define ENC_CNTRL_RST_ENC (1 << 0)
++# define ENC_CNTRL_RST_SEL (1 << 1)
++# define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2)
++
++
++/* Page 12h: HDCP and OTP */
++#define REG_TX3 REG(0x12, 0x9a) /* read/write */
++#define REG_TX33 REG(0x12, 0xb8) /* read/write */
++# define TX33_HDMI (1 << 1)
++
++
++/* Page 13h: Gamut related metadata packets */
++
++
++
++/* CEC registers: (not paged)
++ */
++#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */
++# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
++# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6)
++# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
++# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0)
++#define REG_CEC_RXSHPDLEV 0xfe /* read */
++# define CEC_RXSHPDLEV_RXSENS (1 << 0)
++# define CEC_RXSHPDLEV_HPD (1 << 1)
++
++#define REG_CEC_ENAMODS 0xff /* read/write */
++# define CEC_ENAMODS_DIS_FRO (1 << 6)
++# define CEC_ENAMODS_DIS_CCLK (1 << 5)
++# define CEC_ENAMODS_EN_RXSENS (1 << 2)
++# define CEC_ENAMODS_EN_HDMI (1 << 1)
++# define CEC_ENAMODS_EN_CEC (1 << 0)
++
++
++/* Device versions: */
++#define TDA9989N2 0x0101
++#define TDA19989 0x0201
++#define TDA19989N2 0x0202
++#define TDA19988 0x0301
++
++static void
++cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
++{
++ struct i2c_client *client = to_tda998x_priv(encoder)->cec;
++ uint8_t buf[] = {addr, val};
++ int ret;
++
++ ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
++ if (ret < 0)
++ dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
++}
++
++static uint8_t
++cec_read(struct drm_encoder *encoder, uint8_t addr)
++{
++ struct i2c_client *client = to_tda998x_priv(encoder)->cec;
++ uint8_t val;
++ int ret;
++
++ ret = i2c_master_send(client, &addr, sizeof(addr));
++ if (ret < 0)
++ goto fail;
++
++ ret = i2c_master_recv(client, &val, sizeof(val));
++ if (ret < 0)
++ goto fail;
++
++ return val;
++
++fail:
++ dev_err(&client->dev, "Error %d reading from cec:0x%x\n", ret, addr);
++ return 0;
++}
++
++static void
++set_page(struct drm_encoder *encoder, uint16_t reg)
++{
++ struct tda998x_priv *priv = to_tda998x_priv(encoder);
++
++ if (REG2PAGE(reg) != priv->current_page) {
++ struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
++ uint8_t buf[] = {
++ REG_CURPAGE, REG2PAGE(reg)
++ };
++ int ret = i2c_master_send(client, buf, sizeof(buf));
++ if (ret < 0)
++ dev_err(&client->dev, "Error %d writing to REG_CURPAGE\n", ret);
++
++ priv->current_page = REG2PAGE(reg);
++ }
++}
++
++static int
++reg_read_range(struct drm_encoder *encoder, uint16_t reg, char *buf, int cnt)
++{
++ struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
++ uint8_t addr = REG2ADDR(reg);
++ int ret;
++
++ set_page(encoder, reg);
++
++ ret = i2c_master_send(client, &addr, sizeof(addr));
++ if (ret < 0)
++ goto fail;
++
++ ret = i2c_master_recv(client, buf, cnt);
++ if (ret < 0)
++ goto fail;
++
++ return ret;
++
++fail:
++ dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg);
++ return ret;
++}
++
++static uint8_t
++reg_read(struct drm_encoder *encoder, uint16_t reg)
++{
++ uint8_t val = 0;
++ reg_read_range(encoder, reg, &val, sizeof(val));
++ return val;
++}
++
++static void
++reg_write(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
++{
++ struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
++ uint8_t buf[] = {REG2ADDR(reg), val};
++ int ret;
++
++ set_page(encoder, reg);
++
++ ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
++ if (ret < 0)
++ dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
++}
++
++static void
++reg_write16(struct drm_encoder *encoder, uint16_t reg, uint16_t val)
++{
++ struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
++ uint8_t buf[] = {REG2ADDR(reg), val >> 8, val};
++ int ret;
++
++ set_page(encoder, reg);
++
++ ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
++ if (ret < 0)
++ dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
++}
++
++static void
++reg_set(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
++{
++ reg_write(encoder, reg, reg_read(encoder, reg) | val);
++}
++
++static void
++reg_clear(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
++{
++ reg_write(encoder, reg, reg_read(encoder, reg) & ~val);
++}
++
++static void
++tda998x_reset(struct drm_encoder *encoder)
++{
++ /* reset audio and i2c master: */
++ reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
++ msleep(50);
++ reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
++ msleep(50);
++
++ /* reset transmitter: */
++ reg_set(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
++ reg_clear(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
++
++ /* PLL registers common configuration */
++ reg_write(encoder, REG_PLL_SERIAL_1, 0x00);
++ reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
++ reg_write(encoder, REG_PLL_SERIAL_3, 0x00);
++ reg_write(encoder, REG_SERIALIZER, 0x00);
++ reg_write(encoder, REG_BUFFER_OUT, 0x00);
++ reg_write(encoder, REG_PLL_SCG1, 0x00);
++ reg_write(encoder, REG_AUDIO_DIV, 0x03);
++ reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
++ reg_write(encoder, REG_PLL_SCGN1, 0xfa);
++ reg_write(encoder, REG_PLL_SCGN2, 0x00);
++ reg_write(encoder, REG_PLL_SCGR1, 0x5b);
++ reg_write(encoder, REG_PLL_SCGR2, 0x00);
++ reg_write(encoder, REG_PLL_SCG2, 0x10);
++}
++
++/* DRM encoder functions */
++
++static void
++tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
++{
++}
++
++static void
++tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
++{
++ struct tda998x_priv *priv = to_tda998x_priv(encoder);
++
++ /* we only care about on or off: */
++ if (mode != DRM_MODE_DPMS_ON)
++ mode = DRM_MODE_DPMS_OFF;
++
++ if (mode == priv->dpms)
++ return;
++
++ switch (mode) {
++ case DRM_MODE_DPMS_ON:
++ /* enable audio and video ports */
++ reg_write(encoder, REG_ENA_AP, 0xff);
++ reg_write(encoder, REG_ENA_VP_0, 0xff);
++ reg_write(encoder, REG_ENA_VP_1, 0xff);
++ reg_write(encoder, REG_ENA_VP_2, 0xff);
++ /* set muxing after enabling ports: */
++ reg_write(encoder, REG_VIP_CNTRL_0,
++ VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3));
++ reg_write(encoder, REG_VIP_CNTRL_1,
++ VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1));
++ reg_write(encoder, REG_VIP_CNTRL_2,
++ VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5));
++ break;
++ case DRM_MODE_DPMS_OFF:
++ /* disable audio and video ports */
++ reg_write(encoder, REG_ENA_AP, 0x00);
++ reg_write(encoder, REG_ENA_VP_0, 0x00);
++ reg_write(encoder, REG_ENA_VP_1, 0x00);
++ reg_write(encoder, REG_ENA_VP_2, 0x00);
++ break;
++ }
++
++ priv->dpms = mode;
++}
++
++static void
++tda998x_encoder_save(struct drm_encoder *encoder)
++{
++ DBG("");
++}
++
++static void
++tda998x_encoder_restore(struct drm_encoder *encoder)
++{
++ DBG("");
++}
++
++static bool
++tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
++ const struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ return true;
++}
++
++static int
++tda998x_encoder_mode_valid(struct drm_encoder *encoder,
++ struct drm_display_mode *mode)
++{
++ return MODE_OK;
++}
++
++static void
++tda998x_encoder_mode_set(struct drm_encoder *encoder,
++ struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ struct tda998x_priv *priv = to_tda998x_priv(encoder);
++ uint16_t hs_start, hs_end, line_start, line_end;
++ uint16_t vwin_start, vwin_end, de_start, de_end;
++ uint16_t ref_pix, ref_line, pix_start2;
++ uint8_t reg, div, rep;
++
++ hs_start = mode->hsync_start - mode->hdisplay;
++ hs_end = mode->hsync_end - mode->hdisplay;
++ line_start = 1;
++ line_end = 1 + mode->vsync_end - mode->vsync_start;
++ vwin_start = mode->vtotal - mode->vsync_start;
++ vwin_end = vwin_start + mode->vdisplay;
++ de_start = mode->htotal - mode->hdisplay;
++ de_end = mode->htotal;
++
++ pix_start2 = 0;
++ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
++ pix_start2 = (mode->htotal / 2) + hs_start;
++
++ /* TODO how is this value calculated? It is 2 for all common
++ * formats in the tables in out of tree nxp driver (assuming
++ * I've properly deciphered their byzantine table system)
++ */
++ ref_line = 2;
++
++ /* this might changes for other color formats from the CRTC: */
++ ref_pix = 3 + hs_start;
++
++ div = 148500 / mode->clock;
++
++ DBG("clock=%d, div=%u", mode->clock, div);
++ DBG("hs_start=%u, hs_end=%u, line_start=%u, line_end=%u",
++ hs_start, hs_end, line_start, line_end);
++ DBG("vwin_start=%u, vwin_end=%u, de_start=%u, de_end=%u",
++ vwin_start, vwin_end, de_start, de_end);
++ DBG("ref_line=%u, ref_pix=%u, pix_start2=%u",
++ ref_line, ref_pix, pix_start2);
++
++ /* mute the audio FIFO: */
++ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
++
++ /* set HDMI HDCP mode off: */
++ reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
++ reg_clear(encoder, REG_TX33, TX33_HDMI);
++
++ reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
++ /* no pre-filter or interpolator: */
++ reg_write(encoder, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
++ HVF_CNTRL_0_INTPOL(0));
++ reg_write(encoder, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
++ reg_write(encoder, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
++ VIP_CNTRL_4_BLC(0));
++ reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
++
++ reg_clear(encoder, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
++ reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
++ reg_write(encoder, REG_SERIALIZER, 0);
++ reg_write(encoder, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
++
++ /* TODO enable pixel repeat for pixel rates less than 25Msamp/s */
++ rep = 0;
++ reg_write(encoder, REG_RPT_CNTRL, 0);
++ reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
++ SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
++
++ reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
++ PLL_SERIAL_2_SRL_PR(rep));
++
++ reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, pix_start2);
++ reg_write16(encoder, REG_VS_PIX_END_2_MSB, pix_start2);
++
++ /* set color matrix bypass flag: */
++ reg_set(encoder, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP);
++
++ /* set BIAS tmds value: */
++ reg_write(encoder, REG_ANA_GENERAL, 0x09);
++
++ reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
++
++ reg_write(encoder, REG_VIP_CNTRL_3, 0);
++ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS);
++ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
++ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL);
++
++ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
++ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
++
++ reg_write(encoder, REG_VIDFORMAT, 0x00);
++ reg_write16(encoder, REG_NPIX_MSB, mode->hdisplay - 1);
++ reg_write16(encoder, REG_NLINE_MSB, mode->vdisplay - 1);
++ reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, line_start);
++ reg_write16(encoder, REG_VS_LINE_END_1_MSB, line_end);
++ reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, hs_start);
++ reg_write16(encoder, REG_VS_PIX_END_1_MSB, hs_start);
++ reg_write16(encoder, REG_HS_PIX_START_MSB, hs_start);
++ reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_end);
++ reg_write16(encoder, REG_VWIN_START_1_MSB, vwin_start);
++ reg_write16(encoder, REG_VWIN_END_1_MSB, vwin_end);
++ reg_write16(encoder, REG_DE_START_MSB, de_start);
++ reg_write16(encoder, REG_DE_STOP_MSB, de_end);
++
++ if (priv->rev == TDA19988) {
++ /* let incoming pixels fill the active space (if any) */
++ reg_write(encoder, REG_ENABLE_SPACE, 0x01);
++ }
++
++ reg_write16(encoder, REG_REFPIX_MSB, ref_pix);
++ reg_write16(encoder, REG_REFLINE_MSB, ref_line);
++
++ reg = TBG_CNTRL_1_VHX_EXT_DE |
++ TBG_CNTRL_1_VHX_EXT_HS |
++ TBG_CNTRL_1_VHX_EXT_VS |
++ TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
++ TBG_CNTRL_1_VH_TGL_2;
++ if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC))
++ reg |= TBG_CNTRL_1_VH_TGL_0;
++ reg_set(encoder, REG_TBG_CNTRL_1, reg);
++
++ /* must be last register set: */
++ reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
++}
++
++static enum drm_connector_status
++tda998x_encoder_detect(struct drm_encoder *encoder,
++ struct drm_connector *connector)
++{
++ uint8_t val = cec_read(encoder, REG_CEC_RXSHPDLEV);
++ return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
++ connector_status_disconnected;
++}
++
++static int
++read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
++{
++ uint8_t offset, segptr;
++ int ret, i;
++
++ /* enable EDID read irq: */
++ reg_set(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
++
++ offset = (blk & 1) ? 128 : 0;
++ segptr = blk / 2;
++
++ reg_write(encoder, REG_DDC_ADDR, 0xa0);
++ reg_write(encoder, REG_DDC_OFFS, offset);
++ reg_write(encoder, REG_DDC_SEGM_ADDR, 0x60);
++ reg_write(encoder, REG_DDC_SEGM, segptr);
++
++ /* enable reading EDID: */
++ reg_write(encoder, REG_EDID_CTRL, 0x1);
++
++ /* flag must be cleared by sw: */
++ reg_write(encoder, REG_EDID_CTRL, 0x0);
++
++ /* wait for block read to complete: */
++ for (i = 100; i > 0; i--) {
++ uint8_t val = reg_read(encoder, REG_INT_FLAGS_2);
++ if (val & INT_FLAGS_2_EDID_BLK_RD)
++ break;
++ msleep(1);
++ }
++
++ if (i == 0)
++ return -ETIMEDOUT;
++
++ ret = reg_read_range(encoder, REG_EDID_DATA_0, buf, EDID_LENGTH);
++ if (ret != EDID_LENGTH) {
++ dev_err(encoder->dev->dev, "failed to read edid block %d: %d",
++ blk, ret);
++ return ret;
++ }
++
++ reg_clear(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
++
++ return 0;
++}
++
++static uint8_t *
++do_get_edid(struct drm_encoder *encoder)
++{
++ int j = 0, valid_extensions = 0;
++ uint8_t *block, *new;
++ bool print_bad_edid = drm_debug & DRM_UT_KMS;
++
++ if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
++ return NULL;
++
++ /* base block fetch */
++ if (read_edid_block(encoder, block, 0))
++ goto fail;
++
++ if (!drm_edid_block_valid(block, 0, print_bad_edid))
++ goto fail;
++
++ /* if there's no extensions, we're done */
++ if (block[0x7e] == 0)
++ return block;
++
++ new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
++ if (!new)
++ goto fail;
++ block = new;
++
++ for (j = 1; j <= block[0x7e]; j++) {
++ uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH;
++ if (read_edid_block(encoder, ext_block, j))
++ goto fail;
++
++ if (!drm_edid_block_valid(ext_block, j, print_bad_edid))
++ goto fail;
++
++ valid_extensions++;
++ }
++
++ if (valid_extensions != block[0x7e]) {
++ block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
++ block[0x7e] = valid_extensions;
++ new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
++ if (!new)
++ goto fail;
++ block = new;
++ }
++
++ return block;
++
++fail:
++ dev_warn(encoder->dev->dev, "failed to read EDID\n");
++ kfree(block);
++ return NULL;
++}
++
++static int
++tda998x_encoder_get_modes(struct drm_encoder *encoder,
++ struct drm_connector *connector)
++{
++ struct edid *edid = (struct edid *)do_get_edid(encoder);
++ int n = 0;
++
++ if (edid) {
++ drm_mode_connector_update_edid_property(connector, edid);
++ n = drm_add_edid_modes(connector, edid);
++ kfree(edid);
++ }
++
++ return n;
++}
++
++static int
++tda998x_encoder_create_resources(struct drm_encoder *encoder,
++ struct drm_connector *connector)
++{
++ DBG("");
++ return 0;
++}
++
++static int
++tda998x_encoder_set_property(struct drm_encoder *encoder,
++ struct drm_connector *connector,
++ struct drm_property *property,
++ uint64_t val)
++{
++ DBG("");
++ return 0;
++}
++
++static void
++tda998x_encoder_destroy(struct drm_encoder *encoder)
++{
++ struct tda998x_priv *priv = to_tda998x_priv(encoder);
++ drm_i2c_encoder_destroy(encoder);
++ kfree(priv);
++}
++
++static struct drm_encoder_slave_funcs tda998x_encoder_funcs = {
++ .set_config = tda998x_encoder_set_config,
++ .destroy = tda998x_encoder_destroy,
++ .dpms = tda998x_encoder_dpms,
++ .save = tda998x_encoder_save,
++ .restore = tda998x_encoder_restore,
++ .mode_fixup = tda998x_encoder_mode_fixup,
++ .mode_valid = tda998x_encoder_mode_valid,
++ .mode_set = tda998x_encoder_mode_set,
++ .detect = tda998x_encoder_detect,
++ .get_modes = tda998x_encoder_get_modes,
++ .create_resources = tda998x_encoder_create_resources,
++ .set_property = tda998x_encoder_set_property,
++};
++
++/* I2C driver functions */
++
++static int
++tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
++{
++ return 0;
++}
++
++static int
++tda998x_remove(struct i2c_client *client)
++{
++ return 0;
++}
++
++static int
++tda998x_encoder_init(struct i2c_client *client,
++ struct drm_device *dev,
++ struct drm_encoder_slave *encoder_slave)
++{
++ struct drm_encoder *encoder = &encoder_slave->base;
++ struct tda998x_priv *priv;
++
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->current_page = 0;
++ priv->cec = i2c_new_dummy(client->adapter, 0x34);
++ priv->dpms = DRM_MODE_DPMS_OFF;
++
++ encoder_slave->slave_priv = priv;
++ encoder_slave->slave_funcs = &tda998x_encoder_funcs;
++
++ /* wake up the device: */
++ cec_write(encoder, REG_CEC_ENAMODS,
++ CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
++
++ tda998x_reset(encoder);
++
++ /* read version: */
++ priv->rev = reg_read(encoder, REG_VERSION_LSB) |
++ reg_read(encoder, REG_VERSION_MSB) << 8;
++
++ /* mask off feature bits: */
++ priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
++
++ switch (priv->rev) {
++ case TDA9989N2: dev_info(dev->dev, "found TDA9989 n2"); break;
++ case TDA19989: dev_info(dev->dev, "found TDA19989"); break;
++ case TDA19989N2: dev_info(dev->dev, "found TDA19989 n2"); break;
++ case TDA19988: dev_info(dev->dev, "found TDA19988"); break;
++ default:
++ DBG("found unsupported device: %04x", priv->rev);
++ goto fail;
++ }
++
++ /* after reset, enable DDC: */
++ reg_write(encoder, REG_DDC_DISABLE, 0x00);
++
++ /* set clock on DDC channel: */
++ reg_write(encoder, REG_TX3, 39);
++
++ /* if necessary, disable multi-master: */
++ if (priv->rev == TDA19989)
++ reg_set(encoder, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
++
++ cec_write(encoder, REG_CEC_FRO_IM_CLK_CTRL,
++ CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
++
++ return 0;
++
++fail:
++ /* if encoder_init fails, the encoder slave is never registered,
++ * so cleanup here:
++ */
++ if (priv->cec)
++ i2c_unregister_device(priv->cec);
++ kfree(priv);
++ encoder_slave->slave_priv = NULL;
++ encoder_slave->slave_funcs = NULL;
++ return -ENXIO;
++}
++
++static struct i2c_device_id tda998x_ids[] = {
++ { "tda998x", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, tda998x_ids);
++
++static struct drm_i2c_encoder_driver tda998x_driver = {
++ .i2c_driver = {
++ .probe = tda998x_probe,
++ .remove = tda998x_remove,
++ .driver = {
++ .name = "tda998x",
++ },
++ .id_table = tda998x_ids,
++ },
++ .encoder_init = tda998x_encoder_init,
++};
++
++/* Module initialization */
++
++static int __init
++tda998x_init(void)
++{
++ DBG("");
++ return drm_i2c_encoder_register(THIS_MODULE, &tda998x_driver);
++}
++
++static void __exit
++tda998x_exit(void)
++{
++ DBG("");
++ drm_i2c_encoder_unregister(&tda998x_driver);
++}
++
++MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
++MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
++MODULE_LICENSE("GPL");
++
++module_init(tda998x_init);
++module_exit(tda998x_exit);
diff --git a/patches/linux-3.8.13/0234-drm-tilcdc-add-encoder-slave.patch b/patches/linux-3.8.13/0234-drm-tilcdc-add-encoder-slave.patch
new file mode 100644
index 0000000..77df96a
--- /dev/null
+++ b/patches/linux-3.8.13/0234-drm-tilcdc-add-encoder-slave.patch
@@ -0,0 +1,475 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Tue, 22 Jan 2013 16:02:21 -0600
+Subject: [PATCH] drm/tilcdc: add encoder slave
+
+Add output panel driver for i2c encoder slaves.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/tilcdc/Makefile | 1 +
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 5 +-
+ drivers/gpu/drm/tilcdc/tilcdc_slave.c | 376 +++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_slave.h | 26 +++
+ 4 files changed, 407 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.c
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_slave.h
+
+diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile
+index 1359cc2..aa9097e 100644
+--- a/drivers/gpu/drm/tilcdc/Makefile
++++ b/drivers/gpu/drm/tilcdc/Makefile
+@@ -3,6 +3,7 @@ ccflags-y := -Iinclude/drm -Werror
+ tilcdc-y := \
+ tilcdc_crtc.o \
+ tilcdc_tfp410.o \
++ tilcdc_slave.o \
+ tilcdc_drv.o
+
+ obj-$(CONFIG_DRM_TILCDC) += tilcdc.o
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index f6defbf..25f3add 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -20,6 +20,7 @@
+ #include "tilcdc_drv.h"
+ #include "tilcdc_regs.h"
+ #include "tilcdc_tfp410.h"
++#include "tilcdc_slave.h"
+
+ #include "drm_fb_helper.h"
+
+@@ -587,6 +588,7 @@ static int __init tilcdc_drm_init(void)
+ {
+ DBG("init");
+ tilcdc_tfp410_init();
++ tilcdc_slave_init();
+ return platform_driver_register(&tilcdc_platform_driver);
+ }
+
+@@ -594,10 +596,11 @@ static void __exit tilcdc_drm_fini(void)
+ {
+ DBG("fini");
+ tilcdc_tfp410_fini();
++ tilcdc_slave_fini();
+ platform_driver_unregister(&tilcdc_platform_driver);
+ }
+
+-module_init(tilcdc_drm_init);
++late_initcall(tilcdc_drm_init);
+ module_exit(tilcdc_drm_fini);
+
+ MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+new file mode 100644
+index 0000000..7d05c3d
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+@@ -0,0 +1,376 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/i2c.h>
++#include <linux/of_i2c.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <drm/drm_encoder_slave.h>
++
++#include "tilcdc_drv.h"
++
++struct slave_module {
++ struct tilcdc_module base;
++ struct i2c_adapter *i2c;
++};
++#define to_slave_module(x) container_of(x, struct slave_module, base)
++
++static const struct tilcdc_panel_info slave_info = {
++ .bpp = 16,
++ .ac_bias = 255,
++ .ac_bias_intrpt = 0,
++ .dma_burst_sz = 16,
++ .fdd = 0x80,
++ .tft_alt_mode = 0,
++ .sync_edge = 0,
++ .sync_ctrl = 1,
++ .raster_order = 0,
++};
++
++
++/*
++ * Encoder:
++ */
++
++struct slave_encoder {
++ struct drm_encoder_slave base;
++ struct slave_module *mod;
++};
++#define to_slave_encoder(x) container_of(to_encoder_slave(x), struct slave_encoder, base)
++
++static inline struct drm_encoder_slave_funcs *
++get_slave_funcs(struct drm_encoder *enc)
++{
++ return to_encoder_slave(enc)->slave_funcs;
++}
++
++static void slave_encoder_destroy(struct drm_encoder *encoder)
++{
++ struct slave_encoder *slave_encoder = to_slave_encoder(encoder);
++ if (get_slave_funcs(encoder))
++ get_slave_funcs(encoder)->destroy(encoder);
++ drm_encoder_cleanup(encoder);
++ kfree(slave_encoder);
++}
++
++static void slave_encoder_prepare(struct drm_encoder *encoder)
++{
++ drm_i2c_encoder_prepare(encoder);
++ tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info);
++}
++
++static const struct drm_encoder_funcs slave_encoder_funcs = {
++ .destroy = slave_encoder_destroy,
++};
++
++static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = {
++ .dpms = drm_i2c_encoder_dpms,
++ .mode_fixup = drm_i2c_encoder_mode_fixup,
++ .prepare = slave_encoder_prepare,
++ .commit = drm_i2c_encoder_commit,
++ .mode_set = drm_i2c_encoder_mode_set,
++ .save = drm_i2c_encoder_save,
++ .restore = drm_i2c_encoder_restore,
++};
++
++static const struct i2c_board_info info = {
++ I2C_BOARD_INFO("tda998x", 0x70)
++};
++
++static struct drm_encoder *slave_encoder_create(struct drm_device *dev,
++ struct slave_module *mod)
++{
++ struct slave_encoder *slave_encoder;
++ struct drm_encoder *encoder;
++ int ret;
++
++ slave_encoder = kzalloc(sizeof(*slave_encoder), GFP_KERNEL);
++ if (!slave_encoder) {
++ dev_err(dev->dev, "allocation failed\n");
++ return NULL;
++ }
++
++ slave_encoder->mod = mod;
++
++ encoder = &slave_encoder->base.base;
++ encoder->possible_crtcs = 1;
++
++ ret = drm_encoder_init(dev, encoder, &slave_encoder_funcs,
++ DRM_MODE_ENCODER_TMDS);
++ if (ret)
++ goto fail;
++
++ drm_encoder_helper_add(encoder, &slave_encoder_helper_funcs);
++
++ ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), mod->i2c, &info);
++ if (ret)
++ goto fail;
++
++ return encoder;
++
++fail:
++ slave_encoder_destroy(encoder);
++ return NULL;
++}
++
++/*
++ * Connector:
++ */
++
++struct slave_connector {
++ struct drm_connector base;
++
++ struct drm_encoder *encoder; /* our connected encoder */
++ struct slave_module *mod;
++};
++#define to_slave_connector(x) container_of(x, struct slave_connector, base)
++
++static void slave_connector_destroy(struct drm_connector *connector)
++{
++ struct slave_connector *slave_connector = to_slave_connector(connector);
++ drm_connector_cleanup(connector);
++ kfree(slave_connector);
++}
++
++static enum drm_connector_status slave_connector_detect(
++ struct drm_connector *connector,
++ bool force)
++{
++ struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
++ return get_slave_funcs(encoder)->detect(encoder, connector);
++}
++
++static int slave_connector_get_modes(struct drm_connector *connector)
++{
++ struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
++ return get_slave_funcs(encoder)->get_modes(encoder, connector);
++}
++
++static int slave_connector_mode_valid(struct drm_connector *connector,
++ struct drm_display_mode *mode)
++{
++ struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
++ struct tilcdc_drm_private *priv = connector->dev->dev_private;
++ int ret;
++
++ ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
++ if (ret != MODE_OK)
++ return ret;
++
++ return get_slave_funcs(encoder)->mode_valid(encoder, mode);
++}
++
++static struct drm_encoder *slave_connector_best_encoder(
++ struct drm_connector *connector)
++{
++ struct slave_connector *slave_connector = to_slave_connector(connector);
++ return slave_connector->encoder;
++}
++
++static int slave_connector_set_property(struct drm_connector *connector,
++ struct drm_property *property, uint64_t value)
++{
++ struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
++ return get_slave_funcs(encoder)->set_property(encoder,
++ connector, property, value);
++}
++
++static const struct drm_connector_funcs slave_connector_funcs = {
++ .destroy = slave_connector_destroy,
++ .dpms = drm_helper_connector_dpms,
++ .detect = slave_connector_detect,
++ .fill_modes = drm_helper_probe_single_connector_modes,
++ .set_property = slave_connector_set_property,
++};
++
++static const struct drm_connector_helper_funcs slave_connector_helper_funcs = {
++ .get_modes = slave_connector_get_modes,
++ .mode_valid = slave_connector_mode_valid,
++ .best_encoder = slave_connector_best_encoder,
++};
++
++static struct drm_connector *slave_connector_create(struct drm_device *dev,
++ struct slave_module *mod, struct drm_encoder *encoder)
++{
++ struct slave_connector *slave_connector;
++ struct drm_connector *connector;
++ int ret;
++
++ slave_connector = kzalloc(sizeof(*slave_connector), GFP_KERNEL);
++ if (!slave_connector) {
++ dev_err(dev->dev, "allocation failed\n");
++ return NULL;
++ }
++
++ slave_connector->encoder = encoder;
++ slave_connector->mod = mod;
++
++ connector = &slave_connector->base;
++
++ drm_connector_init(dev, connector, &slave_connector_funcs,
++ DRM_MODE_CONNECTOR_HDMIA);
++ drm_connector_helper_add(connector, &slave_connector_helper_funcs);
++
++ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
++ DRM_CONNECTOR_POLL_DISCONNECT;
++
++ connector->interlace_allowed = 0;
++ connector->doublescan_allowed = 0;
++
++ get_slave_funcs(encoder)->create_resources(encoder, connector);
++
++ ret = drm_mode_connector_attach_encoder(connector, encoder);
++ if (ret)
++ goto fail;
++
++ drm_sysfs_connector_add(connector);
++
++ return connector;
++
++fail:
++ slave_connector_destroy(connector);
++ return NULL;
++}
++
++/*
++ * Module:
++ */
++
++static int slave_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
++{
++ struct slave_module *slave_mod = to_slave_module(mod);
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ struct drm_encoder *encoder;
++ struct drm_connector *connector;
++
++ encoder = slave_encoder_create(dev, slave_mod);
++ if (!encoder)
++ return -ENOMEM;
++
++ connector = slave_connector_create(dev, slave_mod, encoder);
++ if (!connector)
++ return -ENOMEM;
++
++ priv->encoders[priv->num_encoders++] = encoder;
++ priv->connectors[priv->num_connectors++] = connector;
++
++ return 0;
++}
++
++static void slave_destroy(struct tilcdc_module *mod)
++{
++ struct slave_module *slave_mod = to_slave_module(mod);
++
++ tilcdc_module_cleanup(mod);
++ kfree(slave_mod);
++}
++
++static const struct tilcdc_module_ops slave_module_ops = {
++ .modeset_init = slave_modeset_init,
++ .destroy = slave_destroy,
++};
++
++/*
++ * Device:
++ */
++
++static struct of_device_id slave_of_match[];
++
++static int slave_probe(struct platform_device *pdev)
++{
++ struct device_node *node = pdev->dev.of_node;
++ struct device_node *i2c_node;
++ struct slave_module *slave_mod;
++ struct tilcdc_module *mod;
++ struct pinctrl *pinctrl;
++ uint32_t i2c_phandle;
++ int ret = -EINVAL;
++
++ /* bail out early if no DT data: */
++ if (!node) {
++ dev_err(&pdev->dev, "device-tree data is missing\n");
++ return -ENXIO;
++ }
++
++ slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL);
++ if (!slave_mod)
++ return -ENOMEM;
++
++ mod = &slave_mod->base;
++
++ tilcdc_module_init(mod, "slave", &slave_module_ops);
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "pins are not configured\n");
++
++ if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
++ dev_err(&pdev->dev, "could not get i2c bus phandle\n");
++ goto fail;
++ }
++
++ i2c_node = of_find_node_by_phandle(i2c_phandle);
++ if (!i2c_node) {
++ dev_err(&pdev->dev, "could not get i2c bus node\n");
++ goto fail;
++ }
++
++ slave_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
++ if (!slave_mod->i2c) {
++ dev_err(&pdev->dev, "could not get i2c\n");
++ goto fail;
++ }
++
++ of_node_put(i2c_node);
++
++ return 0;
++
++fail:
++ slave_destroy(mod);
++ return ret;
++}
++
++static int slave_remove(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static struct of_device_id slave_of_match[] = {
++ { .compatible = "tilcdc,slave", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, slave_of_match);
++
++struct platform_driver slave_driver = {
++ .probe = slave_probe,
++ .remove = slave_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "slave",
++ .of_match_table = slave_of_match,
++ },
++};
++
++int __init tilcdc_slave_init(void)
++{
++ return platform_driver_register(&slave_driver);
++}
++
++void __exit tilcdc_slave_fini(void)
++{
++ platform_driver_unregister(&slave_driver);
++}
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.h b/drivers/gpu/drm/tilcdc/tilcdc_slave.h
+new file mode 100644
+index 0000000..2f85048
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.h
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __TILCDC_SLAVE_H__
++#define __TILCDC_SLAVE_H__
++
++/* sub-module for i2c slave encoder output */
++
++int tilcdc_slave_init(void);
++void tilcdc_slave_fini(void);
++
++#endif /* __TILCDC_SLAVE_H__ */
diff --git a/patches/linux-3.8.13/0235-drm-tilcdc-add-support-for-LCD-panels-v5.patch b/patches/linux-3.8.13/0235-drm-tilcdc-add-support-for-LCD-panels-v5.patch
new file mode 100644
index 0000000..600c74d
--- /dev/null
+++ b/patches/linux-3.8.13/0235-drm-tilcdc-add-support-for-LCD-panels-v5.patch
@@ -0,0 +1,557 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Tue, 18 Dec 2012 17:34:16 -0600
+Subject: [PATCH] drm/tilcdc: add support for LCD panels (v5)
+
+Add an output panel driver for LCD panels. Tested with LCD3 cape on
+beaglebone.
+
+v1: original
+v2: s/of_find_node_by_name()/of_get_child_by_name()/ from Pantelis
+ Antoniou
+v3: add backlight support
+v4: rebase to latest of video timing helpers
+v5: remove some unneeded fields from panel-info struct
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+---
+ drivers/gpu/drm/tilcdc/Kconfig | 5 +-
+ drivers/gpu/drm/tilcdc/Makefile | 1 +
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 3 +
+ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 436 +++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_panel.h | 26 ++
+ 5 files changed, 470 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.c
+ create mode 100644 drivers/gpu/drm/tilcdc/tilcdc_panel.h
+
+diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
+index ee9b592..d2928c7 100644
+--- a/drivers/gpu/drm/tilcdc/Kconfig
++++ b/drivers/gpu/drm/tilcdc/Kconfig
+@@ -1,9 +1,12 @@
+ config DRM_TILCDC
+ tristate "DRM Support for TI LCDC Display Controller"
+- depends on DRM && OF
++ depends on DRM && OF && BACKLIGHT_LCD_SUPPORT
+ select DRM_KMS_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_GEM_CMA_HELPER
++ select OF_VIDEOMODE
++ select OF_DISPLAY_TIMING
++ select BACKLIGHT_CLASS_DEVICE
+ help
+ Choose this option if you have an TI SoC with LCDC display
+ controller, for example AM33xx in beagle-bone, DA8xx, or
+diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile
+index aa9097e..deda656 100644
+--- a/drivers/gpu/drm/tilcdc/Makefile
++++ b/drivers/gpu/drm/tilcdc/Makefile
+@@ -4,6 +4,7 @@ tilcdc-y := \
+ tilcdc_crtc.o \
+ tilcdc_tfp410.o \
+ tilcdc_slave.o \
++ tilcdc_panel.o \
+ tilcdc_drv.o
+
+ obj-$(CONFIG_DRM_TILCDC) += tilcdc.o
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index 25f3add..c5b592d 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -21,6 +21,7 @@
+ #include "tilcdc_regs.h"
+ #include "tilcdc_tfp410.h"
+ #include "tilcdc_slave.h"
++#include "tilcdc_panel.h"
+
+ #include "drm_fb_helper.h"
+
+@@ -589,6 +590,7 @@ static int __init tilcdc_drm_init(void)
+ DBG("init");
+ tilcdc_tfp410_init();
+ tilcdc_slave_init();
++ tilcdc_panel_init();
+ return platform_driver_register(&tilcdc_platform_driver);
+ }
+
+@@ -597,6 +599,7 @@ static void __exit tilcdc_drm_fini(void)
+ DBG("fini");
+ tilcdc_tfp410_fini();
+ tilcdc_slave_fini();
++ tilcdc_panel_fini();
+ platform_driver_unregister(&tilcdc_platform_driver);
+ }
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+new file mode 100644
+index 0000000..d1463f5
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+@@ -0,0 +1,436 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/backlight.h>
++#include <video/display_timing.h>
++#include <video/of_display_timing.h>
++#include <video/videomode.h>
++
++#include "tilcdc_drv.h"
++
++struct panel_module {
++ struct tilcdc_module base;
++ struct tilcdc_panel_info *info;
++ struct display_timings *timings;
++ struct backlight_device *backlight;
++};
++#define to_panel_module(x) container_of(x, struct panel_module, base)
++
++
++/*
++ * Encoder:
++ */
++
++struct panel_encoder {
++ struct drm_encoder base;
++ struct panel_module *mod;
++};
++#define to_panel_encoder(x) container_of(x, struct panel_encoder, base)
++
++
++static void panel_encoder_destroy(struct drm_encoder *encoder)
++{
++ struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
++ drm_encoder_cleanup(encoder);
++ kfree(panel_encoder);
++}
++
++static void panel_encoder_dpms(struct drm_encoder *encoder, int mode)
++{
++ struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
++ struct backlight_device *backlight = panel_encoder->mod->backlight;
++
++ if (!backlight)
++ return;
++
++ backlight->props.power = mode == DRM_MODE_DPMS_ON
++ ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
++ backlight_update_status(backlight);
++}
++
++static bool panel_encoder_mode_fixup(struct drm_encoder *encoder,
++ const struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ /* nothing needed */
++ return true;
++}
++
++static void panel_encoder_prepare(struct drm_encoder *encoder)
++{
++ struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
++ panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
++ tilcdc_crtc_set_panel_info(encoder->crtc, panel_encoder->mod->info);
++}
++
++static void panel_encoder_commit(struct drm_encoder *encoder)
++{
++ panel_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
++}
++
++static void panel_encoder_mode_set(struct drm_encoder *encoder,
++ struct drm_display_mode *mode,
++ struct drm_display_mode *adjusted_mode)
++{
++ /* nothing needed */
++}
++
++static const struct drm_encoder_funcs panel_encoder_funcs = {
++ .destroy = panel_encoder_destroy,
++};
++
++static const struct drm_encoder_helper_funcs panel_encoder_helper_funcs = {
++ .dpms = panel_encoder_dpms,
++ .mode_fixup = panel_encoder_mode_fixup,
++ .prepare = panel_encoder_prepare,
++ .commit = panel_encoder_commit,
++ .mode_set = panel_encoder_mode_set,
++};
++
++static struct drm_encoder *panel_encoder_create(struct drm_device *dev,
++ struct panel_module *mod)
++{
++ struct panel_encoder *panel_encoder;
++ struct drm_encoder *encoder;
++ int ret;
++
++ panel_encoder = kzalloc(sizeof(*panel_encoder), GFP_KERNEL);
++ if (!panel_encoder) {
++ dev_err(dev->dev, "allocation failed\n");
++ return NULL;
++ }
++
++ panel_encoder->mod = mod;
++
++ encoder = &panel_encoder->base;
++ encoder->possible_crtcs = 1;
++
++ ret = drm_encoder_init(dev, encoder, &panel_encoder_funcs,
++ DRM_MODE_ENCODER_LVDS);
++ if (ret < 0)
++ goto fail;
++
++ drm_encoder_helper_add(encoder, &panel_encoder_helper_funcs);
++
++ return encoder;
++
++fail:
++ panel_encoder_destroy(encoder);
++ return NULL;
++}
++
++/*
++ * Connector:
++ */
++
++struct panel_connector {
++ struct drm_connector base;
++
++ struct drm_encoder *encoder; /* our connected encoder */
++ struct panel_module *mod;
++};
++#define to_panel_connector(x) container_of(x, struct panel_connector, base)
++
++
++static void panel_connector_destroy(struct drm_connector *connector)
++{
++ struct panel_connector *panel_connector = to_panel_connector(connector);
++ drm_connector_cleanup(connector);
++ kfree(panel_connector);
++}
++
++static enum drm_connector_status panel_connector_detect(
++ struct drm_connector *connector,
++ bool force)
++{
++ return connector_status_connected;
++}
++
++static int panel_connector_get_modes(struct drm_connector *connector)
++{
++ struct drm_device *dev = connector->dev;
++ struct panel_connector *panel_connector = to_panel_connector(connector);
++ struct display_timings *timings = panel_connector->mod->timings;
++ int i;
++
++ for (i = 0; i < timings->num_timings; i++) {
++ struct drm_display_mode *mode = drm_mode_create(dev);
++ struct videomode vm;
++
++ if (videomode_from_timing(timings, &vm, i))
++ break;
++
++ drm_display_mode_from_videomode(&vm, mode);
++
++ mode->type = DRM_MODE_TYPE_DRIVER;
++
++ if (timings->native_mode == i)
++ mode->type |= DRM_MODE_TYPE_PREFERRED;
++
++ drm_mode_set_name(mode);
++ drm_mode_probed_add(connector, mode);
++ }
++
++ return i;
++}
++
++static int panel_connector_mode_valid(struct drm_connector *connector,
++ struct drm_display_mode *mode)
++{
++ struct tilcdc_drm_private *priv = connector->dev->dev_private;
++ /* our only constraints are what the crtc can generate: */
++ return tilcdc_crtc_mode_valid(priv->crtc, mode);
++}
++
++static struct drm_encoder *panel_connector_best_encoder(
++ struct drm_connector *connector)
++{
++ struct panel_connector *panel_connector = to_panel_connector(connector);
++ return panel_connector->encoder;
++}
++
++static const struct drm_connector_funcs panel_connector_funcs = {
++ .destroy = panel_connector_destroy,
++ .dpms = drm_helper_connector_dpms,
++ .detect = panel_connector_detect,
++ .fill_modes = drm_helper_probe_single_connector_modes,
++};
++
++static const struct drm_connector_helper_funcs panel_connector_helper_funcs = {
++ .get_modes = panel_connector_get_modes,
++ .mode_valid = panel_connector_mode_valid,
++ .best_encoder = panel_connector_best_encoder,
++};
++
++static struct drm_connector *panel_connector_create(struct drm_device *dev,
++ struct panel_module *mod, struct drm_encoder *encoder)
++{
++ struct panel_connector *panel_connector;
++ struct drm_connector *connector;
++ int ret;
++
++ panel_connector = kzalloc(sizeof(*panel_connector), GFP_KERNEL);
++ if (!panel_connector) {
++ dev_err(dev->dev, "allocation failed\n");
++ return NULL;
++ }
++
++ panel_connector->encoder = encoder;
++ panel_connector->mod = mod;
++
++ connector = &panel_connector->base;
++
++ drm_connector_init(dev, connector, &panel_connector_funcs,
++ DRM_MODE_CONNECTOR_LVDS);
++ drm_connector_helper_add(connector, &panel_connector_helper_funcs);
++
++ connector->interlace_allowed = 0;
++ connector->doublescan_allowed = 0;
++
++ ret = drm_mode_connector_attach_encoder(connector, encoder);
++ if (ret)
++ goto fail;
++
++ drm_sysfs_connector_add(connector);
++
++ return connector;
++
++fail:
++ panel_connector_destroy(connector);
++ return NULL;
++}
++
++/*
++ * Module:
++ */
++
++static int panel_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
++{
++ struct panel_module *panel_mod = to_panel_module(mod);
++ struct tilcdc_drm_private *priv = dev->dev_private;
++ struct drm_encoder *encoder;
++ struct drm_connector *connector;
++
++ encoder = panel_encoder_create(dev, panel_mod);
++ if (!encoder)
++ return -ENOMEM;
++
++ connector = panel_connector_create(dev, panel_mod, encoder);
++ if (!connector)
++ return -ENOMEM;
++
++ priv->encoders[priv->num_encoders++] = encoder;
++ priv->connectors[priv->num_connectors++] = connector;
++
++ return 0;
++}
++
++static void panel_destroy(struct tilcdc_module *mod)
++{
++ struct panel_module *panel_mod = to_panel_module(mod);
++
++ if (panel_mod->timings) {
++ display_timings_release(panel_mod->timings);
++ kfree(panel_mod->timings);
++ }
++
++ tilcdc_module_cleanup(mod);
++ kfree(panel_mod->info);
++ kfree(panel_mod);
++}
++
++static const struct tilcdc_module_ops panel_module_ops = {
++ .modeset_init = panel_modeset_init,
++ .destroy = panel_destroy,
++};
++
++/*
++ * Device:
++ */
++
++/* maybe move this somewhere common if it is needed by other outputs? */
++static struct tilcdc_panel_info * of_get_panel_info(struct device_node *np)
++{
++ struct device_node *info_np;
++ struct tilcdc_panel_info *info;
++ int ret = 0;
++
++ if (!np) {
++ pr_err("%s: no devicenode given\n", __func__);
++ return NULL;
++ }
++
++ info_np = of_get_child_by_name(np, "panel-info");
++ if (!info_np) {
++ pr_err("%s: could not find panel-info node\n", __func__);
++ return NULL;
++ }
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (!info) {
++ pr_err("%s: allocation failed\n", __func__);
++ return NULL;
++ }
++
++ ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias);
++ ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt);
++ ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz);
++ ret |= of_property_read_u32(info_np, "bpp", &info->bpp);
++ ret |= of_property_read_u32(info_np, "fdd", &info->fdd);
++ ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge);
++ ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl);
++ ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order);
++ ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th);
++
++ /* optional: */
++ info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode");
++ info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk");
++
++ if (ret) {
++ pr_err("%s: error reading panel-info properties\n", __func__);
++ kfree(info);
++ return NULL;
++ }
++
++ return info;
++}
++
++static struct of_device_id panel_of_match[];
++
++static int panel_probe(struct platform_device *pdev)
++{
++ struct device_node *node = pdev->dev.of_node;
++ struct panel_module *panel_mod;
++ struct tilcdc_module *mod;
++ struct pinctrl *pinctrl;
++ int ret = -EINVAL;
++
++
++ /* bail out early if no DT data: */
++ if (!node) {
++ dev_err(&pdev->dev, "device-tree data is missing\n");
++ return -ENXIO;
++ }
++
++ panel_mod = kzalloc(sizeof(*panel_mod), GFP_KERNEL);
++ if (!panel_mod)
++ return -ENOMEM;
++
++ mod = &panel_mod->base;
++
++ tilcdc_module_init(mod, "panel", &panel_module_ops);
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "pins are not configured\n");
++
++
++ panel_mod->timings = of_get_display_timings(node);
++ if (!panel_mod->timings) {
++ dev_err(&pdev->dev, "could not get panel timings\n");
++ goto fail;
++ }
++
++ panel_mod->info = of_get_panel_info(node);
++ if (!panel_mod->info) {
++ dev_err(&pdev->dev, "could not get panel info\n");
++ goto fail;
++ }
++
++ panel_mod->backlight = of_find_backlight_by_node(node);
++ if (panel_mod->backlight)
++ dev_info(&pdev->dev, "found backlight\n");
++
++ return 0;
++
++fail:
++ panel_destroy(mod);
++ return ret;
++}
++
++static int panel_remove(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static struct of_device_id panel_of_match[] = {
++ { .compatible = "tilcdc,panel", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, panel_of_match);
++
++struct platform_driver panel_driver = {
++ .probe = panel_probe,
++ .remove = panel_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "panel",
++ .of_match_table = panel_of_match,
++ },
++};
++
++int __init tilcdc_panel_init(void)
++{
++ return platform_driver_register(&panel_driver);
++}
++
++void __exit tilcdc_panel_fini(void)
++{
++ platform_driver_unregister(&panel_driver);
++}
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.h b/drivers/gpu/drm/tilcdc/tilcdc_panel.h
+new file mode 100644
+index 0000000..7db40aa
+--- /dev/null
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.h
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (C) 2012 Texas Instruments
++ * Author: Rob Clark <robdclark@gmail.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __TILCDC_PANEL_H__
++#define __TILCDC_PANEL_H__
++
++/* sub-module for generic lcd panel output */
++
++int tilcdc_panel_init(void);
++void tilcdc_panel_fini(void);
++
++#endif /* __TILCDC_PANEL_H__ */
diff --git a/patches/linux-3.8.13/0236-drm-lcdc-Power-control-GPIO-support.patch b/patches/linux-3.8.13/0236-drm-lcdc-Power-control-GPIO-support.patch
new file mode 100644
index 0000000..7db0077
--- /dev/null
+++ b/patches/linux-3.8.13/0236-drm-lcdc-Power-control-GPIO-support.patch
@@ -0,0 +1,62 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 9 Jan 2013 16:31:29 +0200
+Subject: [PATCH] drm: lcdc: Power control GPIO support
+
+A large number of LCDC designs use a GPIO pin for power control.
+Implement it trivialy.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index c5b592d..91e8ed2 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -25,6 +25,8 @@
+
+ #include "drm_fb_helper.h"
+
++#include <linux/of_gpio.h>
++
+ static LIST_HEAD(module_list);
+
+ void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
+@@ -158,7 +160,9 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+ struct device_node *node = pdev->dev.of_node;
+ struct tilcdc_drm_private *priv;
+ struct resource *res;
+- int ret;
++ enum of_gpio_flags ofgpioflags;
++ unsigned long gpioflags;
++ int gpio, ret;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+@@ -198,6 +202,25 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+ goto fail;
+ }
+
++ /* some devices have a power gpio control */
++ gpio = of_get_named_gpio_flags(pdev->dev.of_node, "ti,power-gpio",
++ 0, &ofgpioflags);
++ if (IS_ERR_VALUE(gpio)) {
++ dev_info(&pdev->dev, "No power control GPIO\n");
++ } else {
++ gpioflags = GPIOF_DIR_OUT;
++ if (ofgpioflags & OF_GPIO_ACTIVE_LOW)
++ gpioflags |= GPIOF_INIT_LOW;
++ else
++ gpioflags |= GPIOF_INIT_HIGH;
++ ret = devm_gpio_request_one(&pdev->dev, gpio,
++ gpioflags, "lcdc_drv:PDN");
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to request power gpio\n");
++ goto fail;
++ }
++ }
++
+ #ifdef CONFIG_CPU_FREQ
+ priv->lcd_fck_rate = clk_get_rate(priv->clk);
+ priv->freq_transition.notifier_call = cpufreq_transition;
diff --git a/patches/linux-3.8.13/0237-drm-tilcdc-Fix-scheduling-while-atomic-from-irq-hand.patch b/patches/linux-3.8.13/0237-drm-tilcdc-Fix-scheduling-while-atomic-from-irq-hand.patch
new file mode 100644
index 0000000..11bba34
--- /dev/null
+++ b/patches/linux-3.8.13/0237-drm-tilcdc-Fix-scheduling-while-atomic-from-irq-hand.patch
@@ -0,0 +1,53 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 3 Jun 2013 17:57:18 +0300
+Subject: [PATCH] drm: tilcdc: Fix scheduling while atomic from irq handler.
+
+Fix the crash by not making pm_runtime calls while in the irq.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 5dd3c7d..9f10f05 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -66,7 +66,6 @@ static void set_scanout(struct drm_crtc *crtc, int n)
+ struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+
+- pm_runtime_get_sync(dev->dev);
+ tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
+ tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
+ if (tilcdc_crtc->scanout[n]) {
+@@ -82,7 +81,6 @@ static void set_scanout(struct drm_crtc *crtc, int n)
+ tilcdc_crtc->scanout[n] = crtc->fb;
+ drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
+ tilcdc_crtc->dirty &= ~stat[n];
+- pm_runtime_put_sync(dev->dev);
+ }
+
+ static void update_scanout(struct drm_crtc *crtc)
+@@ -165,7 +163,9 @@ static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
+
+ crtc->fb = fb;
+ tilcdc_crtc->event = event;
++ pm_runtime_get_sync(dev->dev);
+ update_scanout(crtc);
++ pm_runtime_put_sync(dev->dev);
+
+ return 0;
+ }
+@@ -380,7 +380,11 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+ {
++ struct drm_device *dev = crtc->dev;
++
++ pm_runtime_get_sync(dev->dev);
+ update_scanout(crtc);
++ pm_runtime_put_sync(dev->dev);
+ return 0;
+ }
+
diff --git a/patches/linux-3.8.13/0238-add-dvi-pinmuxes-to-am33xx.dtsi.patch b/patches/linux-3.8.13/0238-add-dvi-pinmuxes-to-am33xx.dtsi.patch
new file mode 100644
index 0000000..01405b4
--- /dev/null
+++ b/patches/linux-3.8.13/0238-add-dvi-pinmuxes-to-am33xx.dtsi.patch
@@ -0,0 +1,74 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 21 Dec 2012 09:08:49 +0100
+Subject: [PATCH] add dvi pinmuxes to am33xx.dtsi
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 54 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 6dcd42a..1b91637 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -67,6 +67,60 @@
+ #size-cells = <0>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x7f>;
++
++ 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 */
++ >;
++ };
+ };
+
+ /*
diff --git a/patches/linux-3.8.13/0239-add-defconfig-file-to-use-as-.config.patch b/patches/linux-3.8.13/0239-add-defconfig-file-to-use-as-.config.patch
new file mode 100644
index 0000000..d4c4b14
--- /dev/null
+++ b/patches/linux-3.8.13/0239-add-defconfig-file-to-use-as-.config.patch
@@ -0,0 +1,4013 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 28 Dec 2012 14:41:10 +0100
+Subject: [PATCH] add 'defconfig' file to use as .config
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ defconfig | 3997 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 3997 insertions(+)
+ create mode 100644 defconfig
+
+diff --git a/defconfig b/defconfig
+new file mode 100644
+index 0000000..5eb94b7
+--- /dev/null
++++ b/defconfig
+@@ -0,0 +1,3997 @@
++#
++# Automatically generated file; DO NOT EDIT.
++# Linux/arm 3.8.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_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_GENERIC_BUG=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_HAVE_IRQ_WORK=y
++CONFIG_IRQ_WORK=y
++CONFIG_BUILDTIME_EXTABLE_SORT=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_RCU_NOCB_CPU 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_HAVE_ARCH_SECCOMP_FILTER=y
++CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
++CONFIG_MODULES_USE_ELF_REL=y
++CONFIG_CLONE_BACKWARDS=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_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_SINGLE 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_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
++# CONFIG_ARCH_VT8500 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_MULTIPLE_DRIVERS=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=y
++# 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_HAVE_NET_DSA=y
++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_DAT=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_GRCAN=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_KVASER_USB=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=y
++# 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_DENALI 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_CADENCE=y
++# CONFIG_ARM_AT91_ETHER is not set
++# CONFIG_MACB is not set
++CONFIG_NET_VENDOR_BROADCOM=y
++# CONFIG_B44 is not set
++# CONFIG_NET_CALXEDA_XGMAC is not set
++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_MVMDIO=m
++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_TI_CPTS 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_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_CDC_MBIM=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_CARDS=m
++# CONFIG_ATH_DEBUG is not set
++# CONFIG_ATH9K is not set
++# CONFIG_ATH9K_HTC is not set
++# CONFIG_CARL9170 is not set
++# CONFIG_ATH6KL is not set
++# CONFIG_AR5523 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=y
++CONFIG_WL1251=m
++CONFIG_WL1251_SPI=m
++CONFIG_WL1251_SDIO=m
++CONFIG_WL12XX=m
++CONFIG_WL18XX=m
++CONFIG_WLCORE=m
++CONFIG_WLCORE_SPI=m
++CONFIG_WLCORE_SDIO=m
++CONFIG_WL12XX_PLATFORM_DATA=y
++# 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=m
++# 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_PWM_BEEPER=m
++# 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_SERIO_ARC_PS2 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_SERIAL_ARC 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=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_CBUS_GPIO is not set
++# 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=y
++# CONFIG_PPS_DEBUG is not set
++
++#
++# PPS clients support
++#
++# CONFIG_PPS_CLIENT_KTIMER is not set
++# CONFIG_PPS_CLIENT_LDISC is not set
++# CONFIG_PPS_CLIENT_GPIO is not set
++
++#
++# PPS generators support
++#
++
++#
++# PTP clock support
++#
++CONFIG_PTP_1588_CLOCK=y
++
++#
++# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
++#
++# CONFIG_PTP_1588_CLOCK_PCH is not set
++CONFIG_PINCTRL=y
++
++#
++# Pin controllers
++#
++CONFIG_PINMUX=y
++CONFIG_PINCONF=y
++# CONFIG_DEBUG_PINCTRL is not set
++CONFIG_PINCTRL_SINGLE=y
++# CONFIG_PINCTRL_EXYNOS4 is not set
++# CONFIG_PINCTRL_EXYNOS5440 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
++# CONFIG_GPIO_TS5500 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:
++#
++
++#
++# USB 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_BQ2415X=m
++# CONFIG_CHARGER_SMB347 is not set
++# CONFIG_POWER_RESET 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_THERMAL_DEFAULT_GOV_STEP_WISE=y
++# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
++# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
++CONFIG_FAIR_SHARE=y
++CONFIG_STEP_WISE=y
++CONFIG_USER_SPACE=y
++CONFIG_CPU_THERMAL=y
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_CORE=y
++# 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_MFD_TPS80031 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_MFD_VIPERBOARD is not set
++# CONFIG_MFD_RETU is not set
++# CONFIG_MFD_AS3711 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_MAX8973 is not set
++# CONFIG_REGULATOR_LP3971 is not set
++# CONFIG_REGULATOR_LP3972 is not set
++# CONFIG_REGULATOR_LP872X is not set
++# CONFIG_REGULATOR_TPS51632 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 is not set
++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=y
++CONFIG_DRM_USB=m
++CONFIG_DRM_KMS_HELPER=y
++CONFIG_DRM_LOAD_EDID_FIRMWARE=y
++CONFIG_DRM_GEM_CMA_HELPER=y
++CONFIG_DRM_KMS_CMA_HELPER=y
++
++#
++# I2C encoder or helper chips
++#
++CONFIG_DRM_I2C_CH7006=m
++CONFIG_DRM_I2C_SIL164=m
++CONFIG_DRM_UDL=m
++CONFIG_DRM_LCDC=y
++# 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=m
++CONFIG_FB_CFB_COPYAREA=m
++CONFIG_FB_CFB_IMAGEBLIT=m
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++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 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=y
++CONFIG_OMAP2_VRFB=y
++CONFIG_OMAP2_DSS=m
++# CONFIG_OMAP2_DSS_DEBUG is not set
++CONFIG_OMAP2_DSS_DEBUGFS=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
++# CONFIG_BACKLIGHT_TLC59108 is not set
++
++#
++# Console display driver support
++#
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
++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_FB_SSD1307=m
++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_ICADE 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
++
++#
++# I2C HID support
++#
++CONFIG_I2C_HID=y
++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=y
++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
++
++#
++# 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_RCAR_PHY is not set
++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_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_PCF8523=m
++# 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_OMAP=y
++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 is not set
++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_UIO_DMEM_GENIRQ=m
++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_HAVE_CLK_PREPARE=y
++CONFIG_COMMON_CLK=y
++
++#
++# Common Clock Framework
++#
++CONFIG_COMMON_CLK_DEBUG=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_BUFFER_CB=y
++CONFIG_IIO_KFIFO_BUF=y
++CONFIG_IIO_TRIGGERED_BUFFER=y
++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_AD7298=m
++CONFIG_AD7791=m
++CONFIG_AD7793=m
++CONFIG_AD7476=m
++CONFIG_AD7887=m
++CONFIG_MAX1363=m
++CONFIG_TI_ADC081C=m
++CONFIG_TI_AM335X_ADC=y
++
++#
++# Amplifiers
++#
++# CONFIG_AD8366 is not set
++
++#
++# Hid Sensor IIO Common
++#
++CONFIG_HID_SENSOR_IIO_COMMON=m
++# CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS is not set
++
++#
++# Digital to analog converters
++#
++CONFIG_AD5064=m
++CONFIG_AD5360=m
++CONFIG_AD5380=m
++CONFIG_AD5421=m
++CONFIG_AD5624R_SPI=m
++CONFIG_AD5446=m
++CONFIG_AD5449=m
++CONFIG_AD5504=m
++CONFIG_AD5755=m
++CONFIG_AD5764=m
++CONFIG_AD5791=m
++CONFIG_AD5686=m
++CONFIG_MAX517=m
++CONFIG_MCP4725=m
++
++#
++# Frequency Synthesizers DDS/PLL
++#
++
++#
++# Clock Generator/Distribution
++#
++CONFIG_AD9523=m
++
++#
++# Phase-Locked Loop (PLL) frequency synthesizers
++#
++CONFIG_ADF4350=m
++
++#
++# Digital gyroscope sensors
++#
++CONFIG_ADIS16136=m
++CONFIG_HID_SENSOR_GYRO_3D=m
++
++#
++# Inertial measurement units
++#
++CONFIG_ADIS16480=m
++CONFIG_IIO_ADIS_LIB=m
++CONFIG_IIO_ADIS_LIB_BUFFER=y
++
++#
++# Light sensors
++#
++CONFIG_ADJD_S311=m
++CONFIG_VCNL4000=m
++CONFIG_HID_SENSOR_ALS=m
++
++#
++# Magnetometer sensors
++#
++CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
++CONFIG_PWM=y
++CONFIG_PWM_TIECAP=y
++CONFIG_PWM_TIEHRPWM=y
++CONFIG_PWM_TIPWMSS=y
++CONFIG_PWM_TWL=y
++CONFIG_PWM_TWL_LED=y
++CONFIG_EHRPWM_TEST=m
++# CONFIG_IPACK_BUS is not set
++
++#
++# 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_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=y
++CONFIG_FSCACHE_STATS=y
++CONFIG_FSCACHE_HISTOGRAM=y
++# CONFIG_FSCACHE_DEBUG is not set
++# CONFIG_FSCACHE_OBJECT_LIST is not set
++CONFIG_CACHEFILES=m
++# CONFIG_CACHEFILES_DEBUG is not set
++CONFIG_CACHEFILES_HISTOGRAM=y
++
++#
++# 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=y
++CONFIG_PNFS_FILE_LAYOUT=m
++CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
++CONFIG_ROOT_NFS=y
++CONFIG_NFS_FSCACHE=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_BACKCHANNEL=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=y
++CONFIG_SECURITY_NETWORK_XFRM=y
++# CONFIG_SECURITY_PATH is not set
++CONFIG_SECURITY_SMACK=y
++# 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_SMACK 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=m
++# 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_PERCPU_RWSEM=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.8.13/0240-am33xx-musb-Add-OF-definitions.patch b/patches/linux-3.8.13/0240-am33xx-musb-Add-OF-definitions.patch
new file mode 100644
index 0000000..0613a09
--- /dev/null
+++ b/patches/linux-3.8.13/0240-am33xx-musb-Add-OF-definitions.patch
@@ -0,0 +1,82 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 20:45:35 +0200
+Subject: [PATCH] am33xx-musb: Add OF definitions
+
+For some reason these got dropped; reintroduce.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.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 1b91637..5c6e272 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -324,6 +324,66 @@
+ 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";
++ #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.8.13/0241-Mark-the-device-as-PRIVATE.patch b/patches/linux-3.8.13/0241-Mark-the-device-as-PRIVATE.patch
new file mode 100644
index 0000000..6f83bb1
--- /dev/null
+++ b/patches/linux-3.8.13/0241-Mark-the-device-as-PRIVATE.patch
@@ -0,0 +1,52 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:12:55 +0200
+Subject: [PATCH] Mark the device as PRIVATE
+
+Turns out if you enable CONFIG_NET_DMA the ip stack will try
+to grab all the available non-private DMA channels sometime late in the
+boot sequence.
+
+That's bad enough, what is worse is that it brindly iterates over
+any possible channel; if the driver returns ENODEV on any of the
+channels dmaengine will remove the device from the list of available
+dma devices.
+
+Very crazy bug.
+---
+ drivers/dma/edma.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index e57cce3..2e27ec5 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -395,8 +395,11 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
+ a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
+ chan, EVENTQ_DEFAULT);
+
++ /* NOTE: DO NOT RETURN ENODEV */
++ /* It causes dmaengine to remove the device from it's list */
++
+ if (a_ch_num < 0) {
+- ret = -ENODEV;
++ ret = -EINVAL;
+ goto err_no_chan;
+ }
+
+@@ -404,7 +407,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
+ dev_err(dev, "failed to allocate requested channel %u:%u\n",
+ EDMA_CTLR(echan->ch_num),
+ EDMA_CHAN_SLOT(echan->ch_num));
+- ret = -ENODEV;
++ ret = -EINVAL;
+ goto err_wrong_chan;
+ }
+
+@@ -591,6 +594,7 @@ static int edma_probe(struct platform_device *pdev)
+
+ dma_cap_zero(ecc->dma_slave.cap_mask);
+ dma_cap_set(DMA_SLAVE, ecc->dma_slave.cap_mask);
++ dma_cap_set(DMA_PRIVATE, ecc->dma_slave.cap_mask);
+
+ edma_dma_init(ecc, &ecc->dma_slave, &pdev->dev);
+
diff --git a/patches/linux-3.8.13/0242-omap_hsmmc-Bug-fixes-pinctl-gpio-reset.patch b/patches/linux-3.8.13/0242-omap_hsmmc-Bug-fixes-pinctl-gpio-reset.patch
new file mode 100644
index 0000000..3cee9e0
--- /dev/null
+++ b/patches/linux-3.8.13/0242-omap_hsmmc-Bug-fixes-pinctl-gpio-reset.patch
@@ -0,0 +1,138 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:18:16 +0200
+Subject: [PATCH] omap_hsmmc: Bug fixes, pinctl & gpio-reset
+
+Cleanup omapmmc & add gpio-reset.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+
+Conflicts:
+ drivers/mmc/host/omap_hsmmc.c
+---
+ drivers/mmc/host/omap_hsmmc.c | 42 +++++++++++++++++++++++++++++++-
+ include/linux/platform_data/mmc-omap.h | 3 +++
+ 2 files changed, 44 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index e30c1ee..1f29d67 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -40,6 +40,10 @@
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/platform_data/mmc-omap.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
++#include <mach/hardware.h>
++#include <plat/cpu.h>
+
+ /* OMAP HSMMC Host Controller Registers */
+ #define OMAP_HSMMC_SYSSTATUS 0x0014
+@@ -390,6 +394,7 @@ static inline int omap_hsmmc_have_reg(void)
+ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+ {
+ int ret;
++ unsigned long flags;
+
+ if (gpio_is_valid(pdata->slots[0].switch_pin)) {
+ if (pdata->slots[0].cover)
+@@ -419,6 +424,24 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+ } else
+ pdata->slots[0].gpio_wp = -EINVAL;
+
++ if (gpio_is_valid(pdata->slots[0].gpio_reset)) {
++ flags = pdata->slots[0].gpio_reset_active_low ?
++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
++ ret = gpio_request_one(pdata->slots[0].gpio_reset, flags,
++ "mmc_reset");
++ if (ret)
++ goto err_free_wp;
++
++ /* hold reset */
++ udelay(pdata->slots[0].gpio_reset_hold_us);
++
++ gpio_set_value(pdata->slots[0].gpio_reset,
++ !pdata->slots[0].gpio_reset_active_low);
++
++ } else
++ pdata->slots[0].gpio_reset = -EINVAL;
++
++
+ return 0;
+
+ err_free_wp:
+@@ -432,6 +455,8 @@ err_free_sp:
+
+ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
+ {
++ if (gpio_is_valid(pdata->slots[0].gpio_reset))
++ gpio_free(pdata->slots[0].gpio_reset);
+ if (gpio_is_valid(pdata->slots[0].gpio_wp))
+ gpio_free(pdata->slots[0].gpio_wp);
+ if (gpio_is_valid(pdata->slots[0].switch_pin))
+@@ -786,7 +811,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
+ * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
+ * a val of 0x3, rest 0x0.
+ */
+- if (cmd == host->mrq->stop)
++ if (host->mrq && cmd == host->mrq->stop)
+ cmdtype = 0x3;
+
+ cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
+@@ -828,6 +853,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
+ int dma_ch;
+ unsigned long flags;
+
++ BUG_ON(mrq == NULL);
++
+ spin_lock_irqsave(&host->irq_lock, flags);
+ host->req_in_progress = 0;
+ dma_ch = host->dma_ch;
+@@ -1717,6 +1744,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ struct omap_mmc_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+ u32 bus_width, max_freq;
++ enum of_gpio_flags reset_flags;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+@@ -1729,6 +1757,14 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ pdata->nr_slots = 1;
+ pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0);
+ pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
++ reset_flags = 0;
++ pdata->slots[0].gpio_reset = of_get_named_gpio_flags(np,
++ "reset-gpios", 0, &reset_flags);
++ pdata->slots[0].gpio_reset_active_low =
++ (reset_flags & OF_GPIO_ACTIVE_LOW) != 0;
++ pdata->slots[0].gpio_reset_hold_us = 100; /* default */
++ of_property_read_u32(np, "reset-gpio-hold-us",
++ &pdata->slots[0].gpio_reset_hold_us);
+
+ if (of_find_property(np, "ti,non-removable", NULL)) {
+ pdata->slots[0].nonremovable = true;
+@@ -1791,6 +1827,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ return -ENXIO;
+ }
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (res == NULL || irq < 0)
+diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
+index 2bf1b30..d548994 100644
+--- a/include/linux/platform_data/mmc-omap.h
++++ b/include/linux/platform_data/mmc-omap.h
+@@ -115,6 +115,9 @@ struct omap_mmc_platform_data {
+
+ int switch_pin; /* gpio (card detect) */
+ int gpio_wp; /* gpio (write protect) */
++ int gpio_reset; /* gpio (reset) */
++ int gpio_reset_active_low; /* 1 if reset is active low */
++ u32 gpio_reset_hold_us; /* time to hold in us */
+
+ int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
+ int (*set_power)(struct device *dev, int slot,
diff --git a/patches/linux-3.8.13/0243-tps65217-bl-Locate-backlight-node-correctly.patch b/patches/linux-3.8.13/0243-tps65217-bl-Locate-backlight-node-correctly.patch
new file mode 100644
index 0000000..18c903b
--- /dev/null
+++ b/patches/linux-3.8.13/0243-tps65217-bl-Locate-backlight-node-correctly.patch
@@ -0,0 +1,47 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 16:54:51 +0200
+Subject: [PATCH] tps65217-bl: Locate backlight node correctly.
+
+When using overlays find_node doesn't work like it used to, because
+the new nodes are inserted at the head of allnodes.
+
+Use the correct function to locate the child node.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/video/backlight/tps65217_bl.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
+index 69c1dfe..31a9203 100644
+--- a/drivers/video/backlight/tps65217_bl.c
++++ b/drivers/video/backlight/tps65217_bl.c
+@@ -247,12 +247,14 @@ tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
+
+ rnode = of_node_get(tps->dev->of_node);
+
+- node = of_find_node_by_name(rnode, "backlight");
++ node = of_get_child_by_name(rnode, "backlight");
+ of_node_put(rnode);
+ rnode = NULL;
+
+- if (!node)
++ if (!node) {
++ dev_err(&pdev->dev, "failed to find backlight node\n");
+ return ERR_PTR(-ENODEV);
++ }
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+@@ -339,8 +341,10 @@ static int tps65217_bl_probe(struct platform_device *pdev)
+
+ if (pdev->dev.of_node) {
+ pdata = tps65217_bl_parse_dt(pdev, &tps, &brightness);
+- if (IS_ERR(pdata))
++ if (IS_ERR(pdata)) {
++ dev_err(&pdev->dev, "DT parse failed.\n");
+ return PTR_ERR(pdata);
++ }
+ } else {
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "no platform data provided\n");
diff --git a/patches/linux-3.8.13/0244-arm-Export-cache-flush-management-symbols-when-MULTI.patch b/patches/linux-3.8.13/0244-arm-Export-cache-flush-management-symbols-when-MULTI.patch
new file mode 100644
index 0000000..7dd8b13
--- /dev/null
+++ b/patches/linux-3.8.13/0244-arm-Export-cache-flush-management-symbols-when-MULTI.patch
@@ -0,0 +1,29 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sun, 16 Dec 2012 19:46:34 +0200
+Subject: [PATCH] arm: Export cache flush management symbols when !MULTI_CACHE
+
+When compiling a kernel without CONFIG_MULTI_CACHE enabled the
+dma access functions end up not being exported. Fix it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/kernel/setup.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
+index 3f6cbb2..4540dad 100644
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -931,3 +931,12 @@ const struct seq_operations cpuinfo_op = {
+ .stop = c_stop,
+ .show = c_show
+ };
++
++/* export the cache management functions */
++#ifndef MULTI_CACHE
++
++EXPORT_SYMBOL(__glue(_CACHE,_dma_map_area));
++EXPORT_SYMBOL(__glue(_CACHE,_dma_unmap_area));
++EXPORT_SYMBOL(__glue(_CACHE,_dma_flush_range));
++
++#endif
diff --git a/patches/linux-3.8.13/0245-am335x-bone-dtsi-Clean-up.patch b/patches/linux-3.8.13/0245-am335x-bone-dtsi-Clean-up.patch
new file mode 100644
index 0000000..7eb4697
--- /dev/null
+++ b/patches/linux-3.8.13/0245-am335x-bone-dtsi-Clean-up.patch
@@ -0,0 +1,127 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Dec 2012 14:34:08 +0200
+Subject: [PATCH] am335x-bone-dtsi: Clean up
+
+Clean up the common dtsi.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+
+Conflicts:
+ arch/arm/boot/dts/am335x-bone-common.dtsi
+ arch/arm/boot/dts/am335x-bone.dts
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 80 +----------------------------
+ 1 file changed, 1 insertion(+), 79 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 8295b30..b084324 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -73,7 +73,7 @@
+ };
+ };
+
+- ocp {
++ ocp: ocp {
+ uart1: serial@44e09000 {
+ status = "okay";
+ };
+@@ -128,35 +128,6 @@
+ };
+ };
+
+- leds {
+- compatible = "gpio-leds";
+-
+- led@2 {
+- label = "beaglebone:green:heartbeat";
+- gpios = <&gpio2 21 0>;
+- linux,default-trigger = "heartbeat";
+- default-state = "off";
+- };
+-
+- led@3 {
+- label = "beaglebone:green:mmc0";
+- gpios = <&gpio2 22 0>;
+- linux,default-trigger = "mmc0";
+- default-state = "off";
+- };
+-
+- led@4 {
+- label = "beaglebone:green:usr2";
+- gpios = <&gpio2 23 0>;
+- default-state = "off";
+- };
+-
+- led@5 {
+- label = "beaglebone:green:usr3";
+- gpios = <&gpio2 24 0>;
+- default-state = "off";
+- };
+- };
+ };
+
+ &i2c0 {
+@@ -166,41 +137,6 @@
+ 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"
+@@ -264,20 +200,6 @@
+ vmmc-supply = <&ldo3_reg>;
+ };
+
+-&spi1 {
+- status = "okay";
+-
+- lcd@0 {
+- compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
+- spi-max-frequency = <8000000>;
+- reg = <0>;
+- spi-cpol;
+- spi-cpha;
+- st7735-rst = <&gpio4 19 0>;
+- st7735-dc = <&gpio4 21 0>;
+- };
+-};
+-
+ &edma {
+ ti,edma-xbar-event-map = <32 12>;
+ };
diff --git a/patches/linux-3.8.13/0246-am335x-bone-dtsi-Introduce-new-I2C-entries.patch b/patches/linux-3.8.13/0246-am335x-bone-dtsi-Introduce-new-I2C-entries.patch
new file mode 100644
index 0000000..df0ad85
--- /dev/null
+++ b/patches/linux-3.8.13/0246-am335x-bone-dtsi-Introduce-new-I2C-entries.patch
@@ -0,0 +1,55 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Dec 2012 14:36:38 +0200
+Subject: [PATCH] am335x-bone-dtsi: Introduce new I2C entries
+
+Introduce I2C entries that are required for capes.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 33 +++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index b084324..312ded8 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -137,6 +137,39 @@
+ 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>;
++
++ cape_eeprom0: cape_eeprom0@54 {
++ compatible = "at,24c256";
++ reg = <0x54>;
++ };
++
++ cape_eeprom1: cape_eeprom1@55 {
++ compatible = "at,24c256";
++ reg = <0x55>;
++ };
++
++ cape_eeprom2: cape_eeprom2@56 {
++ compatible = "at,24c256";
++ reg = <0x56>;
++ };
++
++ cape_eeprom3: cape_eeprom3@57 {
++ compatible = "at,24c256";
++ reg = <0x57>;
++ };
+ };
+
+ /include/ "tps65217.dtsi"
diff --git a/patches/linux-3.8.13/0247-am335x-dt-Add-I2C0-pinctrl-entries.patch b/patches/linux-3.8.13/0247-am335x-dt-Add-I2C0-pinctrl-entries.patch
new file mode 100644
index 0000000..4889713
--- /dev/null
+++ b/patches/linux-3.8.13/0247-am335x-dt-Add-I2C0-pinctrl-entries.patch
@@ -0,0 +1,38 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 11:26:59 +0200
+Subject: [PATCH] am335x-dt: Add I2C0 pinctrl entries.
+
+Make sure I2C0 gets it's own pinctrl entries and doesn't rely on the
+bootloader.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 312ded8..e43417b 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -65,6 +65,12 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++ i2c0_pins: pinmux_i2c0_pins {
++ pinctrl-single,pins = <
++ 0x188 0x70 /* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
++ 0x18c 0x70 /* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
++ >;
++ };
+ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+@@ -133,6 +139,8 @@
+ &i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c0_pins>;
+
+ tps: tps@24 {
+ reg = <0x24>;
diff --git a/patches/linux-3.8.13/0248-Cleanup-am33xx.dtsi.patch b/patches/linux-3.8.13/0248-Cleanup-am33xx.dtsi.patch
new file mode 100644
index 0000000..5308f2e
--- /dev/null
+++ b/patches/linux-3.8.13/0248-Cleanup-am33xx.dtsi.patch
@@ -0,0 +1,73 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 20:15:52 +0200
+Subject: [PATCH] Cleanup am33xx.dtsi
+
+---
+ arch/arm/boot/dts/am33xx.dtsi | 54 -----------------------------------------
+ 1 file changed, 54 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 5c6e272..5218fbe 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -67,60 +67,6 @@
+ #size-cells = <0>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x7f>;
+-
+- 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 */
+- >;
+- };
+ };
+
+ /*
diff --git a/patches/linux-3.8.13/0249-Fix-platform-device-resource-linking.patch b/patches/linux-3.8.13/0249-Fix-platform-device-resource-linking.patch
new file mode 100644
index 0000000..e1bcc35
--- /dev/null
+++ b/patches/linux-3.8.13/0249-Fix-platform-device-resource-linking.patch
@@ -0,0 +1,214 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 11:34:15 +0200
+Subject: [PATCH] Fix platform device resource linking
+
+Platform device removal uncovered a number of problems with
+the way resources are handled in the core platform code.
+
+Resources now form child/parent linkages and this requires
+proper linking of the resources. On top of that the OF core
+directly creates it's own platform devices. Simplify things
+by providing helper functions that manage the linking properly.
+
+Two functions are provided:
+
+platform_device_link_resources(), which links all the
+linkable resources (if not already linked).
+
+and platform_device_unlink_resources(), which unlinks all the
+resources.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/base/platform.c | 124 ++++++++++++++++++++++++++-------------
+ include/linux/platform_device.h | 4 ++
+ 2 files changed, 87 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/base/platform.c b/drivers/base/platform.c
+index c0b8df3..dab9552 100644
+--- a/drivers/base/platform.c
++++ b/drivers/base/platform.c
+@@ -270,6 +270,80 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
+ }
+ EXPORT_SYMBOL_GPL(platform_device_add_data);
+
++static struct resource *platform_device_parent_resource(
++ struct platform_device *pdev, struct resource *r)
++{
++ unsigned long type;
++
++ if (r->parent)
++ return r->parent;
++
++ type = resource_type(r);
++ switch (type) {
++ case IORESOURCE_MEM:
++ return &iomem_resource;
++ case IORESOURCE_IO:
++ return &ioport_resource;
++ /* TODO: What about the other resources? */
++ default:
++ break;
++ }
++ pr_debug("%s: no parent for resource %p type 0x%lx\n",
++ dev_name(&pdev->dev), r, resource_type(r));
++ return NULL;
++}
++
++int platform_device_unlink_resources(struct platform_device *pdev)
++{
++ struct resource *r;
++ int i;
++
++ for (i = pdev->num_resources - 1; i >= 0; i--) {
++ r = &pdev->resource[i];
++ if (r->parent == NULL)
++ continue;
++ release_resource(r);
++ }
++ return 0;
++}
++EXPORT_SYMBOL_GPL(platform_device_unlink_resources);
++
++int platform_device_link_resources(struct platform_device *pdev)
++{
++ int i;
++ struct resource *p, *r;
++
++ for (i = 0; i < pdev->num_resources; i++) {
++ r = &pdev->resource[i];
++
++ if (r->name == NULL)
++ r->name = dev_name(&pdev->dev);
++
++ /* already linked */
++ if (r->parent != NULL)
++ continue;
++
++ p = platform_device_parent_resource(pdev, r);
++ if (p && insert_resource(p, r)) {
++ pr_err("%s: failed to claim resource %d\n",
++ dev_name(&pdev->dev), i);
++ goto fail;
++ }
++ }
++
++ return 0;
++
++fail:
++ while (--i >= 0) {
++ r = &pdev->resource[i];
++ if (r->parent == NULL)
++ continue;
++ release_resource(r);
++ }
++ return -EBUSY;
++}
++EXPORT_SYMBOL_GPL(platform_device_link_resources);
++
+ /**
+ * platform_device_add - add a platform device to device hierarchy
+ * @pdev: platform device we're adding
+@@ -279,7 +353,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data);
+ */
+ int platform_device_add(struct platform_device *pdev)
+ {
+- int i, ret;
++ int ret;
+
+ if (!pdev)
+ return -EINVAL;
+@@ -311,28 +385,10 @@ int platform_device_add(struct platform_device *pdev)
+ break;
+ }
+
+- for (i = 0; i < pdev->num_resources; i++) {
+- struct resource *p, *r = &pdev->resource[i];
+-
+- if (r->name == NULL)
+- r->name = dev_name(&pdev->dev);
+-
+- p = r->parent;
+- if (!p) {
+- if (resource_type(r) == IORESOURCE_MEM)
+- p = &iomem_resource;
+- else if (resource_type(r) == IORESOURCE_IO)
+- p = &ioport_resource;
+- }
+-
+- if (p && insert_resource(p, r)) {
+- printk(KERN_ERR
+- "%s: failed to claim resource %d\n",
+- dev_name(&pdev->dev), i);
+- ret = -EBUSY;
+- goto failed;
+- }
+- }
++ /* make sure the resources are linked properly */
++ ret = platform_device_link_resources(pdev);
++ if (ret != 0)
++ goto failed_res;
+
+ pr_debug("Registering platform device '%s'. Parent at %s\n",
+ dev_name(&pdev->dev), dev_name(pdev->dev.parent));
+@@ -341,20 +397,14 @@ int platform_device_add(struct platform_device *pdev)
+ if (ret == 0)
+ return ret;
+
+- failed:
++ platform_device_unlink_resources(pdev);
++
++ failed_res:
+ if (pdev->id_auto) {
+ ida_simple_remove(&platform_devid_ida, pdev->id);
+ pdev->id = PLATFORM_DEVID_AUTO;
+ }
+
+- while (--i >= 0) {
+- struct resource *r = &pdev->resource[i];
+- unsigned long type = resource_type(r);
+-
+- if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
+- release_resource(r);
+- }
+-
+ err_out:
+ return ret;
+ }
+@@ -370,8 +420,6 @@ EXPORT_SYMBOL_GPL(platform_device_add);
+ */
+ void platform_device_del(struct platform_device *pdev)
+ {
+- int i;
+-
+ if (pdev) {
+ device_del(&pdev->dev);
+
+@@ -380,13 +428,7 @@ void platform_device_del(struct platform_device *pdev)
+ pdev->id = PLATFORM_DEVID_AUTO;
+ }
+
+- for (i = 0; i < pdev->num_resources; i++) {
+- struct resource *r = &pdev->resource[i];
+- unsigned long type = resource_type(r);
+-
+- if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
+- release_resource(r);
+- }
++ platform_device_unlink_resources(pdev);
+ }
+ }
+ EXPORT_SYMBOL_GPL(platform_device_del);
+diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
+index a9ded9a..e48c2d5 100644
+--- a/include/linux/platform_device.h
++++ b/include/linux/platform_device.h
+@@ -293,4 +293,8 @@ extern int platform_pm_restore(struct device *dev);
+ #define USE_PLATFORM_PM_SLEEP_OPS
+ #endif
+
++/* helper functions for resource list managment */
++int platform_device_unlink_resources(struct platform_device *pdev);
++int platform_device_link_resources(struct platform_device *pdev);
++
+ #endif /* _PLATFORM_DEVICE_H_ */
diff --git a/patches/linux-3.8.13/0250-Link-platform-device-resources-properly.patch b/patches/linux-3.8.13/0250-Link-platform-device-resources-properly.patch
new file mode 100644
index 0000000..a503bbb
--- /dev/null
+++ b/patches/linux-3.8.13/0250-Link-platform-device-resources-properly.patch
@@ -0,0 +1,27 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 11:39:29 +0200
+Subject: [PATCH] Link platform device resources properly.
+
+The resources of the platform devices created by the OF core were
+not properly linked. Make sure that they are, so that we don't get
+any crashes when trying to remove the device.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/device.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/of/device.c b/drivers/of/device.c
+index 4c74e4f..d75fcaf 100644
+--- a/drivers/of/device.c
++++ b/drivers/of/device.c
+@@ -62,6 +62,9 @@ int of_device_add(struct platform_device *ofdev)
+ if (!ofdev->dev.parent)
+ set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node));
+
++ /* make sure we add the resources to the appropriate lists */
++ platform_device_link_resources(ofdev);
++
+ return device_add(&ofdev->dev);
+ }
+
diff --git a/patches/linux-3.8.13/0251-Properly-handle-resources-for-omap_devices.patch b/patches/linux-3.8.13/0251-Properly-handle-resources-for-omap_devices.patch
new file mode 100644
index 0000000..92b22e2
--- /dev/null
+++ b/patches/linux-3.8.13/0251-Properly-handle-resources-for-omap_devices.patch
@@ -0,0 +1,290 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 11:41:11 +0200
+Subject: [PATCH] Properly handle resources for omap_devices
+
+omap_device relies on the platform notifier callbacks managing resources
+behind the scenes. The resources were not properly linked causing crashes
+when removing the device.
+
+Rework the resource modification code so that linking is performed properly,
+and make sure that no resources that have no parent (which can happen for DMA
+& IRQ resources) are ever left for cleanup by the core resource layer.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/omap_device.c | 232 +++++++++++++++++++++++--------------
+ 1 file changed, 148 insertions(+), 84 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
+index e065daa..9f8dba1 100644
+--- a/arch/arm/mach-omap2/omap_device.c
++++ b/arch/arm/mach-omap2/omap_device.c
+@@ -494,30 +494,156 @@ static int omap_device_fill_resources(struct omap_device *od,
+ }
+
+ /**
+- * _od_fill_dma_resources - fill in array of struct resource with dma resources
++ * omap_device_fixup_resources - Fix platform device resources
+ * @od: struct omap_device *
+- * @res: pointer to an array of struct resource to be filled in
+- *
+- * Populate one or more empty struct resource pointed to by @res with
+- * the dma resource data for this omap_device @od. Used by
+- * omap_device_alloc() after calling omap_device_count_resources().
+- *
+- * Ideally this function would not be needed at all. If we have
+- * mechanism to get dma resources from DT.
+ *
+- * Returns 0.
++ * Fixup the platform device resources so that the resources
++ * from the hwmods are included for.
+ */
+-static int _od_fill_dma_resources(struct omap_device *od,
+- struct resource *res)
++static int omap_device_fixup_resources(struct omap_device *od)
+ {
+- int i, r;
++ struct platform_device *pdev = od->pdev;
++ int i, j, ret, res_count;
++ struct resource *res, *r, *rnew, *rn;
++ unsigned long type;
+
+- for (i = 0; i < od->hwmods_cnt; i++) {
+- r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
+- res += r;
++ /*
++ * DT Boot:
++ * OF framework will construct the resource structure (currently
++ * does for MEM & IRQ resource) and we should respect/use these
++ * resources, killing hwmod dependency.
++ * If pdev->num_resources > 0, we assume that MEM & IRQ resources
++ * have been allocated by OF layer already (through DTB).
++ *
++ * Non-DT Boot:
++ * Here, pdev->num_resources = 0, and we should get all the
++ * resources from hwmod.
++ *
++ * TODO: Once DMA resource is available from OF layer, we should
++ * kill filling any resources from hwmod.
++ */
++
++ /* count number of resources hwmod provides */
++ res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
++ IORESOURCE_DMA | IORESOURCE_MEM);
++
++ /* if no resources from hwmod, we're done already */
++ if (res_count == 0)
++ return 0;
++
++ /* Allocate resources memory to account for all hwmod resources */
++ res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
++ if (!res) {
++ ret = -ENOMEM;
++ goto fail_no_res;
+ }
+
++ /* fill all the resources */
++ ret = omap_device_fill_resources(od, res);
++ if (ret != 0)
++ goto fail_no_fill;
++
++ /*
++ * If pdev->num_resources > 0, then assume that,
++ * MEM and IRQ resources will only come from DT and only
++ * fill DMA resource from hwmod layer.
++ */
++ if (pdev->num_resources > 0) {
++
++ dev_dbg(&pdev->dev, "%s(): resources allocated %d hwmod #%d\n",
++ __func__, pdev->num_resources, res_count);
++
++ /* find number of resources needing to be inserted */
++ for (i = 0, j = 0, r = res; i < res_count; i++, r++) {
++ type = resource_type(r);
++ if (type == IORESOURCE_DMA)
++ j++;
++ }
++
++ /* no need to insert anything, just return */
++ if (j == 0) {
++ kfree(res);
++ return 0;
++ }
++
++ /* we need to insert j additional resources */
++ rnew = kzalloc(sizeof(*rnew) *
++ (pdev->num_resources + j), GFP_KERNEL);
++ if (rnew == NULL)
++ goto fail_no_rnew;
++
++ /*
++ * Unlink any resources from any lists.
++ * This is important since the copying destroys any
++ * linkage
++ */
++ for (i = 0, r = pdev->resource;
++ i < pdev->num_resources; i++, r++) {
++
++ if (!r->parent)
++ continue;
++
++ dev_dbg(&pdev->dev,
++ "Releasing resource %p\n", r);
++ release_resource(r);
++ r->parent = NULL;
++ r->sibling = NULL;
++ r->child = NULL;
++ }
++
++ memcpy(rnew, pdev->resource,
++ sizeof(*rnew) * pdev->num_resources);
++
++ /* now append the resources from the hwmods */
++ rn = rnew + pdev->num_resources;
++ for (i = 0, r = res; i < res_count; i++, r++) {
++
++ type = resource_type(r);
++ if (type != IORESOURCE_DMA)
++ continue;
++
++ /* append the hwmod resource */
++ memcpy(rn, r, sizeof(*r));
++
++ /* make sure these are zeroed out */
++ rn->parent = NULL;
++ rn->child = NULL;
++ rn->sibling = NULL;
++
++ rn++;
++ }
++ kfree(res); /* we don't need res anymore */
++
++ /* this is our new resource table */
++ res = rnew;
++ res_count = j;
++
++ } else {
++ dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
++ __func__, res_count);
++ }
++
++ ret = platform_device_add_resources(pdev, res, res_count);
++ kfree(res);
++
++ /* failed to add the resources? */
++ if (ret != 0)
++ return ret;
++
++ /* finally link all the resources again */
++ ret = platform_device_link_resources(pdev);
++ if (ret != 0)
++ return ret;
++
+ return 0;
++
++fail_no_rnew:
++ /* nothing */
++fail_no_fill:
++ kfree(res);
++
++fail_no_res:
++ return ret;
+ }
+
+ /**
+@@ -541,9 +667,8 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
+ {
+ int ret = -ENOMEM;
+ struct omap_device *od;
+- struct resource *res = NULL;
+- int i, res_count;
+ struct omap_hwmod **hwmods;
++ int i;
+
+ od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+ if (!od) {
+@@ -553,79 +678,18 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
+ od->hwmods_cnt = oh_cnt;
+
+ hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+- if (!hwmods)
++ if (!hwmods) {
++ ret = -ENOMEM;
+ goto oda_exit2;
++ }
+
+ od->hwmods = hwmods;
+ od->pdev = pdev;
+
+- /*
+- * Non-DT Boot:
+- * Here, pdev->num_resources = 0, and we should get all the
+- * resources from hwmod.
+- *
+- * DT Boot:
+- * OF framework will construct the resource structure (currently
+- * does for MEM & IRQ resource) and we should respect/use these
+- * resources, killing hwmod dependency.
+- * If pdev->num_resources > 0, we assume that MEM & IRQ resources
+- * have been allocated by OF layer already (through DTB).
+- * As preparation for the future we examine the OF provided resources
+- * to see if we have DMA resources provided already. In this case
+- * there is no need to update the resources for the device, we use the
+- * OF provided ones.
+- *
+- * TODO: Once DMA resource is available from OF layer, we should
+- * kill filling any resources from hwmod.
+- */
+- if (!pdev->num_resources) {
+- /* Count all resources for the device */
+- res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
+- IORESOURCE_DMA |
+- IORESOURCE_MEM);
+- } else {
+- /* Take a look if we already have DMA resource via DT */
+- for (i = 0; i < pdev->num_resources; i++) {
+- struct resource *r = &pdev->resource[i];
+-
+- /* We have it, no need to touch the resources */
+- if (r->flags == IORESOURCE_DMA)
+- goto have_everything;
+- }
+- /* Count only DMA resources for the device */
+- res_count = omap_device_count_resources(od, IORESOURCE_DMA);
+- /* The device has no DMA resource, no need for update */
+- if (!res_count)
+- goto have_everything;
+-
+- res_count += pdev->num_resources;
+- }
+-
+- /* Allocate resources memory to account for new resources */
+- res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+- if (!res)
+- goto oda_exit3;
+-
+- if (!pdev->num_resources) {
+- dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
+- __func__, res_count);
+- omap_device_fill_resources(od, res);
+- } else {
+- dev_dbg(&pdev->dev,
+- "%s: appending %d DMA resources from hwmod\n",
+- __func__, res_count - pdev->num_resources);
+- memcpy(res, pdev->resource,
+- sizeof(struct resource) * pdev->num_resources);
+- _od_fill_dma_resources(od, &res[pdev->num_resources]);
+- }
+-
+- ret = platform_device_add_resources(pdev, res, res_count);
+- kfree(res);
+-
+- if (ret)
++ ret = omap_device_fixup_resources(od);
++ if (ret != 0)
+ goto oda_exit3;
+
+-have_everything:
+ if (!pm_lats) {
+ pm_lats = omap_default_latency;
+ pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
diff --git a/patches/linux-3.8.13/0252-omap-Avoid-crashes-in-the-case-of-hwmod-misconfigura.patch b/patches/linux-3.8.13/0252-omap-Avoid-crashes-in-the-case-of-hwmod-misconfigura.patch
new file mode 100644
index 0000000..0527d5f
--- /dev/null
+++ b/patches/linux-3.8.13/0252-omap-Avoid-crashes-in-the-case-of-hwmod-misconfigura.patch
@@ -0,0 +1,79 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 8 Jan 2013 15:19:52 +0200
+Subject: [PATCH] omap: Avoid crashes in the case of hwmod misconfiguration
+
+omap hwmod is really sensitive to hwmod misconfiguration.
+Getting a minor clock wrong always ended up in a crash.
+Attempt to be more resilient by not assigning variables with
+error codes and then attempting to use them.
+
+Without this patch, missing a clock ends up with something like this:
+omap_hwmod: ehrpwm0: cannot clk_get opt_clk ehrpwm0_tbclk!
+Unable to handle kernel NULL pointer dereference at virtual address 0000002a!
+pgd = c0004000!
+[0000002a] *pgd=00000000!
+Internal error: Oops: 5 [#1] SMP ARM!
+Modules linked in:!
+CPU: 0 Not tainted (3.8.0-rc2-12157-g76c7825-dirty #291)!
+PC is at __clk_prepare+0x10/0x70!
+LR is at clk_prepare+0x1c/0x34!
+pc : [<c03e37f0>] lr : [<c03e386c>] psr: a0000113!
+sp : cf04fef8 ip : 22222222 fp : 00000000!
+r10: ffffffea r9 : 00000000 r8 : 00000000!
+r7 : fffffffe r6 : 00000001 r5 : fffffffe r4 : fffffffe!
+r3 : cf041ac0 r2 : cf04ff00 r1 : 22222222 r0 : fffffffe!
+Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel!
+Control: 10c5387d Table: 80004019 DAC: 00000015!
+Process swapper/0 (pid: 1, stack limit = 0xcf04e240)!
+Stack: (0xcf04fef8 to 0xcf050000)!
+fee0: cf041ac0 c07749f4!
+ff00: fffffffe c03e386c c07499cc c073c070 c073d2fc c06d4e4c c073c070 c071cc18!
+ff20: c06d4c4c 00000000 00000000 c0708284 c06c91bc c0025e28 c073a030 00000001!
+ff40: c06f5f60 c06f5f40 c06d5324 c06d533c cf04e000 c0008870 c06d5324 c060abe8!
+ff60: c07082e8 00000002 00000001 c06f5f60 c06f5f40 c077d700 00000099 c04a43d4!
+ff80: 00000001 00000001 c06c91bc 00000000 00000000 c04a42dc 00000000 00000000!
+ffa0: 00000000 00000000 00000000 c000d678 00000000 00000000 00000000 00000000!
+ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000!
+ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 9e7befee f7bbaaab!
+[<c03e37f0>] (__clk_prepare+0x10/0x70) from [<c03e386c>] (clk_prepare+0x1c/0x34)!
+[<c03e386c>] (clk_prepare+0x1c/0x34) from [<c06d4e4c>] (_init+0x200/0x288)!
+[<c06d4e4c>] (_init+0x200/0x288) from [<c0025e28>] (omap_hwmod_for_each+0x28/0x58)!
+[<c0025e28>] (omap_hwmod_for_each+0x28/0x58) from [<c06d533c>] (omap_hwmod_setup_all+0x18/0x34)!
+[<c06d533c>] (omap_hwmod_setup_all+0x18/0x34) from [<c0008870>] (do_one_initcall+0x90/0x160)!
+[<c0008870>] (do_one_initcall+0x90/0x160) from [<c04a43d4>] (kernel_init+0xf8/0x290)!
+[<c04a43d4>] (kernel_init+0xf8/0x290) from [<c000d678>] (ret_from_fork+0x14/0x3c)!
+Code: e92d4038 e2504000 01a05004 0a000015 (e594302c) !
+---[ end trace 1b75b31a2719ed1c ]---!
+Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b!
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/omap_hwmod.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
+index 4653efb..2b58e21 100644
+--- a/arch/arm/mach-omap2/omap_hwmod.c
++++ b/arch/arm/mach-omap2/omap_hwmod.c
+@@ -783,7 +783,9 @@ static int _init_interface_clks(struct omap_hwmod *oh)
+ if (IS_ERR(c)) {
+ pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
+ oh->name, os->clk);
+- ret = -EINVAL;
++ if (ret == 0)
++ ret = -EINVAL;
++ continue;
+ }
+ os->_clk = c;
+ /*
+@@ -819,7 +821,9 @@ static int _init_opt_clks(struct omap_hwmod *oh)
+ if (IS_ERR(c)) {
+ pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
+ oh->name, oc->clk);
+- ret = -EINVAL;
++ if (ret == 0)
++ ret = -EINVAL;
++ continue;
+ }
+ oc->_clk = c;
+ /*
diff --git a/patches/linux-3.8.13/0253-i2c-EEPROM-In-kernel-memory-accessor-interface.patch b/patches/linux-3.8.13/0253-i2c-EEPROM-In-kernel-memory-accessor-interface.patch
new file mode 100644
index 0000000..307ee7d
--- /dev/null
+++ b/patches/linux-3.8.13/0253-i2c-EEPROM-In-kernel-memory-accessor-interface.patch
@@ -0,0 +1,127 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 13 Dec 2012 11:23:21 +0200
+Subject: [PATCH] i2c-EEPROM: In kernel memory accessor interface
+
+In kernel users need to access the EEPROM using the i2c_client
+interface. Extend at24 to use it via the command interface.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/eeprom/at24.c | 23 +++++++++++++++++
+ include/linux/i2c/eeprom.h | 59 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 82 insertions(+)
+ create mode 100644 include/linux/i2c/eeprom.h
+
+diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
+index 2baeec5..40b1a95 100644
+--- a/drivers/misc/eeprom/at24.c
++++ b/drivers/misc/eeprom/at24.c
+@@ -23,6 +23,7 @@
+ #include <linux/of.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c/at24.h>
++#include <linux/i2c/eeprom.h>
+
+ /*
+ * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
+@@ -672,6 +673,27 @@ static int at24_remove(struct i2c_client *client)
+ return 0;
+ }
+
++static int at24_command(struct i2c_client *client, unsigned int cmd, void *arg)
++{
++ struct at24_data *at24;
++ const struct memory_accessor **maccp;
++
++ /* only supporting a single command */
++ if (cmd != I2C_EEPROM_GET_MEMORY_ACCESSOR)
++ return -ENOTSUPP;
++
++ /* rudimentary check */
++ if (arg == NULL)
++ return -EINVAL;
++
++ at24 = i2c_get_clientdata(client);
++
++ maccp = arg;
++ *maccp = &at24->macc;
++
++ return 0;
++}
++
+ /*-------------------------------------------------------------------------*/
+
+ static struct i2c_driver at24_driver = {
+@@ -682,6 +704,7 @@ static struct i2c_driver at24_driver = {
+ .probe = at24_probe,
+ .remove = at24_remove,
+ .id_table = at24_ids,
++ .command = at24_command,
+ };
+
+ static int __init at24_init(void)
+diff --git a/include/linux/i2c/eeprom.h b/include/linux/i2c/eeprom.h
+new file mode 100644
+index 0000000..1393980
+--- /dev/null
++++ b/include/linux/i2c/eeprom.h
+@@ -0,0 +1,59 @@
++/*
++ * i2c/eeprom.h
++ *
++ * In-kernel interface for accessing eeprom memory.
++ *
++ * Copyright (C) 2012 Texas Instruments Inc.
++ * Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++#ifndef I2C_EEPROM_H
++#define I2C_EEPROM_H
++
++#include <linux/types.h>
++#include <linux/memory.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++
++/*
++ * The method called in the client is
++ *
++ * int command(struct i2c_client *client, unsigned int cmd, void *arg);
++ *
++ * A single command is supported, which returns a pointer to the memory
++ * accessor already available, but which was only accessible via platform
++ * callbacks. We can't use platform callbacks anymore for device tree
++ * platforms, hence this interface.
++ *
++ */
++
++/* interface commands */
++#define I2C_EEPROM_GET_MEMORY_ACCESSOR 1
++
++static inline struct memory_accessor *
++i2c_eeprom_get_memory_accessor(struct i2c_client *client)
++{
++ int ret;
++ struct memory_accessor *macc;
++
++ /* verify that the i2c client's driver has a command method */
++ if (!client || !client->driver || !client->driver->command)
++ return ERR_PTR(-ENOTSUPP);
++
++ macc = NULL;
++ ret = client->driver->command(client, I2C_EEPROM_GET_MEMORY_ACCESSOR,
++ &macc);
++ if (ret != 0)
++ return ERR_PTR(ret);
++
++ if (macc == NULL)
++ return ERR_PTR(-ENOTSUPP);
++
++ return macc;
++}
++
++#endif
diff --git a/patches/linux-3.8.13/0254-Fix-util_is_printable_string.patch b/patches/linux-3.8.13/0254-Fix-util_is_printable_string.patch
new file mode 100644
index 0000000..dbbfd6c
--- /dev/null
+++ b/patches/linux-3.8.13/0254-Fix-util_is_printable_string.patch
@@ -0,0 +1,50 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 6 Dec 2012 13:22:49 +0200
+Subject: [PATCH] Fix util_is_printable_string
+
+The method used did not account for multi-part strings.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ scripts/dtc/util.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
+index 2422c34..45f186b 100644
+--- a/scripts/dtc/util.c
++++ b/scripts/dtc/util.c
+@@ -72,7 +72,7 @@ char *join_path(const char *path, const char *name)
+ int util_is_printable_string(const void *data, int len)
+ {
+ const char *s = data;
+- const char *ss;
++ const char *ss, *se;
+
+ /* zero length is not */
+ if (len == 0)
+@@ -82,13 +82,19 @@ int util_is_printable_string(const void *data, int len)
+ if (s[len - 1] != '\0')
+ return 0;
+
+- ss = s;
+- while (*s && isprint(*s))
+- s++;
++ se = s + len;
+
+- /* not zero, or not done yet */
+- if (*s != '\0' || (s + 1 - ss) < len)
+- return 0;
++ while (s < se) {
++ ss = s;
++ while (s < se && *s && isprint(*s))
++ s++;
++
++ /* not zero, or not done yet */
++ if (*s != '\0' || s == ss)
++ return 0;
++
++ s++;
++ }
+
+ return 1;
+ }
diff --git a/patches/linux-3.8.13/0255-fdtdump-properly-handle-multi-string-properties.patch b/patches/linux-3.8.13/0255-fdtdump-properly-handle-multi-string-properties.patch
new file mode 100644
index 0000000..9060d99
--- /dev/null
+++ b/patches/linux-3.8.13/0255-fdtdump-properly-handle-multi-string-properties.patch
@@ -0,0 +1,41 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 6 Dec 2012 13:44:10 +0200
+Subject: [PATCH] fdtdump: properly handle multi-string properties
+
+Device tree can store multiple strings in a single property.
+We didn't handle that case properly.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ scripts/dtc/fdtdump.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
+index 207a46d..d4fa6d7 100644
+--- a/scripts/dtc/fdtdump.c
++++ b/scripts/dtc/fdtdump.c
+@@ -21,13 +21,23 @@ static void print_data(const char *data, int len)
+ {
+ int i;
+ const char *p = data;
++ const char *s;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ if (util_is_printable_string(data, len)) {
+- printf(" = \"%s\"", (const char *)data);
++ printf(" = ");
++
++ s = data;
++ do {
++ printf("\"%s\"", s);
++ s += strlen(s) + 1;
++ if (s < data + len)
++ printf(", ");
++ } while (s < data + len);
++
+ } else if ((len % 4) == 0) {
+ printf(" = <");
+ for (i = 0; i < len; i += 4)
diff --git a/patches/linux-3.8.13/0256-dtc-Dynamic-symbols-fixup-support.patch b/patches/linux-3.8.13/0256-dtc-Dynamic-symbols-fixup-support.patch
new file mode 100644
index 0000000..fd446cb
--- /dev/null
+++ b/patches/linux-3.8.13/0256-dtc-Dynamic-symbols-fixup-support.patch
@@ -0,0 +1,2901 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 6 Dec 2012 13:48:11 +0200
+Subject: [PATCH] dtc: Dynamic symbols & fixup support
+
+Enable the generation of symbol & fixup information for
+usage with dynamic DT loading.
+
+Passing the -@ option generates a __symbols__ node at the
+root node of the resulting blob for any node labels used.
+
+When using the /plugin/ tag all unresolved label references
+be tracked in the __fixups__ node, while all local phandle
+references will the tracked in the __local_fixups__ node.
+
+This is sufficient to implement a dynamic DT object loader.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ Documentation/devicetree/00-INDEX | 1 +
+ Documentation/devicetree/dt-object-internal.txt | 295 ++++++++++
+ scripts/dtc/checks.c | 120 +++-
+ scripts/dtc/dtc-lexer.l | 5 +
+ scripts/dtc/dtc-lexer.lex.c_shipped | 435 ++++++++-------
+ scripts/dtc/dtc-parser.tab.c_shipped | 679 ++++++++++++-----------
+ scripts/dtc/dtc-parser.tab.h_shipped | 48 +-
+ scripts/dtc/dtc-parser.y | 23 +-
+ scripts/dtc/dtc.c | 9 +-
+ scripts/dtc/dtc.h | 38 ++
+ scripts/dtc/flattree.c | 139 +++++
+ 11 files changed, 1224 insertions(+), 568 deletions(-)
+ create mode 100644 Documentation/devicetree/dt-object-internal.txt
+
+diff --git a/Documentation/devicetree/00-INDEX b/Documentation/devicetree/00-INDEX
+index b78f691..fb932e2 100644
+--- a/Documentation/devicetree/00-INDEX
++++ b/Documentation/devicetree/00-INDEX
+@@ -8,3 +8,4 @@ https://lists.ozlabs.org/listinfo/devicetree-discuss
+ - this file
+ booting-without-of.txt
+ - Booting Linux without Open Firmware, describes history and format of device trees.
++dt-object-internals.txt
+diff --git a/Documentation/devicetree/dt-object-internal.txt b/Documentation/devicetree/dt-object-internal.txt
+new file mode 100644
+index 0000000..f86d054
+--- /dev/null
++++ b/Documentation/devicetree/dt-object-internal.txt
+@@ -0,0 +1,295 @@
++Device Tree Dynamic Object format internals
++-------------------------------------------
++
++The Device Tree for most platforms is a static representation of
++the hardware capabilities. This is insufficient for many platforms
++that need to dynamically insert device tree fragments to the
++running kernel's live tree.
++
++This document explains the the device tree object format and the
++modifications made to the device tree compiler, which make it possible.
++
++1. Simplified Problem Definition
++--------------------------------
++
++Assume we have a platform which boots using following simplified device tree.
++
++---- foo.dts -----------------------------------------------------------------
++ /* FOO platform */
++ / {
++ compatible = "corp,foo";
++
++ /* shared resources */
++ res: res {
++ };
++
++ /* On chip peripherals */
++ ocp: ocp {
++ /* peripherals that are always instantiated */
++ peripheral1 { ... };
++ }
++ };
++---- foo.dts -----------------------------------------------------------------
++
++We have a number of peripherals that after probing (using some undefined method)
++should result in different device tree configuration.
++
++We cannot boot with this static tree because due to the configuration of the
++foo platform there exist multiple conficting peripherals DT fragments.
++
++So for the bar peripheral we would have this:
++
++---- foo+bar.dts -------------------------------------------------------------
++ /* FOO platform + bar peripheral */
++ / {
++ compatible = "corp,foo";
++
++ /* shared resources */
++ res: res {
++ };
++
++ /* On chip peripherals */
++ ocp: ocp {
++ /* peripherals that are always instantiated */
++ peripheral1 { ... };
++
++ /* bar peripheral */
++ bar {
++ compatible = "corp,bar";
++ ... /* various properties and child nodes */
++ }
++ }
++ };
++---- foo+bar.dts -------------------------------------------------------------
++
++While for the baz peripheral we would have this:
++
++---- foo+baz.dts -------------------------------------------------------------
++ /* FOO platform + baz peripheral */
++ / {
++ compatible = "corp,foo";
++
++ /* shared resources */
++ res: res {
++ /* baz resources */
++ baz_res: res_baz { ... };
++ };
++
++ /* On chip peripherals */
++ ocp: ocp {
++ /* peripherals that are always instantiated */
++ peripheral1 { ... };
++
++ /* baz peripheral */
++ baz {
++ compatible = "corp,baz";
++ /* reference to another point in the tree */
++ ref-to-res = <&baz_res>;
++ ... /* various properties and child nodes */
++ }
++ }
++ };
++---- foo+baz.dts -------------------------------------------------------------
++
++We note that the baz case is more complicated, since the baz peripheral needs to
++reference another node in the DT tree.
++
++2. Device Tree Object Format Requirements
++-----------------------------------------
++
++Since the device tree is used for booting a number of very different hardware
++platforms it is imperative that we tread very carefully.
++
++2.a) No changes to the Device Tree binary format. We cannot modify the tree
++format at all and all the information we require should be encoded using device
++tree itself. We can add nodes that can be safely ignored by both bootloaders and
++the kernel.
++
++2.b) Changes to the DTS source format should be absolutely minimal, and should
++only be needed for the DT fragment definitions, and not the base boot DT.
++
++2.c) An explicit option should be used to instruct DTC to generate the required
++information needed for object resolution. Platforms that don't use the
++dynamic object format can safely ignore it.
++
++2.d) Finally, DT syntax changes should be kept to a minimum. It should be
++possible to express everything using the existing DT syntax.
++
++3. Implementation
++-----------------
++
++The basic unit of addressing in Device Tree is the phandle. Turns out it's
++relatively simple to extend the way phandles are generated and referenced
++so that it's possible to dynamically convert symbolic references (labels)
++to phandle values.
++
++We can roughly divide the operation into two steps.
++
++3.a) Compilation of the base board DTS file using the '-@' option
++generates a valid DT blob with an added __symbols__ node at the root node,
++containing a list of all nodes that are marked with a label.
++
++Using the foo.dts file above the following node will be generated;
++
++$ dtc -@ -O dtb -o foo.dtb -b 0 foo.dts
++$ fdtdump foo.dtb
++...
++/ {
++ ...
++ res {
++ ...
++ linux,phandle = <0x00000001>;
++ phandle = <0x00000001>;
++ ...
++ };
++ ocp {
++ ...
++ linux,phandle = <0x00000002>;
++ phandle = <0x00000002>;
++ ...
++ };
++ __symbols__ {
++ res="/res";
++ ocp="/ocp";
++ };
++};
++
++Notice that all the nodes that had a label have been recorded, and that
++phandles have been generated for them.
++
++This blob can be used to boot the board normally, the __symbols__ node will
++be safely ignored both by the bootloader and the kernel (the only loss will
++be a few bytes of memory and disk space).
++
++3.b) The Device Tree fragments must be compiled with the same option but they
++must also have a tag (/plugin/) that allows undefined references to labels
++that are not present at compilation time to be recorded so that the runtime
++loader can fix them.
++
++So the bar peripheral's DTS format would be of the form:
++
++/plugin/; /* allow undefined label references and record them */
++/ {
++ .... /* various properties for loader use; i.e. part id etc. */
++ fragment@0 {
++ target = <&ocp>;
++ __overlay__ {
++ /* bar peripheral */
++ bar {
++ compatible = "corp,bar";
++ ... /* various properties and child nodes */
++ }
++ };
++ };
++};
++
++Note that there's a target property that specifies the location where the
++contents of the overlay node will be placed, and it references the label
++in the foo.dts file.
++
++$ dtc -@ -O dtb -o bar.dtbo -b 0 bar.dts
++$ fdtdump bar.dtbo
++...
++/ {
++ ... /* properties */
++ fragment@0 {
++ target = <0xdeadbeef>;
++ __overlay__ {
++ bar {
++ compatible = "corp,bar";
++ ... /* various properties and child nodes */
++ }
++ };
++ };
++ __fixups__ {
++ ocp = "/fragment@0:target:0";
++ };
++};
++
++No __symbols__ has been generated (no label in bar.dts).
++Note that the target's ocp label is undefined, so the phandle handle
++value is filled with the illegal value '0xdeadbeef', while a __fixups__
++node has been generated, which marks the location in the tree where
++the label lookup should store the runtime phandle value of the ocp node.
++
++The format of the __fixups__ node entry is
++
++ <label> = "<local-full-path>:<property-name>:<offset>";
++
++<label> Is the label we're referring
++<local-full-path> Is the full path of the node the reference is
++<property-name> Is the name of the property containing the
++ reference
++<offset> The offset (in bytes) of where the property's
++ phandle value is located.
++
++Doing the same with the baz peripheral's DTS format is a little bit more
++involved, since baz contains references to local labels which require
++local fixups.
++
++/plugin/; /* allow undefined label references and record them */
++/ {
++ .... /* various properties for loader use; i.e. part id etc. */
++ fragment@0 {
++ target = <&res>;
++ __overlay__ {
++ /* baz resources */
++ baz_res: res_baz { ... };
++ };
++ };
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ /* baz peripheral */
++ baz {
++ compatible = "corp,baz";
++ /* reference to another point in the tree */
++ ref-to-res = <&baz_res>;
++ ... /* various properties and child nodes */
++ }
++ };
++ };
++};
++
++Note that &bar_res reference.
++
++$ dtc -@ -O dtb -o baz.dtbo -b 0 baz.dts
++$ fdtdump baz.dtbo
++...
++/ {
++ ... /* properties */
++ fragment@0 {
++ target = <0xdeadbeef>;
++ __overlay__ {
++ res_baz {
++ ....
++ linux,phandle = <0x00000001>;
++ phandle = <0x00000001>;
++ };
++ };
++ };
++ fragment@1 {
++ target = <0xdeadbeef>;
++ __overlay__ {
++ baz {
++ compatible = "corp,baz";
++ ... /* various properties and child nodes */
++ res=<0x00000001>;
++ }
++ };
++ };
++ __fixups__ {
++ res = "/fragment@0:target:0";
++ ocp = "/fragment@1:target:0";
++ };
++ __local_fixups__ {
++ fixup = </fragment@1/__overlay__/baz:res:0>;
++ };
++};
++
++This is similar to the bar case, but the reference of a local label by the
++baz node generates a __local_fixups__ entry that records the place that the
++local reference is being made. Since phandles are allocated starting at 1
++the run time loader must apply an offset to each phandle in every dynamic
++DT object loaded. The __local_fixups__ node records the place of every
++local reference so that the loader can apply the offset.
+diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
+index ee96a25..970c0a3 100644
+--- a/scripts/dtc/checks.c
++++ b/scripts/dtc/checks.c
+@@ -457,22 +457,93 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
+ struct node *node, struct property *prop)
+ {
+ struct marker *m = prop->val.markers;
++ struct fixup *f, **fp;
++ struct fixup_entry *fe, **fep;
+ struct node *refnode;
+ cell_t phandle;
++ int has_phandle_refs;
++
++ has_phandle_refs = 0;
++ for_each_marker_of_type(m, REF_PHANDLE) {
++ has_phandle_refs = 1;
++ break;
++ }
++
++ if (!has_phandle_refs)
++ return;
+
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ assert(m->offset + sizeof(cell_t) <= prop->val.len);
+
+ refnode = get_node_by_ref(dt, m->ref);
+- if (! refnode) {
++ if (!refnode && !symbol_fixup_support) {
+ FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+- m->ref);
++ m->ref);
+ continue;
+ }
+
+- phandle = get_node_phandle(dt, refnode);
+- *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
++ if (!refnode) {
++ /* allocate fixup entry */
++ fe = xmalloc(sizeof(*fe));
++
++ fe->node = node;
++ fe->prop = prop;
++ fe->offset = m->offset;
++ fe->next = NULL;
++
++ /* search for an already existing fixup */
++ for_each_fixup(dt, f)
++ if (strcmp(f->ref, m->ref) == 0)
++ break;
++
++ /* no fixup found, add new */
++ if (f == NULL) {
++ f = xmalloc(sizeof(*f));
++ f->ref = m->ref;
++ f->entries = NULL;
++ f->next = NULL;
++
++ /* add it to the tree */
++ fp = &dt->fixups;
++ while (*fp)
++ fp = &(*fp)->next;
++ *fp = f;
++ }
++
++ /* and now append fixup entry */
++ fep = &f->entries;
++ while (*fep)
++ fep = &(*fep)->next;
++ *fep = fe;
++
++ /* mark the entry as unresolved */
++ phandle = 0xdeadbeef;
++ } else {
++ phandle = get_node_phandle(dt, refnode);
++
++ /* if it's a plugin, we need to record it */
++ if (symbol_fixup_support && dt->is_plugin) {
++
++ /* allocate a new local fixup entry */
++ fe = xmalloc(sizeof(*fe));
++
++ fe->node = node;
++ fe->prop = prop;
++ fe->offset = m->offset;
++ fe->next = NULL;
++
++ /* append it to the local fixups */
++ fep = &dt->local_fixups;
++ while (*fep)
++ fep = &(*fep)->next;
++ *fep = fe;
++ }
++ }
++
++ *((cell_t *)(prop->val.val + m->offset)) =
++ cpu_to_fdt32(phandle);
+ }
++
+ }
+ ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
+ &duplicate_node_names, &explicit_phandles);
+@@ -651,6 +722,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
+ }
+ TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
+
++static void check_auto_label_phandles(struct check *c, struct node *dt,
++ struct node *node)
++{
++ struct label *l;
++ struct symbol *s, **sp;
++ int has_label;
++
++ if (!symbol_fixup_support)
++ return;
++
++ has_label = 0;
++ for_each_label(node->labels, l) {
++ has_label = 1;
++ break;
++ }
++
++ if (!has_label)
++ return;
++
++ /* force allocation of a phandle for this node */
++ (void)get_node_phandle(dt, node);
++
++ /* add the symbol */
++ for_each_label(node->labels, l) {
++
++ s = xmalloc(sizeof(*s));
++ s->label = l;
++ s->node = node;
++ s->next = NULL;
++
++ /* add it to the symbols list */
++ sp = &dt->symbols;
++ while (*sp)
++ sp = &((*sp)->next);
++ *sp = s;
++ }
++}
++NODE_WARNING(auto_label_phandles, NULL);
++
+ static struct check *check_table[] = {
+ &duplicate_node_names, &duplicate_property_names,
+ &node_name_chars, &node_name_format, &property_name_chars,
+@@ -669,6 +779,8 @@ static struct check *check_table[] = {
+ &avoid_default_addr_size,
+ &obsolete_chosen_interrupt_controller,
+
++ &auto_label_phandles,
++
+ &always_fail,
+ };
+
+diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
+index 254d5af..2cef406 100644
+--- a/scripts/dtc/dtc-lexer.l
++++ b/scripts/dtc/dtc-lexer.l
+@@ -112,6 +112,11 @@ static int pop_input_file(void);
+ return DT_V1;
+ }
+
++<*>"/plugin/" {
++ DPRINT("Keyword: /plugin/\n");
++ return DT_PLUGIN;
++ }
++
+ <*>"/memreserve/" {
+ DPRINT("Keyword: /memreserve/\n");
+ BEGIN_DEFAULT();
+diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
+index a6c5fcd..90bfb9e 100644
+--- a/scripts/dtc/dtc-lexer.lex.c_shipped
++++ b/scripts/dtc/dtc-lexer.lex.c_shipped
+@@ -372,8 +372,8 @@ static void yy_fatal_error (yyconst char msg[] );
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+-#define YY_NUM_RULES 30
+-#define YY_END_OF_BUFFER 31
++#define YY_NUM_RULES 31
++#define YY_END_OF_BUFFER 32
+ /* This struct is not used in this scanner,
+ but its presence is necessary. */
+ struct yy_trans_info
+@@ -381,25 +381,26 @@ struct yy_trans_info
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+-static yyconst flex_int16_t yy_accept[161] =
++static yyconst flex_int16_t yy_accept[168] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+- 31, 29, 18, 18, 29, 29, 29, 29, 29, 29,
+- 29, 29, 29, 29, 29, 29, 29, 29, 15, 16,
+- 16, 29, 16, 10, 10, 18, 26, 0, 3, 0,
+- 27, 12, 0, 0, 11, 0, 0, 0, 0, 0,
+- 0, 0, 21, 23, 25, 24, 22, 0, 9, 28,
+- 0, 0, 0, 14, 14, 16, 16, 16, 10, 10,
+- 10, 0, 12, 0, 11, 0, 0, 0, 20, 0,
+- 0, 0, 0, 0, 0, 0, 0, 16, 10, 10,
+- 10, 0, 19, 0, 0, 0, 0, 0, 0, 0,
+-
+- 0, 0, 16, 13, 0, 0, 0, 0, 0, 0,
+- 0, 0, 0, 16, 6, 0, 0, 0, 0, 0,
+- 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+- 4, 17, 0, 0, 2, 0, 0, 0, 0, 0,
+- 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+- 0, 0, 5, 8, 0, 0, 0, 0, 7, 0
++ 32, 30, 19, 19, 30, 30, 30, 30, 30, 30,
++ 30, 30, 30, 30, 30, 30, 30, 30, 16, 17,
++ 17, 30, 17, 11, 11, 19, 27, 0, 3, 0,
++ 28, 13, 0, 0, 12, 0, 0, 0, 0, 0,
++ 0, 0, 0, 22, 24, 26, 25, 23, 0, 10,
++ 29, 0, 0, 0, 15, 15, 17, 17, 17, 11,
++ 11, 11, 0, 13, 0, 12, 0, 0, 0, 21,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 17,
++ 11, 11, 11, 0, 20, 0, 0, 0, 0, 0,
++
++ 0, 0, 0, 0, 0, 17, 14, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 17, 7, 0,
++ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 4, 18, 0, 0,
++ 5, 2, 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 1, 0, 0, 0, 0, 6,
++ 9, 0, 0, 0, 0, 8, 0
+ } ;
+
+ static yyconst flex_int32_t yy_ec[256] =
+@@ -415,9 +416,9 @@ static yyconst flex_int32_t yy_ec[256] =
+ 21, 21, 21, 21, 23, 21, 21, 24, 21, 21,
+ 1, 25, 26, 1, 21, 1, 20, 27, 28, 29,
+
+- 30, 20, 21, 21, 31, 21, 21, 32, 33, 34,
+- 35, 36, 21, 37, 38, 39, 40, 41, 21, 24,
+- 42, 21, 43, 44, 45, 1, 1, 1, 1, 1,
++ 30, 20, 31, 21, 32, 21, 21, 33, 34, 35,
++ 36, 37, 21, 38, 39, 40, 41, 42, 21, 24,
++ 43, 21, 44, 45, 46, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+@@ -434,163 +435,167 @@ static yyconst flex_int32_t yy_ec[256] =
+ 1, 1, 1, 1, 1
+ } ;
+
+-static yyconst flex_int32_t yy_meta[46] =
++static yyconst flex_int32_t yy_meta[47] =
+ { 0,
+ 1, 1, 1, 1, 1, 2, 3, 1, 2, 2,
+ 2, 4, 5, 5, 5, 6, 1, 1, 1, 7,
+ 8, 8, 8, 8, 1, 1, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+- 8, 8, 3, 1, 1
++ 8, 8, 8, 3, 1, 1
+ } ;
+
+-static yyconst flex_int16_t yy_base[175] =
++static yyconst flex_int16_t yy_base[182] =
+ { 0,
+- 0, 388, 381, 40, 41, 386, 71, 385, 34, 44,
+- 390, 395, 60, 62, 371, 112, 111, 111, 111, 104,
+- 370, 106, 371, 342, 124, 119, 0, 144, 395, 0,
+- 123, 0, 159, 153, 165, 167, 395, 130, 395, 382,
+- 395, 0, 372, 122, 395, 157, 374, 379, 350, 21,
+- 346, 349, 395, 395, 395, 395, 395, 362, 395, 395,
+- 181, 346, 342, 395, 359, 0, 191, 343, 190, 351,
+- 350, 0, 0, 0, 173, 362, 177, 367, 357, 329,
+- 335, 328, 337, 331, 206, 329, 334, 327, 395, 338,
+- 170, 314, 346, 345, 318, 325, 343, 158, 316, 212,
+-
+- 322, 319, 320, 395, 340, 336, 308, 305, 314, 304,
+- 295, 138, 208, 220, 395, 292, 305, 265, 264, 254,
+- 201, 222, 285, 275, 273, 270, 236, 235, 225, 115,
+- 395, 395, 252, 216, 216, 217, 214, 230, 209, 220,
+- 213, 239, 211, 217, 216, 209, 229, 395, 240, 225,
+- 206, 169, 395, 395, 116, 106, 99, 54, 395, 395,
+- 254, 260, 268, 272, 276, 282, 289, 293, 301, 309,
+- 313, 319, 327, 335
++ 0, 392, 385, 41, 42, 390, 72, 389, 35, 45,
++ 394, 399, 61, 63, 375, 114, 113, 113, 149, 105,
++ 374, 106, 375, 345, 126, 357, 0, 174, 399, 0,
++ 121, 0, 131, 127, 130, 133, 399, 121, 399, 385,
++ 399, 0, 375, 140, 399, 146, 377, 382, 352, 126,
++ 348, 352, 348, 399, 399, 399, 399, 399, 364, 399,
++ 399, 160, 347, 343, 399, 361, 0, 189, 344, 193,
++ 353, 352, 0, 0, 0, 147, 364, 158, 369, 359,
++ 330, 336, 329, 339, 332, 324, 207, 329, 335, 327,
++ 399, 339, 146, 314, 347, 346, 318, 326, 344, 34,
++
++ 316, 322, 177, 322, 318, 320, 399, 340, 336, 307,
++ 304, 313, 303, 313, 310, 172, 182, 189, 399, 311,
++ 326, 304, 309, 298, 301, 188, 209, 314, 303, 299,
++ 279, 255, 254, 268, 215, 188, 399, 399, 266, 239,
++ 399, 218, 238, 220, 232, 215, 227, 209, 236, 219,
++ 213, 212, 203, 221, 399, 233, 215, 207, 184, 399,
++ 399, 158, 120, 104, 40, 399, 399, 246, 252, 260,
++ 264, 268, 274, 281, 285, 293, 301, 305, 311, 319,
++ 327
+ } ;
+
+-static yyconst flex_int16_t yy_def[175] =
++static yyconst flex_int16_t yy_def[182] =
+ { 0,
+- 160, 1, 1, 1, 1, 5, 160, 7, 1, 1,
+- 160, 160, 160, 160, 160, 161, 162, 163, 160, 160,
+- 160, 160, 164, 160, 160, 160, 165, 164, 160, 166,
+- 167, 166, 166, 160, 160, 160, 160, 161, 160, 161,
+- 160, 168, 160, 163, 160, 163, 169, 170, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 164, 160, 160,
+- 160, 160, 160, 160, 164, 166, 167, 166, 160, 160,
+- 160, 171, 168, 172, 163, 169, 169, 170, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 166, 160, 160,
+- 171, 172, 160, 160, 160, 160, 160, 160, 160, 160,
+-
+- 160, 160, 166, 160, 160, 160, 160, 160, 160, 160,
+- 160, 173, 160, 166, 160, 160, 160, 160, 160, 160,
+- 173, 160, 173, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 174, 160, 160, 160, 174, 160, 174, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 0,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160
++ 167, 1, 1, 1, 1, 5, 167, 7, 1, 1,
++ 167, 167, 167, 167, 167, 168, 169, 170, 167, 167,
++ 167, 167, 171, 167, 167, 19, 172, 171, 167, 173,
++ 174, 173, 173, 167, 167, 167, 167, 168, 167, 168,
++ 167, 175, 167, 170, 167, 170, 176, 177, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 171, 167,
++ 167, 167, 167, 167, 167, 171, 173, 174, 173, 167,
++ 167, 167, 178, 175, 179, 170, 176, 176, 177, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 173,
++ 167, 167, 178, 179, 167, 167, 167, 167, 167, 167,
++
++ 167, 167, 167, 167, 167, 173, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 180, 167, 173, 167, 167,
++ 167, 167, 167, 167, 167, 180, 167, 180, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 181,
++ 167, 167, 167, 181, 167, 181, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 0, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167
+ } ;
+
+-static yyconst flex_int16_t yy_nxt[441] =
++static yyconst flex_int16_t yy_nxt[446] =
+ { 0,
+ 12, 13, 14, 15, 16, 12, 17, 18, 12, 12,
+ 12, 19, 12, 12, 12, 12, 20, 21, 22, 23,
+ 23, 23, 23, 23, 12, 12, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+- 23, 23, 12, 24, 12, 25, 34, 35, 35, 25,
+- 81, 26, 26, 27, 27, 27, 34, 35, 35, 82,
+- 28, 36, 36, 36, 36, 159, 29, 28, 28, 28,
+- 28, 12, 13, 14, 15, 16, 30, 17, 18, 30,
+- 30, 30, 26, 30, 30, 30, 12, 20, 21, 22,
+- 31, 31, 31, 31, 31, 32, 12, 31, 31, 31,
++ 23, 23, 23, 12, 24, 12, 25, 34, 35, 35,
++ 25, 166, 26, 26, 27, 27, 27, 34, 35, 35,
++ 112, 28, 36, 36, 36, 36, 113, 29, 28, 28,
++ 28, 28, 12, 13, 14, 15, 16, 30, 17, 18,
++ 30, 30, 30, 26, 30, 30, 30, 12, 20, 21,
++ 22, 31, 31, 31, 31, 31, 32, 12, 31, 31,
+
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+- 31, 31, 31, 12, 24, 12, 39, 41, 45, 47,
+- 53, 54, 48, 56, 57, 61, 61, 47, 66, 45,
+- 48, 66, 66, 66, 39, 46, 40, 49, 59, 50,
+- 158, 51, 122, 52, 157, 49, 46, 50, 136, 63,
+- 137, 52, 156, 43, 40, 62, 65, 65, 65, 59,
+- 61, 61, 123, 65, 75, 69, 69, 69, 36, 36,
+- 65, 65, 65, 65, 70, 71, 72, 69, 69, 69,
+- 45, 46, 61, 61, 109, 77, 70, 71, 93, 110,
+- 68, 70, 71, 85, 85, 85, 66, 46, 155, 66,
+-
+- 66, 66, 69, 69, 69, 122, 59, 100, 100, 61,
+- 61, 70, 71, 100, 100, 148, 112, 154, 85, 85,
+- 85, 61, 61, 129, 129, 123, 129, 129, 135, 135,
+- 135, 142, 142, 148, 143, 149, 153, 135, 135, 135,
+- 142, 142, 160, 143, 152, 151, 150, 146, 145, 144,
+- 141, 140, 139, 149, 38, 38, 38, 38, 38, 38,
+- 38, 38, 42, 138, 134, 133, 42, 42, 44, 44,
+- 44, 44, 44, 44, 44, 44, 58, 58, 58, 58,
+- 64, 132, 64, 66, 131, 130, 66, 160, 66, 66,
+- 67, 128, 127, 67, 67, 67, 67, 73, 126, 73,
+-
+- 73, 76, 76, 76, 76, 76, 76, 76, 76, 78,
+- 78, 78, 78, 78, 78, 78, 78, 91, 125, 91,
+- 92, 124, 92, 92, 120, 92, 92, 121, 121, 121,
+- 121, 121, 121, 121, 121, 147, 147, 147, 147, 147,
+- 147, 147, 147, 119, 118, 117, 116, 115, 47, 114,
+- 110, 113, 111, 108, 107, 106, 48, 105, 104, 89,
+- 103, 102, 101, 99, 98, 97, 96, 95, 94, 79,
+- 77, 90, 89, 88, 59, 87, 86, 59, 84, 83,
+- 80, 79, 77, 74, 160, 60, 59, 55, 37, 160,
+- 33, 25, 26, 25, 11, 160, 160, 160, 160, 160,
+-
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160
++ 31, 31, 31, 31, 31, 12, 24, 12, 39, 41,
++ 45, 54, 55, 57, 58, 39, 67, 62, 62, 67,
++ 67, 67, 62, 62, 36, 36, 60, 46, 40, 70,
++ 70, 70, 70, 70, 70, 40, 165, 45, 71, 72,
++ 73, 71, 72, 76, 45, 82, 43, 47, 63, 164,
++ 48, 62, 62, 69, 46, 83, 78, 71, 72, 95,
++ 46, 46, 87, 87, 87, 49, 127, 50, 103, 103,
++ 51, 116, 52, 62, 62, 53, 66, 66, 66, 60,
++ 62, 62, 127, 66, 67, 163, 128, 67, 67, 67,
++
++ 66, 66, 66, 66, 60, 70, 70, 70, 103, 103,
++ 135, 135, 128, 162, 71, 72, 135, 135, 161, 87,
++ 87, 87, 143, 155, 144, 155, 160, 142, 142, 142,
++ 142, 142, 142, 149, 149, 167, 150, 149, 149, 159,
++ 150, 158, 157, 156, 153, 156, 38, 38, 38, 38,
++ 38, 38, 38, 38, 42, 152, 151, 148, 42, 42,
++ 44, 44, 44, 44, 44, 44, 44, 44, 59, 59,
++ 59, 59, 65, 147, 65, 67, 146, 145, 67, 141,
++ 67, 67, 68, 140, 139, 68, 68, 68, 68, 74,
++ 138, 74, 74, 77, 77, 77, 77, 77, 77, 77,
++
++ 77, 79, 79, 79, 79, 79, 79, 79, 79, 93,
++ 137, 93, 94, 136, 94, 94, 167, 94, 94, 126,
++ 126, 126, 126, 126, 126, 126, 126, 154, 154, 154,
++ 154, 154, 154, 154, 154, 134, 133, 132, 131, 130,
++ 129, 125, 124, 123, 122, 121, 120, 119, 47, 118,
++ 113, 117, 115, 114, 111, 110, 109, 48, 108, 107,
++ 91, 106, 105, 104, 102, 101, 100, 99, 98, 97,
++ 96, 80, 78, 92, 91, 90, 60, 89, 88, 60,
++ 86, 85, 84, 81, 80, 78, 75, 167, 64, 61,
++ 60, 56, 37, 167, 33, 25, 26, 25, 11, 167,
++
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167
+ } ;
+
+-static yyconst flex_int16_t yy_chk[441] =
++static yyconst flex_int16_t yy_chk[446] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+- 1, 1, 1, 1, 1, 4, 9, 9, 9, 10,
+- 50, 4, 5, 5, 5, 5, 10, 10, 10, 50,
+- 5, 13, 13, 14, 14, 158, 5, 5, 5, 5,
+- 5, 7, 7, 7, 7, 7, 7, 7, 7, 7,
++ 1, 1, 1, 1, 1, 1, 4, 9, 9, 9,
++ 10, 165, 4, 5, 5, 5, 5, 10, 10, 10,
++ 100, 5, 13, 13, 14, 14, 100, 5, 5, 5,
++ 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+- 7, 7, 7, 7, 7, 7, 16, 17, 18, 19,
+- 20, 20, 19, 22, 22, 25, 25, 26, 31, 44,
+- 26, 31, 31, 31, 38, 18, 16, 19, 31, 19,
+- 157, 19, 112, 19, 156, 26, 44, 26, 130, 26,
+- 130, 26, 155, 17, 38, 25, 28, 28, 28, 28,
+- 33, 33, 112, 28, 46, 34, 34, 34, 36, 36,
+- 28, 28, 28, 28, 34, 34, 34, 35, 35, 35,
+- 75, 46, 61, 61, 98, 77, 35, 35, 77, 98,
+- 33, 91, 91, 61, 61, 61, 67, 75, 152, 67,
+-
+- 67, 67, 69, 69, 69, 121, 67, 85, 85, 113,
+- 113, 69, 69, 100, 100, 143, 100, 151, 85, 85,
+- 85, 114, 114, 122, 122, 121, 129, 129, 135, 135,
+- 135, 138, 138, 147, 138, 143, 150, 129, 129, 129,
+- 142, 142, 149, 142, 146, 145, 144, 141, 140, 139,
+- 137, 136, 134, 147, 161, 161, 161, 161, 161, 161,
+- 161, 161, 162, 133, 128, 127, 162, 162, 163, 163,
+- 163, 163, 163, 163, 163, 163, 164, 164, 164, 164,
+- 165, 126, 165, 166, 125, 124, 166, 123, 166, 166,
+- 167, 120, 119, 167, 167, 167, 167, 168, 118, 168,
+-
+- 168, 169, 169, 169, 169, 169, 169, 169, 169, 170,
+- 170, 170, 170, 170, 170, 170, 170, 171, 117, 171,
+- 172, 116, 172, 172, 111, 172, 172, 173, 173, 173,
+- 173, 173, 173, 173, 173, 174, 174, 174, 174, 174,
+- 174, 174, 174, 110, 109, 108, 107, 106, 105, 103,
+- 102, 101, 99, 97, 96, 95, 94, 93, 92, 90,
+- 88, 87, 86, 84, 83, 82, 81, 80, 79, 78,
+- 76, 71, 70, 68, 65, 63, 62, 58, 52, 51,
+- 49, 48, 47, 43, 40, 24, 23, 21, 15, 11,
+- 8, 6, 3, 2, 160, 160, 160, 160, 160, 160,
+-
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160
++ 7, 7, 7, 7, 7, 7, 7, 7, 16, 17,
++ 18, 20, 20, 22, 22, 38, 31, 25, 25, 31,
++ 31, 31, 33, 33, 36, 36, 31, 18, 16, 34,
++ 34, 34, 35, 35, 35, 38, 164, 44, 34, 34,
++ 34, 35, 35, 46, 76, 50, 17, 19, 25, 163,
++ 19, 62, 62, 33, 44, 50, 78, 93, 93, 78,
++ 46, 76, 62, 62, 62, 19, 116, 19, 103, 103,
++ 19, 103, 19, 117, 117, 19, 28, 28, 28, 28,
++ 118, 118, 126, 28, 68, 162, 116, 68, 68, 68,
++
++ 28, 28, 28, 28, 68, 70, 70, 70, 87, 87,
++ 127, 127, 126, 159, 70, 70, 135, 135, 158, 87,
++ 87, 87, 136, 150, 136, 154, 157, 135, 135, 135,
++ 142, 142, 142, 145, 145, 156, 145, 149, 149, 153,
++ 149, 152, 151, 150, 148, 154, 168, 168, 168, 168,
++ 168, 168, 168, 168, 169, 147, 146, 144, 169, 169,
++ 170, 170, 170, 170, 170, 170, 170, 170, 171, 171,
++ 171, 171, 172, 143, 172, 173, 140, 139, 173, 134,
++ 173, 173, 174, 133, 132, 174, 174, 174, 174, 175,
++ 131, 175, 175, 176, 176, 176, 176, 176, 176, 176,
++
++ 176, 177, 177, 177, 177, 177, 177, 177, 177, 178,
++ 130, 178, 179, 129, 179, 179, 128, 179, 179, 180,
++ 180, 180, 180, 180, 180, 180, 180, 181, 181, 181,
++ 181, 181, 181, 181, 181, 125, 124, 123, 122, 121,
++ 120, 115, 114, 113, 112, 111, 110, 109, 108, 106,
++ 105, 104, 102, 101, 99, 98, 97, 96, 95, 94,
++ 92, 90, 89, 88, 86, 85, 84, 83, 82, 81,
++ 80, 79, 77, 72, 71, 69, 66, 64, 63, 59,
++ 53, 52, 51, 49, 48, 47, 43, 40, 26, 24,
++ 23, 21, 15, 11, 8, 6, 3, 2, 167, 167,
++
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
++ 167, 167, 167, 167, 167
+ } ;
+
+ static yy_state_type yy_last_accepting_state;
+@@ -660,7 +665,7 @@ static int dts_version = 1;
+
+ static void push_input_file(const char *filename);
+ static int pop_input_file(void);
+-#line 664 "dtc-lexer.lex.c"
++#line 669 "dtc-lexer.lex.c"
+
+ #define INITIAL 0
+ #define INCLUDE 1
+@@ -854,7 +859,7 @@ YY_DECL
+
+ #line 67 "dtc-lexer.l"
+
+-#line 858 "dtc-lexer.lex.c"
++#line 863 "dtc-lexer.lex.c"
+
+ if ( !(yy_init) )
+ {
+@@ -908,13 +913,13 @@ yy_match:
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+- if ( yy_current_state >= 161 )
++ if ( yy_current_state >= 168 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+- while ( yy_current_state != 160 );
++ while ( yy_current_state != 167 );
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+
+@@ -1006,23 +1011,31 @@ case 5:
+ YY_RULE_SETUP
+ #line 115 "dtc-lexer.l"
+ {
++ DPRINT("Keyword: /plugin/\n");
++ return DT_PLUGIN;
++ }
++ YY_BREAK
++case 6:
++YY_RULE_SETUP
++#line 120 "dtc-lexer.l"
++{
+ DPRINT("Keyword: /memreserve/\n");
+ BEGIN_DEFAULT();
+ return DT_MEMRESERVE;
+ }
+ YY_BREAK
+-case 6:
++case 7:
+ YY_RULE_SETUP
+-#line 121 "dtc-lexer.l"
++#line 126 "dtc-lexer.l"
+ {
+ DPRINT("Keyword: /bits/\n");
+ BEGIN_DEFAULT();
+ return DT_BITS;
+ }
+ YY_BREAK
+-case 7:
++case 8:
+ YY_RULE_SETUP
+-#line 127 "dtc-lexer.l"
++#line 132 "dtc-lexer.l"
+ {
+ DPRINT("Keyword: /delete-property/\n");
+ DPRINT("<PROPNODENAME>\n");
+@@ -1030,9 +1043,9 @@ YY_RULE_SETUP
+ return DT_DEL_PROP;
+ }
+ YY_BREAK
+-case 8:
++case 9:
+ YY_RULE_SETUP
+-#line 134 "dtc-lexer.l"
++#line 139 "dtc-lexer.l"
+ {
+ DPRINT("Keyword: /delete-node/\n");
+ DPRINT("<PROPNODENAME>\n");
+@@ -1040,9 +1053,9 @@ YY_RULE_SETUP
+ return DT_DEL_NODE;
+ }
+ YY_BREAK
+-case 9:
++case 10:
+ YY_RULE_SETUP
+-#line 141 "dtc-lexer.l"
++#line 146 "dtc-lexer.l"
+ {
+ DPRINT("Label: %s\n", yytext);
+ yylval.labelref = xstrdup(yytext);
+@@ -1050,19 +1063,19 @@ YY_RULE_SETUP
+ return DT_LABEL;
+ }
+ YY_BREAK
+-case 10:
++case 11:
+ YY_RULE_SETUP
+-#line 148 "dtc-lexer.l"
++#line 153 "dtc-lexer.l"
+ {
+ yylval.literal = xstrdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LITERAL;
+ }
+ YY_BREAK
+-case 11:
+-/* rule 11 can match eol */
++case 12:
++/* rule 12 can match eol */
+ YY_RULE_SETUP
+-#line 154 "dtc-lexer.l"
++#line 159 "dtc-lexer.l"
+ {
+ yytext[yyleng-1] = '\0';
+ yylval.literal = xstrdup(yytext+1);
+@@ -1070,18 +1083,18 @@ YY_RULE_SETUP
+ return DT_CHAR_LITERAL;
+ }
+ YY_BREAK
+-case 12:
++case 13:
+ YY_RULE_SETUP
+-#line 161 "dtc-lexer.l"
++#line 166 "dtc-lexer.l"
+ { /* label reference */
+ DPRINT("Ref: %s\n", yytext+1);
+ yylval.labelref = xstrdup(yytext+1);
+ return DT_REF;
+ }
+ YY_BREAK
+-case 13:
++case 14:
+ YY_RULE_SETUP
+-#line 167 "dtc-lexer.l"
++#line 172 "dtc-lexer.l"
+ { /* new-style path reference */
+ yytext[yyleng-1] = '\0';
+ DPRINT("Ref: %s\n", yytext+2);
+@@ -1089,27 +1102,27 @@ YY_RULE_SETUP
+ return DT_REF;
+ }
+ YY_BREAK
+-case 14:
++case 15:
+ YY_RULE_SETUP
+-#line 174 "dtc-lexer.l"
++#line 179 "dtc-lexer.l"
+ {
+ yylval.byte = strtol(yytext, NULL, 16);
+ DPRINT("Byte: %02x\n", (int)yylval.byte);
+ return DT_BYTE;
+ }
+ YY_BREAK
+-case 15:
++case 16:
+ YY_RULE_SETUP
+-#line 180 "dtc-lexer.l"
++#line 185 "dtc-lexer.l"
+ {
+ DPRINT("/BYTESTRING\n");
+ BEGIN_DEFAULT();
+ return ']';
+ }
+ YY_BREAK
+-case 16:
++case 17:
+ YY_RULE_SETUP
+-#line 186 "dtc-lexer.l"
++#line 191 "dtc-lexer.l"
+ {
+ DPRINT("PropNodeName: %s\n", yytext);
+ yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+@@ -1118,75 +1131,75 @@ YY_RULE_SETUP
+ return DT_PROPNODENAME;
+ }
+ YY_BREAK
+-case 17:
++case 18:
+ YY_RULE_SETUP
+-#line 194 "dtc-lexer.l"
++#line 199 "dtc-lexer.l"
+ {
+ DPRINT("Binary Include\n");
+ return DT_INCBIN;
+ }
+ YY_BREAK
+-case 18:
+-/* rule 18 can match eol */
+-YY_RULE_SETUP
+-#line 199 "dtc-lexer.l"
+-/* eat whitespace */
+- YY_BREAK
+ case 19:
+ /* rule 19 can match eol */
+ YY_RULE_SETUP
+-#line 200 "dtc-lexer.l"
+-/* eat C-style comments */
++#line 204 "dtc-lexer.l"
++/* eat whitespace */
+ YY_BREAK
+ case 20:
+ /* rule 20 can match eol */
+ YY_RULE_SETUP
+-#line 201 "dtc-lexer.l"
+-/* eat C++-style comments */
++#line 205 "dtc-lexer.l"
++/* eat C-style comments */
+ YY_BREAK
+ case 21:
++/* rule 21 can match eol */
+ YY_RULE_SETUP
+-#line 203 "dtc-lexer.l"
+-{ return DT_LSHIFT; };
++#line 206 "dtc-lexer.l"
++/* eat C++-style comments */
+ YY_BREAK
+ case 22:
+ YY_RULE_SETUP
+-#line 204 "dtc-lexer.l"
+-{ return DT_RSHIFT; };
++#line 208 "dtc-lexer.l"
++{ return DT_LSHIFT; };
+ YY_BREAK
+ case 23:
+ YY_RULE_SETUP
+-#line 205 "dtc-lexer.l"
+-{ return DT_LE; };
++#line 209 "dtc-lexer.l"
++{ return DT_RSHIFT; };
+ YY_BREAK
+ case 24:
+ YY_RULE_SETUP
+-#line 206 "dtc-lexer.l"
+-{ return DT_GE; };
++#line 210 "dtc-lexer.l"
++{ return DT_LE; };
+ YY_BREAK
+ case 25:
+ YY_RULE_SETUP
+-#line 207 "dtc-lexer.l"
+-{ return DT_EQ; };
++#line 211 "dtc-lexer.l"
++{ return DT_GE; };
+ YY_BREAK
+ case 26:
+ YY_RULE_SETUP
+-#line 208 "dtc-lexer.l"
+-{ return DT_NE; };
++#line 212 "dtc-lexer.l"
++{ return DT_EQ; };
+ YY_BREAK
+ case 27:
+ YY_RULE_SETUP
+-#line 209 "dtc-lexer.l"
+-{ return DT_AND; };
++#line 213 "dtc-lexer.l"
++{ return DT_NE; };
+ YY_BREAK
+ case 28:
+ YY_RULE_SETUP
+-#line 210 "dtc-lexer.l"
+-{ return DT_OR; };
++#line 214 "dtc-lexer.l"
++{ return DT_AND; };
+ YY_BREAK
+ case 29:
+ YY_RULE_SETUP
+-#line 212 "dtc-lexer.l"
++#line 215 "dtc-lexer.l"
++{ return DT_OR; };
++ YY_BREAK
++case 30:
++YY_RULE_SETUP
++#line 217 "dtc-lexer.l"
+ {
+ DPRINT("Char: %c (\\x%02x)\n", yytext[0],
+ (unsigned)yytext[0]);
+@@ -1202,12 +1215,12 @@ YY_RULE_SETUP
+ return yytext[0];
+ }
+ YY_BREAK
+-case 30:
++case 31:
+ YY_RULE_SETUP
+-#line 227 "dtc-lexer.l"
++#line 232 "dtc-lexer.l"
+ ECHO;
+ YY_BREAK
+-#line 1211 "dtc-lexer.lex.c"
++#line 1224 "dtc-lexer.lex.c"
+
+ case YY_END_OF_BUFFER:
+ {
+@@ -1499,7 +1512,7 @@ static int yy_get_next_buffer (void)
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+- if ( yy_current_state >= 161 )
++ if ( yy_current_state >= 168 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+@@ -1527,11 +1540,11 @@ static int yy_get_next_buffer (void)
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+- if ( yy_current_state >= 161 )
++ if ( yy_current_state >= 168 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+- yy_is_jam = (yy_current_state == 160);
++ yy_is_jam = (yy_current_state == 167);
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+@@ -2166,7 +2179,7 @@ void yyfree (void * ptr )
+
+ #define YYTABLES_NAME "yytables"
+
+-#line 227 "dtc-lexer.l"
++#line 232 "dtc-lexer.l"
+
+
+
+diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
+index 4af5590..2977268 100644
+--- a/scripts/dtc/dtc-parser.tab.c_shipped
++++ b/scripts/dtc/dtc-parser.tab.c_shipped
+@@ -71,6 +71,7 @@
+ #line 21 "dtc-parser.y"
+
+ #include <stdio.h>
++#include <inttypes.h>
+
+ #include "dtc.h"
+ #include "srcpos.h"
+@@ -89,7 +90,7 @@ static unsigned char eval_char_literal(const char *s);
+
+
+ /* Line 189 of yacc.c */
+-#line 93 "dtc-parser.tab.c"
++#line 94 "dtc-parser.tab.c"
+
+ /* Enabling traces. */
+ #ifndef YYDEBUG
+@@ -117,27 +118,28 @@ static unsigned char eval_char_literal(const char *s);
+ know about them. */
+ enum yytokentype {
+ DT_V1 = 258,
+- DT_MEMRESERVE = 259,
+- DT_LSHIFT = 260,
+- DT_RSHIFT = 261,
+- DT_LE = 262,
+- DT_GE = 263,
+- DT_EQ = 264,
+- DT_NE = 265,
+- DT_AND = 266,
+- DT_OR = 267,
+- DT_BITS = 268,
+- DT_DEL_PROP = 269,
+- DT_DEL_NODE = 270,
+- DT_PROPNODENAME = 271,
+- DT_LITERAL = 272,
+- DT_CHAR_LITERAL = 273,
+- DT_BASE = 274,
+- DT_BYTE = 275,
+- DT_STRING = 276,
+- DT_LABEL = 277,
+- DT_REF = 278,
+- DT_INCBIN = 279
++ DT_PLUGIN = 259,
++ DT_MEMRESERVE = 260,
++ DT_LSHIFT = 261,
++ DT_RSHIFT = 262,
++ DT_LE = 263,
++ DT_GE = 264,
++ DT_EQ = 265,
++ DT_NE = 266,
++ DT_AND = 267,
++ DT_OR = 268,
++ DT_BITS = 269,
++ DT_DEL_PROP = 270,
++ DT_DEL_NODE = 271,
++ DT_PROPNODENAME = 272,
++ DT_LITERAL = 273,
++ DT_CHAR_LITERAL = 274,
++ DT_BASE = 275,
++ DT_BYTE = 276,
++ DT_STRING = 277,
++ DT_LABEL = 278,
++ DT_REF = 279,
++ DT_INCBIN = 280
+ };
+ #endif
+
+@@ -148,7 +150,7 @@ typedef union YYSTYPE
+ {
+
+ /* Line 214 of yacc.c */
+-#line 40 "dtc-parser.y"
++#line 41 "dtc-parser.y"
+
+ char *propnodename;
+ char *literal;
+@@ -168,11 +170,12 @@ typedef union YYSTYPE
+ struct node *nodelist;
+ struct reserve_info *re;
+ uint64_t integer;
++ int is_plugin;
+
+
+
+ /* Line 214 of yacc.c */
+-#line 176 "dtc-parser.tab.c"
++#line 179 "dtc-parser.tab.c"
+ } YYSTYPE;
+ # define YYSTYPE_IS_TRIVIAL 1
+ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
+@@ -184,7 +187,7 @@ typedef union YYSTYPE
+
+
+ /* Line 264 of yacc.c */
+-#line 188 "dtc-parser.tab.c"
++#line 191 "dtc-parser.tab.c"
+
+ #ifdef short
+ # undef short
+@@ -399,20 +402,20 @@ union yyalloc
+ /* YYFINAL -- State number of the termination state. */
+ #define YYFINAL 4
+ /* YYLAST -- Last index in YYTABLE. */
+-#define YYLAST 133
++#define YYLAST 134
+
+ /* YYNTOKENS -- Number of terminals. */
+-#define YYNTOKENS 48
++#define YYNTOKENS 49
+ /* YYNNTS -- Number of nonterminals. */
+-#define YYNNTS 28
++#define YYNNTS 29
+ /* YYNRULES -- Number of rules. */
+-#define YYNRULES 79
++#define YYNRULES 81
+ /* YYNRULES -- Number of states. */
+-#define YYNSTATES 141
++#define YYNSTATES 144
+
+ /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+ #define YYUNDEFTOK 2
+-#define YYMAXUTOK 279
++#define YYMAXUTOK 280
+
+ #define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+@@ -423,16 +426,16 @@ static const yytype_uint8 yytranslate[] =
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 47, 2, 2, 2, 45, 41, 2,
+- 33, 35, 44, 42, 34, 43, 2, 26, 2, 2,
+- 2, 2, 2, 2, 2, 2, 2, 2, 38, 25,
+- 36, 29, 30, 37, 2, 2, 2, 2, 2, 2,
++ 2, 2, 2, 48, 2, 2, 2, 46, 42, 2,
++ 34, 36, 45, 43, 35, 44, 2, 27, 2, 2,
++ 2, 2, 2, 2, 2, 2, 2, 2, 39, 26,
++ 37, 30, 31, 38, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 31, 2, 32, 40, 2, 2, 2, 2, 2,
++ 2, 32, 2, 33, 41, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+- 2, 2, 2, 27, 39, 28, 46, 2, 2, 2,
++ 2, 2, 2, 28, 40, 29, 47, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+@@ -447,7 +450,8 @@ static const yytype_uint8 yytranslate[] =
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
++ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
++ 25
+ };
+
+ #if YYDEBUG
+@@ -455,59 +459,61 @@ static const yytype_uint8 yytranslate[] =
+ YYRHS. */
+ static const yytype_uint16 yyprhs[] =
+ {
+- 0, 0, 3, 8, 9, 12, 17, 20, 23, 27,
+- 31, 36, 42, 43, 46, 51, 54, 58, 61, 64,
+- 68, 73, 76, 86, 92, 95, 96, 99, 102, 106,
+- 108, 111, 114, 117, 119, 121, 125, 127, 129, 135,
+- 137, 141, 143, 147, 149, 153, 155, 159, 161, 165,
+- 167, 171, 175, 177, 181, 185, 189, 193, 197, 201,
+- 203, 207, 211, 213, 217, 221, 225, 227, 229, 232,
+- 235, 238, 239, 242, 245, 246, 249, 252, 255, 259
++ 0, 0, 3, 9, 10, 13, 14, 17, 22, 25,
++ 28, 32, 36, 41, 47, 48, 51, 56, 59, 63,
++ 66, 69, 73, 78, 81, 91, 97, 100, 101, 104,
++ 107, 111, 113, 116, 119, 122, 124, 126, 130, 132,
++ 134, 140, 142, 146, 148, 152, 154, 158, 160, 164,
++ 166, 170, 172, 176, 180, 182, 186, 190, 194, 198,
++ 202, 206, 208, 212, 216, 218, 222, 226, 230, 232,
++ 234, 237, 240, 243, 244, 247, 250, 251, 254, 257,
++ 260, 264
+ };
+
+ /* YYRHS -- A `-1'-separated list of the rules' RHS. */
+ static const yytype_int8 yyrhs[] =
+ {
+- 49, 0, -1, 3, 25, 50, 52, -1, -1, 51,
+- 50, -1, 4, 59, 59, 25, -1, 22, 51, -1,
+- 26, 53, -1, 52, 26, 53, -1, 52, 23, 53,
+- -1, 52, 15, 23, 25, -1, 27, 54, 74, 28,
+- 25, -1, -1, 54, 55, -1, 16, 29, 56, 25,
+- -1, 16, 25, -1, 14, 16, 25, -1, 22, 55,
+- -1, 57, 21, -1, 57, 58, 30, -1, 57, 31,
+- 73, 32, -1, 57, 23, -1, 57, 24, 33, 21,
+- 34, 59, 34, 59, 35, -1, 57, 24, 33, 21,
+- 35, -1, 56, 22, -1, -1, 56, 34, -1, 57,
+- 22, -1, 13, 17, 36, -1, 36, -1, 58, 59,
+- -1, 58, 23, -1, 58, 22, -1, 17, -1, 18,
+- -1, 33, 60, 35, -1, 61, -1, 62, -1, 62,
+- 37, 60, 38, 61, -1, 63, -1, 62, 12, 63,
+- -1, 64, -1, 63, 11, 64, -1, 65, -1, 64,
+- 39, 65, -1, 66, -1, 65, 40, 66, -1, 67,
+- -1, 66, 41, 67, -1, 68, -1, 67, 9, 68,
+- -1, 67, 10, 68, -1, 69, -1, 68, 36, 69,
+- -1, 68, 30, 69, -1, 68, 7, 69, -1, 68,
+- 8, 69, -1, 69, 5, 70, -1, 69, 6, 70,
+- -1, 70, -1, 70, 42, 71, -1, 70, 43, 71,
+- -1, 71, -1, 71, 44, 72, -1, 71, 26, 72,
+- -1, 71, 45, 72, -1, 72, -1, 59, -1, 43,
+- 72, -1, 46, 72, -1, 47, 72, -1, -1, 73,
+- 20, -1, 73, 22, -1, -1, 75, 74, -1, 75,
+- 55, -1, 16, 53, -1, 15, 16, 25, -1, 22,
+- 75, -1
++ 50, 0, -1, 3, 26, 51, 52, 54, -1, -1,
++ 4, 26, -1, -1, 53, 52, -1, 5, 61, 61,
++ 26, -1, 23, 53, -1, 27, 55, -1, 54, 27,
++ 55, -1, 54, 24, 55, -1, 54, 16, 24, 26,
++ -1, 28, 56, 76, 29, 26, -1, -1, 56, 57,
++ -1, 17, 30, 58, 26, -1, 17, 26, -1, 15,
++ 17, 26, -1, 23, 57, -1, 59, 22, -1, 59,
++ 60, 31, -1, 59, 32, 75, 33, -1, 59, 24,
++ -1, 59, 25, 34, 22, 35, 61, 35, 61, 36,
++ -1, 59, 25, 34, 22, 36, -1, 58, 23, -1,
++ -1, 58, 35, -1, 59, 23, -1, 14, 18, 37,
++ -1, 37, -1, 60, 61, -1, 60, 24, -1, 60,
++ 23, -1, 18, -1, 19, -1, 34, 62, 36, -1,
++ 63, -1, 64, -1, 64, 38, 62, 39, 63, -1,
++ 65, -1, 64, 13, 65, -1, 66, -1, 65, 12,
++ 66, -1, 67, -1, 66, 40, 67, -1, 68, -1,
++ 67, 41, 68, -1, 69, -1, 68, 42, 69, -1,
++ 70, -1, 69, 10, 70, -1, 69, 11, 70, -1,
++ 71, -1, 70, 37, 71, -1, 70, 31, 71, -1,
++ 70, 8, 71, -1, 70, 9, 71, -1, 71, 6,
++ 72, -1, 71, 7, 72, -1, 72, -1, 72, 43,
++ 73, -1, 72, 44, 73, -1, 73, -1, 73, 45,
++ 74, -1, 73, 27, 74, -1, 73, 46, 74, -1,
++ 74, -1, 61, -1, 44, 74, -1, 47, 74, -1,
++ 48, 74, -1, -1, 75, 21, -1, 75, 23, -1,
++ -1, 77, 76, -1, 77, 57, -1, 17, 55, -1,
++ 16, 17, 26, -1, 23, 77, -1
+ };
+
+ /* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+ static const yytype_uint16 yyrline[] =
+ {
+- 0, 109, 109, 118, 121, 128, 132, 140, 144, 148,
+- 158, 172, 180, 183, 190, 194, 198, 202, 210, 214,
+- 218, 222, 226, 243, 253, 261, 264, 268, 275, 290,
+- 295, 315, 329, 336, 340, 344, 351, 355, 356, 360,
+- 361, 365, 366, 370, 371, 375, 376, 380, 381, 385,
+- 386, 387, 391, 392, 393, 394, 395, 399, 400, 401,
+- 405, 406, 407, 411, 412, 413, 414, 418, 419, 420,
+- 421, 426, 429, 433, 441, 444, 448, 456, 460, 464
++ 0, 113, 113, 124, 127, 135, 138, 145, 149, 157,
++ 161, 165, 175, 189, 197, 200, 207, 211, 215, 219,
++ 227, 231, 235, 239, 243, 260, 270, 278, 281, 285,
++ 292, 307, 312, 332, 346, 353, 357, 361, 368, 372,
++ 373, 377, 378, 382, 383, 387, 388, 392, 393, 397,
++ 398, 402, 403, 404, 408, 409, 410, 411, 412, 416,
++ 417, 418, 422, 423, 424, 428, 429, 430, 431, 435,
++ 436, 437, 438, 443, 446, 450, 458, 461, 465, 473,
++ 477, 481
+ };
+ #endif
+
+@@ -516,19 +522,20 @@ static const yytype_uint16 yyrline[] =
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+ static const char *const yytname[] =
+ {
+- "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
+- "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
+- "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
+- "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL",
+- "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
+- "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
+- "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
+- "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
+- "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
+- "integer_expr", "integer_trinary", "integer_or", "integer_and",
+- "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
+- "integer_rela", "integer_shift", "integer_add", "integer_mul",
+- "integer_unary", "bytestring", "subnodes", "subnode", 0
++ "$end", "error", "$undefined", "DT_V1", "DT_PLUGIN", "DT_MEMRESERVE",
++ "DT_LSHIFT", "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND",
++ "DT_OR", "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME",
++ "DT_LITERAL", "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING",
++ "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='",
++ "'>'", "'['", "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'",
++ "'^'", "'&'", "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept",
++ "sourcefile", "plugindecl", "memreserves", "memreserve", "devicetree",
++ "nodedef", "proplist", "propdef", "propdata", "propdataprefix",
++ "arrayprefix", "integer_prim", "integer_expr", "integer_trinary",
++ "integer_or", "integer_and", "integer_bitor", "integer_bitxor",
++ "integer_bitand", "integer_eq", "integer_rela", "integer_shift",
++ "integer_add", "integer_mul", "integer_unary", "bytestring", "subnodes",
++ "subnode", 0
+ };
+ #endif
+
+@@ -539,36 +546,38 @@ static const yytype_uint16 yytoknum[] =
+ {
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+- 275, 276, 277, 278, 279, 59, 47, 123, 125, 61,
+- 62, 91, 93, 40, 44, 41, 60, 63, 58, 124,
+- 94, 38, 43, 45, 42, 37, 126, 33
++ 275, 276, 277, 278, 279, 280, 59, 47, 123, 125,
++ 61, 62, 91, 93, 40, 44, 41, 60, 63, 58,
++ 124, 94, 38, 43, 45, 42, 37, 126, 33
+ };
+ # endif
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+ static const yytype_uint8 yyr1[] =
+ {
+- 0, 48, 49, 50, 50, 51, 51, 52, 52, 52,
+- 52, 53, 54, 54, 55, 55, 55, 55, 56, 56,
+- 56, 56, 56, 56, 56, 57, 57, 57, 58, 58,
+- 58, 58, 58, 59, 59, 59, 60, 61, 61, 62,
+- 62, 63, 63, 64, 64, 65, 65, 66, 66, 67,
+- 67, 67, 68, 68, 68, 68, 68, 69, 69, 69,
+- 70, 70, 70, 71, 71, 71, 71, 72, 72, 72,
+- 72, 73, 73, 73, 74, 74, 74, 75, 75, 75
++ 0, 49, 50, 51, 51, 52, 52, 53, 53, 54,
++ 54, 54, 54, 55, 56, 56, 57, 57, 57, 57,
++ 58, 58, 58, 58, 58, 58, 58, 59, 59, 59,
++ 60, 60, 60, 60, 60, 61, 61, 61, 62, 63,
++ 63, 64, 64, 65, 65, 66, 66, 67, 67, 68,
++ 68, 69, 69, 69, 70, 70, 70, 70, 70, 71,
++ 71, 71, 72, 72, 72, 73, 73, 73, 73, 74,
++ 74, 74, 74, 75, 75, 75, 76, 76, 76, 77,
++ 77, 77
+ };
+
+ /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+ static const yytype_uint8 yyr2[] =
+ {
+- 0, 2, 4, 0, 2, 4, 2, 2, 3, 3,
+- 4, 5, 0, 2, 4, 2, 3, 2, 2, 3,
+- 4, 2, 9, 5, 2, 0, 2, 2, 3, 1,
+- 2, 2, 2, 1, 1, 3, 1, 1, 5, 1,
+- 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+- 3, 3, 1, 3, 3, 3, 3, 3, 3, 1,
+- 3, 3, 1, 3, 3, 3, 1, 1, 2, 2,
+- 2, 0, 2, 2, 0, 2, 2, 2, 3, 2
++ 0, 2, 5, 0, 2, 0, 2, 4, 2, 2,
++ 3, 3, 4, 5, 0, 2, 4, 2, 3, 2,
++ 2, 3, 4, 2, 9, 5, 2, 0, 2, 2,
++ 3, 1, 2, 2, 2, 1, 1, 3, 1, 1,
++ 5, 1, 3, 1, 3, 1, 3, 1, 3, 1,
++ 3, 1, 3, 3, 1, 3, 3, 3, 3, 3,
++ 3, 1, 3, 3, 1, 3, 3, 3, 1, 1,
++ 2, 2, 2, 0, 2, 2, 0, 2, 2, 2,
++ 3, 2
+ };
+
+ /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+@@ -576,59 +585,59 @@ static const yytype_uint8 yyr2[] =
+ means the default is an error. */
+ static const yytype_uint8 yydefact[] =
+ {
+- 0, 0, 0, 3, 1, 0, 0, 0, 3, 33,
+- 34, 0, 0, 6, 0, 2, 4, 0, 0, 0,
+- 67, 0, 36, 37, 39, 41, 43, 45, 47, 49,
+- 52, 59, 62, 66, 0, 12, 7, 0, 0, 0,
+- 68, 69, 70, 35, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 3, 1, 0, 5, 4, 0, 0,
++ 0, 5, 35, 36, 0, 0, 8, 0, 2, 6,
++ 0, 0, 0, 69, 0, 38, 39, 41, 43, 45,
++ 47, 49, 51, 54, 61, 64, 68, 0, 14, 9,
++ 0, 0, 0, 70, 71, 72, 37, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+- 0, 0, 0, 5, 74, 0, 9, 8, 40, 0,
+- 42, 44, 46, 48, 50, 51, 55, 56, 54, 53,
+- 57, 58, 60, 61, 64, 63, 65, 0, 0, 0,
+- 0, 13, 0, 74, 10, 0, 0, 0, 15, 25,
+- 77, 17, 79, 0, 76, 75, 38, 16, 78, 0,
+- 0, 11, 24, 14, 26, 0, 18, 27, 21, 0,
+- 71, 29, 0, 0, 0, 0, 32, 31, 19, 30,
+- 28, 0, 72, 73, 20, 0, 23, 0, 0, 0,
+- 22
++ 0, 0, 0, 0, 0, 0, 7, 76, 0, 11,
++ 10, 42, 0, 44, 46, 48, 50, 52, 53, 57,
++ 58, 56, 55, 59, 60, 62, 63, 66, 65, 67,
++ 0, 0, 0, 0, 15, 0, 76, 12, 0, 0,
++ 0, 17, 27, 79, 19, 81, 0, 78, 77, 40,
++ 18, 80, 0, 0, 13, 26, 16, 28, 0, 20,
++ 29, 23, 0, 73, 31, 0, 0, 0, 0, 34,
++ 33, 21, 32, 30, 0, 74, 75, 22, 0, 25,
++ 0, 0, 0, 24
+ };
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+-static const yytype_int8 yydefgoto[] =
++static const yytype_int16 yydefgoto[] =
+ {
+- -1, 2, 7, 8, 15, 36, 64, 91, 109, 110,
+- 122, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+- 29, 30, 31, 32, 33, 125, 92, 93
++ -1, 2, 6, 10, 11, 18, 39, 67, 94, 112,
++ 113, 125, 23, 24, 25, 26, 27, 28, 29, 30,
++ 31, 32, 33, 34, 35, 36, 128, 95, 96
+ };
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+-#define YYPACT_NINF -78
++#define YYPACT_NINF -81
+ static const yytype_int8 yypact[] =
+ {
+- 22, 11, 51, 10, -78, 23, 10, 2, 10, -78,
+- -78, -9, 23, -78, 30, 38, -78, -9, -9, -9,
+- -78, 35, -78, -6, 52, 29, 48, 49, 33, 3,
+- 71, 36, 0, -78, 64, -78, -78, 68, 30, 30,
+- -78, -78, -78, -78, -9, -9, -9, -9, -9, -9,
+- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
+- -9, -9, -9, -78, 44, 67, -78, -78, 52, 55,
+- 29, 48, 49, 33, 3, 3, 71, 71, 71, 71,
+- 36, 36, 0, 0, -78, -78, -78, 78, 79, 42,
+- 44, -78, 69, 44, -78, -9, 73, 74, -78, -78,
+- -78, -78, -78, 75, -78, -78, -78, -78, -78, -7,
+- -1, -78, -78, -78, -78, 84, -78, -78, -78, 63,
+- -78, -78, 32, 66, 82, -3, -78, -78, -78, -78,
+- -78, 46, -78, -78, -78, 23, -78, 70, 23, 72,
+- -78
++ 33, 44, 63, 47, -81, 46, 9, -81, 22, 9,
++ 55, 9, -81, -81, -10, 22, -81, -3, 37, -81,
++ -10, -10, -10, -81, 49, -81, -7, 76, 50, 48,
++ 52, 8, 2, 36, -15, -1, -81, 65, -81, -81,
++ 68, -3, -3, -81, -81, -81, -81, -10, -10, -10,
++ -10, -10, -10, -10, -10, -10, -10, -10, -10, -10,
++ -10, -10, -10, -10, -10, -10, -81, 51, 67, -81,
++ -81, 76, 56, 50, 48, 52, 8, 2, 2, 36,
++ 36, 36, 36, -15, -15, -1, -1, -81, -81, -81,
++ 79, 80, 45, 51, -81, 69, 51, -81, -10, 73,
++ 74, -81, -81, -81, -81, -81, 75, -81, -81, -81,
++ -81, -81, 34, -2, -81, -81, -81, -81, 84, -81,
++ -81, -81, 70, -81, -81, 31, 66, 83, -6, -81,
++ -81, -81, -81, -81, 23, -81, -81, -81, 22, -81,
++ 71, 22, 72, -81
+ };
+
+ /* YYPGOTO[NTERM-NUM]. */
+ static const yytype_int8 yypgoto[] =
+ {
+- -78, -78, 97, 100, -78, -37, -78, -77, -78, -78,
+- -78, -5, 65, 13, -78, 76, 77, 62, 80, 83,
+- 34, 20, 26, 28, -14, -78, 18, 24
++ -81, -81, -81, 96, 100, -81, -40, -81, -80, -81,
++ -81, -81, -8, 62, 13, -81, 77, 64, 78, 61,
++ 82, 27, 21, 24, 25, -17, -81, 18, 26
+ };
+
+ /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+@@ -638,59 +647,59 @@ static const yytype_int8 yypgoto[] =
+ #define YYTABLE_NINF -1
+ static const yytype_uint8 yytable[] =
+ {
+- 12, 66, 67, 40, 41, 42, 44, 34, 9, 10,
+- 52, 53, 115, 101, 5, 112, 104, 132, 113, 133,
+- 116, 117, 118, 119, 11, 1, 60, 114, 14, 134,
+- 120, 45, 6, 54, 17, 121, 3, 18, 19, 55,
+- 9, 10, 50, 51, 61, 62, 84, 85, 86, 9,
+- 10, 4, 100, 37, 126, 127, 11, 35, 87, 88,
+- 89, 38, 128, 46, 39, 11, 90, 98, 47, 35,
+- 43, 99, 76, 77, 78, 79, 56, 57, 58, 59,
+- 135, 136, 80, 81, 74, 75, 82, 83, 48, 63,
+- 49, 65, 94, 95, 96, 97, 124, 103, 107, 108,
+- 111, 123, 130, 131, 138, 16, 13, 140, 106, 71,
+- 69, 105, 0, 0, 102, 0, 0, 129, 0, 0,
+- 68, 0, 0, 70, 0, 0, 0, 0, 72, 0,
+- 137, 0, 73, 139
++ 15, 69, 70, 43, 44, 45, 47, 37, 12, 13,
++ 55, 56, 118, 104, 8, 135, 107, 136, 53, 54,
++ 119, 120, 121, 122, 14, 38, 63, 137, 61, 62,
++ 123, 48, 9, 57, 20, 124, 1, 21, 22, 58,
++ 12, 13, 59, 60, 64, 65, 87, 88, 89, 12,
++ 13, 5, 103, 40, 129, 130, 14, 115, 138, 139,
++ 116, 41, 131, 4, 42, 14, 90, 91, 92, 117,
++ 3, 101, 7, 38, 93, 102, 79, 80, 81, 82,
++ 77, 78, 17, 83, 84, 46, 85, 86, 49, 51,
++ 50, 66, 68, 97, 52, 98, 99, 100, 106, 110,
++ 111, 114, 126, 133, 127, 134, 141, 19, 143, 16,
++ 72, 109, 75, 73, 108, 0, 0, 132, 0, 105,
++ 0, 0, 0, 0, 71, 0, 0, 0, 74, 0,
++ 140, 0, 0, 142, 76
+ };
+
+ static const yytype_int16 yycheck[] =
+ {
+- 5, 38, 39, 17, 18, 19, 12, 12, 17, 18,
+- 7, 8, 13, 90, 4, 22, 93, 20, 25, 22,
+- 21, 22, 23, 24, 33, 3, 26, 34, 26, 32,
+- 31, 37, 22, 30, 43, 36, 25, 46, 47, 36,
+- 17, 18, 9, 10, 44, 45, 60, 61, 62, 17,
+- 18, 0, 89, 15, 22, 23, 33, 27, 14, 15,
+- 16, 23, 30, 11, 26, 33, 22, 25, 39, 27,
+- 35, 29, 52, 53, 54, 55, 5, 6, 42, 43,
+- 34, 35, 56, 57, 50, 51, 58, 59, 40, 25,
+- 41, 23, 25, 38, 16, 16, 33, 28, 25, 25,
+- 25, 17, 36, 21, 34, 8, 6, 35, 95, 47,
+- 45, 93, -1, -1, 90, -1, -1, 122, -1, -1,
+- 44, -1, -1, 46, -1, -1, -1, -1, 48, -1,
+- 135, -1, 49, 138
++ 8, 41, 42, 20, 21, 22, 13, 15, 18, 19,
++ 8, 9, 14, 93, 5, 21, 96, 23, 10, 11,
++ 22, 23, 24, 25, 34, 28, 27, 33, 43, 44,
++ 32, 38, 23, 31, 44, 37, 3, 47, 48, 37,
++ 18, 19, 6, 7, 45, 46, 63, 64, 65, 18,
++ 19, 4, 92, 16, 23, 24, 34, 23, 35, 36,
++ 26, 24, 31, 0, 27, 34, 15, 16, 17, 35,
++ 26, 26, 26, 28, 23, 30, 55, 56, 57, 58,
++ 53, 54, 27, 59, 60, 36, 61, 62, 12, 41,
++ 40, 26, 24, 26, 42, 39, 17, 17, 29, 26,
++ 26, 26, 18, 37, 34, 22, 35, 11, 36, 9,
++ 48, 98, 51, 49, 96, -1, -1, 125, -1, 93,
++ -1, -1, -1, -1, 47, -1, -1, -1, 50, -1,
++ 138, -1, -1, 141, 52
+ };
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+ static const yytype_uint8 yystos[] =
+ {
+- 0, 3, 49, 25, 0, 4, 22, 50, 51, 17,
+- 18, 33, 59, 51, 26, 52, 50, 43, 46, 47,
+- 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+- 69, 70, 71, 72, 59, 27, 53, 15, 23, 26,
+- 72, 72, 72, 35, 12, 37, 11, 39, 40, 41,
+- 9, 10, 7, 8, 30, 36, 5, 6, 42, 43,
+- 26, 44, 45, 25, 54, 23, 53, 53, 63, 60,
+- 64, 65, 66, 67, 68, 68, 69, 69, 69, 69,
+- 70, 70, 71, 71, 72, 72, 72, 14, 15, 16,
+- 22, 55, 74, 75, 25, 38, 16, 16, 25, 29,
+- 53, 55, 75, 28, 55, 74, 61, 25, 25, 56,
+- 57, 25, 22, 25, 34, 13, 21, 22, 23, 24,
+- 31, 36, 58, 17, 33, 73, 22, 23, 30, 59,
+- 36, 21, 20, 22, 32, 34, 35, 59, 34, 59,
+- 35
++ 0, 3, 50, 26, 0, 4, 51, 26, 5, 23,
++ 52, 53, 18, 19, 34, 61, 53, 27, 54, 52,
++ 44, 47, 48, 61, 62, 63, 64, 65, 66, 67,
++ 68, 69, 70, 71, 72, 73, 74, 61, 28, 55,
++ 16, 24, 27, 74, 74, 74, 36, 13, 38, 12,
++ 40, 41, 42, 10, 11, 8, 9, 31, 37, 6,
++ 7, 43, 44, 27, 45, 46, 26, 56, 24, 55,
++ 55, 65, 62, 66, 67, 68, 69, 70, 70, 71,
++ 71, 71, 71, 72, 72, 73, 73, 74, 74, 74,
++ 15, 16, 17, 23, 57, 76, 77, 26, 39, 17,
++ 17, 26, 30, 55, 57, 77, 29, 57, 76, 63,
++ 26, 26, 58, 59, 26, 23, 26, 35, 14, 22,
++ 23, 24, 25, 32, 37, 60, 18, 34, 75, 23,
++ 24, 31, 61, 37, 22, 21, 23, 33, 35, 36,
++ 61, 35, 61, 36
+ };
+
+ #define yyerrok (yyerrstatus = 0)
+@@ -1504,72 +1513,92 @@ yyreduce:
+ case 2:
+
+ /* Line 1455 of yacc.c */
+-#line 110 "dtc-parser.y"
++#line 114 "dtc-parser.y"
+ {
+- the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
+- guess_boot_cpuid((yyvsp[(4) - (4)].node)));
++ (yyvsp[(5) - (5)].node)->is_plugin = (yyvsp[(3) - (5)].is_plugin);
++ (yyvsp[(5) - (5)].node)->is_root = 1;
++ the_boot_info = build_boot_info((yyvsp[(4) - (5)].re), (yyvsp[(5) - (5)].node),
++ guess_boot_cpuid((yyvsp[(5) - (5)].node)));
+ ;}
+ break;
+
+ case 3:
+
+ /* Line 1455 of yacc.c */
+-#line 118 "dtc-parser.y"
++#line 124 "dtc-parser.y"
+ {
+- (yyval.re) = NULL;
++ (yyval.is_plugin) = 0;
+ ;}
+ break;
+
+ case 4:
+
+ /* Line 1455 of yacc.c */
+-#line 122 "dtc-parser.y"
++#line 128 "dtc-parser.y"
+ {
+- (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
++ (yyval.is_plugin) = 1;
+ ;}
+ break;
+
+ case 5:
+
+ /* Line 1455 of yacc.c */
+-#line 129 "dtc-parser.y"
++#line 135 "dtc-parser.y"
+ {
+- (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
++ (yyval.re) = NULL;
+ ;}
+ break;
+
+ case 6:
+
+ /* Line 1455 of yacc.c */
+-#line 133 "dtc-parser.y"
++#line 139 "dtc-parser.y"
++ {
++ (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
++ ;}
++ break;
++
++ case 7:
++
++/* Line 1455 of yacc.c */
++#line 146 "dtc-parser.y"
++ {
++ (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
++ ;}
++ break;
++
++ case 8:
++
++/* Line 1455 of yacc.c */
++#line 150 "dtc-parser.y"
+ {
+ add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
+ (yyval.re) = (yyvsp[(2) - (2)].re);
+ ;}
+ break;
+
+- case 7:
++ case 9:
+
+ /* Line 1455 of yacc.c */
+-#line 141 "dtc-parser.y"
++#line 158 "dtc-parser.y"
+ {
+ (yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
+ ;}
+ break;
+
+- case 8:
++ case 10:
+
+ /* Line 1455 of yacc.c */
+-#line 145 "dtc-parser.y"
++#line 162 "dtc-parser.y"
+ {
+ (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+ ;}
+ break;
+
+- case 9:
++ case 11:
+
+ /* Line 1455 of yacc.c */
+-#line 149 "dtc-parser.y"
++#line 166 "dtc-parser.y"
+ {
+ struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
+
+@@ -1581,10 +1610,10 @@ yyreduce:
+ ;}
+ break;
+
+- case 10:
++ case 12:
+
+ /* Line 1455 of yacc.c */
+-#line 159 "dtc-parser.y"
++#line 176 "dtc-parser.y"
+ {
+ struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
+
+@@ -1597,110 +1626,110 @@ yyreduce:
+ ;}
+ break;
+
+- case 11:
++ case 13:
+
+ /* Line 1455 of yacc.c */
+-#line 173 "dtc-parser.y"
++#line 190 "dtc-parser.y"
+ {
+ (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
+ ;}
+ break;
+
+- case 12:
++ case 14:
+
+ /* Line 1455 of yacc.c */
+-#line 180 "dtc-parser.y"
++#line 197 "dtc-parser.y"
+ {
+ (yyval.proplist) = NULL;
+ ;}
+ break;
+
+- case 13:
++ case 15:
+
+ /* Line 1455 of yacc.c */
+-#line 184 "dtc-parser.y"
++#line 201 "dtc-parser.y"
+ {
+ (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
+ ;}
+ break;
+
+- case 14:
++ case 16:
+
+ /* Line 1455 of yacc.c */
+-#line 191 "dtc-parser.y"
++#line 208 "dtc-parser.y"
+ {
+ (yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
+ ;}
+ break;
+
+- case 15:
++ case 17:
+
+ /* Line 1455 of yacc.c */
+-#line 195 "dtc-parser.y"
++#line 212 "dtc-parser.y"
+ {
+ (yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
+ ;}
+ break;
+
+- case 16:
++ case 18:
+
+ /* Line 1455 of yacc.c */
+-#line 199 "dtc-parser.y"
++#line 216 "dtc-parser.y"
+ {
+ (yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename));
+ ;}
+ break;
+
+- case 17:
++ case 19:
+
+ /* Line 1455 of yacc.c */
+-#line 203 "dtc-parser.y"
++#line 220 "dtc-parser.y"
+ {
+ add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
+ (yyval.prop) = (yyvsp[(2) - (2)].prop);
+ ;}
+ break;
+
+- case 18:
++ case 20:
+
+ /* Line 1455 of yacc.c */
+-#line 211 "dtc-parser.y"
++#line 228 "dtc-parser.y"
+ {
+ (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
+ ;}
+ break;
+
+- case 19:
++ case 21:
+
+ /* Line 1455 of yacc.c */
+-#line 215 "dtc-parser.y"
++#line 232 "dtc-parser.y"
+ {
+ (yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data);
+ ;}
+ break;
+
+- case 20:
++ case 22:
+
+ /* Line 1455 of yacc.c */
+-#line 219 "dtc-parser.y"
++#line 236 "dtc-parser.y"
+ {
+ (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+ ;}
+ break;
+
+- case 21:
++ case 23:
+
+ /* Line 1455 of yacc.c */
+-#line 223 "dtc-parser.y"
++#line 240 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+- case 22:
++ case 24:
+
+ /* Line 1455 of yacc.c */
+-#line 227 "dtc-parser.y"
++#line 244 "dtc-parser.y"
+ {
+ FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
+ struct data d;
+@@ -1719,10 +1748,10 @@ yyreduce:
+ ;}
+ break;
+
+- case 23:
++ case 25:
+
+ /* Line 1455 of yacc.c */
+-#line 244 "dtc-parser.y"
++#line 261 "dtc-parser.y"
+ {
+ FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
+ struct data d = empty_data;
+@@ -1734,46 +1763,46 @@ yyreduce:
+ ;}
+ break;
+
+- case 24:
++ case 26:
+
+ /* Line 1455 of yacc.c */
+-#line 254 "dtc-parser.y"
++#line 271 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+- case 25:
++ case 27:
+
+ /* Line 1455 of yacc.c */
+-#line 261 "dtc-parser.y"
++#line 278 "dtc-parser.y"
+ {
+ (yyval.data) = empty_data;
+ ;}
+ break;
+
+- case 26:
++ case 28:
+
+ /* Line 1455 of yacc.c */
+-#line 265 "dtc-parser.y"
++#line 282 "dtc-parser.y"
+ {
+ (yyval.data) = (yyvsp[(1) - (2)].data);
+ ;}
+ break;
+
+- case 27:
++ case 29:
+
+ /* Line 1455 of yacc.c */
+-#line 269 "dtc-parser.y"
++#line 286 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+- case 28:
++ case 30:
+
+ /* Line 1455 of yacc.c */
+-#line 276 "dtc-parser.y"
++#line 293 "dtc-parser.y"
+ {
+ (yyval.array).data = empty_data;
+ (yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7);
+@@ -1790,20 +1819,20 @@ yyreduce:
+ ;}
+ break;
+
+- case 29:
++ case 31:
+
+ /* Line 1455 of yacc.c */
+-#line 291 "dtc-parser.y"
++#line 308 "dtc-parser.y"
+ {
+ (yyval.array).data = empty_data;
+ (yyval.array).bits = 32;
+ ;}
+ break;
+
+- case 30:
++ case 32:
+
+ /* Line 1455 of yacc.c */
+-#line 296 "dtc-parser.y"
++#line 313 "dtc-parser.y"
+ {
+ if ((yyvsp[(1) - (2)].array).bits < 64) {
+ uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1;
+@@ -1825,10 +1854,10 @@ yyreduce:
+ ;}
+ break;
+
+- case 31:
++ case 33:
+
+ /* Line 1455 of yacc.c */
+-#line 316 "dtc-parser.y"
++#line 333 "dtc-parser.y"
+ {
+ uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits);
+
+@@ -1844,273 +1873,273 @@ yyreduce:
+ ;}
+ break;
+
+- case 32:
++ case 34:
+
+ /* Line 1455 of yacc.c */
+-#line 330 "dtc-parser.y"
++#line 347 "dtc-parser.y"
+ {
+ (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+- case 33:
++ case 35:
+
+ /* Line 1455 of yacc.c */
+-#line 337 "dtc-parser.y"
++#line 354 "dtc-parser.y"
+ {
+ (yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
+ ;}
+ break;
+
+- case 34:
++ case 36:
+
+ /* Line 1455 of yacc.c */
+-#line 341 "dtc-parser.y"
++#line 358 "dtc-parser.y"
+ {
+ (yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal));
+ ;}
+ break;
+
+- case 35:
++ case 37:
+
+ /* Line 1455 of yacc.c */
+-#line 345 "dtc-parser.y"
++#line 362 "dtc-parser.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (3)].integer);
+ ;}
+ break;
+
+- case 38:
++ case 40:
+
+ /* Line 1455 of yacc.c */
+-#line 356 "dtc-parser.y"
++#line 373 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); ;}
+ break;
+
+- case 40:
++ case 42:
+
+ /* Line 1455 of yacc.c */
+-#line 361 "dtc-parser.y"
++#line 378 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 42:
++ case 44:
+
+ /* Line 1455 of yacc.c */
+-#line 366 "dtc-parser.y"
++#line 383 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 44:
++ case 46:
+
+ /* Line 1455 of yacc.c */
+-#line 371 "dtc-parser.y"
++#line 388 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 46:
++ case 48:
+
+ /* Line 1455 of yacc.c */
+-#line 376 "dtc-parser.y"
++#line 393 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 48:
++ case 50:
+
+ /* Line 1455 of yacc.c */
+-#line 381 "dtc-parser.y"
++#line 398 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 50:
++ case 52:
+
+ /* Line 1455 of yacc.c */
+-#line 386 "dtc-parser.y"
++#line 403 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 51:
++ case 53:
+
+ /* Line 1455 of yacc.c */
+-#line 387 "dtc-parser.y"
++#line 404 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 53:
++ case 55:
+
+ /* Line 1455 of yacc.c */
+-#line 392 "dtc-parser.y"
++#line 409 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 54:
++ case 56:
+
+ /* Line 1455 of yacc.c */
+-#line 393 "dtc-parser.y"
++#line 410 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 55:
++ case 57:
+
+ /* Line 1455 of yacc.c */
+-#line 394 "dtc-parser.y"
++#line 411 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 56:
++ case 58:
+
+ /* Line 1455 of yacc.c */
+-#line 395 "dtc-parser.y"
++#line 412 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 57:
++ case 59:
+
+ /* Line 1455 of yacc.c */
+-#line 399 "dtc-parser.y"
++#line 416 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 58:
++ case 60:
+
+ /* Line 1455 of yacc.c */
+-#line 400 "dtc-parser.y"
++#line 417 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 60:
++ case 62:
+
+ /* Line 1455 of yacc.c */
+-#line 405 "dtc-parser.y"
++#line 422 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 61:
++ case 63:
+
+ /* Line 1455 of yacc.c */
+-#line 406 "dtc-parser.y"
++#line 423 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 63:
++ case 65:
+
+ /* Line 1455 of yacc.c */
+-#line 411 "dtc-parser.y"
++#line 428 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 64:
++ case 66:
+
+ /* Line 1455 of yacc.c */
+-#line 412 "dtc-parser.y"
++#line 429 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 65:
++ case 67:
+
+ /* Line 1455 of yacc.c */
+-#line 413 "dtc-parser.y"
++#line 430 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+- case 68:
++ case 70:
+
+ /* Line 1455 of yacc.c */
+-#line 419 "dtc-parser.y"
++#line 436 "dtc-parser.y"
+ { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+- case 69:
++ case 71:
+
+ /* Line 1455 of yacc.c */
+-#line 420 "dtc-parser.y"
++#line 437 "dtc-parser.y"
+ { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+- case 70:
++ case 72:
+
+ /* Line 1455 of yacc.c */
+-#line 421 "dtc-parser.y"
++#line 438 "dtc-parser.y"
+ { (yyval.integer) = !(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+- case 71:
++ case 73:
+
+ /* Line 1455 of yacc.c */
+-#line 426 "dtc-parser.y"
++#line 443 "dtc-parser.y"
+ {
+ (yyval.data) = empty_data;
+ ;}
+ break;
+
+- case 72:
++ case 74:
+
+ /* Line 1455 of yacc.c */
+-#line 430 "dtc-parser.y"
++#line 447 "dtc-parser.y"
+ {
+ (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+ ;}
+ break;
+
+- case 73:
++ case 75:
+
+ /* Line 1455 of yacc.c */
+-#line 434 "dtc-parser.y"
++#line 451 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+- case 74:
++ case 76:
+
+ /* Line 1455 of yacc.c */
+-#line 441 "dtc-parser.y"
++#line 458 "dtc-parser.y"
+ {
+ (yyval.nodelist) = NULL;
+ ;}
+ break;
+
+- case 75:
++ case 77:
+
+ /* Line 1455 of yacc.c */
+-#line 445 "dtc-parser.y"
++#line 462 "dtc-parser.y"
+ {
+ (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
+ ;}
+ break;
+
+- case 76:
++ case 78:
+
+ /* Line 1455 of yacc.c */
+-#line 449 "dtc-parser.y"
++#line 466 "dtc-parser.y"
+ {
+ print_error("syntax error: properties must precede subnodes");
+ YYERROR;
+ ;}
+ break;
+
+- case 77:
++ case 79:
+
+ /* Line 1455 of yacc.c */
+-#line 457 "dtc-parser.y"
++#line 474 "dtc-parser.y"
+ {
+ (yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
+ ;}
+ break;
+
+- case 78:
++ case 80:
+
+ /* Line 1455 of yacc.c */
+-#line 461 "dtc-parser.y"
++#line 478 "dtc-parser.y"
+ {
+ (yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename));
+ ;}
+ break;
+
+- case 79:
++ case 81:
+
+ /* Line 1455 of yacc.c */
+-#line 465 "dtc-parser.y"
++#line 482 "dtc-parser.y"
+ {
+ add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
+ (yyval.node) = (yyvsp[(2) - (2)].node);
+@@ -2120,7 +2149,7 @@ yyreduce:
+
+
+ /* Line 1455 of yacc.c */
+-#line 2124 "dtc-parser.tab.c"
++#line 2153 "dtc-parser.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+@@ -2332,7 +2361,7 @@ yyreturn:
+
+
+ /* Line 1675 of yacc.c */
+-#line 471 "dtc-parser.y"
++#line 488 "dtc-parser.y"
+
+
+ void print_error(char const *fmt, ...)
+diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
+index 9d2dce4..e4dfadf 100644
+--- a/scripts/dtc/dtc-parser.tab.h_shipped
++++ b/scripts/dtc/dtc-parser.tab.h_shipped
+@@ -40,27 +40,28 @@
+ know about them. */
+ enum yytokentype {
+ DT_V1 = 258,
+- DT_MEMRESERVE = 259,
+- DT_LSHIFT = 260,
+- DT_RSHIFT = 261,
+- DT_LE = 262,
+- DT_GE = 263,
+- DT_EQ = 264,
+- DT_NE = 265,
+- DT_AND = 266,
+- DT_OR = 267,
+- DT_BITS = 268,
+- DT_DEL_PROP = 269,
+- DT_DEL_NODE = 270,
+- DT_PROPNODENAME = 271,
+- DT_LITERAL = 272,
+- DT_CHAR_LITERAL = 273,
+- DT_BASE = 274,
+- DT_BYTE = 275,
+- DT_STRING = 276,
+- DT_LABEL = 277,
+- DT_REF = 278,
+- DT_INCBIN = 279
++ DT_PLUGIN = 259,
++ DT_MEMRESERVE = 260,
++ DT_LSHIFT = 261,
++ DT_RSHIFT = 262,
++ DT_LE = 263,
++ DT_GE = 264,
++ DT_EQ = 265,
++ DT_NE = 266,
++ DT_AND = 267,
++ DT_OR = 268,
++ DT_BITS = 269,
++ DT_DEL_PROP = 270,
++ DT_DEL_NODE = 271,
++ DT_PROPNODENAME = 272,
++ DT_LITERAL = 273,
++ DT_CHAR_LITERAL = 274,
++ DT_BASE = 275,
++ DT_BYTE = 276,
++ DT_STRING = 277,
++ DT_LABEL = 278,
++ DT_REF = 279,
++ DT_INCBIN = 280
+ };
+ #endif
+
+@@ -71,7 +72,7 @@ typedef union YYSTYPE
+ {
+
+ /* Line 1676 of yacc.c */
+-#line 40 "dtc-parser.y"
++#line 41 "dtc-parser.y"
+
+ char *propnodename;
+ char *literal;
+@@ -91,11 +92,12 @@ typedef union YYSTYPE
+ struct node *nodelist;
+ struct reserve_info *re;
+ uint64_t integer;
++ int is_plugin;
+
+
+
+ /* Line 1676 of yacc.c */
+-#line 99 "dtc-parser.tab.h"
++#line 101 "dtc-parser.tab.h"
+ } YYSTYPE;
+ # define YYSTYPE_IS_TRIVIAL 1
+ # define yystype YYSTYPE /* obsolescent; will be withdrawn */
+diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
+index f412460..e444acf 100644
+--- a/scripts/dtc/dtc-parser.y
++++ b/scripts/dtc/dtc-parser.y
+@@ -20,6 +20,7 @@
+
+ %{
+ #include <stdio.h>
++#include <inttypes.h>
+
+ #include "dtc.h"
+ #include "srcpos.h"
+@@ -56,9 +57,11 @@ static unsigned char eval_char_literal(const char *s);
+ struct node *nodelist;
+ struct reserve_info *re;
+ uint64_t integer;
++ int is_plugin;
+ }
+
+ %token DT_V1
++%token DT_PLUGIN
+ %token DT_MEMRESERVE
+ %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
+ %token DT_BITS
+@@ -76,6 +79,7 @@ static unsigned char eval_char_literal(const char *s);
+
+ %type <data> propdata
+ %type <data> propdataprefix
++%type <is_plugin> plugindecl
+ %type <re> memreserve
+ %type <re> memreserves
+ %type <array> arrayprefix
+@@ -106,10 +110,23 @@ static unsigned char eval_char_literal(const char *s);
+ %%
+
+ sourcefile:
+- DT_V1 ';' memreserves devicetree
++ DT_V1 ';' plugindecl memreserves devicetree
+ {
+- the_boot_info = build_boot_info($3, $4,
+- guess_boot_cpuid($4));
++ $5->is_plugin = $3;
++ $5->is_root = 1;
++ the_boot_info = build_boot_info($4, $5,
++ guess_boot_cpuid($5));
++ }
++ ;
++
++plugindecl:
++ /* empty */
++ {
++ $$ = 0;
++ }
++ | DT_PLUGIN ';'
++ {
++ $$ = 1;
+ }
+ ;
+
+diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
+index a375683..30d9607 100644
+--- a/scripts/dtc/dtc.c
++++ b/scripts/dtc/dtc.c
+@@ -31,6 +31,7 @@ int reservenum; /* Number of memory reservation slots */
+ int minsize; /* Minimum blob size */
+ int padsize; /* Additional padding to blob */
+ int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
++int symbol_fixup_support = 0;
+
+ static void fill_fullpaths(struct node *tree, const char *prefix)
+ {
+@@ -96,6 +97,8 @@ static void __attribute__ ((noreturn)) usage(void)
+ fprintf(stderr, "\t-W [no-]<checkname>\n");
+ fprintf(stderr, "\t-E [no-]<checkname>\n");
+ fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
++ fprintf(stderr, "\t-@\n");
++ fprintf(stderr, "\t\tSymbols and Fixups support\n");
+ exit(3);
+ }
+
+@@ -118,7 +121,7 @@ int main(int argc, char *argv[])
+ minsize = 0;
+ padsize = 0;
+
+- while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
++ while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:@"))
+ != EOF) {
+ switch (opt) {
+ case 'I':
+@@ -183,7 +186,9 @@ int main(int argc, char *argv[])
+ case 'E':
+ parse_checks_option(false, true, optarg);
+ break;
+-
++ case '@':
++ symbol_fixup_support = 1;
++ break;
+ case 'h':
+ default:
+ usage();
+diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
+index 3e42a07..0c8ecf6 100644
+--- a/scripts/dtc/dtc.h
++++ b/scripts/dtc/dtc.h
+@@ -54,6 +54,7 @@ extern int reservenum; /* Number of memory reservation slots */
+ extern int minsize; /* Minimum blob size */
+ extern int padsize; /* Additional padding to blob */
+ extern int phandle_format; /* Use linux,phandle or phandle properties */
++extern int symbol_fixup_support;/* enable symbols & fixup support */
+
+ #define PHANDLE_LEGACY 0x1
+ #define PHANDLE_EPAPR 0x2
+@@ -133,6 +134,25 @@ struct label {
+ struct label *next;
+ };
+
++struct fixup_entry {
++ int offset;
++ struct node *node;
++ struct property *prop;
++ struct fixup_entry *next;
++};
++
++struct fixup {
++ char *ref;
++ struct fixup_entry *entries;
++ struct fixup *next;
++};
++
++struct symbol {
++ struct label *label;
++ struct node *node;
++ struct symbol *next;
++};
++
+ struct property {
+ int deleted;
+ char *name;
+@@ -159,6 +179,12 @@ struct node {
+ int addr_cells, size_cells;
+
+ struct label *labels;
++
++ int is_root;
++ int is_plugin;
++ struct fixup *fixups;
++ struct symbol *symbols;
++ struct fixup_entry *local_fixups;
+ };
+
+ #define for_each_label_withdel(l0, l) \
+@@ -182,6 +208,18 @@ struct node {
+ for_each_child_withdel(n, c) \
+ if (!(c)->deleted)
+
++#define for_each_fixup(n, f) \
++ for ((f) = (n)->fixups; (f); (f) = (f)->next)
++
++#define for_each_fixup_entry(f, fe) \
++ for ((fe) = (f)->entries; (fe); (fe) = (fe)->next)
++
++#define for_each_symbol(n, s) \
++ for ((s) = (n)->symbols; (s); (s) = (s)->next)
++
++#define for_each_local_fixup_entry(n, fe) \
++ for ((fe) = (n)->local_fixups; (fe); (fe) = (fe)->next)
++
+ void add_label(struct label **labels, char *label);
+ void delete_labels(struct label **labels);
+
+diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
+index 665dad7..6237715 100644
+--- a/scripts/dtc/flattree.c
++++ b/scripts/dtc/flattree.c
+@@ -262,6 +262,12 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
+ struct property *prop;
+ struct node *child;
+ int seen_name_prop = 0;
++ struct symbol *sym;
++ struct fixup *f;
++ struct fixup_entry *fe;
++ char *name, *s;
++ const char *fullpath;
++ int namesz, nameoff, vallen;
+
+ if (tree->deleted)
+ return;
+@@ -310,6 +316,139 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
+ flatten_tree(child, emit, etarget, strbuf, vi);
+ }
+
++ if (!symbol_fixup_support)
++ goto no_symbols;
++
++ /* add the symbol nodes (if any) */
++ if (tree->symbols) {
++
++ emit->beginnode(etarget, NULL);
++ emit->string(etarget, "__symbols__", 0);
++ emit->align(etarget, sizeof(cell_t));
++
++ for_each_symbol(tree, sym) {
++
++ vallen = strlen(sym->node->fullpath);
++
++ nameoff = stringtable_insert(strbuf, sym->label->label);
++
++ emit->property(etarget, NULL);
++ emit->cell(etarget, vallen + 1);
++ emit->cell(etarget, nameoff);
++
++ if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
++ emit->align(etarget, 8);
++
++ emit->string(etarget, sym->node->fullpath,
++ strlen(sym->node->fullpath));
++ emit->align(etarget, sizeof(cell_t));
++ }
++
++ emit->endnode(etarget, NULL);
++ }
++
++ /* add the fixup nodes */
++ if (tree->fixups) {
++
++ /* emit the external fixups */
++ emit->beginnode(etarget, NULL);
++ emit->string(etarget, "__fixups__", 0);
++ emit->align(etarget, sizeof(cell_t));
++
++ for_each_fixup(tree, f) {
++
++ namesz = 0;
++ for_each_fixup_entry(f, fe) {
++ fullpath = fe->node->fullpath;
++ if (fullpath[0] == '\0')
++ fullpath = "/";
++ namesz += strlen(fullpath) + 1;
++ namesz += strlen(fe->prop->name) + 1;
++ namesz += 32; /* space for :<number> + '\0' */
++ }
++
++ name = xmalloc(namesz);
++
++ s = name;
++ for_each_fixup_entry(f, fe) {
++ fullpath = fe->node->fullpath;
++ if (fullpath[0] == '\0')
++ fullpath = "/";
++ snprintf(s, name + namesz - s, "%s:%s:%d",
++ fullpath,
++ fe->prop->name, fe->offset);
++ s += strlen(s) + 1;
++ }
++
++ nameoff = stringtable_insert(strbuf, f->ref);
++ vallen = s - name - 1;
++
++ emit->property(etarget, NULL);
++ emit->cell(etarget, vallen + 1);
++ emit->cell(etarget, nameoff);
++
++ if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
++ emit->align(etarget, 8);
++
++ emit->string(etarget, name, vallen);
++ emit->align(etarget, sizeof(cell_t));
++
++ free(name);
++ }
++
++ emit->endnode(etarget, tree->labels);
++ }
++
++ /* add the local fixup property */
++ if (tree->local_fixups) {
++
++ /* emit the external fixups */
++ emit->beginnode(etarget, NULL);
++ emit->string(etarget, "__local_fixups__", 0);
++ emit->align(etarget, sizeof(cell_t));
++
++ namesz = 0;
++ for_each_local_fixup_entry(tree, fe) {
++ fullpath = fe->node->fullpath;
++ if (fullpath[0] == '\0')
++ fullpath = "/";
++ namesz += strlen(fullpath) + 1;
++ namesz += strlen(fe->prop->name) + 1;
++ namesz += 32; /* space for :<number> + '\0' */
++ }
++
++ name = xmalloc(namesz);
++
++ s = name;
++ for_each_local_fixup_entry(tree, fe) {
++ fullpath = fe->node->fullpath;
++ if (fullpath[0] == '\0')
++ fullpath = "/";
++ snprintf(s, name + namesz - s, "%s:%s:%d",
++ fullpath, fe->prop->name,
++ fe->offset);
++ s += strlen(s) + 1;
++ }
++
++ nameoff = stringtable_insert(strbuf, "fixup");
++ vallen = s - name - 1;
++
++ emit->property(etarget, NULL);
++ emit->cell(etarget, vallen + 1);
++ emit->cell(etarget, nameoff);
++
++ if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
++ emit->align(etarget, 8);
++
++ emit->string(etarget, name, vallen);
++ emit->align(etarget, sizeof(cell_t));
++
++ free(name);
++
++ emit->endnode(etarget, tree->labels);
++ }
++
++no_symbols:
+ emit->endnode(etarget, tree->labels);
+ }
+
diff --git a/patches/linux-3.8.13/0257-dtc-Add-DTCO-rule-for-DTB-objects.patch b/patches/linux-3.8.13/0257-dtc-Add-DTCO-rule-for-DTB-objects.patch
new file mode 100644
index 0000000..4b487ce
--- /dev/null
+++ b/patches/linux-3.8.13/0257-dtc-Add-DTCO-rule-for-DTB-objects.patch
@@ -0,0 +1,26 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Dec 2012 12:57:13 +0200
+Subject: [PATCH] dtc: Add DTCO rule for DTB objects
+
+Add a rule for compiling DTS files as objects.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ scripts/Makefile.lib | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
+index bdf42fd..72ac3eb 100644
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -269,6 +269,10 @@ cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile
+ $(obj)/%.dtb: $(src)/%.dts FORCE
+ $(call if_changed_dep,dtc)
+
++# plugin compile
++quiet_cmd_dtco = DTCO $@
++cmd_dtco = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -@ -d $(depfile) $<
++
+ # Bzip2
+ # ---------------------------------------------------------------------------
+
diff --git a/patches/linux-3.8.13/0258-OF-Compile-Device-Tree-sources-with-resolve-option.patch b/patches/linux-3.8.13/0258-OF-Compile-Device-Tree-sources-with-resolve-option.patch
new file mode 100644
index 0000000..6501e2b
--- /dev/null
+++ b/patches/linux-3.8.13/0258-OF-Compile-Device-Tree-sources-with-resolve-option.patch
@@ -0,0 +1,57 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Dec 2012 13:05:34 +0200
+Subject: [PATCH] OF: Compile Device Tree sources with resolve option
+
+If the resolve config option has been enabled compile
+the device tree sources with the appropriate flag to generate
+the required for resolution __symbols__ node.
+
+Note that both arch/arm/Makefile & arch/arm/boot/Makefile need
+the DTC_FLAGS definition, because when issuing make dtbs the
+boot Makefile doesn't seem to pick it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/Makefile | 6 +++++-
+ arch/arm/boot/Makefile | 4 ++++
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index da4434d..e9729a4 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -275,6 +275,10 @@ ifeq ($(CONFIG_USE_OF),y)
+ KBUILD_DTBS := dtbs
+ endif
+
++ifeq ($(CONFIG_OF_RESOLVE),y)
++DTC_FLAGS += -@
++endif
++
+ all: $(KBUILD_IMAGE) $(KBUILD_DTBS)
+
+ boot := arch/arm/boot
+@@ -298,7 +302,7 @@ uImage-dtb.%: scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
+
+ dtbs: scripts
+- $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs
++ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) DTC_FLAGS=$(DTC_FLAGS) dtbs
+
+ # We use MRPROPER_FILES and CLEAN_FILES now
+ archclean:
+diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
+index e37ebb5..bedc651 100644
+--- a/arch/arm/boot/Makefile
++++ b/arch/arm/boot/Makefile
+@@ -60,6 +60,10 @@ $(obj)/zImage-dtb.%: $(obj)/dts/%.dtb $(obj)/zImage
+
+ endif
+
++ifeq ($(CONFIG_OF_RESOLVE),y)
++DTC_FLAGS += -@
++endif
++
+ ifneq ($(LOADADDR),)
+ UIMAGE_LOADADDR=$(LOADADDR)
+ else
diff --git a/patches/linux-3.8.13/0259-firmware-update-.gitignore-with-dtbo-objects.patch b/patches/linux-3.8.13/0259-firmware-update-.gitignore-with-dtbo-objects.patch
new file mode 100644
index 0000000..c677b8a
--- /dev/null
+++ b/patches/linux-3.8.13/0259-firmware-update-.gitignore-with-dtbo-objects.patch
@@ -0,0 +1,20 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 20:23:17 +0200
+Subject: [PATCH] firmware: update .gitignore with dtbo objects
+
+Ignore generated dtbo files.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/.gitignore | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/firmware/.gitignore b/firmware/.gitignore
+index d9c6901..21e3640 100644
+--- a/firmware/.gitignore
++++ b/firmware/.gitignore
+@@ -4,3 +4,4 @@
+ *.csp
+ *.dsp
+ ihex2fw
++*.dtbo
diff --git a/patches/linux-3.8.13/0260-OF-Introduce-device-tree-node-flag-helpers.patch b/patches/linux-3.8.13/0260-OF-Introduce-device-tree-node-flag-helpers.patch
new file mode 100644
index 0000000..d7da53d
--- /dev/null
+++ b/patches/linux-3.8.13/0260-OF-Introduce-device-tree-node-flag-helpers.patch
@@ -0,0 +1,42 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Dec 2012 13:10:51 +0200
+Subject: [PATCH] OF: Introduce device tree node flag helpers.
+
+Helper functions for working with device node flags.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ include/linux/of.h | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 5ebcc5c..2ff35b5 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -114,6 +114,26 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
+ set_bit(flag, &n->_flags);
+ }
+
++static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
++{
++ clear_bit(flag, &n->_flags);
++}
++
++static inline int of_property_check_flag(struct property *p, unsigned long flag)
++{
++ return test_bit(flag, &p->_flags);
++}
++
++static inline void of_property_set_flag(struct property *p, unsigned long flag)
++{
++ set_bit(flag, &p->_flags);
++}
++
++static inline void of_property_clear_flag(struct property *p, unsigned long flag)
++{
++ clear_bit(flag, &p->_flags);
++}
++
+ extern struct device_node *of_find_all_nodes(struct device_node *prev);
+
+ /*
diff --git a/patches/linux-3.8.13/0261-OF-export-of_property_notify.patch b/patches/linux-3.8.13/0261-OF-export-of_property_notify.patch
new file mode 100644
index 0000000..d50566a
--- /dev/null
+++ b/patches/linux-3.8.13/0261-OF-export-of_property_notify.patch
@@ -0,0 +1,60 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 3 Jan 2013 11:46:39 +0200
+Subject: [PATCH] OF: export of_property_notify
+
+of_property_notify can be utilized by other users too, export it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/base.c | 8 +-------
+ include/linux/of.h | 11 +++++++++++
+ 2 files changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index 2390ddb..d598216 100644
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -1115,7 +1115,7 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na
+ EXPORT_SYMBOL(of_parse_phandle_with_args);
+
+ #if defined(CONFIG_OF_DYNAMIC)
+-static int of_property_notify(int action, struct device_node *np,
++int of_property_notify(int action, struct device_node *np,
+ struct property *prop)
+ {
+ struct of_prop_reconfig pr;
+@@ -1124,12 +1124,6 @@ static int of_property_notify(int action, struct device_node *np,
+ pr.prop = prop;
+ return of_reconfig_notify(action, &pr);
+ }
+-#else
+-static int of_property_notify(int action, struct device_node *np,
+- struct property *prop)
+-{
+- return 0;
+-}
+ #endif
+
+ /**
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 2ff35b5..aea3694 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -298,6 +298,17 @@ extern int of_parse_phandle_with_args(const struct device_node *np,
+ const char *list_name, const char *cells_name, int index,
+ struct of_phandle_args *out_args);
+
++#if defined(CONFIG_OF_DYNAMIC)
++extern int of_property_notify(int action, struct device_node *np,
++ struct property *prop);
++#else
++static inline int of_property_notify(int action, struct device_node *np,
++ struct property *prop)
++{
++ return 0;
++}
++#endif
++
+ extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
+ extern int of_alias_get_id(struct device_node *np, const char *stem);
+
diff --git a/patches/linux-3.8.13/0262-OF-Export-all-DT-proc-update-functions.patch b/patches/linux-3.8.13/0262-OF-Export-all-DT-proc-update-functions.patch
new file mode 100644
index 0000000..ae1674b
--- /dev/null
+++ b/patches/linux-3.8.13/0262-OF-Export-all-DT-proc-update-functions.patch
@@ -0,0 +1,209 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 3 Jan 2013 12:02:14 +0200
+Subject: [PATCH] OF: Export all DT proc update functions
+
+There are other users for the proc DT functions.
+Export them.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/base.c | 108 ++++++++++++++++++++++++++++------------------------
+ include/linux/of.h | 29 ++++++++++++++
+ 2 files changed, 87 insertions(+), 50 deletions(-)
+
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index d598216..526db99 100644
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -1126,6 +1126,61 @@ int of_property_notify(int action, struct device_node *np,
+ }
+ #endif
+
++#ifdef CONFIG_PROC_DEVICETREE
++
++void of_add_proc_dt_entry(struct device_node *dn)
++{
++ struct proc_dir_entry *ent;
++
++ ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
++ if (ent)
++ proc_device_tree_add_node(dn, ent);
++}
++
++void of_remove_proc_dt_entry(struct device_node *dn)
++{
++ struct device_node *parent;
++ struct property *prop;
++
++ if (!dn)
++ return;
++
++ parent = dn->parent;
++ prop = dn->properties;
++ while (prop) {
++ if (dn->pde)
++ remove_proc_entry(prop->name, dn->pde);
++ prop = prop->next;
++ }
++
++ if (dn->pde)
++ remove_proc_entry(dn->pde->name,
++ parent ? parent->pde : NULL);
++}
++
++void of_add_proc_dt_prop_entry(struct device_node *np,
++ struct property *prop)
++{
++ if (np && prop && np->pde)
++ proc_device_tree_add_prop(np->pde, prop);
++}
++
++void of_remove_proc_dt_prop_entry(struct device_node *np,
++ struct property *prop)
++{
++ if (np && prop && np->pde)
++ proc_device_tree_remove_prop(np->pde, prop);
++}
++
++void of_update_proc_dt_prop_entry(struct device_node *np,
++ struct property *newprop, struct property *oldprop)
++{
++ if (np && newprop && oldprop && np->pde)
++ proc_device_tree_update_prop(np->pde, newprop, oldprop);
++}
++
++#endif /* CONFIG_PROC_DEVICETREE */
++
+ /**
+ * of_add_property - Add a property to a node
+ */
+@@ -1153,11 +1208,8 @@ int of_add_property(struct device_node *np, struct property *prop)
+ *next = prop;
+ write_unlock_irqrestore(&devtree_lock, flags);
+
+-#ifdef CONFIG_PROC_DEVICETREE
+ /* try to add to proc as well if it was initialized */
+- if (np->pde)
+- proc_device_tree_add_prop(np->pde, prop);
+-#endif /* CONFIG_PROC_DEVICETREE */
++ of_add_proc_dt_prop_entry(np, prop);
+
+ return 0;
+ }
+@@ -1199,11 +1251,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
+ if (!found)
+ return -ENODEV;
+
+-#ifdef CONFIG_PROC_DEVICETREE
+- /* try to remove the proc node as well */
+- if (np->pde)
+- proc_device_tree_remove_prop(np->pde, prop);
+-#endif /* CONFIG_PROC_DEVICETREE */
++ of_remove_proc_dt_prop_entry(np, prop);
+
+ return 0;
+ }
+@@ -1253,11 +1301,8 @@ int of_update_property(struct device_node *np, struct property *newprop)
+ if (!found)
+ return -ENODEV;
+
+-#ifdef CONFIG_PROC_DEVICETREE
+ /* try to add to proc as well if it was initialized */
+- if (np->pde)
+- proc_device_tree_update_prop(np->pde, newprop, oldprop);
+-#endif /* CONFIG_PROC_DEVICETREE */
++ of_update_proc_dt_prop_entry(np, newprop, oldprop);
+
+ return 0;
+ }
+@@ -1293,22 +1338,6 @@ int of_reconfig_notify(unsigned long action, void *p)
+ return notifier_to_errno(rc);
+ }
+
+-#ifdef CONFIG_PROC_DEVICETREE
+-static void of_add_proc_dt_entry(struct device_node *dn)
+-{
+- struct proc_dir_entry *ent;
+-
+- ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
+- if (ent)
+- proc_device_tree_add_node(dn, ent);
+-}
+-#else
+-static void of_add_proc_dt_entry(struct device_node *dn)
+-{
+- return;
+-}
+-#endif
+-
+ /**
+ * of_attach_node - Plug a device node into the tree and global list.
+ */
+@@ -1332,27 +1361,6 @@ int of_attach_node(struct device_node *np)
+ return 0;
+ }
+
+-#ifdef CONFIG_PROC_DEVICETREE
+-static void of_remove_proc_dt_entry(struct device_node *dn)
+-{
+- struct device_node *parent = dn->parent;
+- struct property *prop = dn->properties;
+-
+- while (prop) {
+- remove_proc_entry(prop->name, dn->pde);
+- prop = prop->next;
+- }
+-
+- if (dn->pde)
+- remove_proc_entry(dn->pde->name, parent->pde);
+-}
+-#else
+-static void of_remove_proc_dt_entry(struct device_node *dn)
+-{
+- return;
+-}
+-#endif
+-
+ /**
+ * of_detach_node - "Unplug" a node from the device tree.
+ *
+diff --git a/include/linux/of.h b/include/linux/of.h
+index aea3694..305b087 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -309,6 +309,35 @@ static inline int of_property_notify(int action, struct device_node *np,
+ }
+ #endif
+
++#ifdef CONFIG_PROC_DEVICETREE
++
++extern void of_add_proc_dt_entry(struct device_node *dn);
++extern void of_remove_proc_dt_entry(struct device_node *dn);
++
++extern void of_add_proc_dt_prop_entry(struct device_node *np,
++ struct property *prop);
++
++extern void of_remove_proc_dt_prop_entry(struct device_node *np,
++ struct property *prop);
++
++extern void of_update_proc_dt_prop_entry(struct device_node *np,
++ struct property *newprop, struct property *oldprop);
++#else
++
++static inline void of_add_proc_dt_entry(struct device_node *dn) { }
++static inline void of_remove_proc_dt_entry(struct device_node *dn) { }
++
++static inline void of_add_proc_dt_prop_entry(struct device_node *np,
++ struct property *prop) { }
++
++static inline void of_remove_proc_dt_prop_entry(struct device_node *np,
++ struct property *prop) { }
++
++static inline void of_update_proc_dt_prop_entry(struct device_node *np,
++ struct property *newprop, struct property *oldprop) { }
++
++#endif
++
+ extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
+ extern int of_alias_get_id(struct device_node *np, const char *stem);
+
diff --git a/patches/linux-3.8.13/0263-OF-Introduce-utility-helper-functions.patch b/patches/linux-3.8.13/0263-OF-Introduce-utility-helper-functions.patch
new file mode 100644
index 0000000..ad63055
--- /dev/null
+++ b/patches/linux-3.8.13/0263-OF-Introduce-utility-helper-functions.patch
@@ -0,0 +1,360 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 3 Jan 2013 12:11:31 +0200
+Subject: [PATCH] OF: Introduce utility helper functions
+
+Introduce helper functions for working with the live DT tree.
+
+__of_free_property() frees a dynamically created property
+__of_free_tree() recursively frees a device node tree
+__of_copy_property() copies a property dynamically
+__of_create_empty_node() creates an empty node
+__of_find_node_by_full_name() finds the node with the full name
+and
+of_multi_prop_cmp() performs a multi property compare but without
+having to take locks.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/Makefile | 2 +-
+ drivers/of/util.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/of.h | 59 ++++++++++++
+ 3 files changed, 313 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/of/util.c
+
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index eafa107..3e561a2 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -1,4 +1,4 @@
+-obj-y = base.o dma.o
++obj-y = base.o dma.o util.o
+ obj-$(CONFIG_OF_FLATTREE) += fdt.o
+ obj-$(CONFIG_OF_PROMTREE) += pdt.o
+ obj-$(CONFIG_OF_ADDRESS) += address.o
+diff --git a/drivers/of/util.c b/drivers/of/util.c
+new file mode 100644
+index 0000000..5117e2b
+--- /dev/null
++++ b/drivers/of/util.c
+@@ -0,0 +1,253 @@
++/*
++ * Utility functions for working with device tree(s)
++ *
++ * 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
++ * version 2 as published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++
++/**
++ * __of_free_property - release the memory of an allocated property
++ * @prop: Property to release
++ *
++ * Release the memory of an allocated property only after checking
++ * that the property has been marked as OF_DYNAMIC.
++ * Only call on known allocated properties.
++ */
++void __of_free_property(struct property *prop)
++{
++ if (prop == NULL)
++ return;
++
++ if (of_property_check_flag(prop, OF_DYNAMIC)) {
++ kfree(prop->value);
++ kfree(prop->name);
++ kfree(prop);
++ } else {
++ pr_warn("%s: property %p cannot be freed; memory is gone\n",
++ __func__, prop);
++ }
++}
++
++/**
++ * __of_free_tree - release the memory of a device tree node and
++ * of all it's children + properties.
++ * @node: Device Tree node to release
++ *
++ * Release the memory of a device tree node and of all it's children.
++ * Also release the properties and the dead properties.
++ * Only call on detached node trees, and you better be sure that
++ * no pointer exist for any properties. Only safe to do if you
++ * absolutely control the life cycle of the node.
++ * Also note that the node is not removed from the all_nodes list,
++ * neither from the parent's child list; this should be handled before
++ * calling this function.
++ */
++void __of_free_tree(struct device_node *node)
++{
++ struct property *prop;
++ struct device_node *noden;
++
++ /* sanity check */
++ if (!node)
++ return;
++
++ /* free recursively any children */
++ while ((noden = node->child) != NULL) {
++ node->child = noden->sibling;
++ __of_free_tree(noden);
++ }
++
++ /* free every property already allocated */
++ while ((prop = node->properties) != NULL) {
++ node->properties = prop->next;
++ __of_free_property(prop);
++ }
++
++ /* free dead properties already allocated */
++ while ((prop = node->deadprops) != NULL) {
++ node->deadprops = prop->next;
++ __of_free_property(prop);
++ }
++
++ if (of_node_check_flag(node, OF_DYNAMIC)) {
++ kfree(node->type);
++ kfree(node->name);
++ kfree(node);
++ } else {
++ pr_warn("%s: node %p cannot be freed; memory is gone\n",
++ __func__, node);
++ }
++}
++
++/**
++ * __of_copy_property - Copy a property dynamically.
++ * @prop: Property to copy
++ * @flags: Allocation flags (typically pass GFP_KERNEL)
++ *
++ * Copy a property by dynamically allocating the memory of both the
++ * property stucture and the property name & contents. The property's
++ * flags have the OF_DYNAMIC bit set so that we can differentiate between
++ * dynamically allocated properties and not.
++ * Returns the newly allocated property or NULL on out of memory error.
++ */
++struct property *__of_copy_property(const struct property *prop, gfp_t flags)
++{
++ struct property *propn;
++
++ propn = kzalloc(sizeof(*prop), flags);
++ if (propn == NULL)
++ return NULL;
++
++ propn->name = kstrdup(prop->name, flags);
++ if (propn->name == NULL)
++ goto err_fail_name;
++
++ if (prop->length > 0) {
++ propn->value = kmalloc(prop->length, flags);
++ if (propn->value == NULL)
++ goto err_fail_value;
++ memcpy(propn->value, prop->value, prop->length);
++ propn->length = prop->length;
++ }
++
++ /* mark the property as dynamic */
++ of_property_set_flag(propn, OF_DYNAMIC);
++
++ return propn;
++
++err_fail_value:
++ kfree(propn->name);
++err_fail_name:
++ kfree(propn);
++ return NULL;
++}
++
++/**
++ * __of_create_empty_node - Create an empty device node dynamically.
++ * @name: Name of the new device node
++ * @type: Type of the new device node
++ * @full_name: Full name of the new device node
++ * @phandle: Phandle of the new device node
++ * @flags: Allocation flags (typically pass GFP_KERNEL)
++ *
++ * Create an empty device tree node, suitable for further modification.
++ * The node data are dynamically allocated and all the node flags
++ * have the OF_DYNAMIC & OF_DETACHED bits set.
++ * Returns the newly allocated node or NULL on out of memory error.
++ */
++struct device_node *__of_create_empty_node(
++ const char *name, const char *type, const char *full_name,
++ phandle phandle, gfp_t flags)
++{
++ struct device_node *node;
++
++ node = kzalloc(sizeof(*node), flags);
++ if (node == NULL)
++ return NULL;
++
++ node->name = kstrdup(name, flags);
++ if (node->name == NULL)
++ goto err_return;
++
++ node->type = kstrdup(type, flags);
++ if (node->type == NULL)
++ goto err_return;
++
++ node->full_name = kstrdup(full_name, flags);
++ if (node->type == NULL)
++ goto err_return;
++
++ node->phandle = phandle;
++ kref_init(&node->kref);
++ of_node_set_flag(node, OF_DYNAMIC);
++ of_node_set_flag(node, OF_DETACHED);
++
++ return node;
++
++err_return:
++ __of_free_tree(node);
++ return NULL;
++}
++
++/**
++ * __of_find_node_by_full_name - Find a node with the full name recursively
++ * @node: Root of the tree to perform the search
++ * @full_name: Full name of the node to find.
++ *
++ * Find a node with the give full name by recursively following any of
++ * the child node links.
++ * Returns the matching node, or NULL if not found.
++ * Note that the devtree lock is not taken, so this function is only
++ * safe to call on either detached trees, or when devtree lock is already
++ * taken.
++ */
++struct device_node *__of_find_node_by_full_name(struct device_node *node,
++ const char *full_name)
++{
++ struct device_node *child, *found;
++
++ if (node == NULL)
++ return NULL;
++
++ /* check */
++ if (of_node_cmp(node->full_name, full_name) == 0)
++ return node;
++
++ __for_each_child_of_node(node, child) {
++ found = __of_find_node_by_full_name(child, full_name);
++ if (found != NULL)
++ return found;
++ }
++
++ return NULL;
++}
++
++/**
++ * of_multi_prop_cmp - Check if a property matches a value
++ * @prop: Property to check
++ * @value: Value to check against
++ *
++ * Check whether a property matches a value, using the standard
++ * of_compat_cmp() test on each string. It is similar to the test
++ * of_device_is_compatible() makes, but it can be performed without
++ * taking the devtree_lock, which is required in some cases.
++ * Returns 0 on a match, -1 on no match.
++ */
++int of_multi_prop_cmp(const struct property *prop, const char *value)
++{
++ const char *cp;
++ int cplen, vlen, l;
++
++ if (prop == NULL || value == NULL)
++ return -1;
++
++ cp = prop->value;
++ cplen = prop->length;
++ vlen = strlen(value);
++
++ while (cplen > 0) {
++ if (of_compat_cmp(cp, value, vlen) == 0)
++ return 0;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ return -1;
++}
++
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 305b087..c38e41a 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -591,4 +591,63 @@ static inline int of_property_read_u32(const struct device_node *np,
+ return of_property_read_u32_array(np, propname, out_value, 1);
+ }
+
++/**
++ * General utilities for working with live trees.
++ *
++ * All functions with two leading underscores operate
++ * without taking node references, so you either have to
++ * own the devtree lock or work on detached trees only.
++ */
++
++#ifdef CONFIG_OF
++
++/* iterator for internal use; not references, neither affects devtree lock */
++#define __for_each_child_of_node(dn, chld) \
++ for (chld = (dn)->child; chld != NULL; chld = chld->sibling)
++
++void __of_free_property(struct property *prop);
++void __of_free_tree(struct device_node *node);
++struct property *__of_copy_property(const struct property *prop, gfp_t flags);
++struct device_node *__of_create_empty_node( const char *name,
++ const char *type, const char *full_name,
++ phandle phandle, gfp_t flags);
++struct device_node *__of_find_node_by_full_name(struct device_node *node,
++ const char *full_name);
++int of_multi_prop_cmp(const struct property *prop, const char *value);
++
++#else /* !CONFIG_OF */
++
++#define __for_each_child_of_node(dn, chld) \
++ while (0)
++
++static inline void __of_free_property(struct property *prop) { }
++
++static inline void __of_free_tree(struct device_node *node) { }
++
++static inline struct property *__of_copy_property(const struct property *prop,
++ gfp_t flags)
++{
++ return NULL;
++}
++
++static inline struct device_node *__of_create_empty_node( const char *name,
++ const char *type, const char *full_name,
++ phandle phandle, gfp_t flags)
++{
++ return NULL;
++}
++
++static inline struct device_node *__of_find_node_by_full_name(struct device_node *node,
++ const char *full_name)
++{
++ return NULL;
++}
++
++static inline int of_multi_prop_cmp(const struct property *prop, const char *value)
++{
++ return -1;
++}
++
++#endif /* !CONFIG_OF */
++
+ #endif /* _LINUX_OF_H */
diff --git a/patches/linux-3.8.13/0264-OF-Introduce-Device-Tree-resolve-support.patch b/patches/linux-3.8.13/0264-OF-Introduce-Device-Tree-resolve-support.patch
new file mode 100644
index 0000000..57949d0
--- /dev/null
+++ b/patches/linux-3.8.13/0264-OF-Introduce-Device-Tree-resolve-support.patch
@@ -0,0 +1,504 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 3 Jan 2013 12:18:25 +0200
+Subject: [PATCH] OF: Introduce Device Tree resolve support.
+
+Introduce support for dynamic device tree resolution.
+Using it, it is possible to prepare a device tree that's
+been loaded on runtime to be modified and inserted at the kernel
+live tree.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ .../devicetree/dynamic-resolution-notes.txt | 25 ++
+ drivers/of/Kconfig | 9 +
+ drivers/of/Makefile | 1 +
+ drivers/of/resolver.c | 394 ++++++++++++++++++++
+ include/linux/of.h | 17 +
+ 5 files changed, 446 insertions(+)
+ create mode 100644 Documentation/devicetree/dynamic-resolution-notes.txt
+ create mode 100644 drivers/of/resolver.c
+
+diff --git a/Documentation/devicetree/dynamic-resolution-notes.txt b/Documentation/devicetree/dynamic-resolution-notes.txt
+new file mode 100644
+index 0000000..0b396c4
+--- /dev/null
++++ b/Documentation/devicetree/dynamic-resolution-notes.txt
+@@ -0,0 +1,25 @@
++Device Tree Dynamic Resolver Notes
++----------------------------------
++
++This document describes the implementation of the in-kernel
++Device Tree resolver, residing in drivers/of/resolver.c and is a
++companion document to Documentation/devicetree/dt-object-internal.txt[1]
++
++How the resolver works
++----------------------
++
++The resolver is given as an input an arbitrary tree compiled with the
++proper dtc option and having a /plugin/ tag. This generates the
++appropriate __fixups__ & __local_fixups__ nodes as described in [1].
++
++In sequence the resolver works by the following steps:
++
++1. Get the maximum device tree phandle value from the live tree + 1.
++2. Adjust all the local phandles of the tree to resolve by that amount.
++3. Using the __local__fixups__ node information adjust all local references
++ by the same amount.
++4. For each property in the __fixups__ node locate the node it references
++ in the live tree. This is the label used to tag the node.
++5. Retrieve the phandle of the target of the fixup.
++5. For each fixup in the property locate the node:property:offset location
++ and replace it with the phandle value.
+diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
+index d37bfcf..f9a6193 100644
+--- a/drivers/of/Kconfig
++++ b/drivers/of/Kconfig
+@@ -83,4 +83,13 @@ config OF_MTD
+ depends on MTD
+ def_bool y
+
++config OF_RESOLVE
++ bool "OF Dynamic resolution support"
++ depends on OF
++ select OF_DYNAMIC
++ select OF_DEVICE
++ help
++ Enable OF dynamic resolution support. This allows you to
++ load Device Tree object fragments are run time.
++
+ endmenu # OF
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index 3e561a2..19a8593 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -11,3 +11,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o
+ obj-$(CONFIG_OF_PCI) += of_pci.o
+ obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
+ obj-$(CONFIG_OF_MTD) += of_mtd.o
++obj-$(CONFIG_OF_RESOLVE) += resolver.o
+diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
+new file mode 100644
+index 0000000..016d7da
+--- /dev/null
++++ b/drivers/of/resolver.c
+@@ -0,0 +1,394 @@
++/*
++ * Functions for dealing with DT resolution
++ *
++ * 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
++ * version 2 as published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_fdt.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++
++/**
++ * Find a subtree's maximum phandle value.
++ */
++static phandle __of_get_tree_max_phandle(struct device_node *node,
++ phandle max_phandle)
++{
++ struct device_node *child;
++
++ if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL &&
++ node->phandle > max_phandle)
++ max_phandle = node->phandle;
++
++ __for_each_child_of_node(node, child)
++ max_phandle = __of_get_tree_max_phandle(child, max_phandle);
++
++ return max_phandle;
++}
++
++/**
++ * Find live tree's maximum phandle value.
++ */
++static phandle of_get_tree_max_phandle(void)
++{
++ struct device_node *node;
++ phandle phandle;
++
++ /* get root node */
++ node = of_find_node_by_path("/");
++ if (node == NULL)
++ return OF_PHANDLE_ILLEGAL;
++
++ /* now search recursively */
++ read_lock(&devtree_lock);
++ phandle = __of_get_tree_max_phandle(node, 0);
++ read_unlock(&devtree_lock);
++
++ of_node_put(node);
++
++ return phandle;
++}
++
++/**
++ * Adjust a subtree's phandle values by a given delta.
++ * Makes sure not to just adjust the device node's phandle value,
++ * but modify the phandle properties values as well.
++ */
++static void __of_adjust_tree_phandles(struct device_node *node,
++ int phandle_delta)
++{
++ struct device_node *child;
++ struct property *prop;
++ phandle phandle;
++
++ /* first adjust the node's phandle direct value */
++ if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL)
++ node->phandle += phandle_delta;
++
++ /* now adjust phandle & linux,phandle values */
++ for_each_property_of_node(node, prop) {
++
++ /* only look for these two */
++ if (of_prop_cmp(prop->name, "phandle") != 0 &&
++ of_prop_cmp(prop->name, "linux,phandle") != 0)
++ continue;
++
++ /* must be big enough */
++ if (prop->length < 4)
++ continue;
++
++ /* read phandle value */
++ phandle = be32_to_cpu(*(uint32_t *)prop->value);
++ if (phandle == OF_PHANDLE_ILLEGAL) /* unresolved */
++ continue;
++
++ /* adjust */
++ *(uint32_t *)prop->value = cpu_to_be32(node->phandle);
++ }
++
++ /* now do the children recursively */
++ __for_each_child_of_node(node, child)
++ __of_adjust_tree_phandles(child, phandle_delta);
++}
++
++/**
++ * Adjust the local phandle references by the given phandle delta.
++ * Assumes the existances of a __local_fixups__ node at the root
++ * of the tree. Does not take any devtree locks so make sure you
++ * call this on a tree which is at the detached state.
++ */
++static int __of_adjust_tree_phandle_references(struct device_node *node,
++ int phandle_delta)
++{
++ phandle phandle;
++ struct device_node *refnode, *child;
++ struct property *rprop, *sprop;
++ char *propval, *propcur, *propend, *nodestr, *propstr, *s;
++ int offset, propcurlen;
++ int err;
++
++ /* locate the symbols & fixups nodes on resolve */
++ __for_each_child_of_node(node, child)
++ if (of_node_cmp(child->name, "__local_fixups__") == 0)
++ break;
++
++ /* no local fixups */
++ if (child == NULL)
++ return 0;
++
++ /* find the local fixups property */
++ for_each_property_of_node(child, rprop) {
++
++ /* skip properties added automatically */
++ if (of_prop_cmp(rprop->name, "name") == 0)
++ continue;
++
++ /* make a copy */
++ propval = kmalloc(rprop->length, GFP_KERNEL);
++ if (propval == NULL) {
++ pr_err("%s: Could not copy value of '%s'\n",
++ __func__, rprop->name);
++ return -ENOMEM;
++ }
++ memcpy(propval, rprop->value, rprop->length);
++
++ propend = propval + rprop->length;
++ for (propcur = propval; propcur < propend;
++ propcur += propcurlen + 1) {
++
++ propcurlen = strlen(propcur);
++
++ nodestr = propcur;
++ s = strchr(propcur, ':');
++ if (s == NULL) {
++ pr_err("%s: Illegal symbol entry '%s' (1)\n",
++ __func__, propcur);
++ err = -EINVAL;
++ goto err_fail;
++ }
++ *s++ = '\0';
++
++ propstr = s;
++ s = strchr(s, ':');
++ if (s == NULL) {
++ pr_err("%s: Illegal symbol entry '%s' (2)\n",
++ __func__, (char *)rprop->value);
++ err = -EINVAL;
++ goto err_fail;
++ }
++
++ *s++ = '\0';
++ offset = simple_strtoul(s, NULL, 10);
++
++ /* look into the resolve node for the full path */
++ refnode = __of_find_node_by_full_name(node, nodestr);
++ if (refnode == NULL) {
++ pr_warn("%s: Could not find refnode '%s'\n",
++ __func__, (char *)rprop->value);
++ continue;
++ }
++
++ /* now find the property */
++ for_each_property_of_node(refnode, sprop) {
++ if (of_prop_cmp(sprop->name, propstr) == 0)
++ break;
++ }
++
++ if (sprop == NULL) {
++ pr_err("%s: Could not find property '%s'\n",
++ __func__, (char *)rprop->value);
++ err = -ENOENT;
++ goto err_fail;
++ }
++
++ phandle = be32_to_cpu(*(uint32_t *)
++ (sprop->value + offset));
++ *(uint32_t *)(sprop->value + offset) =
++ cpu_to_be32(phandle + phandle_delta);
++ }
++
++ kfree(propval);
++ }
++
++ return 0;
++
++err_fail:
++ kfree(propval);
++ return err;
++}
++
++/**
++ * of_resolve - Resolve the given node against the live tree.
++ *
++ * @resolve: Node to resolve
++ *
++ * Perform dynamic Device Tree resolution against the live tree
++ * to the given node to resolve. This depends on the live tree
++ * having a __symbols__ node, and the resolve node the __fixups__ &
++ * __local_fixups__ nodes (if needed).
++ * The result of the operation is a resolve node that it's contents
++ * are fit to be inserted or operate upon the live tree.
++ * Returns 0 on success or a negative error value on error.
++ */
++int of_resolve(struct device_node *resolve)
++{
++ struct device_node *child, *refnode;
++ struct device_node *root_sym, *resolve_sym, *resolve_fix;
++ struct property *rprop, *sprop;
++ const char *refpath;
++ char *propval, *propcur, *propend, *nodestr, *propstr, *s;
++ int offset, propcurlen;
++ phandle phandle, phandle_delta;
++ int err;
++
++ /* the resolve node must exist, and be detached */
++ if (resolve == NULL ||
++ !of_node_check_flag(resolve, OF_DETACHED)) {
++ return -EINVAL;
++ }
++
++ /* first we need to adjust the phandles */
++ phandle_delta = of_get_tree_max_phandle() + 1;
++ __of_adjust_tree_phandles(resolve, phandle_delta);
++ err = __of_adjust_tree_phandle_references(resolve, phandle_delta);
++ if (err != 0)
++ return err;
++
++ root_sym = NULL;
++ resolve_sym = NULL;
++ resolve_fix = NULL;
++
++ /* this may fail (if no fixups are required) */
++ root_sym = of_find_node_by_path("/__symbols__");
++
++ /* locate the symbols & fixups nodes on resolve */
++ __for_each_child_of_node(resolve, child) {
++
++ if (resolve_sym == NULL &&
++ of_node_cmp(child->name, "__symbols__") == 0)
++ resolve_sym = child;
++
++ if (resolve_fix == NULL &&
++ of_node_cmp(child->name, "__fixups__") == 0)
++ resolve_fix = child;
++
++ /* both found, don't bother anymore */
++ if (resolve_sym != NULL && resolve_fix != NULL)
++ break;
++ }
++
++ /* we do allow for the case where no fixups are needed */
++ if (resolve_fix == NULL)
++ goto merge_sym;
++
++ /* we need to fixup, but no root symbols... */
++ if (root_sym == NULL)
++ return -EINVAL;
++
++ for_each_property_of_node(resolve_fix, rprop) {
++
++ /* skip properties added automatically */
++ if (of_prop_cmp(rprop->name, "name") == 0)
++ continue;
++
++ err = of_property_read_string(root_sym,
++ rprop->name, &refpath);
++ if (err != 0) {
++ pr_err("%s: Could not find symbol '%s'\n",
++ __func__, rprop->name);
++ goto err_fail;
++ }
++
++ refnode = of_find_node_by_path(refpath);
++ if (refnode == NULL) {
++ pr_err("%s: Could not find node by path '%s'\n",
++ __func__, refpath);
++ err = -ENOENT;
++ goto err_fail;
++ }
++
++ phandle = refnode->phandle;
++ of_node_put(refnode);
++
++ pr_debug("%s: %s phandle is 0x%08x\n",
++ __func__, rprop->name, phandle);
++
++ /* make a copy */
++ propval = kmalloc(rprop->length, GFP_KERNEL);
++ if (propval == NULL) {
++ pr_err("%s: Could not copy value of '%s'\n",
++ __func__, rprop->name);
++ err = -ENOMEM;
++ goto err_fail;
++ }
++
++ memcpy(propval, rprop->value, rprop->length);
++
++ propend = propval + rprop->length;
++ for (propcur = propval; propcur < propend;
++ propcur += propcurlen + 1) {
++ propcurlen = strlen(propcur);
++
++ nodestr = propcur;
++ s = strchr(propcur, ':');
++ if (s == NULL) {
++ pr_err("%s: Illegal symbol "
++ "entry '%s' (1)\n",
++ __func__, (char *)rprop->value);
++ kfree(propval);
++ err = -EINVAL;
++ goto err_fail;
++ }
++ *s++ = '\0';
++
++ propstr = s;
++ s = strchr(s, ':');
++ if (s == NULL) {
++ pr_err("%s: Illegal symbol "
++ "entry '%s' (2)\n",
++ __func__, (char *)rprop->value);
++ kfree(propval);
++ err = -EINVAL;
++ goto err_fail;
++ }
++
++ *s++ = '\0';
++ offset = simple_strtoul(s, NULL, 10);
++
++ /* look into the resolve node for the full path */
++ refnode = __of_find_node_by_full_name(resolve,
++ nodestr);
++ if (refnode == NULL) {
++ pr_err("%s: Could not find refnode '%s'\n",
++ __func__, (char *)rprop->value);
++ kfree(propval);
++ err = -ENOENT;
++ goto err_fail;
++ }
++
++ /* now find the property */
++ for_each_property_of_node(refnode, sprop) {
++ if (of_prop_cmp(sprop->name, propstr) == 0)
++ break;
++ }
++
++ if (sprop == NULL) {
++ pr_err("%s: Could not find property '%s'\n",
++ __func__, (char *)rprop->value);
++ kfree(propval);
++ err = -ENOENT;
++ goto err_fail;
++ }
++
++ *(uint32_t *)(sprop->value + offset) =
++ cpu_to_be32(phandle);
++ }
++
++ kfree(propval);
++ }
++
++merge_sym:
++
++ of_node_put(root_sym);
++
++ return 0;
++
++err_fail:
++
++ if (root_sym != NULL)
++ of_node_put(root_sym);
++
++ return err;
++}
+diff --git a/include/linux/of.h b/include/linux/of.h
+index c38e41a..ab52243 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -650,4 +650,21 @@ static inline int of_multi_prop_cmp(const struct property *prop, const char *val
+
+ #endif /* !CONFIG_OF */
+
++
++/* illegal phandle value (set when unresolved) */
++#define OF_PHANDLE_ILLEGAL 0xdeadbeef
++
++#ifdef CONFIG_OF_RESOLVE
++
++int of_resolve(struct device_node *resolve);
++
++#else
++
++static inline int of_resolve(struct device_node *resolve)
++{
++ return -ENOTSUPP;
++}
++
++#endif
++
+ #endif /* _LINUX_OF_H */
diff --git a/patches/linux-3.8.13/0265-OF-Introduce-DT-overlay-support.patch b/patches/linux-3.8.13/0265-OF-Introduce-DT-overlay-support.patch
new file mode 100644
index 0000000..d863bb6
--- /dev/null
+++ b/patches/linux-3.8.13/0265-OF-Introduce-DT-overlay-support.patch
@@ -0,0 +1,1186 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 3 Jan 2013 12:23:07 +0200
+Subject: [PATCH] OF: Introduce DT overlay support.
+
+Introduce DT overlay support.
+Using this functionality it is possible to dynamically overlay a part of
+the kernel's tree with another tree that's been dynamically loaded.
+It is also possible to remove node and properties.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ Documentation/devicetree/overlay-notes.txt | 179 ++++++
+ drivers/of/Kconfig | 10 +
+ drivers/of/Makefile | 1 +
+ drivers/of/overlay.c | 831 ++++++++++++++++++++++++++++
+ include/linux/of.h | 107 ++++
+ 5 files changed, 1128 insertions(+)
+ create mode 100644 Documentation/devicetree/overlay-notes.txt
+ create mode 100644 drivers/of/overlay.c
+
+diff --git a/Documentation/devicetree/overlay-notes.txt b/Documentation/devicetree/overlay-notes.txt
+new file mode 100644
+index 0000000..5289cbb
+--- /dev/null
++++ b/Documentation/devicetree/overlay-notes.txt
+@@ -0,0 +1,179 @@
++Device Tree Overlay Notes
++-------------------------
++
++This document describes the implementation of the in-kernel
++device tree overlay functionality residing in drivers/of/overlay.c and is a
++companion document to Documentation/devicetree/dt-object-internal.txt[1] &
++Documentation/devicetree/dynamic-resolution-notes.txt[2]
++
++How overlays work
++-----------------
++
++A Device Tree's overlay purpose is to modify the kernel's live tree, and
++have the modification affecting the state of the the kernel in a way that
++is reflecting the changes.
++Since the kernel mainly deals with devices, any new device node that result
++in an active device should have it created while if the device node is either
++disabled or removed all together, the affected device should be deregistered.
++
++Lets take an example where we have a foo board with the following base tree
++which is taken from [1].
++
++---- foo.dts -----------------------------------------------------------------
++ /* FOO platform */
++ / {
++ compatible = "corp,foo";
++
++ /* shared resources */
++ res: res {
++ };
++
++ /* On chip peripherals */
++ ocp: ocp {
++ /* peripherals that are always instantiated */
++ peripheral1 { ... };
++ }
++ };
++---- foo.dts -----------------------------------------------------------------
++
++The overlay bar.dts, when loaded (and resolved as described in [2]) should
++
++---- bar.dts -----------------------------------------------------------------
++/plugin/; /* allow undefined label references and record them */
++/ {
++ .... /* various properties for loader use; i.e. part id etc. */
++ fragment@0 {
++ target = <&ocp>;
++ __overlay__ {
++ /* bar peripheral */
++ bar {
++ compatible = "corp,bar";
++ ... /* various properties and child nodes */
++ }
++ };
++ };
++};
++---- bar.dts -----------------------------------------------------------------
++
++result in foo+bar.dts
++
++---- foo+bar.dts -------------------------------------------------------------
++ /* FOO platform + bar peripheral */
++ / {
++ compatible = "corp,foo";
++
++ /* shared resources */
++ res: res {
++ };
++
++ /* On chip peripherals */
++ ocp: ocp {
++ /* peripherals that are always instantiated */
++ peripheral1 { ... };
++
++ /* bar peripheral */
++ bar {
++ compatible = "corp,bar";
++ ... /* various properties and child nodes */
++ }
++ }
++ };
++---- foo+bar.dts -------------------------------------------------------------
++
++As a result of the the overlay, a new device node (bar) has been created
++so a bar platform device will be registered and if a matching device driver
++is loaded the device will be created as expected.
++
++Overlay in-kernel API
++---------------------
++
++The steps typically required to get an overlay to work are as follows:
++
++1. Use of_build_overlay_info() to create an array of initialized and
++ready to use of_overlay_info structures.
++2. Call of_overlay() to apply the overlays declared in the array.
++3. If the overlay needs to be removed, call of_overlay_revert().
++4. Finally release the memory taken by the overlay info array by
++of_free_overlay_info().
++
++/**
++ * of_build_overlay_info - Build an overlay info array
++ * @tree: Device node containing all the overlays
++ * @cntp: Pointer to where the overlay info count will be help
++ * @ovinfop: Pointer to the pointer of an overlay info structure.
++ *
++ * Helper function that given a tree containing overlay information,
++ * allocates and builds an overlay info array containing it, ready
++ * for use using of_overlay.
++ *
++ * Returns 0 on success with the @cntp @ovinfop pointers valid,
++ * while on error a negative error value is returned.
++ */
++int of_build_overlay_info(struct device_node *tree,
++ int *cntp, struct of_overlay_info **ovinfop);
++
++/**
++ * of_free_overlay_info - Free an overlay info array
++ * @count: Number of of_overlay_info's
++ * @ovinfo_tab: Array of overlay_info's to free
++ *
++ * Releases the memory of a previously allocate ovinfo array
++ * by of_build_overlay_info.
++ * Returns 0, or an error if the arguments are bogus.
++ */
++int of_free_overlay_info(int count, struct of_overlay_info *ovinfo_tab);
++
++/**
++ * of_overlay - Apply @count overlays pointed at by @ovinfo_tab
++ * @count: Number of of_overlay_info's
++ * @ovinfo_tab: Array of overlay_info's to apply
++ *
++ * Applies the overlays given, while handling all error conditions
++ * appropriately. Either the operation succeeds, or if it fails the
++ * live tree is reverted to the state before the attempt.
++ * Returns 0, or an error if the overlay attempt failed.
++ */
++int of_overlay(int count, struct of_overlay_info *ovinfo_tab);
++
++/**
++ * of_overlay_revert - Revert a previously applied overlay
++ * @count: Number of of_overlay_info's
++ * @ovinfo_tab: Array of overlay_info's to apply
++ *
++ * Revert a previous overlay. The state of the live tree
++ * is reverted to the one before the overlay.
++ * Returns 0, or an error if the overlay table is not given.
++ */
++int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab);
++
++Overlay DTS Format
++------------------
++
++The DTS of an overlay should have the following format:
++
++{
++ /* ignored properties by the overlay */
++
++ fragment@0 { /* first child node */
++ target=<phandle>; /* target of the overlay */
++ __overlay__ {
++ property-a; /* add property-a to the target */
++ -property-b; /* remove property-b from target */
++ node-a { /* add to an existing, or create a node-a */
++ ...
++ };
++ -node-b { /* remove an existing node-b */
++ ...
++ };
++ };
++ }
++ fragment@1 { /* second child node */
++ ...
++ };
++ /* more fragments follow */
++}
++
++It should be noted that the DT overlay format described is the one expected
++by the of_build_overlay_info() function, which is a helper function. There
++is nothing stopping someone coming up with his own DTS format and that will
++end up filling in the fields of the of_overlay_info array.
+diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
+index f9a6193..964a1c2 100644
+--- a/drivers/of/Kconfig
++++ b/drivers/of/Kconfig
+@@ -92,4 +92,14 @@ config OF_RESOLVE
+ Enable OF dynamic resolution support. This allows you to
+ load Device Tree object fragments are run time.
+
++config OF_OVERLAY
++ bool "OF overlay support"
++ depends on OF
++ select OF_DYNAMIC
++ select OF_DEVICE
++ select OF_RESOLVE
++ help
++ OpenFirmware overlay support. Allows you to modify on runtime the
++ live tree using overlays.
++
+ endmenu # OF
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index 19a8593..307ceb6 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -12,3 +12,4 @@ obj-$(CONFIG_OF_PCI) += of_pci.o
+ obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
+ obj-$(CONFIG_OF_MTD) += of_mtd.o
+ obj-$(CONFIG_OF_RESOLVE) += resolver.o
++obj-$(CONFIG_OF_OVERLAY) += overlay.o
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+new file mode 100644
+index 0000000..f65c3a3
+--- /dev/null
++++ b/drivers/of/overlay.c
+@@ -0,0 +1,831 @@
++/*
++ * Functions for working with device tree overlays
++ *
++ * 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
++ * version 2 as published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++
++/**
++ * Apply a single overlay node recursively.
++ *
++ * Property or node names that start with '-' signal that
++ * the property/node is to be removed.
++ *
++ * All the property notifiers are appropriately called.
++ * Note that the in case of an error the target node is left
++ * in a inconsistent state. Error recovery should be performed
++ * by recording the modification using the of notifiers.
++ */
++static int of_overlay_apply_one(struct device_node *target,
++ const struct device_node *overlay)
++{
++ const char *pname, *cname;
++ struct device_node *child, *tchild;
++ struct property *prop, *propn, *tprop;
++ int remove;
++ char *full_name;
++ const char *suffix;
++ int ret;
++
++ /* sanity checks */
++ if (target == NULL || overlay == NULL)
++ return -EINVAL;
++
++ for_each_property_of_node(overlay, prop) {
++
++ /* don't touch, 'name' */
++ if (of_prop_cmp(prop->name, "name") == 0)
++ continue;
++
++ /* default is add */
++ remove = 0;
++ pname = prop->name;
++ if (*pname == '-') { /* skip, - notes removal */
++ pname++;
++ remove = 1;
++ propn = NULL;
++ } else {
++ propn = __of_copy_property(prop,
++ GFP_KERNEL);
++ if (propn == NULL)
++ return -ENOMEM;
++ }
++
++ tprop = of_find_property(target, pname, NULL);
++
++ /* found? */
++ if (tprop != NULL) {
++ if (propn != NULL)
++ ret = of_update_property(target, propn);
++ else
++ ret = of_remove_property(target, tprop);
++ } else {
++ if (propn != NULL)
++ ret = of_add_property(target, propn);
++ else
++ ret = 0;
++ }
++ if (ret != 0)
++ return ret;
++ }
++
++ __for_each_child_of_node(overlay, child) {
++
++ /* default is add */
++ remove = 0;
++ cname = child->name;
++ if (*cname == '-') { /* skip, - notes removal */
++ cname++;
++ remove = 1;
++ }
++
++ /* special case for nodes with a suffix */
++ suffix = strrchr(child->full_name, '@');
++ if (suffix != NULL) {
++ cname = kbasename(child->full_name);
++ WARN_ON(cname == NULL); /* sanity check */
++ if (cname == NULL)
++ continue;
++ if (*cname == '-')
++ cname++;
++ }
++
++ tchild = of_get_child_by_name(target, cname);
++ if (tchild != NULL) {
++
++ if (!remove) {
++
++ /* apply overlay recursively */
++ ret = of_overlay_apply_one(tchild, child);
++ of_node_put(tchild);
++
++ if (ret != 0)
++ return ret;
++
++ } else {
++
++ ret = of_detach_node(tchild);
++ of_node_put(tchild);
++ }
++
++ } else {
++
++ if (!remove) {
++ full_name = kasprintf(GFP_KERNEL, "%s/%s",
++ target->full_name, cname);
++ if (full_name == NULL)
++ return -ENOMEM;
++
++ /* create empty tree as a target */
++ tchild = __of_create_empty_node(cname,
++ child->type, full_name,
++ child->phandle, GFP_KERNEL);
++
++ /* free either way */
++ kfree(full_name);
++
++ if (tchild == NULL)
++ return -ENOMEM;
++
++ /* point to parent */
++ tchild->parent = target;
++
++ ret = of_attach_node(tchild);
++ if (ret != 0)
++ return ret;
++
++ /* apply the overlay */
++ ret = of_overlay_apply_one(tchild, child);
++ if (ret != 0) {
++ __of_free_tree(tchild);
++ return ret;
++ }
++ }
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * Lookup an overlay device entry
++ */
++struct of_overlay_device_entry *of_overlay_device_entry_lookup(
++ struct of_overlay_info *ovinfo, struct device_node *node)
++{
++ struct of_overlay_device_entry *re;
++
++ /* no need for locks, we're under the ovinfo->lock */
++ list_for_each_entry(re, &ovinfo->de_list, node) {
++ if (re->np == node)
++ return re;
++ }
++ return NULL;
++}
++
++/**
++ * Add an overlay log entry
++ */
++static int of_overlay_log_entry_entry_add(struct of_overlay_info *ovinfo,
++ unsigned long action, struct device_node *dn,
++ struct property *prop)
++{
++ struct of_overlay_log_entry *le;
++
++ /* check */
++ if (ovinfo == NULL || dn == NULL)
++ return -EINVAL;
++
++ le = kzalloc(sizeof(*le), GFP_KERNEL);
++ if (le == NULL) {
++ pr_err("%s: Failed to allocate\n", __func__);
++ return -ENOMEM;
++ }
++
++ /* get a reference to the node */
++ le->action = action;
++ le->np = of_node_get(dn);
++ le->prop = prop;
++
++ if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
++ le->old_prop = of_find_property(dn, prop->name, NULL);
++
++ list_add_tail(&le->node, &ovinfo->le_list);
++
++ return 0;
++}
++
++/**
++ * Add an overlay device entry
++ */
++static void of_overlay_device_entry_entry_add(struct of_overlay_info *ovinfo,
++ struct device_node *node, struct platform_device *pdev,
++ int state)
++{
++ struct of_overlay_device_entry *re;
++ int fresh;
++
++ /* check */
++ if (ovinfo == NULL)
++ return;
++
++ fresh = 0;
++ re = of_overlay_device_entry_lookup(ovinfo, node);
++ if (re == NULL) {
++ re = kzalloc(sizeof(*re), GFP_KERNEL);
++ if (re == NULL) {
++ pr_err("%s: Failed to allocate\n", __func__);
++ return;
++ }
++ fresh = 1;
++ }
++
++ if (re->np == NULL)
++ re->np = of_node_get(node);
++ if (re->pdev == NULL)
++ re->pdev = of_dev_get(pdev);
++ re->state = state;
++
++ if (fresh)
++ list_add_tail(&re->node, &ovinfo->de_list);
++}
++
++/**
++ * Overlay OF notifier
++ *
++ * Called every time there's a property/node modification
++ * Every modification causes a log entry addition, while
++ * any modification that causes a node's state to change
++ * from/to disabled to/from enabled causes a device entry
++ * addition.
++ */
++static int of_overlay_notify(struct notifier_block *nb,
++ unsigned long action, void *arg)
++{
++#ifdef DEBUG
++ char *propstr = NULL, *spropstr = NULL;
++#endif
++ struct of_overlay_info *ovinfo;
++ struct device_node *node;
++ struct property *prop, *sprop, *cprop;
++ struct of_prop_reconfig *pr;
++ struct platform_device *pdev;
++ int state;
++ int err = 0;
++
++ ovinfo = container_of(nb, struct of_overlay_info, notifier);
++
++ /* prep vars */
++ switch (action) {
++ case OF_RECONFIG_ATTACH_NODE:
++ case OF_RECONFIG_DETACH_NODE:
++ node = arg;
++ if (node == NULL)
++ return notifier_from_errno(-EINVAL);
++ prop = NULL;
++#ifdef DEBUG
++ propstr = NULL;
++#endif
++ break;
++ case OF_RECONFIG_ADD_PROPERTY:
++ case OF_RECONFIG_REMOVE_PROPERTY:
++ case OF_RECONFIG_UPDATE_PROPERTY:
++ pr = arg;
++ if (pr == NULL)
++ return notifier_from_errno(-EINVAL);
++ node = pr->dn;
++ if (node == NULL)
++ return notifier_from_errno(-EINVAL);
++ prop = pr->prop;
++ if (prop == NULL)
++ return notifier_from_errno(-EINVAL);
++#ifdef DEBUG
++ propstr = __of_dump_prop(prop);
++#endif
++ break;
++ default:
++ return notifier_from_errno(0);
++ }
++
++ /* add to the log */
++ err = of_overlay_log_entry_entry_add(ovinfo, action, node, prop);
++ if (err != 0)
++ return notifier_from_errno(err);
++
++#ifdef DEBUG
++ switch (action) {
++ case OF_RECONFIG_ATTACH_NODE:
++ pr_debug("ATTACH_NODE: %s\n", node->full_name);
++ break;
++ case OF_RECONFIG_DETACH_NODE:
++ pr_debug("DETACH_NODE: %s\n", node->full_name);
++ break;
++ case OF_RECONFIG_ADD_PROPERTY:
++ pr_debug("ADD_PROP: %s %s%s\n", node->full_name,
++ prop->name, propstr);
++ break;
++ case OF_RECONFIG_REMOVE_PROPERTY:
++ pr_debug("REMOVE_PROP: %s %s%s\n", node->full_name,
++ prop->name, propstr);
++ break;
++ case OF_RECONFIG_UPDATE_PROPERTY:
++ sprop = of_find_property(node, prop->name, NULL);
++ if (sprop)
++ spropstr = __of_dump_prop(sprop);
++ pr_debug("UPDATE_PROP: %s '%s%s' -> '%s%s'\n", node->full_name,
++ prop->name, spropstr,
++ prop->name, propstr);
++ break;
++
++ }
++
++ /* NULL is fine */
++ kfree(propstr);
++ kfree(spropstr);
++#endif
++
++ /* come up with the device entry (if any) */
++ pdev = NULL;
++ state = 0;
++
++ /* determine the state the node will end up */
++ switch (action) {
++ case OF_RECONFIG_ATTACH_NODE:
++ /* we demand that a compatible node is present */
++ state = of_find_property(node, "compatible", NULL) &&
++ of_device_is_available(node);
++ break;
++ case OF_RECONFIG_DETACH_NODE:
++ state = 0;
++ pdev = of_find_device_by_node(node);
++ break;
++ case OF_RECONFIG_ADD_PROPERTY:
++ case OF_RECONFIG_REMOVE_PROPERTY:
++ case OF_RECONFIG_UPDATE_PROPERTY:
++ /* either one cause a change in state */
++ if (strcmp(prop->name, "status") != 0 &&
++ strcmp(prop->name, "compatible") != 0)
++ return notifier_from_errno(0);
++
++ if (strcmp(prop->name, "status") == 0) {
++ /* status */
++ cprop = of_find_property(node, "compatible", NULL);
++ sprop = action != OF_RECONFIG_REMOVE_PROPERTY ?
++ prop : NULL;
++ } else {
++ /* compatible */
++ sprop = of_find_property(node, "status", NULL);
++ cprop = action != OF_RECONFIG_REMOVE_PROPERTY ?
++ prop : NULL;
++ }
++
++ state = cprop && cprop->length > 0 &&
++ (!sprop || (sprop->length > 0 &&
++ (strcmp(sprop->value, "okay") == 0 ||
++ strcmp(sprop->value, "ok") == 0)));
++ break;
++
++ default:
++ return notifier_from_errno(0);
++ }
++
++ if (state == 0)
++ pdev = of_find_device_by_node(node);
++
++ of_overlay_device_entry_entry_add(ovinfo, node, pdev, state);
++
++ return notifier_from_errno(err);
++}
++
++/**
++ * Prepare for the overlay, for now it just registers the
++ * notifier.
++ */
++static int of_overlay_prep_one(struct of_overlay_info *ovinfo)
++{
++ int err;
++
++ err = of_reconfig_notifier_register(&ovinfo->notifier);
++ if (err != 0) {
++ pr_err("%s: failed to register notifier for '%s'\n",
++ __func__, ovinfo->target->full_name);
++ return err;
++ }
++ return 0;
++}
++
++/**
++ * Revert one overlay
++ * Either due to an error, or due to normal overlay removal.
++ * Using the log entries, we revert any change to the live tree.
++ * In the same manner, using the device entries we enable/disable
++ * the platform devices appropriately.
++ */
++static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
++{
++ struct of_overlay_device_entry *re, *ren;
++ struct of_overlay_log_entry *le, *len;
++ struct property *prop, **propp;
++ struct platform_device *pdev, *parent_pdev;
++ int ret;
++ unsigned long flags;
++
++ if (!ovinfo || !ovinfo->target || !ovinfo->overlay)
++ return;
++
++ pr_debug("%s: Reverting overlay on '%s'\n", __func__,
++ ovinfo->target->full_name);
++
++ /* overlay applied correctly, now create/destroy pdevs */
++ list_for_each_entry_safe_reverse(re, ren, &ovinfo->de_list, node) {
++
++ if (!re->state) {
++
++ parent_pdev = of_find_device_by_node(re->np->parent);
++
++ pr_debug("%s: creating new platform device "
++ "new_node='%s' %p\n",
++ __func__, re->np->full_name, re->np);
++
++ pdev = of_platform_device_create(re->np, NULL,
++ parent_pdev ? &parent_pdev->dev : NULL);
++ of_dev_put(parent_pdev);
++
++ if (pdev == NULL) {
++ pr_warn("%s: Failed to create platform device "
++ "for '%s'\n",
++ __func__, re->np->full_name);
++ }
++
++ } else {
++
++ if (re->pdev) {
++ pr_debug("%s: removing pdev %s\n", __func__,
++ dev_name(&re->pdev->dev));
++ platform_device_unregister(re->pdev);
++ }
++ }
++
++ of_node_put(re->np);
++
++ list_del(&re->node);
++
++ kfree(re);
++ }
++
++ list_for_each_entry_safe_reverse(le, len, &ovinfo->le_list, node) {
++
++ ret = 0;
++ switch (le->action) {
++ case OF_RECONFIG_ATTACH_NODE:
++ pr_debug("Reverting ATTACH_NODE %s\n",
++ le->np->full_name);
++ ret = of_detach_node(le->np);
++ break;
++
++ case OF_RECONFIG_DETACH_NODE:
++ pr_debug("Reverting DETACH_NODE %s\n",
++ le->np->full_name);
++ ret = of_attach_node(le->np);
++ break;
++
++ case OF_RECONFIG_ADD_PROPERTY:
++ pr_debug("Reverting ADD_PROPERTY %s %s\n",
++ le->np->full_name, le->prop->name);
++ ret = of_remove_property(le->np, le->prop);
++ break;
++
++ case OF_RECONFIG_REMOVE_PROPERTY:
++ case OF_RECONFIG_UPDATE_PROPERTY:
++
++ pr_debug("Reverting %s_PROPERTY %s %s\n",
++ le->action == OF_RECONFIG_REMOVE_PROPERTY ?
++ "REMOVE" : "UPDATE",
++ le->np->full_name, le->prop->name);
++
++ /* property is possibly on deadprops (avoid alloc) */
++ write_lock_irqsave(&devtree_lock, flags);
++ prop = le->action == OF_RECONFIG_REMOVE_PROPERTY ?
++ le->prop : le->old_prop;
++ propp = &le->np->deadprops;
++ while (*propp != NULL) {
++ if (*propp == prop)
++ break;
++ propp = &(*propp)->next;
++ }
++ if (*propp != NULL) {
++ /* remove it from deadprops */
++ (*propp)->next = prop->next;
++ write_unlock_irqrestore(&devtree_lock, flags);
++ } else {
++ write_unlock_irqrestore(&devtree_lock, flags);
++ /* not found, just make a copy */
++ prop = __of_copy_property(prop, GFP_KERNEL);
++ if (prop == NULL) {
++ pr_err("%s: Failed to copy property\n",
++ __func__);
++ break;
++ }
++ }
++
++ if (le->action == OF_RECONFIG_REMOVE_PROPERTY)
++ ret = of_add_property(le->np, prop);
++ else
++ ret = of_update_property(le->np, prop);
++ break;
++
++ default:
++ /* nothing */
++ break;
++ }
++
++ if (ret != 0)
++ pr_err("%s: revert on node %s Failed!\n",
++ __func__, le->np->full_name);
++
++ of_node_put(le->np);
++
++ list_del(&le->node);
++
++ kfree(le);
++ }
++}
++
++/**
++ * Perform the post overlay work.
++ *
++ * We unregister the notifier, and in the case on an error we
++ * revert the overlay.
++ * If the overlay applied correctly, we iterare over the device entries
++ * and create/destroy the platform devices appropriately.
++ */
++static int of_overlay_post_one(struct of_overlay_info *ovinfo, int err)
++{
++ struct of_overlay_device_entry *re, *ren;
++ struct platform_device *pdev, *parent_pdev;
++
++ of_reconfig_notifier_unregister(&ovinfo->notifier);
++
++ if (err != 0) {
++ /* revert this (possible partially applied) overlay */
++ of_overlay_revert_one(ovinfo);
++ return 0;
++ }
++
++ /* overlay applied correctly, now create/destroy pdevs */
++ list_for_each_entry_safe(re, ren, &ovinfo->de_list, node) {
++
++ if (re->state) {
++
++ parent_pdev = of_find_device_by_node(re->np->parent);
++
++ pr_debug("%s: creating new platform device "
++ "new_node='%s' %p\n",
++ __func__, re->np->full_name, re->np);
++
++ pdev = of_platform_device_create(re->np, NULL,
++ parent_pdev ? &parent_pdev->dev : NULL);
++ of_dev_put(parent_pdev);
++
++ if (pdev == NULL) {
++ pr_warn("%s: Failed to create platform device "
++ "for '%s'\n",
++ __func__, re->np->full_name);
++ }
++
++ /* keep it around */
++ re->pdev = pdev;
++
++ } else {
++
++ if (re->pdev) {
++ platform_device_unregister(re->pdev);
++ }
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * of_overlay - Apply @count overlays pointed at by @ovinfo_tab
++ * @count: Number of of_overlay_info's
++ * @ovinfo_tab: Array of overlay_info's to apply
++ *
++ * Applies the overlays given, while handling all error conditions
++ * appropriately. Either the operation succeeds, or if it fails the
++ * live tree is reverted to the state before the attempt.
++ * Returns 0, or an error if the overlay attempt failed.
++ */
++int of_overlay(int count, struct of_overlay_info *ovinfo_tab)
++{
++ struct of_overlay_info *ovinfo;
++ int i, err;
++
++ if (!ovinfo_tab)
++ return -EINVAL;
++
++ /* first we apply the overlays atomically */
++ for (i = 0; i < count; i++) {
++
++ ovinfo = &ovinfo_tab[i];
++
++ mutex_lock(&ovinfo->lock);
++
++ err = of_overlay_prep_one(ovinfo);
++ if (err == 0)
++ err = of_overlay_apply_one(ovinfo->target,
++ ovinfo->overlay);
++ of_overlay_post_one(ovinfo, err);
++
++ mutex_unlock(&ovinfo->lock);
++
++ if (err != 0) {
++ pr_err("%s: overlay failed '%s'\n",
++ __func__, ovinfo->target->full_name);
++ goto err_fail;
++ }
++ }
++
++ return 0;
++
++err_fail:
++ while (--i >= 0) {
++ ovinfo = &ovinfo_tab[i];
++
++ mutex_lock(&ovinfo->lock);
++ of_overlay_revert_one(ovinfo);
++ mutex_unlock(&ovinfo->lock);
++ }
++
++ return err;
++}
++
++/**
++ * of_overlay_revert - Revert a previously applied overlay
++ * @count: Number of of_overlay_info's
++ * @ovinfo_tab: Array of overlay_info's to apply
++ *
++ * Revert a previous overlay. The state of the live tree
++ * is reverted to the one before the overlay.
++ * Returns 0, or an error if the overlay table is not given.
++ */
++int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab)
++{
++ struct of_overlay_info *ovinfo;
++ int i;
++
++ if (!ovinfo_tab)
++ return -EINVAL;
++
++ /* revert the overlays in reverse */
++ for (i = count - 1; i >= 0; i--) {
++
++ ovinfo = &ovinfo_tab[i];
++
++ mutex_lock(&ovinfo->lock);
++ of_overlay_revert_one(ovinfo);
++ mutex_unlock(&ovinfo->lock);
++
++ }
++
++ return 0;
++}
++
++/**
++ * of_init_overlay_info - Initialize a single of_overlay_info structure
++ * @ovinfo: Pointer to the overlay info structure to initialize
++ *
++ * Initialize a single overlay info structure.
++ */
++void of_init_overlay_info(struct of_overlay_info *ovinfo)
++{
++ memset(ovinfo, 0, sizeof(ovinfo));
++ mutex_init(&ovinfo->lock);
++ INIT_LIST_HEAD(&ovinfo->de_list);
++ INIT_LIST_HEAD(&ovinfo->le_list);
++
++ ovinfo->notifier.notifier_call = of_overlay_notify;
++}
++
++/**
++ * of_fill_overlay_info - Fill an overlay info structure
++ * @info_node: Device node containing the overlay
++ * @ovinfo: Pointer to the overlay info structure to fill
++ *
++ * Fills an overlay info structure with the overlay information
++ * from a device node. This device node must have a target property
++ * which contains a phandle of the overlay target node, and an
++ * __overlay__ child node which has the overlay contents.
++ * Both ovinfo->target & ovinfo->overlay have their references taken.
++ *
++ * Returns 0 on success, or a negative error value.
++ */
++int of_fill_overlay_info(struct device_node *info_node,
++ struct of_overlay_info *ovinfo)
++{
++ u32 val;
++ int ret;
++
++ if (!info_node || !ovinfo)
++ return -EINVAL;
++
++ ret = of_property_read_u32(info_node, "target", &val);
++ if (ret != 0)
++ goto err_fail;
++
++ ovinfo->target = of_find_node_by_phandle(val);
++ if (ovinfo->target == NULL)
++ goto err_fail;
++
++ ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__");
++ if (ovinfo->overlay == NULL)
++ goto err_fail;
++
++ return 0;
++
++err_fail:
++ of_node_put(ovinfo->target);
++ of_node_put(ovinfo->overlay);
++
++ memset(ovinfo, 0, sizeof(*ovinfo));
++ return -EINVAL;
++}
++
++/**
++ * of_build_overlay_info - Build an overlay info array
++ * @tree: Device node containing all the overlays
++ * @cntp: Pointer to where the overlay info count will be help
++ * @ovinfop: Pointer to the pointer of an overlay info structure.
++ *
++ * Helper function that given a tree containing overlay information,
++ * allocates and builds an overlay info array containing it, ready
++ * for use using of_overlay.
++ *
++ * Returns 0 on success with the @cntp @ovinfop pointers valid,
++ * while on error a negative error value is returned.
++ */
++int of_build_overlay_info(struct device_node *tree,
++ int *cntp, struct of_overlay_info **ovinfop)
++{
++ struct device_node *node;
++ struct of_overlay_info *ovinfo;
++ int cnt, err;
++
++ if (tree == NULL || cntp == NULL || ovinfop == NULL)
++ return -EINVAL;
++
++ /* worst case; every child is a node */
++ cnt = 0;
++ for_each_child_of_node(tree, node)
++ cnt++;
++
++ ovinfo = kzalloc(cnt * sizeof(*ovinfo), GFP_KERNEL);
++ if (ovinfo == NULL)
++ return -ENOMEM;
++
++ cnt = 0;
++ for_each_child_of_node(tree, node) {
++
++ of_init_overlay_info(&ovinfo[cnt]);
++ err = of_fill_overlay_info(node, &ovinfo[cnt]);
++ if (err == 0)
++ cnt++;
++ }
++
++ /* if nothing filled, return error */
++ if (cnt == 0) {
++ kfree(ovinfo);
++ return -ENODEV;
++ }
++
++ *cntp = cnt;
++ *ovinfop = ovinfo;
++
++ return 0;
++}
++
++/**
++ * of_free_overlay_info - Free an overlay info array
++ * @count: Number of of_overlay_info's
++ * @ovinfo_tab: Array of overlay_info's to free
++ *
++ * Releases the memory of a previously allocate ovinfo array
++ * by of_build_overlay_info.
++ * Returns 0, or an error if the arguments are bogus.
++ */
++int of_free_overlay_info(int count, struct of_overlay_info *ovinfo_tab)
++{
++ struct of_overlay_info *ovinfo;
++ int i;
++
++ if (!ovinfo_tab || count < 0)
++ return -EINVAL;
++
++ /* do it in reverse */
++ for (i = count - 1; i >= 0; i--) {
++ ovinfo = &ovinfo_tab[i];
++
++ of_node_put(ovinfo->target);
++ of_node_put(ovinfo->overlay);
++ }
++ kfree(ovinfo_tab);
++
++ return 0;
++}
++
+diff --git a/include/linux/of.h b/include/linux/of.h
+index ab52243..8a908f0 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -667,4 +667,111 @@ static inline int of_resolve(struct device_node *resolve)
+
+ #endif
+
++/**
++ * Overlay support
++ */
++
++/**
++ * struct of_overlay_log_entry - Holds a DT log entry
++ * @node: list_head for the log list
++ * @action: notifier action
++ * @np: pointer to the device node affected
++ * @prop: pointer to the property affected
++ * @old_prop: hold a pointer to the original property
++ *
++ * Every modification of the device tree during application of the
++ * overlay is held in a list of of_overlay_log_entry structures.
++ * That way we can recover from a partial application, or we can
++ * revert the overlay properly.
++ */
++struct of_overlay_log_entry {
++ struct list_head node;
++ unsigned long action;
++ struct device_node *np;
++ struct property *prop;
++ struct property *old_prop;
++};
++
++/**
++ * struct of_overlay_device_entry - Holds an overlay device entry
++ * @node: list_head for the device list
++ * @np: device node pointer to the device node affected
++ * @pdev: pointer to the platform device affected
++ * @state: new device state
++ *
++ * When the overlay results in a device node's state to change this
++ * fact is recorded in a list of device entries. After the overlay
++ * is applied we can create/destroy the platform devices according
++ * to the new state of the live tree.
++ */
++struct of_overlay_device_entry {
++ struct list_head node;
++ struct device_node *np;
++ struct platform_device *pdev;
++ int state;
++};
++
++/**
++ * struct of_overlay_info - Holds a single overlay info
++ * @target: target of the overlay operation
++ * @overlay: pointer to the overlay contents node
++ * @lock: Lock to hold when accessing the lists
++ * @le_list: List of the overlay logs
++ * @de_list: List of the overlay records
++ * @notifier: of reconfiguration notifier
++ *
++ * Holds a single overlay state, including all the overlay logs &
++ * records.
++ */
++struct of_overlay_info {
++ struct device_node *target;
++ struct device_node *overlay;
++ struct mutex lock;
++ struct list_head le_list;
++ struct list_head de_list;
++ struct notifier_block notifier;
++};
++
++#ifdef CONFIG_OF_OVERLAY
++
++int of_overlay(int count, struct of_overlay_info *ovinfo_tab);
++int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab);
++
++int of_fill_overlay_info(struct device_node *info_node,
++ struct of_overlay_info *ovinfo);
++int of_build_overlay_info(struct device_node *tree,
++ int *cntp, struct of_overlay_info **ovinfop);
++int of_free_overlay_info(int cnt, struct of_overlay_info *ovinfo);
++
++#else
++
++static inline int of_overlay(int count, struct of_overlay_info *ovinfo_tab)
++{
++ return -ENOTSUPP;
++}
++
++static inline int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab)
++{
++ return -ENOTSUPP;
++}
++
++static inline int of_fill_overlay_info(struct device_node *info_node,
++ struct of_overlay_info *ovinfo)
++{
++ return -ENOTSUPP;
++}
++
++static inline int of_build_overlay_info(struct device_node *tree,
++ int *cntp, struct of_overlay_info **ovinfop)
++{
++ return -ENOTSUPP;
++}
++
++int of_free_overlay_info(int cnt, struct of_overlay_info *ovinfo)
++{
++ return -ENOTSUPP;
++}
++
++#endif
++
+ #endif /* _LINUX_OF_H */
diff --git a/patches/linux-3.8.13/0266-capemgr-Capemgr-makefiles-and-Kconfig-fragments.patch b/patches/linux-3.8.13/0266-capemgr-Capemgr-makefiles-and-Kconfig-fragments.patch
new file mode 100644
index 0000000..c4ecff8
--- /dev/null
+++ b/patches/linux-3.8.13/0266-capemgr-Capemgr-makefiles-and-Kconfig-fragments.patch
@@ -0,0 +1,115 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 20:56:48 +0200
+Subject: [PATCH] capemgr: Capemgr makefiles and Kconfig fragments.
+
+Introduce a cape loader using DT overlays and dynamic
+DT objects.
+
+Makefile and Kconfig fragments.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/Kconfig | 2 ++
+ drivers/misc/Kconfig | 2 ++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/cape/Kconfig | 5 +++++
+ drivers/misc/cape/Makefile | 5 +++++
+ drivers/misc/cape/beaglebone/Kconfig | 18 ++++++++++++++++++
+ drivers/misc/cape/beaglebone/Makefile | 6 ++++++
+ 7 files changed, 39 insertions(+)
+ create mode 100644 drivers/misc/cape/Kconfig
+ create mode 100644 drivers/misc/cape/Makefile
+ create mode 100644 drivers/misc/cape/beaglebone/Kconfig
+ create mode 100644 drivers/misc/cape/beaglebone/Makefile
+
+diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
+index 9cbbd2b..d8486c8 100644
+--- a/arch/arm/mach-omap2/Kconfig
++++ b/arch/arm/mach-omap2/Kconfig
+@@ -18,6 +18,8 @@ config ARCH_OMAP2PLUS_TYPICAL
+ select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
+ select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
+ select VFP
++ select OF_OVERLAY
++ select OF_RESOLVE
+ help
+ Compile a kernel suitable for booting most boards
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index cd43cbd..a0f75af 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -513,4 +513,6 @@ source "drivers/misc/lis3lv02d/Kconfig"
+ source "drivers/misc/carma/Kconfig"
+ source "drivers/misc/altera-stapl/Kconfig"
+ source "drivers/misc/mei/Kconfig"
++source "drivers/misc/cape/Kconfig"
++
+ endmenu
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 661d093..f063b90 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -50,3 +50,4 @@ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+ obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
+ obj-$(CONFIG_INTEL_MEI) += mei/
+ obj-$(CONFIG_GPEVT) += gpevt.o
++obj-y += cape/
+diff --git a/drivers/misc/cape/Kconfig b/drivers/misc/cape/Kconfig
+new file mode 100644
+index 0000000..a2ef85e
+--- /dev/null
++++ b/drivers/misc/cape/Kconfig
+@@ -0,0 +1,5 @@
++#
++# Capes
++#
++
++source "drivers/misc/cape/beaglebone/Kconfig"
+diff --git a/drivers/misc/cape/Makefile b/drivers/misc/cape/Makefile
+new file mode 100644
+index 0000000..7c4eb96
+--- /dev/null
++++ b/drivers/misc/cape/Makefile
+@@ -0,0 +1,5 @@
++#
++# Makefile for cape like devices
++#
++
++obj-y += beaglebone/
+diff --git a/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig
+new file mode 100644
+index 0000000..ebeedce
+--- /dev/null
++++ b/drivers/misc/cape/beaglebone/Kconfig
+@@ -0,0 +1,18 @@
++#
++# Beaglebone capes
++#
++
++config CAPE_BEAGLEBONE
++ tristate "Beaglebone cape support"
++ depends on ARCH_OMAP2PLUS && OF && I2C
++ default n
++ select OF_PLUGIN
++ help
++ Say Y here to include support for beaglebone capes
++
++config CAPE_BEAGLEBONE_GEIGER
++ tristate "Beaglebone Geiger Cape"
++ depends on CAPE_BEAGLEBONE
++ default n
++ help
++ Say Y here to include support for the Geiger Cape
+diff --git a/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile
+new file mode 100644
+index 0000000..b79ace4
+--- /dev/null
++++ b/drivers/misc/cape/beaglebone/Makefile
+@@ -0,0 +1,6 @@
++#
++# Makefile for beaglebone capes
++#
++
++obj-$(CONFIG_CAPE_BEAGLEBONE) += capemgr.o
++obj-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += cape-bone-geiger.o
diff --git a/patches/linux-3.8.13/0267-capemgr-Beaglebone-capemanager.patch b/patches/linux-3.8.13/0267-capemgr-Beaglebone-capemanager.patch
new file mode 100644
index 0000000..18bdda4
--- /dev/null
+++ b/patches/linux-3.8.13/0267-capemgr-Beaglebone-capemanager.patch
@@ -0,0 +1,1855 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:00:31 +0200
+Subject: [PATCH] capemgr: Beaglebone capemanager
+
+A cape loader based on DT overlays and DT objects.
+
+Beaglebone cape manager implementation.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 1835 ++++++++++++++++++++++++++++++++
+ 1 file changed, 1835 insertions(+)
+ create mode 100644 drivers/misc/cape/beaglebone/capemgr.c
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+new file mode 100644
+index 0000000..651f48d
+--- /dev/null
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -0,0 +1,1835 @@
++/*
++ * TI Beaglebone cape 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/of_fdt.h>
++#include <linux/slab.h>
++#include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/firmware.h>
++#include <linux/err.h>
++#include <linux/ctype.h>
++#include <linux/string.h>
++#include <linux/memory.h>
++#include <linux/i2c.h>
++#include <linux/i2c/eeprom.h>
++#include <linux/kthread.h>
++
++/* extra command line overrides */
++static char *extra_override = NULL;
++module_param(extra_override, charp, 0444);
++
++struct bone_capemgr_info;
++
++struct slot_ee_attribute {
++ struct device_attribute devattr;
++ unsigned int field;
++ struct bone_cape_slot *slot; /* this is filled when instantiated */
++};
++#define to_slot_ee_attribute(x) \
++ container_of((x), struct slot_ee_attribute, devattr)
++
++struct bbrd_ee_attribute {
++ struct device_attribute devattr;
++ unsigned int field;
++};
++#define to_bbrd_ee_attribute(x) \
++ container_of((x), struct bbrd_ee_attribute, devattr)
++
++struct bone_cape_slot {
++ struct list_head node;
++ struct bone_capemgr_info *info;
++ int slotno;
++ u32 eeprom_handle;
++ int eeprom_addr;
++ struct i2c_client *client;
++ struct memory_accessor *macc;
++ unsigned int probed : 1;
++ unsigned int probe_failed : 1;
++ unsigned int override : 1;
++ char text_id[256];
++ char signature[256];
++ /* quick access */
++ char board_name[32+1];
++ char version[4+1];
++ char manufacturer[16+1];
++ char part_number[16+1];
++
++ /* attribute group */
++ char *ee_attr_name;
++ int ee_attrs_count;
++ struct slot_ee_attribute *ee_attrs;
++ struct attribute **ee_attrs_tab;
++ struct attribute_group attrgroup;
++
++ unsigned int loading : 1;
++ unsigned int loaded : 1;
++ char *dtbo;
++ const struct firmware *fw;
++ struct device_node *overlay;
++ int ovinfo_cnt;
++ struct of_overlay_info *ovinfo;
++
++ /* loader thread */
++ struct task_struct *loader_thread;
++};
++
++struct bone_capemap {
++ struct list_head node;
++ char *part_number;
++ struct device_node *map_node;
++};
++
++struct bone_baseboard {
++
++ /* from the matched boardmap node */
++ char *compatible_name;
++
++ /* filled in by reading the eeprom */
++ char signature[256];
++ char text_id[64+1];
++
++ /* quick access */
++ char board_name[8+1];
++ char revision[4+1];
++ char serial_number[12+1];
++
++ /* access to the eeprom */
++ u32 eeprom_handle;
++ int eeprom_addr;
++ struct i2c_client *client;
++ struct memory_accessor *macc;
++ unsigned int probed : 1;
++ unsigned int probe_failed : 1;
++ unsigned int override : 1;
++};
++
++struct bone_capemgr_info {
++ struct platform_device *pdev;
++
++ atomic_t next_slot_nr;
++ struct list_head slot_list;
++ struct mutex slots_list_mutex;
++
++ int capemaps_nr;
++ struct list_head capemap_list;
++ struct mutex capemap_mutex;
++
++ /* baseboard EEPROM data */
++ struct bone_baseboard baseboard;
++};
++
++static int bone_slot_fill_override(struct bone_cape_slot *slot,
++ struct device_node *node,
++ const char *part_number, const char *version);
++static struct bone_cape_slot *bone_capemgr_add_slot(
++ struct bone_capemgr_info *info, struct device_node *node,
++ const char *part_number, const char *version);
++static int bone_capemgr_load(struct bone_cape_slot *slot);
++static int bone_capemgr_unload(struct bone_cape_slot *slot);
++
++/* baseboard EEPROM field definition */
++#define BBRD_EE_FIELD_HEADER 0
++#define BBRD_EE_FIELD_BOARD_NAME 1
++#define BBRD_EE_FIELD_REVISION 2
++#define BBRD_EE_FIELD_SERIAL_NUMBER 3
++#define BBRD_EE_FIELD_CONFIG_OPTION 4
++#define BBRD_EE_FILED_RSVD1 5
++#define BBRD_EE_FILED_RSVD2 6
++#define BBRD_EE_FILED_RSVD3 7
++
++/* cape EEPROM field definitions */
++#define CAPE_EE_FIELD_HEADER 0
++#define CAPE_EE_FIELD_EEPROM_REV 1
++#define CAPE_EE_FIELD_BOARD_NAME 2
++#define CAPE_EE_FIELD_VERSION 3
++#define CAPE_EE_FIELD_MANUFACTURER 4
++#define CAPE_EE_FIELD_PART_NUMBER 5
++#define CAPE_EE_FIELD_NUMBER_OF_PINS 6
++#define CAPE_EE_FIELD_SERIAL_NUMBER 7
++#define CAPE_EE_FIELD_PIN_USAGE 8
++#define CAPE_EE_FIELD_VDD_3V3EXP 9
++#define CAPE_EE_FIELD_VDD_5V 10
++#define CAPE_EE_FIELD_SYS_5V 11
++#define CAPE_EE_FIELD_DC_SUPPLIED 12
++#define CAPE_EE_FIELD_FIELDS_NR 13
++
++#define EE_FIELD_MAKE_HEADER(p) \
++ ({ \
++ const u8 *_p = (p); \
++ (((u32)_p[0] << 24) | ((u32)_p[1] << 16) | \
++ ( (u32)_p[2] << 8) | (u32)_p[3] ); \
++ })
++
++#define EE_FIELD_HEADER_VALID 0xaa5533ee
++
++struct ee_field {
++ const char *name;
++ int start;
++ int size;
++ unsigned int ascii : 1;
++ unsigned int strip_trailing_dots : 1;
++ const char *override;
++};
++
++/* baseboard EEPROM definitions */
++static const struct ee_field bbrd_sig_fields[] = {
++ [BBRD_EE_FIELD_HEADER] = {
++ .name = "header",
++ .start = 0,
++ .size = 4,
++ .ascii = 0,
++ .override = "\xaa\x55\x33\xee", /* AA 55 33 EE */
++ },
++ [BBRD_EE_FIELD_BOARD_NAME] = {
++ .name = "board-name",
++ .start = 4,
++ .size = 8,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Board Name",
++ },
++ [BBRD_EE_FIELD_REVISION] = {
++ .name = "revision",
++ .start = 12,
++ .size = 4,
++ .ascii = 1,
++ .override = "00A0",
++ },
++ [BBRD_EE_FIELD_SERIAL_NUMBER] = {
++ .name = "serial-number",
++ .start = 16,
++ .size = 12,
++ .ascii = 1,
++ .override = "0000000000",
++ },
++ [BBRD_EE_FIELD_CONFIG_OPTION] = {
++ .name = "config-option",
++ .start = 28,
++ .size = 32,
++ },
++};
++
++/* cape EEPROM definitions */
++static const struct ee_field cape_sig_fields[] = {
++ [CAPE_EE_FIELD_HEADER] = {
++ .name = "header",
++ .start = 0,
++ .size = 4,
++ .ascii = 0,
++ .override = "\xaa\x55\x33\xee", /* AA 55 33 EE */
++ },
++ [CAPE_EE_FIELD_EEPROM_REV] = {
++ .name = "eeprom-format-revision",
++ .start = 4,
++ .size = 2,
++ .ascii = 1,
++ .override = "A0",
++ },
++ [CAPE_EE_FIELD_BOARD_NAME] = {
++ .name = "board-name",
++ .start = 6,
++ .size = 32,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Override Board Name",
++ },
++ [CAPE_EE_FIELD_VERSION] = {
++ .name = "version",
++ .start = 38,
++ .size = 4,
++ .ascii = 1,
++ .override = "00A0",
++ },
++ [CAPE_EE_FIELD_MANUFACTURER] = {
++ .name = "manufacturer",
++ .start = 42,
++ .size = 16,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Override Manuf",
++ },
++ [CAPE_EE_FIELD_PART_NUMBER] = {
++ .name = "part-number",
++ .start = 58,
++ .size = 16,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Override Part#",
++ },
++ [CAPE_EE_FIELD_NUMBER_OF_PINS] = {
++ .name = "number-of-pins",
++ .start = 74,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [CAPE_EE_FIELD_SERIAL_NUMBER] = {
++ .name = "serial-number",
++ .start = 76,
++ .size = 12,
++ .ascii = 1,
++ .override = "0000000000",
++ },
++ [CAPE_EE_FIELD_PIN_USAGE] = {
++ .name = "pin-usage",
++ .start = 88,
++ .size = 140,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [CAPE_EE_FIELD_VDD_3V3EXP] = {
++ .name = "vdd-3v3exp",
++ .start = 228,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [CAPE_EE_FIELD_VDD_5V] = {
++ .name = "vdd-5v",
++ .start = 230,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [CAPE_EE_FIELD_SYS_5V] = {
++ .name = "sys-5v",
++ .start = 232,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [CAPE_EE_FIELD_DC_SUPPLIED] = {
++ .name = "dc-supplied",
++ .start = 234,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++};
++
++static char *ee_field_get(const struct ee_field *sig_field,
++ const void *data, int field, char *buf, int bufsz)
++{
++ int len;
++
++ /* enough space? */
++ if (bufsz < sig_field->size + sig_field->ascii)
++ return NULL;
++
++ memcpy(buf, (char *)data + sig_field->start, sig_field->size);
++
++ /* terminate ascii field */
++ if (sig_field->ascii)
++ buf[sig_field->size] = '\0';;
++
++ if (sig_field->strip_trailing_dots) {
++ len = strlen(buf);
++ while (len > 1 && buf[len - 1] == '.')
++ buf[--len] = '\0';
++ }
++
++ return buf;
++}
++
++char *bbrd_ee_field_get(const void *data,
++ int field, char *buf, int bufsz)
++{
++ if ((unsigned int)field >= ARRAY_SIZE(bbrd_sig_fields))
++ return NULL;
++
++ return ee_field_get(&bbrd_sig_fields[field], data, field, buf, bufsz);
++}
++
++char *cape_ee_field_get(const void *data,
++ int field, char *buf, int bufsz)
++{
++ if ((unsigned int)field >= ARRAY_SIZE(cape_sig_fields))
++ return NULL;
++
++ return ee_field_get(&cape_sig_fields[field], data, field, buf, bufsz);
++}
++
++#ifdef CONFIG_OF
++static const struct of_device_id bone_capemgr_of_match[] = {
++ {
++ .compatible = "ti,bone-capemgr",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bone_capemgr_of_match);
++
++#endif
++
++static int bone_baseboard_scan(struct bone_baseboard *bbrd)
++{
++ struct bone_capemgr_info *info = container_of(bbrd,
++ struct bone_capemgr_info, baseboard);
++ struct memory_accessor *macc = bbrd->macc;
++ const u8 *p;
++ int i, r;
++
++ /* need to read EEPROM? */
++ if (bbrd->probed)
++ goto bbrd_fail_check;
++
++ bbrd->probed = 1;
++
++ if (!bbrd->override) {
++
++ if (macc == NULL || macc->read == NULL) {
++ dev_err(&info->pdev->dev,
++ "bone: No memory accessor for baseboard\n");
++ return -ENODEV;
++ }
++
++ for (i = 0; i < 10; i++) {
++
++ /* perform read */
++ r = macc->read(macc, bbrd->signature,
++ 0, sizeof(bbrd->signature));
++
++ if (r == sizeof(bbrd->signature))
++ break;
++
++ dev_info(&info->pdev->dev,
++ "bone: scan failed (%d time)\n", i + 1);
++
++ msleep(500);
++ }
++
++ if (i >= 10) {
++ bbrd->probe_failed = 1;
++ return r >= 0 ? -EINVAL : r;
++ }
++
++ } else
++ dev_info(&info->pdev->dev,
++ "bone: Using override eeprom data for baseboard\n");
++
++ p = bbrd->signature;
++ if (EE_FIELD_MAKE_HEADER(p) != EE_FIELD_HEADER_VALID) {
++ dev_err(&info->pdev->dev, "bone: Invalid signature "
++ "'%08x' at baseboard\n",
++ EE_FIELD_MAKE_HEADER(p));
++ bbrd->probe_failed = 1;
++ return -ENODEV;
++ }
++
++ bbrd_ee_field_get(bbrd->signature,
++ BBRD_EE_FIELD_BOARD_NAME,
++ bbrd->board_name, sizeof(bbrd->board_name));
++ bbrd_ee_field_get(bbrd->signature,
++ BBRD_EE_FIELD_REVISION,
++ bbrd->revision, sizeof(bbrd->revision));
++ bbrd_ee_field_get(bbrd->signature,
++ BBRD_EE_FIELD_SERIAL_NUMBER,
++ bbrd->serial_number, sizeof(bbrd->serial_number));
++
++ /* board_name,version,manufacturer,part_number */
++ snprintf(bbrd->text_id, sizeof(bbrd->text_id) - 1,
++ "%s,%s,%s", bbrd->board_name, bbrd->revision,
++ bbrd->serial_number);
++
++ /* terminate always */
++ bbrd->text_id[sizeof(bbrd->text_id) - 1] = '\0';
++
++bbrd_fail_check:
++ /* bbrd has failed and we don't support hotpluging */
++ if (bbrd->probe_failed)
++ return -ENODEV;
++
++ return 0;
++}
++
++static int bone_slot_scan(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ struct memory_accessor *macc = slot->macc;
++ const u8 *p;
++ int r;
++
++ /* need to read EEPROM? */
++ if (slot->probed)
++ goto slot_fail_check;
++
++ slot->probed = 1;
++
++ if (!slot->override) {
++
++ if (macc == NULL || macc->read == NULL) {
++ dev_err(&info->pdev->dev,
++ "bone: No memory accessor for slot %d\n",
++ slot->slotno);
++ return -ENODEV;
++ }
++
++ /* perform read */
++ r = macc->read(macc, slot->signature,
++ 0, sizeof(slot->signature));
++
++ if (r != sizeof(slot->signature)) {
++ slot->probe_failed = 1;
++ return r >= 0 ? -EINVAL : r;
++ }
++ } else
++ dev_info(&info->pdev->dev,
++ "bone: Using override eeprom data at slot %d\n",
++ slot->slotno);
++
++ p = slot->signature;
++ if (EE_FIELD_MAKE_HEADER(p) != EE_FIELD_HEADER_VALID) {
++ dev_err(&info->pdev->dev, "bone: Invalid signature "
++ "'%08x' at slot %d\n",
++ EE_FIELD_MAKE_HEADER(p),
++ slot->slotno);
++ slot->probe_failed = 1;
++ return -ENODEV;
++ }
++
++ cape_ee_field_get(slot->signature,
++ CAPE_EE_FIELD_BOARD_NAME,
++ slot->board_name, sizeof(slot->board_name));
++ cape_ee_field_get(slot->signature,
++ CAPE_EE_FIELD_VERSION,
++ slot->version, sizeof(slot->version));
++ cape_ee_field_get(slot->signature,
++ CAPE_EE_FIELD_MANUFACTURER,
++ slot->manufacturer, sizeof(slot->manufacturer));
++ cape_ee_field_get(slot->signature,
++ CAPE_EE_FIELD_PART_NUMBER,
++ slot->part_number, sizeof(slot->part_number));
++
++ /* board_name,version,manufacturer,part_number */
++ snprintf(slot->text_id, sizeof(slot->text_id) - 1,
++ "%s,%s,%s,%s", slot->board_name, slot->version,
++ slot->manufacturer, slot->part_number);
++
++ /* terminate always */
++ slot->text_id[sizeof(slot->text_id) - 1] = '\0';
++
++slot_fail_check:
++ /* slot has failed and we don't support hotpluging */
++ if (slot->probe_failed)
++ return -ENODEV;
++
++ return 0;
++}
++
++/* check an override slot node if it's compatible */
++static int bone_is_compatible_override(struct device_node *node,
++ const char *compatible_name)
++{
++ struct property *prop;
++ char *buf, *s, *e, *sn;
++ const char *part_number;
++ const char *version;
++ char *tmp_part_number, *tmp_version;
++ int found;
++
++ /* check if the slot is compatible with the board */
++ prop = of_find_property(node, "compatible", NULL);
++
++ /* no prop, it's something that's compatible with everything */
++ if (prop == NULL)
++ return 1;
++
++ /* check if it's directly compatible with the baseboard */
++ if (of_multi_prop_cmp(prop, compatible_name) == 0)
++ return 1;
++
++ /* final try, check if it's specified in the kernel command line */
++ if (extra_override == NULL)
++ return 0;
++
++ /* the compatible name should have kernel-command-line in it */
++ if (of_multi_prop_cmp(prop, "kernel-command-line") != 0)
++ return 0;
++
++ /* we must have at least the part-name */
++ if (of_property_read_string(node, "part-number",
++ &part_number) != 0)
++ return 0;
++
++ /* read the version (if it exists) */
++ if (of_property_read_string(node, "version", &version) != 0)
++ version = NULL;
++
++ /* copy the argument to work on it */
++ buf = kstrdup(extra_override, GFP_KERNEL);
++
++ /* no memory, too bad... */
++ if (buf == NULL)
++ return 0;
++
++ found = 0;
++ s = buf;
++ e = s + strlen(s);
++ while (s < e) {
++ /* find comma separator */
++ sn = strchr(s, ',');
++ if (sn != NULL)
++ *sn++ = '\0';
++ else
++ sn = e;
++ tmp_part_number = s;
++ tmp_version = strchr(tmp_part_number, ':');
++ if (tmp_version != NULL)
++ *tmp_version++ = '\0';
++ s = sn;
++
++ /* the part names must match */
++ if (strcmp(tmp_part_number, part_number) != 0)
++ continue;
++
++ pr_info("override: part-number='%s' version='%s' "
++ "tmp_version='%s'\n",
++ part_number,
++ version ? version : "N/A",
++ tmp_version ? tmp_version : "N/A");
++
++ /* if there's no version, match any */
++ if (version == NULL || tmp_version == NULL ||
++ strcmp(version, tmp_version) == 0) {
++ found = 1;
++ break;
++ }
++ }
++
++ kfree(buf);
++
++ return found;
++}
++
++static int bone_is_compatible_runtime_override(struct device_node *node,
++ const char *req_part_number, const char *req_version)
++{
++ struct property *prop;
++ const char *part_number;
++ const char *version;
++
++ /* only check overrides */
++ if (!of_property_read_bool(node, "ti,cape-override"))
++ return 0;
++
++ /* check if the slot is compatible with the board */
++ prop = of_find_property(node, "compatible", NULL);
++
++ /* no prop, it's something that's compatible with everything */
++ if (prop == NULL)
++ return 1;
++
++ /* the compatible name should have runtime in it */
++ if (of_multi_prop_cmp(prop, "runtime") != 0)
++ return 0;
++
++ /* we must have at least the part-name */
++ if (of_property_read_string(node, "part-number",
++ &part_number) != 0)
++ return 0;
++
++ /* read the version (if it exists) */
++ if (of_property_read_string(node, "version", &version) != 0)
++ version = NULL;
++
++ /* the part names must match */
++ if (strcmp(req_part_number, part_number) != 0)
++ return 0;
++
++ /* if any version is null, any version matches */
++ if (version == NULL || req_version == NULL)
++ return 1;
++
++ /* finally versions must match */
++ return strcmp(req_version, version) == 0;
++}
++
++
++static ssize_t slot_ee_attr_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct slot_ee_attribute *ee_attr = to_slot_ee_attribute(attr);
++ struct bone_cape_slot *slot = ee_attr->slot;
++ const struct ee_field *sig_field;
++ int i, len;
++ char *p, *s;
++ u16 val;
++
++ /* add newline for ascii fields */
++ sig_field = &cape_sig_fields[ee_attr->field];
++
++ len = sig_field->size + sig_field->ascii;
++ p = kmalloc(len, GFP_KERNEL);
++ if (p == NULL)
++ return -ENOMEM;
++
++ s = cape_ee_field_get(slot->signature, ee_attr->field, p, len);
++ if (s == NULL)
++ return -EINVAL;
++
++ /* add newline for ascii fields and return */
++ if (sig_field->ascii) {
++ len = sprintf(buf, "%s\n", s);
++ goto out;
++ }
++
++ /* case by case handling */
++ switch (ee_attr->field) {
++ case CAPE_EE_FIELD_HEADER:
++ len = sprintf(buf, "%02x %02x %02x %02x\n",
++ s[0], s[1], s[2], s[3]);
++ break;
++
++ /* 2 bytes */
++ case CAPE_EE_FIELD_NUMBER_OF_PINS:
++ case CAPE_EE_FIELD_VDD_3V3EXP:
++ case CAPE_EE_FIELD_VDD_5V:
++ case CAPE_EE_FIELD_SYS_5V:
++ case CAPE_EE_FIELD_DC_SUPPLIED:
++ /* the bone is LE */
++ val = s[0] & (s[1] << 8);
++ len = sprintf(buf, "%u\n", (unsigned int)val & 0xffff);
++ break;
++
++ case CAPE_EE_FIELD_PIN_USAGE:
++
++ len = 0;
++ for (i = 0; i < sig_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 SLOT_EE_ATTR(_name, _field) \
++ { \
++ .devattr = __ATTR(_name, 0440, slot_ee_attr_show, NULL), \
++ .field = CAPE_EE_FIELD_##_field , \
++ .slot = NULL, \
++ }
++
++static const struct slot_ee_attribute slot_ee_attrs[] = {
++ SLOT_EE_ATTR(header, HEADER),
++ SLOT_EE_ATTR(eeprom-format-revision, EEPROM_REV),
++ SLOT_EE_ATTR(board-name, BOARD_NAME),
++ SLOT_EE_ATTR(version, VERSION),
++ SLOT_EE_ATTR(manufacturer, MANUFACTURER),
++ SLOT_EE_ATTR(part-number, PART_NUMBER),
++ SLOT_EE_ATTR(number-of-pins, NUMBER_OF_PINS),
++ SLOT_EE_ATTR(serial-number, SERIAL_NUMBER),
++ SLOT_EE_ATTR(pin-usage, PIN_USAGE),
++ SLOT_EE_ATTR(vdd-3v3exp, VDD_3V3EXP),
++ SLOT_EE_ATTR(vdd-5v, VDD_5V),
++ SLOT_EE_ATTR(sys-5v, SYS_5V),
++ SLOT_EE_ATTR(dc-supplied, DC_SUPPLIED),
++};
++
++static int bone_cape_slot_sysfs_register(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ struct device *dev = &info->pdev->dev;
++ struct slot_ee_attribute *ee_attr;
++ struct attribute_group *attrgroup;
++ int i, err, sz;
++
++ slot->ee_attr_name = kasprintf(GFP_KERNEL, "slot-%d", slot->slotno);
++ if (slot->ee_attr_name == NULL) {
++ dev_err(dev, "slot #%d: Failed to allocate ee_attr_name\n",
++ slot->slotno);
++ err = -ENOMEM;
++ goto err_fail_no_ee_attr_name;
++ }
++
++ slot->ee_attrs_count = ARRAY_SIZE(slot_ee_attrs);
++
++ sz = slot->ee_attrs_count * sizeof(*slot->ee_attrs);
++ slot->ee_attrs = kmalloc(sz, GFP_KERNEL);
++ if (slot->ee_attrs == NULL) {
++ dev_err(dev, "slot #%d: Failed to allocate ee_attrs\n",
++ slot->slotno);
++ err = -ENOMEM;
++ goto err_fail_no_ee_attrs;
++ }
++
++ attrgroup = &slot->attrgroup;
++ memset(attrgroup, 0, sizeof(*attrgroup));
++ attrgroup->name = slot->ee_attr_name;
++
++ sz = sizeof(*slot->ee_attrs_tab) * (slot->ee_attrs_count + 1);
++ attrgroup->attrs = kmalloc(sz, GFP_KERNEL);
++ if (attrgroup->attrs == NULL) {
++ dev_err(dev, "slot #%d: Failed to allocate ee_attrs_tab\n",
++ slot->slotno);
++ err = -ENOMEM;
++ goto err_fail_no_ee_attrs_tab;
++ }
++ /* copy everything over */
++ memcpy(slot->ee_attrs, slot_ee_attrs, sizeof(slot_ee_attrs));
++
++ /* bind this attr to the slot */
++ for (i = 0; i < slot->ee_attrs_count; i++) {
++ ee_attr = &slot->ee_attrs[i];
++ ee_attr->slot = slot;
++ attrgroup->attrs[i] = &ee_attr->devattr.attr;
++ }
++ attrgroup->attrs[i] = NULL;
++
++ err = sysfs_create_group(&dev->kobj, attrgroup);
++ if (err != 0) {
++ dev_err(dev, "slot #%d: Failed to allocate ee_attrs_tab\n",
++ slot->slotno);
++ err = -ENOMEM;
++ goto err_fail_no_ee_attrs_group;
++ }
++
++ return 0;
++
++err_fail_no_ee_attrs_group:
++ kfree(slot->ee_attrs_tab);
++err_fail_no_ee_attrs_tab:
++ kfree(slot->ee_attrs);
++err_fail_no_ee_attrs:
++ kfree(slot->ee_attr_name);
++err_fail_no_ee_attr_name:
++ return err;
++}
++
++static void bone_cape_slot_sysfs_unregister(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ struct device *dev = &info->pdev->dev;
++
++ sysfs_remove_group(&dev->kobj, &slot->attrgroup);
++ kfree(slot->ee_attrs_tab);
++ kfree(slot->ee_attrs);
++ kfree(slot->ee_attr_name);
++}
++
++static ssize_t bbrd_ee_attr_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct bbrd_ee_attribute *ee_attr = to_bbrd_ee_attribute(attr);
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capemgr_info *info = platform_get_drvdata(pdev);
++ struct bone_baseboard *bbrd = &info->baseboard;
++ const struct ee_field *sig_field;
++ u16 val;
++ int i, len;
++ char *p, *s;
++
++ /* add newline for ascii fields */
++ sig_field = &bbrd_sig_fields[ee_attr->field];
++
++ len = sig_field->size + sig_field->ascii;
++ p = kmalloc(len, GFP_KERNEL);
++ if (p == NULL)
++ return -ENOMEM;
++
++ s = bbrd_ee_field_get(bbrd->signature, ee_attr->field, p, len);
++ if (s == NULL)
++ return -EINVAL;
++
++ /* add newline for ascii fields and return */
++ if (sig_field->ascii) {
++ len = sprintf(buf, "%s\n", s);
++ goto out;
++ }
++
++ /* case by case handling */
++ switch (ee_attr->field) {
++ case BBRD_EE_FIELD_HEADER:
++ len = sprintf(buf, "%02x %02x %02x %02x\n",
++ s[0], s[1], s[2], s[3]);
++ break;
++
++ case BBRD_EE_FIELD_CONFIG_OPTION:
++ len = 0;
++ for (i = 0; i < sig_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 BBRD_EE_ATTR(_name, _field) \
++ { \
++ .devattr = __ATTR(_name, 0440, bbrd_ee_attr_show, NULL), \
++ .field = BBRD_EE_FIELD_##_field , \
++ }
++
++static struct bbrd_ee_attribute bbrd_ee_attrs[] = {
++ BBRD_EE_ATTR(header, HEADER),
++ BBRD_EE_ATTR(board-name, BOARD_NAME),
++ BBRD_EE_ATTR(revision, REVISION),
++ BBRD_EE_ATTR(serial-number, SERIAL_NUMBER),
++ BBRD_EE_ATTR(config-option, CONFIG_OPTION),
++};
++
++static struct attribute *bbrd_attrs_flat[] = {
++ &bbrd_ee_attrs[BBRD_EE_FIELD_HEADER ].devattr.attr,
++ &bbrd_ee_attrs[BBRD_EE_FIELD_BOARD_NAME ].devattr.attr,
++ &bbrd_ee_attrs[BBRD_EE_FIELD_REVISION ].devattr.attr,
++ &bbrd_ee_attrs[BBRD_EE_FIELD_SERIAL_NUMBER ].devattr.attr,
++ &bbrd_ee_attrs[BBRD_EE_FIELD_CONFIG_OPTION ].devattr.attr,
++ NULL,
++};
++
++static const struct attribute_group bbrd_attr_group = {
++ .name = "baseboard",
++ .attrs = bbrd_attrs_flat,
++};
++
++static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capemgr_info *info = platform_get_drvdata(pdev);
++ struct bone_cape_slot *slot;
++ ssize_t len, sz;
++
++ mutex_lock(&info->slots_list_mutex);
++ sz = 0;
++ list_for_each_entry(slot, &info->slot_list, node) {
++
++ len = sprintf(buf, "%2d: %02x:%c%c%c%c%c %s\n",
++ slot->slotno,
++ (int)slot->client ?
++ slot->client->addr & 0x7f : 0xff,
++ slot->probed ? 'P' : '-',
++ slot->probe_failed ? 'F' : '-',
++ slot->override ? 'O' : '-',
++ slot->loading ? 'l' : '-',
++ slot->loaded ? 'L' : '-',
++ slot->text_id);
++
++ buf += len;
++ sz += len;
++ }
++ mutex_unlock(&info->slots_list_mutex);
++
++ 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_capemgr_info *info = platform_get_drvdata(pdev);
++ struct bone_cape_slot *slot;
++ struct device_node *pnode, *node, *slots_node;
++ char *s, *part_number, *version;
++ int ret;
++ int slotno;
++
++ /* check for remove slot */
++ if (strlen(buf) > 0 && buf[0] == '-') {
++ slotno = simple_strtoul(buf + 1, NULL, 10);
++
++ /* now load each (take lock to be sure */
++ mutex_lock(&info->slots_list_mutex);
++ list_for_each_entry(slot, &info->slot_list, node) {
++ if (slotno == slot->slotno)
++ break;
++ }
++ mutex_unlock(&info->slots_list_mutex);
++
++ if (slot == NULL)
++ return -ENODEV;
++
++ bone_capemgr_unload(slot);
++
++ return strlen(buf);
++ }
++
++ part_number = kstrdup(buf, GFP_KERNEL);
++ if (part_number == NULL)
++ return -ENOMEM;
++
++ /* remove trailing spaces dots and newlines */
++ s = part_number + strlen(part_number);
++ while (s > part_number &&
++ (isspace(s[-1]) || s[-1] == '\n' || s[-1] == '.'))
++ *--s = '\0';
++
++ version = strchr(part_number, ':');
++ if (version != NULL)
++ *version++ = '\0';
++
++ dev_info(&pdev->dev, "part_number '%s', version '%s'\n",
++ part_number, version ? version : "N/A");
++
++ pnode = pdev->dev.of_node;
++ node = NULL;
++ slot = NULL;
++ ret = 0;
++
++ /* iterate over any slots */
++ slots_node = of_get_child_by_name(pnode, "slots");
++ if (slots_node != NULL) {
++ for_each_child_of_node(slots_node, node) {
++
++ /* check if the override is compatible */
++ if (!bone_is_compatible_runtime_override(node,
++ part_number, version))
++ continue;
++
++ slot = bone_capemgr_add_slot(info, node,
++ part_number, version);
++ if (IS_ERR(slot)) {
++ dev_err(&pdev->dev, "Failed to add slot #%d\n",
++ atomic_read(&info->next_slot_nr) - 1);
++ ret = PTR_ERR(slot);
++ slot = NULL;
++ goto err_fail;
++ }
++ break;
++ }
++ of_node_put(node);
++ of_node_put(slots_node);
++ }
++ slots_node = NULL;
++
++ /* no specific slot found, try immediate */
++ if (!slot)
++ slot = bone_capemgr_add_slot(info, NULL,
++ part_number, version);
++
++ if (IS_ERR_OR_NULL(slot)) {
++ dev_err(&pdev->dev, "Failed to add slot #%d\n",
++ atomic_read(&info->next_slot_nr) - 1);
++ ret = slot ? PTR_ERR(slot) : -ENODEV;
++ slot = NULL;
++ goto err_fail;
++ }
++
++ kfree(part_number);
++
++ ret = bone_capemgr_load(slot);
++
++ return ret == 0 ? strlen(buf) : ret;
++err_fail:
++ of_node_put(node);
++ of_node_put(slots_node);
++ kfree(part_number);
++ return ret;
++}
++
++static DEVICE_ATTR(slots, 0644, slots_show, slots_store);
++
++static int bone_capemgr_info_sysfs_register(struct bone_capemgr_info *info)
++{
++ struct device *dev = &info->pdev->dev;
++ int ret;
++
++ ret = device_create_file(dev, &dev_attr_slots);
++ if (ret != 0)
++ goto err_fail_no_slots;
++
++ ret = sysfs_create_group(&dev->kobj, &bbrd_attr_group);
++ if (ret != 0)
++ goto err_fail_no_bbrd_grp;
++
++ return 0;
++err_fail_no_bbrd_grp:
++ device_remove_file(dev, &dev_attr_slots);
++err_fail_no_slots:
++ return ret;
++}
++
++static void bone_capemgr_info_sysfs_unregister(struct bone_capemgr_info *info)
++{
++ struct device *dev = &info->pdev->dev;
++
++ sysfs_remove_group(&dev->kobj, &bbrd_attr_group);
++ device_remove_file(dev, &dev_attr_slots);
++}
++
++static int bone_capemgr_load(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ struct device *dev = &info->pdev->dev;
++ struct device_node *node;
++ struct property *prop;
++ const char *dtbo;
++ int found, err;
++ struct bone_capemap *capemap;
++
++ if (slot->probe_failed)
++ return -ENODEV;
++
++ if (slot->loaded)
++ return -EAGAIN;
++
++ mutex_lock(&info->capemap_mutex);
++ found = 0;
++ list_for_each_entry(capemap, &info->capemap_list, node) {
++ if (strcmp(capemap->part_number, slot->part_number) == 0) {
++ found = 1;
++ break;
++ }
++ }
++
++ /* found? */
++ if (found) {
++ if (capemap->map_node == NULL) {
++ mutex_unlock(&info->capemap_mutex);
++ /* need to match programatically; not supported yet */
++ dev_err(dev, "slot #%d: Failed to find capemap "
++ "for '%s'\n",
++ slot->slotno, slot->part_number);
++ return -ENODEV;
++ }
++
++ /* locate first match */
++ dtbo = NULL;
++ for_each_child_of_node(capemap->map_node, node) {
++
++ /* dtbo must exist */
++ if (of_property_read_string(node, "dtbo", &dtbo) != 0)
++ continue;
++
++ /* get version property (if any) */
++ prop = of_find_property(node, "version", NULL);
++
++ /* if no version node exists, we match */
++ if (prop == NULL)
++ break;
++
++ if (of_multi_prop_cmp(prop, slot->version) == 0)
++ break;
++ }
++
++ if (node == NULL) {
++ /* can't find dtbo version node? try the default */
++ if (of_property_read_string(capemap->map_node,
++ "dtbo", &dtbo) != 0) {
++ mutex_unlock(&info->capemap_mutex);
++ dev_err(dev, "slot #%d: Failed to find dtbo "
++ "for '%s'\n",
++ slot->slotno,
++ slot->part_number);
++ return -ENODEV;
++ }
++ }
++
++ slot->dtbo = kstrdup(dtbo, GFP_KERNEL);
++ of_node_put(node); /* handles NULL */
++ } else {
++ dev_info(dev, "slot #%d: Requesting part number/version based "
++ "'%s-%s.dtbo\n",
++ slot->slotno,
++ slot->part_number, slot->version);
++
++ /* no specific capemap node; request the part number + .dtbo*/
++ slot->dtbo = kasprintf(GFP_KERNEL, "%s-%s.dtbo",
++ slot->part_number, slot->version);
++ }
++
++ if (slot->dtbo == NULL) {
++ mutex_unlock(&info->capemap_mutex);
++ dev_err(dev, "slot #%d: Failed to get dtbo '%s'\n",
++ slot->slotno, dtbo);
++ return -ENOMEM;
++ }
++
++ dev_info(dev, "slot #%d: Requesting firmware '%s' for board-name '%s'"
++ ", version '%s'\n",
++ slot->slotno,
++ slot->dtbo, slot->board_name, slot->version);
++
++ err = request_firmware(&slot->fw, slot->dtbo, dev);
++ if (err != 0) {
++ dev_err(dev, "failed to load firmware '%s'\n", slot->dtbo);
++ mutex_unlock(&info->capemap_mutex);
++ goto err_fail_no_fw;
++ }
++
++ dev_info(dev, "slot #%d: dtbo '%s' loaded; converting to live tree\n",
++ slot->slotno, slot->dtbo);
++
++ mutex_unlock(&info->capemap_mutex);
++
++ of_fdt_unflatten_tree((void *)slot->fw->data, &slot->overlay);
++ if (slot->overlay == NULL) {
++ dev_err(dev, "slot #%d: Failed to unflatten\n",
++ slot->slotno);
++ err = -EINVAL;
++ goto err_fail;
++ }
++
++ /* mark it as detached */
++ of_node_set_flag(slot->overlay, OF_DETACHED);
++
++ /* perform resolution */
++ err = of_resolve(slot->overlay);
++ if (err != 0) {
++ dev_err(dev, "slot #%d: Failed to resolve tree\n",
++ slot->slotno);
++ goto err_fail;
++ }
++
++ /* now build an overlay info array */
++ err = of_build_overlay_info(slot->overlay,
++ &slot->ovinfo_cnt, &slot->ovinfo);
++ if (err != 0) {
++ dev_err(dev, "slot #%d: Failed to build overlay info\n",
++ slot->slotno);
++ goto err_fail;
++ }
++
++ dev_info(dev, "slot #%d: #%d overlays\n",
++ slot->slotno, slot->ovinfo_cnt);
++
++ err = of_overlay(slot->ovinfo_cnt, slot->ovinfo);
++ if (err != 0) {
++ if (err != 0) {
++ dev_err(dev, "slot #%d: Failed to overlay\n",
++ slot->slotno);
++ goto err_fail_overlay;
++ }
++ }
++
++ dev_info(dev, "slot #%d: Applied #%d overlays.\n",
++ slot->slotno, slot->ovinfo_cnt);
++
++ slot->loading = 0;
++ slot->loaded = 1;
++
++ return 0;
++
++err_fail_overlay:
++
++ of_free_overlay_info(slot->ovinfo_cnt, slot->ovinfo);
++ slot->ovinfo_cnt = 0;
++ slot->ovinfo = NULL;
++
++err_fail:
++
++ /* we can't free the overlay, because the unflatten method is a mess */
++ /* __of_free_tree(slot->overlay); */
++ slot->overlay = NULL;
++
++ release_firmware(slot->fw);
++ slot->fw = NULL;
++
++err_fail_no_fw:
++ return err;
++}
++
++static int bone_capemgr_unload(struct bone_cape_slot *slot)
++{
++ if (!slot->loaded || slot->ovinfo == NULL)
++ return -EINVAL;
++
++ of_overlay_revert(slot->ovinfo_cnt, slot->ovinfo);
++
++ slot->ovinfo_cnt = 0;
++ kfree(slot->ovinfo);
++
++ slot->loaded = 0;
++
++ return 0;
++
++}
++
++static int bone_slot_fill_override(struct bone_cape_slot *slot,
++ struct device_node *node,
++ const char *part_number, const char *version)
++{
++ const struct ee_field *sig_field;
++ struct property *prop;
++ int i, len, has_part_number;
++ char *p;
++
++ slot->probe_failed = 0;
++ slot->probed = 0;
++
++ /* zero out signature */
++ memset(slot->signature, 0,
++ sizeof(slot->signature));
++
++ /* first, fill in all with override defaults */
++ for (i = 0; i < ARRAY_SIZE(cape_sig_fields); i++) {
++
++ sig_field = &cape_sig_fields[i];
++
++ /* point to the entry */
++ p = slot->signature + sig_field->start;
++
++ if (sig_field->override)
++ memcpy(p, sig_field->override,
++ sig_field->size);
++ else
++ memset(p, 0, sig_field->size);
++ }
++
++ /* and now, fill any override data from the node */
++ has_part_number = 0;
++ if (node != NULL) {
++ for (i = 0; i < ARRAY_SIZE(cape_sig_fields); i++) {
++
++ sig_field = &cape_sig_fields[i];
++
++ /* find property with the same name (if any) */
++ prop = of_find_property(node, sig_field->name, NULL);
++ if (prop == NULL)
++ continue;
++
++ /* point to the entry */
++ p = slot->signature + sig_field->start;
++
++ /* copy and zero out any remainder */
++ len = prop->length;
++ if (prop->length > sig_field->size)
++ len = sig_field->size;
++ memcpy(p, prop->value, len);
++ if (len < sig_field->size)
++ memset(p + len, 0, sig_field->size - len);
++
++ /* remember if we got a part number which is required */
++ if (i == CAPE_EE_FIELD_PART_NUMBER && len > 0)
++ has_part_number = 1;
++ }
++ }
++
++ /* if a part_number is supplied use it */
++ if (part_number && (len = strlen(part_number)) > 0) {
++ sig_field = &cape_sig_fields[CAPE_EE_FIELD_PART_NUMBER];
++
++ /* point to the entry */
++ p = slot->signature + sig_field->start;
++
++ /* copy and zero out any remainder */
++ if (len > sig_field->size)
++ len = sig_field->size;
++ memcpy(p, part_number, len);
++ if (len < sig_field->size)
++ memset(p + len, 0, sig_field->size - len);
++
++ has_part_number = 1;
++ }
++
++ /* if a version is supplied use it */
++ if (version && (len = strlen(version)) > 0) {
++ sig_field = &cape_sig_fields[CAPE_EE_FIELD_VERSION];
++
++ /* point to the entry */
++ p = slot->signature + sig_field->start;
++
++ /* copy and zero out any remainder */
++ if (len > sig_field->size)
++ len = sig_field->size;
++ memcpy(p, version, len);
++ if (len < sig_field->size)
++ memset(p + len, 0, sig_field->size - len);
++ }
++
++ /* we must have a part number */
++ if (!has_part_number)
++ return -EINVAL;
++
++ slot->override = 1;
++
++ return 0;
++}
++
++static struct bone_cape_slot *
++bone_capemgr_add_slot(struct bone_capemgr_info *info, struct device_node *node,
++ const char *part_number, const char *version)
++{
++ struct device_node *eeprom_node;
++ struct bone_cape_slot *slot;
++ struct device *dev = &info->pdev->dev;
++ int slotno;
++ int ret;
++
++ eeprom_node = NULL;
++
++ slotno = atomic_inc_return(&info->next_slot_nr) - 1;
++
++ slot = devm_kzalloc(dev, sizeof(*slot), GFP_KERNEL);
++ if (slot == NULL) {
++ ret = -ENOMEM;
++ goto err_no_mem;
++ }
++ slot->info = info;
++ slot->slotno = slotno;
++
++ if (node && !of_property_read_bool(node, "ti,cape-override")) {
++ ret = of_property_read_u32(node, "eeprom",
++ &slot->eeprom_handle);
++ if (ret != 0) {
++ dev_err(dev, "slot #%d: failed to locate eeprom\n",
++ slotno);
++ goto err_no_eeprom;
++ }
++ eeprom_node = of_find_node_by_phandle(slot->eeprom_handle);
++ if (eeprom_node == NULL) {
++ dev_err(dev, "slot #%d: failed to find eeprom node\n",
++ slotno);
++ ret = -ENODEV;
++ goto err_no_eeprom_node;
++ }
++ slot->client = of_find_i2c_device_by_node(eeprom_node);
++ if (slot->client == NULL) {
++ dev_err(dev, "slot #%d: failed to find i2c client\n",
++ slotno);
++ ret = -ENODEV;
++ goto err_no_eeprom_client;
++ }
++ /* release ref to the node & get ref of the i2c client */
++ of_node_put(eeprom_node);
++ eeprom_node = NULL;
++ i2c_use_client(slot->client);
++
++ /* grab the memory accessor of the eeprom */
++ slot->macc = i2c_eeprom_get_memory_accessor(slot->client);
++ if (IS_ERR_OR_NULL(slot->macc)) {
++ dev_err(dev, "slot #%d: failed to get "
++ "memory accessor\n", slotno);
++ ret = slot->macc == NULL ? -ENODEV :
++ PTR_ERR(slot->macc);
++ slot->macc = NULL;
++ goto err_no_eeprom_macc;
++ }
++
++ } else {
++ if (node)
++ dev_info(dev, "slot #%d: specific override\n", slotno);
++ else
++ dev_info(dev, "slot #%d: generic override\n", slotno);
++
++ /* fill in everything with defaults first */
++ ret = bone_slot_fill_override(slot, node, part_number, version);
++ if (ret != 0) {
++ dev_err(dev, "slot #%d: override failed\n",
++ slotno);
++ goto err_no_eeprom;
++ }
++ }
++
++ ret = bone_slot_scan(slot);
++ if (ret != 0) {
++
++ if (!slot->probe_failed) {
++ dev_err(dev, "slot #%d: scan failed\n",
++ slotno);
++ goto err_bad_scan;
++ }
++
++ dev_err(dev, "slot #%d: No cape found\n",
++ slotno);
++ /* but all is fine */
++ } else {
++ dev_info(dev, "slot #%d: '%s'\n",
++ slotno, slot->text_id);
++
++ ret = bone_cape_slot_sysfs_register(slot);
++ if (ret != 0) {
++ dev_err(dev, "slot #%d: sysfs register failed\n",
++ slotno);
++ goto err_no_sysfs;
++ }
++
++ }
++
++ /* add to the slot list */
++ mutex_lock(&info->slots_list_mutex);
++ list_add_tail(&slot->node, &info->slot_list);
++ mutex_unlock(&info->slots_list_mutex);
++
++ return slot;
++
++err_no_sysfs:
++err_bad_scan:
++err_no_eeprom_macc:
++ i2c_release_client(slot->client);
++err_no_eeprom_client:
++ of_node_put(eeprom_node); /* handles NULL */
++err_no_eeprom_node:
++ /* nothing */
++err_no_eeprom:
++ devm_kfree(dev, slot);
++
++err_no_mem:
++ return ERR_PTR(ret);
++}
++
++static int bone_capemgr_loader(void *data)
++{
++ struct bone_cape_slot *slot = data;
++
++ return bone_capemgr_load(slot);
++}
++
++static int __devinit
++bone_capemgr_probe(struct platform_device *pdev)
++{
++ struct bone_capemgr_info *info;
++ struct bone_baseboard *bbrd;
++ struct bone_cape_slot *slot;
++ struct device_node *pnode = pdev->dev.of_node;
++ struct device_node *baseboardmaps_node;
++ struct device_node *slots_node, *capemaps_node, *node;
++ struct device_node *eeprom_node;
++ const char *part_number;
++ const char *board_name;
++ const char *compatible_name;
++ struct bone_capemap *capemap;
++ int ret, len;
++
++ /* we don't use platform_data at all; we require OF */
++ if (pnode == NULL)
++ return -ENOTSUPP;
++
++ info = devm_kzalloc(&pdev->dev,
++ sizeof(struct bone_capemgr_info), GFP_KERNEL);
++ if (!info) {
++ dev_err(&pdev->dev, "Failed to allocate device structure\n");
++ return -ENOMEM;
++ }
++
++ info->pdev = pdev;
++ platform_set_drvdata(pdev, info);
++
++ atomic_set(&info->next_slot_nr, 0);
++ INIT_LIST_HEAD(&info->slot_list);
++ mutex_init(&info->slots_list_mutex);
++
++ INIT_LIST_HEAD(&info->capemap_list);
++ mutex_init(&info->capemap_mutex);
++
++ baseboardmaps_node = NULL;
++ capemaps_node = NULL;
++
++ /* find the baseboard */
++ bbrd = &info->baseboard;
++
++ baseboardmaps_node = of_get_child_by_name(pnode, "baseboardmaps");
++ if (baseboardmaps_node == NULL) {
++ dev_err(&pdev->dev, "Failed to get baseboardmaps node");
++ ret = -ENODEV;
++ goto err_exit;
++ }
++
++ /* get eeprom of the baseboard */
++ ret = of_property_read_u32(pnode, "eeprom",
++ &bbrd->eeprom_handle);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to locate baseboard eeprom\n");
++ goto err_exit;
++ }
++ eeprom_node = of_find_node_by_phandle(bbrd->eeprom_handle);
++ if (eeprom_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find baseboard eeprom node\n");
++ ret = -ENODEV;
++ goto err_exit;
++ }
++ bbrd->client = of_find_i2c_device_by_node(eeprom_node);
++ of_node_put(eeprom_node);
++ eeprom_node = NULL;
++ if (bbrd->client == NULL) {
++ dev_err(&pdev->dev, "Failed to find baseboard i2c client\n");
++ ret = -ENODEV;
++ goto err_exit;
++ }
++
++ /* release ref to the node & get ref of the i2c client */
++ i2c_use_client(bbrd->client);
++
++ /* grab the memory accessor of the eeprom */
++ bbrd->macc = i2c_eeprom_get_memory_accessor(bbrd->client);
++ if (IS_ERR_OR_NULL(bbrd->macc)) {
++ dev_err(&pdev->dev, "Failed to get "
++ "baseboard memory accessor\n");
++ ret = bbrd->macc == NULL ? -ENODEV :
++ PTR_ERR(bbrd->macc);
++ bbrd->macc = NULL;
++ goto err_exit;
++ }
++
++ ret = bone_baseboard_scan(bbrd);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to scan baseboard eeprom\n");
++ goto err_exit;
++ }
++
++ dev_info(&pdev->dev, "Baseboard: '%s'\n", bbrd->text_id);
++
++ board_name = NULL;
++ compatible_name = NULL;
++ for_each_child_of_node(baseboardmaps_node, node) {
++ /* there must be board-name */
++ if (of_property_read_string(node, "board-name",
++ &board_name) != 0 ||
++ of_property_read_string(node, "compatible-name",
++ &compatible_name) != 0)
++ continue;
++
++ if (strcmp(bbrd->board_name, board_name) == 0)
++ break;
++ }
++ of_node_put(baseboardmaps_node);
++ baseboardmaps_node = NULL;
++
++ if (node == NULL) {
++ dev_err(&pdev->dev, "Failed to find compatible map for %s\n",
++ bbrd->board_name);
++ ret = -ENODEV;
++ goto err_exit;
++ }
++ bbrd->compatible_name = kstrdup(compatible_name, GFP_KERNEL);
++ if (bbrd->compatible_name == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate compatible name\n");
++ ret = -ENOMEM;
++ goto err_exit;
++ }
++ of_node_put(node);
++
++ dev_info(&pdev->dev, "compatible-baseboard=%s\n",
++ bbrd->compatible_name);
++
++ /* iterate over any capemaps */
++ capemaps_node = of_get_child_by_name(pnode, "capemaps");
++ if (capemaps_node != NULL) {
++
++ for_each_child_of_node(capemaps_node, node) {
++
++ /* there must be part-number */
++ if (of_property_read_string(node, "part-number",
++ &part_number) != 0)
++ continue;
++
++ len = sizeof(*capemap) + strlen(part_number) + 1;
++ capemap = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
++ if (capemap == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate "
++ "capemap\n");
++ ret = -ENOMEM;
++ goto err_exit;
++ }
++ capemap->part_number = (char *)(capemap + 1);
++ capemap->map_node = of_node_get(node);
++ strcpy(capemap->part_number, part_number);
++
++ /* add to the slot list */
++ mutex_lock(&info->capemap_mutex);
++ list_add_tail(&capemap->node, &info->capemap_list);
++ info->capemaps_nr++;
++ mutex_unlock(&info->capemap_mutex);
++ }
++ of_node_put(capemaps_node);
++ capemaps_node = NULL;
++ }
++
++ /* iterate over any slots */
++ slots_node = of_get_child_by_name(pnode, "slots");
++ if (slots_node != NULL) {
++ for_each_child_of_node(slots_node, node) {
++
++ /* check if the override is compatible */
++ if (!bone_is_compatible_override(node,
++ bbrd->compatible_name))
++ continue;
++
++ slot = bone_capemgr_add_slot(info, node,
++ NULL, NULL);
++ if (IS_ERR(slot)) {
++ dev_err(&pdev->dev, "Failed to add slot #%d\n",
++ atomic_read(&info->next_slot_nr));
++ ret = PTR_ERR(slot);
++ goto err_exit;
++ }
++ }
++ of_node_put(slots_node);
++ }
++ slots_node = NULL;
++
++ pm_runtime_enable(&pdev->dev);
++ ret = pm_runtime_get_sync(&pdev->dev);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(&pdev->dev, "Failed to pm_runtime_get_sync()\n");
++ goto err_exit;
++ }
++
++ pm_runtime_put(&pdev->dev);
++
++ bone_capemgr_info_sysfs_register(info);
++
++ /* now load each (take lock to be sure */
++ mutex_lock(&info->slots_list_mutex);
++ list_for_each_entry(slot, &info->slot_list, node) {
++ if (!slot->probe_failed && !slot->loaded) {
++ slot->loading = 1;
++ slot->loader_thread = kthread_run(bone_capemgr_loader,
++ slot, "capemgr-loader-%d",
++ slot->slotno);
++ if (IS_ERR(slot->loader_thread)) {
++ dev_warn(&pdev->dev, "slot #%d: Failed to "
++ "start loader\n", slot->slotno);
++ slot->loader_thread = NULL;
++ }
++ }
++ }
++
++ mutex_unlock(&info->slots_list_mutex);
++
++
++ dev_info(&pdev->dev, "initialized OK.\n");
++
++ return 0;
++
++err_exit:
++ of_node_put(baseboardmaps_node);
++ of_node_put(capemaps_node);
++ platform_set_drvdata(pdev, NULL);
++ devm_kfree(&pdev->dev, info);
++
++ return ret;
++}
++
++static int __devexit bone_capemgr_remove(struct platform_device *pdev)
++{
++ struct bone_capemgr_info *info = platform_get_drvdata(pdev);
++ struct bone_cape_slot *slot, *slotn;
++ int ret;
++
++ mutex_lock(&info->slots_list_mutex);
++ list_for_each_entry_safe(slot, slotn, &info->slot_list, node) {
++
++ /* unload just in case */
++ bone_capemgr_unload(slot);
++
++ /* if probed OK, remove the sysfs nodes */
++ if (slot->probed && !slot->probe_failed)
++ bone_cape_slot_sysfs_unregister(slot);
++
++ /* remove it from the list */
++ list_del(&slot->node);
++
++ }
++ mutex_unlock(&info->slots_list_mutex);
++
++ bone_capemgr_info_sysfs_unregister(info);
++
++ 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);
++
++ devm_kfree(&pdev->dev, info);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++#ifdef CONFIG_PM_RUNTIME
++static int bone_capemgr_runtime_suspend(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capemgr_info *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++
++static int bone_capemgr_runtime_resume(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capemgr_info *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++#endif /* CONFIG_PM_RUNTIME */
++
++static struct dev_pm_ops bone_capemgr_pm_ops = {
++ SET_RUNTIME_PM_OPS(bone_capemgr_runtime_suspend,
++ bone_capemgr_runtime_resume, NULL)
++};
++#define BONE_CAPEMGR_PM_OPS (&bone_capemgr_pm_ops)
++#else
++#define BONE_CAPEMGR_PM_OPS NULL
++#endif /* CONFIG_PM */
++
++static struct platform_driver bone_capemgr_driver = {
++ .probe = bone_capemgr_probe,
++ .remove = __devexit_p(bone_capemgr_remove),
++ .driver = {
++ .name = "bone-capemgr",
++ .owner = THIS_MODULE,
++ .pm = BONE_CAPEMGR_PM_OPS,
++ .of_match_table = of_match_ptr(bone_capemgr_of_match),
++ },
++};
++
++module_platform_driver(bone_capemgr_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone cape manager");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone_capemgr");
diff --git a/patches/linux-3.8.13/0268-capemgr-Add-beaglebone-s-cape-driver-bindings.patch b/patches/linux-3.8.13/0268-capemgr-Add-beaglebone-s-cape-driver-bindings.patch
new file mode 100644
index 0000000..ad38175
--- /dev/null
+++ b/patches/linux-3.8.13/0268-capemgr-Add-beaglebone-s-cape-driver-bindings.patch
@@ -0,0 +1,128 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 7 Jan 2013 19:43:11 +0200
+Subject: [PATCH] capemgr: Add beaglebone's cape driver bindings
+
+Document the beaglebone's cape driver bindings.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ .../devicetree/bindings/misc/capes-beaglebone.txt | 110 ++++++++++++++++++++
+ 1 file changed, 110 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/misc/capes-beaglebone.txt
+
+diff --git a/Documentation/devicetree/bindings/misc/capes-beaglebone.txt b/Documentation/devicetree/bindings/misc/capes-beaglebone.txt
+new file mode 100644
+index 0000000..f73cab5
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/capes-beaglebone.txt
+@@ -0,0 +1,110 @@
++* TI Beaglebone DT Overlay Cape Driver
++
++Required properties:
++
++- compatible: "ti,bone-capemgr"
++
++- eeprom: Contains the phandle beaglebone's baseboard i2c eeprom.
++
++- baseboardmaps - node containing a list of supported
++ beaglebone revisions; each node in should have the
++ following properties:
++ - board-name: The board name stored in the baseboard
++ eeprom.
++ - compatible-name: The name which will be used for
++ matching compatible capes.
++
++- slots: node containing a list of slot nodes (which in the beaglebone
++ case correspond to I2C addresses for dynamically probed capes,
++ or an override slot definition for hardcoded capes.
++ - eeprom: Contains the phandle beaglebone's cape i2c eeprom.
++
++ It is possible to define override slots that will be activated
++ when the baseboard matches, and/or if supplied on the kernel command
++ line and/or when dynamically requested on runtime.
++ In that case the slot is marked with
++ - ti,cape-override: Marks a slot override.
++ - compatible: any of the "runtime", "kernel", or any compatible-name
++ on a matching baseboardmap node.
++ - Any of the eeprom-format-revision, board-name, version, manufacturer,
++ part-number, number-of-pins, serial-number, pin-usage, vdd-3v3exp,
++ vdd-5v, sys-5v, dc-supplied properties which fill in the simulated
++ cape's EEPROM fields. The part-number field is required, the rest
++ are optional taking into default values.
++
++- capemaps: node contains list of cape mappings, which allow converting
++ from a part-number & version tuple to the filename of the dtbo file.
++ - part-number: part number contained in the EEPROM
++ - version node containing a
++ - version: specific version to map to
++ - dtbo: name of the dtbo file
++
++Example:
++bone_capemgr {
++ compatible = "ti,bone-capemgr";
++ status = "okay";
++
++ eeprom = <&baseboard_eeprom>;
++
++ baseboardmaps {
++ baseboard_beaglebone: board@0 {
++ board-name = "A335BONE";
++ compatible-name = "ti,beaglebone";
++ };
++ };
++
++ slots {
++ slot@0 {
++ eeprom = <&cape_eeprom0>;
++ };
++
++ slot@1 {
++ eeprom = <&cape_eeprom1>;
++ };
++
++ slot@2 {
++ eeprom = <&cape_eeprom2>;
++ };
++
++ slot@3 {
++ eeprom = <&cape_eeprom3>;
++ };
++ };
++
++ /* mapping between board names and dtb objects */
++ capemaps {
++ /* Weather cape */
++ cape@0 {
++ part-number = "BB-BONE-WTHR-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-weather-00A0.dtbo";
++ };
++ };
++ };
++};
++
++Example of the override syntax when used on a bone compatible foo board.
++
++{
++ ...
++
++ baseboardmaps {
++ ...
++ baseboard_beaglebone: board@0 {
++ board-name = "A335FOO";
++ compatible-name = "ti,foo";
++ };
++
++ slot@6 {
++ ti,cape-override;
++ compatible = "ti,foo";
++ board-name = "FOO-hardcoded";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONE-FOO-01";
++ };
++ };
++
++};
++
diff --git a/patches/linux-3.8.13/0269-capemgr-am33xx-family-DT-bindings.patch b/patches/linux-3.8.13/0269-capemgr-am33xx-family-DT-bindings.patch
new file mode 100644
index 0000000..1182e83
--- /dev/null
+++ b/patches/linux-3.8.13/0269-capemgr-am33xx-family-DT-bindings.patch
@@ -0,0 +1,125 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:02:12 +0200
+Subject: [PATCH] capemgr: am33xx family DT bindings
+
+A cape loader based on DT overlays and DT objects.
+
+These are the DT bindings.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 101 +++++++++++++++++++++++++++++
+ 1 file changed, 101 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index e43417b..1ddc72d 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -134,6 +134,107 @@
+ };
+ };
+
++ bone_capemgr {
++ compatible = "ti,bone-capemgr";
++ status = "okay";
++
++ eeprom = <&baseboard_eeprom>;
++
++ baseboardmaps {
++ baseboard_beaglebone: board@0 {
++ board-name = "A335BONE";
++ compatible-name = "ti,beaglebone";
++ };
++
++ baseboard_beaglebone_black: board@1 {
++ board-name = "A335BNLT";
++ compatible-name = "ti,beaglebone-black";
++ };
++ };
++
++ slots {
++ slot@0 {
++ eeprom = <&cape_eeprom0>;
++ };
++
++ slot@1 {
++ eeprom = <&cape_eeprom1>;
++ };
++
++ slot@2 {
++ eeprom = <&cape_eeprom2>;
++ };
++
++ slot@3 {
++ eeprom = <&cape_eeprom3>;
++ };
++
++ /* Beaglebone black has it soldered on */
++ // slot@4 {
++ // ti,cape-override;
++ // compatible = "ti,beaglebone-black";
++ // board-name = "Bone-LT-eMMC-2G";
++ // version = "00A0";
++ // manufacturer = "Texas Instruments";
++ // part-number = "BB-BONE-EMMC-2G";
++ // };
++
++ /* geiger cape version A0 without an EEPROM */
++ slot@5 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-Geiger";
++ version = "00A0";
++ manufacturer = "Geiger Inc.";
++ part-number = "BB-BONE-GEIGER";
++ };
++ };
++
++ /* mapping between board names and dtb objects */
++ capemaps {
++ /* DVI cape */
++ cape@0 {
++ /* board-name = "BeagleBone DVI-D CAPE"; */
++ part-number = "BB-BONE-DVID-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-dvi-00A0.dtbo";
++ };
++ version@00A1 {
++ version = "00A1", "01";
++ dtbo = "cape-bone-dvi-00A1.dtbo";
++ };
++ };
++
++ /* beaglebone black emmc on board */
++ cape@1 {
++ /* board-name = "BeagleBone 2G eMMC1 CAPE"; */
++ part-number = "BB-BONE-EMMC-2G";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-2g-emmc1.dtbo";
++ };
++ };
++
++ /* geiger cape */
++ cape@2 {
++ part-number = "BB-BONE-GEIGER";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-geiger-00A0.dtbo";
++ };
++ };
++
++ /* LCD3 cape */
++ cape@3 {
++ part-number = "BB-BONE-LCD3-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-lcd3-00A0.dtbo";
++ };
++ };
++ };
++ };
+ };
+
+ &i2c0 {
diff --git a/patches/linux-3.8.13/0270-bone-geiger-Geiger-bone-driver.patch b/patches/linux-3.8.13/0270-bone-geiger-Geiger-bone-driver.patch
new file mode 100644
index 0000000..af2a4ec
--- /dev/null
+++ b/patches/linux-3.8.13/0270-bone-geiger-Geiger-bone-driver.patch
@@ -0,0 +1,507 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:03:59 +0200
+Subject: [PATCH] bone-geiger: Geiger bone driver.
+
+A driver for the beaglebone geiger cape.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/cape-bone-geiger.c | 489 +++++++++++++++++++++++
+ 1 file changed, 489 insertions(+)
+ create mode 100644 drivers/misc/cape/beaglebone/cape-bone-geiger.c
+
+diff --git a/drivers/misc/cape/beaglebone/cape-bone-geiger.c b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
+new file mode 100644
+index 0000000..1e50594
+--- /dev/null
++++ b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
+@@ -0,0 +1,489 @@
++/*
++ * Driver for beaglebone Geiger cape
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 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 <linux/interrupt.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 <linux/iio/iio.h>
++#include <linux/iio/machine.h>
++#include <linux/iio/consumer.h>
++
++/* fwd decl. */
++struct bone_geiger_info {
++ struct platform_device *pdev;
++ 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-cape-geiger",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bonegeiger_of_match);
++
++static int bonegeiger_start(struct platform_device *pdev)
++{
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++ int duty, period;
++
++ if (info->run != 0)
++ return 0;
++
++ /* checks */
++ if (info->pwm_frequency < 1000 || info->pwm_frequency > 50000) {
++ dev_err(&pdev->dev, "Cowardly refusing to use a "
++ "frequency of %d\n",
++ info->pwm_frequency);
++ return -EINVAL;
++ }
++ if (info->pwm_duty_cycle > 80) {
++ dev_err(&pdev->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(&pdev->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 platform_device *pdev)
++{
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++
++ if (info->run == 0)
++ return 0;
++
++ dev_info(&pdev->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 platform_device *pdev = to_platform_device(dev);
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++
++ 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 platform_device *pdev = to_platform_device(dev);
++ int run, err;
++
++ if (sscanf(buf, "%i", &run) != 1)
++ return -EINVAL;
++
++ if (run)
++ err = bonegeiger_start(pdev);
++ else
++ err = bonegeiger_stop(pdev);
++
++ return err ? err : count;
++}
++
++static ssize_t bonegeiger_show_counter(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++
++ 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 platform_device *pdev = to_platform_device(dev);
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++
++ 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 platform_device *pdev = to_platform_device(dev);
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++ 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 platform_device *pdev)
++{
++ int err;
++
++ err = device_create_file(&pdev->dev, &dev_attr_run);
++ if (err != 0)
++ goto err_no_run;
++
++ err = device_create_file(&pdev->dev, &dev_attr_counter);
++ if (err != 0)
++ goto err_no_counter;
++
++ err = device_create_file(&pdev->dev, &dev_attr_vsense);
++ if (err != 0)
++ goto err_no_vsense;
++
++ return 0;
++
++err_no_vsense:
++ device_remove_file(&pdev->dev, &dev_attr_counter);
++err_no_counter:
++ device_remove_file(&pdev->dev, &dev_attr_run);
++err_no_run:
++ return err;
++}
++
++static void bonegeiger_sysfs_unregister(struct platform_device *pdev)
++{
++ device_remove_file(&pdev->dev, &dev_attr_vsense);
++ device_remove_file(&pdev->dev, &dev_attr_counter);
++ device_remove_file(&pdev->dev, &dev_attr_run);
++}
++
++static irqreturn_t bonegeiger_irq_handler(int irq, void *dev_id)
++{
++ struct platform_device *pdev = dev_id;
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++
++ 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 platform_device *pdev)
++{
++ struct bone_geiger_info *info;
++ struct pinctrl *pinctrl;
++ struct device_node *pnode = pdev->dev.of_node;
++ phandle phandle;
++ u32 val;
++ int err;
++
++ /* we only support OF */
++ if (pnode == NULL) {
++ dev_err(&pdev->dev, "No platform of_node!\n");
++ return -ENODEV;
++ }
++
++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate info\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ platform_set_drvdata(pdev, info);
++ info->pdev = pdev;
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ err = of_property_read_u32(pnode, "pwms", &val);
++ if (err != 0) {
++ dev_err(&pdev->dev, "unable to read pwm handle\n");
++ goto err_no_pwm;
++ }
++ phandle = val;
++
++ info->pwm_dev = of_pwm_request(pnode, NULL);
++ if (IS_ERR(info->pwm_dev)) {
++ dev_err(&pdev->dev, "unable to request PWM\n");
++ err = PTR_ERR(info->pwm_dev);
++ goto err_no_pwm;
++ }
++
++ if (of_property_read_u32(pnode, "pwm-frequency", &val) != 0) {
++ val = 20000;
++ dev_warn(&pdev->dev, "Could not read pwm-frequency property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_frequency = val;
++
++ if (of_property_read_u32(pnode, "pwm-duty-cycle", &val) != 0) {
++ val = 60;
++ dev_warn(&pdev->dev, "Could not read pwm-duty-cycle property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_duty_cycle = val;
++
++ info->event_gpio = of_get_gpio_flags(pnode, 0, NULL);
++ if (IS_ERR_VALUE(info->event_gpio)) {
++ dev_err(&pdev->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(&pdev->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(&pdev->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", pdev);
++ if (err != 0) {
++ dev_err(&pdev->dev, "unable to request irq\n");
++ goto err_no_irq;
++ }
++
++ err = bonegeiger_sysfs_register(pdev);
++ if (err != 0) {
++ dev_err(&pdev->dev, "unable to register sysfs\n");
++ goto err_no_sysfs;
++ }
++
++ info->counter_sd = sysfs_get_dirent(pdev->dev.kobj.sd, NULL, "counter");
++ if (info->counter_sd == NULL) {
++ dev_err(&pdev->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);
++
++ led_trigger_event(info->run_led, LED_OFF);
++
++ /* default */
++ if (of_property_read_u32(pnode, "event-blink-delay", &val) != 0) {
++ val = 30;
++ dev_warn(&pdev->dev, "Could not read event-blink-delay "
++ "property; using default %u\n",
++ val);
++ }
++ info->event_blink_delay = val;
++
++ /* default */
++ if (of_property_read_string(pnode, "vsense-name", &info->vsense_name) != 0) {
++ info->vsense_name = "AIN5";
++ dev_warn(&pdev->dev, "Could not read vsense-name property; "
++ "using default '%s'\n",
++ info->vsense_name);
++ }
++
++ if (of_property_read_u32(pnode, "vsense-scale", &info->vsense_scale) != 0) {
++ info->vsense_scale = 37325; /* 373.25 */
++ dev_warn(&pdev->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(&pdev->dev, "Could not get AIN5 analog input\n");
++ err = PTR_ERR(info->vsense_channel);
++ goto err_no_vsense;
++ }
++
++ dev_info(&pdev->dev, "ready\n");
++
++ err = bonegeiger_start(pdev);
++ if (err != 0) {
++ dev_err(&pdev->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:
++ 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(pdev);
++err_no_sysfs:
++ free_irq(info->event_irq, pdev);
++err_no_irq:
++ gpio_free(info->event_gpio);
++err_no_gpio:
++ pwm_put(info->pwm_dev);
++err_no_pwm:
++ devm_kfree(&pdev->dev, info);
++err_no_mem:
++ return err;
++}
++
++static int bonegeiger_remove(struct platform_device *pdev)
++{
++ struct bone_geiger_info *info = platform_get_drvdata(pdev);
++
++ dev_info(&pdev->dev, "Removing geiger cape driver...\n");
++
++ bonegeiger_stop(pdev);
++
++ iio_channel_release(info->vsense_channel);
++ led_trigger_unregister_simple(info->run_led);
++ led_trigger_unregister_simple(info->event_led);
++ sysfs_put(info->counter_sd);
++ bonegeiger_sysfs_unregister(pdev);
++ free_irq(info->event_irq, pdev);
++ gpio_free(info->event_gpio);
++ pwm_put(info->pwm_dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++#ifdef CONFIG_PM_RUNTIME
++static int bonegeiger_runtime_suspend(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bonegeiger_info *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++
++static int bonegeiger_runtime_resume(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bonegeiger_info *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++#endif /* CONFIG_PM_RUNTIME */
++
++static struct dev_pm_ops bonegeiger_pm_ops = {
++ SET_RUNTIME_PM_OPS(bonegeiger_runtime_suspend,
++ bonegeiger_runtime_resume, NULL)
++};
++#define BONEGEIGER_PM_OPS (&bonegeiger_pm_ops)
++#else
++#define BONEGEIGER_PM_OPS NULL
++#endif /* CONFIG_PM */
++
++struct platform_driver bonegeiger_driver = {
++ .probe = bonegeiger_probe,
++ .remove = bonegeiger_remove,
++ .driver = {
++ .name = "bone-cape-geiger",
++ .owner = THIS_MODULE,
++ .pm = BONEGEIGER_PM_OPS,
++ .of_match_table = bonegeiger_of_match,
++ },
++};
++
++module_platform_driver(bonegeiger_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone geiger cape");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-cape-geiger");
diff --git a/patches/linux-3.8.13/0271-capemgr-firmware-makefiles-for-DT-objects.patch b/patches/linux-3.8.13/0271-capemgr-firmware-makefiles-for-DT-objects.patch
new file mode 100644
index 0000000..9c93d29
--- /dev/null
+++ b/patches/linux-3.8.13/0271-capemgr-firmware-makefiles-for-DT-objects.patch
@@ -0,0 +1,53 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:05:28 +0200
+Subject: [PATCH] capemgr: firmware makefiles for DT objects
+
+Makefile changes to support the DT cape definitions.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index cbb09ce..f47024c 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -136,6 +136,16 @@ fw-shipped-$(CONFIG_USB_VICAM) += vicam/firmware.fw
+ fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin
+ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+
++# all the generic capes
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ capes/cape-bone-2g-emmc1.dtbo \
++ capes/cape-bone-dvi-00A0.dtbo capes/cape-bone-dvi-00A1.dtbo \
++ capes/cape-bone-lcd3-00A0.dtbo
++
++# the geiger cape
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
++ capes/cape-bone-geiger-00A0.dtbo
++
+ fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+
+ # Directories which we _might_ need to create, so we have a rule for them.
+@@ -147,6 +157,9 @@ quiet_cmd_mkdir = MKDIR $(patsubst $(objtree)/%,%,$@)
+ quiet_cmd_ihex = IHEX $@
+ cmd_ihex = $(OBJCOPY) -Iihex -Obinary $< $@
+
++quiet_cmd_dtco = DTCO $@
++ cmd_dtco = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -@ $<
++
+ quiet_cmd_ihex2fw = IHEX2FW $@
+ cmd_ihex2fw = $(objtree)/$(obj)/ihex2fw $< $@
+
+@@ -233,6 +246,10 @@ $(obj)/%.fw: $(obj)/%.HEX $(ihex2fw_dep) | $(objtree)/$(obj)/$$(dir %)
+ $(obj)/%.fw: $(obj)/%.H16 $(ihex2fw_dep) | $(objtree)/$(obj)/$$(dir %)
+ $(call cmd,h16tofw)
+
++# DTBO is device tree blob object
++$(obj)/%.dtbo: $(obj)/%.dts | $(objtree)/$(obj)/$$(dir %)
++ $(call cmd,dtco)
++
+ $(firmware-dirs):
+ $(call cmd,mkdir)
+
diff --git a/patches/linux-3.8.13/0272-capemgr-emmc2-cape-definition.patch b/patches/linux-3.8.13/0272-capemgr-emmc2-cape-definition.patch
new file mode 100644
index 0000000..e6e8183
--- /dev/null
+++ b/patches/linux-3.8.13/0272-capemgr-emmc2-cape-definition.patch
@@ -0,0 +1,71 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:07:18 +0200
+Subject: [PATCH] capemgr: emmc2 cape definition.
+
+Definition for a virtual eMMC cape.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-2g-emmc1.dts | 53 +++++++++++++++++++++++++++++++++
+ 1 file changed, 53 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-2g-emmc1.dts
+
+diff --git a/firmware/capes/cape-bone-2g-emmc1.dts b/firmware/capes/cape-bone-2g-emmc1.dts
+new file mode 100644
+index 0000000..c81a986
+--- /dev/null
++++ b/firmware/capes/cape-bone-2g-emmc1.dts
+@@ -0,0 +1,53 @@
++/*
++* 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone-black";
++ ti,on-baseboard;
++
++ /* identification */
++ part-number = "*"; /* any part number */
++ version = "*"; /* any version */
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ emmc2_pins: pinmux_emmc2_pins {
++ pinctrl-single,pins = <
++ 0x80 0x32 /* gpmc_csn1.mmc1_clk, INPUT_PULLUP | MODE2 */
++ 0x84 0x32 /* gpmc_csn1.mmc1_cmd, INPUT_PULLUP | MODE2 */
++ 0x00 0x31 /* gpmc_ad0.mmc1_dat0, INPUT_PULLUP | MODE1 */
++ 0x04 0x31 /* gpmc_ad1.mmc1_dat1, INPUT_PULLUP | MODE1 */
++ 0x08 0x31 /* gpmc_ad2.mmc1_dat2, INPUT_PULLUP | MODE1 */
++ 0x0c 0x31 /* gpmc_ad3.mmc1_dat3, INPUT_PULLUP | MODE1 */
++ 0x10 0x31 /* gpmc_ad4.mmc1_dat4, INPUT_PULLUP | MODE1 */
++ 0x14 0x31 /* gpmc_ad5.mmc1_dat5, INPUT_PULLUP | MODE1 */
++ 0x18 0x31 /* gpmc_ad6.mmc1_dat6, INPUT_PULLUP | MODE1 */
++ 0x1c 0x31 /* gpmc_ad7.mmc1_dat7, INPUT_PULLUP | MODE1 */
++
++ /* the reset */
++ 0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */
++ >;
++ };
++ };
++ };
++ fragment@1 {
++ target = <&mmc2>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&emmc2_pins>; /* wrong numbering */
++ vmmc-supply = <&ldo3_reg>;
++ bus-width = <4>;
++ ti,non-removable;
++ status = "okay";
++ reset-gpios = <&gpio2 20 1>; /* active low */
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0273-capemgr-DVI-capes-definitions.patch b/patches/linux-3.8.13/0273-capemgr-DVI-capes-definitions.patch
new file mode 100644
index 0000000..7e40c66
--- /dev/null
+++ b/patches/linux-3.8.13/0273-capemgr-DVI-capes-definitions.patch
@@ -0,0 +1,216 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:08:16 +0200
+Subject: [PATCH] capemgr: DVI capes definitions
+
+Definitions for the beaglebone DVI capes.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-dvi-00A0.dts | 95 +++++++++++++++++++++++++++++++++
+ firmware/capes/cape-bone-dvi-00A1.dts | 95 +++++++++++++++++++++++++++++++++
+ 2 files changed, 190 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-dvi-00A0.dts
+ create mode 100644 firmware/capes/cape-bone-dvi-00A1.dts
+
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+new file mode 100644
+index 0000000..b9db80b
+--- /dev/null
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -0,0 +1,95 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-DVID-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ 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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++
++ gpio-leds-cape-dvi {
++ 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";
++ };
++ };
++
++ dvi-cape {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
++ powerdn-gpio = <&gpio2 7 0>;
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+new file mode 100644
+index 0000000..567d12b
+--- /dev/null
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -0,0 +1,95 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-DVID-01";
++ version = "00A1", "01";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ 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_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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++
++ gpio-leds-cape-dvi {
++ 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";
++ };
++ };
++
++ dvi-cape {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
++ powerdn-gpio = <&gpio2 31 0>;
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0274-capemgr-Geiger-cape-definition.patch b/patches/linux-3.8.13/0274-capemgr-Geiger-cape-definition.patch
new file mode 100644
index 0000000..e20c3ac
--- /dev/null
+++ b/patches/linux-3.8.13/0274-capemgr-Geiger-cape-definition.patch
@@ -0,0 +1,116 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:09:01 +0200
+Subject: [PATCH] capemgr: Geiger cape definition
+
+Geiger Cape definition
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-geiger-00A0.dts | 98 ++++++++++++++++++++++++++++++
+ 1 file changed, 98 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-geiger-00A0.dts
+
+diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
+new file mode 100644
+index 0000000..4003161
+--- /dev/null
++++ b/firmware/capes/cape-bone-geiger-00A0.dts
+@@ -0,0 +1,98 @@
++/*
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-GEIGER";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ 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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++
++ gpio-leds-cape-geiger {
++ 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";
++ };
++
++ };
++
++ tscadc-cape-geiger {
++ compatible = "ti-tscadc-dt";
++ adc-channels = <0 1 2 3 4 5 6 7>;
++ };
++
++ bone-cape-geiger {
++ compatible = "bone-cape-geiger";
++ status = "okay";
++
++ 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 */
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0275-capemgr-LCD3-cape-definition.patch b/patches/linux-3.8.13/0275-capemgr-LCD3-cape-definition.patch
new file mode 100644
index 0000000..0b79e1c
--- /dev/null
+++ b/patches/linux-3.8.13/0275-capemgr-LCD3-cape-definition.patch
@@ -0,0 +1,196 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 28 Dec 2012 21:09:48 +0200
+Subject: [PATCH] capemgr: LCD3 cape definition
+
+Definition for the beaglebone LCD3 cape.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-lcd3-00A0.dts | 178 ++++++++++++++++++++++++++++++++
+ 1 file changed, 178 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-lcd3-00A0.dts
+
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+new file mode 100644
+index 0000000..0a3079e
+--- /dev/null
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -0,0 +1,178 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-LCD3-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ 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 */
++ >;
++ };
++
++ };
++ };
++
++ fragment@1 {
++ target = <&tps>;
++ __overlay__ {
++ backlight {
++ compatible = "tps65217-backlight";
++ isel = <1>;
++ fdim = <200>;
++ brightness = <100>;
++ tps = <&tps>;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ tsc-wires = <4>;
++ tsc-x-plate-resistance = <200>;
++ tsc-steps = <6>;
++
++ adc-channels = <4>;
++ };
++
++ gpio-leds-cape-lcd3 {
++ 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;
++ };
++ };
++
++ lcd3-cape {
++ compatible = "da8xx-dt";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++
++ ti,hwmods = "lcdc";
++
++ disp-pll = <16000000>;
++ panel-type = "CDTech_S035Q01";
++
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0276-capemgr-Add-weather-cape-definition.patch b/patches/linux-3.8.13/0276-capemgr-Add-weather-cape-definition.patch
new file mode 100644
index 0000000..90204c0
--- /dev/null
+++ b/patches/linux-3.8.13/0276-capemgr-Add-weather-cape-definition.patch
@@ -0,0 +1,122 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 7 Jan 2013 18:42:24 +0200
+Subject: [PATCH] capemgr: Add weather cape definition
+
+Circuit-co's weather cape definition.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 9 ++++
+ firmware/Makefile | 3 ++
+ firmware/capes/cape-bone-weather-00A0.dts | 68 +++++++++++++++++++++++++++++
+ 3 files changed, 80 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-weather-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 1ddc72d..b184224 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -233,6 +233,15 @@
+ dtbo = "cape-bone-lcd3-00A0.dtbo";
+ };
+ };
++
++ /* Weather cape */
++ cape@4 {
++ part-number = "BB-BONE-WTHR-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-weather-00A0.dtbo";
++ };
++ };
+ };
+ };
+ };
+diff --git a/firmware/Makefile b/firmware/Makefile
+index f47024c..25ea3fb 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -146,6 +146,9 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+ capes/cape-bone-geiger-00A0.dtbo
+
++# the weather cape
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += capes/cape-bone-weather-00A0.dtbo
++
+ fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+
+ # Directories which we _might_ need to create, so we have a rule for them.
+diff --git a/firmware/capes/cape-bone-weather-00A0.dts b/firmware/capes/cape-bone-weather-00A0.dts
+new file mode 100644
+index 0000000..76284d6
+--- /dev/null
++++ b/firmware/capes/cape-bone-weather-00A0.dts
+@@ -0,0 +1,68 @@
++/*
++* 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++ part-number = "BB-BONE-WTHR-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ 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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c2>;
++
++ __overlay__ {
++ /* needed to avoid gripping by DTC */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* 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>;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++ onewire@0 {
++ compatible = "w1-gpio";
++ pinctrl-names = "default";
++ pinctrl-0 = <&weather_cape_w1_pins>;
++ status = "okay";
++
++ gpios = <&gpio2 3 0>;
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0277-ehrpwm-add-missing-dts-nodes.patch b/patches/linux-3.8.13/0277-ehrpwm-add-missing-dts-nodes.patch
new file mode 100644
index 0000000..05677e3
--- /dev/null
+++ b/patches/linux-3.8.13/0277-ehrpwm-add-missing-dts-nodes.patch
@@ -0,0 +1,49 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 4 Jan 2013 10:51:47 +0200
+Subject: [PATCH] ehrpwm: add missing dts nodes
+
+---
+ arch/arm/boot/dts/am33xx.dtsi | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 5218fbe..662ff27 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -407,6 +407,36 @@
+ ti,timer-pwm;
+ };
+
++ ehrpwm0: ehrpwm@48300200 {
++ compatible = "ti,am33xx-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,am33xx-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,am33xx-ehrpwm";
++ reg = <0x48304200 0x100 0x48304000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <39 60>;
++ ti,hwmods = "ehrpwm2";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
+ rtc@44e3e000 {
+ compatible = "ti,da830-rtc";
+ reg = <0x44e3e000 0x1000>;
diff --git a/patches/linux-3.8.13/0278-am33xx-DT-Update-am33xx.dsi-with-the-new-PWM-DT-bind.patch b/patches/linux-3.8.13/0278-am33xx-DT-Update-am33xx.dsi-with-the-new-PWM-DT-bind.patch
new file mode 100644
index 0000000..240dfee
--- /dev/null
+++ b/patches/linux-3.8.13/0278-am33xx-DT-Update-am33xx.dsi-with-the-new-PWM-DT-bind.patch
@@ -0,0 +1,140 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 4 Jan 2013 11:51:06 +0200
+Subject: [PATCH] am33xx DT: Update am33xx.dsi with the new PWM DT bindings
+
+Use the new bindings for the PWM subsystem.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 118 +++++++++++++++++++++++++++++++----------
+ 1 file changed, 89 insertions(+), 29 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 662ff27..c9eee93 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -407,35 +407,95 @@
+ ti,timer-pwm;
+ };
+
+- ehrpwm0: ehrpwm@48300200 {
+- compatible = "ti,am33xx-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,am33xx-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,am33xx-ehrpwm";
+- reg = <0x48304200 0x100 0x48304000 0x10>;
+- interrupt-parent = <&intc>;
+- interrupt = <39 60>;
+- ti,hwmods = "ehrpwm2";
+- #pwm-cells = <3>;
+- status = "disabled";
+- };
++ epwmss0: epwmss@48300000 {
++ compatible = "ti,am33xx-pwmss";
++ reg = <0x48300000 0x10
++ 0x48300100 0x80
++ 0x48300180 0x80
++ 0x48300200 0x80>;
++ ti,hwmods = "epwmss0";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ status = "disabled";
++ ranges;
++
++ ecap0: ecap@48300100 {
++ compatible = "ti,am33xx-ecap";
++ #pwm-cells = <3>;
++ reg = <0x48300100 0x80>;
++ ti,hwmods = "ecap0";
++ status = "disabled";
++ };
++
++ ehrpwm0: ehrpwm@48300200 {
++ compatible = "ti,am33xx-ehrpwm";
++ #pwm-cells = <3>;
++ reg = <0x48300200 0x80>;
++ ti,hwmods = "ehrpwm0";
++ status = "disabled";
++ tbclkgating;
++ };
++ };
++
++ epwmss1: epwmss@48302000 {
++ compatible = "ti,am33xx-pwmss";
++ reg = <0x48302000 0x10
++ 0x48302100 0x80
++ 0x48302180 0x80
++ 0x48302200 0x80>;
++ ti,hwmods = "epwmss1";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ status = "disabled";
++ ranges;
++
++ ecap1: ecap@48302100 {
++ compatible = "ti,am33xx-ecap";
++ #pwm-cells = <3>;
++ reg = <0x48302100 0x80>;
++ ti,hwmods = "ecap1";
++ status = "disabled";
++ };
++
++ ehrpwm1: ehrpwm@48302200 {
++ compatible = "ti,am33xx-ehrpwm";
++ #pwm-cells = <3>;
++ reg = <0x48302200 0x80>;
++ ti,hwmods = "ehrpwm1";
++ status = "disabled";
++ tbclkgating;
++ };
++ };
++
++ epwmss2: epwmss@48304000 {
++ compatible = "ti,am33xx-pwmss";
++ reg = <0x48304000 0x10
++ 0x48304100 0x80
++ 0x48304180 0x80
++ 0x48304200 0x80>;
++ ti,hwmods = "epwmss2";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ status = "disabled";
++ ranges;
++
++ ecap2: ecap@48304100 {
++ compatible = "ti,am33xx-ecap";
++ #pwm-cells = <3>;
++ reg = <0x48304100 0x80>;
++ ti,hwmods = "ecap2";
++ status = "disabled";
++ };
++
++ ehrpwm2: ehrpwm@48304200 {
++ compatible = "ti,am33xx-ehrpwm";
++ #pwm-cells = <3>;
++ reg = <0x48304200 0x80>;
++ ti,hwmods = "ehrpwm2";
++ status = "disabled";
++ tbclkgating;
++ };
++ };
+
+ rtc@44e3e000 {
+ compatible = "ti,da830-rtc";
diff --git a/patches/linux-3.8.13/0279-geiger-cape-Update-to-using-the-new-PWM-interface.patch b/patches/linux-3.8.13/0279-geiger-cape-Update-to-using-the-new-PWM-interface.patch
new file mode 100644
index 0000000..7eb22c7
--- /dev/null
+++ b/patches/linux-3.8.13/0279-geiger-cape-Update-to-using-the-new-PWM-interface.patch
@@ -0,0 +1,38 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 8 Jan 2013 21:05:27 +0200
+Subject: [PATCH] geiger-cape: Update to using the new PWM interface.
+
+The DT PWM interface has changed; update.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-geiger-00A0.dts | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
+index 4003161..67ec568 100644
+--- a/firmware/capes/cape-bone-geiger-00A0.dts
++++ b/firmware/capes/cape-bone-geiger-00A0.dts
+@@ -36,6 +36,13 @@
+ };
+ };
+
++ fragment@2 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
+ fragment@1 {
+ target = <&ehrpwm1>;
+ __overlay__ {
+@@ -43,7 +50,7 @@
+ };
+ };
+
+- fragment@2 {
++ fragment@3 {
+ target = <&ocp>;
+ __overlay__ {
+
diff --git a/patches/linux-3.8.13/0280-lcd3-cape-Change-into-using-the-lcdc-DRM-driver-inst.patch b/patches/linux-3.8.13/0280-lcd3-cape-Change-into-using-the-lcdc-DRM-driver-inst.patch
new file mode 100644
index 0000000..5fb1f33
--- /dev/null
+++ b/patches/linux-3.8.13/0280-lcd3-cape-Change-into-using-the-lcdc-DRM-driver-inst.patch
@@ -0,0 +1,102 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 8 Jan 2013 20:53:56 +0200
+Subject: [PATCH] lcd3-cape: Change into using the lcdc DRM driver instead of
+ da8xx-fb
+
+Use the new DRM driver instead of the da8xx-fb driver.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-lcd3-00A0.dts | 65 ++++++++++++++++++++++++++++----
+ 1 file changed, 58 insertions(+), 7 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index 0a3079e..83a6d88 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -79,8 +79,13 @@
+
+ fragment@2 {
+ target = <&ocp>;
++
+ __overlay__ {
+
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
+ tscadc {
+ compatible = "ti-tscadc-dt";
+
+@@ -161,18 +166,64 @@
+ };
+ };
+
+- lcd3-cape {
+- compatible = "da8xx-dt";
+-
++// lcd3-cape {
++// compatible = "da8xx-dt";
++//
++// pinctrl-names = "default";
++// pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++//
++// ti,hwmods = "lcdc";
++//
++// disp-pll = <16000000>;
++// panel-type = "CDTech_S035Q01";
++//
++// };
++
++ /* Settings for CDTech_S035Q01 / LCD3 cape: */
++ panel {
++ compatible = "lcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ invert-line-clock = <1>;
++ invert-frm-clock = <1>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 320x240 {
++ hactive = <320>;
++ vactive = <240>;
++ hback-porch = <21>;
++ hfront-porch = <58>;
++ hsync-len = <47>;
++ vback-porch = <11>;
++ vfront-porch = <23>;
++ vsync-len = <2>;
++ clock-frequency = <8000000>;
++ };
++ };
++ };
+
++ fb {
++ compatible = "ti,am33xx-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
+ ti,hwmods = "lcdc";
+-
+- disp-pll = <16000000>;
+- panel-type = "CDTech_S035Q01";
+-
+ };
++
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0281-am33xx-Add-default-config.patch b/patches/linux-3.8.13/0281-am33xx-Add-default-config.patch
new file mode 100644
index 0000000..6fc4763
--- /dev/null
+++ b/patches/linux-3.8.13/0281-am33xx-Add-default-config.patch
@@ -0,0 +1,621 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 8 Jan 2013 21:15:34 +0200
+Subject: [PATCH] am33xx: Add default config.
+
+---
+ defconfig | 209 ++++++++++++++++++++++++++-----------------------------------
+ 1 file changed, 90 insertions(+), 119 deletions(-)
+
+diff --git a/defconfig b/defconfig
+index 5eb94b7..0817f18 100644
+--- a/defconfig
++++ b/defconfig
+@@ -1,6 +1,6 @@
+ #
+ # Automatically generated file; DO NOT EDIT.
+-# Linux/arm 3.8.0-rc1 Kernel Configuration
++# Linux/arm 3.8.0-rc2 Kernel Configuration
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+@@ -240,12 +240,7 @@ CONFIG_DEFAULT_CFQ=y
+ 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_UNINLINE_SPIN_UNLOCK=y
+ CONFIG_FREEZER=y
+
+ #
+@@ -343,6 +338,9 @@ CONFIG_OMAP_PACKAGE_CBS=y
+ #
+ # OMAP Board Type
+ #
++CONFIG_MACH_AM335XEVM=y
++CONFIG_MACH_AM335XIAEVM=y
++CONFIG_MACH_TAM335X=y
+ CONFIG_MACH_OMAP3_BEAGLE=y
+ # CONFIG_MACH_DEVKIT8000 is not set
+ # CONFIG_MACH_OMAP_LDP is not set
+@@ -474,7 +472,7 @@ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ CONFIG_HAVE_MEMBLOCK=y
+ CONFIG_PAGEFLAGS_EXTENDED=y
+-CONFIG_SPLIT_PTLOCK_CPUS=4
++CONFIG_SPLIT_PTLOCK_CPUS=999999
+ # CONFIG_COMPACTION is not set
+ # CONFIG_PHYS_ADDR_T_64BIT is not set
+ CONFIG_ZONE_DMA_FLAG=0
+@@ -519,6 +517,7 @@ CONFIG_CMDLINE=""
+ #
+ CONFIG_CPU_FREQ=y
+ CONFIG_CPU_FREQ_TABLE=y
++CONFIG_CPU_FREQ_GOV_COMMON=y
+ CONFIG_CPU_FREQ_STAT=y
+ CONFIG_CPU_FREQ_STAT_DETAILS=y
+ CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+@@ -541,7 +540,7 @@ CONFIG_GENERIC_CPUFREQ_CPU0=y
+ # CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
+ # CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
+ CONFIG_CPU_IDLE=y
+-CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
++# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
+ CONFIG_CPU_IDLE_GOV_LADDER=y
+ CONFIG_CPU_IDLE_GOV_MENU=y
+ CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y
+@@ -683,7 +682,7 @@ CONFIG_IPV6_SUBTREES=y
+ CONFIG_IPV6_MROUTE=y
+ CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+ CONFIG_IPV6_PIMSM_V2=y
+-CONFIG_NETLABEL=y
++# CONFIG_NETLABEL is not set
+ # CONFIG_NETWORK_SECMARK is not set
+ # CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+ CONFIG_NETFILTER=y
+@@ -912,7 +911,7 @@ CONFIG_NET_SCH_FIFO=y
+ CONFIG_DNS_RESOLVER=y
+ CONFIG_BATMAN_ADV=m
+ CONFIG_BATMAN_ADV_BLA=y
+-CONFIG_BATMAN_ADV_DAT=y
++# CONFIG_BATMAN_ADV_DAT is not set
+ # CONFIG_BATMAN_ADV_DEBUG is not set
+ CONFIG_OPENVSWITCH=m
+ CONFIG_RPS=y
+@@ -943,7 +942,7 @@ CONFIG_CAN_DEV=m
+ CONFIG_CAN_CALC_BITTIMING=y
+ CONFIG_CAN_TI_HECC=m
+ CONFIG_CAN_MCP251X=m
+-CONFIG_CAN_GRCAN=m
++# CONFIG_CAN_GRCAN is not set
+ # CONFIG_CAN_SJA1000 is not set
+ CONFIG_CAN_C_CAN=m
+ CONFIG_CAN_C_CAN_PLATFORM=m
+@@ -954,7 +953,7 @@ CONFIG_CAN_C_CAN_PLATFORM=m
+ #
+ CONFIG_CAN_EMS_USB=m
+ CONFIG_CAN_ESD_USB2=m
+-CONFIG_CAN_KVASER_USB=m
++# CONFIG_CAN_KVASER_USB is not set
+ CONFIG_CAN_PEAK_USB=m
+ # CONFIG_CAN_SOFTING is not set
+ # CONFIG_CAN_DEBUG_DEVICES is not set
+@@ -1245,6 +1244,7 @@ CONFIG_PROC_DEVICETREE=y
+ # CONFIG_OF_SELFTEST is not set
+ CONFIG_OF_FLATTREE=y
+ CONFIG_OF_EARLY_FLATTREE=y
++CONFIG_OF_DYNAMIC=y
+ CONFIG_OF_ADDRESS=y
+ CONFIG_OF_IRQ=y
+ CONFIG_OF_DEVICE=y
+@@ -1252,6 +1252,9 @@ CONFIG_OF_I2C=y
+ CONFIG_OF_NET=y
+ CONFIG_OF_MDIO=y
+ CONFIG_OF_MTD=y
++CONFIG_OF_DISPLAY_TIMINGS=y
++CONFIG_OF_RESOLVE=y
++CONFIG_OF_OVERLAY=y
+ # CONFIG_PARPORT is not set
+ CONFIG_BLK_DEV=y
+ # CONFIG_BLK_DEV_COW_COMMON is not set
+@@ -1316,6 +1319,8 @@ CONFIG_TI_ST=m
+ # Altera FPGA firmware download module
+ #
+ # CONFIG_ALTERA_STAPL is not set
++CONFIG_CAPE_BEAGLEBONE=y
++CONFIG_CAPE_BEAGLEBONE_GEIGER=y
+
+ #
+ # SCSI device support
+@@ -1410,9 +1415,9 @@ CONFIG_NET_VENDOR_FARADAY=y
+ CONFIG_NET_VENDOR_INTEL=y
+ CONFIG_NET_VENDOR_I825XX=y
+ CONFIG_NET_VENDOR_MARVELL=y
+-CONFIG_MVMDIO=m
++# CONFIG_MVMDIO is not set
+ CONFIG_NET_VENDOR_MICREL=y
+-CONFIG_KS8842=m
++# CONFIG_KS8842 is not set
+ CONFIG_KS8851=y
+ CONFIG_KS8851_MLL=y
+ CONFIG_NET_VENDOR_MICROCHIP=y
+@@ -1493,7 +1498,7 @@ 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_CDC_MBIM=y
++# CONFIG_USB_NET_CDC_MBIM is not set
+ # CONFIG_USB_NET_DM9601 is not set
+ # CONFIG_USB_NET_SMSC75XX is not set
+ CONFIG_USB_NET_SMSC95XX=y
+@@ -1526,13 +1531,7 @@ CONFIG_WLAN=y
+ # CONFIG_USB_NET_RNDIS_WLAN is not set
+ # CONFIG_RTL8187 is not set
+ # CONFIG_MAC80211_HWSIM is not set
+-CONFIG_ATH_CARDS=m
+-# CONFIG_ATH_DEBUG is not set
+-# CONFIG_ATH9K is not set
+-# CONFIG_ATH9K_HTC is not set
+-# CONFIG_CARL9170 is not set
+-# CONFIG_ATH6KL is not set
+-# CONFIG_AR5523 is not set
++# CONFIG_ATH_CARDS is not set
+ # CONFIG_B43 is not set
+ # CONFIG_B43LEGACY is not set
+ # CONFIG_BRCMFMAC is not set
+@@ -1546,16 +1545,7 @@ CONFIG_LIBERTAS_DEBUG=y
+ # CONFIG_P54_COMMON is not set
+ # CONFIG_RT2X00 is not set
+ # CONFIG_RTL8192CU is not set
+-CONFIG_WL_TI=y
+-CONFIG_WL1251=m
+-CONFIG_WL1251_SPI=m
+-CONFIG_WL1251_SDIO=m
+-CONFIG_WL12XX=m
+-CONFIG_WL18XX=m
+-CONFIG_WLCORE=m
+-CONFIG_WLCORE_SPI=m
+-CONFIG_WLCORE_SDIO=m
+-CONFIG_WL12XX_PLATFORM_DATA=y
++# CONFIG_WL_TI is not set
+ # CONFIG_ZD1211RW is not set
+ # CONFIG_MWIFIEX is not set
+
+@@ -1670,7 +1660,7 @@ CONFIG_TOUCHSCREEN_WM9713=y
+ # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+ # CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+ # CONFIG_TOUCHSCREEN_TSC2005 is not set
+-CONFIG_TOUCHSCREEN_TSC2007=m
++# CONFIG_TOUCHSCREEN_TSC2007 is not set
+ # CONFIG_TOUCHSCREEN_W90X900 is not set
+ # CONFIG_TOUCHSCREEN_ST1232 is not set
+ # CONFIG_TOUCHSCREEN_TPS6507X is not set
+@@ -1691,7 +1681,7 @@ 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_PWM_BEEPER=m
++# CONFIG_INPUT_PWM_BEEPER is not set
+ # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+ # CONFIG_INPUT_ADXL34X is not set
+ # CONFIG_INPUT_CMA3000 is not set
+@@ -1838,15 +1828,7 @@ CONFIG_SPI_SPIDEV=y
+ #
+ # PPS support
+ #
+-CONFIG_PPS=y
+-# CONFIG_PPS_DEBUG is not set
+-
+-#
+-# PPS clients support
+-#
+-# CONFIG_PPS_CLIENT_KTIMER is not set
+-# CONFIG_PPS_CLIENT_LDISC is not set
+-# CONFIG_PPS_CLIENT_GPIO is not set
++# CONFIG_PPS is not set
+
+ #
+ # PPS generators support
+@@ -1855,7 +1837,7 @@ CONFIG_PPS=y
+ #
+ # PTP clock support
+ #
+-CONFIG_PTP_1588_CLOCK=y
++# CONFIG_PTP_1588_CLOCK is not set
+
+ #
+ # Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+@@ -1966,7 +1948,7 @@ CONFIG_GENERIC_ADC_BATTERY=m
+ # CONFIG_CHARGER_LP8727 is not set
+ CONFIG_CHARGER_GPIO=m
+ # CONFIG_CHARGER_MANAGER is not set
+-CONFIG_CHARGER_BQ2415X=m
++# CONFIG_CHARGER_BQ2415X is not set
+ # CONFIG_CHARGER_SMB347 is not set
+ # CONFIG_POWER_RESET is not set
+ # CONFIG_POWER_AVS is not set
+@@ -2077,9 +2059,9 @@ CONFIG_THERMAL_HWMON=y
+ CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+ # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+ # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+-CONFIG_FAIR_SHARE=y
++# CONFIG_FAIR_SHARE is not set
+ CONFIG_STEP_WISE=y
+-CONFIG_USER_SPACE=y
++# CONFIG_USER_SPACE is not set
+ CONFIG_CPU_THERMAL=y
+ CONFIG_WATCHDOG=y
+ CONFIG_WATCHDOG_CORE=y
+@@ -2231,7 +2213,6 @@ 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
+@@ -2421,7 +2402,7 @@ 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_VIDEO_MEM2MEM_DEINTERLACE is not set
+ CONFIG_V4L_TEST_DRIVERS=y
+ CONFIG_VIDEO_VIVI=m
+ CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+@@ -2671,29 +2652,34 @@ CONFIG_DVB_AF9033=m
+ # Graphics support
+ #
+ CONFIG_DRM=y
+-CONFIG_DRM_USB=m
+ CONFIG_DRM_KMS_HELPER=y
+-CONFIG_DRM_LOAD_EDID_FIRMWARE=y
++# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
+ CONFIG_DRM_GEM_CMA_HELPER=y
+ CONFIG_DRM_KMS_CMA_HELPER=y
+
+ #
+ # I2C encoder or helper chips
+ #
+-CONFIG_DRM_I2C_CH7006=m
+-CONFIG_DRM_I2C_SIL164=m
+-CONFIG_DRM_UDL=m
++# CONFIG_DRM_I2C_CH7006 is not set
++# CONFIG_DRM_I2C_SIL164 is not set
++# CONFIG_DRM_UDL is not set
+ CONFIG_DRM_LCDC=y
++
++#
++# I2C encoder or helper chips
++#
++CONFIG_DRM_I2C_NXP_TDA998X=y
+ # CONFIG_VGASTATE is not set
+ # CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_DISPLAY_TIMING=y
+ 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=m
+-CONFIG_FB_CFB_COPYAREA=m
+-CONFIG_FB_CFB_IMAGEBLIT=m
+-# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE 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
+@@ -2718,7 +2704,7 @@ CONFIG_FB_TILEBLITTING=y
+ # CONFIG_FB_TMIO is not set
+ # CONFIG_FB_SMSCUFX is not set
+ # CONFIG_FB_UDL is not set
+-# CONFIG_FB_DA8XX 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
+@@ -2727,8 +2713,7 @@ CONFIG_FB_ST7735=y
+ CONFIG_OMAP2_VRFB=y
+ CONFIG_OMAP2_DSS=m
+ # CONFIG_OMAP2_DSS_DEBUG is not set
+-CONFIG_OMAP2_DSS_DEBUGFS=y
+-# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
++# CONFIG_OMAP2_DSS_DEBUGFS is not set
+ CONFIG_OMAP2_DSS_DPI=y
+ CONFIG_OMAP2_DSS_RFBI=y
+ CONFIG_OMAP2_DSS_VENC=y
+@@ -2801,7 +2786,7 @@ CONFIG_LOGO=y
+ CONFIG_LOGO_LINUX_MONO=y
+ CONFIG_LOGO_LINUX_VGA16=y
+ CONFIG_LOGO_LINUX_CLUT224=y
+-CONFIG_FB_SSD1307=m
++# CONFIG_FB_SSD1307 is not set
+ CONFIG_SOUND=m
+ CONFIG_SOUND_OSS_CORE=y
+ CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+@@ -2930,7 +2915,7 @@ CONFIG_USB_HID=y
+ #
+ # I2C HID support
+ #
+-CONFIG_I2C_HID=y
++# CONFIG_I2C_HID is not set
+ CONFIG_USB_ARCH_HAS_OHCI=y
+ CONFIG_USB_ARCH_HAS_EHCI=y
+ # CONFIG_USB_ARCH_HAS_XHCI is not set
+@@ -2966,12 +2951,7 @@ CONFIG_USB_MON=y
+ # 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_MUSB_HDRC is not set
+ # CONFIG_USB_CHIPIDEA is not set
+ # CONFIG_USB_RENESAS_USBHS is not set
+
+@@ -2980,7 +2960,7 @@ CONFIG_MUSB_PIO_ONLY=y
+ #
+ CONFIG_USB_ACM=m
+ CONFIG_USB_PRINTER=m
+-CONFIG_USB_WDM=y
++CONFIG_USB_WDM=m
+ CONFIG_USB_TMC=m
+
+ #
+@@ -3100,8 +3080,6 @@ 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
+@@ -3129,7 +3107,6 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+ # 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
+@@ -3160,7 +3137,6 @@ CONFIG_USB_G_HID=m
+ 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
+@@ -3258,7 +3234,7 @@ CONFIG_RTC_INTF_DEV=y
+ # CONFIG_RTC_DRV_ISL1208 is not set
+ # CONFIG_RTC_DRV_ISL12022 is not set
+ # CONFIG_RTC_DRV_X1205 is not set
+-CONFIG_RTC_DRV_PCF8523=m
++# CONFIG_RTC_DRV_PCF8523 is not set
+ # CONFIG_RTC_DRV_PCF8563 is not set
+ # CONFIG_RTC_DRV_PCF8583 is not set
+ # CONFIG_RTC_DRV_M41T80 is not set
+@@ -3305,7 +3281,7 @@ CONFIG_RTC_DRV_DS2404=m
+ #
+ # on-CPU RTC drivers
+ #
+-CONFIG_RTC_DRV_OMAP=y
++# CONFIG_RTC_DRV_OMAP is not set
+ CONFIG_RTC_DRV_SNVS=m
+ CONFIG_DMADEVICES=y
+ # CONFIG_DMADEVICES_DEBUG is not set
+@@ -3324,13 +3300,13 @@ CONFIG_DMA_VIRTUAL_CHANNELS=y
+ # DMA Clients
+ #
+ # CONFIG_NET_DMA is not set
+-CONFIG_ASYNC_TX_DMA=y
+-CONFIG_DMATEST=m
++# CONFIG_ASYNC_TX_DMA is not set
++# CONFIG_DMATEST is not set
+ # CONFIG_AUXDISPLAY is not set
+ CONFIG_UIO=y
+ CONFIG_UIO_PDRV=y
+ CONFIG_UIO_PDRV_GENIRQ=y
+-CONFIG_UIO_DMEM_GENIRQ=m
++# CONFIG_UIO_DMEM_GENIRQ is not set
+ CONFIG_VIRTIO=m
+
+ #
+@@ -3350,7 +3326,7 @@ CONFIG_COMMON_CLK=y
+ #
+ # Common Clock Framework
+ #
+-CONFIG_COMMON_CLK_DEBUG=y
++# CONFIG_COMMON_CLK_DEBUG is not set
+ CONFIG_HWSPINLOCK=m
+
+ #
+@@ -3377,9 +3353,9 @@ CONFIG_STE_MODEM_RPROC=m
+ # CONFIG_MEMORY is not set
+ CONFIG_IIO=y
+ CONFIG_IIO_BUFFER=y
+-CONFIG_IIO_BUFFER_CB=y
+-CONFIG_IIO_KFIFO_BUF=y
+-CONFIG_IIO_TRIGGERED_BUFFER=y
++# CONFIG_IIO_BUFFER_CB is not set
++CONFIG_IIO_KFIFO_BUF=m
++CONFIG_IIO_TRIGGERED_BUFFER=m
+ CONFIG_IIO_TRIGGER=y
+ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+
+@@ -3393,13 +3369,13 @@ CONFIG_HID_SENSOR_ACCEL_3D=m
+ #
+ CONFIG_AD_SIGMA_DELTA=m
+ CONFIG_AD7266=m
+-CONFIG_AD7298=m
++# CONFIG_AD7298 is not set
+ CONFIG_AD7791=m
+-CONFIG_AD7793=m
++# CONFIG_AD7793 is not set
+ CONFIG_AD7476=m
+-CONFIG_AD7887=m
+-CONFIG_MAX1363=m
+-CONFIG_TI_ADC081C=m
++# CONFIG_AD7887 is not set
++# CONFIG_MAX1363 is not set
++# CONFIG_TI_ADC081C is not set
+ CONFIG_TI_AM335X_ADC=y
+
+ #
+@@ -3422,7 +3398,7 @@ CONFIG_AD5380=m
+ CONFIG_AD5421=m
+ CONFIG_AD5624R_SPI=m
+ CONFIG_AD5446=m
+-CONFIG_AD5449=m
++# CONFIG_AD5449 is not set
+ CONFIG_AD5504=m
+ CONFIG_AD5755=m
+ CONFIG_AD5764=m
+@@ -3448,15 +3424,13 @@ CONFIG_ADF4350=m
+ #
+ # Digital gyroscope sensors
+ #
+-CONFIG_ADIS16136=m
++# CONFIG_ADIS16136 is not set
+ CONFIG_HID_SENSOR_GYRO_3D=m
+
+ #
+ # Inertial measurement units
+ #
+-CONFIG_ADIS16480=m
+-CONFIG_IIO_ADIS_LIB=m
+-CONFIG_IIO_ADIS_LIB_BUFFER=y
++# CONFIG_ADIS16480 is not set
+
+ #
+ # Light sensors
+@@ -3473,9 +3447,9 @@ CONFIG_PWM=y
+ CONFIG_PWM_TIECAP=y
+ CONFIG_PWM_TIEHRPWM=y
+ CONFIG_PWM_TIPWMSS=y
+-CONFIG_PWM_TWL=y
+-CONFIG_PWM_TWL_LED=y
+-CONFIG_EHRPWM_TEST=m
++# CONFIG_PWM_TWL is not set
++# CONFIG_PWM_TWL_LED is not set
++# CONFIG_EHRPWM_TEST is not set
+ # CONFIG_IPACK_BUS is not set
+
+ #
+@@ -3538,14 +3512,7 @@ CONFIG_CUSE=m
+ #
+ # Caches
+ #
+-CONFIG_FSCACHE=y
+-CONFIG_FSCACHE_STATS=y
+-CONFIG_FSCACHE_HISTOGRAM=y
+-# CONFIG_FSCACHE_DEBUG is not set
+-# CONFIG_FSCACHE_OBJECT_LIST is not set
+-CONFIG_CACHEFILES=m
+-# CONFIG_CACHEFILES_DEBUG is not set
+-CONFIG_CACHEFILES_HISTOGRAM=y
++# CONFIG_FSCACHE is not set
+
+ #
+ # CD-ROM/DVD Filesystems
+@@ -3629,11 +3596,8 @@ CONFIG_NFS_V3=y
+ CONFIG_NFS_V3_ACL=y
+ CONFIG_NFS_V4=y
+ CONFIG_NFS_SWAP=y
+-CONFIG_NFS_V4_1=y
+-CONFIG_PNFS_FILE_LAYOUT=m
+-CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
++# CONFIG_NFS_V4_1 is not set
+ CONFIG_ROOT_NFS=y
+-CONFIG_NFS_FSCACHE=y
+ # CONFIG_NFS_USE_LEGACY_DNS is not set
+ CONFIG_NFS_USE_KERNEL_DNS=y
+ # CONFIG_NFSD is not set
+@@ -3643,7 +3607,6 @@ CONFIG_NFS_ACL_SUPPORT=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
+ CONFIG_SUNRPC_GSS=y
+-CONFIG_SUNRPC_BACKCHANNEL=y
+ CONFIG_SUNRPC_SWAP=y
+ # CONFIG_SUNRPC_DEBUG is not set
+ # CONFIG_CEPH_FS is not set
+@@ -3721,10 +3684,15 @@ CONFIG_DEBUG_FS=y
+ # CONFIG_DEBUG_SECTION_MISMATCH is not set
+ CONFIG_DEBUG_KERNEL=y
+ # CONFIG_DEBUG_SHIRQ is not set
+-# CONFIG_LOCKUP_DETECTOR is not set
++CONFIG_LOCKUP_DETECTOR=y
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+ # CONFIG_PANIC_ON_OOPS is not set
+ CONFIG_PANIC_ON_OOPS_VALUE=0
+-# CONFIG_DETECT_HUNG_TASK is not set
++CONFIG_DETECT_HUNG_TASK=y
++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=60
++CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
++CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
+ CONFIG_SCHED_DEBUG=y
+ CONFIG_SCHEDSTATS=y
+ CONFIG_TIMER_STATS=y
+@@ -3734,8 +3702,8 @@ 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_SPINLOCK=y
++CONFIG_DEBUG_MUTEXES=y
+ # CONFIG_DEBUG_LOCK_ALLOC is not set
+ # CONFIG_PROVE_LOCKING is not set
+ # CONFIG_SPARSE_RCU_POINTER is not set
+@@ -3771,6 +3739,7 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60
+ CONFIG_NOTIFIER_ERROR_INJECTION=m
+ # CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
+ CONFIG_PM_NOTIFIER_ERROR_INJECT=m
++# CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT is not set
+ # CONFIG_FAULT_INJECTION is not set
+ # CONFIG_DEBUG_PAGEALLOC is not set
+ CONFIG_NOP_TRACER=y
+@@ -3814,8 +3783,12 @@ CONFIG_HAVE_ARCH_KGDB=y
+ # 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=y
++CONFIG_DEBUG_LL_UART_NONE=y
++# CONFIG_DEBUG_ICEDCC is not set
++# CONFIG_DEBUG_SEMIHOSTING is not set
+ CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
++CONFIG_EARLY_PRINTK=y
+ # CONFIG_ARM_KPROBES_TEST is not set
+ # CONFIG_PID_IN_CONTEXTIDR is not set
+
+@@ -3828,16 +3801,14 @@ CONFIG_KEYS=y
+ # CONFIG_SECURITY_DMESG_RESTRICT is not set
+ CONFIG_SECURITY=y
+ CONFIG_SECURITYFS=y
+-CONFIG_SECURITY_NETWORK=y
+-CONFIG_SECURITY_NETWORK_XFRM=y
++# CONFIG_SECURITY_NETWORK is not set
+ # CONFIG_SECURITY_PATH is not set
+-CONFIG_SECURITY_SMACK=y
++# CONFIG_SECURITY_SMACK 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_SMACK is not set
+ CONFIG_DEFAULT_SECURITY_DAC=y
+ CONFIG_DEFAULT_SECURITY=""
+ CONFIG_CRYPTO=y
diff --git a/patches/linux-3.8.13/0282-lcd3-cape-Convert-to-using-the-proper-touchscreen-dr.patch b/patches/linux-3.8.13/0282-lcd3-cape-Convert-to-using-the-proper-touchscreen-dr.patch
new file mode 100644
index 0000000..f40e259
--- /dev/null
+++ b/patches/linux-3.8.13/0282-lcd3-cape-Convert-to-using-the-proper-touchscreen-dr.patch
@@ -0,0 +1,64 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 9 Jan 2013 14:42:11 +0200
+Subject: [PATCH] lcd3-cape: Convert to using the proper touchscreen driver.
+
+Now that the touchscreen driver has DT bindings switch to using it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-lcd3-00A0.dts | 33 +++++++++++++++-----------------
+ 1 file changed, 15 insertions(+), 18 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index 83a6d88..b0784b2 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -87,13 +87,23 @@
+ #size-cells = <1>;
+
+ tscadc {
+- compatible = "ti-tscadc-dt";
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
+
+- tsc-wires = <4>;
+- tsc-x-plate-resistance = <200>;
+- tsc-steps = <6>;
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++
++ tsc {
++ wires = <4>;
++ x-plate-resistance = <200>;
++ coordinate-readouts = <5>;
++ wire-config = <0x00 0x11 0x22 0x33>;
++ };
+
+- adc-channels = <4>;
++ adc {
++ adc-channels = <4>;
++ };
+ };
+
+ gpio-leds-cape-lcd3 {
+@@ -166,19 +176,6 @@
+ };
+ };
+
+-// lcd3-cape {
+-// compatible = "da8xx-dt";
+-//
+-// pinctrl-names = "default";
+-// pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
+-//
+-// ti,hwmods = "lcdc";
+-//
+-// disp-pll = <16000000>;
+-// panel-type = "CDTech_S035Q01";
+-//
+-// };
+-
+ /* Settings for CDTech_S035Q01 / LCD3 cape: */
+ panel {
+ compatible = "lcdc,panel";
diff --git a/patches/linux-3.8.13/0283-geiger-cape-Convert-to-using-the-new-ADC-driver.patch b/patches/linux-3.8.13/0283-geiger-cape-Convert-to-using-the-new-ADC-driver.patch
new file mode 100644
index 0000000..e1276a4
--- /dev/null
+++ b/patches/linux-3.8.13/0283-geiger-cape-Convert-to-using-the-new-ADC-driver.patch
@@ -0,0 +1,47 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 9 Jan 2013 14:53:59 +0200
+Subject: [PATCH] geiger-cape: Convert to using the new ADC driver
+
+Now that the proper driver has DT binding convert to using it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-geiger-00A0.dts | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
+index 67ec568..39e7d38 100644
+--- a/firmware/capes/cape-bone-geiger-00A0.dts
++++ b/firmware/capes/cape-bone-geiger-00A0.dts
+@@ -54,6 +54,10 @@
+ target = <&ocp>;
+ __overlay__ {
+
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
+ gpio-leds-cape-geiger {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+@@ -75,9 +79,17 @@
+
+ };
+
+- tscadc-cape-geiger {
+- compatible = "ti-tscadc-dt";
+- adc-channels = <0 1 2 3 4 5 6 7>;
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++
++ adc {
++ adc-channels = <0 1 2 3 4 5 6 7>;
++ };
+ };
+
+ bone-cape-geiger {
diff --git a/patches/linux-3.8.13/0284-cape-dvi-Convert-DVI-capes-to-the-new-LCDC-DRM-drive.patch b/patches/linux-3.8.13/0284-cape-dvi-Convert-DVI-capes-to-the-new-LCDC-DRM-drive.patch
new file mode 100644
index 0000000..102be9c
--- /dev/null
+++ b/patches/linux-3.8.13/0284-cape-dvi-Convert-DVI-capes-to-the-new-LCDC-DRM-drive.patch
@@ -0,0 +1,163 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 9 Jan 2013 16:34:14 +0200
+Subject: [PATCH] cape-dvi: Convert DVI capes to the new LCDC DRM driver
+
+The new DRM driver works fine, switch into using that and ditch
+da8xx-fb.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-dvi-00A0.dts | 55 ++++++++++++++++++++++++++++-----
+ firmware/capes/cape-bone-dvi-00A1.dts | 53 ++++++++++++++++++++++++++-----
+ 2 files changed, 93 insertions(+), 15 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+index b9db80b..5445847 100644
+--- a/firmware/capes/cape-bone-dvi-00A0.dts
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -59,6 +59,10 @@
+ target = <&ocp>;
+ __overlay__ {
+
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
+ gpio-leds-cape-dvi {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+@@ -79,17 +83,52 @@
+ };
+ };
+
+- dvi-cape {
+- compatible = "da8xx-dt";
++ /* Settings for DVI 1024x768@60 */
++ panel {
++ compatible = "lcdc,panel";
+ pinctrl-names = "default";
+- ti,hwmods = "lcdc";
+-
+- disp-pll = <560000000>;
+- panel-type = "1024x768@60";
+-
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
+- powerdn-gpio = <&gpio2 7 0>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ invert-line-clock = <1>;
++ invert-frm-clock = <1>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 1024x768 {
++ hactive = <1024>;
++ vactive = <768>;
++ hback-porch = <80>;
++ hfront-porch = <48>;
++ vback-porch = <15>;
++ vfront-porch = <3>;
++ hsync-len = <32>;
++ vsync-len = <4>;
++ clock-frequency = <56000000>;
++ };
++ };
+ };
++
++ fb {
++ compatible = "ti,am33xx-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio2 7 0x0>;
++ };
++
+ };
+ };
+ };
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index 567d12b..dc31146 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -59,6 +59,10 @@
+ target = <&ocp>;
+ __overlay__ {
+
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
+ gpio-leds-cape-dvi {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+@@ -79,16 +83,51 @@
+ };
+ };
+
+- dvi-cape {
+- compatible = "da8xx-dt";
++ /* Settings for DVI 1024x768@60 */
++ panel {
++ compatible = "lcdc,panel";
+ pinctrl-names = "default";
+- ti,hwmods = "lcdc";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ invert-line-clock = <1>;
++ invert-frm-clock = <1>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 1024x768 {
++ hactive = <1024>;
++ vactive = <768>;
++ hback-porch = <80>;
++ hfront-porch = <48>;
++ vback-porch = <15>;
++ vfront-porch = <3>;
++ hsync-len = <32>;
++ vsync-len = <4>;
++ clock-frequency = <56000000>;
++ };
++ };
++ };
+
+- disp-pll = <560000000>;
+- panel-type = "1024x768@60";
++ fb {
++ compatible = "ti,am33xx-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio2 31 0x0>;
+
+- pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
+- powerdn-gpio = <&gpio2 31 0>;
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0285-boneblack-Add-default-HDMI-cape.patch b/patches/linux-3.8.13/0285-boneblack-Add-default-HDMI-cape.patch
new file mode 100644
index 0000000..657b243
--- /dev/null
+++ b/patches/linux-3.8.13/0285-boneblack-Add-default-HDMI-cape.patch
@@ -0,0 +1,161 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 9 Jan 2013 20:00:04 +0200
+Subject: [PATCH] boneblack: Add default HDMI cape
+
+WIP, doesn't work for me...
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 20 ++++++
+ firmware/Makefile | 3 +
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 89 +++++++++++++++++++++++++++
+ 3 files changed, 112 insertions(+)
+ create mode 100644 firmware/capes/cape-boneblack-hdmi-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index b184224..7cb7a9b 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -188,6 +188,16 @@
+ manufacturer = "Geiger Inc.";
+ part-number = "BB-BONE-GEIGER";
+ };
++
++ /* Beaglebone black has it soldered on */
++ slot@6 {
++ ti,cape-override;
++ compatible = "ti,beaglebone-black";
++ board-name = "Bone-Black-HDMI";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONELT-HDMI";
++ };
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -242,6 +252,16 @@
+ dtbo = "cape-bone-weather-00A0.dtbo";
+ };
+ };
++
++ /* beaglebone black hdmi on board */
++ cape@5 {
++ part-number = "BB-BONELT-HDMI";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-boneblack-hdmi-00A0.dtbo";
++ };
++ };
++
+ };
+ };
+ };
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 25ea3fb..600640a 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -149,6 +149,9 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+ # the weather cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += capes/cape-bone-weather-00A0.dtbo
+
++# the HDMI virtual cape on the beaglebone-black
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += capes/cape-boneblack-hdmi-00A0.dtbo
++
+ fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+
+ # Directories which we _might_ need to create, so we have a rule for them.
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+new file mode 100644
+index 0000000..4fe58d5
+--- /dev/null
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -0,0 +1,89 @@
++/*
++* 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++ part-number = "BB-BONELT-HDMI";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
++ pinctrl-single,pins = <
++ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
++ 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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c0>;
++
++ __overlay__ {
++ /* needed to avoid gripping by DTC */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* NXP TDA998x */
++ tsl2550@34 {
++ compatible = "tda998x";
++ reg = <0x34>;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ hdmi {
++ compatible = "lcdc,slave";
++ i2c = <&i2c0>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
++ };
++
++ fb {
++ compatible = "ti,am33xx-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ };
++
++ };
++ };
++
++};
diff --git a/patches/linux-3.8.13/0286-cape-bone-dvi-Use-720p-mode-as-default.patch b/patches/linux-3.8.13/0286-cape-bone-dvi-Use-720p-mode-as-default.patch
new file mode 100644
index 0000000..9055f57
--- /dev/null
+++ b/patches/linux-3.8.13/0286-cape-bone-dvi-Use-720p-mode-as-default.patch
@@ -0,0 +1,75 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 9 Jan 2013 23:28:11 +0200
+Subject: [PATCH] cape-bone-dvi: Use 720p mode as default
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-dvi-00A0.dts | 15 ++++++++++++++-
+ firmware/capes/cape-bone-dvi-00A1.dts | 14 +++++++++++++-
+ 2 files changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+index 5445847..988e801 100644
+--- a/firmware/capes/cape-bone-dvi-00A0.dts
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -105,7 +105,7 @@
+ fifo-th = <0>;
+ };
+ display-timings {
+- native-mode = <&timing0>;
++ native-mode = <&timing1>;
+ timing0: 1024x768 {
+ hactive = <1024>;
+ vactive = <768>;
+@@ -117,6 +117,19 @@
+ vsync-len = <4>;
+ clock-frequency = <56000000>;
+ };
++ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
++ timing1: 1280x720-60 {
++ hactive = <1280>;
++ hfront-porch = <48>;
++ hsync-len = <32>;
++ hback-porch = <80>;
++ vactive = <720>;
++ vfront-porch = <3>;
++ vsync-len = <5>;
++ vback-porch = <13>;
++ clock-frequency = <64000000>;
++ };
++
+ };
+ };
+
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index dc31146..bd275e0 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -105,7 +105,7 @@
+ fifo-th = <0>;
+ };
+ display-timings {
+- native-mode = <&timing0>;
++ native-mode = <&timing1>;
+ timing0: 1024x768 {
+ hactive = <1024>;
+ vactive = <768>;
+@@ -117,6 +117,18 @@
+ vsync-len = <4>;
+ clock-frequency = <56000000>;
+ };
++ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
++ timing1: 1280x720-60 {
++ hactive = <1280>;
++ hfront-porch = <48>;
++ hsync-len = <32>;
++ hback-porch = <80>;
++ vactive = <720>;
++ vfront-porch = <3>;
++ vsync-len = <5>;
++ vback-porch = <13>;
++ clock-frequency = <64000000>;
++ };
+ };
+ };
+
diff --git a/patches/linux-3.8.13/0287-am33xx.dtsi-Make-the-MUSB-not-crash-on-load.patch b/patches/linux-3.8.13/0287-am33xx.dtsi-Make-the-MUSB-not-crash-on-load.patch
new file mode 100644
index 0000000..28d8122
--- /dev/null
+++ b/patches/linux-3.8.13/0287-am33xx.dtsi-Make-the-MUSB-not-crash-on-load.patch
@@ -0,0 +1,104 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 10 Jan 2013 16:22:59 +0200
+Subject: [PATCH] am33xx.dtsi: Make the MUSB not crash on load
+
+Two entries for the same musb instance end up with a crash.
+Remove the duplicate, but it still doesn't work.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 67 ++++-------------------------------------
+ 1 file changed, 6 insertions(+), 61 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index c9eee93..9142e54 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -270,66 +270,6 @@
+ 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";
+- #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";
+@@ -535,6 +475,11 @@
+ &edma 45>;
+ dma-names = "tx0", "rx0", "tx1", "rx1";
+ status = "disabled";
++
++ };
++
++ nop-phy {
++ compatible = "nop-xceiv-usb";
+ };
+
+ usb@47400000 {
+@@ -549,7 +494,7 @@
+ num-eps = <16>;
+ ram-bits = <12>;
+ port0-mode = <3>;
+- port1-mode = <3>;
++ port1-mode = <1>;
+ power = <250>;
+ ti,hwmods = "usb_otg_hs";
+ };
diff --git a/patches/linux-3.8.13/0288-regulator-DUMMY_REGULATOR-should-work-for-OF-too.patch b/patches/linux-3.8.13/0288-regulator-DUMMY_REGULATOR-should-work-for-OF-too.patch
new file mode 100644
index 0000000..86988a7
--- /dev/null
+++ b/patches/linux-3.8.13/0288-regulator-DUMMY_REGULATOR-should-work-for-OF-too.patch
@@ -0,0 +1,32 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 11:17:59 +0200
+Subject: [PATCH] regulator: DUMMY_REGULATOR should work for OF too
+
+Dummy regulator should work when using Device Tree.
+So don't set has_full_constraints when it is set.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/regulator/core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
+index 8e7ec07..b160fcc 100644
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -3786,6 +3786,7 @@ static int __init regulator_init_complete(void)
+ struct regulation_constraints *c;
+ int enabled, ret;
+
++#ifndef CONFIG_REGULATOR_DUMMY
+ /*
+ * Since DT doesn't provide an idiomatic mechanism for
+ * enabling full constraints and since it's much more natural
+@@ -3794,6 +3795,7 @@ static int __init regulator_init_complete(void)
+ */
+ if (of_have_populated_dt())
+ has_full_constraints = true;
++#endif
+
+ mutex_lock(&regulator_list_mutex);
+
diff --git a/patches/linux-3.8.13/0289-OF-Overlay-Remove-excessive-debugging-crud.patch b/patches/linux-3.8.13/0289-OF-Overlay-Remove-excessive-debugging-crud.patch
new file mode 100644
index 0000000..93bd52b
--- /dev/null
+++ b/patches/linux-3.8.13/0289-OF-Overlay-Remove-excessive-debugging-crud.patch
@@ -0,0 +1,84 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 12:05:11 +0200
+Subject: [PATCH] OF: Overlay: Remove excessive debugging crud
+
+There's no need for such excessive debugging crud anymore. Remove it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/overlay.c | 41 -----------------------------------------
+ 1 file changed, 41 deletions(-)
+
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index f65c3a3..fc7bf5a 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -257,9 +257,6 @@ static void of_overlay_device_entry_entry_add(struct of_overlay_info *ovinfo,
+ static int of_overlay_notify(struct notifier_block *nb,
+ unsigned long action, void *arg)
+ {
+-#ifdef DEBUG
+- char *propstr = NULL, *spropstr = NULL;
+-#endif
+ struct of_overlay_info *ovinfo;
+ struct device_node *node;
+ struct property *prop, *sprop, *cprop;
+@@ -278,9 +275,6 @@ static int of_overlay_notify(struct notifier_block *nb,
+ if (node == NULL)
+ return notifier_from_errno(-EINVAL);
+ prop = NULL;
+-#ifdef DEBUG
+- propstr = NULL;
+-#endif
+ break;
+ case OF_RECONFIG_ADD_PROPERTY:
+ case OF_RECONFIG_REMOVE_PROPERTY:
+@@ -294,9 +288,6 @@ static int of_overlay_notify(struct notifier_block *nb,
+ prop = pr->prop;
+ if (prop == NULL)
+ return notifier_from_errno(-EINVAL);
+-#ifdef DEBUG
+- propstr = __of_dump_prop(prop);
+-#endif
+ break;
+ default:
+ return notifier_from_errno(0);
+@@ -307,38 +298,6 @@ static int of_overlay_notify(struct notifier_block *nb,
+ if (err != 0)
+ return notifier_from_errno(err);
+
+-#ifdef DEBUG
+- switch (action) {
+- case OF_RECONFIG_ATTACH_NODE:
+- pr_debug("ATTACH_NODE: %s\n", node->full_name);
+- break;
+- case OF_RECONFIG_DETACH_NODE:
+- pr_debug("DETACH_NODE: %s\n", node->full_name);
+- break;
+- case OF_RECONFIG_ADD_PROPERTY:
+- pr_debug("ADD_PROP: %s %s%s\n", node->full_name,
+- prop->name, propstr);
+- break;
+- case OF_RECONFIG_REMOVE_PROPERTY:
+- pr_debug("REMOVE_PROP: %s %s%s\n", node->full_name,
+- prop->name, propstr);
+- break;
+- case OF_RECONFIG_UPDATE_PROPERTY:
+- sprop = of_find_property(node, prop->name, NULL);
+- if (sprop)
+- spropstr = __of_dump_prop(sprop);
+- pr_debug("UPDATE_PROP: %s '%s%s' -> '%s%s'\n", node->full_name,
+- prop->name, spropstr,
+- prop->name, propstr);
+- break;
+-
+- }
+-
+- /* NULL is fine */
+- kfree(propstr);
+- kfree(spropstr);
+-#endif
+-
+ /* come up with the device entry (if any) */
+ pdev = NULL;
+ state = 0;
diff --git a/patches/linux-3.8.13/0290-of-i2c-Export-single-device-registration-method.patch b/patches/linux-3.8.13/0290-of-i2c-Export-single-device-registration-method.patch
new file mode 100644
index 0000000..f0f1f25
--- /dev/null
+++ b/patches/linux-3.8.13/0290-of-i2c-Export-single-device-registration-method.patch
@@ -0,0 +1,167 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 11:26:27 +0200
+Subject: [PATCH] of-i2c: Export single device registration method
+
+Dynamically inserting i2c client device nodes requires the use
+of a single device registration method. Rework and export it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/of_i2c.c | 104 ++++++++++++++++++++++++++----------------------
+ include/linux/of_i2c.h | 11 +++++
+ 2 files changed, 68 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
+index b667264..116a5e0 100644
+--- a/drivers/of/of_i2c.c
++++ b/drivers/of/of_i2c.c
+@@ -17,10 +17,64 @@
+ #include <linux/of_i2c.h>
+ #include <linux/of_irq.h>
+ #include <linux/module.h>
++#include <linux/err.h>
++
++struct i2c_client *
++of_i2c_register_device(struct i2c_adapter *adap,
++ struct device_node *node)
++{
++ struct i2c_client *result;
++ struct i2c_board_info info = {};
++ struct dev_archdata dev_ad = {};
++ const __be32 *addr;
++ int len;
++
++ dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
++
++ if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
++ dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
++ node->full_name);
++ return ERR_PTR(-EINVAL);
++ }
++
++ addr = of_get_property(node, "reg", &len);
++ if (!addr || (len < sizeof(int))) {
++ dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
++ node->full_name);
++ return ERR_PTR(-EINVAL);
++ }
++
++ info.addr = be32_to_cpup(addr);
++ if (info.addr > (1 << 10) - 1) {
++ dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
++ info.addr, node->full_name);
++ return ERR_PTR(-EINVAL);
++ }
++
++ info.irq = irq_of_parse_and_map(node, 0);
++ info.of_node = of_node_get(node);
++ info.archdata = &dev_ad;
++
++ if (of_get_property(node, "wakeup-source", NULL))
++ info.flags |= I2C_CLIENT_WAKE;
++
++ request_module("%s%s", I2C_MODULE_PREFIX, info.type);
++
++ result = i2c_new_device(adap, &info);
++ if (result == NULL) {
++ dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
++ node->full_name);
++ of_node_put(node);
++ irq_dispose_mapping(info.irq);
++ return ERR_PTR(-ENODEV);
++ }
++
++ return result;
++}
++EXPORT_SYMBOL(of_i2c_register_device);
+
+ void of_i2c_register_devices(struct i2c_adapter *adap)
+ {
+- void *result;
+ struct device_node *node;
+
+ /* Only register child devices if the adapter has a node pointer set */
+@@ -29,52 +83,8 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
+
+ dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
+
+- for_each_available_child_of_node(adap->dev.of_node, node) {
+- struct i2c_board_info info = {};
+- struct dev_archdata dev_ad = {};
+- const __be32 *addr;
+- int len;
+-
+- dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
+-
+- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+- dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
+- node->full_name);
+- continue;
+- }
+-
+- addr = of_get_property(node, "reg", &len);
+- if (!addr || (len < sizeof(int))) {
+- dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
+- node->full_name);
+- continue;
+- }
+-
+- info.addr = be32_to_cpup(addr);
+- if (info.addr > (1 << 10) - 1) {
+- dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
+- info.addr, node->full_name);
+- continue;
+- }
+-
+- info.irq = irq_of_parse_and_map(node, 0);
+- info.of_node = of_node_get(node);
+- info.archdata = &dev_ad;
+-
+- if (of_get_property(node, "wakeup-source", NULL))
+- info.flags |= I2C_CLIENT_WAKE;
+-
+- request_module("%s%s", I2C_MODULE_PREFIX, info.type);
+-
+- result = i2c_new_device(adap, &info);
+- if (result == NULL) {
+- dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
+- node->full_name);
+- of_node_put(node);
+- irq_dispose_mapping(info.irq);
+- continue;
+- }
+- }
++ for_each_available_child_of_node(adap->dev.of_node, node)
++ of_i2c_register_device(adap, node);
+ }
+ EXPORT_SYMBOL(of_i2c_register_devices);
+
+diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h
+index cfb545c..53fca8f 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>
+
++struct i2c_client *
++of_i2c_register_device(struct i2c_adapter *adap, struct device_node *node);
++
+ extern void of_i2c_register_devices(struct i2c_adapter *adap);
+
+ /* must call put_device() when done with returned i2c_client device */
+@@ -25,6 +28,14 @@ extern struct i2c_adapter *of_find_i2c_adapter_by_node(
+ struct device_node *node);
+
+ #else
++
++static inline struct i2c_client *
++of_i2c_register_device(struct i2c_adapter *adap,
++ struct device_node *node)
++{
++ return ERR_PTR(-ENODEV);
++}
++
+ static inline void of_i2c_register_devices(struct i2c_adapter *adap)
+ {
+ return;
diff --git a/patches/linux-3.8.13/0291-OF-Overlay-I2C-client-devices-special-handling.patch b/patches/linux-3.8.13/0291-OF-Overlay-I2C-client-devices-special-handling.patch
new file mode 100644
index 0000000..2b9fefa
--- /dev/null
+++ b/patches/linux-3.8.13/0291-OF-Overlay-I2C-client-devices-special-handling.patch
@@ -0,0 +1,193 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 12:07:50 +0200
+Subject: [PATCH] OF: Overlay: I2C client devices special handling.
+
+The I2C client devices are 'special', as in they're not platform
+devices. They need to be registered with an I2C specific method.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/overlay.c | 132 +++++++++++++++++++++++++++-----------------------
+ 1 file changed, 71 insertions(+), 61 deletions(-)
+
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index fc7bf5a..0577067 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
++#include <linux/of_i2c.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+ #include <linux/errno.h>
+@@ -368,6 +369,72 @@ static int of_overlay_prep_one(struct of_overlay_info *ovinfo)
+ return 0;
+ }
+
++static int of_overlay_device_entry_change(struct of_overlay_info *ovinfo,
++ struct of_overlay_device_entry *re, int revert)
++{
++ struct i2c_adapter *adap = NULL;
++ struct i2c_client *client;
++ struct platform_device *pdev, *parent_pdev = NULL;
++ int state;
++
++ state = !!re->state ^ !!revert;
++
++ if (re->np && re->np->parent) {
++ pr_debug("%s: parent is %s\n",
++ __func__, re->np->parent->full_name);
++ adap = of_find_i2c_adapter_by_node(re->np->parent);
++ if (adap == NULL)
++ parent_pdev = of_find_device_by_node(re->np->parent);
++ }
++
++ if (state) {
++
++ /* try to see if it's an I2C client node */
++ if (adap == NULL) {
++
++ pr_debug("%s: creating new platform device "
++ "new_node='%s' %p\n",
++ __func__, re->np->full_name, re->np);
++
++ pdev = of_platform_device_create(re->np, NULL,
++ parent_pdev ? &parent_pdev->dev : NULL);
++ if (pdev == NULL) {
++ pr_warn("%s: Failed to create platform device "
++ "for '%s'\n",
++ __func__, re->np->full_name);
++ }
++ } else {
++ pr_debug("%s: creating new i2c_client device "
++ "new_node='%s' %p\n",
++ __func__, re->np->full_name, re->np);
++
++ client = of_i2c_register_device(adap, re->np);
++
++ if (client == NULL) {
++ pr_warn("%s: Failed to create i2c client device "
++ "for '%s'\n",
++ __func__, re->np->full_name);
++ }
++ }
++
++ } else {
++
++ if (re->pdev) {
++ pr_debug("%s: removing pdev %s\n", __func__,
++ dev_name(&re->pdev->dev));
++ platform_device_unregister(re->pdev);
++ }
++ }
++
++ if (adap)
++ put_device(&adap->dev);
++
++ if (parent_pdev)
++ of_dev_put(parent_pdev);
++
++ return 0;
++}
++
+ /**
+ * Revert one overlay
+ * Either due to an error, or due to normal overlay removal.
+@@ -380,7 +447,6 @@ static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
+ struct of_overlay_device_entry *re, *ren;
+ struct of_overlay_log_entry *le, *len;
+ struct property *prop, **propp;
+- struct platform_device *pdev, *parent_pdev;
+ int ret;
+ unsigned long flags;
+
+@@ -393,37 +459,10 @@ static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
+ /* overlay applied correctly, now create/destroy pdevs */
+ list_for_each_entry_safe_reverse(re, ren, &ovinfo->de_list, node) {
+
+- if (!re->state) {
+-
+- parent_pdev = of_find_device_by_node(re->np->parent);
+-
+- pr_debug("%s: creating new platform device "
+- "new_node='%s' %p\n",
+- __func__, re->np->full_name, re->np);
+-
+- pdev = of_platform_device_create(re->np, NULL,
+- parent_pdev ? &parent_pdev->dev : NULL);
+- of_dev_put(parent_pdev);
+-
+- if (pdev == NULL) {
+- pr_warn("%s: Failed to create platform device "
+- "for '%s'\n",
+- __func__, re->np->full_name);
+- }
+-
+- } else {
+-
+- if (re->pdev) {
+- pr_debug("%s: removing pdev %s\n", __func__,
+- dev_name(&re->pdev->dev));
+- platform_device_unregister(re->pdev);
+- }
+- }
++ of_overlay_device_entry_change(ovinfo, re, 1);
+
+ of_node_put(re->np);
+-
+ list_del(&re->node);
+-
+ kfree(re);
+ }
+
+@@ -515,8 +554,7 @@ static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
+ */
+ static int of_overlay_post_one(struct of_overlay_info *ovinfo, int err)
+ {
+- struct of_overlay_device_entry *re, *ren;
+- struct platform_device *pdev, *parent_pdev;
++ struct of_overlay_device_entry *re;
+
+ of_reconfig_notifier_unregister(&ovinfo->notifier);
+
+@@ -527,36 +565,8 @@ static int of_overlay_post_one(struct of_overlay_info *ovinfo, int err)
+ }
+
+ /* overlay applied correctly, now create/destroy pdevs */
+- list_for_each_entry_safe(re, ren, &ovinfo->de_list, node) {
+-
+- if (re->state) {
+-
+- parent_pdev = of_find_device_by_node(re->np->parent);
+-
+- pr_debug("%s: creating new platform device "
+- "new_node='%s' %p\n",
+- __func__, re->np->full_name, re->np);
+-
+- pdev = of_platform_device_create(re->np, NULL,
+- parent_pdev ? &parent_pdev->dev : NULL);
+- of_dev_put(parent_pdev);
+-
+- if (pdev == NULL) {
+- pr_warn("%s: Failed to create platform device "
+- "for '%s'\n",
+- __func__, re->np->full_name);
+- }
+-
+- /* keep it around */
+- re->pdev = pdev;
+-
+- } else {
+-
+- if (re->pdev) {
+- platform_device_unregister(re->pdev);
+- }
+- }
+- }
++ list_for_each_entry(re, &ovinfo->de_list, node)
++ of_overlay_device_entry_change(ovinfo, re, 0);
+
+ return 0;
+ }
diff --git a/patches/linux-3.8.13/0292-omap-Fix-bug-on-partial-resource-addition.patch b/patches/linux-3.8.13/0292-omap-Fix-bug-on-partial-resource-addition.patch
new file mode 100644
index 0000000..ce1c728
--- /dev/null
+++ b/patches/linux-3.8.13/0292-omap-Fix-bug-on-partial-resource-addition.patch
@@ -0,0 +1,25 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 13:22:00 +0200
+Subject: [PATCH] omap: Fix bug on partial resource addition.
+
+Correctly add all of the resources. Bug was uncovered by missing dma
+resources.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/omap_device.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
+index 9f8dba1..0d7b065 100644
+--- a/arch/arm/mach-omap2/omap_device.c
++++ b/arch/arm/mach-omap2/omap_device.c
+@@ -616,7 +616,7 @@ static int omap_device_fixup_resources(struct omap_device *od)
+
+ /* this is our new resource table */
+ res = rnew;
+- res_count = j;
++ res_count = j + pdev->num_resources;
+
+ } else {
+ dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
diff --git a/patches/linux-3.8.13/0293-ASoC-davinci-mcasp-Add-pinctrl-support.patch b/patches/linux-3.8.13/0293-ASoC-davinci-mcasp-Add-pinctrl-support.patch
new file mode 100644
index 0000000..b296f5d
--- /dev/null
+++ b/patches/linux-3.8.13/0293-ASoC-davinci-mcasp-Add-pinctrl-support.patch
@@ -0,0 +1,41 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Mon, 29 Oct 2012 19:18:47 +0530
+Subject: [PATCH] ASoC: davinci-mcasp: Add pinctrl support
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+---
+ sound/soc/davinci/davinci-mcasp.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
+index 55e2bf6..83d96eb 100644
+--- a/sound/soc/davinci/davinci-mcasp.c
++++ b/sound/soc/davinci/davinci-mcasp.c
+@@ -25,6 +25,7 @@
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/of_device.h>
++#include <linux/pinctrl/consumer.h>
+
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+@@ -1080,6 +1081,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+ struct resource *mem, *ioarea, *res;
+ struct snd_platform_data *pdata;
+ struct davinci_audio_dev *dev;
++ struct pinctrl *pinctrl;
+ int ret;
+
+ if (!pdev->dev.platform_data && !pdev->dev.of_node) {
+@@ -1111,6 +1113,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+ return -EBUSY;
+ }
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
+ pm_runtime_enable(&pdev->dev);
+
+ ret = pm_runtime_get_sync(&pdev->dev);
diff --git a/patches/linux-3.8.13/0294-ASoC-Davinci-machine-Add-device-tree-binding.patch b/patches/linux-3.8.13/0294-ASoC-Davinci-machine-Add-device-tree-binding.patch
new file mode 100644
index 0000000..3a5144b
--- /dev/null
+++ b/patches/linux-3.8.13/0294-ASoC-Davinci-machine-Add-device-tree-binding.patch
@@ -0,0 +1,313 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Tue, 31 Jul 2012 21:25:38 +0530
+Subject: [PATCH] ASoC: Davinci: machine: Add device tree binding
+
+Device tree support for Davinci Machine driver
+
+When the board boots with device tree, the driver will receive card,
+codec, dai interface details (like the card name, DAPM routing map,
+phandle for the audio components described in the dts file, codec mclk
+speed).
+The card will be set up based on this information.
+Since the routing is provided via DT we can mark the card fully routed
+so core can take care of disconnecting the unused pins.
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+---
+ .../bindings/sound/davinci-evm-audio.txt | 53 ++++++
+ sound/soc/davinci/davinci-evm.c | 179 +++++++++++++++++---
+ 2 files changed, 212 insertions(+), 20 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
+
+diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
+new file mode 100644
+index 0000000..25f7180
+--- /dev/null
++++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
+@@ -0,0 +1,53 @@
++* Texas Instruments SoC audio setups with TLV320AIC3X Codec
++
++Required properties:
++- compatible :
++ "ti,dm365-voice-codec-audio" : for DM365 platforms with Voice Codec
++ "ti,da830-evm-audio" : for DM365/DA8xx/OMAPL1x/AM33xx
++
++- ti,model : The user-visible name of this sound complex.
++- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
++- ti,mcasp-controller : The phandle of the McASP controller
++- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
++- ti,audio-routing : A list of the connections between audio components.
++ Each entry is a pair of strings, the first being the connection's sink,
++ the second being the connection's source. Valid names for sources and
++ sinks are the codec's pins, and the jacks on the board:
++
++ Codec pins:
++
++ * MIC3L
++ * MIC3R
++ * LINE1L
++ * LINE2L
++ * LINE1R
++ * LINE2R
++
++ Board connectors:
++
++ * Headphone Jack
++ * Line Out
++ * Mic Jack
++
++
++Example:
++
++sound {
++ compatible = "ti,da830-evm-audio";
++ ti,model = "DA830 EVM";
++ ti,audio-codec = <&tlv320aic3x>;
++ ti,mcasp-controller = <&mcasp1>;
++ ti,codec-clock-rate = <12000000>;
++ ti,audio-routing =
++ "Headphone Jack", "HPLOUT",
++ "Headphone Jack", "HPROUT",
++ "Line Out", "LLOUT",
++ "Line Out", "RLOUT",
++ "MIC3L", "Mic Bias 2V",
++ "MIC3R", "Mic Bias 2V",
++ "Mic Bias 2V", "Mic Jack",
++ "LINE1L", "Line In",
++ "LINE2L", "Line In",
++ "LINE1R", "Line In",
++ "LINE2R", "Line In";
++};
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+index 591f547..a39dbee 100644
+--- a/sound/soc/davinci/davinci-evm.c
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -16,6 +16,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/platform_data/edma.h>
+ #include <linux/i2c.h>
++#include <linux/of_platform.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/soc.h>
+@@ -35,27 +36,38 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++ struct snd_soc_codec *codec = rtd->codec;
++ struct snd_soc_card *soc_card = codec->card;
++ struct device_node *np = soc_card->dev->of_node;
+ int ret = 0;
+ unsigned sysclk;
+
+- /* ASP1 on DM355 EVM is clocked by an external oscillator */
+- if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
+- machine_is_davinci_dm365_evm())
+- sysclk = 27000000;
+-
+- /* ASP0 in DM6446 EVM is clocked by U55, as configured by
+- * board-dm644x-evm.c using GPIOs from U18. There are six
+- * options; here we "know" we use a 48 KHz sample rate.
+- */
+- else if (machine_is_davinci_evm())
+- sysclk = 12288000;
+-
+- else if (machine_is_davinci_da830_evm() ||
+- machine_is_davinci_da850_evm())
+- sysclk = 24576000;
+-
+- else
+- return -EINVAL;
++ if (np) {
++ ret = of_property_read_u32(np, "ti,codec-clock-rate", &sysclk);
++ if (ret < 0)
++ return ret;
++ } else {
++ /* ASP1 on DM355 EVM is clocked by an external oscillator */
++ if (machine_is_davinci_dm355_evm() ||
++ machine_is_davinci_dm6467_evm() ||
++ machine_is_davinci_dm365_evm())
++ sysclk = 27000000;
++
++ /*
++ * ASP0 in DM6446 EVM is clocked by U55, as configured by
++ * board-dm644x-evm.c using GPIOs from U18. There are six
++ * options; here we "know" we use a 48 KHz sample rate.
++ */
++ else if (machine_is_davinci_evm())
++ sysclk = 12288000;
++
++ else if (machine_is_davinci_da830_evm() ||
++ machine_is_davinci_da850_evm())
++ sysclk = 24576000;
++
++ else
++ return -EINVAL;
++ }
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
+@@ -133,13 +145,22 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
+ {
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
++ struct device_node *np = codec->card->dev->of_node;
++ int ret;
+
+ /* Add davinci-evm specific widgets */
+ snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
+ ARRAY_SIZE(aic3x_dapm_widgets));
+
+- /* Set up davinci-evm specific audio path audio_map */
+- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
++ if (np) {
++ ret = snd_soc_of_parse_audio_routing(codec->card,
++ "ti,audio-routing");
++ if (ret)
++ return ret;
++ } else {
++ /* Set up davinci-evm specific audio path audio_map */
++ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
++ }
+
+ /* not connected */
+ snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
+@@ -288,6 +309,108 @@ static struct snd_soc_card da850_snd_soc_card = {
+ .num_links = 1,
+ };
+
++#if defined(CONFIG_OF)
++
++enum {
++ MACHINE_VERSION_1 = 0, /* DM365 with Voice Codec */
++ MACHINE_VERSION_2, /* DM365/DA8xx/OMAPL1x/AM33xx */
++};
++
++static const struct of_device_id davinci_evm_dt_ids[] = {
++ {
++ .compatible = "ti,dm365-voice-codec-audio",
++ .data = (void *)MACHINE_VERSION_1,
++ },
++ {
++ .compatible = "ti,da830-evm-audio",
++ .data = (void *)MACHINE_VERSION_2,
++ },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, davinci_mcasp_dt_ids);
++
++/*
++ * This struct is just used as place holder. It will be filled with
++ * data from dt node
++ */
++static struct snd_soc_dai_link evm_dai = {
++ .name = "TLV320AIC3X",
++ .stream_name = "AIC3X",
++ .codec_dai_name = "tlv320aic3x-hifi",
++};
++
++/* davinci evm audio machine driver */
++static struct snd_soc_card evm_soc_card = {
++ .owner = THIS_MODULE,
++ .dai_link = &evm_dai,
++ .num_links = 1,
++};
++
++static int davinci_evm_probe(struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ const struct of_device_id *match =
++ of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
++ u32 machine_ver;
++ int ret = 0;
++
++ machine_ver = (u32)match->data;
++ switch (machine_ver) {
++ case MACHINE_VERSION_1:
++ evm_dai.name = "Voice Codec - CQ93VC";
++ evm_dai.stream_name = "CQ93";
++ evm_dai.codec_dai_name = "cq93vc-hifi";
++ break;
++
++ case MACHINE_VERSION_2:
++ evm_dai.ops = &evm_ops;
++ evm_dai.init = evm_aic3x_init;
++ break;
++ }
++
++ evm_dai.codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
++ if (!evm_dai.codec_of_node)
++ return -EINVAL;
++
++ evm_dai.cpu_of_node = of_parse_phandle(np,
++ "ti,mcasp-controller", 0);
++ if (!evm_dai.cpu_of_node)
++ return -EINVAL;
++
++ evm_dai.platform_of_node = evm_dai.cpu_of_node;
++
++ evm_soc_card.dev = &pdev->dev;
++ ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
++ if (ret)
++ return ret;
++
++ ret = snd_soc_register_card(&evm_soc_card);
++ if (ret)
++ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
++
++ return ret;
++}
++
++static int __devexit davinci_evm_remove(struct platform_device *pdev)
++{
++ struct snd_soc_card *card = platform_get_drvdata(pdev);
++
++ snd_soc_unregister_card(card);
++
++ return 0;
++}
++
++static struct platform_driver davinci_evm_driver = {
++ .probe = davinci_evm_probe,
++ .remove = __devexit_p(davinci_evm_remove),
++ .driver = {
++ .name = "davinci_evm",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(davinci_evm_dt_ids),
++ },
++};
++#endif
++
+ static struct platform_device *evm_snd_device;
+
+ static int __init evm_init(void)
+@@ -296,6 +419,15 @@ static int __init evm_init(void)
+ int index;
+ int ret;
+
++#if defined(CONFIG_OF)
++ /*
++ * If dtb is there, the devices will be created dynamically.
++ * Only register platfrom driver structure.
++ */
++ if (of_have_populated_dt())
++ return platform_driver_register(&davinci_evm_driver);
++#endif
++
+ if (machine_is_davinci_evm()) {
+ evm_snd_dev_data = &dm6446_snd_soc_card_evm;
+ index = 0;
+@@ -331,6 +463,13 @@ static int __init evm_init(void)
+
+ static void __exit evm_exit(void)
+ {
++#if defined(CONFIG_OF)
++ if (of_have_populated_dt()) {
++ platform_driver_unregister(&davinci_evm_driver);
++ return;
++ }
++#endif
++
+ platform_device_unregister(evm_snd_device);
+ }
+
diff --git a/patches/linux-3.8.13/0295-am33xx-Add-mcasp0-and-mcasp1-device-tree-entries.patch b/patches/linux-3.8.13/0295-am33xx-Add-mcasp0-and-mcasp1-device-tree-entries.patch
new file mode 100644
index 0000000..a4aa777
--- /dev/null
+++ b/patches/linux-3.8.13/0295-am33xx-Add-mcasp0-and-mcasp1-device-tree-entries.patch
@@ -0,0 +1,42 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 10 Jan 2013 20:37:45 +0200
+Subject: [PATCH] am33xx: Add mcasp0 and mcasp1 device tree entries
+
+Add missing mcasp entries in teh am33xx.dtsi include file.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 9142e54..cc1c013 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -670,5 +670,26 @@
+ &edma 5>;
+ dma-names = "tx", "rx";
+ };
++
++ mcasp0: mcasp@48038000 {
++ compatible = "ti,omap2-mcasp-audio";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ ti,hwmods = "mcasp0";
++ reg = <0x48038000 0x2000>;
++ interrupts = <80 81>;
++ status = "disabled";
++ };
++
++ mcasp1: mcasp@4803C000 {
++ compatible = "ti,omap2-mcasp-audio";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ ti,hwmods = "mcasp1";
++ reg = <0x4803C000 0x2000>;
++ interrupts = <82 83>;
++ status = "disabled";
++ };
++
+ };
+ };
diff --git a/patches/linux-3.8.13/0296-ASoC-dts-OMAP2-AM33xx-HACK-Add-missing-dma-info.patch b/patches/linux-3.8.13/0296-ASoC-dts-OMAP2-AM33xx-HACK-Add-missing-dma-info.patch
new file mode 100644
index 0000000..d80e200
--- /dev/null
+++ b/patches/linux-3.8.13/0296-ASoC-dts-OMAP2-AM33xx-HACK-Add-missing-dma-info.patch
@@ -0,0 +1,91 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Fri, 10 Aug 2012 20:38:09 +0530
+Subject: [PATCH] ASoC/dts: OMAP2+: AM33xx: [HACK] Add missing dma info
+
+This patch adds dma related dt entries and functions that later will be
+replaced by actual DMA porting
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+
+Conflicts:
+ arch/arm/boot/dts/am33xx.dtsi
+---
+ arch/arm/boot/dts/am33xx.dtsi | 6 ++++++
+ sound/soc/davinci/davinci-mcasp.c | 26 ++++++++++++++++++++++++--
+ 2 files changed, 30 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index cc1c013..3560959 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -679,6 +679,9 @@
+ reg = <0x48038000 0x2000>;
+ interrupts = <80 81>;
+ status = "disabled";
++ asp-chan-q = <2>; /* EVENTQ_2 */
++ tx-dma-offset = <0x46000000>;
++ rx-dma-offset = <0x46000000>;
+ };
+
+ mcasp1: mcasp@4803C000 {
+@@ -689,6 +692,9 @@
+ reg = <0x4803C000 0x2000>;
+ interrupts = <82 83>;
+ status = "disabled";
++ asp-chan-q = <2>; /* EVENTQ_2 */
++ tx-dma-offset = <0x46400000>;
++ rx-dma-offset = <0x46400000>;
+ };
+
+ };
+diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
+index 83d96eb..621ce30 100644
+--- a/sound/soc/davinci/davinci-mcasp.c
++++ b/sound/soc/davinci/davinci-mcasp.c
+@@ -1048,6 +1048,22 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
+ pdata->serial_dir = of_serial_dir;
+ }
+
++ ret = of_property_read_u32(np, "asp-chan-q", &pdata->asp_chan_q);
++ if (ret < 0)
++ goto nodata;
++
++ ret = of_property_read_u32(np, "ram-chan-q", &val);
++ if (ret >= 0)
++ pdata->ram_chan_q = val;
++
++ ret = of_property_read_u32(np, "tx-dma-offset", &pdata->tx_dma_offset);
++ if (ret < 0)
++ goto nodata;
++
++ ret = of_property_read_u32(np, "rx-dma-offset", &pdata->rx_dma_offset);
++ if (ret < 0)
++ goto nodata;
++
+ ret = of_property_read_u32(np, "tx-num-evt", &val);
+ if (ret >= 0)
+ pdata->txnumevt = val;
+@@ -1147,7 +1163,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+ dma_data->ram_chan_q = pdata->ram_chan_q;
+ dma_data->sram_pool = pdata->sram_pool;
+ dma_data->sram_size = pdata->sram_size_playback;
+- dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
++ if (dev->version == MCASP_VERSION_3)
++ dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset);
++ else
++ dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
+ mem->start);
+
+ /* first TX, then RX */
+@@ -1165,7 +1184,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+ dma_data->ram_chan_q = pdata->ram_chan_q;
+ dma_data->sram_pool = pdata->sram_pool;
+ dma_data->sram_size = pdata->sram_size_capture;
+- dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
++ if (dev->version == MCASP_VERSION_3)
++ dma_data->dma_addr = (dma_addr_t) (pdata->rx_dma_offset);
++ else
++ dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
+ mem->start);
+
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
diff --git a/patches/linux-3.8.13/0297-ASoC-Davinci-McASP-remove-unused-header-include.patch b/patches/linux-3.8.13/0297-ASoC-Davinci-McASP-remove-unused-header-include.patch
new file mode 100644
index 0000000..36ac5ff
--- /dev/null
+++ b/patches/linux-3.8.13/0297-ASoC-Davinci-McASP-remove-unused-header-include.patch
@@ -0,0 +1,29 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Mon, 26 Sep 2011 18:16:19 +0530
+Subject: [PATCH] ASoC: Davinci: McASP: remove unused header include
+
+Defines or parameters from <mach/mux.h> isn't used anywhere. Hence
+remove the header include.
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+
+Conflicts:
+ sound/soc/davinci/davinci-evm.c
+---
+ sound/soc/davinci/davinci-evm.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+index a39dbee..d0fad7e 100644
+--- a/sound/soc/davinci/davinci-evm.c
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -24,6 +24,9 @@
+ #include <asm/dma.h>
+ #include <asm/mach-types.h>
+
++#include <mach/asp.h>
++#include <mach/edma.h>
++
+ #include "davinci-pcm.h"
+ #include "davinci-i2s.h"
+ #include "davinci-mcasp.h"
diff --git a/patches/linux-3.8.13/0298-ASoC-AM33XX-Add-support-for-AM33xx-SoC-Audio.patch b/patches/linux-3.8.13/0298-ASoC-AM33XX-Add-support-for-AM33xx-SoC-Audio.patch
new file mode 100644
index 0000000..beb777d
--- /dev/null
+++ b/patches/linux-3.8.13/0298-ASoC-AM33XX-Add-support-for-AM33xx-SoC-Audio.patch
@@ -0,0 +1,55 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Wed, 1 Aug 2012 12:04:22 +0530
+Subject: [PATCH] ASoC: AM33XX: Add support for AM33xx SoC Audio
+
+AM33xx uses same McASP IP as the Davinci Platform. This patch updates
+Kconfig and makefile to enable build or McASP, PCM & Codec drivers
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+---
+ sound/soc/davinci/Kconfig | 8 ++++++++
+ sound/soc/davinci/Makefile | 3 +++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
+index 9e11a14..cfeb3a0 100644
+--- a/sound/soc/davinci/Kconfig
++++ b/sound/soc/davinci/Kconfig
+@@ -6,6 +6,14 @@ config SND_DAVINCI_SOC
+ the DAVINCI AC97 or I2S interface. You will also need
+ to select the audio interfaces to support below.
+
++config SND_AM33XX_SOC
++ tristate "SoC Audio for the AM33XX chip"
++ depends on SOC_AM33XX
++ select SND_SOC_TLV320AIC3X
++ help
++ Say Y or M if you want to add support for SoC audio on AM33xx
++ boards using McASP and TLV320AIC3X codec.
++
+ config SND_DAVINCI_SOC_I2S
+ tristate
+
+diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
+index a93679d..3e07a53 100644
+--- a/sound/soc/davinci/Makefile
++++ b/sound/soc/davinci/Makefile
+@@ -5,8 +5,10 @@ snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
+ snd-soc-davinci-vcif-objs:= davinci-vcif.o
+
+ obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
++obj-$(CONFIG_SND_AM33XX_SOC) += snd-soc-davinci.o
+ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
+ obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
++obj-$(CONFIG_SND_AM33XX_SOC) += snd-soc-davinci-mcasp.o
+ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
+
+ # DAVINCI Machine Support
+@@ -14,6 +16,7 @@ snd-soc-evm-objs := davinci-evm.o
+ snd-soc-sffsdr-objs := davinci-sffsdr.o
+
+ obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
++obj-$(CONFIG_SND_AM33XX_SOC) += snd-soc-evm.o
+ obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
+ obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
+ obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
diff --git a/patches/linux-3.8.13/0299-am33xx-mcasp-Add-dma-channel-definitions.patch b/patches/linux-3.8.13/0299-am33xx-mcasp-Add-dma-channel-definitions.patch
new file mode 100644
index 0000000..389e5fa
--- /dev/null
+++ b/patches/linux-3.8.13/0299-am33xx-mcasp-Add-dma-channel-definitions.patch
@@ -0,0 +1,37 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 13:26:05 +0200
+Subject: [PATCH] am33xx: mcasp: Add dma channel definitions
+
+Add DMA channel definitions even though they are not used yet.
+The channels still come from hwmod but it's nice to have them
+in the DT too.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 3560959..9745507 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -682,6 +682,9 @@
+ asp-chan-q = <2>; /* EVENTQ_2 */
+ tx-dma-offset = <0x46000000>;
+ rx-dma-offset = <0x46000000>;
++ dmas = <&edma 8
++ &edma 9>;
++ dma-names = "tx", "rx";
+ };
+
+ mcasp1: mcasp@4803C000 {
+@@ -695,6 +698,9 @@
+ asp-chan-q = <2>; /* EVENTQ_2 */
+ tx-dma-offset = <0x46400000>;
+ rx-dma-offset = <0x46400000>;
++ dmas = <&edma 10
++ &edma 11>;
++ dma-names = "tx", "rx";
+ };
+
+ };
diff --git a/patches/linux-3.8.13/0300-ARM-OMAP2-AM33xx-removed-invalid-McASP-HWMOD-data.patch b/patches/linux-3.8.13/0300-ARM-OMAP2-AM33xx-removed-invalid-McASP-HWMOD-data.patch
new file mode 100644
index 0000000..78b2b26
--- /dev/null
+++ b/patches/linux-3.8.13/0300-ARM-OMAP2-AM33xx-removed-invalid-McASP-HWMOD-data.patch
@@ -0,0 +1,77 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Tue, 31 Jul 2012 19:10:20 +0530
+Subject: [PATCH] ARM: OMAP2+: AM33xx: removed invalid McASP HWMOD data
+
+McASP Data Address space is used for edma operation. Driver uses this
+address to setup edma dst/src. No Mapping is done on this address and
+hence it is not required to create a new hwmod entry
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 38 ----------------------------
+ 1 file changed, 38 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index a180336..6e80edb 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -2951,24 +2951,6 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp0 = {
+ .user = OCP_USER_MPU,
+ };
+
+-/* l3 s -> mcasp0 data */
+-static struct omap_hwmod_addr_space am33xx_mcasp0_data_addr_space[] = {
+- {
+- .pa_start = 0x46000000,
+- .pa_end = 0x46000000 + SZ_4M - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- { }
+-};
+-
+-static struct omap_hwmod_ocp_if am33xx_l3_s__mcasp0_data = {
+- .master = &am33xx_l3_s_hwmod,
+- .slave = &am33xx_mcasp0_hwmod,
+- .clk = "l3s_gclk",
+- .addr = am33xx_mcasp0_data_addr_space,
+- .user = OCP_USER_SDMA,
+-};
+-
+ /* l4 ls -> mcasp1 */
+ static struct omap_hwmod_addr_space am33xx_mcasp1_addr_space[] = {
+ {
+@@ -2987,24 +2969,6 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1 = {
+ .user = OCP_USER_MPU,
+ };
+
+-/* l3 s -> mcasp1 data */
+-static struct omap_hwmod_addr_space am33xx_mcasp1_data_addr_space[] = {
+- {
+- .pa_start = 0x46400000,
+- .pa_end = 0x46400000 + SZ_4M - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- { }
+-};
+-
+-static struct omap_hwmod_ocp_if am33xx_l3_s__mcasp1_data = {
+- .master = &am33xx_l3_s_hwmod,
+- .slave = &am33xx_mcasp1_hwmod,
+- .clk = "l3s_gclk",
+- .addr = am33xx_mcasp1_data_addr_space,
+- .user = OCP_USER_SDMA,
+-};
+-
+ /* l4 ls -> mmc0 */
+ static struct omap_hwmod_addr_space am33xx_mmc0_addr_space[] = {
+ {
+@@ -3525,9 +3489,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l4_per__i2c3,
+ &am33xx_l4_per__mailbox,
+ &am33xx_l4_ls__mcasp0,
+- &am33xx_l3_s__mcasp0_data,
+ &am33xx_l4_ls__mcasp1,
+- &am33xx_l3_s__mcasp1_data,
+ &am33xx_l4_ls__mmc0,
+ &am33xx_l4_ls__mmc1,
+ &am33xx_l3_s__mmc2,
diff --git a/patches/linux-3.8.13/0301-davinci-evm-Header-include-move-fix.patch b/patches/linux-3.8.13/0301-davinci-evm-Header-include-move-fix.patch
new file mode 100644
index 0000000..6c25ae4
--- /dev/null
+++ b/patches/linux-3.8.13/0301-davinci-evm-Header-include-move-fix.patch
@@ -0,0 +1,25 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 12:11:26 +0200
+Subject: [PATCH] davinci-evm: Header include move fix.
+
+Headers have been moved. Fix by including the correct header.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ sound/soc/davinci/davinci-evm.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+index d0fad7e..7420434 100644
+--- a/sound/soc/davinci/davinci-evm.c
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -24,8 +24,7 @@
+ #include <asm/dma.h>
+ #include <asm/mach-types.h>
+
+-#include <mach/asp.h>
+-#include <mach/edma.h>
++#include <linux/edma.h>
+
+ #include "davinci-pcm.h"
+ #include "davinci-i2s.h"
diff --git a/patches/linux-3.8.13/0302-bone-dvi-cape-Add-DT-definition-for-00A2-revision.patch b/patches/linux-3.8.13/0302-bone-dvi-cape-Add-DT-definition-for-00A2-revision.patch
new file mode 100644
index 0000000..5901513
--- /dev/null
+++ b/patches/linux-3.8.13/0302-bone-dvi-cape-Add-DT-definition-for-00A2-revision.patch
@@ -0,0 +1,23 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 12:25:42 +0200
+Subject: [PATCH] bone-dvi-cape: Add DT definition for 00A2 revision
+
+Add cape definition for the 00A2 revision of the DVI cape.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 600640a..256f8d4 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -140,6 +140,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ capes/cape-bone-2g-emmc1.dtbo \
+ capes/cape-bone-dvi-00A0.dtbo capes/cape-bone-dvi-00A1.dtbo \
++ capes/cape-bone-dvi-00A2.dtbo \
+ capes/cape-bone-lcd3-00A0.dtbo
+
+ # the geiger cape
diff --git a/patches/linux-3.8.13/0303-bone-dvi-cape-Update-A1-cape-definition-with-sound.patch b/patches/linux-3.8.13/0303-bone-dvi-cape-Update-A1-cape-definition-with-sound.patch
new file mode 100644
index 0000000..354c65c
--- /dev/null
+++ b/patches/linux-3.8.13/0303-bone-dvi-cape-Update-A1-cape-definition-with-sound.patch
@@ -0,0 +1,129 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 12:27:05 +0200
+Subject: [PATCH] bone-dvi-cape: Update A1 cape definition with sound
+
+Add sound definitions for the reworked A1 cape definition.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-dvi-00A1.dts | 74 +++++++++++++++++++++++++++++++--
+ 1 file changed, 70 insertions(+), 4 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index bd275e0..12b8526 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -9,11 +9,11 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone", "ti,beaglebone-black";
++ compatible = "ti,beaglebone";
+
+ /* identification */
+ part-number = "BB-BONE-DVID-01";
+- version = "00A1", "01";
++ version = "00A1", "A1";
+
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+@@ -28,7 +28,7 @@
+
+ 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 */
++ 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 */
+@@ -52,6 +52,16 @@
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ >;
+ };
++
++ bone_dvi_cape_audio_pins: pinmux_bone_dvi_cape_audio_pins {
++ pinctrl-single,pins = <
++ 0x190 0x20 /* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
++ 0x194 0x20 /* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
++ 0x19c 0x22 /* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
++ 0x1ac 0x22 /* mcasp0_ahclkx.mcasp0_axr3, INPUT | MODE2 */
++
++ >;
++ };
+ };
+ };
+
+@@ -129,6 +139,7 @@
+ vback-porch = <13>;
+ clock-frequency = <64000000>;
+ };
++
+ };
+ };
+
+@@ -138,9 +149,64 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio2 31 0x0>;
++ ti,power-gpio = <&gpio2 7 0x0>;
++ };
++
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c2>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
+
++ tlv320aic3x: tlv320aic3x@1b {
++ compatible = "ti,tlv320aic3x";
++ reg = <0x1b>;
++ status = "okay";
+ };
+ };
+ };
++
++ fragment@3 {
++ target = <&mcasp0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_audio_pins>;
++
++ status = "okay";
++
++ op-mode = <0>; /* MCASP_IIS_MODE */
++ tdm-slots = <2>;
++ num-serializer = <16>;
++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
++ 0 0 2 1
++ 0 0 0 0
++ 0 0 0 0
++ 0 0 0 0
++ >;
++ tx-num-evt = <1>;
++ rx-num-evt = <1>;
++ };
++ };
++
++ fragment@4 {
++ target = <&ocp>;
++ __overlay__ {
++ sound {
++ compatible = "ti,da830-evm-audio";
++ ti,model = "DA830 EVM";
++ ti,audio-codec = <&tlv320aic3x>;
++ ti,mcasp-controller = <&mcasp0>;
++ ti,codec-clock-rate = <12000000>;
++ ti,audio-routing =
++ "Headphone Jack", "HPLOUT",
++ "Headphone Jack", "HPROUT",
++ "LINE1L", "Line In",
++ "LINE1R", "Line In";
++ };
++ };
++
++ };
+ };
diff --git a/patches/linux-3.8.13/0304-sndsoc-mcasp-Get-DMA-channels-via-byname.patch b/patches/linux-3.8.13/0304-sndsoc-mcasp-Get-DMA-channels-via-byname.patch
new file mode 100644
index 0000000..5813af4
--- /dev/null
+++ b/patches/linux-3.8.13/0304-sndsoc-mcasp-Get-DMA-channels-via-byname.patch
@@ -0,0 +1,40 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 14 Jan 2013 19:57:10 +0200
+Subject: [PATCH] sndsoc: mcasp: Get DMA channels via byname
+
+Use get resource by name for DMA channels. Note that even for the
+case where we're booting with DT, they still come out of hwmod data.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ sound/soc/davinci/davinci-mcasp.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
+index 621ce30..ea292f6 100644
+--- a/sound/soc/davinci/davinci-mcasp.c
++++ b/sound/soc/davinci/davinci-mcasp.c
+@@ -1170,9 +1170,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+ mem->start);
+
+ /* first TX, then RX */
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+ if (!res) {
+- dev_err(&pdev->dev, "no DMA resource\n");
++ dev_err(&pdev->dev, "Failed to get tx dma resource\n");
+ ret = -ENODEV;
+ goto err_release_clk;
+ }
+@@ -1190,9 +1190,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+ dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
+ mem->start);
+
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
++ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+ if (!res) {
+- dev_err(&pdev->dev, "no DMA resource\n");
++ dev_err(&pdev->dev, "Failed to get rx dma resource\n");
+ ret = -ENODEV;
+ goto err_release_clk;
+ }
diff --git a/patches/linux-3.8.13/0305-sound-soc-Davinci-Remove-__devinit-__devexit.patch b/patches/linux-3.8.13/0305-sound-soc-Davinci-Remove-__devinit-__devexit.patch
new file mode 100644
index 0000000..8bceb4f
--- /dev/null
+++ b/patches/linux-3.8.13/0305-sound-soc-Davinci-Remove-__devinit-__devexit.patch
@@ -0,0 +1,33 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 14:13:53 +0200
+Subject: [PATCH] sound-soc: Davinci: Remove __devinit/__devexit
+
+__devinit/__devexit and the like has been purged. Remove them.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ sound/soc/davinci/davinci-evm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+index 7420434..349db80 100644
+--- a/sound/soc/davinci/davinci-evm.c
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -393,7 +393,7 @@ static int davinci_evm_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+-static int __devexit davinci_evm_remove(struct platform_device *pdev)
++static int davinci_evm_remove(struct platform_device *pdev)
+ {
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+@@ -404,7 +404,7 @@ static int __devexit davinci_evm_remove(struct platform_device *pdev)
+
+ static struct platform_driver davinci_evm_driver = {
+ .probe = davinci_evm_probe,
+- .remove = __devexit_p(davinci_evm_remove),
++ .remove = davinci_evm_remove,
+ .driver = {
+ .name = "davinci_evm",
+ .owner = THIS_MODULE,
diff --git a/patches/linux-3.8.13/0306-st7735fb-Remove-__devinit-__devexit.patch b/patches/linux-3.8.13/0306-st7735fb-Remove-__devinit-__devexit.patch
new file mode 100644
index 0000000..8d00aff
--- /dev/null
+++ b/patches/linux-3.8.13/0306-st7735fb-Remove-__devinit-__devexit.patch
@@ -0,0 +1,60 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 14:14:33 +0200
+Subject: [PATCH] st7735fb: Remove __devinit/__devexit
+
+__devinit/__devexit and the like has been purged. Remove them.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/video/st7735fb.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/video/st7735fb.c b/drivers/video/st7735fb.c
+index 67c2544..3a5c8a9 100644
+--- a/drivers/video/st7735fb.c
++++ b/drivers/video/st7735fb.c
+@@ -128,7 +128,7 @@ static struct st7735_function st7735_cfg_script[] = {
+ { ST7735_END, ST7735_END},
+ };
+
+-static struct fb_fix_screeninfo st7735fb_fix __devinitdata = {
++static struct fb_fix_screeninfo st7735fb_fix = {
+ .id = "ST7735",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_DIRECTCOLOR,
+@@ -139,7 +139,7 @@ static struct fb_fix_screeninfo st7735fb_fix __devinitdata = {
+ .accel = FB_ACCEL_NONE,
+ };
+
+-static struct fb_var_screeninfo st7735fb_var __devinitdata = {
++static struct fb_var_screeninfo st7735fb_var = {
+ .xres = WIDTH,
+ .yres = HEIGHT,
+ .xres_virtual = WIDTH,
+@@ -426,7 +426,7 @@ static const struct of_device_id st7735fb_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, st7735fb_dt_ids);
+
+-static int __devinit st7735fb_probe (struct spi_device *spi)
++static int st7735fb_probe (struct spi_device *spi)
+ {
+ int vmem_size = WIDTH*HEIGHT*BPP/8;
+ u8 *vmem;
+@@ -581,7 +581,7 @@ fballoc_fail:
+ return retval;
+ }
+
+-static int __devexit st7735fb_remove(struct spi_device *spi)
++static int st7735fb_remove(struct spi_device *spi)
+ {
+ struct fb_info *info = spi_get_drvdata(spi);
+
+@@ -608,7 +608,7 @@ static struct spi_driver st7735fb_driver = {
+ .of_match_table = st7735fb_dt_ids,
+ },
+ .probe = st7735fb_probe,
+- .remove = __devexit_p(st7735fb_remove),
++ .remove = st7735fb_remove,
+ };
+
+ static int __init st7735fb_init(void)
diff --git a/patches/linux-3.8.13/0307-capemgr-Remove-__devinit-__devexit.patch b/patches/linux-3.8.13/0307-capemgr-Remove-__devinit-__devexit.patch
new file mode 100644
index 0000000..35cf436
--- /dev/null
+++ b/patches/linux-3.8.13/0307-capemgr-Remove-__devinit-__devexit.patch
@@ -0,0 +1,42 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 14:15:00 +0200
+Subject: [PATCH] capemgr: Remove __devinit/__devexit
+
+__devinit/__devexit and the like has been purged. Remove them.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 651f48d..d828af7 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -1522,7 +1522,7 @@ static int bone_capemgr_loader(void *data)
+ return bone_capemgr_load(slot);
+ }
+
+-static int __devinit
++static int
+ bone_capemgr_probe(struct platform_device *pdev)
+ {
+ struct bone_capemgr_info *info;
+@@ -1748,7 +1748,7 @@ err_exit:
+ return ret;
+ }
+
+-static int __devexit bone_capemgr_remove(struct platform_device *pdev)
++static int bone_capemgr_remove(struct platform_device *pdev)
+ {
+ struct bone_capemgr_info *info = platform_get_drvdata(pdev);
+ struct bone_cape_slot *slot, *slotn;
+@@ -1818,7 +1818,7 @@ static struct dev_pm_ops bone_capemgr_pm_ops = {
+
+ static struct platform_driver bone_capemgr_driver = {
+ .probe = bone_capemgr_probe,
+- .remove = __devexit_p(bone_capemgr_remove),
++ .remove = bone_capemgr_remove,
+ .driver = {
+ .name = "bone-capemgr",
+ .owner = THIS_MODULE,
diff --git a/patches/linux-3.8.13/0308-capes-fw-target-firmware-directory-change.patch b/patches/linux-3.8.13/0308-capes-fw-target-firmware-directory-change.patch
new file mode 100644
index 0000000..099804e
--- /dev/null
+++ b/patches/linux-3.8.13/0308-capes-fw-target-firmware-directory-change.patch
@@ -0,0 +1,54 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 19:08:47 +0200
+Subject: [PATCH] capes-fw: target firmware directory change
+
+Change the target firmware directory to firmware, instead of firmware/capes.
+Two benefits; auto-firmware inclusion in the kernel image if enabled, and
+correct directory install when issuing firmware install.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 256f8d4..83b7787 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -138,20 +138,20 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+
+ # all the generic capes
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+- capes/cape-bone-2g-emmc1.dtbo \
+- capes/cape-bone-dvi-00A0.dtbo capes/cape-bone-dvi-00A1.dtbo \
+- capes/cape-bone-dvi-00A2.dtbo \
+- capes/cape-bone-lcd3-00A0.dtbo
++ cape-bone-2g-emmc1.dtbo \
++ cape-bone-dvi-00A0.dtbo cape-bone-dvi-00A1.dtbo \
++ cape-bone-dvi-00A2.dtbo \
++ cape-bone-lcd3-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+- capes/cape-bone-geiger-00A0.dtbo
++ cape-bone-geiger-00A0.dtbo
+
+ # the weather cape
+-fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += capes/cape-bone-weather-00A0.dtbo
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-weather-00A0.dtbo
+
+ # the HDMI virtual cape on the beaglebone-black
+-fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += capes/cape-boneblack-hdmi-00A0.dtbo
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-boneblack-hdmi-00A0.dtbo
+
+ fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+
+@@ -254,7 +254,7 @@ $(obj)/%.fw: $(obj)/%.H16 $(ihex2fw_dep) | $(objtree)/$(obj)/$$(dir %)
+ $(call cmd,h16tofw)
+
+ # DTBO is device tree blob object
+-$(obj)/%.dtbo: $(obj)/%.dts | $(objtree)/$(obj)/$$(dir %)
++$(obj)/%.dtbo: $(obj)/capes/%.dts | $(objtree)/$(obj)/$$(dir %)
+ $(call cmd,dtco)
+
+ $(firmware-dirs):
diff --git a/patches/linux-3.8.13/0309-am33xx-edma-Always-update-unused-channel-list.patch b/patches/linux-3.8.13/0309-am33xx-edma-Always-update-unused-channel-list.patch
new file mode 100644
index 0000000..2114a24
--- /dev/null
+++ b/patches/linux-3.8.13/0309-am33xx-edma-Always-update-unused-channel-list.patch
@@ -0,0 +1,57 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 20:03:18 +0200
+Subject: [PATCH] am33xx: edma: Always update unused channel list
+
+When using dynamically created devices the single initialization
+of the the unused channels list is wrong, so do it every time.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/common/edma.c | 27 ++++++++++++---------------
+ 1 file changed, 12 insertions(+), 15 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index beeb1d2..7654324 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -576,8 +576,6 @@ static int prepare_unused_channel_list(struct device *dev, void *data)
+
+ /*-----------------------------------------------------------------------*/
+
+-static bool unused_chan_list_done;
+-
+ /* Resource alloc/free: dma channels, parameter RAM slots */
+
+ /**
+@@ -618,19 +616,18 @@ int edma_alloc_channel(int channel,
+ 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;
+- }
++ /*
++ * 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.
++ *
++ * Note: We do this every time now, since when devices are
++ * dynamically created the old unused list must be updated.
++ */
++ ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
++ prepare_unused_channel_list);
++ if (ret < 0)
++ return ret;
+
+ if (channel >= 0) {
+ ctlr = EDMA_CTLR(channel);
diff --git a/patches/linux-3.8.13/0310-defconfig-Update-bone-default-config.patch b/patches/linux-3.8.13/0310-defconfig-Update-bone-default-config.patch
new file mode 100644
index 0000000..af8189b
--- /dev/null
+++ b/patches/linux-3.8.13/0310-defconfig-Update-bone-default-config.patch
@@ -0,0 +1,169 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 15 Jan 2013 20:06:37 +0200
+Subject: [PATCH] defconfig: Update bone default config
+
+---
+ defconfig | 72 ++++++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 38 insertions(+), 34 deletions(-)
+
+diff --git a/defconfig b/defconfig
+index 0817f18..8902d3f 100644
+--- a/defconfig
++++ b/defconfig
+@@ -1,6 +1,6 @@
+ #
+ # Automatically generated file; DO NOT EDIT.
+-# Linux/arm 3.8.0-rc2 Kernel Configuration
++# Linux/arm 3.8.0-rc3 Kernel Configuration
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+@@ -1115,7 +1115,7 @@ CONFIG_EXTRA_FIRMWARE=""
+ # CONFIG_GENERIC_CPU_DEVICES is not set
+ CONFIG_REGMAP=y
+ CONFIG_REGMAP_I2C=y
+-CONFIG_REGMAP_SPI=m
++CONFIG_REGMAP_SPI=y
+ CONFIG_REGMAP_MMIO=y
+ CONFIG_DMA_SHARED_BUFFER=y
+ # CONFIG_CMA is not set
+@@ -2166,7 +2166,7 @@ CONFIG_MFD_WL1273_CORE=m
+ # CONFIG_MFD_AS3711 is not set
+ CONFIG_REGULATOR=y
+ # CONFIG_REGULATOR_DEBUG is not set
+-# CONFIG_REGULATOR_DUMMY is not set
++CONFIG_REGULATOR_DUMMY=y
+ CONFIG_REGULATOR_FIXED_VOLTAGE=y
+ # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+ # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+@@ -2787,20 +2787,18 @@ CONFIG_LOGO_LINUX_MONO=y
+ CONFIG_LOGO_LINUX_VGA16=y
+ CONFIG_LOGO_LINUX_CLUT224=y
+ # CONFIG_FB_SSD1307 is not set
+-CONFIG_SOUND=m
++CONFIG_SOUND=y
+ 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=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_OSSEMUL=y
+-CONFIG_SND_MIXER_OSS=m
+-CONFIG_SND_PCM_OSS=m
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
+ CONFIG_SND_PCM_OSS_PLUGINS=y
+ # CONFIG_SND_HRTIMER is not set
+ # CONFIG_SND_DYNAMIC_MINORS is not set
+@@ -2823,19 +2821,16 @@ CONFIG_SND_DRIVERS=y
+ # 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_AC97_POWER_SAVE is not set
+ 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_USB is not set
++CONFIG_SND_SOC=y
++CONFIG_SND_AM33XX_SOC=y
+ # CONFIG_SND_DESIGNWARE_I2S is not set
+-CONFIG_SND_SOC_I2C_AND_SPI=m
++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
+ CONFIG_AC97_BUS=m
+@@ -2951,7 +2946,12 @@ CONFIG_USB_MON=y
+ # 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 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
+
+@@ -3019,18 +3019,18 @@ 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_KEYSPAN_MPR is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
++# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+ CONFIG_USB_SERIAL_KLSI=m
+ CONFIG_USB_SERIAL_KOBIL_SCT=m
+ CONFIG_USB_SERIAL_MCT_U232=m
+@@ -3080,6 +3080,7 @@ CONFIG_USB_CYTHERM=m
+ CONFIG_USB_IDMOUSE=m
+ CONFIG_USB_FTDI_ELAN=m
+ CONFIG_USB_APPLEDISPLAY=m
++# CONFIG_USB_SISUSBVGA is not set
+ CONFIG_USB_LD=m
+ CONFIG_USB_TRANCEVIBRATOR=m
+ CONFIG_USB_IOWARRIOR=m
+@@ -3107,6 +3108,7 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+ # 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
+@@ -3137,6 +3139,7 @@ CONFIG_USB_G_HID=m
+ 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
+@@ -3387,6 +3390,7 @@ CONFIG_TI_AM335X_ADC=y
+ # Hid Sensor IIO Common
+ #
+ CONFIG_HID_SENSOR_IIO_COMMON=m
++CONFIG_HID_SENSOR_IIO_TRIGGER=m
+ # CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS is not set
+
+ #
diff --git a/patches/linux-3.8.13/0311-capes-add-dvi-a2-and-lcd3-a2-dts-files.patch b/patches/linux-3.8.13/0311-capes-add-dvi-a2-and-lcd3-a2-dts-files.patch
new file mode 100644
index 0000000..7bf80ce
--- /dev/null
+++ b/patches/linux-3.8.13/0311-capes-add-dvi-a2-and-lcd3-a2-dts-files.patch
@@ -0,0 +1,560 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 15 Jan 2013 14:54:04 +0100
+Subject: [PATCH] capes: add dvi-a2 and lcd3-a2 dts files
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 25 +---
+ firmware/Makefile | 7 +-
+ firmware/capes/cape-bone-dvi-00A0.dts | 2 +-
+ firmware/capes/cape-bone-dvi-00A1.dts | 2 +-
+ firmware/capes/cape-bone-dvi-00A2.dts | 212 +++++++++++++++++++++++++++
+ firmware/capes/cape-bone-lcd3-00A2.dts | 226 +++++++++++++++++++++++++++++
+ 6 files changed, 450 insertions(+), 24 deletions(-)
+ create mode 100644 firmware/capes/cape-bone-dvi-00A2.dts
+ create mode 100644 firmware/capes/cape-bone-lcd3-00A2.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 7cb7a9b..bf863bd 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -25,16 +25,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&user_leds_s0 &spi1_pins_s0 &lcd_pins_s0 &gpevt_pins_s0>;
+-
+- user_leds_s0: user_leds_s0 {
+- 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 */
+- >;
+- };
++ pinctrl-0 = <&userleds_pins>;
+
+ spi1_pins_s0: spi1_pins_s0 {
+ pinctrl-single,pins = <
+@@ -44,15 +35,7 @@
+ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+ >;
+ };
+-
+- lcd_pins_s0: lcd_pins_s0 {
+- pinctrl-single,pins = <
+- 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
+- 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+- >;
+- };
+-
+- gpevt_pins_s0: gpevt_pins_s0 {
++ gpevt_pins: pinmux_gpevt_pins {
+ pinctrl-single,pins = <
+ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
+ >;
+@@ -242,6 +225,10 @@
+ version = "00A0";
+ dtbo = "cape-bone-lcd3-00A0.dtbo";
+ };
++ version@00A2 {
++ version = "00A2";
++ dtbo = "cape-bone-lcd3-00A2.dtbo";
++ };
+ };
+
+ /* Weather cape */
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 83b7787..2f14ea4 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -139,9 +139,10 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+ # all the generic capes
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-2g-emmc1.dtbo \
+- cape-bone-dvi-00A0.dtbo cape-bone-dvi-00A1.dtbo \
+- cape-bone-dvi-00A2.dtbo \
+- cape-bone-lcd3-00A0.dtbo
++ cape-bone-dvi-00A0.dtbo capes/cape-bone-dvi-00A1.dtbo \
++ cape-bone-dvi-00A2.dtbo \
++ cape-bone-lcd3-00A0.dtbo \
++ cape-bone-lcd3-00A2.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+index 988e801..a21d84e 100644
+--- a/firmware/capes/cape-bone-dvi-00A0.dts
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -139,7 +139,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio2 7 0x0>;
++ ti,power-gpio = <&gpio1 7 0x0>;
+ };
+
+ };
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index 12b8526..bb49ae6 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -149,7 +149,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio2 7 0x0>;
++ ti,power-gpio = <&gpio1 7 0x0>;
+ };
+
+ };
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+new file mode 100644
+index 0000000..84f84c4
+--- /dev/null
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -0,0 +1,212 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-DVID-01";
++ version = "00A2", "A2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ 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_00A2_pins: pinmux_bone_dvi_cape_dvi_00A2_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_audio_pins: pinmux_bone_dvi_cape_audio_pins {
++ pinctrl-single,pins = <
++ 0x190 0x20 /* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
++ 0x194 0x20 /* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
++ 0x19c 0x22 /* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
++ 0x1ac 0x22 /* mcasp0_ahclkx.mcasp0_axr3, INPUT | MODE2 */
++
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ gpio-leds-cape-dvi {
++ 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";
++ };
++ };
++
++ /* Settings for DVI 1024x768@60 */
++ panel {
++ compatible = "lcdc,panel";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A2_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ invert-line-clock = <1>;
++ invert-frm-clock = <1>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing1>;
++ timing0: 1024x768 {
++ hactive = <1024>;
++ vactive = <768>;
++ hback-porch = <80>;
++ hfront-porch = <48>;
++ vback-porch = <15>;
++ vfront-porch = <3>;
++ hsync-len = <32>;
++ vsync-len = <4>;
++ clock-frequency = <56000000>;
++ };
++ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
++ timing1: 1280x720-60 {
++ hactive = <1280>;
++ hfront-porch = <48>;
++ hsync-len = <32>;
++ hback-porch = <80>;
++ vactive = <720>;
++ vfront-porch = <3>;
++ vsync-len = <5>;
++ vback-porch = <13>;
++ clock-frequency = <64000000>;
++ };
++
++ };
++ };
++
++ fb {
++ compatible = "ti,am33xx-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio1 31 0x0>;
++ };
++
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c2>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tlv320aic3x: tlv320aic3x@1b {
++ compatible = "ti,tlv320aic3x";
++ reg = <0x1b>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&mcasp0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_audio_pins>;
++
++ status = "okay";
++
++ op-mode = <0>; /* MCASP_IIS_MODE */
++ tdm-slots = <2>;
++ num-serializer = <16>;
++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
++ 0 0 2 1
++ 0 0 0 0
++ 0 0 0 0
++ 0 0 0 0
++ >;
++ tx-num-evt = <1>;
++ rx-num-evt = <1>;
++ };
++ };
++
++ fragment@4 {
++ target = <&ocp>;
++ __overlay__ {
++ sound {
++ compatible = "ti,da830-evm-audio";
++ ti,model = "DA830 EVM";
++ ti,audio-codec = <&tlv320aic3x>;
++ ti,mcasp-controller = <&mcasp0>;
++ ti,codec-clock-rate = <12000000>;
++ ti,audio-routing =
++ "Headphone Jack", "HPLOUT",
++ "Headphone Jack", "HPROUT",
++ "LINE1L", "Line In",
++ "LINE1R", "Line In";
++ };
++ };
++
++ };
++};
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+new file mode 100644
+index 0000000..3f68434
+--- /dev/null
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -0,0 +1,226 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-LCD3-01";
++ version = "00A2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_lcd3_cape_led_00A2_pins: pinmux_bone_lcd3_cape_led_00A2_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x07 /* mcasp0_fsr.gpio3_19, OUTPUT | MODE7 */
++ >;
++ };
++
++ pwm_bl_pins: pinmux_pwm_bl_pins {
++ pinctrl-single,pins = <
++ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ 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_00A2_pins: pinmux_bone_lcd3_cape_keys_00A2_pins {
++ pinctrl-single,pins = <
++ 0x040 0x2f /* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ 0x044 0x2f /* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
++ 0x04c 0x2f /* gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
++ 0x154 0x2f /* P9_21 spi0_d0.gpio0_3 INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ ehrpwm1 {
++ status = "okay";
++ };
++
++ backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_bl_pins>;
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "LCD3";
++ 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 */
++ };
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++
++ tsc {
++ wires = <4>;
++ x-plate-resistance = <200>;
++ coordinate-readouts = <5>;
++ wire-config = <0x00 0x11 0x22 0x33>;
++ };
++
++ adc {
++ adc-channels = <4>;
++ };
++ };
++
++ gpio-leds-cape-lcd3 {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++
++ pinctrl-0 = <&bone_lcd3_cape_led_00A2_pins>;
++
++ lcd3-led0 {
++ label = "lcd3:green:usr0";
++ gpios = <&gpio4 19 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_keys_00A2_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 = <&gpio2 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio4 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 3 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++
++ /* Settings for CDTech_S035Q01 / LCD3 cape: */
++ panel {
++ compatible = "lcdc,panel";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ invert-line-clock = <1>;
++ invert-frm-clock = <1>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 320x240 {
++ hactive = <320>;
++ vactive = <240>;
++ hback-porch = <21>;
++ hfront-porch = <58>;
++ hsync-len = <47>;
++ vback-porch = <11>;
++ vfront-porch = <23>;
++ vsync-len = <2>;
++ clock-frequency = <8000000>;
++ };
++ };
++ };
++
++ fb {
++ compatible = "ti,am33xx-lcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ };
++
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0312-capemgr-catch-up-with-lcdc-tilcdc-rename.patch b/patches/linux-3.8.13/0312-capemgr-catch-up-with-lcdc-tilcdc-rename.patch
new file mode 100644
index 0000000..a10a35e
--- /dev/null
+++ b/patches/linux-3.8.13/0312-capemgr-catch-up-with-lcdc-tilcdc-rename.patch
@@ -0,0 +1,145 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 16 Jan 2013 15:00:17 +0100
+Subject: [PATCH] capemgr: catch up with lcdc->tilcdc rename
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/cape-bone-dvi-00A0.dts | 4 ++--
+ firmware/capes/cape-bone-dvi-00A1.dts | 4 ++--
+ firmware/capes/cape-bone-dvi-00A2.dts | 4 ++--
+ firmware/capes/cape-bone-lcd3-00A0.dts | 4 ++--
+ firmware/capes/cape-bone-lcd3-00A2.dts | 4 ++--
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 4 ++--
+ 6 files changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+index a21d84e..bc3d926 100644
+--- a/firmware/capes/cape-bone-dvi-00A0.dts
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -85,7 +85,7 @@
+
+ /* Settings for DVI 1024x768@60 */
+ panel {
+- compatible = "lcdc,panel";
++ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
+ panel-info {
+@@ -134,7 +134,7 @@
+ };
+
+ fb {
+- compatible = "ti,am33xx-lcdc";
++ compatible = "ti,am33xx-tilcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index bb49ae6..d36415f 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -95,7 +95,7 @@
+
+ /* Settings for DVI 1024x768@60 */
+ panel {
+- compatible = "lcdc,panel";
++ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
+ panel-info {
+@@ -144,7 +144,7 @@
+ };
+
+ fb {
+- compatible = "ti,am33xx-lcdc";
++ compatible = "ti,am33xx-tilcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+index 84f84c4..54fba3f 100644
+--- a/firmware/capes/cape-bone-dvi-00A2.dts
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -95,7 +95,7 @@
+
+ /* Settings for DVI 1024x768@60 */
+ panel {
+- compatible = "lcdc,panel";
++ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A2_pins>;
+ panel-info {
+@@ -144,7 +144,7 @@
+ };
+
+ fb {
+- compatible = "ti,am33xx-lcdc";
++ compatible = "ti,am33xx-tilcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index b0784b2..8d9482d 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -178,7 +178,7 @@
+
+ /* Settings for CDTech_S035Q01 / LCD3 cape: */
+ panel {
+- compatible = "lcdc,panel";
++ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
+ panel-info {
+@@ -214,7 +214,7 @@
+ };
+
+ fb {
+- compatible = "ti,am33xx-lcdc";
++ compatible = "ti,am33xx-tilcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index 3f68434..d78b56b 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -178,7 +178,7 @@
+
+ /* Settings for CDTech_S035Q01 / LCD3 cape: */
+ panel {
+- compatible = "lcdc,panel";
++ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
+ panel-info {
+@@ -214,7 +214,7 @@
+ };
+
+ fb {
+- compatible = "ti,am33xx-lcdc";
++ compatible = "ti,am33xx-tilcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index 4fe58d5..911cbb5 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -69,14 +69,14 @@
+ #size-cells = <1>;
+
+ hdmi {
+- compatible = "lcdc,slave";
++ compatible = "tilcdc,slave";
+ i2c = <&i2c0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ };
+
+ fb {
+- compatible = "ti,am33xx-lcdc";
++ compatible = "ti,am33xx-tilcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
diff --git a/patches/linux-3.8.13/0313-firmware-fix-dvi-a1-target.patch b/patches/linux-3.8.13/0313-firmware-fix-dvi-a1-target.patch
new file mode 100644
index 0000000..0eb0742
--- /dev/null
+++ b/patches/linux-3.8.13/0313-firmware-fix-dvi-a1-target.patch
@@ -0,0 +1,23 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 17 Jan 2013 10:26:39 +0100
+Subject: [PATCH] firmware: fix dvi a1 target
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 2f14ea4..0bcacba 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -139,7 +139,8 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+ # all the generic capes
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-2g-emmc1.dtbo \
+- cape-bone-dvi-00A0.dtbo capes/cape-bone-dvi-00A1.dtbo \
++ cape-bone-dvi-00A0.dtbo \
++ cape-bone-dvi-00A1.dtbo \
+ cape-bone-dvi-00A2.dtbo \
+ cape-bone-lcd3-00A0.dtbo \
+ cape-bone-lcd3-00A2.dtbo
diff --git a/patches/linux-3.8.13/0314-capes-remove-tda-from-hdmi-cape-lcdc-handles-it-by-t.patch b/patches/linux-3.8.13/0314-capes-remove-tda-from-hdmi-cape-lcdc-handles-it-by-t.patch
new file mode 100644
index 0000000..01f4200
--- /dev/null
+++ b/patches/linux-3.8.13/0314-capes-remove-tda-from-hdmi-cape-lcdc-handles-it-by-t.patch
@@ -0,0 +1,37 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 17 Jan 2013 23:23:17 +0100
+Subject: [PATCH] capes: remove tda from hdmi cape, lcdc handles it by the
+ looks of it
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index 911cbb5..b080907 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -44,22 +44,6 @@
+ };
+ };
+
+- fragment@1 {
+- target = <&i2c0>;
+-
+- __overlay__ {
+- /* needed to avoid gripping by DTC */
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- /* NXP TDA998x */
+- tsl2550@34 {
+- compatible = "tda998x";
+- reg = <0x34>;
+- };
+- };
+- };
+-
+ fragment@2 {
+ target = <&ocp>;
+ __overlay__ {
diff --git a/patches/linux-3.8.13/0315-tilcdc-magic-debug-statement-makes-power-gpio-work-o.patch b/patches/linux-3.8.13/0315-tilcdc-magic-debug-statement-makes-power-gpio-work-o.patch
new file mode 100644
index 0000000..bbfd769
--- /dev/null
+++ b/patches/linux-3.8.13/0315-tilcdc-magic-debug-statement-makes-power-gpio-work-o.patch
@@ -0,0 +1,29 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 18 Jan 2013 11:49:48 +0100
+Subject: [PATCH] tilcdc: magic debug statement makes power gpio work on LCD7
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index 91e8ed2..3ffa2e5 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -209,10 +209,13 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+ dev_info(&pdev->dev, "No power control GPIO\n");
+ } else {
+ gpioflags = GPIOF_DIR_OUT;
+- if (ofgpioflags & OF_GPIO_ACTIVE_LOW)
++ if (ofgpioflags & OF_GPIO_ACTIVE_LOW) {
+ gpioflags |= GPIOF_INIT_LOW;
+- else
++ dev_info(&pdev->dev, "Power GPIO active low, initial state set to low\n");
++ } else {
+ gpioflags |= GPIOF_INIT_HIGH;
++ dev_info(&pdev->dev, "Power GPIO active high, initial state set to high\n");
++ }
+ ret = devm_gpio_request_one(&pdev->dev, gpio,
+ gpioflags, "lcdc_drv:PDN");
+ if (ret != 0) {
diff --git a/patches/linux-3.8.13/0316-capemgr-add-dts-overlay-for-LCD7-00A2-cape.patch b/patches/linux-3.8.13/0316-capemgr-add-dts-overlay-for-LCD7-00A2-cape.patch
new file mode 100644
index 0000000..ab7f350
--- /dev/null
+++ b/patches/linux-3.8.13/0316-capemgr-add-dts-overlay-for-LCD7-00A2-cape.patch
@@ -0,0 +1,256 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 18 Jan 2013 11:51:10 +0100
+Subject: [PATCH] capemgr: add dts overlay for LCD7 00A2 cape
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 225 +++++++++++++++++++++++++++++++
+ 2 files changed, 227 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-LCD7-01-00A2.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 0bcacba..f8c4a9e 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -143,7 +143,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-dvi-00A1.dtbo \
+ cape-bone-dvi-00A2.dtbo \
+ cape-bone-lcd3-00A0.dtbo \
+- cape-bone-lcd3-00A2.dtbo
++ cape-bone-lcd3-00A2.dtbo \
++ BB-BONE-LCD7-01-00A2.dtbo \
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+new file mode 100644
+index 0000000..20f4cc5
+--- /dev/null
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -0,0 +1,225 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-LCD7-01";
++ version = "00A2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_lcd7_cape_led_00A2_pins: pinmux_bone_lcd7_cape_led_00A2_pins {
++ pinctrl-single,pins = <
++ 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ pwm_bl_pins: pinmux_pwm_bl_pins {
++ pinctrl-single,pins = <
++ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
++ pinctrl-single,pins = <
++ //0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 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_lcd7_cape_keys_00A2_pins: pinmux_bone_lcd7_cape_keys_00A2_pins {
++ pinctrl-single,pins = <
++ 0x040 0x2f /* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
++ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
++ 0x1a4 0x2f /* KEY_ENTER mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
++ // gpio3_16 KEY_DOWN
++ >;
++ };
++
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_bl_pins>;
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "LCD7";
++ 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 */
++ };
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++
++ tsc {
++ wires = <4>;
++ x-plate-resistance = <200>;
++ coordinate-readouts = <5>;
++ wire-config = <0x00 0x11 0x22 0x33>;
++ };
++
++ adc {
++ adc-channels = <4>;
++ };
++ };
++
++ gpio-leds-cape-lcd7 {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++
++ pinctrl-0 = <&bone_lcd7_cape_led_00A2_pins>;
++
++ lcd7-led0 {
++ label = "lcd7:green:usr0";
++ gpios = <&gpio2 28 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd7_cape_keys_00A2_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 = <&gpio2 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio4 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio4 19 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++
++ /* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */
++ panel {
++ compatible = "tilcdc,panel";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd7_cape_lcd_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ invert-line-clock = <1>;
++ invert-frm-clock = <1>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 800x480 {
++ hactive = <800>;
++ vactive = <480>;
++ hback-porch = <39>;
++ hfront-porch = <39>;
++ hsync-len = <47>;
++ vback-porch = <29>;
++ vfront-porch = <13>;
++ vsync-len = <2>;
++ clock-frequency = <30000000>;
++ };
++ };
++ };
++
++ fb {
++ compatible = "ti,am33xx-tilcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio2 31 0x0>;
++ };
++
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0317-HACK-am33xx.dtsi-enable-all-PWMs.patch b/patches/linux-3.8.13/0317-HACK-am33xx.dtsi-enable-all-PWMs.patch
new file mode 100644
index 0000000..e772a82
--- /dev/null
+++ b/patches/linux-3.8.13/0317-HACK-am33xx.dtsi-enable-all-PWMs.patch
@@ -0,0 +1,94 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 18 Jan 2013 11:15:22 +0100
+Subject: [PATCH] HACK: am33xx.dtsi: enable all PWMs
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 9745507..912cfcd 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -356,7 +356,7 @@
+ ti,hwmods = "epwmss0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- status = "disabled";
++ status = "okay";
+ ranges;
+
+ ecap0: ecap@48300100 {
+@@ -364,7 +364,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48300100 0x80>;
+ ti,hwmods = "ecap0";
+- status = "disabled";
++ status = "okay";
+ };
+
+ ehrpwm0: ehrpwm@48300200 {
+@@ -372,7 +372,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48300200 0x80>;
+ ti,hwmods = "ehrpwm0";
+- status = "disabled";
++ status = "okay";
+ tbclkgating;
+ };
+ };
+@@ -386,7 +386,7 @@
+ ti,hwmods = "epwmss1";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- status = "disabled";
++ status = "okay";
+ ranges;
+
+ ecap1: ecap@48302100 {
+@@ -394,7 +394,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48302100 0x80>;
+ ti,hwmods = "ecap1";
+- status = "disabled";
++ status = "okay";
+ };
+
+ ehrpwm1: ehrpwm@48302200 {
+@@ -402,7 +402,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48302200 0x80>;
+ ti,hwmods = "ehrpwm1";
+- status = "disabled";
++ status = "okay";
+ tbclkgating;
+ };
+ };
+@@ -416,7 +416,7 @@
+ ti,hwmods = "epwmss2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- status = "disabled";
++ status = "okay";
+ ranges;
+
+ ecap2: ecap@48304100 {
+@@ -424,7 +424,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48304100 0x80>;
+ ti,hwmods = "ecap2";
+- status = "disabled";
++ status = "okay";
+ };
+
+ ehrpwm2: ehrpwm@48304200 {
+@@ -432,7 +432,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48304200 0x80>;
+ ti,hwmods = "ehrpwm2";
+- status = "disabled";
++ status = "okay";
+ tbclkgating;
+ };
+ };
diff --git a/patches/linux-3.8.13/0318-beaglebone-Add-nixie-cape-prototype-driver.patch b/patches/linux-3.8.13/0318-beaglebone-Add-nixie-cape-prototype-driver.patch
new file mode 100644
index 0000000..fdba822
--- /dev/null
+++ b/patches/linux-3.8.13/0318-beaglebone-Add-nixie-cape-prototype-driver.patch
@@ -0,0 +1,447 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 22 Jan 2013 10:09:47 -0800
+Subject: [PATCH] beaglebone: Add nixie cape prototype driver
+
+Add support for nixie cape breadboard prototype.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/misc/cape/beaglebone/Kconfig | 9 +
+ drivers/misc/cape/beaglebone/Makefile | 1 +
+ drivers/misc/cape/beaglebone/cape-bone-nixie.c | 401 ++++++++++++++++++++++++
+ 3 files changed, 411 insertions(+)
+ create mode 100644 drivers/misc/cape/beaglebone/cape-bone-nixie.c
+
+diff --git a/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig
+index ebeedce..8d4f73e 100644
+--- a/drivers/misc/cape/beaglebone/Kconfig
++++ b/drivers/misc/cape/beaglebone/Kconfig
+@@ -16,3 +16,12 @@ config CAPE_BEAGLEBONE_GEIGER
+ default n
+ help
+ Say Y here to include support for the Geiger Cape
++
++
++config CAPE_BEAGLEBONE_NIXIE
++ tristate "Beaglebone Nixie Cape"
++ depends on CAPE_BEAGLEBONE
++ default n
++ help
++ Say Y here to include support for the Nixie Cape
++
+diff --git a/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile
+index b79ace4..808fe14 100644
+--- a/drivers/misc/cape/beaglebone/Makefile
++++ b/drivers/misc/cape/beaglebone/Makefile
+@@ -4,3 +4,4 @@
+
+ obj-$(CONFIG_CAPE_BEAGLEBONE) += capemgr.o
+ obj-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += cape-bone-geiger.o
++obj-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += cape-bone-nixie.o
+diff --git a/drivers/misc/cape/beaglebone/cape-bone-nixie.c b/drivers/misc/cape/beaglebone/cape-bone-nixie.c
+new file mode 100644
+index 0000000..7adfdc9
+--- /dev/null
++++ b/drivers/misc/cape/beaglebone/cape-bone-nixie.c
+@@ -0,0 +1,401 @@
++/*
++ * Driver for beaglebone Nixie cape
++ *
++ * Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
++ *
++ * Based on original work by
++ * 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/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <asm/barrier.h>
++#include <linux/pwm.h>
++#include <linux/leds.h>
++
++enum {
++ BLANK_PWM_CHAN = 0,
++ BOOST_PWM_CHAN = 1,
++};
++
++struct bone_nixie_info {
++ struct platform_device *pdev;
++ struct pwm_device *pwm_dev;
++ struct led_trigger *run_led; /* running */
++
++ int pwm_frequency;
++ int pwm_duty_cycle;
++ int pwm_period;
++ int brightness;
++ int run;
++};
++
++static const struct of_device_id bonenixie_of_match[] = {
++ {
++ .compatible = "bone-cape-nixie",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bonenixie_of_match);
++
++/*
++ * XXX: PWM subsystem doesn't allow easily selecting multiple channels on
++ * the same chip... so we hack it.. this shouldn't be here long term
++ */
++
++static void nixie_pwm_config(struct bone_nixie_info *info,
++ int duty, int chan)
++{
++ struct pwm_device *pwm = info->pwm_dev;
++
++ duty = (info->pwm_period * duty) / 100;
++
++ pwm->hwpwm = chan;
++ pwm_config(pwm, duty, info->pwm_period);
++
++ pwm->chip->ops->enable(pwm->chip, pwm);
++}
++
++static void nixie_pwm_disable(struct pwm_device *pwm, int chan)
++{
++ pwm->hwpwm = chan;
++ pwm->chip->ops->disable(pwm->chip, pwm);
++}
++
++static int bonenixie_start(struct platform_device *pdev)
++{
++ struct bone_nixie_info *info = platform_get_drvdata(pdev);
++ int duty;
++
++ if (info->run != 0)
++ return 0;
++
++ /* checks */
++ if (info->pwm_frequency < 1000 || info->pwm_frequency > 50000) {
++ dev_err(&pdev->dev, "Cowardly refusing to use a "
++ "frequency of %d\n",
++ info->pwm_frequency);
++ return -EINVAL;
++ }
++ if (info->pwm_duty_cycle > 80) {
++ dev_err(&pdev->dev, "Cowardly refusing to use a "
++ "duty cycle of %d\n",
++ info->pwm_duty_cycle);
++ return -EINVAL;
++ }
++
++ info->pwm_period = div_u64(1000000000LLU, info->pwm_frequency);
++ duty = (info->pwm_period * info->pwm_duty_cycle) / 100;
++
++ dev_info(&pdev->dev, "starting nixie tube with "
++ " boost converter duty=%duns period=%dus"
++ " default brightness percent=%d\n",
++ duty, info->pwm_period, info->brightness);
++
++ nixie_pwm_config(info, 100 - info->brightness, BLANK_PWM_CHAN);
++ nixie_pwm_config(info, info->pwm_duty_cycle, BOOST_PWM_CHAN);
++
++ info->run = 1;
++ led_trigger_event(info->run_led, LED_FULL);
++
++ return 0;
++}
++
++static int bonenixie_stop(struct platform_device *pdev)
++{
++ struct bone_nixie_info *info = platform_get_drvdata(pdev);
++
++ if (info->run == 0)
++ return 0;
++
++ dev_info(&pdev->dev, "disabling nixie tube\n");
++
++ nixie_pwm_config(info, 0, BLANK_PWM_CHAN); /* 0% duty cycle */
++ nixie_pwm_disable(info->pwm_dev, BLANK_PWM_CHAN);
++
++ nixie_pwm_config(info, 0, BOOST_PWM_CHAN); /* 0% duty cycle */
++ nixie_pwm_disable(info->pwm_dev, BOOST_PWM_CHAN);
++
++ info->run = 0;
++ led_trigger_event(info->run_led, LED_OFF);
++
++ return 0;
++}
++
++static ssize_t bonenixie_show_brightness(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_nixie_info *info = platform_get_drvdata(pdev);
++
++ return sprintf(buf, "%d\n", info->brightness);
++}
++
++
++static ssize_t bonenixie_store_brightness(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_nixie_info *info = platform_get_drvdata(pdev);
++ int brightness;
++
++ if (sscanf(buf, "%d", &brightness) != 1)
++ return -EINVAL;
++
++ if (brightness < 0 || brightness > 100)
++ return -EINVAL;
++
++ info->brightness = brightness;
++ nixie_pwm_config(info, 100 - brightness, BLANK_PWM_CHAN);
++
++ return count;
++}
++
++
++static ssize_t bonenixie_show_run(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_nixie_info *info = platform_get_drvdata(pdev);
++
++ return sprintf(buf, "%d\n", info->run);
++}
++
++
++static ssize_t bonenixie_store_run(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ int run, err;
++
++ if (sscanf(buf, "%i", &run) != 1)
++ return -EINVAL;
++
++ if (run)
++ err = bonenixie_start(pdev);
++ else
++ err = bonenixie_stop(pdev);
++
++ return err ? err : count;
++}
++
++static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR,
++ bonenixie_show_brightness, bonenixie_store_brightness);
++
++static DEVICE_ATTR(run, S_IRUGO | S_IWUSR,
++ bonenixie_show_run, bonenixie_store_run);
++
++static int bonenixie_sysfs_register(struct platform_device *pdev)
++{
++ int err;
++
++ err = device_create_file(&pdev->dev, &dev_attr_run);
++ if (err != 0)
++ goto err_no_run;
++
++ err = device_create_file(&pdev->dev, &dev_attr_brightness);
++ if (err != 0)
++ goto err_no_brightness;
++
++ return 0;
++
++err_no_brightness:
++ device_remove_file(&pdev->dev, &dev_attr_run);
++err_no_run:
++ return err;
++}
++
++static void bonenixie_sysfs_unregister(struct platform_device *pdev)
++{
++ device_remove_file(&pdev->dev, &dev_attr_brightness);
++ device_remove_file(&pdev->dev, &dev_attr_run);
++}
++
++static int bonenixie_probe(struct platform_device *pdev)
++{
++ struct bone_nixie_info *info;
++ struct pinctrl *pinctrl;
++ struct device_node *pnode = pdev->dev.of_node;
++ phandle phandle;
++ u32 val;
++ int err;
++
++ /* we only support OF */
++ if (pnode == NULL) {
++ dev_err(&pdev->dev, "No platform of_node!\n");
++ return -ENODEV;
++ }
++
++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate info\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ platform_set_drvdata(pdev, info);
++ info->pdev = pdev;
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ err = of_property_read_u32(pnode, "pwms", &val);
++ if (err != 0) {
++ dev_err(&pdev->dev, "unable to read pwm handle\n");
++ goto err_no_pwm;
++ }
++ phandle = val;
++
++ info->pwm_dev = of_pwm_request(pnode, NULL);
++ if (IS_ERR(info->pwm_dev)) {
++ dev_err(&pdev->dev, "unable to request PWM\n");
++ err = PTR_ERR(info->pwm_dev);
++ goto err_no_pwm;
++ }
++
++ if (of_property_read_u32(pnode, "pwm-frequency", &val) != 0) {
++ val = 9250;
++ dev_warn(&pdev->dev, "Could not read pwm-frequency property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_frequency = val;
++
++ if (of_property_read_u32(pnode, "pwm-duty-cycle", &val) != 0) {
++ val = 35;
++ dev_warn(&pdev->dev, "Could not read pwm-duty-cycle property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_duty_cycle = val;
++
++ if (of_property_read_u32(pnode, "default-brightness", &val) != 0) {
++ val = 80;
++ dev_warn(&pdev->dev, "Could not read default-brightness property; "
++ "using default %u\n",
++ val);
++ }
++ info->brightness = val;
++
++ err = bonenixie_sysfs_register(pdev);
++ if (err != 0) {
++ dev_err(&pdev->dev, "unable to register sysfs\n");
++ goto err_no_sysfs;
++ }
++
++ led_trigger_register_simple("nixie-run", &info->run_led);
++ led_trigger_event(info->run_led, LED_OFF);
++
++ dev_info(&pdev->dev, "ready\n");
++
++ err = bonenixie_start(pdev);
++ if (err != 0) {
++ dev_err(&pdev->dev, "Could not start nixie device\n");
++ goto err_no_start;
++ }
++
++ return 0;
++
++err_no_start:
++ led_trigger_unregister_simple(info->run_led);
++ bonenixie_sysfs_unregister(pdev);
++err_no_sysfs:
++ /* fall-through */
++err_no_pwm:
++ devm_kfree(&pdev->dev, info);
++err_no_mem:
++ return err;
++}
++
++static int bonenixie_remove(struct platform_device *pdev)
++{
++ struct bone_nixie_info *info = platform_get_drvdata(pdev);
++
++ dev_info(&pdev->dev, "Remove nixie cape driver...\n");
++
++ bonenixie_stop(pdev);
++
++ led_trigger_unregister_simple(info->run_led);
++ bonenixie_sysfs_unregister(pdev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++#ifdef CONFIG_PM_RUNTIME
++static int bonenixie_runtime_suspend(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_nixie_info *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++
++static int bonenixie_runtime_resume(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_nixie_info *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++#endif /* CONFIG_PM_RUNTIME */
++
++static struct dev_pm_ops bonenixie_pm_ops = {
++ SET_RUNTIME_PM_OPS(bonenixie_runtime_suspend,
++ bonenixie_runtime_resume, NULL)
++};
++#define BONENIXIE_PM_OPS (&bonenixie_pm_ops)
++#else
++#define BONENIXIE_PM_OPS NULL
++#endif /* CONFIG_PM */
++
++
++struct platform_driver bonenixie_driver = {
++ .probe = bonenixie_probe,
++ .remove = bonenixie_remove,
++ .driver = {
++ .name = "bone-cape-nixie",
++ .owner = THIS_MODULE,
++ .pm = BONENIXIE_PM_OPS,
++ .of_match_table = bonenixie_of_match,
++ },
++};
++
++module_platform_driver(bonenixie_driver);
++
++MODULE_AUTHOR("Matt Ranostay");
++MODULE_DESCRIPTION("Beaglebone nixie cape");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-nixie-cape");
diff --git a/patches/linux-3.8.13/0319-beaglebone-Add-nixie-cape-device-tree-entry.patch b/patches/linux-3.8.13/0319-beaglebone-Add-nixie-cape-device-tree-entry.patch
new file mode 100644
index 0000000..1a4b9aa
--- /dev/null
+++ b/patches/linux-3.8.13/0319-beaglebone-Add-nixie-cape-device-tree-entry.patch
@@ -0,0 +1,179 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 22 Jan 2013 10:09:48 -0800
+Subject: [PATCH] beaglebone: Add nixie cape device tree entry
+
+Added nixie dt overlays, PWM, and leds definitions to am355x-bone-common
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 19 +++++
+ firmware/Makefile | 4 ++
+ firmware/capes/cape-bone-nixie-00A0.dts | 107 +++++++++++++++++++++++++++++
+ 3 files changed, 130 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-nixie-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index bf863bd..c45daa2 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -181,6 +181,17 @@
+ manufacturer = "Texas Instruments";
+ part-number = "BB-BONELT-HDMI";
+ };
++
++ /* Nixie cape version A0 without an EEPROM */
++ slot@7 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-Nixie";
++ version = "00A0";
++ manufacturer = "Ranostay Industries";
++ part-number = "BB-BONE-NIXIE";
++ };
++
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -249,6 +260,14 @@
+ };
+ };
+
++ /* nixie cape */
++ cape@6 {
++ part-number = "BB-BONE-NIXIE";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-nixie-00A0.dtbo";
++ };
++ };
+ };
+ };
+ };
+diff --git a/firmware/Makefile b/firmware/Makefile
+index f8c4a9e..efe2b90 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -150,6 +150,10 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+ cape-bone-geiger-00A0.dtbo
+
++# the nixie cape
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += \
++ cape-bone-nixie-00A0.dtbo
++
+ # the weather cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-weather-00A0.dtbo
+
+diff --git a/firmware/capes/cape-bone-nixie-00A0.dts b/firmware/capes/cape-bone-nixie-00A0.dts
+new file mode 100644
+index 0000000..7ec2c46
+--- /dev/null
++++ b/firmware/capes/cape-bone-nixie-00A0.dts
+@@ -0,0 +1,107 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-NIXIE";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_nixie_cape_led_pins: pinmux_bone_nixie_cape_led_pins {
++ pinctrl-single,pins = <
++ 0x1ac 0x07 /* mcasp0_ahclkx.gpio3_21, MODE7 */
++ >;
++ };
++
++ bone_nixie_cape_pins: pinmux_bone_nixie_cape_pins {
++ pinctrl-single,pins = <
++ 0x0a0 0x03 /* lcd_data0.gpio2_6 | MODE3 */
++ 0x0a4 0x03 /* lcd_data1.gpio2_7 | MODE3 */
++ >;
++ };
++
++ pruss_pins: pinmux_pruss_pins {
++ pinctrl-single,pins = <
++ 0x190 0x05 /* mcasp0_aclkx.pr1_pru0_pru_r30_0, MODE5 | DATA */
++ 0x194 0x05 /* mcasp0_fsx.pr1_pru0_pru_r30_1, MODE5 | LATCH */
++ 0x1a4 0x05 /* mcasp0_fsr.pr1_pru1_pru_r30_5, MODE5 | CLK */
++ >;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&epwmss2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&ehrpwm2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
++ target = <&ocp>;
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ gpio-leds-cape-nixie {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_nixie_cape_led_pins>;
++
++ nixie-led0 {
++ label = "nixie:green:usr0";
++ gpios = <&gpio4 21 0>;
++ linux,default-trigger = "nixie-run";
++ default-state = "off";
++ };
++ };
++
++ bone-cape-nixie {
++ compatible = "bone-cape-nixie";
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_nixie_cape_pins>;
++
++ pwms = <&ehrpwm2 0 500000 0>;
++ pwm-names = "bone-nixie-cape";
++
++ pwm-frequency = <9250>; /* 9.250KHz */
++ pwm-duty-cycle = <35>; /* 35% */
++
++ default-brightness = <35>; /* 35% */
++ };
++ };
++ };
++
++ fragment@4 {
++ target = <&pruss>;
++ __overlay__ {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pruss_pins>;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0320-am335x-bone-common.dtsi-Cleanup-test-remnants.patch b/patches/linux-3.8.13/0320-am335x-bone-common.dtsi-Cleanup-test-remnants.patch
new file mode 100644
index 0000000..83f10f7
--- /dev/null
+++ b/patches/linux-3.8.13/0320-am335x-bone-common.dtsi-Cleanup-test-remnants.patch
@@ -0,0 +1,52 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 18 Jan 2013 14:10:49 +0200
+Subject: [PATCH] am335x-bone-common.dtsi: Cleanup test remnants
+
+Cleanup various test remnants.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index c45daa2..4787d8c 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -35,11 +35,6 @@
+ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+ >;
+ };
+- 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 */
+@@ -67,10 +62,6 @@
+ status = "okay";
+ };
+
+- uart5: serial@481a8000 {
+- status = "okay";
+- };
+-
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+@@ -105,13 +96,6 @@
+ };
+ };
+
+- gpevt {
+- compatible = "gpevt";
+- dmas = <&edma 12>;
+- dma-names = "gpioevt";
+- gpio-evt = <&gpio3 2 0>;
+- };
+-
+ rtc@44e3e000 {
+ ti,system-power-controller;
+ };
diff --git a/patches/linux-3.8.13/0321-omap_hsmmc-Add-ti-vcc-aux-disable-is-sleep-DT-proper.patch b/patches/linux-3.8.13/0321-omap_hsmmc-Add-ti-vcc-aux-disable-is-sleep-DT-proper.patch
new file mode 100644
index 0000000..71e61f7
--- /dev/null
+++ b/patches/linux-3.8.13/0321-omap_hsmmc-Add-ti-vcc-aux-disable-is-sleep-DT-proper.patch
@@ -0,0 +1,25 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 18 Jan 2013 15:44:44 +0200
+Subject: [PATCH] omap_hsmmc: Add ti,vcc-aux-disable-is-sleep DT property
+
+This exposes the vcc_aux_disable_is_sleep property to DT users.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 1f29d67..7a35c8e 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1785,6 +1785,9 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
+ pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
+
++ if (of_find_property(np, "ti,vcc-aux-disable-is-sleep", NULL))
++ pdata->slots[0].vcc_aux_disable_is_sleep = 1;
++
+ return pdata;
+ }
+ #else
diff --git a/patches/linux-3.8.13/0322-bone-common-ti-vcc-aux-disable-is-sleep-enable.patch b/patches/linux-3.8.13/0322-bone-common-ti-vcc-aux-disable-is-sleep-enable.patch
new file mode 100644
index 0000000..bae5ab7
--- /dev/null
+++ b/patches/linux-3.8.13/0322-bone-common-ti-vcc-aux-disable-is-sleep-enable.patch
@@ -0,0 +1,36 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 18 Jan 2013 15:46:52 +0200
+Subject: [PATCH] bone-common: ti,vcc-aux-disable-is-sleep enable
+
+Enable vcc-aux-disable-is-sleep on both MMC interfaces.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 1 +
+ firmware/capes/cape-bone-2g-emmc1.dts | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 4787d8c..96bce02 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -359,6 +359,7 @@
+ &mmc1 {
+ status = "okay";
+ vmmc-supply = <&ldo3_reg>;
++ ti,vcc-aux-disable-is-sleep;
+ };
+
+ &edma {
+diff --git a/firmware/capes/cape-bone-2g-emmc1.dts b/firmware/capes/cape-bone-2g-emmc1.dts
+index c81a986..e2a4a46 100644
+--- a/firmware/capes/cape-bone-2g-emmc1.dts
++++ b/firmware/capes/cape-bone-2g-emmc1.dts
+@@ -48,6 +48,7 @@
+ ti,non-removable;
+ status = "okay";
+ reset-gpios = <&gpio2 20 1>; /* active low */
++ ti,vcc-aux-disable-is-sleep;
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0323-am33xx-disable-NAPI.patch b/patches/linux-3.8.13/0323-am33xx-disable-NAPI.patch
new file mode 100644
index 0000000..68b7275
--- /dev/null
+++ b/patches/linux-3.8.13/0323-am33xx-disable-NAPI.patch
@@ -0,0 +1,21 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 24 Jan 2013 15:35:12 +0100
+Subject: [PATCH] am33xx: disable NAPI
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 912cfcd..4b20654 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -525,6 +525,7 @@
+ */
+ interrupts = <40 41 42 43>;
+ ranges;
++ disable-napi;
+
+ davinci_mdio: mdio@4a101000 {
+ compatible = "ti,davinci_mdio";
diff --git a/patches/linux-3.8.13/0324-capemgr-Fixed-AIN-name-display-in-error-message.patch b/patches/linux-3.8.13/0324-capemgr-Fixed-AIN-name-display-in-error-message.patch
new file mode 100644
index 0000000..005660d
--- /dev/null
+++ b/patches/linux-3.8.13/0324-capemgr-Fixed-AIN-name-display-in-error-message.patch
@@ -0,0 +1,25 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Sat, 26 Jan 2013 22:31:12 -0800
+Subject: [PATCH] capemgr: Fixed AIN name display in error message
+
+AIN5 was harded in error message instead of using info->vsense_name
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/misc/cape/beaglebone/cape-bone-geiger.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/misc/cape/beaglebone/cape-bone-geiger.c b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
+index 1e50594..6be383e 100644
+--- a/drivers/misc/cape/beaglebone/cape-bone-geiger.c
++++ b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
+@@ -385,7 +385,8 @@ static int bonegeiger_probe(struct platform_device *pdev)
+
+ info->vsense_channel = iio_channel_get(NULL, info->vsense_name);
+ if (IS_ERR(info->vsense_channel)) {
+- dev_err(&pdev->dev, "Could not get AIN5 analog input\n");
++ dev_err(&pdev->dev, "Could not get %s analog input\n",
++ info->vsense_name);
+ err = PTR_ERR(info->vsense_channel);
+ goto err_no_vsense;
+ }
diff --git a/patches/linux-3.8.13/0325-am33xx.dtsi-remove-duplicate-nodes.patch b/patches/linux-3.8.13/0325-am33xx.dtsi-remove-duplicate-nodes.patch
new file mode 100644
index 0000000..f69f291
--- /dev/null
+++ b/patches/linux-3.8.13/0325-am33xx.dtsi-remove-duplicate-nodes.patch
@@ -0,0 +1,110 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 28 Jan 2013 14:38:49 +0100
+Subject: [PATCH] am33xx.dtsi: remove duplicate nodes
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 90 -----------------------------------------
+ 1 file changed, 90 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 4b20654..b4b62af 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -347,96 +347,6 @@
+ ti,timer-pwm;
+ };
+
+- epwmss0: epwmss@48300000 {
+- compatible = "ti,am33xx-pwmss";
+- reg = <0x48300000 0x10
+- 0x48300100 0x80
+- 0x48300180 0x80
+- 0x48300200 0x80>;
+- ti,hwmods = "epwmss0";
+- #address-cells = <1>;
+- #size-cells = <1>;
+- status = "okay";
+- ranges;
+-
+- ecap0: ecap@48300100 {
+- compatible = "ti,am33xx-ecap";
+- #pwm-cells = <3>;
+- reg = <0x48300100 0x80>;
+- ti,hwmods = "ecap0";
+- status = "okay";
+- };
+-
+- ehrpwm0: ehrpwm@48300200 {
+- compatible = "ti,am33xx-ehrpwm";
+- #pwm-cells = <3>;
+- reg = <0x48300200 0x80>;
+- ti,hwmods = "ehrpwm0";
+- status = "okay";
+- tbclkgating;
+- };
+- };
+-
+- epwmss1: epwmss@48302000 {
+- compatible = "ti,am33xx-pwmss";
+- reg = <0x48302000 0x10
+- 0x48302100 0x80
+- 0x48302180 0x80
+- 0x48302200 0x80>;
+- ti,hwmods = "epwmss1";
+- #address-cells = <1>;
+- #size-cells = <1>;
+- status = "okay";
+- ranges;
+-
+- ecap1: ecap@48302100 {
+- compatible = "ti,am33xx-ecap";
+- #pwm-cells = <3>;
+- reg = <0x48302100 0x80>;
+- ti,hwmods = "ecap1";
+- status = "okay";
+- };
+-
+- ehrpwm1: ehrpwm@48302200 {
+- compatible = "ti,am33xx-ehrpwm";
+- #pwm-cells = <3>;
+- reg = <0x48302200 0x80>;
+- ti,hwmods = "ehrpwm1";
+- status = "okay";
+- tbclkgating;
+- };
+- };
+-
+- epwmss2: epwmss@48304000 {
+- compatible = "ti,am33xx-pwmss";
+- reg = <0x48304000 0x10
+- 0x48304100 0x80
+- 0x48304180 0x80
+- 0x48304200 0x80>;
+- ti,hwmods = "epwmss2";
+- #address-cells = <1>;
+- #size-cells = <1>;
+- status = "okay";
+- ranges;
+-
+- ecap2: ecap@48304100 {
+- compatible = "ti,am33xx-ecap";
+- #pwm-cells = <3>;
+- reg = <0x48304100 0x80>;
+- ti,hwmods = "ecap2";
+- status = "okay";
+- };
+-
+- ehrpwm2: ehrpwm@48304200 {
+- compatible = "ti,am33xx-ehrpwm";
+- #pwm-cells = <3>;
+- reg = <0x48304200 0x80>;
+- ti,hwmods = "ehrpwm2";
+- status = "okay";
+- tbclkgating;
+- };
+- };
+-
+ rtc@44e3e000 {
+ compatible = "ti,da830-rtc";
+ reg = <0x44e3e000 0x1000>;
diff --git a/patches/linux-3.8.13/0326-cape-dtbos-update-to-latest-OF-videomode-bindings.patch b/patches/linux-3.8.13/0326-cape-dtbos-update-to-latest-OF-videomode-bindings.patch
new file mode 100644
index 0000000..0ab6d82
--- /dev/null
+++ b/patches/linux-3.8.13/0326-cape-dtbos-update-to-latest-OF-videomode-bindings.patch
@@ -0,0 +1,77 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 28 Jan 2013 16:11:27 +0100
+Subject: [PATCH] cape dtbos: update to latest OF videomode bindings
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 4 ++--
+ firmware/capes/cape-bone-lcd3-00A0.dts | 4 ++--
+ firmware/capes/cape-bone-lcd3-00A2.dts | 4 ++--
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index 20f4cc5..da0e43f 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -188,8 +188,6 @@
+ tft-alt-mode = <0>;
+ stn-565-mode = <0>;
+ mono-8bit-mode = <0>;
+- invert-line-clock = <1>;
+- invert-frm-clock = <1>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+@@ -207,6 +205,8 @@
+ vfront-porch = <13>;
+ vsync-len = <2>;
+ clock-frequency = <30000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+ };
+ };
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index 8d9482d..899f7c9 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -190,8 +190,6 @@
+ tft-alt-mode = <0>;
+ stn-565-mode = <0>;
+ mono-8bit-mode = <0>;
+- invert-line-clock = <1>;
+- invert-frm-clock = <1>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+@@ -209,6 +207,8 @@
+ vfront-porch = <23>;
+ vsync-len = <2>;
+ clock-frequency = <8000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+ };
+ };
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index d78b56b..d4f5ac2 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -190,8 +190,6 @@
+ tft-alt-mode = <0>;
+ stn-565-mode = <0>;
+ mono-8bit-mode = <0>;
+- invert-line-clock = <1>;
+- invert-frm-clock = <1>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+@@ -209,6 +207,8 @@
+ vfront-porch = <23>;
+ vsync-len = <2>;
+ clock-frequency = <8000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0327-beaglebone-uncomment-eMMC-override.patch b/patches/linux-3.8.13/0327-beaglebone-uncomment-eMMC-override.patch
new file mode 100644
index 0000000..7efc511
--- /dev/null
+++ b/patches/linux-3.8.13/0327-beaglebone-uncomment-eMMC-override.patch
@@ -0,0 +1,36 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 29 Jan 2013 15:06:00 +0100
+Subject: [PATCH] beaglebone: uncomment eMMC override
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 96bce02..23a8b01 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -137,14 +137,14 @@
+ };
+
+ /* Beaglebone black has it soldered on */
+- // slot@4 {
+- // ti,cape-override;
+- // compatible = "ti,beaglebone-black";
+- // board-name = "Bone-LT-eMMC-2G";
+- // version = "00A0";
+- // manufacturer = "Texas Instruments";
+- // part-number = "BB-BONE-EMMC-2G";
+- // };
++ slot@4 {
++ ti,cape-override;
++ compatible = "ti,beaglebone-black";
++ board-name = "Bone-LT-eMMC-2G";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONE-EMMC-2G";
++ };
+
+ /* geiger cape version A0 without an EEPROM */
+ slot@5 {
diff --git a/patches/linux-3.8.13/0328-bone-capes-Update-with-new-tscadc-bindings.patch b/patches/linux-3.8.13/0328-bone-capes-Update-with-new-tscadc-bindings.patch
new file mode 100644
index 0000000..c9279d2
--- /dev/null
+++ b/patches/linux-3.8.13/0328-bone-capes-Update-with-new-tscadc-bindings.patch
@@ -0,0 +1,111 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 15:38:19 +0200
+Subject: [PATCH] bone-capes: Update with new tscadc bindings
+
+Update the capes with the new driver bindings.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 11 ++++++-----
+ firmware/capes/cape-bone-geiger-00A0.dts | 3 ++-
+ firmware/capes/cape-bone-lcd3-00A0.dts | 11 ++++++-----
+ firmware/capes/cape-bone-lcd3-00A2.dts | 11 ++++++-----
+ 4 files changed, 20 insertions(+), 16 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index da0e43f..5a9a5f9 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -97,16 +97,17 @@
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ ti,hwmods = "adc_tsc";
++ status = "okay";
+
+ tsc {
+- wires = <4>;
+- x-plate-resistance = <200>;
+- coordinate-readouts = <5>;
+- wire-config = <0x00 0x11 0x22 0x33>;
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,coordinate-readouts = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
+ };
+
+ adc {
+- adc-channels = <4>;
++ ti,adc-channels = <4 5 6 7>;
+ };
+ };
+
+diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
+index 39e7d38..89417fb 100644
+--- a/firmware/capes/cape-bone-geiger-00A0.dts
++++ b/firmware/capes/cape-bone-geiger-00A0.dts
+@@ -86,9 +86,10 @@
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ ti,hwmods = "adc_tsc";
++ status = "okay";
+
+ adc {
+- adc-channels = <0 1 2 3 4 5 6 7>;
++ ti,adc-channels = <0 1 2 3 4 5 6 7>;
+ };
+ };
+
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index 899f7c9..ca31bc3 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -93,16 +93,17 @@
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ ti,hwmods = "adc_tsc";
++ status = "okay";
+
+ tsc {
+- wires = <4>;
+- x-plate-resistance = <200>;
+- coordinate-readouts = <5>;
+- wire-config = <0x00 0x11 0x22 0x33>;
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,coordinate-readouts = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
+ };
+
+ adc {
+- adc-channels = <4>;
++ ti,adc-channels = <4 5 6 7>;
+ };
+ };
+
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index d4f5ac2..efa2d10 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -99,16 +99,17 @@
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ ti,hwmods = "adc_tsc";
++ status = "okay";
+
+ tsc {
+- wires = <4>;
+- x-plate-resistance = <200>;
+- coordinate-readouts = <5>;
+- wire-config = <0x00 0x11 0x22 0x33>;
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,coordinate-readouts = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
+ };
+
+ adc {
+- adc-channels = <4>;
++ ti,adc-channels = <4 5 6 7>;
+ };
+ };
+
diff --git a/patches/linux-3.8.13/0329-am33xx.dtsi-Update-and-disable-status-of-nodes.patch b/patches/linux-3.8.13/0329-am33xx.dtsi-Update-and-disable-status-of-nodes.patch
new file mode 100644
index 0000000..98b9d5d
--- /dev/null
+++ b/patches/linux-3.8.13/0329-am33xx.dtsi-Update-and-disable-status-of-nodes.patch
@@ -0,0 +1,101 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 15:40:50 +0200
+Subject: [PATCH] am33xx.dtsi: Update and disable status of nodes
+
+---
+ arch/arm/boot/dts/am33xx.dtsi | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index b4b62af..797f421 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -463,6 +463,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <16>;
+ ti,hwmods = "adc_tsc";
++ status = "disabled";
+ };
+
+ lcdc: lcdc@4830e000 {
+@@ -479,7 +480,7 @@
+ ti,hwmods = "epwmss0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- //status = "disabled";
++ status = "disabled";
+ ranges = <0x48300100 0x48300100 0x80 /* ECAP */
+ 0x48300180 0x48300180 0x80 /* EQEP */
+ 0x48300200 0x48300200 0x80>; /* EHRPWM */
+@@ -489,7 +490,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48300100 0x80>;
+ ti,hwmods = "ecap0";
+- //status = "disabled";
++ status = "disabled";
+ };
+
+ ehrpwm0: ehrpwm@48300200 {
+@@ -497,7 +498,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48300200 0x80>;
+ ti,hwmods = "ehrpwm0";
+- //status = "disabled";
++ status = "disabled";
+ };
+ };
+
+@@ -507,7 +508,7 @@
+ ti,hwmods = "epwmss1";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- //status = "disabled";
++ status = "disabled";
+ ranges = <0x48302100 0x48302100 0x80 /* ECAP */
+ 0x48302180 0x48302180 0x80 /* EQEP */
+ 0x48302200 0x48302200 0x80>; /* EHRPWM */
+@@ -517,7 +518,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48302100 0x80>;
+ ti,hwmods = "ecap1";
+- //status = "disabled";
++ status = "disabled";
+ };
+
+ ehrpwm1: ehrpwm@48302200 {
+@@ -525,7 +526,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48302200 0x80>;
+ ti,hwmods = "ehrpwm1";
+- //status = "disabled";
++ status = "disabled";
+ };
+ };
+
+@@ -535,7 +536,7 @@
+ ti,hwmods = "epwmss2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+- //status = "disabled";
++ status = "disabled";
+ ranges = <0x48304100 0x48304100 0x80 /* ECAP */
+ 0x48304180 0x48304180 0x80 /* EQEP */
+ 0x48304200 0x48304200 0x80>; /* EHRPWM */
+@@ -545,7 +546,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48304100 0x80>;
+ ti,hwmods = "ecap2";
+- //status = "disabled";
++ status = "disabled";
+ };
+
+ ehrpwm2: ehrpwm@48304200 {
+@@ -553,7 +554,7 @@
+ #pwm-cells = <3>;
+ reg = <0x48304200 0x80>;
+ ti,hwmods = "ehrpwm2";
+- //status = "disabled";
++ status = "disabled";
+ };
+ };
+
diff --git a/patches/linux-3.8.13/0330-bone-capes-Adapt-to-new-pwms-setup.patch b/patches/linux-3.8.13/0330-bone-capes-Adapt-to-new-pwms-setup.patch
new file mode 100644
index 0000000..9649235
--- /dev/null
+++ b/patches/linux-3.8.13/0330-bone-capes-Adapt-to-new-pwms-setup.patch
@@ -0,0 +1,87 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 16:28:59 +0200
+Subject: [PATCH] bone-capes: Adapt to new pwms setup
+
+---
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 1 +
+ firmware/capes/cape-bone-geiger-00A0.dts | 4 ++--
+ firmware/capes/cape-bone-lcd3-00A2.dts | 19 +++++++++++++++----
+ 3 files changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index 5a9a5f9..c13fe80 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -83,6 +83,7 @@
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_bl_pins>;
++ status = "okay";
+
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "LCD7";
+diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
+index 89417fb..4757ce7 100644
+--- a/firmware/capes/cape-bone-geiger-00A0.dts
++++ b/firmware/capes/cape-bone-geiger-00A0.dts
+@@ -36,14 +36,14 @@
+ };
+ };
+
+- fragment@2 {
++ fragment@1 {
+ target = <&epwmss1>;
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+- fragment@1 {
++ fragment@2 {
+ target = <&ehrpwm1>;
+ __overlay__ {
+ status = "okay";
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index efa2d10..ce72c17 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -69,6 +69,20 @@
+ };
+
+ fragment@1 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
+ target = <&ocp>;
+
+ __overlay__ {
+@@ -77,10 +91,6 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+- ehrpwm1 {
+- status = "okay";
+- };
+-
+ backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+@@ -90,6 +100,7 @@
+ pwm-names = "LCD3";
+ 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 */
++ status = "okay";
+ };
+
+ tscadc {
diff --git a/patches/linux-3.8.13/0331-tilcdc-introduce-panel-tfp410-power-down-gpio-contro.patch b/patches/linux-3.8.13/0331-tilcdc-introduce-panel-tfp410-power-down-gpio-contro.patch
new file mode 100644
index 0000000..e423c23
--- /dev/null
+++ b/patches/linux-3.8.13/0331-tilcdc-introduce-panel-tfp410-power-down-gpio-contro.patch
@@ -0,0 +1,115 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 18:15:57 +0200
+Subject: [PATCH] tilcdc: introduce panel & tfp410 power down gpio control
+
+Introduce power down GPIO support for panels and tfp410.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 26 +++++++++++++++++++++++++-
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 23 +++++++++++++++++------
+ 2 files changed, 42 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+index d1463f5..f4b794d 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+@@ -21,6 +21,7 @@
+ #include <video/display_timing.h>
+ #include <video/of_display_timing.h>
+ #include <video/videomode.h>
++#include <linux/of_gpio.h>
+
+ #include "tilcdc_drv.h"
+
+@@ -29,6 +30,7 @@ struct panel_module {
+ struct tilcdc_panel_info *info;
+ struct display_timings *timings;
+ struct backlight_device *backlight;
++ int gpio;
+ };
+ #define to_panel_module(x) container_of(x, struct panel_module, base)
+
+@@ -359,9 +361,10 @@ static int panel_probe(struct platform_device *pdev)
+ struct panel_module *panel_mod;
+ struct tilcdc_module *mod;
+ struct pinctrl *pinctrl;
++ enum of_gpio_flags ofgpioflags;
++ unsigned long gpioflags;
+ int ret = -EINVAL;
+
+-
+ /* bail out early if no DT data: */
+ if (!node) {
+ dev_err(&pdev->dev, "device-tree data is missing\n");
+@@ -397,6 +400,27 @@ static int panel_probe(struct platform_device *pdev)
+ if (panel_mod->backlight)
+ dev_info(&pdev->dev, "found backlight\n");
+
++ panel_mod->gpio = of_get_named_gpio_flags(pdev->dev.of_node, "ti,power-gpio",
++ 0, &ofgpioflags);
++ if (IS_ERR_VALUE(panel_mod->gpio)) {
++ dev_warn(&pdev->dev, "panel: No power control GPIO\n");
++ } else {
++ gpioflags = GPIOF_DIR_OUT;
++ if (ofgpioflags & OF_GPIO_ACTIVE_LOW) {
++ gpioflags |= GPIOF_INIT_LOW;
++ dev_info(&pdev->dev, "Power GPIO active low, initial state set to low\n");
++ } else {
++ gpioflags |= GPIOF_INIT_HIGH;
++ dev_info(&pdev->dev, "Power GPIO active high, initial state set to high\n");
++ }
++ ret = devm_gpio_request_one(&pdev->dev, panel_mod->gpio,
++ gpioflags, "panel:PDN");
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to request power gpio\n");
++ goto fail;
++ }
++ }
++
+ return 0;
+
+ fail:
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+index 10444ee..c9cd8f1 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+@@ -329,6 +329,8 @@ static int tfp410_probe(struct platform_device *pdev)
+ struct tilcdc_module *mod;
+ struct pinctrl *pinctrl;
+ uint32_t i2c_phandle;
++ enum of_gpio_flags ofgpioflags;
++ unsigned long gpioflags;
+ int ret = -EINVAL;
+
+ /* bail out early if no DT data: */
+@@ -368,14 +370,23 @@ static int tfp410_probe(struct platform_device *pdev)
+
+ of_node_put(i2c_node);
+
+- tfp410_mod->gpio = of_get_named_gpio_flags(node, "powerdn-gpio",
+- 0, NULL);
++ tfp410_mod->gpio = of_get_named_gpio_flags(pdev->dev.of_node, "ti,power-gpio",
++ 0, &ofgpioflags);
+ if (IS_ERR_VALUE(tfp410_mod->gpio)) {
+- dev_warn(&pdev->dev, "No power down GPIO\n");
++ dev_warn(&pdev->dev, "tftp410: No power control GPIO\n");
+ } else {
+- ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
+- if (ret) {
+- dev_err(&pdev->dev, "could not get DVI_PDn gpio\n");
++ gpioflags = GPIOF_DIR_OUT;
++ if (ofgpioflags & OF_GPIO_ACTIVE_LOW) {
++ gpioflags |= GPIOF_INIT_LOW;
++ dev_info(&pdev->dev, "Power GPIO active low, initial state set to low\n");
++ } else {
++ gpioflags |= GPIOF_INIT_HIGH;
++ dev_info(&pdev->dev, "Power GPIO active high, initial state set to high\n");
++ }
++ ret = devm_gpio_request_one(&pdev->dev, tfp410_mod->gpio,
++ gpioflags, "tfp410:PDN");
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to request power gpio\n");
+ goto fail;
+ }
+ }
diff --git a/patches/linux-3.8.13/0332-bone-dvi-Update-to-new-style-tilcdc-bindings.patch b/patches/linux-3.8.13/0332-bone-dvi-Update-to-new-style-tilcdc-bindings.patch
new file mode 100644
index 0000000..1317963
--- /dev/null
+++ b/patches/linux-3.8.13/0332-bone-dvi-Update-to-new-style-tilcdc-bindings.patch
@@ -0,0 +1,154 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 18:17:16 +0200
+Subject: [PATCH] bone-dvi: Update to new style tilcdc bindings
+
+Binding differences and place the GPIOs to the panels.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-dvi-00A0.dts | 8 +++++---
+ firmware/capes/cape-bone-dvi-00A1.dts | 8 +++++---
+ firmware/capes/cape-bone-dvi-00A2.dts | 8 +++++---
+ 3 files changed, 15 insertions(+), 9 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+index bc3d926..293b655 100644
+--- a/firmware/capes/cape-bone-dvi-00A0.dts
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -88,6 +88,7 @@
+ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
++ ti,power-gpio = <&gpio1 7 0x0>;
+ panel-info {
+ ac-bias = <255>;
+ ac-bias-intrpt = <0>;
+@@ -97,8 +98,6 @@
+ tft-alt-mode = <0>;
+ stn-565-mode = <0>;
+ mono-8bit-mode = <0>;
+- invert-line-clock = <1>;
+- invert-frm-clock = <1>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+@@ -116,6 +115,8 @@
+ hsync-len = <32>;
+ vsync-len = <4>;
+ clock-frequency = <56000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
+ timing1: 1280x720-60 {
+@@ -128,6 +129,8 @@
+ vsync-len = <5>;
+ vback-porch = <13>;
+ clock-frequency = <64000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+
+ };
+@@ -139,7 +142,6 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio1 7 0x0>;
+ };
+
+ };
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index d36415f..e706b93 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -98,6 +98,7 @@
+ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
++ ti,power-gpio = <&gpio1 7 0x0>;
+ panel-info {
+ ac-bias = <255>;
+ ac-bias-intrpt = <0>;
+@@ -107,8 +108,6 @@
+ tft-alt-mode = <0>;
+ stn-565-mode = <0>;
+ mono-8bit-mode = <0>;
+- invert-line-clock = <1>;
+- invert-frm-clock = <1>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+@@ -126,6 +125,8 @@
+ hsync-len = <32>;
+ vsync-len = <4>;
+ clock-frequency = <56000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
+ timing1: 1280x720-60 {
+@@ -138,6 +139,8 @@
+ vsync-len = <5>;
+ vback-porch = <13>;
+ clock-frequency = <64000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+
+ };
+@@ -149,7 +152,6 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio1 7 0x0>;
+ };
+
+ };
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+index 54fba3f..1dbaef8 100644
+--- a/firmware/capes/cape-bone-dvi-00A2.dts
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -98,6 +98,7 @@
+ compatible = "tilcdc,panel";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A2_pins>;
++ ti,power-gpio = <&gpio1 31 0x0>;
+ panel-info {
+ ac-bias = <255>;
+ ac-bias-intrpt = <0>;
+@@ -107,8 +108,6 @@
+ tft-alt-mode = <0>;
+ stn-565-mode = <0>;
+ mono-8bit-mode = <0>;
+- invert-line-clock = <1>;
+- invert-frm-clock = <1>;
+ sync-edge = <0>;
+ sync-ctrl = <1>;
+ raster-order = <0>;
+@@ -126,6 +125,8 @@
+ hsync-len = <32>;
+ vsync-len = <4>;
+ clock-frequency = <56000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+ /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
+ timing1: 1280x720-60 {
+@@ -138,6 +139,8 @@
+ vsync-len = <5>;
+ vback-porch = <13>;
+ clock-frequency = <64000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
+ };
+
+ };
+@@ -149,7 +152,6 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio1 31 0x0>;
+ };
+
+ };
diff --git a/patches/linux-3.8.13/0333-tilcdc-tfp410-Rework-power-down-GPIO-logic.patch b/patches/linux-3.8.13/0333-tilcdc-tfp410-Rework-power-down-GPIO-logic.patch
new file mode 100644
index 0000000..179bca7
--- /dev/null
+++ b/patches/linux-3.8.13/0333-tilcdc-tfp410-Rework-power-down-GPIO-logic.patch
@@ -0,0 +1,76 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 20:05:05 +0200
+Subject: [PATCH] tilcdc-tfp410: Rework power down GPIO logic
+
+Rework power down GPIO logic to be configurable.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+index c9cd8f1..7065dfa 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+@@ -27,6 +27,7 @@
+ struct tfp410_module {
+ struct tilcdc_module base;
+ struct i2c_adapter *i2c;
++ enum of_gpio_flags ofgpioflags;
+ int gpio;
+ };
+ #define to_tfp410_module(x) container_of(x, struct tfp410_module, base)
+@@ -66,17 +67,22 @@ static void tfp410_encoder_destroy(struct drm_encoder *encoder)
+ static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode)
+ {
+ struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
++ int state;
+
+ if (tfp410_encoder->dpms == mode)
+ return;
+
+- if (mode == DRM_MODE_DPMS_ON) {
+- DBG("Power on");
+- gpio_direction_output(tfp410_encoder->mod->gpio, 1);
+- } else {
+- DBG("Power off");
+- gpio_direction_output(tfp410_encoder->mod->gpio, 0);
+- }
++ if (IS_ERR_VALUE(tfp410_encoder->mod->gpio))
++ return;
++
++ state = mode == DRM_MODE_DPMS_ON;
++ if (tfp410_encoder->mod->ofgpioflags & OF_GPIO_ACTIVE_LOW)
++ state = !state;
++
++ pr_debug("%s: dpms %d, gpio-state %d\n", __func__,
++ mode == DRM_MODE_DPMS_ON, state);
++
++ gpio_direction_output(tfp410_encoder->mod->gpio, state);
+
+ tfp410_encoder->dpms = mode;
+ }
+@@ -329,7 +335,6 @@ static int tfp410_probe(struct platform_device *pdev)
+ struct tilcdc_module *mod;
+ struct pinctrl *pinctrl;
+ uint32_t i2c_phandle;
+- enum of_gpio_flags ofgpioflags;
+ unsigned long gpioflags;
+ int ret = -EINVAL;
+
+@@ -371,12 +376,12 @@ static int tfp410_probe(struct platform_device *pdev)
+ of_node_put(i2c_node);
+
+ tfp410_mod->gpio = of_get_named_gpio_flags(pdev->dev.of_node, "ti,power-gpio",
+- 0, &ofgpioflags);
++ 0, &tfp410_mod->ofgpioflags);
+ if (IS_ERR_VALUE(tfp410_mod->gpio)) {
+ dev_warn(&pdev->dev, "tftp410: No power control GPIO\n");
+ } else {
+ gpioflags = GPIOF_DIR_OUT;
+- if (ofgpioflags & OF_GPIO_ACTIVE_LOW) {
++ if (tfp410_mod->ofgpioflags & OF_GPIO_ACTIVE_LOW) {
+ gpioflags |= GPIOF_INIT_LOW;
+ dev_info(&pdev->dev, "Power GPIO active low, initial state set to low\n");
+ } else {
diff --git a/patches/linux-3.8.13/0334-tilcdc-Add-reduced-blanking-mode-checks.patch b/patches/linux-3.8.13/0334-tilcdc-Add-reduced-blanking-mode-checks.patch
new file mode 100644
index 0000000..3eb1afd
--- /dev/null
+++ b/patches/linux-3.8.13/0334-tilcdc-Add-reduced-blanking-mode-checks.patch
@@ -0,0 +1,74 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 20:09:11 +0200
+Subject: [PATCH] tilcdc: Add reduced blanking mode checks
+
+The driver doesn't support (yet?) non-reduced blanking mode.
+So by default disable any non-reduced blanking modes, and add a switch
+to enable them in the future.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 11 +++++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 5 ++++-
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 +
+ 3 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 9f10f05..dcbafad 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -426,6 +426,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
+ {
+ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+ unsigned int bandwidth;
++ int rb;
+
+ if (mode->hdisplay > tilcdc_crtc_max_width(crtc))
+ return MODE_VIRTUAL_X;
+@@ -442,6 +443,16 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
+ if (bandwidth > priv->max_bandwidth)
+ return MODE_BAD;
+
++ if (priv->allow_non_rblank == 0) {
++ /* we only support reduced blanking modes */
++ rb = (mode->htotal - mode->hdisplay == 160) &&
++ (mode->hsync_end - mode->hdisplay == 80) &&
++ (mode->hsync_end - mode->hsync_start == 32) &&
++ (mode->vsync_start - mode->vdisplay == 3);
++ if (!rb)
++ return MODE_BAD;
++ }
++
+ return MODE_OK;
+ }
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index 3ffa2e5..0fe14ea 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -235,9 +235,12 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+ }
+ #endif
+
+- if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth))
++ if (of_property_read_u32(node, "ti,max-bandwidth", &priv->max_bandwidth))
+ priv->max_bandwidth = 1280 * 1024 * 60;
+
++ priv->allow_non_rblank = of_property_read_bool(node,
++ "ti,allow-non-reduced-blanking-modes");
++
+ pm_runtime_enable(dev->dev);
+
+ /* Determine LCD IP Version */
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index 8242b5a..c858f73 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -43,6 +43,7 @@ struct tilcdc_drm_private {
+
+ /* don't attempt resolutions w/ higher W * H * Hz: */
+ uint32_t max_bandwidth;
++ int allow_non_rblank; /* ATM we don't support non reduced blank modes */
+
+ /* register contents saved across suspend/resume: */
+ u32 saved_register[12];
diff --git a/patches/linux-3.8.13/0335-cape-dvi-Switch-all-DVI-capes-to-using-the-TFTP410-p.patch b/patches/linux-3.8.13/0335-cape-dvi-Switch-all-DVI-capes-to-using-the-TFTP410-p.patch
new file mode 100644
index 0000000..640fd88
--- /dev/null
+++ b/patches/linux-3.8.13/0335-cape-dvi-Switch-all-DVI-capes-to-using-the-TFTP410-p.patch
@@ -0,0 +1,208 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 30 Jan 2013 20:11:05 +0200
+Subject: [PATCH] cape-dvi: Switch all DVI capes to using the TFTP410 panel
+
+Now that TFP410 works reasonably well switch to using it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-dvi-00A0.dts | 50 ++-------------------------------
+ firmware/capes/cape-bone-dvi-00A1.dts | 50 ++-------------------------------
+ firmware/capes/cape-bone-dvi-00A2.dts | 50 ++-------------------------------
+ 3 files changed, 9 insertions(+), 141 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+index 293b655..92fc6be 100644
+--- a/firmware/capes/cape-bone-dvi-00A0.dts
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -83,57 +83,13 @@
+ };
+ };
+
+- /* Settings for DVI 1024x768@60 */
++ /* use the DVI panel now */
+ panel {
+- compatible = "tilcdc,panel";
++ compatible = "tilcdc,tfp410";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
+ ti,power-gpio = <&gpio1 7 0x0>;
+- panel-info {
+- ac-bias = <255>;
+- ac-bias-intrpt = <0>;
+- dma-burst-sz = <16>;
+- bpp = <16>;
+- fdd = <0x80>;
+- tft-alt-mode = <0>;
+- stn-565-mode = <0>;
+- mono-8bit-mode = <0>;
+- sync-edge = <0>;
+- sync-ctrl = <1>;
+- raster-order = <0>;
+- fifo-th = <0>;
+- };
+- display-timings {
+- native-mode = <&timing1>;
+- timing0: 1024x768 {
+- hactive = <1024>;
+- vactive = <768>;
+- hback-porch = <80>;
+- hfront-porch = <48>;
+- vback-porch = <15>;
+- vfront-porch = <3>;
+- hsync-len = <32>;
+- vsync-len = <4>;
+- clock-frequency = <56000000>;
+- hsync-active = <0>;
+- vsync-active = <0>;
+- };
+- /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
+- timing1: 1280x720-60 {
+- hactive = <1280>;
+- hfront-porch = <48>;
+- hsync-len = <32>;
+- hback-porch = <80>;
+- vactive = <720>;
+- vfront-porch = <3>;
+- vsync-len = <5>;
+- vback-porch = <13>;
+- clock-frequency = <64000000>;
+- hsync-active = <0>;
+- vsync-active = <0>;
+- };
+-
+- };
++ i2c = <&i2c2>;
+ };
+
+ fb {
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index e706b93..ed9099c 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -93,57 +93,13 @@
+ };
+ };
+
+- /* Settings for DVI 1024x768@60 */
++ /* use the DVI panel now */
+ panel {
+- compatible = "tilcdc,panel";
++ compatible = "tilcdc,tfp410";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
+ ti,power-gpio = <&gpio1 7 0x0>;
+- panel-info {
+- ac-bias = <255>;
+- ac-bias-intrpt = <0>;
+- dma-burst-sz = <16>;
+- bpp = <16>;
+- fdd = <0x80>;
+- tft-alt-mode = <0>;
+- stn-565-mode = <0>;
+- mono-8bit-mode = <0>;
+- sync-edge = <0>;
+- sync-ctrl = <1>;
+- raster-order = <0>;
+- fifo-th = <0>;
+- };
+- display-timings {
+- native-mode = <&timing1>;
+- timing0: 1024x768 {
+- hactive = <1024>;
+- vactive = <768>;
+- hback-porch = <80>;
+- hfront-porch = <48>;
+- vback-porch = <15>;
+- vfront-porch = <3>;
+- hsync-len = <32>;
+- vsync-len = <4>;
+- clock-frequency = <56000000>;
+- hsync-active = <0>;
+- vsync-active = <0>;
+- };
+- /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
+- timing1: 1280x720-60 {
+- hactive = <1280>;
+- hfront-porch = <48>;
+- hsync-len = <32>;
+- hback-porch = <80>;
+- vactive = <720>;
+- vfront-porch = <3>;
+- vsync-len = <5>;
+- vback-porch = <13>;
+- clock-frequency = <64000000>;
+- hsync-active = <0>;
+- vsync-active = <0>;
+- };
+-
+- };
++ i2c = <&i2c2>;
+ };
+
+ fb {
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+index 1dbaef8..fb2dcf0 100644
+--- a/firmware/capes/cape-bone-dvi-00A2.dts
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -93,57 +93,13 @@
+ };
+ };
+
+- /* Settings for DVI 1024x768@60 */
++ /* use the DVI panel now */
+ panel {
+- compatible = "tilcdc,panel";
++ compatible = "tilcdc,tfp410";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bone_dvi_cape_dvi_00A2_pins>;
+ ti,power-gpio = <&gpio1 31 0x0>;
+- panel-info {
+- ac-bias = <255>;
+- ac-bias-intrpt = <0>;
+- dma-burst-sz = <16>;
+- bpp = <16>;
+- fdd = <0x80>;
+- tft-alt-mode = <0>;
+- stn-565-mode = <0>;
+- mono-8bit-mode = <0>;
+- sync-edge = <0>;
+- sync-ctrl = <1>;
+- raster-order = <0>;
+- fifo-th = <0>;
+- };
+- display-timings {
+- native-mode = <&timing1>;
+- timing0: 1024x768 {
+- hactive = <1024>;
+- vactive = <768>;
+- hback-porch = <80>;
+- hfront-porch = <48>;
+- vback-porch = <15>;
+- vfront-porch = <3>;
+- hsync-len = <32>;
+- vsync-len = <4>;
+- clock-frequency = <56000000>;
+- hsync-active = <0>;
+- vsync-active = <0>;
+- };
+- /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
+- timing1: 1280x720-60 {
+- hactive = <1280>;
+- hfront-porch = <48>;
+- hsync-len = <32>;
+- hback-porch = <80>;
+- vactive = <720>;
+- vfront-porch = <3>;
+- vsync-len = <5>;
+- vback-porch = <13>;
+- clock-frequency = <64000000>;
+- hsync-active = <0>;
+- vsync-active = <0>;
+- };
+-
+- };
++ i2c = <&i2c2>;
+ };
+
+ fb {
diff --git a/patches/linux-3.8.13/0336-beaglebone-switch-eMMC-to-8bit-mode.patch b/patches/linux-3.8.13/0336-beaglebone-switch-eMMC-to-8bit-mode.patch
new file mode 100644
index 0000000..648637e
--- /dev/null
+++ b/patches/linux-3.8.13/0336-beaglebone-switch-eMMC-to-8bit-mode.patch
@@ -0,0 +1,36 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 13 Feb 2013 20:43:31 +0100
+Subject: [PATCH] beaglebone: switch eMMC to 8bit mode
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-boneblack.dts | 2 +-
+ firmware/capes/cape-bone-2g-emmc1.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index 6cb2a51..e88723c 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -28,7 +28,7 @@
+
+ &mmc2 {
+ vmmc-supply = <&ldo3_reg>;
+- bus-width = <4>;
++ bus-width = <8>;
+ ti,non-removable;
+ status = "okay";
+ };
+diff --git a/firmware/capes/cape-bone-2g-emmc1.dts b/firmware/capes/cape-bone-2g-emmc1.dts
+index e2a4a46..17ea449 100644
+--- a/firmware/capes/cape-bone-2g-emmc1.dts
++++ b/firmware/capes/cape-bone-2g-emmc1.dts
+@@ -44,7 +44,7 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc2_pins>; /* wrong numbering */
+ vmmc-supply = <&ldo3_reg>;
+- bus-width = <4>;
++ bus-width = <8>;
+ ti,non-removable;
+ status = "okay";
+ reset-gpios = <&gpio2 20 1>; /* active low */
diff --git a/patches/linux-3.8.13/0337-Pinmux-helper-driver.patch b/patches/linux-3.8.13/0337-Pinmux-helper-driver.patch
new file mode 100644
index 0000000..6094273
--- /dev/null
+++ b/patches/linux-3.8.13/0337-Pinmux-helper-driver.patch
@@ -0,0 +1,130 @@
+From: Pantelis Antoniou <panto@vm-ubuntu.(none)>
+Date: Mon, 25 Feb 2013 00:48:01 +0200
+Subject: [PATCH] Pinmux helper driver.
+
+ That's just a hack to get a pinmux helper driver working.
+
+ Define in the DT
+
+ helper {
+ compatible = "bone-pinmux-helper";
+ pinctrl-names = "default";
+ pinctrl-0 = <&helper_pins>;
+ status = "okay";
+ };
+---
+ drivers/misc/cape/beaglebone/Kconfig | 7 ++
+ drivers/misc/cape/beaglebone/Makefile | 2 +
+ drivers/misc/cape/beaglebone/bone-pinmux-helper.c | 72 +++++++++++++++++++++
+ 3 files changed, 81 insertions(+)
+ create mode 100644 drivers/misc/cape/beaglebone/bone-pinmux-helper.c
+
+diff --git a/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig
+index 8d4f73e..9bf5ac0 100644
+--- a/drivers/misc/cape/beaglebone/Kconfig
++++ b/drivers/misc/cape/beaglebone/Kconfig
+@@ -2,6 +2,13 @@
+ # Beaglebone capes
+ #
+
++config BEAGLEBONE_PINMUX_HELPER
++ tristate "Beaglebone Pinmux Helper"
++ depends on ARCH_OMAP2PLUS && OF
++ default n
++ help
++ Say Y here to include support for the pinmux helper
++
+ config CAPE_BEAGLEBONE
+ tristate "Beaglebone cape support"
+ depends on ARCH_OMAP2PLUS && OF && I2C
+diff --git a/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile
+index 808fe14..508b931 100644
+--- a/drivers/misc/cape/beaglebone/Makefile
++++ b/drivers/misc/cape/beaglebone/Makefile
+@@ -2,6 +2,8 @@
+ # Makefile for beaglebone capes
+ #
+
++obj-$(CONFIG_BEAGLEBONE_PINMUX_HELPER) += bone-pinmux-helper.o
++
+ obj-$(CONFIG_CAPE_BEAGLEBONE) += capemgr.o
+ obj-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += cape-bone-geiger.o
+ obj-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += cape-bone-nixie.o
+diff --git a/drivers/misc/cape/beaglebone/bone-pinmux-helper.c b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
+new file mode 100644
+index 0000000..ba3922d
+--- /dev/null
++++ b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
+@@ -0,0 +1,72 @@
++/*
++ * Pinmux helper driver
++ *
++ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.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>
++
++static const struct of_device_id bone_pinmux_helper_of_match[] = {
++ {
++ .compatible = "bone-pinmux-helper",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bone_pinmux_helper_of_match);
++
++static int bone_pinmux_helper_probe(struct platform_device *pdev)
++{
++ struct pinctrl *pinctrl;
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++
++ /* don't bother with anything */
++ return PTR_RET(pinctrl);
++}
++
++static int bone_pinmux_helper_remove(struct platform_device *pdev)
++{
++ /* nothing more is needed */
++ return 0;
++}
++
++struct platform_driver bone_pinmux_helper_driver = {
++ .probe = bone_pinmux_helper_probe,
++ .remove = bone_pinmux_helper_remove,
++ .driver = {
++ .name = "bone-pinmux-helper",
++ .owner = THIS_MODULE,
++ .of_match_table = bone_pinmux_helper_of_match,
++ },
++};
++
++module_platform_driver(bone_pinmux_helper_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone pinmux helper driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-pinmux-helper");
diff --git a/patches/linux-3.8.13/0338-OF-Clear-detach-flag-on-attach.patch b/patches/linux-3.8.13/0338-OF-Clear-detach-flag-on-attach.patch
new file mode 100644
index 0000000..e7eed6d
--- /dev/null
+++ b/patches/linux-3.8.13/0338-OF-Clear-detach-flag-on-attach.patch
@@ -0,0 +1,24 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 27 Feb 2013 11:26:34 +0200
+Subject: [PATCH] OF: Clear detach flag on attach
+
+When attaching a node always clear the detach flag. Without this change
+the sequence detach, attach fails.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/base.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index 526db99..5ebfc33 100644
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -1355,6 +1355,7 @@ int of_attach_node(struct device_node *np)
+ np->allnext = of_allnodes;
+ np->parent->child = np;
+ of_allnodes = np;
++ of_node_clear_flag(np, OF_DETACHED);
+ write_unlock_irqrestore(&devtree_lock, flags);
+
+ of_add_proc_dt_entry(np);
diff --git a/patches/linux-3.8.13/0339-OF-overlay-Fix-overlay-revert-failure.patch b/patches/linux-3.8.13/0339-OF-overlay-Fix-overlay-revert-failure.patch
new file mode 100644
index 0000000..4a5350e
--- /dev/null
+++ b/patches/linux-3.8.13/0339-OF-overlay-Fix-overlay-revert-failure.patch
@@ -0,0 +1,337 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 27 Feb 2013 11:28:19 +0200
+Subject: [PATCH] OF-overlay: Fix overlay revert failure
+
+Somewhere along the line of changes we dropped the ability to cleanly revert
+overlays. This patchset fixes the bug, and makes it possible to add/remove
+overlays at will.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/overlay.c | 136 +++++++++++++++++++++++++++++++-------------------
+ include/linux/of.h | 5 ++
+ 2 files changed, 91 insertions(+), 50 deletions(-)
+
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index 0577067..41b883f 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -8,12 +8,13 @@
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+-
++#undef DEBUG
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/of_i2c.h>
++#include <linux/i2c.h>
+ #include <linux/string.h>
+ #include <linux/ctype.h>
+ #include <linux/errno.h>
+@@ -169,12 +170,12 @@ static int of_overlay_apply_one(struct device_node *target,
+ struct of_overlay_device_entry *of_overlay_device_entry_lookup(
+ struct of_overlay_info *ovinfo, struct device_node *node)
+ {
+- struct of_overlay_device_entry *re;
++ struct of_overlay_device_entry *de;
+
+- /* no need for locks, we're under the ovinfo->lock */
+- list_for_each_entry(re, &ovinfo->de_list, node) {
+- if (re->np == node)
+- return re;
++ /* no need for locks, we'de under the ovinfo->lock */
++ list_for_each_entry(de, &ovinfo->de_list, node) {
++ if (de->np == node)
++ return de;
+ }
+ return NULL;
+ }
+@@ -215,10 +216,11 @@ static int of_overlay_log_entry_entry_add(struct of_overlay_info *ovinfo,
+ * Add an overlay device entry
+ */
+ static void of_overlay_device_entry_entry_add(struct of_overlay_info *ovinfo,
+- struct device_node *node, struct platform_device *pdev,
+- int state)
++ struct device_node *node,
++ struct platform_device *pdev, struct i2c_client *client,
++ int prevstate, int state)
+ {
+- struct of_overlay_device_entry *re;
++ struct of_overlay_device_entry *de;
+ int fresh;
+
+ /* check */
+@@ -226,24 +228,29 @@ static void of_overlay_device_entry_entry_add(struct of_overlay_info *ovinfo,
+ return;
+
+ fresh = 0;
+- re = of_overlay_device_entry_lookup(ovinfo, node);
+- if (re == NULL) {
+- re = kzalloc(sizeof(*re), GFP_KERNEL);
+- if (re == NULL) {
++ de = of_overlay_device_entry_lookup(ovinfo, node);
++ if (de == NULL) {
++ de = kzalloc(sizeof(*de), GFP_KERNEL);
++ if (de == NULL) {
+ pr_err("%s: Failed to allocate\n", __func__);
+ return;
+ }
+ fresh = 1;
++ de->prevstate = -1;
+ }
+
+- if (re->np == NULL)
+- re->np = of_node_get(node);
+- if (re->pdev == NULL)
+- re->pdev = of_dev_get(pdev);
+- re->state = state;
++ if (de->np == NULL)
++ de->np = of_node_get(node);
++ if (de->pdev == NULL && pdev)
++ de->pdev = of_dev_get(pdev);
++ if (de->client == NULL && client)
++ de->client = i2c_use_client(client);
++ if (fresh)
++ de->prevstate = prevstate;
++ de->state = state;
+
+ if (fresh)
+- list_add_tail(&re->node, &ovinfo->de_list);
++ list_add_tail(&de->node, &ovinfo->de_list);
+ }
+
+ /**
+@@ -263,7 +270,8 @@ static int of_overlay_notify(struct notifier_block *nb,
+ struct property *prop, *sprop, *cprop;
+ struct of_prop_reconfig *pr;
+ struct platform_device *pdev;
+- int state;
++ struct i2c_client *client;
++ int prevstate, state;
+ int err = 0;
+
+ ovinfo = container_of(nb, struct of_overlay_info, notifier);
+@@ -301,7 +309,9 @@ static int of_overlay_notify(struct notifier_block *nb,
+
+ /* come up with the device entry (if any) */
+ pdev = NULL;
++ client = NULL;
+ state = 0;
++ prevstate = 0;
+
+ /* determine the state the node will end up */
+ switch (action) {
+@@ -311,8 +321,11 @@ static int of_overlay_notify(struct notifier_block *nb,
+ of_device_is_available(node);
+ break;
+ case OF_RECONFIG_DETACH_NODE:
++ prevstate = of_find_property(node, "compatible", NULL) &&
++ of_device_is_available(node);
+ state = 0;
+ pdev = of_find_device_by_node(node);
++ client = of_find_i2c_device_by_node(node);
+ break;
+ case OF_RECONFIG_ADD_PROPERTY:
+ case OF_RECONFIG_REMOVE_PROPERTY:
+@@ -334,6 +347,8 @@ static int of_overlay_notify(struct notifier_block *nb,
+ prop : NULL;
+ }
+
++ prevstate = of_find_property(node, "compatible", NULL) &&
++ of_device_is_available(node);
+ state = cprop && cprop->length > 0 &&
+ (!sprop || (sprop->length > 0 &&
+ (strcmp(sprop->value, "okay") == 0 ||
+@@ -344,10 +359,13 @@ static int of_overlay_notify(struct notifier_block *nb,
+ return notifier_from_errno(0);
+ }
+
+- if (state == 0)
++ if (state == 0) {
+ pdev = of_find_device_by_node(node);
++ client = of_find_i2c_device_by_node(node);
++ }
+
+- of_overlay_device_entry_entry_add(ovinfo, node, pdev, state);
++ of_overlay_device_entry_entry_add(ovinfo, node, pdev, client,
++ prevstate, state);
+
+ return notifier_from_errno(err);
+ }
+@@ -370,21 +388,21 @@ static int of_overlay_prep_one(struct of_overlay_info *ovinfo)
+ }
+
+ static int of_overlay_device_entry_change(struct of_overlay_info *ovinfo,
+- struct of_overlay_device_entry *re, int revert)
++ struct of_overlay_device_entry *de, int revert)
+ {
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *client;
+ struct platform_device *pdev, *parent_pdev = NULL;
+ int state;
+
+- state = !!re->state ^ !!revert;
++ state = !!de->state ^ !!revert;
+
+- if (re->np && re->np->parent) {
++ if (de->np && de->np->parent) {
+ pr_debug("%s: parent is %s\n",
+- __func__, re->np->parent->full_name);
+- adap = of_find_i2c_adapter_by_node(re->np->parent);
++ __func__, de->np->parent->full_name);
++ adap = of_find_i2c_adapter_by_node(de->np->parent);
+ if (adap == NULL)
+- parent_pdev = of_find_device_by_node(re->np->parent);
++ parent_pdev = of_find_device_by_node(de->np->parent);
+ }
+
+ if (state) {
+@@ -394,35 +412,46 @@ static int of_overlay_device_entry_change(struct of_overlay_info *ovinfo,
+
+ pr_debug("%s: creating new platform device "
+ "new_node='%s' %p\n",
+- __func__, re->np->full_name, re->np);
++ __func__, de->np->full_name, de->np);
+
+- pdev = of_platform_device_create(re->np, NULL,
++ pdev = of_platform_device_create(de->np, NULL,
+ parent_pdev ? &parent_pdev->dev : NULL);
+ if (pdev == NULL) {
+ pr_warn("%s: Failed to create platform device "
+ "for '%s'\n",
+- __func__, re->np->full_name);
+- }
++ __func__, de->np->full_name);
++ } else
++ de->pdev = pdev;
++
+ } else {
+ pr_debug("%s: creating new i2c_client device "
+ "new_node='%s' %p\n",
+- __func__, re->np->full_name, re->np);
++ __func__, de->np->full_name, de->np);
+
+- client = of_i2c_register_device(adap, re->np);
++ client = of_i2c_register_device(adap, de->np);
+
+ if (client == NULL) {
+ pr_warn("%s: Failed to create i2c client device "
+ "for '%s'\n",
+- __func__, re->np->full_name);
+- }
++ __func__, de->np->full_name);
++ } else
++ de->client = client;
+ }
+
+ } else {
+
+- if (re->pdev) {
++ if (de->pdev) {
+ pr_debug("%s: removing pdev %s\n", __func__,
+- dev_name(&re->pdev->dev));
+- platform_device_unregister(re->pdev);
++ dev_name(&de->pdev->dev));
++ platform_device_unregister(de->pdev);
++ de->pdev = NULL;
++ }
++
++ if (de->client) {
++ pr_debug("%s: removing i2c client %s\n", __func__,
++ dev_name(&de->client->dev));
++ i2c_unregister_device(de->client);
++ de->client = NULL;
+ }
+ }
+
+@@ -444,7 +473,7 @@ static int of_overlay_device_entry_change(struct of_overlay_info *ovinfo,
+ */
+ static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
+ {
+- struct of_overlay_device_entry *re, *ren;
++ struct of_overlay_device_entry *de, *den;
+ struct of_overlay_log_entry *le, *len;
+ struct property *prop, **propp;
+ int ret;
+@@ -457,13 +486,11 @@ static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
+ ovinfo->target->full_name);
+
+ /* overlay applied correctly, now create/destroy pdevs */
+- list_for_each_entry_safe_reverse(re, ren, &ovinfo->de_list, node) {
+-
+- of_overlay_device_entry_change(ovinfo, re, 1);
+-
+- of_node_put(re->np);
+- list_del(&re->node);
+- kfree(re);
++ list_for_each_entry_safe_reverse(de, den, &ovinfo->de_list, node) {
++ of_overlay_device_entry_change(ovinfo, de, 1);
++ of_node_put(de->np);
++ list_del(&de->node);
++ kfree(de);
+ }
+
+ list_for_each_entry_safe_reverse(le, len, &ovinfo->le_list, node) {
+@@ -554,7 +581,7 @@ static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
+ */
+ static int of_overlay_post_one(struct of_overlay_info *ovinfo, int err)
+ {
+- struct of_overlay_device_entry *re;
++ struct of_overlay_device_entry *de, *den;
+
+ of_reconfig_notifier_unregister(&ovinfo->notifier);
+
+@@ -565,8 +592,17 @@ static int of_overlay_post_one(struct of_overlay_info *ovinfo, int err)
+ }
+
+ /* overlay applied correctly, now create/destroy pdevs */
+- list_for_each_entry(re, &ovinfo->de_list, node)
+- of_overlay_device_entry_change(ovinfo, re, 0);
++ list_for_each_entry_safe(de, den, &ovinfo->de_list, node) {
++
++ /* no state change? just remove this entry */
++ if (de->prevstate == de->state) {
++ of_node_put(de->np);
++ list_del(&de->node);
++ kfree(de);
++ } else {
++ of_overlay_device_entry_change(ovinfo, de, 0);
++ }
++ }
+
+ return 0;
+ }
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 8a908f0..73cfde5 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -23,6 +23,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/topology.h>
+ #include <linux/notifier.h>
++#include <linux/i2c.h>
+
+ #include <asm/byteorder.h>
+ #include <asm/errno.h>
+@@ -697,7 +698,9 @@ struct of_overlay_log_entry {
+ * @node: list_head for the device list
+ * @np: device node pointer to the device node affected
+ * @pdev: pointer to the platform device affected
++ * @client: pointer to the I2C client device affected
+ * @state: new device state
++ * @prevstate: previous device state
+ *
+ * When the overlay results in a device node's state to change this
+ * fact is recorded in a list of device entries. After the overlay
+@@ -708,6 +711,8 @@ struct of_overlay_device_entry {
+ struct list_head node;
+ struct device_node *np;
+ struct platform_device *pdev;
++ struct i2c_client *client;
++ int prevstate;
+ int state;
+ };
+
diff --git a/patches/linux-3.8.13/0340-bone-capemgr-Make-sure-cape-removal-works.patch b/patches/linux-3.8.13/0340-bone-capemgr-Make-sure-cape-removal-works.patch
new file mode 100644
index 0000000..838b423
--- /dev/null
+++ b/patches/linux-3.8.13/0340-bone-capemgr-Make-sure-cape-removal-works.patch
@@ -0,0 +1,109 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 27 Feb 2013 11:32:20 +0200
+Subject: [PATCH] bone-capemgr: Make sure cape removal works.
+
+Cape removal wasn't working properly before; fix it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 62 +++++++++++++++++++++++---------
+ 1 file changed, 45 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index d828af7..2656e3a 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -154,6 +154,7 @@ static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ static struct bone_cape_slot *bone_capemgr_add_slot(
+ struct bone_capemgr_info *info, struct device_node *node,
+ const char *part_number, const char *version);
++static int bone_capemgr_remove_slot(struct bone_cape_slot *slot);
+ static int bone_capemgr_load(struct bone_cape_slot *slot);
+ static int bone_capemgr_unload(struct bone_cape_slot *slot);
+
+@@ -991,14 +992,23 @@ static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
+ if (slotno == slot->slotno)
+ break;
+ }
+- mutex_unlock(&info->slots_list_mutex);
+
+- if (slot == NULL)
++ /* found? */
++ if (slot == NULL) {
++ mutex_unlock(&info->slots_list_mutex);
+ return -ENODEV;
++ }
++
++ ret = bone_capemgr_remove_slot(slot);
++ mutex_unlock(&info->slots_list_mutex);
+
+- bone_capemgr_unload(slot);
++ if (ret == 0)
++ dev_info(&pdev->dev, "Removed slot #%d\n", slotno);
++ else
++ dev_err(&pdev->dev, "Failed to remove slot #%d\n",
++ slotno);
+
+- return strlen(buf);
++ return ret == 0 ? strlen(buf) : ret;
+ }
+
+ part_number = kstrdup(buf, GFP_KERNEL);
+@@ -1292,6 +1302,35 @@ static int bone_capemgr_unload(struct bone_cape_slot *slot)
+
+ }
+
++/* slots_list_mutex must be taken */
++static int bone_capemgr_remove_slot(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ struct device *dev = &info->pdev->dev;
++ int ret;
++
++ if (slot == NULL)
++ return 0;
++
++ /* unload just in case */
++ ret = bone_capemgr_unload(slot);
++ if (ret != 0) {
++ dev_err(dev, "Unable to unload slot #%d\n", slot->slotno);
++ return ret;
++ }
++
++ /* if probed OK, remove the sysfs nodes */
++ if (slot->probed && !slot->probe_failed)
++ bone_cape_slot_sysfs_unregister(slot);
++
++ /* remove it from the list */
++ list_del(&slot->node);
++
++ devm_kfree(dev, slot);
++
++ return 0;
++}
++
+ static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ struct device_node *node,
+ const char *part_number, const char *version)
+@@ -1755,19 +1794,8 @@ static int bone_capemgr_remove(struct platform_device *pdev)
+ int ret;
+
+ mutex_lock(&info->slots_list_mutex);
+- list_for_each_entry_safe(slot, slotn, &info->slot_list, node) {
+-
+- /* unload just in case */
+- bone_capemgr_unload(slot);
+-
+- /* if probed OK, remove the sysfs nodes */
+- if (slot->probed && !slot->probe_failed)
+- bone_cape_slot_sysfs_unregister(slot);
+-
+- /* remove it from the list */
+- list_del(&slot->node);
+-
+- }
++ list_for_each_entry_safe(slot, slotn, &info->slot_list, node)
++ bone_capemgr_remove_slot(slot);
+ mutex_unlock(&info->slots_list_mutex);
+
+ bone_capemgr_info_sysfs_unregister(info);
diff --git a/patches/linux-3.8.13/0341-bone-capemgr-Fix-crash-when-trying-to-remove-non-exi.patch b/patches/linux-3.8.13/0341-bone-capemgr-Fix-crash-when-trying-to-remove-non-exi.patch
new file mode 100644
index 0000000..0e958c5
--- /dev/null
+++ b/patches/linux-3.8.13/0341-bone-capemgr-Fix-crash-when-trying-to-remove-non-exi.patch
@@ -0,0 +1,36 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 27 Feb 2013 18:35:09 +0200
+Subject: [PATCH] bone-capemgr: Fix crash when trying to remove non-existant
+ slot
+
+Wrong test for not-found case lead to crash. Fix.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 2656e3a..9f8da94 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -990,15 +990,12 @@ static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
+ mutex_lock(&info->slots_list_mutex);
+ list_for_each_entry(slot, &info->slot_list, node) {
+ if (slotno == slot->slotno)
+- break;
+- }
+-
+- /* found? */
+- if (slot == NULL) {
+- mutex_unlock(&info->slots_list_mutex);
+- return -ENODEV;
++ goto found;
+ }
+
++ mutex_unlock(&info->slots_list_mutex);
++ return -ENODEV;
++found:
+ ret = bone_capemgr_remove_slot(slot);
+ mutex_unlock(&info->slots_list_mutex);
+
diff --git a/patches/linux-3.8.13/0342-beaglebone-LCD7-cape-enable-PWM-and-allow-the-specif.patch b/patches/linux-3.8.13/0342-beaglebone-LCD7-cape-enable-PWM-and-allow-the-specif.patch
new file mode 100644
index 0000000..489b71b
--- /dev/null
+++ b/patches/linux-3.8.13/0342-beaglebone-LCD7-cape-enable-PWM-and-allow-the-specif.patch
@@ -0,0 +1,42 @@
+From: Jan Luebbe <jluebbe@debian.org>
+Date: Wed, 6 Mar 2013 16:38:40 +0100
+Subject: [PATCH] beaglebone: LCD7 cape: enable PWM and allow the specified
+ mode
+
+---
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index c13fe80..dc31da7 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -71,6 +71,20 @@
+ };
+
+ fragment@1 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
+ target = <&ocp>;
+
+ __overlay__ {
+@@ -220,6 +234,7 @@
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+ ti,power-gpio = <&gpio2 31 0x0>;
++ ti,allow-non-reduced-blanking-modes;
+ };
+
+ };
diff --git a/patches/linux-3.8.13/0343-bone-capemgr-Introduce-pinmux-helper.patch b/patches/linux-3.8.13/0343-bone-capemgr-Introduce-pinmux-helper.patch
new file mode 100644
index 0000000..5620578
--- /dev/null
+++ b/patches/linux-3.8.13/0343-bone-capemgr-Introduce-pinmux-helper.patch
@@ -0,0 +1,74 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 27 Feb 2013 11:33:50 +0200
+Subject: [PATCH] bone-capemgr: Introduce pinmux helper
+
+Introduce a very basic pinmux helper driver.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/cape-bone-pinmux-test-00A0.dts | 43 +++++++++++++++++++++++++
+ 2 files changed, 44 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-pinmux-test-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index efe2b90..26e9323 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -145,6 +145,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-lcd3-00A0.dtbo \
+ cape-bone-lcd3-00A2.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
++ cape-bone-pinmux-test-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/cape-bone-pinmux-test-00A0.dts b/firmware/capes/cape-bone-pinmux-test-00A0.dts
+new file mode 100644
+index 0000000..76c9656
+--- /dev/null
++++ b/firmware/capes/cape-bone-pinmux-test-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "pinctrl-test";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pinctrl_test_7: pinctrl_test_7_pins {
++ pinctrl-single,pins = <
++ 0x164 0x07 /* P9_42 muxRegOffset, OUTPUT | MODE7 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ test_helper: helper {
++ compatible = "bone-pinmux-helper";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_test_7>;
++ status = "okay";
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0344-bone-geiger-Fix-comment-to-match-the-contents.patch b/patches/linux-3.8.13/0344-bone-geiger-Fix-comment-to-match-the-contents.patch
new file mode 100644
index 0000000..ce22be7
--- /dev/null
+++ b/patches/linux-3.8.13/0344-bone-geiger-Fix-comment-to-match-the-contents.patch
@@ -0,0 +1,21 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 5 Mar 2013 18:25:32 +0200
+Subject: [PATCH] bone-geiger: Fix comment to match the contents
+
+---
+ firmware/capes/cape-bone-geiger-00A0.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
+index 4757ce7..967e03b 100644
+--- a/firmware/capes/cape-bone-geiger-00A0.dts
++++ b/firmware/capes/cape-bone-geiger-00A0.dts
+@@ -30,7 +30,7 @@
+ 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 */
++ 0x19c 0x37 /* mcasp0_ahclkr.gpio3_17, OMAP_MUX_MODE7 | INPUT_PULLUP */
+ >;
+ };
+ };
diff --git a/patches/linux-3.8.13/0345-of-overlay-Handle-I2C-devices-already-registered-by-.patch b/patches/linux-3.8.13/0345-of-overlay-Handle-I2C-devices-already-registered-by-.patch
new file mode 100644
index 0000000..a5e1ce6
--- /dev/null
+++ b/patches/linux-3.8.13/0345-of-overlay-Handle-I2C-devices-already-registered-by-.patch
@@ -0,0 +1,54 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 4 Mar 2013 21:46:13 +0200
+Subject: [PATCH] of-overlay: Handle I2C devices already registered by new
+ busses.
+
+I2C is special, as in the busses register the child i2c clients.
+So do not register the client device twice.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/overlay.c | 29 ++++++++++++++++++-----------
+ 1 file changed, 18 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index 41b883f..29078c7 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -424,18 +424,25 @@ static int of_overlay_device_entry_change(struct of_overlay_info *ovinfo,
+ de->pdev = pdev;
+
+ } else {
+- pr_debug("%s: creating new i2c_client device "
+- "new_node='%s' %p\n",
+- __func__, de->np->full_name, de->np);
+
+- client = of_i2c_register_device(adap, de->np);
+-
+- if (client == NULL) {
+- pr_warn("%s: Failed to create i2c client device "
+- "for '%s'\n",
+- __func__, de->np->full_name);
+- } else
+- de->client = client;
++ client = of_find_i2c_device_by_node(de->np);
++ if (client != NULL) {
++ /* bus already created the device; do nothing */
++ put_device(&client->dev);
++ } else {
++ pr_debug("%s: creating new i2c_client device "
++ "new_node='%s' %p\n",
++ __func__, de->np->full_name, de->np);
++
++ client = of_i2c_register_device(adap, de->np);
++
++ if (client == NULL) {
++ pr_warn("%s: Failed to create i2c client device "
++ "for '%s'\n",
++ __func__, de->np->full_name);
++ } else
++ de->client = client;
++ }
+ }
+
+ } else {
diff --git a/patches/linux-3.8.13/0346-pinmux-helper-Add-runtime-configuration-capability.patch b/patches/linux-3.8.13/0346-pinmux-helper-Add-runtime-configuration-capability.patch
new file mode 100644
index 0000000..7720da7
--- /dev/null
+++ b/patches/linux-3.8.13/0346-pinmux-helper-Add-runtime-configuration-capability.patch
@@ -0,0 +1,171 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 6 Mar 2013 19:37:53 +0200
+Subject: [PATCH] pinmux-helper: Add runtime configuration capability
+
+Pinctrl already supports multiple states. Just make them visible.
+---
+ drivers/misc/cape/beaglebone/bone-pinmux-helper.c | 143 ++++++++++++++++++++-
+ 1 file changed, 138 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/bone-pinmux-helper.c b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
+index ba3922d..84058e1 100644
+--- a/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
++++ b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
+@@ -38,19 +38,152 @@ static const struct of_device_id bone_pinmux_helper_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, bone_pinmux_helper_of_match);
+
++struct pinmux_helper_data {
++ struct pinctrl *pinctrl;
++ char *selected_state_name;
++};
++
++static ssize_t pinmux_helper_show_state(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pinmux_helper_data *data = platform_get_drvdata(pdev);
++ const char *name;
++ int len;
++
++ name = data->selected_state_name;
++ if (name == NULL || strlen(name) == 0)
++ name = "none";
++ return sprintf(buf, "%s\n", name);
++}
++
++static ssize_t pinmux_helper_store_state(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pinmux_helper_data *data = platform_get_drvdata(pdev);
++ struct pinctrl_state *state;
++ char *state_name;
++ char *s;
++ int err;
++
++ /* duplicate (as a null terminated string) */
++ state_name = devm_kzalloc(dev, count + 1, GFP_KERNEL);
++ if (state_name == NULL)
++ return -ENOMEM;
++ memcpy(state_name, buf, count);
++ state_name[count] = '\0';
++
++ /* and chop off newline */
++ s = strchr(state_name, '\n');
++ if (s != NULL)
++ *s = '\0';
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(data->pinctrl, state_name);
++ if (!IS_ERR(state)) {
++ err = pinctrl_select_state(data->pinctrl, state);
++ if (err != 0)
++ dev_err(dev, "Failed to select state %s\n",
++ state_name);
++ } else {
++ dev_err(dev, "Failed to find state %s\n", state_name);
++ err = PTR_RET(state);
++ }
++
++ if (err == 0) {
++ devm_kfree(dev, data->selected_state_name);
++ data->selected_state_name = state_name;
++ }
++
++ return err ? err : count;
++}
++
++static DEVICE_ATTR(state, S_IWUSR | S_IRUGO,
++ pinmux_helper_show_state, pinmux_helper_store_state);
++
++static struct attribute *pinmux_helper_attributes[] = {
++ &dev_attr_state.attr,
++ NULL
++};
++
++static const struct attribute_group pinmux_helper_attr_group = {
++ .attrs = pinmux_helper_attributes,
++};
++
+ static int bone_pinmux_helper_probe(struct platform_device *pdev)
+ {
+- struct pinctrl *pinctrl;
++ struct device *dev = &pdev->dev;
++ struct pinmux_helper_data *data;
++ struct pinctrl_state *state;
++ char *state_name;
++ int err;
++
++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
++ if (data == NULL) {
++ dev_err(dev, "Failed to allocate data\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ state_name = devm_kzalloc(dev, strlen(PINCTRL_STATE_DEFAULT) + 1,
++ GFP_KERNEL);
++ if (state_name == NULL) {
++ dev_err(dev, "Failed to allocate state name\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ data->selected_state_name = state_name;
++ strcpy(data->selected_state_name, PINCTRL_STATE_DEFAULT);
+
+- pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ platform_set_drvdata(pdev, data);
+
+- /* don't bother with anything */
+- return PTR_RET(pinctrl);
++ data->pinctrl = devm_pinctrl_get(dev);
++ if (IS_ERR(data->pinctrl)) {
++ dev_err(dev, "Failed to get pinctrl\n");
++ err = PTR_RET(data->pinctrl);
++ goto err_no_pinctrl;
++ }
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(data->pinctrl,
++ data->selected_state_name);
++ if (!IS_ERR(state)) {
++ err = pinctrl_select_state(data->pinctrl, state);
++ if (err != 0) {
++ dev_err(dev, "Failed to select default state\n");
++ goto err_no_state;
++ }
++ } else {
++ data->selected_state_name = '\0';
++ }
++
++ /* Register sysfs hooks */
++ err = sysfs_create_group(&dev->kobj, &pinmux_helper_attr_group);
++ if (err) {
++ dev_err(dev, "Failed to create sysfs group\n");
++ goto err_no_sysfs;
++ }
++
++ return 0;
++
++err_no_sysfs:
++err_no_state:
++ devm_pinctrl_put(data->pinctrl);
++err_no_pinctrl:
++ devm_kfree(dev, data);
++err_no_mem:
++ return err;
+ }
+
+ static int bone_pinmux_helper_remove(struct platform_device *pdev)
+ {
+- /* nothing more is needed */
++ struct pinmux_helper_data *data = platform_get_drvdata(pdev);
++ struct device *dev = &pdev->dev;
++
++ sysfs_remove_group(&dev->kobj, &pinmux_helper_attr_group);
++ devm_pinctrl_put(data->pinctrl);
++ devm_kfree(dev, data);
++
+ return 0;
+ }
+
diff --git a/patches/linux-3.8.13/0347-pinmux-helper-Switch-to-using-kmalloc.patch b/patches/linux-3.8.13/0347-pinmux-helper-Switch-to-using-kmalloc.patch
new file mode 100644
index 0000000..d0b0bd8
--- /dev/null
+++ b/patches/linux-3.8.13/0347-pinmux-helper-Switch-to-using-kmalloc.patch
@@ -0,0 +1,64 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 7 Mar 2013 09:54:38 +0200
+Subject: [PATCH] pinmux-helper: Switch to using kmalloc
+
+devm_kfree warned out... why? no idea.
+---
+ drivers/misc/cape/beaglebone/bone-pinmux-helper.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/bone-pinmux-helper.c b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
+index 84058e1..5074365 100644
+--- a/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
++++ b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
+@@ -26,6 +26,7 @@
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/of_gpio.h>
++#include <linux/slab.h>
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/pinctrl/pinmux.h>
+ #include <linux/pinctrl/consumer.h>
+@@ -49,7 +50,6 @@ static ssize_t pinmux_helper_show_state(struct device *dev,
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pinmux_helper_data *data = platform_get_drvdata(pdev);
+ const char *name;
+- int len;
+
+ name = data->selected_state_name;
+ if (name == NULL || strlen(name) == 0)
+@@ -68,7 +68,7 @@ static ssize_t pinmux_helper_store_state(struct device *dev,
+ int err;
+
+ /* duplicate (as a null terminated string) */
+- state_name = devm_kzalloc(dev, count + 1, GFP_KERNEL);
++ state_name = kmalloc(count + 1, GFP_KERNEL);
+ if (state_name == NULL)
+ return -ENOMEM;
+ memcpy(state_name, buf, count);
+@@ -92,7 +92,7 @@ static ssize_t pinmux_helper_store_state(struct device *dev,
+ }
+
+ if (err == 0) {
+- devm_kfree(dev, data->selected_state_name);
++ kfree(data->selected_state_name);
+ data->selected_state_name = state_name;
+ }
+
+@@ -125,7 +125,7 @@ static int bone_pinmux_helper_probe(struct platform_device *pdev)
+ err = -ENOMEM;
+ goto err_no_mem;
+ }
+- state_name = devm_kzalloc(dev, strlen(PINCTRL_STATE_DEFAULT) + 1,
++ state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
+ GFP_KERNEL);
+ if (state_name == NULL) {
+ dev_err(dev, "Failed to allocate state name\n");
+@@ -181,6 +181,7 @@ static int bone_pinmux_helper_remove(struct platform_device *pdev)
+ struct device *dev = &pdev->dev;
+
+ sysfs_remove_group(&dev->kobj, &pinmux_helper_attr_group);
++ kfree(data->selected_state_name);
+ devm_pinctrl_put(data->pinctrl);
+ devm_kfree(dev, data);
+
diff --git a/patches/linux-3.8.13/0348-i2c-DTify-pca954x-driver.patch b/patches/linux-3.8.13/0348-i2c-DTify-pca954x-driver.patch
new file mode 100644
index 0000000..377d395
--- /dev/null
+++ b/patches/linux-3.8.13/0348-i2c-DTify-pca954x-driver.patch
@@ -0,0 +1,151 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 4 Mar 2013 18:53:36 +0200
+Subject: [PATCH] i2c: DTify pca954x driver
+
+Add some basic I2C bindings to the mux-pca954x driver.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/i2c/muxes/i2c-mux-pca954x.c | 105 ++++++++++++++++++++++++++++++++++-
+ 1 file changed, 104 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
+index 8e43872..25aa010 100644
+--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
++++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
+@@ -41,9 +41,12 @@
+ #include <linux/device.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-mux.h>
++#include <linux/of.h>
++#include <linux/of_i2c.h>
+
+ #include <linux/i2c/pca954x.h>
+
++
+ #define PCA954X_MAX_NCHANS 8
+
+ enum pca_type {
+@@ -62,6 +65,10 @@ struct pca954x {
+ struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
+
+ u8 last_chan; /* last register value */
++#ifdef CONFIG_OF
++ struct pca954x_platform_data of_pdata;
++ struct pca954x_platform_mode of_modes[8]; /* maximum is 8 */
++#endif
+ };
+
+ struct chip_desc {
+@@ -117,6 +124,89 @@ static const struct i2c_device_id pca954x_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, pca954x_id);
+
++/* cast the type enum to a ptr */
++#define PCA_TYPE_2_PTR(x) ((const void *)(unsigned long)(x))
++/* cast the ptr back to an enum */
++#define PCA_PTR_2_TYPE(x) ((enum pca_type)(unsigned long)(x))
++
++static const struct of_device_id pca954x_of_match[] = {
++ { .compatible = "nxp,pca9540", PCA_TYPE_2_PTR(pca_9540), },
++ { .compatible = "nxp,pca9542", PCA_TYPE_2_PTR(pca_9542), },
++ { .compatible = "nxp,pca9543", PCA_TYPE_2_PTR(pca_9543), },
++ { .compatible = "nxp,pca9544", PCA_TYPE_2_PTR(pca_9544), },
++ { .compatible = "nxp,pca9545", PCA_TYPE_2_PTR(pca_9545), },
++ { .compatible = "nxp,pca9546", PCA_TYPE_2_PTR(pca_9546), },
++ { .compatible = "nxp,pca9547", PCA_TYPE_2_PTR(pca_9547), },
++ { .compatible = "nxp,pca9548", PCA_TYPE_2_PTR(pca_9548), },
++ { },
++};
++MODULE_DEVICE_TABLE(of, pca954x_of_match);
++
++#ifdef CONFIG_OF
++static int pca954x_get_ofdata(struct i2c_client *client,
++ struct pca954x_platform_data *pdata, struct pca954x *data)
++{
++ struct device_node *node = client->dev.of_node;
++ const struct of_device_id *id_match;
++ struct device_node *anode;
++ int num, busses_no, busses_max, ret;
++ u32 val;
++
++ if (!node)
++ return -ENODEV;
++
++ /* match the compatible device */
++ id_match = of_match_node(pca954x_of_match, node);
++ if (id_match == NULL) {
++ dev_err(&client->dev, "No pca954x compatible node!\n");
++ return -ENODEV;
++ }
++ data->type = PCA_PTR_2_TYPE(id_match->data);
++ busses_max = chips[data->type].nchans;
++
++ /* for each child node which is compatible to us */
++ busses_no = 0;
++ for_each_available_child_of_node(node, anode) {
++ if (!of_device_is_compatible(anode, "nxp,pca954x-bus"))
++ continue;
++ ret = of_property_read_u32(anode, "reg", &val);
++ if (ret != 0)
++ continue;
++ busses_no++;
++ }
++
++ if (busses_no == 0) {
++ dev_err(&client->dev, "No busses found!\n");
++ return -ENODEV;
++ }
++
++ /* ok, fill in everything now */
++ num = 0;
++ for_each_available_child_of_node(node, anode) {
++ if (!of_device_is_compatible(anode, "nxp,pca954x-bus"))
++ continue;
++ ret = of_property_read_u32(anode, "reg", &val);
++ if (ret != 0)
++ continue;
++ pdata->modes[num].adap_id = 0; /* get adapter id */
++ pdata->modes[num].class = 0; /* classs always 0 */
++ pdata->modes[num].deselect_on_exit =
++ of_property_read_bool(anode, "nxp,deselect-on-exit");
++ num++;
++ }
++ pdata->num_modes = num;
++
++ return 0;
++}
++#else
++static int pca954x_get_ofdata(struct i2c_client *client,
++ struct pca954x_platform_data *pdata, struct pca954x *data)
++{
++ return -ENODEV; /* no of data (should never be called) */
++}
++#endif /* CONFIG_OF */
++
++
+ /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ for this as they will try to lock adapter a second time */
+ static int pca954x_reg_write(struct i2c_adapter *adap,
+@@ -210,7 +300,20 @@ static int pca954x_probe(struct i2c_client *client,
+ goto exit_free;
+ }
+
+- data->type = id->driver_data;
++ /* platform device case; substitute platform data */
++ if (pdata == NULL) {
++ /* point to the filled in pdata */
++ pdata = &data->of_pdata;
++ pdata->modes = data->of_modes;
++ ret = pca954x_get_ofdata(client, pdata, data);
++ if (ret != 0) {
++ dev_err(&client->dev,
++ "Failed to get OF data\n");
++ goto exit_free;
++ }
++ } else
++ data->type = id->driver_data;
++
+ data->last_chan = 0; /* force the first selection */
+
+ /* Now create an adapter for each channel */
diff --git a/patches/linux-3.8.13/0349-tty-Add-JHD629-I2C-LCD-Keypad-TTY-driver.patch b/patches/linux-3.8.13/0349-tty-Add-JHD629-I2C-LCD-Keypad-TTY-driver.patch
new file mode 100644
index 0000000..144694b
--- /dev/null
+++ b/patches/linux-3.8.13/0349-tty-Add-JHD629-I2C-LCD-Keypad-TTY-driver.patch
@@ -0,0 +1,1042 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 5 Mar 2013 18:23:10 +0200
+Subject: [PATCH] tty: Add JHD629 I2C LCD/Keypad TTY driver
+
+Add a driver for these kind of devices which include an LCD display and
+a keypad. Although they come in rs232 form, the I2C ones are the most
+common ones.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ Documentation/devices.txt | 4 +
+ drivers/tty/Kconfig | 10 +
+ drivers/tty/Makefile | 3 +
+ drivers/tty/jhd629-i2c.c | 959 ++++++++++++++++++++++++++++++++++++++
+ include/uapi/linux/serial_core.h | 3 +
+ 5 files changed, 979 insertions(+)
+ create mode 100644 drivers/tty/jhd629-i2c.c
+
+diff --git a/Documentation/devices.txt b/Documentation/devices.txt
+index 08f01e7..38f5c7a 100644
+--- a/Documentation/devices.txt
++++ b/Documentation/devices.txt
+@@ -2810,6 +2810,10 @@ Your cooperation is appreciated.
+ 211 = /dev/ttyMAX2 MAX3100 serial port 2
+ 212 = /dev/ttyMAX3 MAX3100 serial port 3
+
++ 220 = /dev/ttyJHD0 JHD629 pseudo serial port 0
++ 221 = /dev/ttyJHD1 JHD629 pseudo serial port 1
++ ..
++
+ 205 char Low-density serial ports (alternate device)
+ 0 = /dev/culu0 Callout device for ttyLU0
+ 1 = /dev/culu1 Callout device for ttyLU1
+diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
+index 0ecf22b..f78b254 100644
+--- a/drivers/tty/Kconfig
++++ b/drivers/tty/Kconfig
+@@ -164,6 +164,16 @@ config BFIN_JTAG_COMM_CONSOLE
+ bool "Console on Blackfin JTAG"
+ depends on BFIN_JTAG_COMM=y
+
++config JHD629_I2C
++ bool "JHD629 I2C support"
++ depends on I2C && OF
++ select SERIAL_CORE
++ default n
++ help
++ This selects support for a pseudo TTY on I2Ced JHD629
++
++ Say Y here if you want to support this.
++
+ config SERIAL_NONSTANDARD
+ bool "Non-standard serial port support"
+ depends on HAS_IOMEM
+diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
+index 2953059..d5df8f5 100644
+--- a/drivers/tty/Makefile
++++ b/drivers/tty/Makefile
+@@ -29,3 +29,6 @@ obj-$(CONFIG_SYNCLINK) += synclink.o
+ obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o
+
+ obj-y += ipwireless/
++
++# JHD pseudo TTY
++obj-$(CONFIG_JHD629_I2C) += jhd629-i2c.o
+diff --git a/drivers/tty/jhd629-i2c.c b/drivers/tty/jhd629-i2c.c
+new file mode 100644
+index 0000000..8ce7c94
+--- /dev/null
++++ b/drivers/tty/jhd629-i2c.c
+@@ -0,0 +1,959 @@
++/*
++ * jhd629-i2c.c: Serial driver (over I2C) for the JHD629 series of modules
++ *
++ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/serial_core.h>
++#include <linux/serial.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/regmap.h>
++#include <linux/gpio.h>
++#include <linux/i2c.h>
++#include <linux/idr.h>
++#include <linux/delay.h>
++#include <linux/timer.h>
++#include <asm/bitops.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/err.h>
++
++#define JHD629_MAJOR 204
++#define JHD629_MINOR 220
++
++/* maximum 4 instances... (meh; tty layer is archaic) */
++#define JHD629_MAX_INSTANCES 4
++
++/* just one byte */
++#define JHD629_FIFO_SIZE 1
++
++struct jhd629_port {
++ int id;
++ struct i2c_client *client;
++
++ struct uart_driver uart;
++ struct uart_port port;
++
++ const char *name;
++
++ struct workqueue_struct *tx_wq;
++ struct work_struct tx_work;
++ struct workqueue_struct *rx_wq;
++ struct work_struct rx_work;
++
++ struct mutex lock;
++
++ int keypad_irq;
++ char keypad_gpio_name[32];
++ struct timer_list poll_timer;
++ unsigned int poll_timer_running : 1;
++
++ /* escape in progress */
++ int esc_mode;
++#define ESC_NONE 0
++#define ESC_ESC 1
++#define ESC_LBRACKET 2
++ int esc_next;
++ char esc_buf[64];
++
++ /* configuration data */
++ int rows, cols;
++ char keymap[16 + 1]; /* 4x4 + 1 '\0' */
++ int keypad_gpio;
++ int poll_period;
++};
++
++static DEFINE_IDA(jhd629_ida);
++
++static void jhd629_send_byte(struct jhd629_port *s, u8 ch)
++{
++ i2c_smbus_write_byte(s->client, ch);
++}
++
++static int jhd629_recv_byte(struct jhd629_port *s)
++{
++ return i2c_smbus_read_byte(s->client);
++}
++
++static void jhd629_send_block(struct jhd629_port *s, const void *buf, int len)
++{
++ const u8 *p;
++
++ p = buf;
++ while (len-- > 0)
++ jhd629_send_byte(s, *p++);
++}
++
++static void jhd629_send_str(struct jhd629_port *s, const char *str)
++{
++ jhd629_send_block(s, str, strlen(str));
++}
++
++static void jhd629_handle_escape(struct jhd629_port *s)
++{
++ char esc_ch;
++ char *ep, *epe, *epr, *epnext;
++ int num = 0, row = 0, col = 0, qmark = 0, num_exists = 0;
++ char xmitbuf[8];
++
++ if (s->esc_mode == ESC_NONE || s->esc_next <= 0)
++ goto esc_end;
++
++ /* fast access to escape buffer */
++ ep = s->esc_buf;
++
++ /* same to the end of the buffer */
++ epe = s->esc_buf + s->esc_next;
++
++ /* single character escapes */
++ if (ep[0] != '[') {
++ esc_ch = ep[0];
++
++ switch (esc_ch) {
++ case 'c':
++ dev_dbg(s->port.dev, "esc-RESET\n");
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 'c';
++ jhd629_send_block(s, xmitbuf, 2);
++ break;
++ case 'a':
++ dev_dbg(s->port.dev, "esc-ACK\n");
++ /* I2C does not have ACK */
++ break;
++ default:
++ /* nothing */
++ break;
++ }
++ } else {
++
++ esc_ch = epe[-1]; /* last character */
++
++ dev_dbg(s->port.dev, "handle escape 0x1b %c\n", esc_ch);
++ num = 1;
++
++ epr = ep + 1;
++ qmark = 0;
++ if (*epr == '?') {
++ epr++;
++ qmark = 1;
++ }
++ /* digit?, read it */
++ if (*epr >= '0' && *epr <= '9') {
++ num_exists = 1;
++ num = simple_strtoul(epr, &epnext, 10);
++ if (*epnext == ',' || *epnext == ';') {
++ row = num;
++ col = simple_strtoul(epnext + 1, NULL, 10);
++ }
++ } else {
++ num_exists = 0;
++ num = 1;
++ row = 1;
++ col = 1;
++ }
++
++ if (!qmark) {
++ switch (esc_ch) {
++ case 'A':
++ dev_dbg(s->port.dev, "esc-UP%d\n", num);
++ while (num-- > 0)
++ jhd629_send_str(s, "\x1b\x20");
++ break;
++ case 'B':
++ dev_dbg(s->port.dev, "esc-DOWN%d\n", num);
++ while (num-- > 0)
++ jhd629_send_str(s, "\x1b\x21");
++ break;
++ case 'C':
++ dev_dbg(s->port.dev, "esc-RIGHT%d\n", num);
++ while (num-- > 0)
++ jhd629_send_str(s, "\x1b\x22");
++ break;
++ case 'D':
++ dev_dbg(s->port.dev, "esc-RIGHT%d\n", num);
++ while (num-- > 0)
++ jhd629_send_str(s, "\x1b\x23");
++ break;
++ case 'H':
++ dev_dbg(s->port.dev, "esc-HOME(%d;%d)\n", row, col);
++
++ if (col != 1 || row != 1) {
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x24;
++ xmitbuf[2] = (u8)row;
++ xmitbuf[3] = (u8)col;
++ jhd629_send_block(s, xmitbuf, 4);
++ } else
++ jhd629_send_str(s, "\x1b\x25");
++ break;
++
++ case 'E':
++ dev_dbg(s->port.dev, "esc-DIRECT%d\n", num);
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x01;
++ xmitbuf[2] = num;
++ jhd629_send_block(s, xmitbuf, 3);
++ break;
++
++ case 'L':
++ dev_dbg(s->port.dev, "esc-LINES%d\n", num);
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x30;
++ xmitbuf[2] = num;
++ jhd629_send_block(s, xmitbuf, 3);
++ break;
++
++ case 'c':
++ dev_dbg(s->port.dev, "esc-COLUMNS%d\n", num);
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x31;
++ xmitbuf[2] = num;
++ jhd629_send_block(s, xmitbuf, 3);
++ break;
++
++ case 'b':
++ dev_dbg(s->port.dev, "esc-BAUD%d\n", num);
++ /* ignored */
++ break;
++
++ case 'd':
++ dev_dbg(s->port.dev, "esc-LF/CR%d\n", num);
++ /* ignored */
++ break;
++
++ case 'x':
++ dev_dbg(s->port.dev, "esc-VERTSCROLL%d\n", num);
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x45;
++ xmitbuf[2] = num;
++ jhd629_send_block(s, xmitbuf, 3);
++ break;
++
++ case 'a':
++ dev_dbg(s->port.dev, "esc-I2CADDR%d\n", num);
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x42;
++ xmitbuf[2] = 0x55;
++ xmitbuf[3] = 0x37;
++ xmitbuf[4] = num;
++ jhd629_send_block(s, xmitbuf, 5);
++ break;
++
++ case 'J':
++ if (num == 4) {
++ dev_dbg(s->port.dev, "esc-RESETEEPROM\n");
++ jhd629_send_str(s, "\x1b\x44");
++ } else if (num == 2) {
++ dev_dbg(s->port.dev, "esc-CLEARSCR\n");
++ jhd629_send_str(s, "\x1b\x50");
++ }
++ break;
++ case 'K':
++ if (!num_exists) {
++ dev_dbg(s->port.dev, "esc-CLRLINERIGHT\n");
++ jhd629_send_str(s, "\x1b\x51");
++ } else if (num == 1) {
++ dev_dbg(s->port.dev, "esc-CLRLINELEFT\n");
++ jhd629_send_str(s, "\x1b\x52");
++ } else if (num == 2) {
++ dev_dbg(s->port.dev, "esc-CLRLINE\n");
++ jhd629_send_str(s, "\x1b\x53");
++ }
++ break;
++ }
++ } else {
++ switch (esc_ch) {
++ case 'I':
++ if (num == 25) {
++ dev_dbg(s->port.dev, "esc-CURSOROFF\n");
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x01;
++ xmitbuf[2] = 0x0c;
++ jhd629_send_block(s, xmitbuf, 3);
++ } else if (num == 26) {
++ dev_dbg(s->port.dev, "esc-BACKLIGHTOFF\n");
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x03;
++ xmitbuf[2] = 0x00;
++ jhd629_send_block(s, xmitbuf, 3);
++ }
++ break;
++ case 'h':
++ if (num == 25) {
++ dev_dbg(s->port.dev, "esc-CURSORON\n");
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x01;
++ xmitbuf[2] = 0x0e;
++ jhd629_send_block(s, xmitbuf, 3);
++ } else if (num == 26) {
++ dev_dbg(s->port.dev, "esc-BACKLIGHTON\n");
++ xmitbuf[0] = 0x1b;
++ xmitbuf[1] = 0x03;
++ xmitbuf[2] = 0x01;
++ jhd629_send_block(s, xmitbuf, 3);
++ }
++ break;
++ case 'd':
++ break;
++ case 'f':
++ break;
++ case 'S':
++ break;
++ }
++ }
++ }
++
++esc_end:
++ s->esc_mode = ESC_NONE;
++ s->esc_next = 0;
++}
++
++static void jh629_cancel_escape(struct jhd629_port *s)
++{
++ s->esc_mode = ESC_NONE;
++ s->esc_next = 0;
++}
++
++/* lock should be taken */
++static void jhd629_tx_char(struct jhd629_port *s, int ch)
++{
++ /* normal, non-escaped output */
++ if (s->esc_mode == ESC_NONE) {
++ switch (ch) {
++ case 0x1b: /* ESC */
++ s->esc_mode = ESC_ESC;
++ s->esc_next = 0;
++ s->esc_buf[s->esc_next] = '\0';
++ break;
++ case '\n': /* LF */
++ jhd629_send_str(s, "\x1b\x0a");
++ break;
++ case '\r': /* CR */
++ jhd629_send_str(s, "\x1b\x0d");
++ break;
++ case '\b': /* BS */
++ /* ignored */
++ break;
++ default:
++ jhd629_send_byte(s, ch);
++ break;
++ }
++ return;
++ }
++
++ /* an escaped mode */
++
++ /* append to escape buffer */
++ if (s->esc_next < ARRAY_SIZE(s->esc_buf) - 1) {
++ s->esc_buf[s->esc_next++] = ch;
++ s->esc_buf[s->esc_next] = '\0';
++ }
++
++ switch (s->esc_mode) {
++
++ case ESC_NONE:
++ /* never happens */
++ break;
++
++ case ESC_ESC:
++ switch (ch) {
++ case '[': /* left bracket */
++ s->esc_mode = ESC_LBRACKET;
++ break;
++ case 'a':
++ case 'c':
++ jhd629_handle_escape(s);
++ break;
++ default:
++ /* unknown escape sequence (ignore) */
++ jh629_cancel_escape(s);
++ break;
++ }
++ break;
++
++ case ESC_LBRACKET:
++ switch (ch) {
++ case '0': case '1': case '2': case '3': case '4':
++ case '5': case '6': case '7': case '8': case '9':
++ case ';': case '?': case ',':
++ break;
++ default:
++ jhd629_handle_escape(s);
++ break;
++ }
++ }
++}
++
++static void jhd629_handle_rx(struct jhd629_port *s)
++{
++ struct tty_struct *tty = tty_port_tty_get(&s->port.state->port);
++ int rx_len, rx_cnt, ch;
++ int row, col;
++
++ if (!tty)
++ return;
++
++ /* find out how many keys in the buffer */
++ rx_cnt = 0;
++ for (;;) {
++ jhd629_send_byte(s, 0x1b);
++ jhd629_send_byte(s, 0x10);
++ rx_len = jhd629_recv_byte(s);
++ if (rx_len <= 0)
++ break;
++
++ /* now get key scan code */
++ while (rx_len--) {
++
++ jhd629_send_byte(s, 0x1b);
++ jhd629_send_byte(s, 0x11);
++ ch = jhd629_recv_byte(s);
++ if (ch <= 0)
++ continue;
++
++ row = ffz(ch & 0xf);
++ col = ffz((ch >> 4) & 0xf);
++
++ ch = s->keymap[row * 4 + col];
++
++ rx_cnt++;
++
++ s->port.icount.rx++;
++ if (uart_handle_sysrq_char(s->port, ch))
++ continue;
++
++ dev_dbg(s->port.dev, "rx 0x%02x\n", (int)ch & 0xff);
++
++ uart_insert_char(&s->port, 0, 0, ch, TTY_NORMAL);
++ }
++ }
++
++ if (rx_cnt > 0)
++ tty_flip_buffer_push(tty);
++
++ tty_kref_put(tty);
++}
++
++static void jhd629_handle_tx(struct jhd629_port *s)
++{
++ struct circ_buf *xmit = &s->port.state->xmit;
++ unsigned int to_send;
++
++ if (unlikely(s->port.x_char)) {
++
++ jhd629_tx_char(s, s->port.x_char);
++
++ s->port.icount.tx++;
++ s->port.x_char = 0;
++ return;
++ }
++
++ if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
++ return;
++
++ /* Get length of data pending in circular buffer */
++ to_send = uart_circ_chars_pending(xmit);
++ if (likely(to_send)) {
++
++ /* Add data to send */
++ s->port.icount.tx += to_send;
++ while (to_send--) {
++
++ jhd629_tx_char(s, xmit->buf[xmit->tail]);
++
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++ };
++ }
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&s->port);
++}
++
++static void jhd629_tx_wq_proc(struct work_struct *ws)
++{
++ struct jhd629_port *s = container_of(ws, struct jhd629_port, tx_work);
++
++ mutex_lock(&s->lock);
++ jhd629_handle_tx(s);
++ mutex_unlock(&s->lock);
++}
++
++static void jhd629_rx_wq_proc(struct work_struct *ws)
++{
++ struct jhd629_port *s = container_of(ws, struct jhd629_port, rx_work);
++
++ mutex_lock(&s->lock);
++ jhd629_handle_rx(s);
++ mutex_unlock(&s->lock);
++}
++
++static void jhd629_start_tx(struct uart_port *port)
++{
++ struct jhd629_port *s = container_of(port, struct jhd629_port, port);
++
++ queue_work(s->tx_wq, &s->tx_work);
++}
++
++static void jhd629_stop_tx(struct uart_port *port)
++{
++ /* Do nothing */
++}
++
++static void jhd629_stop_rx(struct uart_port *port)
++{
++ struct jhd629_port *s = container_of(port, struct jhd629_port, port);
++
++ mutex_lock(&s->lock);
++
++ if (s->poll_timer_running) {
++ del_timer_sync(&s->poll_timer);
++ s->poll_timer_running = 0;
++ }
++
++ mutex_unlock(&s->lock);
++}
++
++static unsigned int jhd629_tx_empty(struct uart_port *port)
++{
++ /* transmitter is always empty */
++ return TIOCSER_TEMT;
++}
++
++static void jhd629_enable_ms(struct uart_port *port)
++{
++ /* Modem status not supported */
++}
++
++static unsigned int jhd629_get_mctrl(struct uart_port *port)
++{
++ /* DCD and DSR are not wired and CTS/RTS is handled automatically
++ * so just indicate DSR and CAR asserted
++ */
++ return TIOCM_DSR | TIOCM_CAR;
++}
++
++static void jhd629_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ /* DCD and DSR are not wired and CTS/RTS is hadnled automatically
++ * so do nothing
++ */
++}
++
++static void jhd629_break_ctl(struct uart_port *port, int break_state)
++{
++ /* nothing */
++}
++
++static void jhd629_set_termios(struct uart_port *port,
++ struct ktermios *termios,
++ struct ktermios *old)
++{
++ struct jhd629_port *s = container_of(port, struct jhd629_port, port);
++
++ /* we don't support much... */
++
++ mutex_lock(&s->lock);
++
++ /* Mask termios capabilities we don't support */
++ termios->c_cflag &= ~CMSPAR;
++ termios->c_iflag &= ~IXANY;
++
++ /* Set read status mask */
++ port->read_status_mask = 0;
++
++ /* Set status ignore mask */
++ port->ignore_status_mask = 0;
++
++ mutex_unlock(&s->lock);
++}
++
++static int jhd629_startup(struct uart_port *port)
++{
++ struct jhd629_port *s = container_of(port, struct jhd629_port, port);
++
++ mutex_lock(&s->lock);
++
++ if (s->keypad_irq < 0 && !s->poll_timer_running) {
++ s->poll_timer.expires = jiffies +
++ msecs_to_jiffies(s->poll_period);
++ s->poll_timer_running = 1;
++ add_timer(&s->poll_timer);
++ }
++
++ mutex_unlock(&s->lock);
++
++ return 0;
++}
++
++static void jhd629_shutdown(struct uart_port *port)
++{
++ struct jhd629_port *s = container_of(port, struct jhd629_port, port);
++
++ mutex_lock(&s->lock);
++
++ if (s->poll_timer_running) {
++ del_timer_sync(&s->poll_timer);
++ s->poll_timer_running = 0;
++ }
++
++ mutex_unlock(&s->lock);
++}
++
++static const char *jhd629_type(struct uart_port *port)
++{
++ struct jhd629_port *s = container_of(port, struct jhd629_port, port);
++
++ return (port->type == PORT_JHD629) ? s->name : NULL;
++}
++
++static int jhd629_request_port(struct uart_port *port)
++{
++ /* Do nothing */
++ return 0;
++}
++
++static void jhd629_release_port(struct uart_port *port)
++{
++ /* Do nothing */
++}
++
++static void jhd629_config_port(struct uart_port *port, int flags)
++{
++ if (flags & UART_CONFIG_TYPE)
++ port->type = PORT_JHD629;
++}
++
++static int jhd629_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++ if (ser->type == PORT_UNKNOWN || ser->type == PORT_JHD629)
++ return 0;
++
++ return -EINVAL;
++}
++
++static struct uart_ops jhd629_ops = {
++ .tx_empty = jhd629_tx_empty,
++ .set_mctrl = jhd629_set_mctrl,
++ .get_mctrl = jhd629_get_mctrl,
++ .stop_tx = jhd629_stop_tx,
++ .start_tx = jhd629_start_tx,
++ .stop_rx = jhd629_stop_rx,
++ .enable_ms = jhd629_enable_ms,
++ .break_ctl = jhd629_break_ctl,
++ .startup = jhd629_startup,
++ .shutdown = jhd629_shutdown,
++ .set_termios = jhd629_set_termios,
++ .type = jhd629_type,
++ .request_port = jhd629_request_port,
++ .release_port = jhd629_release_port,
++ .config_port = jhd629_config_port,
++ .verify_port = jhd629_verify_port,
++};
++
++static irqreturn_t jhd629_keypad_irq(int irq, void *dev_id)
++{
++ struct jhd629_port *s = dev_id;
++
++ /* just queue the check */
++ queue_work(s->rx_wq, &s->rx_work);
++
++ return IRQ_HANDLED;
++}
++
++static void jhd629_poll_timer(unsigned long ptr)
++{
++ struct jhd629_port *s = (void *)ptr;
++
++ /* check for input in the rx work queue */
++ queue_work(s->rx_wq, &s->rx_work);
++
++ /* schedule next timer poll */
++ s->poll_timer.expires = jiffies +
++ msecs_to_jiffies(s->poll_period);
++ add_timer(&s->poll_timer);
++}
++
++/* we only support DT for now */
++static int jhd629_setup(struct jhd629_port *s)
++{
++ struct device_node *node = s->client->dev.of_node;
++ const char *keymap;
++ static const char *default_keymap =
++ "123A"
++ "456B"
++ "789C"
++ "*0#D";
++ u32 val;
++
++ /* rows */
++ if (of_property_read_u32(node, "rows", &val) == 0)
++ s->rows = val;
++ else
++ s->rows = 4;
++
++ /* columns */
++ if (of_property_read_u32(node, "columns", &val) == 0)
++ s->cols = val;
++ else
++ s->cols = 20;
++
++ /* keymap */
++ if (of_property_read_string(node, "keymap", &keymap) != 0)
++ keymap = default_keymap;
++ strncpy(s->keymap, keymap, sizeof(s->keymap));
++
++ /* poll_period */
++ if (of_property_read_u32(node, "poll-period", &val) == 0)
++ s->poll_period = val;
++ else
++ s->poll_period = 250;
++
++ s->keypad_gpio = of_get_gpio_flags(node, 0, NULL);
++ if (IS_ERR_VALUE(s->keypad_gpio))
++ s->keypad_gpio = -1; /* no gpio, switch to polling */
++
++ return 0;
++}
++
++static int jhd629_apply_irq_config(struct jhd629_port *s)
++{
++ int err;
++
++ snprintf(s->keypad_gpio_name, sizeof(s->keypad_gpio_name) - 1,
++ "jhd629:%d", s->id);
++
++ err = gpio_request_one(s->keypad_gpio,
++ GPIOF_DIR_IN | GPIOF_EXPORT,
++ s->keypad_gpio_name);
++ if (err != 0) {
++ dev_err(s->port.dev, "Failed to request keypad INT\n");
++ goto err_no_req;
++ }
++
++ s->keypad_irq = gpio_to_irq(s->keypad_gpio);
++ if (IS_ERR_VALUE(s->keypad_irq)) {
++ dev_err(s->port.dev, "unable to get keypad IRQ\n");
++ err = s->keypad_irq;
++ s->keypad_irq = -1;
++ goto err_no_irq;
++ }
++
++ err = request_irq(s->keypad_irq, jhd629_keypad_irq,
++ IRQF_TRIGGER_FALLING | IRQF_SHARED,
++ s->keypad_gpio_name, s);
++ if (err != 0) {
++ dev_err(s->port.dev, "unable to request keypad irq\n");
++ goto err_no_irq;
++ }
++
++ dev_dbg(s->port.dev, "Using keyboard irq #%d\n",
++ s->keypad_irq);
++ return 0;
++
++err_no_irq:
++ s->keypad_irq = -1;
++ gpio_free(s->keypad_gpio);
++err_no_req:
++ s->keypad_gpio = -1;
++ return err;
++}
++
++static int jhd629_apply_config(struct jhd629_port *s)
++{
++ int err;
++
++ /* clear screen */
++ jhd629_send_block(s, "\x1b\x50", 2);
++
++ /* columns */
++ jhd629_send_block(s, "\x1b\x31", 2);
++ jhd629_send_byte(s, s->cols);
++
++ /* rows */
++ jhd629_send_block(s, "\x1b\x30", 2);
++ jhd629_send_byte(s, s->rows);
++
++ /* try to apply the irq config (if possible) */
++ if (s->keypad_gpio >= 0) {
++ err = jhd629_apply_irq_config(s);
++ if (err == 0)
++ return 0;
++ }
++
++ dev_dbg(s->port.dev, "Using polling period of %dms\n",
++ s->poll_period);
++
++ return 0;
++}
++
++static int jhd629_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ /* struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); */
++ struct device *dev = &client->dev;
++ struct jhd629_port *s = NULL;
++ int ret = 0;
++ struct pinctrl *pinctrl;
++
++ /* this better be early */
++ pinctrl = devm_pinctrl_get_select_default(dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(dev,
++ "pins are not configured from the driver\n");
++
++ /* Alloc port structure */
++ s = devm_kzalloc(dev, sizeof(struct jhd629_port), GFP_KERNEL);
++ if (!s) {
++ dev_err(dev, "Error allocating port structure\n");
++ return -ENOMEM;
++ }
++ s->id = -1;
++
++ s->client = client;
++ i2c_set_clientdata(client, s);
++
++ mutex_init(&s->lock);
++
++ s->id = ida_simple_get(&jhd629_ida, 0, JHD629_MAX_INSTANCES, GFP_KERNEL);
++ if (s->id < 0) {
++ dev_err(dev, "Failed to get port ID (too many instances?)\n");
++ goto err_out;
++ }
++
++ /* Register UART driver */
++ s->uart.owner = THIS_MODULE;
++ s->uart.driver_name = dev_name(dev);
++ s->uart.dev_name = "ttyJHD";
++ s->uart.major = JHD629_MAJOR;
++ s->uart.minor = JHD629_MINOR + s->id;
++ s->uart.nr = 1;
++ s->name = "JHD629";
++ ret = uart_register_driver(&s->uart);
++ if (ret != 0) {
++ dev_err(dev, "Registering UART driver failed\n");
++ goto err_out;
++ }
++
++ /* Initialize workqueue for start TX */
++ s->tx_wq = create_freezable_workqueue(dev_name(dev));
++ INIT_WORK(&s->tx_work, jhd629_tx_wq_proc);
++
++ /* Initialize workqueue for RX polling */
++ s->rx_wq = create_freezable_workqueue(dev_name(dev));
++ INIT_WORK(&s->rx_work, jhd629_rx_wq_proc);
++
++ init_timer(&s->poll_timer);
++ s->poll_timer.function = jhd629_poll_timer;
++ s->poll_timer.data = (unsigned long)s;
++
++ s->keypad_gpio = -1;
++ s->keypad_irq = -1;
++
++ /* Initialize UART port data */
++ s->port.line = 0;
++ s->port.dev = dev;
++ s->port.irq = -1;
++ s->port.type = PORT_JHD629;
++ s->port.fifosize = 1;
++ s->port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
++ s->port.iotype = UPIO_PORT;
++ s->port.membase = (void __iomem *)0xffffffff; /* Bogus value */
++ s->port.uartclk = 9600 * 16; /* emulate a 9600 baud port */
++ s->port.ops = &jhd629_ops;
++ ret = uart_add_one_port(&s->uart, &s->port);
++ if (ret != 0) {
++ dev_err(s->port.dev, "Adding a port failed\n");
++ goto err_port;
++ }
++
++ ret = jhd629_setup(s);
++ if (ret != 0) {
++ dev_err(s->port.dev, "jhd629_setup failed\n");
++ goto err_port;
++ }
++
++ ret = jhd629_apply_config(s);
++ if (ret != 0) {
++ dev_err(s->port.dev, "jhd629_apply_config failed\n");
++ goto err_port;
++ }
++
++ dev_dbg(s->port.dev, "Added port #%d\n", s->id);
++
++ return 0;
++
++err_port:
++ uart_remove_one_port(&s->uart, &s->port);
++
++err_out:
++ if (s != NULL) {
++ if (s->id >= 0) {
++ ida_simple_remove(&jhd629_ida, s->id);
++ s->id = -1;
++ }
++ }
++ i2c_set_clientdata(client, NULL);
++
++ return ret;
++}
++
++static int jhd629_remove(struct i2c_client *client)
++{
++ struct jhd629_port *s = i2c_get_clientdata(client);
++
++ dev_dbg(s->port.dev, "Removing port #%d\n", s->id);
++
++ if (s->keypad_irq >= 0) {
++ free_irq(s->keypad_irq, s);
++ gpio_free(s->keypad_gpio);
++ }
++
++ if (s->poll_timer_running) {
++ del_timer_sync(&s->poll_timer);
++ s->poll_timer_running = 0;
++ }
++
++ destroy_workqueue(s->rx_wq);
++ destroy_workqueue(s->tx_wq);
++
++ uart_remove_one_port(&s->uart, &s->port);
++ uart_unregister_driver(&s->uart);
++
++ ida_simple_remove(&jhd629_ida, s->id);
++
++ i2c_set_clientdata(client, NULL);
++
++ return 0;
++}
++
++static const struct i2c_device_id jhd629_id_table[] = {
++ { "jhd629" },
++ { }
++};
++MODULE_DEVICE_TABLE(spi, jhd629_id_table);
++
++static struct i2c_driver jhd629_driver = {
++ .driver = {
++ .name = "jhd629-i2c",
++ .owner = THIS_MODULE,
++ },
++ .probe = jhd629_probe,
++ .remove = jhd629_remove,
++ .id_table = jhd629_id_table,
++};
++module_i2c_driver(jhd629_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
++MODULE_DESCRIPTION("JHD629-i2c driver");
++MODULE_LICENSE("GPL");
+diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
+index c019b24..7ae8823 100644
+--- a/include/uapi/linux/serial_core.h
++++ b/include/uapi/linux/serial_core.h
+@@ -223,4 +223,7 @@
+ /* ARC (Synopsys) on-chip UART */
+ #define PORT_ARC 101
+
++/* JHD629 pseudo port */
++#define PORT_JHD629 102
++
+ #endif /* _UAPILINUX_SERIAL_CORE_H */
diff --git a/patches/linux-3.8.13/0350-grove-i2c-Add-rudimentary-grove-i2c-motor-control-dr.patch b/patches/linux-3.8.13/0350-grove-i2c-Add-rudimentary-grove-i2c-motor-control-dr.patch
new file mode 100644
index 0000000..c017a34
--- /dev/null
+++ b/patches/linux-3.8.13/0350-grove-i2c-Add-rudimentary-grove-i2c-motor-control-dr.patch
@@ -0,0 +1,286 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 5 Mar 2013 19:45:36 +0200
+Subject: [PATCH] grove-i2c: Add rudimentary grove i2c motor control driver.
+
+Simple solenoid handling using grove i2c.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/Kconfig | 6 ++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/grove-i2c.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 246 insertions(+)
+ create mode 100644 drivers/misc/grove-i2c.c
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index a0f75af..3c0cbf6 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -505,6 +505,12 @@ config GPEVT
+ help
+ Simply amazing!
+
++config GROVE_I2C
++ tristate "Support Grove I2C Motor Driver"
++ depends on OF && I2C
++ help
++ Say Y here to support a minimal Grove I2C Motor Driver
++
+ 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 f063b90..72aef82 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -50,4 +50,5 @@ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+ obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
+ obj-$(CONFIG_INTEL_MEI) += mei/
+ obj-$(CONFIG_GPEVT) += gpevt.o
++obj-$(CONFIG_GROVE_I2C) += grove-i2c.o
+ obj-y += cape/
+diff --git a/drivers/misc/grove-i2c.c b/drivers/misc/grove-i2c.c
+new file mode 100644
+index 0000000..8932616
+--- /dev/null
++++ b/drivers/misc/grove-i2c.c
+@@ -0,0 +1,239 @@
++/*
++ * grove-i2c.c - I2C driver module for the Grove motor drivers
++ *
++ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/mutex.h>
++
++struct grove_data {
++ struct i2c_client *client;
++ struct mutex lock;
++
++ int state[2];
++#define GS_NONE 0
++#define GS_SOLENOID_FORWARD 1
++#define GS_SOLENOID_BACKWARD 2
++
++};
++
++static void grove_send_word(struct grove_data *data, u8 cmd, u16 val)
++{
++ struct i2c_client *client = data->client;
++
++ i2c_smbus_write_word_data(data->client, cmd, val);
++}
++
++static int grove_set_state(struct grove_data *data, unsigned int which,
++ int state)
++{
++ static const u8 motor_addr[2] = { 0xa1, 0xa5 };
++
++ if (which > 1)
++ return -EINVAL;
++
++ switch (state) {
++
++ case GS_NONE:
++ /* nothing */
++ break;
++
++ case GS_SOLENOID_FORWARD:
++ grove_send_word(data, motor_addr[which], 0xff01);
++ break;
++
++ case GS_SOLENOID_BACKWARD:
++ grove_send_word(data, motor_addr[which], 0x0000);
++ break;
++
++ default:
++ /* unknown state */
++ return -EINVAL;
++ }
++
++ data->state[which] = state;
++
++ return 0;
++}
++
++static ssize_t grove_show_state(struct device *dev,
++ struct device_attribute *attr, char *buf, unsigned int which)
++{
++ struct grove_data *data = i2c_get_clientdata(to_i2c_client(dev));
++
++ if (which > 1)
++ return -EINVAL;
++
++ return sprintf(buf, "%u\n", data->state[which]);
++}
++
++static ssize_t grove_store_state(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count,
++ unsigned int which)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct grove_data *data = i2c_get_clientdata(client);
++ unsigned long val = simple_strtoul(buf, NULL, 10);
++ int ret;
++
++ if (which > 1)
++ return -EINVAL;
++
++ if (val < 0 || val > 2)
++ return -EINVAL;
++
++ mutex_lock(&data->lock);
++ ret = grove_set_state(data, which, val);
++ mutex_unlock(&data->lock);
++
++ if (ret < 0)
++ return ret;
++
++ return count;
++}
++
++static ssize_t grove_show_stateA(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return grove_show_state(dev, attr, buf, 0);
++}
++
++static ssize_t grove_store_stateA(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ return grove_store_state(dev, attr, buf, count, 0);
++}
++
++static DEVICE_ATTR(stateA, S_IWUSR | S_IRUGO,
++ grove_show_stateA, grove_store_stateA);
++
++static ssize_t grove_show_stateB(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return grove_show_state(dev, attr, buf, 1);
++}
++
++static ssize_t grove_store_stateB(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ return grove_store_state(dev, attr, buf, count, 1);
++}
++
++
++static DEVICE_ATTR(stateB, S_IWUSR | S_IRUGO,
++ grove_show_stateB, grove_store_stateB);
++
++static struct attribute *grove_attributes[] = {
++ &dev_attr_stateA.attr,
++ &dev_attr_stateB.attr,
++ NULL
++};
++
++static const struct attribute_group grove_attr_group = {
++ .attrs = grove_attributes,
++};
++
++static int grove_init_client(struct i2c_client *client)
++{
++ struct grove_data *data = i2c_get_clientdata(client);
++
++ data->state[0] = GS_NONE;
++ data->state[1] = GS_NONE;
++
++ return 0;
++}
++
++static int grove_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct device *dev = &client->dev;
++ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
++ struct grove_data *data;
++ int err = 0;
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
++ | I2C_FUNC_SMBUS_READ_BYTE_DATA))
++ return -EIO;
++
++ data = devm_kzalloc(dev, sizeof(struct grove_data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ data->client = client;
++ i2c_set_clientdata(client, data);
++
++ mutex_init(&data->lock);
++
++ /* Initialize the TSL2550 chip */
++ err = grove_init_client(client);
++ if (err) {
++ dev_err(dev, "failed to init client\n");
++ goto exit_kfree;
++ }
++
++ /* Register sysfs hooks */
++ err = sysfs_create_group(&client->dev.kobj, &grove_attr_group);
++ if (err) {
++ dev_err(dev, "failed to create sysfs group\n");
++ goto exit_kfree;
++ }
++
++ dev_info(dev, "Initialized OK\n");
++
++ return 0;
++
++exit_kfree:
++ devm_kfree(dev, data);
++ return err;
++}
++
++static int grove_remove(struct i2c_client *client)
++{
++ struct grove_data *data = i2c_get_clientdata(client);
++
++ sysfs_remove_group(&client->dev.kobj, &grove_attr_group);
++
++ devm_kfree(&client->dev, data);
++
++ return 0;
++}
++
++static const struct i2c_device_id grove_id[] = {
++ { "grove", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, grove_id);
++
++static struct i2c_driver grove_driver = {
++ .driver = {
++ .name = "grove-i2c",
++ .owner = THIS_MODULE,
++ },
++ .probe = grove_probe,
++ .remove = grove_remove,
++ .id_table = grove_id,
++};
++
++module_i2c_driver(grove_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
++MODULE_DESCRIPTION("Grove I2C Motor control driver");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.8.13/0351-tty-jhd629-i2c-Clean-keypad-buffer-when-starting.patch b/patches/linux-3.8.13/0351-tty-jhd629-i2c-Clean-keypad-buffer-when-starting.patch
new file mode 100644
index 0000000..9efd7f3
--- /dev/null
+++ b/patches/linux-3.8.13/0351-tty-jhd629-i2c-Clean-keypad-buffer-when-starting.patch
@@ -0,0 +1,32 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 6 Mar 2013 19:35:57 +0200
+Subject: [PATCH] tty: jhd629-i2c: Clean keypad buffer when starting
+
+Make sure we don't pick up key press from when the tty was closed.
+---
+ drivers/tty/jhd629-i2c.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/tty/jhd629-i2c.c b/drivers/tty/jhd629-i2c.c
+index 8ce7c94..7fd4c88 100644
+--- a/drivers/tty/jhd629-i2c.c
++++ b/drivers/tty/jhd629-i2c.c
+@@ -516,6 +516,8 @@ static void jhd629_stop_rx(struct uart_port *port)
+
+ mutex_lock(&s->lock);
+
++ /* clear keypad buffer */
++ jhd629_send_block(s, "\x1b\x14", 2);
+ if (s->poll_timer_running) {
+ del_timer_sync(&s->poll_timer);
+ s->poll_timer_running = 0;
+@@ -584,6 +586,9 @@ static int jhd629_startup(struct uart_port *port)
+
+ mutex_lock(&s->lock);
+
++ /* clear keypad buffer */
++ jhd629_send_block(s, "\x1b\x14", 2);
++
+ if (s->keypad_irq < 0 && !s->poll_timer_running) {
+ s->poll_timer.expires = jiffies +
+ msecs_to_jiffies(s->poll_period);
diff --git a/patches/linux-3.8.13/0352-am335x-bone-common-Remove-SPI-unused-pinmux-config.patch b/patches/linux-3.8.13/0352-am335x-bone-common-Remove-SPI-unused-pinmux-config.patch
new file mode 100644
index 0000000..a26755d
--- /dev/null
+++ b/patches/linux-3.8.13/0352-am335x-bone-common-Remove-SPI-unused-pinmux-config.patch
@@ -0,0 +1,31 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 7 Mar 2013 18:17:02 +0200
+Subject: [PATCH] am335x-bone-common: Remove SPI unused pinmux config
+
+Remove pinmux which is not used.
+The pinmux should be declared for a specific SPI configuration.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 23a8b01..816063c 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -27,14 +27,6 @@
+ pinctrl-names = "default";
+ pinctrl-0 = <&userleds_pins>;
+
+- spi1_pins_s0: spi1_pins_s0 {
+- pinctrl-single,pins = <
+- 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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 */
+- >;
+- };
+ userled_pins: pinmux_userled_pins {
+ pinctrl-single,pins = <
+ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
diff --git a/patches/linux-3.8.13/0353-bone-capemgr-Force-a-slot-to-load-unconditionally.patch b/patches/linux-3.8.13/0353-bone-capemgr-Force-a-slot-to-load-unconditionally.patch
new file mode 100644
index 0000000..db99338
--- /dev/null
+++ b/patches/linux-3.8.13/0353-bone-capemgr-Force-a-slot-to-load-unconditionally.patch
@@ -0,0 +1,27 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 8 Mar 2013 14:31:40 +0200
+Subject: [PATCH] bone-capemgr: Force a slot to load unconditionally
+
+Use this option to force a slot override to load unconditionally.
+Useful for testing.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 9f8da94..255c491 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -568,6 +568,10 @@ static int bone_is_compatible_override(struct device_node *node,
+ if (of_multi_prop_cmp(prop, compatible_name) == 0)
+ return 1;
+
++ /* forced override? */
++ if (of_multi_prop_cmp(prop, "force") == 0)
++ return 1;
++
+ /* final try, check if it's specified in the kernel command line */
+ if (extra_override == NULL)
+ return 0;
diff --git a/patches/linux-3.8.13/0354-beaglebone-Added-Adafruit-prototype-cape.patch b/patches/linux-3.8.13/0354-beaglebone-Added-Adafruit-prototype-cape.patch
new file mode 100644
index 0000000..445b351
--- /dev/null
+++ b/patches/linux-3.8.13/0354-beaglebone-Added-Adafruit-prototype-cape.patch
@@ -0,0 +1,195 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 22 Jan 2013 10:10:13 -0800
+Subject: [PATCH] beaglebone: Added Adafruit prototype cape
+
+Added 1.8" Adafruit prototype cape using DT overlays + cape manager
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 19 ++++
+ firmware/Makefile | 1 +
+ firmware/capes/cape-bone-adafruit-lcd-00A0.dts | 126 ++++++++++++++++++++++++
+ 3 files changed, 146 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 816063c..bcd78a6 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -168,6 +168,16 @@
+ part-number = "BB-BONE-NIXIE";
+ };
+
++ /* adafruit prototype cape */
++ slot@8 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-TFT";
++ version = "00A0";
++ manufacturer = "Adafruit";
++ part-number = "BB-BONE-TFT-01";
++ };
++
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -244,6 +254,15 @@
+ dtbo = "cape-bone-nixie-00A0.dtbo";
+ };
+ };
++
++ cape@7 {
++ part-number = "BB-BONE-TFT-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-adafruit-lcd-00A0.dtbo";
++ };
++ };
++
+ };
+ };
+ };
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 26e9323..0fd76b3 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -139,6 +139,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+ # all the generic capes
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-2g-emmc1.dtbo \
++ cape-bone-adafruit-lcd-00A0.dtbo \
+ cape-bone-dvi-00A0.dtbo \
+ cape-bone-dvi-00A1.dtbo \
+ cape-bone-dvi-00A2.dtbo \
+diff --git a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+new file mode 100644
+index 0000000..f891917
+--- /dev/null
++++ b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+@@ -0,0 +1,126 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/*
++ * Pin assignments
++ *
++ * Module Connector
++ * LITE <- P8.19
++ * MISO -> P9.29
++ * SCK <- P9.31
++ * MOSI <- P9.30
++ * TFT_CS <- P9.28
++ * CARD_CS <- NC
++ * D/C <- P9.25
++ * RESET <- P9.27
++ *
++ */
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "BB-BONE-TFT-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_backlight_pins: pinmux_pwm_backlight_pins {
++ pinctrl-single,pins = <
++ 0x020 0x4 /* gpmc_ad8.gpio0_22 | MODE4 */
++ >;
++ };
++
++ bone_adafruit_lcd_pins: pinmux_bone_adafruit_lcd_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
++
++ bone_adafruit_spi1_pins: pinmux_adafruit_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&epwmss2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++
++ fragment@3 {
++ target = <&spi0>;
++
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_adafruit_spi1_pins>;
++
++ lcd@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
++ reg = <0>;
++
++ spi-max-frequency = <8000000>;
++ spi-cpol;
++ spi-cpha;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_adafruit_lcd_pins>;
++
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++ };
++ };
++
++ fragment@4 {
++ target = <&ocp>;
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ __overlay__ {
++ adafruit-tft-backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_backlight_pins>;
++
++ pwms = <&ehrpwm2 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 */
++ };
++ };
++ };
++
++};
diff --git a/patches/linux-3.8.13/0355-tilcdc-Enable-reduced-blanking-check-only-on-DVI-sla.patch b/patches/linux-3.8.13/0355-tilcdc-Enable-reduced-blanking-check-only-on-DVI-sla.patch
new file mode 100644
index 0000000..20bcedc
--- /dev/null
+++ b/patches/linux-3.8.13/0355-tilcdc-Enable-reduced-blanking-check-only-on-DVI-sla.patch
@@ -0,0 +1,103 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 8 Mar 2013 16:39:10 +0200
+Subject: [PATCH] tilcdc: Enable reduced blanking check only on DVI/slave
+
+There's no reason to enable the check for non EDID probe cases.
+Make sure it does not activate on fixed panel timings.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 7 ++++---
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 3 ++-
+ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 2 +-
+ drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 ++-
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 3 ++-
+ 5 files changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index dcbafad..fe47255 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -241,7 +241,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
+ int ret;
+
+- ret = tilcdc_crtc_mode_valid(crtc, mode);
++ ret = tilcdc_crtc_mode_valid(crtc, mode, 0);
+ if (WARN_ON(ret))
+ return ret;
+
+@@ -422,7 +422,8 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc)
+ return max_width;
+ }
+
+-int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
++int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
++ int rb_check)
+ {
+ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+ unsigned int bandwidth;
+@@ -443,7 +444,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
+ if (bandwidth > priv->max_bandwidth)
+ return MODE_BAD;
+
+- if (priv->allow_non_rblank == 0) {
++ if (rb_check) {
+ /* we only support reduced blanking modes */
+ rb = (mode->htotal - mode->hdisplay == 160) &&
+ (mode->hsync_end - mode->hdisplay == 80) &&
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index c858f73..b04f94c 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -145,7 +145,8 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc);
+ void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
+ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
+ const struct tilcdc_panel_info *info);
+-int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
++int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
++ int rb_check);
+ int tilcdc_crtc_max_width(struct drm_crtc *crtc);
+
+ #endif /* __TILCDC_DRV_H__ */
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+index f4b794d..2496ee4 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+@@ -197,7 +197,7 @@ static int panel_connector_mode_valid(struct drm_connector *connector,
+ {
+ struct tilcdc_drm_private *priv = connector->dev->dev_private;
+ /* our only constraints are what the crtc can generate: */
+- return tilcdc_crtc_mode_valid(priv->crtc, mode);
++ return tilcdc_crtc_mode_valid(priv->crtc, mode, 0);
+ }
+
+ static struct drm_encoder *panel_connector_best_encoder(
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+index 7d05c3d..a2d86ac 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+@@ -167,7 +167,8 @@ static int slave_connector_mode_valid(struct drm_connector *connector,
+ struct tilcdc_drm_private *priv = connector->dev->dev_private;
+ int ret;
+
+- ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
++ ret = tilcdc_crtc_mode_valid(priv->crtc, mode,
++ priv->allow_non_rblank ? 0 : 1);
+ if (ret != MODE_OK)
+ return ret;
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+index 7065dfa..6f9d727 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+@@ -213,7 +213,8 @@ static int tfp410_connector_mode_valid(struct drm_connector *connector,
+ {
+ struct tilcdc_drm_private *priv = connector->dev->dev_private;
+ /* our only constraints are what the crtc can generate: */
+- return tilcdc_crtc_mode_valid(priv->crtc, mode);
++ return tilcdc_crtc_mode_valid(priv->crtc, mode,
++ priv->allow_non_rblank ? 0 : 1);
+ }
+
+ static struct drm_encoder *tfp410_connector_best_encoder(
diff --git a/patches/linux-3.8.13/0356-cape-adafruit-Use-the-correct-spi-bus-spi1-no-spi0.patch b/patches/linux-3.8.13/0356-cape-adafruit-Use-the-correct-spi-bus-spi1-no-spi0.patch
new file mode 100644
index 0000000..013f3b3
--- /dev/null
+++ b/patches/linux-3.8.13/0356-cape-adafruit-Use-the-correct-spi-bus-spi1-no-spi0.patch
@@ -0,0 +1,24 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 9 Mar 2013 18:19:11 +0200
+Subject: [PATCH] cape-adafruit: Use the correct spi bus (spi1 no spi0)
+
+Use the correct SPI bus.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-adafruit-lcd-00A0.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+index f891917..6fe5dcf 100644
+--- a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
++++ b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+@@ -71,7 +71,7 @@
+
+
+ fragment@3 {
+- target = <&spi0>;
++ target = <&spi1>;
+
+ __overlay__ {
+ #address-cells = <1>;
diff --git a/patches/linux-3.8.13/0357-BBB-tester-Introduce-board-DTS.patch b/patches/linux-3.8.13/0357-BBB-tester-Introduce-board-DTS.patch
new file mode 100644
index 0000000..7fd3c13
--- /dev/null
+++ b/patches/linux-3.8.13/0357-BBB-tester-Introduce-board-DTS.patch
@@ -0,0 +1,416 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 7 Mar 2013 17:22:40 +0200
+Subject: [PATCH] BBB tester: Introduce board DTS
+
+We can't use the same DTS base as the standard beaglebone because
+the I2C2 is used for a different purpose for the tester.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/Makefile | 3 +-
+ arch/arm/boot/dts/am335x-tester.dts | 382 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 384 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/am335x-tester.dts
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 8f8c0c8..9da016f 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -114,7 +114,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
+ am335x-evm.dtb \
+ am335x-evmsk.dtb \
+ am335x-bone.dtb \
+- am335x-boneblack.dtb
++ am335x-boneblack.dtb \
++ am335x-tester.dtb
+ dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
+ dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+ dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \
+diff --git a/arch/arm/boot/dts/am335x-tester.dts b/arch/arm/boot/dts/am335x-tester.dts
+new file mode 100644
+index 0000000..c8d6900
+--- /dev/null
++++ b/arch/arm/boot/dts/am335x-tester.dts
+@@ -0,0 +1,382 @@
++/*
++ * 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/ "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 */
++ };
++
++ am33xx_pinmux: pinmux@44e10800 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&userleds_pins>;
++
++ spi1_pins_s0: spi1_pins_s0 {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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 */
++ >;
++ };
++ 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 */
++ >;
++ };
++ i2c0_pins: pinmux_i2c0_pins {
++ pinctrl-single,pins = <
++ 0x188 0x70 /* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
++ 0x18c 0x70 /* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
++ >;
++ };
++ // 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: 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";
++ linux,default-trigger = "mmc1";
++ };
++ };
++
++ rtc@44e3e000 {
++ ti,system-power-controller;
++ };
++ };
++
++ bone_capemgr {
++ compatible = "ti,bone-capemgr";
++ status = "okay";
++
++ eeprom = <&baseboard_eeprom>;
++
++ baseboardmaps {
++ baseboard_beaglebone: board@0 {
++ board-name = "A335BONE";
++ compatible-name = "ti,beaglebone";
++ };
++
++ baseboard_beaglebone_black: board@1 {
++ board-name = "A335BNLT";
++ compatible-name = "ti,beaglebone-black";
++ };
++ };
++
++ slots {
++ // slot@0 {
++ // eeprom = <&cape_eeprom0>;
++ // };
++ //
++ // slot@1 {
++ // eeprom = <&cape_eeprom1>;
++ // };
++ //
++ // slot@2 {
++ // eeprom = <&cape_eeprom2>;
++ // };
++ //
++ // slot@3 {
++ // eeprom = <&cape_eeprom3>;
++ // };
++
++ /* Beaglebone black has it soldered on */
++ slot@4 {
++ ti,cape-override;
++ compatible = "ti,beaglebone-black";
++ board-name = "Bone-LT-eMMC-2G";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONE-EMMC-2G";
++ };
++
++ /* geiger cape version A0 without an EEPROM */
++ slot@5 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-Geiger";
++ version = "00A0";
++ manufacturer = "Geiger Inc.";
++ part-number = "BB-BONE-GEIGER";
++ };
++
++ /* Beaglebone black has it soldered on */
++ slot@6 {
++ ti,cape-override;
++ compatible = "ti,beaglebone-black";
++ board-name = "Bone-Black-HDMI";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONELT-HDMI";
++ };
++
++ /* Nixie cape version A0 without an EEPROM */
++ slot@7 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-Nixie";
++ version = "00A0";
++ manufacturer = "Ranostay Industries";
++ part-number = "BB-BONE-NIXIE";
++ };
++
++ };
++
++ /* mapping between board names and dtb objects */
++ capemaps {
++ /* DVI cape */
++ cape@0 {
++ /* board-name = "BeagleBone DVI-D CAPE"; */
++ part-number = "BB-BONE-DVID-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-dvi-00A0.dtbo";
++ };
++ version@00A1 {
++ version = "00A1", "01";
++ dtbo = "cape-bone-dvi-00A1.dtbo";
++ };
++ };
++
++ /* beaglebone black emmc on board */
++ cape@1 {
++ /* board-name = "BeagleBone 2G eMMC1 CAPE"; */
++ part-number = "BB-BONE-EMMC-2G";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-2g-emmc1.dtbo";
++ };
++ };
++
++ /* geiger cape */
++ cape@2 {
++ part-number = "BB-BONE-GEIGER";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-geiger-00A0.dtbo";
++ };
++ };
++
++ /* LCD3 cape */
++ cape@3 {
++ part-number = "BB-BONE-LCD3-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-lcd3-00A0.dtbo";
++ };
++ version@00A2 {
++ version = "00A2";
++ dtbo = "cape-bone-lcd3-00A2.dtbo";
++ };
++ };
++
++ /* Weather cape */
++ cape@4 {
++ part-number = "BB-BONE-WTHR-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-weather-00A0.dtbo";
++ };
++ };
++
++ /* beaglebone black hdmi on board */
++ cape@5 {
++ part-number = "BB-BONELT-HDMI";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-boneblack-hdmi-00A0.dtbo";
++ };
++ };
++
++ /* nixie cape */
++ cape@6 {
++ part-number = "BB-BONE-NIXIE";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-nixie-00A0.dtbo";
++ };
++ };
++ };
++ };
++};
++
++&i2c0 {
++ status = "okay";
++ clock-frequency = <400000>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c0_pins>;
++
++ 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>;
++//
++// cape_eeprom0: cape_eeprom0@54 {
++// compatible = "at,24c256";
++// reg = <0x54>;
++// };
++//
++// cape_eeprom1: cape_eeprom1@55 {
++// compatible = "at,24c256";
++// reg = <0x55>;
++// };
++//
++// cape_eeprom2: cape_eeprom2@56 {
++// compatible = "at,24c256";
++// reg = <0x56>;
++// };
++//
++// cape_eeprom3: cape_eeprom3@57 {
++// compatible = "at,24c256";
++// reg = <0x57>;
++// };
++// };
++
++/include/ "tps65217.dtsi"
++
++&tps {
++ ti,pmic-shutdown-controller;
++
++ 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;
++ };
++ };
++};
++
++&cpsw_emac0 {
++ phy_id = <&davinci_mdio>, <0>;
++};
++
++&cpsw_emac1 {
++ phy_id = <&davinci_mdio>, <1>;
++};
++
++&mmc1 {
++ status = "okay";
++ vmmc-supply = <&ldo3_reg>;
++ ti,vcc-aux-disable-is-sleep;
++};
++
++&edma {
++ ti,edma-xbar-event-map = <32 12>;
++};
++
++&sham {
++ status = "okay";
++};
++
++&aes {
++ status = "okay";
++};
++
++&usb_otg_hs {
++ interface_type = <1>;
++ power = <500>;
++ status = "okay";
++};
diff --git a/patches/linux-3.8.13/0358-BBB-tester-Introduce-cape-describing-the-contents-of.patch b/patches/linux-3.8.13/0358-BBB-tester-Introduce-cape-describing-the-contents-of.patch
new file mode 100644
index 0000000..7787996
--- /dev/null
+++ b/patches/linux-3.8.13/0358-BBB-tester-Introduce-cape-describing-the-contents-of.patch
@@ -0,0 +1,453 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 26 Feb 2013 20:44:25 +0200
+Subject: [PATCH] BBB-tester: Introduce cape describing the contents of the
+ tester 'cape'
+
+Note that the tester cape uses I2C2 for something different than an I2C
+bus, so you have to load the fragment manually.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 3 +
+ firmware/capes/cape-bone-tester-00A0.dts | 418 ++++++++++++++++++++++++++++++
+ 2 files changed, 421 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-tester-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 0fd76b3..4f51526 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -162,6 +162,9 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-weather-00A0.dtbo
+ # the HDMI virtual cape on the beaglebone-black
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-boneblack-hdmi-00A0.dtbo
+
++# the Tester cape (tester-side)
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-tester-00A0.dtbo
++
+ fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+
+ # Directories which we _might_ need to create, so we have a rule for them.
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+new file mode 100644
+index 0000000..72fba6e
+--- /dev/null
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -0,0 +1,418 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-TESTER";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bone_tester_none_gpio_pins: pinmux_bone_tester_none_gpio_pins {
++ pinctrl-single,pins = <
++ /* nothing */
++ >;
++ };
++ bone_tester_input_gpio_pins: pinmux_bone_tester_input_gpio_pins {
++ pinctrl-single,pins = <
++ /* P8 connector on the bone */
++ /* P3 - P46 pins, B_A3-B_A46, INPUT | PULLDIS | MODE7 */
++ 0x018 0x2f /* 3 GPIO1_6 gpmc_ad6.gpio1[6] */
++ 0x01C 0x2f /* 4 GPIO1_7 gpmc_ad7.gpio1[7] */
++ 0x008 0x2f /* 5 GPIO1_2 gpmc_ad2.gpio1[2] */
++ 0x00C 0x2f /* 6 GPIO1_3 gpmc_ad3.gpio1[3] */
++ 0x090 0x2f /* 7 TIMER4 gpmc_advn_ale.gpio2[2] */
++ 0x094 0x2f /* 8 TIMER7 gpmc_oen_ren.gpio2[3] */
++ 0x09C 0x2f /* 9 TIMER5 gpmc_ben0_cle.gpio2[5] */
++ 0x098 0x2f /* 10 TIMER6 gpmc_wen.gpio2[4] */
++ 0x034 0x2f /* 11 GPIO1_13 gpmc_ad13.gpio1[13] */
++ 0x030 0x2f /* 12 GPIO1_12 gpmc_ad12.gpio1[12] */
++ 0x024 0x2f /* 13 EHRPWM2B gpmc_ad9 .gpio0[23] */
++ 0x028 0x2f /* 14 GPIO0_26 gpmc_ad10.gpio0[26] */
++ 0x03C 0x2f /* 15 GPIO1_15 gpmc_ad15.gpio1[15] */
++ 0x038 0x2f /* 16 GPIO1_14 gpmc_ad14.gpio1[14] */
++ 0x02C 0x2f /* 17 GPIO0_27 gpmc_ad11.gpio0[27] */
++ 0x08C 0x2f /* 18 GPIO2_1 gpmc_clk .gpio2[1] */
++ 0x020 0x2f /* 19 EHRPWM2A gpmc_ad8 .gpio0[22] */
++ 0x084 0x2f /* 20 GPIO1_31 gpmc_csn2.gpio1[31] */
++ 0x080 0x2f /* 21 GPIO1_30 gpmc_csn1.gpio1[30] */
++ 0x014 0x2f /* 22 GPIO1_5 gpmc_ad5 .gpio1[5] */
++ 0x010 0x2f /* 23 GPIO1_4 gpmc_ad4 .gpio1[4] */
++ 0x004 0x2f /* 24 GPIO1_1 gpmc_ad1 .gpio1[1] */
++ 0x000 0x2f /* 25 GPIO1_0 gpmc_ad0 .gpio1[0] */
++ 0x07C 0x2f /* 26 GPIO1_29 gpmc_csn0.gpio1[29] */
++ 0x0E0 0x2f /* 27 GPIO2_22 lcd_vsync.gpio2[22] */
++ 0x0E8 0x2f /* 28 GPIO2_24 lcd_pclk .gpio2[24] */
++ 0x0E4 0x2f /* 29 GPIO2_23 lcd_hsync.gpio2[23] */
++ 0x0EC 0x2f /* 30 GPIO2_25 lcd_ac_bias_en.gpio2[25] */
++ 0x0D8 0x2f /* 31 UART5_CTSN lcd_data14.gpio0[10] */
++ 0x0DC 0x2f /* 32 UART5_RTSN lcd_data15.gpio0[11] */
++ 0x0D4 0x2f /* 33 UART4_RTSN lcd_data13.gpio0[9] */
++ 0x0CC 0x2f /* 34 UART3_RTSN lcd_data11.gpio2[17] */
++ 0x0D0 0x2f /* 35 UART4_CTSN lcd_data12.gpio0[8] */
++ 0x0C8 0x2f /* 36 UART3_CTSN lcd_data10.gpio2[16] */
++ 0x0C0 0x2f /* 37 UART5_TXD lcd_data8.gpio2[14] */
++ 0x0C4 0x2f /* 38 UART5_RXD lcd_data9.gpio2[15] */
++ 0x0B8 0x2f /* 39 GPIO2_12 lcd_data6.gpio2[12] */
++ 0x0BC 0x2f /* 40 GPIO2_13 lcd_data7.gpio2[13] */
++ 0x0B0 0x2f /* 41 GPIO2_10 lcd_data4.gpio2[10] */
++ 0x0B4 0x2f /* 42 GPIO2_11 lcd_data5.gpio2[11] */
++ 0x0A8 0x2f /* 43 GPIO2_8 lcd_data2.gpio2[8] */
++ 0x0AC 0x2f /* 44 GPIO2_9 lcd_data3.gpio2[9] */
++ 0x0A0 0x2f /* 45 GPIO2_6 lcd_data0.gpio2[6] */
++ 0x0A4 0x2f /* 46 GPIO2_7 lcd_data1.gpio2[7] */
++
++ /* P9 connector on the bone */
++ /* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
++ 0x070 0x2f /* 11 UART4_RXD gpmc_wait0.gpio0[30] */
++ 0x078 0x2f /* 12 GPIO1_28 gpmc_be1n.gpio1[28] */
++ 0x074 0x2f /* 13 UART4_TXD gpmc_wpn.gpio0[31] */
++ 0x048 0x2f /* 14 EHRPWM1A gpmc_a2.gpio1[18] */
++ 0x040 0x2f /* 15 GPIO1_16 gpmc_a0.gpio1[16] */
++ 0x04C 0x2f /* 16 EHRPWM1B gpmc_a3.gpio1[19] */
++
++ /* err, those two are used for I2C2 on the beaglebone */
++ /* you should boot with I2C2 disabled on the tester */
++ 0x17C 0x2f /* 19 I2C2_SCL uart1_rtsn.gpio0[13] */
++ 0x178 0x2f /* 20 I2C2_SDA uart1_ctsn.gpio0[12] */
++
++ 0x154 0x2f /* 21 UART2_TXD spi0_d0.gpio0[3] */
++ 0x150 0x2f /* 22 UART2_RXD spi0_sclk.gpio0[2] */
++ 0x044 0x2f /* 23 GPIO1_17 gpmc_a1.gpio1[17] */
++ 0x184 0x2f /* 24 UART1_TXD uart1_txd.gpio0[15] */
++ 0x1AC 0x2f /* 25 GPIO3_21 mcasp0_ahclkx.gpio3[21]*/
++ 0x180 0x2f /* 26 UART1_RXD uart1_rxd.gpio0[14] */
++ 0x1A4 0x2f /* 27 GPIO3_19 mcasp0_fsr.gpio3[19] */
++ 0x19C 0x2f /* 28 SPI1_CS0 mcasp0_ahclkr.gpio3[17]*/
++ 0x198 0x2f /* 30 SPI1_D1 mcasp0_axr0.gpio3[16] */
++ 0x190 0x2f /* 31 SPI1_SCLK mcasp0_aclkx.gpio3[14] */
++ 0x1B4 0x2f /* 41 CLKOUT2 xdma_event_intr1.gpio0[20]*/
++ 0x164 0x2f /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
++ >;
++ };
++
++ bone_tester_output_gpio_pins: pinmux_bone_tester_output_gpio_pins {
++ pinctrl-single,pins = <
++ /* P8 connector on the bone */
++ /* P3 - P46 pins, B_A3-B_A46, OUTPUT | MODE7 */
++ 0x018 0x07 /* 3 GPIO1_6 gpmc_ad6.gpio1[6] */
++ 0x01C 0x07 /* 4 GPIO1_7 gpmc_ad7.gpio1[7] */
++ 0x008 0x07 /* 5 GPIO1_2 gpmc_ad2.gpio1[2] */
++ 0x00C 0x07 /* 6 GPIO1_3 gpmc_ad3.gpio1[3] */
++ 0x090 0x07 /* 7 TIMER4 gpmc_advn_ale.gpio2[2] */
++ 0x094 0x07 /* 8 TIMER7 gpmc_oen_ren.gpio2[3] */
++ 0x09C 0x07 /* 9 TIMER5 gpmc_ben0_cle.gpio2[5] */
++ 0x098 0x07 /* 10 TIMER6 gpmc_wen.gpio2[4] */
++ 0x034 0x07 /* 11 GPIO1_13 gpmc_ad13.gpio1[13] */
++ 0x030 0x07 /* 12 GPIO1_12 gpmc_ad12.gpio1[12] */
++ 0x024 0x07 /* 13 EHRPWM2B gpmc_ad9 .gpio0[23] */
++ 0x028 0x07 /* 14 GPIO0_26 gpmc_ad10.gpio0[26] */
++ 0x03C 0x07 /* 15 GPIO1_15 gpmc_ad15.gpio1[15] */
++ 0x038 0x07 /* 16 GPIO1_14 gpmc_ad14.gpio1[14] */
++ 0x02C 0x07 /* 17 GPIO0_27 gpmc_ad11.gpio0[27] */
++ 0x08C 0x07 /* 18 GPIO2_1 gpmc_clk .gpio2[1] */
++ 0x020 0x07 /* 19 EHRPWM2A gpmc_ad8 .gpio0[22] */
++ 0x084 0x07 /* 20 GPIO1_31 gpmc_csn2.gpio1[31] */
++ 0x080 0x07 /* 21 GPIO1_30 gpmc_csn1.gpio1[30] */
++ 0x014 0x07 /* 22 GPIO1_5 gpmc_ad5 .gpio1[5] */
++ 0x010 0x07 /* 23 GPIO1_4 gpmc_ad4 .gpio1[4] */
++ 0x004 0x07 /* 24 GPIO1_1 gpmc_ad1 .gpio1[1] */
++ 0x000 0x07 /* 25 GPIO1_0 gpmc_ad0 .gpio1[0] */
++ 0x07C 0x07 /* 26 GPIO1_29 gpmc_csn0.gpio1[29] */
++ 0x0E0 0x07 /* 27 GPIO2_22 lcd_vsync.gpio2[22] */
++ 0x0E8 0x07 /* 28 GPIO2_24 lcd_pclk .gpio2[24] */
++ 0x0E4 0x07 /* 29 GPIO2_23 lcd_hsync.gpio2[23] */
++ 0x0EC 0x07 /* 30 GPIO2_25 lcd_ac_bias_en.gpio2[25] */
++ 0x0D8 0x07 /* 31 UART5_CTSN lcd_data14.gpio0[10] */
++ 0x0DC 0x07 /* 32 UART5_RTSN lcd_data15.gpio0[11] */
++ 0x0D4 0x07 /* 33 UART4_RTSN lcd_data13.gpio0[9] */
++ 0x0CC 0x07 /* 34 UART3_RTSN lcd_data11.gpio2[17] */
++ 0x0D0 0x07 /* 35 UART4_CTSN lcd_data12.gpio0[8] */
++ 0x0C8 0x07 /* 36 UART3_CTSN lcd_data10.gpio2[16] */
++ 0x0C0 0x07 /* 37 UART5_TXD lcd_data8.gpio2[14] */
++ 0x0C4 0x07 /* 38 UART5_RXD lcd_data9.gpio2[15] */
++ 0x0B8 0x07 /* 39 GPIO2_12 lcd_data6.gpio2[12] */
++ 0x0BC 0x07 /* 40 GPIO2_13 lcd_data7.gpio2[13] */
++ 0x0B0 0x07 /* 41 GPIO2_10 lcd_data4.gpio2[10] */
++ 0x0B4 0x07 /* 42 GPIO2_11 lcd_data5.gpio2[11] */
++ 0x0A8 0x07 /* 43 GPIO2_8 lcd_data2.gpio2[8] */
++ 0x0AC 0x07 /* 44 GPIO2_9 lcd_data3.gpio2[9] */
++ 0x0A0 0x07 /* 45 GPIO2_6 lcd_data0.gpio2[6] */
++ 0x0A4 0x07 /* 46 GPIO2_7 lcd_data1.gpio2[7] */
++
++ /* P9 connector on the bone */
++ /* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
++ 0x070 0x07 /* 11 UART4_RXD gpmc_wait0.gpio0[30] */
++ 0x078 0x07 /* 12 GPIO1_28 gpmc_be1n.gpio1[28] */
++ 0x074 0x07 /* 13 UART4_TXD gpmc_wpn.gpio0[31] */
++ 0x048 0x07 /* 14 EHRPWM1A gpmc_a2.gpio1[18] */
++ 0x040 0x07 /* 15 GPIO1_16 gpmc_a0.gpio1[16] */
++ 0x04C 0x07 /* 16 EHRPWM1B gpmc_a3.gpio1[19] */
++
++ /* err, those two are used for I2C2 on the beaglebone */
++ /* you should boot with I2C2 disabled on the tester */
++ 0x17C 0x07 /* 19 I2C2_SCL uart1_rtsn.gpio0[13] */
++ 0x178 0x07 /* 20 I2C2_SDA uart1_ctsn.gpio0[12] */
++
++ 0x154 0x07 /* 21 UART2_TXD spi0_d0.gpio0[3] */
++ 0x150 0x07 /* 22 UART2_RXD spi0_sclk.gpio0[2] */
++ 0x044 0x07 /* 23 GPIO1_17 gpmc_a1.gpio1[17] */
++ 0x184 0x07 /* 24 UART1_TXD uart1_txd.gpio0[15] */
++ 0x1AC 0x07 /* 25 GPIO3_21 mcasp0_ahclkx.gpio3[21]*/
++ 0x180 0x07 /* 26 UART1_RXD uart1_rxd.gpio0[14] */
++ 0x1A4 0x07 /* 27 GPIO3_19 mcasp0_fsr.gpio3[19] */
++ 0x19C 0x07 /* 28 SPI1_CS0 mcasp0_ahclkr.gpio3[17]*/
++ 0x198 0x07 /* 30 SPI1_D1 mcasp0_axr0.gpio3[16] */
++ 0x190 0x07 /* 31 SPI1_SCLK mcasp0_aclkx.gpio3[14] */
++ 0x1B4 0x07 /* 41 CLKOUT2 xdma_event_intr1.gpio0[20]*/
++ 0x164 0x07 /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
++ >;
++ };
++
++ bone_tester_i2c1_pins: pinmux_bone_tester_i2c1_pins {
++ pinctrl-single,pins = <
++ 0x158 0x72 /* spi0_d1.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
++ 0x15c 0x72 /* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
++ >;
++ };
++
++ bone_tester_jhd629_pins: pinmux_bone_tester_jhd629_pins {
++ pinctrl-single,pins = <
++ 0x194 0x37 /* mcasp0_fsx.gpio3_15, OMAP_MUX_MODE7 | INPUT_PULLUP */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c1>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_tester_i2c1_pins>;
++ status = "okay";
++ clock-frequency = <100000>;
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c1>;
++ __overlay__ {
++ /* needed to avoid gripping by DTC */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* pca9457 */
++ pca9457_mux {
++ compatible = "nxp,pca9547";
++ status = "okay";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x70>;
++
++ bus@0 { /* LCD/KEY */
++ compatible = "nxp,pca954x-bus";
++ status = "okay";
++ nxp,pca95x-class = <0x0>;
++ reg = <0x0>;
++ nxp,deselect-on-exit;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ jhd629@31 {
++ compatible = "jhd,jhd629";
++ status = "okay";
++ reg = <0x31>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_tester_jhd629_pins>;
++
++ rows = <4>;
++ columns = <20>;
++ keymap = "123A456B789C*0#D";
++ poll-period = <250>; /* poll every 250ms */
++ // gpios = <&gpio4 15 0>; /* keypad interrupt */
++ };
++ };
++
++ bus@1 { /* LATCH */
++ compatible = "nxp,pca954x-bus";
++ status = "okay";
++ nxp,pca95x-class = <0x0>;
++ reg = <0x1>;
++ nxp,deselect-on-exit;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tester_latch: latch@38 {
++ /*
++ * TESTING_LED
++ * FAILED_LED
++ * ATTN_LED
++ * RDY_LED
++ * DC_RELAY
++ * PWRBUT_RELAY
++ * RESET_RELAY
++ */
++ compatible = "nxp,pcf8574";
++ status = "okay";
++ reg = <0x38>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ };
++ };
++
++ bus@2 { /* SOLENOIDS */
++ compatible = "nxp,pca954x-bus";
++ status = "okay";
++ nxp,pca95x-class = <0x0>;
++ reg = <0x2>;
++ nxp,deselect-on-exit;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ grove@f {
++ compatible = "grove";
++ status = "okay";
++ reg = <0x0f>;
++ };
++ };
++
++ bus@3 { /* RTC */
++ compatible = "nxp,pca954x-bus";
++ status = "okay";
++ nxp,pca95x-class = <0x0>;
++ reg = <0x3>;
++ nxp,deselect-on-exit;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ rtc@68 {
++ compatible = "dallas,ds1307";
++ status = "okay";
++ reg = <0x68>;
++ };
++ };
++
++ bus@4 { /* INA219 */
++ compatible = "nxp,pca954x-bus";
++ status = "okay";
++ nxp,pca95x-class = <0x0>;
++ reg = <0x4>;
++ nxp,deselect-on-exit;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ ina@40 {
++ compatible = "ti,ina219";
++ status = "okay";
++ reg = <0x40>;
++ };
++ };
++
++ bus@5 { /* BUFFERS */
++ compatible = "nxp,pca954x-bus";
++ status = "okay";
++ nxp,pca95x-class = <0x0>;
++ reg = <0x5>;
++ nxp,deselect-on-exit;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tester_buffers: latch@39 {
++ /*
++ * TxD_BUFFER
++ * RxD_BUFFER
++ * OE_BUFFER
++ * DIR_BUFFER
++ * CTRL_EEPROM_WP
++ */
++ compatible = "nxp,pcf8574";
++ status = "okay";
++ reg = <0x39>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ };
++ };
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&ocp>;
++ __overlay__ {
++
++ gpio-leds-tester {
++ compatible = "gpio-leds";
++
++ /* note we don't use tester:<color>:<function> */
++ led0 {
++ label = "TESTING_LED";
++ gpios = <&tester_latch 0 0>;
++ linux,default-trigger = "none";
++ default-state = "off";
++ };
++
++ led1 {
++ label = "FAILED_LED";
++ gpios = <&tester_latch 1 0>;
++ linux,default-trigger = "none";
++ default-state = "off";
++ };
++
++ led2 {
++ label = "PASS_LED";
++ gpios = <&tester_latch 2 0>;
++ linux,default-trigger = "none";
++ default-state = "off";
++ };
++
++ led3 {
++ label = "ATTN_LED";
++ gpios = <&tester_latch 3 0>;
++ linux,default-trigger = "none";
++ default-state = "off";
++ };
++
++ led4 {
++ label = "RDY_LED";
++ gpios = <&tester_latch 4 0>;
++ linux,default-trigger = "none";
++ default-state = "off";
++ };
++ };
++ };
++
++ };
++
++ fragment@4 {
++ target = <&ocp>;
++ __overlay__ {
++
++ tester_pinmux_helper {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++
++ pinctrl-names = /* "default", */ "input", "output";
++ // pinctrl-0 = <&bone_tester_none_gpio_pins>;
++ pinctrl-0 = <&bone_tester_input_gpio_pins>;
++ pinctrl-1 = <&bone_tester_output_gpio_pins>;
++ };
++ };
++
++ };
++};
++
diff --git a/patches/linux-3.8.13/0359-bone-tester-Add-overrides-for-BB-BONE-TESTER.patch b/patches/linux-3.8.13/0359-bone-tester-Add-overrides-for-BB-BONE-TESTER.patch
new file mode 100644
index 0000000..f3d5fe5
--- /dev/null
+++ b/patches/linux-3.8.13/0359-bone-tester-Add-overrides-for-BB-BONE-TESTER.patch
@@ -0,0 +1,48 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 11 Mar 2013 12:24:17 +0200
+Subject: [PATCH] bone-tester: Add overrides for BB-BONE-TESTER
+
+Add overrides for BB-BONE-TESTER
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-tester.dts | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-tester.dts b/arch/arm/boot/dts/am335x-tester.dts
+index c8d6900..1fdba03 100644
+--- a/arch/arm/boot/dts/am335x-tester.dts
++++ b/arch/arm/boot/dts/am335x-tester.dts
+@@ -177,6 +177,15 @@
+ part-number = "BB-BONE-NIXIE";
+ };
+
++ /* geiger cape version A0 without an EEPROM */
++ slot@8 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-Tester";
++ version = "00A0";
++ part-number = "BB-BONE-TESTER";
++ };
++
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -253,6 +262,16 @@
+ dtbo = "cape-bone-nixie-00A0.dtbo";
+ };
+ };
++
++ /* tester */
++ cape@7 {
++ part-number = "BB-BONE-TESTER";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-tester-00A0.dtbo";
++ };
++ };
++
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0360-cape-tester-Add-uart-specific-default-pinmux-state.patch b/patches/linux-3.8.13/0360-cape-tester-Add-uart-specific-default-pinmux-state.patch
new file mode 100644
index 0000000..47d0406
--- /dev/null
+++ b/patches/linux-3.8.13/0360-cape-tester-Add-uart-specific-default-pinmux-state.patch
@@ -0,0 +1,96 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 12 Mar 2013 09:36:43 +0200
+Subject: [PATCH] cape-tester: Add uart specific default pinmux state
+
+The UUT UART is by default a UART, but when running the expansion tests
+is GPIO.
+---
+ firmware/capes/cape-bone-tester-00A0.dts | 36 +++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 10 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index 72fba6e..4cc3575 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -18,9 +18,12 @@
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+- bone_tester_none_gpio_pins: pinmux_bone_tester_none_gpio_pins {
++ /* default state has all gpios released and mode set to uart1 */
++ bone_tester_default_gpio_pins: pinmux_bone_tester_default_gpio_pins {
+ pinctrl-single,pins = <
+- /* nothing */
++ /* the uart pins */
++ 0x184 0x20 /* 24 UART1_TXD uart1_txd OUTPUT */
++ 0x180 0x20 /* 26 UART1_RXD uart1_rxd INPUT */
+ >;
+ };
+ bone_tester_input_gpio_pins: pinmux_bone_tester_input_gpio_pins {
+@@ -89,15 +92,17 @@
+ 0x154 0x2f /* 21 UART2_TXD spi0_d0.gpio0[3] */
+ 0x150 0x2f /* 22 UART2_RXD spi0_sclk.gpio0[2] */
+ 0x044 0x2f /* 23 GPIO1_17 gpmc_a1.gpio1[17] */
+- 0x184 0x2f /* 24 UART1_TXD uart1_txd.gpio0[15] */
+ 0x1AC 0x2f /* 25 GPIO3_21 mcasp0_ahclkx.gpio3[21]*/
+- 0x180 0x2f /* 26 UART1_RXD uart1_rxd.gpio0[14] */
+ 0x1A4 0x2f /* 27 GPIO3_19 mcasp0_fsr.gpio3[19] */
+ 0x19C 0x2f /* 28 SPI1_CS0 mcasp0_ahclkr.gpio3[17]*/
+ 0x198 0x2f /* 30 SPI1_D1 mcasp0_axr0.gpio3[16] */
+ 0x190 0x2f /* 31 SPI1_SCLK mcasp0_aclkx.gpio3[14] */
+ 0x1B4 0x2f /* 41 CLKOUT2 xdma_event_intr1.gpio0[20]*/
+ 0x164 0x2f /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
++
++ /* the UART pins */
++ 0x184 0x2f /* 24 UART1_TXD uart1_txd.gpio0[15] */
++ 0x180 0x2f /* 26 UART1_RXD uart1_rxd.gpio0[14] */
+ >;
+ };
+
+@@ -167,15 +172,17 @@
+ 0x154 0x07 /* 21 UART2_TXD spi0_d0.gpio0[3] */
+ 0x150 0x07 /* 22 UART2_RXD spi0_sclk.gpio0[2] */
+ 0x044 0x07 /* 23 GPIO1_17 gpmc_a1.gpio1[17] */
+- 0x184 0x07 /* 24 UART1_TXD uart1_txd.gpio0[15] */
+ 0x1AC 0x07 /* 25 GPIO3_21 mcasp0_ahclkx.gpio3[21]*/
+- 0x180 0x07 /* 26 UART1_RXD uart1_rxd.gpio0[14] */
+ 0x1A4 0x07 /* 27 GPIO3_19 mcasp0_fsr.gpio3[19] */
+ 0x19C 0x07 /* 28 SPI1_CS0 mcasp0_ahclkr.gpio3[17]*/
+ 0x198 0x07 /* 30 SPI1_D1 mcasp0_axr0.gpio3[16] */
+ 0x190 0x07 /* 31 SPI1_SCLK mcasp0_aclkx.gpio3[14] */
+ 0x1B4 0x07 /* 41 CLKOUT2 xdma_event_intr1.gpio0[20]*/
+ 0x164 0x07 /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
++
++ /* the uart pins */
++ 0x184 0x07 /* 24 UART1_TXD uart1_txd.gpio0[15] */
++ 0x180 0x07 /* 26 UART1_RXD uart1_rxd.gpio0[14] */
+ >;
+ };
+
+@@ -406,13 +413,22 @@
+ compatible = "bone-pinmux-helper";
+ status = "okay";
+
+- pinctrl-names = /* "default", */ "input", "output";
+- // pinctrl-0 = <&bone_tester_none_gpio_pins>;
+- pinctrl-0 = <&bone_tester_input_gpio_pins>;
+- pinctrl-1 = <&bone_tester_output_gpio_pins>;
++ pinctrl-names = "default", "input", "output";
++ pinctrl-0 = <&bone_tester_default_gpio_pins>;
++ pinctrl-1 = <&bone_tester_input_gpio_pins>;
++ pinctrl-2 = <&bone_tester_output_gpio_pins>;
+ };
+ };
+
+ };
++
++ fragment@5 {
++ target = <&uart2>; /* really uart1 */
++ __overlay__ {
++ /* please note that the pinconfig is done by the pinmux helper */
++ status = "okay";
++ };
++ };
++
+ };
+
diff --git a/patches/linux-3.8.13/0361-cape-tester-Add-pinmux-helper-for-drvvbus-gpio.patch b/patches/linux-3.8.13/0361-cape-tester-Add-pinmux-helper-for-drvvbus-gpio.patch
new file mode 100644
index 0000000..2935ea0
--- /dev/null
+++ b/patches/linux-3.8.13/0361-cape-tester-Add-pinmux-helper-for-drvvbus-gpio.patch
@@ -0,0 +1,47 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 13 Mar 2013 16:55:15 +0200
+Subject: [PATCH] cape-tester: Add pinmux helper for drvvbus gpio
+
+We need this so that we can control the power to the USB host port.
+---
+ firmware/capes/cape-bone-tester-00A0.dts | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index 4cc3575..d5b7607 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -198,6 +198,17 @@
+ 0x194 0x37 /* mcasp0_fsx.gpio3_15, OMAP_MUX_MODE7 | INPUT_PULLUP */
+ >;
+ };
++
++ bone_default_drvvbus_pins: pinmux_bone_default_drvvbus_pins {
++ pinctrl-single,pins = <
++ 0x234 0x20 /* USB1_DRVVBUS musb */
++ >;
++ };
++ bone_gpio_drvvbus_pins: pinmux_bone_gpio_drvvbus_pins {
++ pinctrl-single,pins = <
++ 0x234 0x07 /* USB1_DRVVBUS.gpio3_13 OUTPUT */
++ >;
++ };
+ };
+ };
+
+@@ -418,6 +429,15 @@
+ pinctrl-1 = <&bone_tester_input_gpio_pins>;
+ pinctrl-2 = <&bone_tester_output_gpio_pins>;
+ };
++
++ drvvbus_pinmux_helper {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++
++ pinctrl-names = "default", "gpio";
++ pinctrl-0 = <&bone_default_drvvbus_pins>;
++ pinctrl-1 = <&bone_gpio_drvvbus_pins>;
++ };
+ };
+
+ };
diff --git a/patches/linux-3.8.13/0362-cape-Added-support-for-IIO-helper-cape.patch b/patches/linux-3.8.13/0362-cape-Added-support-for-IIO-helper-cape.patch
new file mode 100644
index 0000000..088e5f7
--- /dev/null
+++ b/patches/linux-3.8.13/0362-cape-Added-support-for-IIO-helper-cape.patch
@@ -0,0 +1,227 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 19 Mar 2013 17:06:03 +0000
+Subject: [PATCH] cape: Added support for IIO helper cape
+
+Since we currently can't export the IIO channels from the
+ADCs this patch exposes an sysfs entry to read a respective
+channel.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/misc/cape/beaglebone/Kconfig | 7 +
+ drivers/misc/cape/beaglebone/Makefile | 1 +
+ drivers/misc/cape/beaglebone/bone-iio-helper.c | 175 ++++++++++++++++++++++++
+ 3 files changed, 183 insertions(+)
+ create mode 100644 drivers/misc/cape/beaglebone/bone-iio-helper.c
+
+diff --git a/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig
+index 9bf5ac0..4937577 100644
+--- a/drivers/misc/cape/beaglebone/Kconfig
++++ b/drivers/misc/cape/beaglebone/Kconfig
+@@ -9,6 +9,13 @@ config BEAGLEBONE_PINMUX_HELPER
+ help
+ Say Y here to include support for the pinmux helper
+
++config BEAGLEBONE_IIO_HELPER
++ tristate "Beaglebone AM335x TSCADC Helper"
++ depends on ARCH_OMAP2PLUS && OF && MFD_TI_AM335X_TSCADC
++ default n
++ help
++ Say Y here to include support for the IIO helper
++
+ config CAPE_BEAGLEBONE
+ tristate "Beaglebone cape support"
+ depends on ARCH_OMAP2PLUS && OF && I2C
+diff --git a/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile
+index 508b931..e32550d 100644
+--- a/drivers/misc/cape/beaglebone/Makefile
++++ b/drivers/misc/cape/beaglebone/Makefile
+@@ -3,6 +3,7 @@
+ #
+
+ obj-$(CONFIG_BEAGLEBONE_PINMUX_HELPER) += bone-pinmux-helper.o
++obj-$(CONFIG_BEAGLEBONE_IIO_HELPER) += bone-iio-helper.o
+
+ obj-$(CONFIG_CAPE_BEAGLEBONE) += capemgr.o
+ obj-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += cape-bone-geiger.o
+diff --git a/drivers/misc/cape/beaglebone/bone-iio-helper.c b/drivers/misc/cape/beaglebone/bone-iio-helper.c
+new file mode 100644
+index 0000000..d2c76e1
+--- /dev/null
++++ b/drivers/misc/cape/beaglebone/bone-iio-helper.c
+@@ -0,0 +1,175 @@
++/*
++ * Industrial IO helper driver
++ *
++ * Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
++ *
++ * Based on original work by
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/math64.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/iio/iio.h>
++#include <linux/iio/machine.h>
++#include <linux/iio/consumer.h>
++
++static const struct of_device_id bone_iio_helper_of_match[] = {
++ {
++ .compatible = "bone-iio-helper",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bone_iio_helper_of_match);
++
++struct iio_helper_info {
++ struct platform_device *pdev;
++ const char *vsense_name;
++ unsigned int vsense_scale;
++ struct iio_channel *vsense_channel;
++};
++
++static ssize_t iio_helper_show_mvolts(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct iio_helper_info *info = platform_get_drvdata(pdev);
++ int ret, val;
++ u32 mvolts;
++
++ ret = iio_read_channel_raw(info->vsense_channel, &val);
++ if (ret < 0)
++ return ret;
++
++ /* volts = ((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(mvolts, S_IRUGO,
++ iio_helper_show_mvolts, NULL);
++
++static int iio_helper_sysfs_register(struct platform_device *pdev)
++{
++ return device_create_file(&pdev->dev, &dev_attr_mvolts);
++}
++
++static int bone_iio_helper_probe(struct platform_device *pdev)
++{
++ struct iio_helper_info *info;
++ struct device_node *pnode = pdev->dev.of_node;
++ int err;
++
++ /* we only support OF */
++ if (pnode == NULL) {
++ dev_err(&pdev->dev, "No platform of_node!\n");
++ return -ENODEV;
++ }
++
++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate info\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ platform_set_drvdata(pdev, info);
++ info->pdev = pdev;
++
++ if (of_property_read_string(pnode, "vsense-name", &info->vsense_name) != 0) {
++ dev_err(&pdev->dev, "Could not read vsense-name property.");
++ err = -EINVAL;
++ goto err_no_vsense;
++ }
++
++ if (of_property_read_u32(pnode, "vsense-scale", &info->vsense_scale) != 0) {
++ dev_err(&pdev->dev, "Could not read vsense-scale property");
++ err = -EINVAL;
++ goto err_no_vsense;
++ }
++
++ if (info->vsense_scale == 0) {
++ dev_err(&pdev->dev, "Invalid vsense-scale property");
++ err = -EINVAL;
++ goto err_no_vsense;
++ }
++
++ info->vsense_channel = iio_channel_get(NULL, info->vsense_name);
++ if (IS_ERR(info->vsense_channel)) {
++ dev_err(&pdev->dev, "Could not get %s analog input\n",
++ info->vsense_name);
++ err = PTR_ERR(info->vsense_channel);
++ goto err_no_vsense;
++ }
++
++ err = iio_helper_sysfs_register(pdev);
++ if (err != 0) {
++ dev_err(&pdev->dev, "unable to register sysfs\n");
++ goto err_no_sysfs;
++ }
++
++ dev_info(&pdev->dev, "ready\n");
++
++ return 0;
++
++err_no_sysfs:
++ /* fall-through */
++err_no_vsense:
++ kfree(info);
++err_no_mem:
++ return err;
++}
++
++
++static int bone_iio_helper_remove(struct platform_device *pdev)
++{
++ struct iio_helper_info *info = platform_get_drvdata(pdev);
++ struct device *dev = &pdev->dev;
++
++ iio_channel_release(info->vsense_channel);
++ device_remove_file(dev, &dev_attr_mvolts);
++ kfree(info->vsense_name);
++ devm_kfree(dev, info);
++
++ return 0;
++}
++
++struct platform_driver bone_iio_helper_driver = {
++ .probe = bone_iio_helper_probe,
++ .remove = bone_iio_helper_remove,
++ .driver = {
++ .name = "bone-iio-helper",
++ .owner = THIS_MODULE,
++ .of_match_table = bone_iio_helper_of_match,
++ },
++};
++
++module_platform_driver(bone_iio_helper_driver);
++
++MODULE_AUTHOR("Matt Ranostay");
++MODULE_DESCRIPTION("Beaglebone IIO helper driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-iio-helper");
diff --git a/patches/linux-3.8.13/0363-cape-Added-example-IIO-tester-dynamics-overlay.patch b/patches/linux-3.8.13/0363-cape-Added-example-IIO-tester-dynamics-overlay.patch
new file mode 100644
index 0000000..595d1d4
--- /dev/null
+++ b/patches/linux-3.8.13/0363-cape-Added-example-IIO-tester-dynamics-overlay.patch
@@ -0,0 +1,66 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 19 Mar 2013 17:06:04 +0000
+Subject: [PATCH] cape: Added example IIO tester dynamics overlay
+
+Added an example usage of the IIO exporter for an current sensor
+reading.
+
+Scale factor works with INA169 current sensor at 10k load.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/cape-bone-iio-00A0.dts | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 33 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-iio-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 4f51526..95067d2 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -146,6 +146,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-lcd3-00A0.dtbo \
+ cape-bone-lcd3-00A2.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
++ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo
+
+ # the geiger cape
+diff --git a/firmware/capes/cape-bone-iio-00A0.dts b/firmware/capes/cape-bone-iio-00A0.dts
+new file mode 100644
+index 0000000..3165702
+--- /dev/null
++++ b/firmware/capes/cape-bone-iio-00A0.dts
+@@ -0,0 +1,32 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "iio-test";
++
++ fragment@0 {
++ target = <&ocp>;
++ __overlay__ {
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ test_helper: helper {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN6";
++ vsense-scale = <100>;
++ status = "okay";
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0364-docs-Added-capemanager-extra_override-usage.patch b/patches/linux-3.8.13/0364-docs-Added-capemanager-extra_override-usage.patch
new file mode 100644
index 0000000..fc60343
--- /dev/null
+++ b/patches/linux-3.8.13/0364-docs-Added-capemanager-extra_override-usage.patch
@@ -0,0 +1,25 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 19 Mar 2013 17:05:01 +0000
+Subject: [PATCH] docs: Added capemanager extra_override usage
+
+Gave an example on using the kernel-command-line override
+slot options for capemanager.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ Documentation/devicetree/bindings/misc/capes-beaglebone.txt | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/misc/capes-beaglebone.txt b/Documentation/devicetree/bindings/misc/capes-beaglebone.txt
+index f73cab5..1af627a 100644
+--- a/Documentation/devicetree/bindings/misc/capes-beaglebone.txt
++++ b/Documentation/devicetree/bindings/misc/capes-beaglebone.txt
+@@ -107,4 +107,7 @@ Example of the override syntax when used on a bone compatible foo board.
+ };
+
+ };
+-
++
++Example of the same override syntax when used from the kernel command-line:
++
++ capemgr.extra_override=FOO-hardcoded:00A0,FOO-another-hardcoded:00A0
diff --git a/patches/linux-3.8.13/0365-capemgr-Added-module-param-descriptions.patch b/patches/linux-3.8.13/0365-capemgr-Added-module-param-descriptions.patch
new file mode 100644
index 0000000..4a12adc
--- /dev/null
+++ b/patches/linux-3.8.13/0365-capemgr-Added-module-param-descriptions.patch
@@ -0,0 +1,23 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 19 Mar 2013 17:05:02 +0000
+Subject: [PATCH] capemgr: Added module param descriptions
+
+Added a simple MODULE_PARM_DESC for the extra_override option
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 255c491..2ee7b11 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -47,6 +47,7 @@
+ /* extra command line overrides */
+ static char *extra_override = NULL;
+ module_param(extra_override, charp, 0444);
++MODULE_PARM_DESC(extra_override, "Comma delimited list of PART-NUMBER[:REV] overrides");
+
+ struct bone_capemgr_info;
+
diff --git a/patches/linux-3.8.13/0366-beaglebone-Add-Adafruit-RTC-prototype-cape.patch b/patches/linux-3.8.13/0366-beaglebone-Add-Adafruit-RTC-prototype-cape.patch
new file mode 100644
index 0000000..ad0dab0
--- /dev/null
+++ b/patches/linux-3.8.13/0366-beaglebone-Add-Adafruit-RTC-prototype-cape.patch
@@ -0,0 +1,122 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 19 Mar 2013 17:04:06 +0000
+Subject: [PATCH] beaglebone: Add Adafruit RTC prototype cape
+
+Add support for a DS1307 RTC prototype cape with level logic
+shifted output. Some applications need an early RTC value and this
+achieves this.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 21 ++++++++++--
+ firmware/Makefile | 1 +
+ firmware/capes/cape-bone-adafruit-rtc-00A0.dts | 42 ++++++++++++++++++++++++
+ 3 files changed, 62 insertions(+), 2 deletions(-)
+ create mode 100644 firmware/capes/cape-bone-adafruit-rtc-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index bcd78a6..d3803e0 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -168,7 +168,7 @@
+ part-number = "BB-BONE-NIXIE";
+ };
+
+- /* adafruit prototype cape */
++ /* adafruit 1.8" TFT prototype cape */
+ slot@8 {
+ ti,cape-override;
+ compatible = "kernel-command-line", "runtime";
+@@ -178,6 +178,16 @@
+ part-number = "BB-BONE-TFT-01";
+ };
+
++ /* adafruit RTC DS1307 prototype cape */
++ slot@9 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-RTC";
++ version = "00A0";
++ manufacturer = "Adafruit";
++ part-number = "BB-BONE-RTC-01";
++ };
++
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -262,7 +272,14 @@
+ dtbo = "cape-bone-adafruit-lcd-00A0.dtbo";
+ };
+ };
+-
++
++ cape@8 {
++ part-number = "BB-BONE-RTC-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-adafruit-rtc-00A0.dtbo";
++ };
++ };
+ };
+ };
+ };
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 95067d2..2cc21d4 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -140,6 +140,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-2g-emmc1.dtbo \
+ cape-bone-adafruit-lcd-00A0.dtbo \
++ cape-bone-adafruit-rtc-00A0.dtbo \
+ cape-bone-dvi-00A0.dtbo \
+ cape-bone-dvi-00A1.dtbo \
+ cape-bone-dvi-00A2.dtbo \
+diff --git a/firmware/capes/cape-bone-adafruit-rtc-00A0.dts b/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
+new file mode 100644
+index 0000000..9436fd4
+--- /dev/null
++++ b/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
+@@ -0,0 +1,42 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/*
++ * Pin assignments
++ *
++ * Module Connector
++ * SCL -> P9.19
++ * SDA <- P9.20
++ * SQW <- NC
++ *
++ */
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "BB-BONE-RTC-01";
++ version = "00A0";
++
++
++ fragment@0 {
++ target = <&i2c2>;
++
++ __overlay__ {
++ /* shut up DTC warnings */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* DS1307 RTC module */
++ rtc@68 {
++ compatible = "dallas,ds1307";
++ reg = <0x68>;
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0367-cape-vsense-scale-division-by-zero-check.patch b/patches/linux-3.8.13/0367-cape-vsense-scale-division-by-zero-check.patch
new file mode 100644
index 0000000..abeb265
--- /dev/null
+++ b/patches/linux-3.8.13/0367-cape-vsense-scale-division-by-zero-check.patch
@@ -0,0 +1,47 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 19 Mar 2013 17:05:44 +0000
+Subject: [PATCH] cape: vsense-scale division by zero check
+
+Catch corner case of division by zero when passing
+in vsense-scale property from the device tree.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/misc/cape/beaglebone/cape-bone-geiger.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/misc/cape/beaglebone/cape-bone-geiger.c b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
+index 6be383e..fa57be0 100644
+--- a/drivers/misc/cape/beaglebone/cape-bone-geiger.c
++++ b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
+@@ -75,6 +75,9 @@ static const struct of_device_id bonegeiger_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, bonegeiger_of_match);
+
++
++#define DEFAULT_VSENSE_SCALE 37325 /* 373.25 */
++
+ static int bonegeiger_start(struct platform_device *pdev)
+ {
+ struct bone_geiger_info *info = platform_get_drvdata(pdev);
+@@ -377,12 +380,19 @@ static int bonegeiger_probe(struct platform_device *pdev)
+ }
+
+ if (of_property_read_u32(pnode, "vsense-scale", &info->vsense_scale) != 0) {
+- info->vsense_scale = 37325; /* 373.25 */
++ info->vsense_scale = DEFAULT_VSENSE_SCALE;
+ dev_warn(&pdev->dev, "Could not read vsense-scale property; "
+ "using default %u\n",
+ info->vsense_scale);
+ }
+
++ if (info->vsense_scale == 0) {
++ info->vsense_scale = DEFAULT_VSENSE_SCALE;
++ dev_warn(&pdev->dev, "Invalid 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(&pdev->dev, "Could not get %s analog input\n",
diff --git a/patches/linux-3.8.13/0368-capes-add-cape-for-beaglebone-based-Hexy-robot.patch b/patches/linux-3.8.13/0368-capes-add-cape-for-beaglebone-based-Hexy-robot.patch
new file mode 100644
index 0000000..922bac0
--- /dev/null
+++ b/patches/linux-3.8.13/0368-capes-add-cape-for-beaglebone-based-Hexy-robot.patch
@@ -0,0 +1,214 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 20 Mar 2013 13:13:41 +0100
+Subject: [PATCH] capes: add cape for beaglebone based Hexy robot
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 16 +++
+ firmware/Makefile | 1 +
+ firmware/capes/cape-bone-hexy-00A0.dts | 150 +++++++++++++++++++++++++++++
+ 3 files changed, 167 insertions(+)
+ create mode 100644 firmware/capes/cape-bone-hexy-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index d3803e0..3dfbb86 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -188,6 +188,14 @@
+ part-number = "BB-BONE-RTC-01";
+ };
+
++ slot@10 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-Hexy";
++ version = "00A0";
++ manufacturer = "Koen Kooi";
++ part-number = "BB-BONE-HEXY-01";
++ };
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -280,6 +288,14 @@
+ dtbo = "cape-bone-adafruit-rtc-00A0.dtbo";
+ };
+ };
++
++ cape@9 {
++ part-number = "BB-BONE-HEXY-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-hexy-00A0.dtbo";
++ };
++ };
+ };
+ };
+ };
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 2cc21d4..1a81f3f 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -144,6 +144,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-dvi-00A0.dtbo \
+ cape-bone-dvi-00A1.dtbo \
+ cape-bone-dvi-00A2.dtbo \
++ cape-bone-hexy-00A0.dtbo \
+ cape-bone-lcd3-00A0.dtbo \
+ cape-bone-lcd3-00A2.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
+diff --git a/firmware/capes/cape-bone-hexy-00A0.dts b/firmware/capes/cape-bone-hexy-00A0.dts
+new file mode 100644
+index 0000000..4a13484
+--- /dev/null
++++ b/firmware/capes/cape-bone-hexy-00A0.dts
+@@ -0,0 +1,150 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
++* Copyright (C) 2013 Koen Kooi <koen@circuitco.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/;
++/plugin/;
++
++/*
++ * Pin assignments
++ *
++ * Module Connector
++ * LITE <- P8.19
++ * MISO -> P9.29
++ * SCK <- P9.31
++ * MOSI <- P9.30
++ * TFT_CS <- P9.28
++ * CARD_CS <- NC
++ * D/C <- P9.25
++ * RESET <- P9.27
++ *
++ */
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "BB-BONE-HEXY-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_backlight_pins: pinmux_pwm_backlight_pins {
++ pinctrl-single,pins = <
++ 0x020 0x4 /* gpmc_ad8.gpio0_22 | MODE4 */
++ >;
++ };
++
++ bone_hexy_lcd_pins: pinmux_bone_hexy_lcd_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
++
++ bone_hexy_spi1_pins: pinmux_adafruit_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&epwmss2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++
++ fragment@3 {
++ target = <&spi1>;
++
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_hexy_spi1_pins>;
++
++ lcd@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
++ reg = <0>;
++
++ spi-max-frequency = <16000000>;
++ spi-cpol;
++ spi-cpha;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_hexy_lcd_pins>;
++
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++ };
++ };
++
++ fragment@4 {
++ target = <&ocp>;
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ __overlay__ {
++ hexy_display {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_backlight_pins>;
++
++ pwms = <&ehrpwm2 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 */
++ };
++ };
++ };
++
++ fragment@5 {
++ target = <&i2c2>;
++
++ __overlay__ {
++ /* needed to avoid gripping by DTC */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ lsm303dlhc_magn@1e {
++ compatible = "st,lsm303dlhc_magn";
++ reg = <0x1E>;
++ };
++
++ lsm303dlh_accel@1e {
++ compatible = "st,lsm303dlhc_accel";
++ reg = <0x19>;
++ };
++ vcnl4000@13 {
++ compatible = "vishay,vcnl4000";
++ reg = <0x13>;
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0369-Extend-bone-iio-helper.patch b/patches/linux-3.8.13/0369-Extend-bone-iio-helper.patch
new file mode 100644
index 0000000..2a2c6ee
--- /dev/null
+++ b/patches/linux-3.8.13/0369-Extend-bone-iio-helper.patch
@@ -0,0 +1,232 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 21 Mar 2013 14:32:03 +0200
+Subject: [PATCH] Extend bone-iio helper
+
+Allow multiple ADC entries.
+DT bindinds are extended so you can do:
+
+vsense-name = "AIN1", "AIN3";
+vsense-scale = <100 100>;
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/bone-iio-helper.c | 152 +++++++++++++++++-------
+ 1 file changed, 110 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/bone-iio-helper.c b/drivers/misc/cape/beaglebone/bone-iio-helper.c
+index d2c76e1..a919857 100644
+--- a/drivers/misc/cape/beaglebone/bone-iio-helper.c
++++ b/drivers/misc/cape/beaglebone/bone-iio-helper.c
+@@ -45,44 +45,51 @@ static const struct of_device_id bone_iio_helper_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, bone_iio_helper_of_match);
+
+-struct iio_helper_info {
+- struct platform_device *pdev;
++struct iio_helper_info;
++
++struct iio_helper_chan {
++ struct iio_helper_info *info;
++ int index;
+ const char *vsense_name;
+ unsigned int vsense_scale;
+ struct iio_channel *vsense_channel;
++ struct device_attribute attr;
++ unsigned int attr_created : 1;
++};
++
++#define iio_helper_attr_to_chan(attr) \
++ container_of((attr), struct iio_helper_chan, attr)
++
++struct iio_helper_info {
++ struct platform_device *pdev;
++ int channel_count;
++ struct iio_helper_chan *channel;
++ u32 *scale;
+ };
+
+ static ssize_t iio_helper_show_mvolts(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+- struct platform_device *pdev = to_platform_device(dev);
+- struct iio_helper_info *info = platform_get_drvdata(pdev);
++ struct iio_helper_chan *chan = iio_helper_attr_to_chan(attr);
+ int ret, val;
+ u32 mvolts;
+
+- ret = iio_read_channel_raw(info->vsense_channel, &val);
++ ret = iio_read_channel_raw(chan->vsense_channel, &val);
+ if (ret < 0)
+ return ret;
+
+ /* volts = ((1800 / 4096) * val * scale) = (1.8 * val * scale /4096) */
+- mvolts = div_u64(1800 * info->vsense_scale * (u64)val, 4096 * 100);
++ mvolts = div_u64(1800 * chan->vsense_scale * (u64)val, 4096 * 100);
+
+ return sprintf(buf, "%d\n", mvolts);
+ }
+
+-static DEVICE_ATTR(mvolts, S_IRUGO,
+- iio_helper_show_mvolts, NULL);
+-
+-static int iio_helper_sysfs_register(struct platform_device *pdev)
+-{
+- return device_create_file(&pdev->dev, &dev_attr_mvolts);
+-}
+-
+ static int bone_iio_helper_probe(struct platform_device *pdev)
+ {
+ struct iio_helper_info *info;
++ struct iio_helper_chan *chan;
+ struct device_node *pnode = pdev->dev.of_node;
+- int err;
++ int i, err;
+
+ /* we only support OF */
+ if (pnode == NULL) {
+@@ -99,46 +106,101 @@ static int bone_iio_helper_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, info);
+ info->pdev = pdev;
+
+- if (of_property_read_string(pnode, "vsense-name", &info->vsense_name) != 0) {
+- dev_err(&pdev->dev, "Could not read vsense-name property.");
+- err = -EINVAL;
++ err = of_property_count_strings(pnode, "vsense-name");
++ if (err < 0) {
++ dev_err(&pdev->dev, "Failed on vsense-name string property\n");
+ goto err_no_vsense;
+ }
+-
+- if (of_property_read_u32(pnode, "vsense-scale", &info->vsense_scale) != 0) {
+- dev_err(&pdev->dev, "Could not read vsense-scale property");
++ if (err == 0) {
++ dev_err(&pdev->dev, "vsense-name property is empty\n");
+ err = -EINVAL;
+ goto err_no_vsense;
+ }
+-
+- if (info->vsense_scale == 0) {
+- dev_err(&pdev->dev, "Invalid vsense-scale property");
+- err = -EINVAL;
+- goto err_no_vsense;
++ info->channel_count = err;
++ info->channel = devm_kzalloc(&pdev->dev,
++ info->channel_count * sizeof(*info->channel), GFP_KERNEL);
++ if (info->channel == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate channel array\n");
++ err = -ENOMEM;
++ goto err_no_chan;
+ }
+
+- info->vsense_channel = iio_channel_get(NULL, info->vsense_name);
+- if (IS_ERR(info->vsense_channel)) {
+- dev_err(&pdev->dev, "Could not get %s analog input\n",
+- info->vsense_name);
+- err = PTR_ERR(info->vsense_channel);
+- goto err_no_vsense;
++ info->scale = devm_kzalloc(&pdev->dev,
++ info->channel_count * sizeof(*info->scale), GFP_KERNEL);
++ if (info->scale == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate scale array\n");
++ err = -ENOMEM;
++ goto err_no_scale;
+ }
+
+- err = iio_helper_sysfs_register(pdev);
++ err = of_property_read_u32_array(pnode, "vsense-scale", info->scale,
++ info->channel_count);
+ if (err != 0) {
+- dev_err(&pdev->dev, "unable to register sysfs\n");
+- goto err_no_sysfs;
++ dev_err(&pdev->dev, "Failed to read vsense-scale array\n");
++ goto err_bad_scale;
++ }
++
++ for (i = 0; i < info->channel_count; i++) {
++
++ chan = &info->channel[i];
++
++ err = of_property_read_string_index(pnode, "vsense-name", i,
++ &chan->vsense_name);
++ if (err != 0) {
++ dev_err(&pdev->dev, "Error on vsense-name #%d\n", i);
++ goto err_bad_chan;
++ }
++
++ chan->vsense_scale = info->scale[i];
++ if (chan->vsense_scale == 0) {
++ dev_err(&pdev->dev, "vsense-sense #%d zero\n", i);
++ err = -EINVAL;
++ goto err_bad_chan;
++ }
++
++ chan->vsense_channel = iio_channel_get(NULL, chan->vsense_name);
++ if (IS_ERR(chan->vsense_channel)) {
++ dev_err(&pdev->dev, "Could not get %s analog input\n",
++ chan->vsense_name);
++ err = PTR_ERR(chan->vsense_channel);
++ chan->vsense_channel = NULL;
++ goto err_bad_chan;
++ }
++
++ chan->attr.attr.name = chan->vsense_name;
++ chan->attr.attr.mode = S_IRUGO;
++ chan->attr.show = iio_helper_show_mvolts;
++ chan->attr.store = NULL;
++
++ err = device_create_file(&pdev->dev, &chan->attr);
++ if (err != 0) {
++ dev_err(&pdev->dev, "Could not create %s attr\n",
++ chan->vsense_name);
++ goto err_bad_chan;
++ }
++ chan->attr_created = 1;
+ }
+
+ dev_info(&pdev->dev, "ready\n");
+
+ return 0;
+-
+-err_no_sysfs:
+- /* fall-through */
++err_bad_chan:
++ /* cleanup possible channels allocated */
++ for (i = info->channel_count - 1; i >= 0; i--) {
++ chan = &info->channel[i];
++ if (chan->attr_created)
++ device_remove_file(&pdev->dev, &chan->attr);
++ if (chan->vsense_channel != NULL)
++ iio_channel_release(chan->vsense_channel);
++ }
++err_bad_scale:
++ /* nothing */
++err_no_scale:
++ /* nothing */
+ err_no_vsense:
+- kfree(info);
++ /* nothing */
++err_no_chan:
++ /* nothing */
+ err_no_mem:
+ return err;
+ }
+@@ -148,10 +210,16 @@ static int bone_iio_helper_remove(struct platform_device *pdev)
+ {
+ struct iio_helper_info *info = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
++ struct iio_helper_chan *chan;
++ int i;
+
+- iio_channel_release(info->vsense_channel);
+- device_remove_file(dev, &dev_attr_mvolts);
+- kfree(info->vsense_name);
++ for (i = info->channel_count - 1; i >= 0; i--) {
++ chan = &info->channel[i];
++ device_remove_file(&pdev->dev, &chan->attr);
++ iio_channel_release(chan->vsense_channel);
++ }
++ devm_kfree(dev, info->scale);
++ devm_kfree(dev, info->channel);
+ devm_kfree(dev, info);
+
+ return 0;
diff --git a/patches/linux-3.8.13/0370-Update-iio-helper-with-more-channels.patch b/patches/linux-3.8.13/0370-Update-iio-helper-with-more-channels.patch
new file mode 100644
index 0000000..55e2f15
--- /dev/null
+++ b/patches/linux-3.8.13/0370-Update-iio-helper-with-more-channels.patch
@@ -0,0 +1,40 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 21 Mar 2013 14:34:24 +0200
+Subject: [PATCH] Update iio helper with more channels
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-bone-iio-00A0.dts | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-iio-00A0.dts b/firmware/capes/cape-bone-iio-00A0.dts
+index 3165702..f1cf814 100644
+--- a/firmware/capes/cape-bone-iio-00A0.dts
++++ b/firmware/capes/cape-bone-iio-00A0.dts
+@@ -21,10 +21,24 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ adc {
++ ti,adc-channels = <0 1 2 3 4 5 6 7>;
++ };
++ };
++
+ test_helper: helper {
+ compatible = "bone-iio-helper";
+- vsense-name = "AIN6";
+- vsense-scale = <100>;
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ vsense-scale = <100 100 100 100 100 100 100 100>;
+ status = "okay";
+ };
+ };
diff --git a/patches/linux-3.8.13/0371-Add-ADC-IIO-helper.patch b/patches/linux-3.8.13/0371-Add-ADC-IIO-helper.patch
new file mode 100644
index 0000000..398a28f
--- /dev/null
+++ b/patches/linux-3.8.13/0371-Add-ADC-IIO-helper.patch
@@ -0,0 +1,48 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 21 Mar 2013 17:08:58 +0200
+Subject: [PATCH] Add ADC IIO helper
+
+---
+ firmware/capes/cape-bone-tester-00A0.dts | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index d5b7607..333849c 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -450,5 +450,35 @@
+ };
+ };
+
++ fragment@6 {
++ target = <&ocp>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ adc {
++ ti,adc-channels = <0 1 2 3 4 5 6 7>;
++ };
++ };
++
++ tester_iio_helper {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ vsense-scale = <100 100 100 100 100 100 100 100>;
++ // vsense-scale = <200 200 296 296 296 296 100 100>;
++ /* 3.3V 3.3V 5V 5V 5V 5V 1.8V */
++ status = "okay";
++ };
++ };
++ };
+ };
+
diff --git a/patches/linux-3.8.13/0372-Changing-DT-data-to-make-selection-of-standard-i.e.-.patch b/patches/linux-3.8.13/0372-Changing-DT-data-to-make-selection-of-standard-i.e.-.patch
new file mode 100644
index 0000000..a635a8b
--- /dev/null
+++ b/patches/linux-3.8.13/0372-Changing-DT-data-to-make-selection-of-standard-i.e.-.patch
@@ -0,0 +1,21 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Thu, 21 Mar 2013 13:53:54 -0500
+Subject: [PATCH] Changing DT data to make selection of standard (i.e.
+ non-reduced blanking) modes the default
+
+---
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index b080907..02bcb93 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -65,6 +65,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
++ ti,allow-non-reduced-blanking-modes;
+ };
+
+ };
diff --git a/patches/linux-3.8.13/0373-Enhancing-to-support-extra-device-tree-options-for-t.patch b/patches/linux-3.8.13/0373-Enhancing-to-support-extra-device-tree-options-for-t.patch
new file mode 100644
index 0000000..c5a5d5b
--- /dev/null
+++ b/patches/linux-3.8.13/0373-Enhancing-to-support-extra-device-tree-options-for-t.patch
@@ -0,0 +1,147 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Thu, 21 Mar 2013 16:23:03 -0500
+Subject: [PATCH] Enhancing to support extra device tree options for tilcdc:
+ ti,max_width (maximum width in pixels) ti,max_pixelclock
+ (maximum allowable pixel clock for the device) also added
+ some extra debugging enabled with drm debug to help
+ understand why modes are being selected or rejected.
+
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 36 +++++++++++++++++++++++++++++-----
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 18 ++++++++++++++++-
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 14 +++++++++++++
+ 3 files changed, 62 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index fe47255..edafddc 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -425,12 +425,15 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc)
+ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ int rb_check)
+ {
+- struct tilcdc_drm_private *priv = crtc->dev->dev_private;
++ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+ unsigned int bandwidth;
++
+ int rb;
+
+- if (mode->hdisplay > tilcdc_crtc_max_width(crtc))
++ /* check to see if the width is within the range that the LCD Controller physically supports */
++ if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) {
+ return MODE_VIRTUAL_X;
++ }
+
+ /* width must be multiple of 16 */
+ if (mode->hdisplay & 0xf)
+@@ -439,10 +442,31 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ if (mode->vdisplay > 2048)
+ return MODE_VIRTUAL_Y;
+
++
++ DBG("Processing mode %dx%d@%d with pixel clock %d",
++ mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), mode->clock);
++
++ /* some devices have a maximum allowed pixel clock */
++ /* configured from the DT */
++ if(mode->clock > priv->max_pixelclock) {
++ DBG("Rejecting mode, pixel clock too high");
++ return MODE_BAD;
++ }
++
++ /* some devices further limit the max horizontal resolution */
++ /* configured from the DT */
++ if(mode->hdisplay > priv->max_width) {
++ return MODE_BAD;
++ }
++
+ /* filter out modes that would require too much memory bandwidth: */
++ /* configured from the DT */
+ bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode);
+- if (bandwidth > priv->max_bandwidth)
+- return MODE_BAD;
++ if (bandwidth > priv->max_bandwidth) {
++ DBG("Rejecting mode, exceeds defined bandwidth limit");
++ return MODE_BAD;
++ }
++
+
+ if (rb_check) {
+ /* we only support reduced blanking modes */
+@@ -450,8 +474,10 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ (mode->hsync_end - mode->hdisplay == 80) &&
+ (mode->hsync_end - mode->hsync_start == 32) &&
+ (mode->vsync_start - mode->vdisplay == 3);
+- if (!rb)
++ if (!rb) {
++ DBG("Throwing away because we only support reduced blanking");
+ return MODE_BAD;
++ }
+ }
+
+ return MODE_OK;
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index 0fe14ea..fca4f16 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -236,11 +236,27 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+ #endif
+
+ if (of_property_read_u32(node, "ti,max-bandwidth", &priv->max_bandwidth))
+- priv->max_bandwidth = 1280 * 1024 * 60;
++ priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH;
++
++ DBG("Maximum Bandwidth Value %d", priv->max_bandwidth);
++
++ if (of_property_read_u32(node, "ti,max-width", &priv->max_width))
++ priv->max_width = TILCDC_DEFAULT_MAX_WIDTH;
++
++ DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width);
++
++ if (of_property_read_u32(node, "ti,max-pixelclock", &priv->max_pixelclock))
++ priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK;
++
++ DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
++
+
+ priv->allow_non_rblank = of_property_read_bool(node,
+ "ti,allow-non-reduced-blanking-modes");
+
++
++ DBG("Allowing Standard Monitor Modes: %s", priv->allow_non_rblank?"true":"false");
++
+ pm_runtime_enable(dev->dev);
+
+ /* Determine LCD IP Version */
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index b04f94c..48d744c 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -34,6 +34,13 @@
+ #include <drm/drm_gem_cma_helper.h>
+ #include <drm/drm_fb_cma_helper.h>
+
++/* Defaulting to pixel clock defined on AM335x */
++#define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000
++/* Defaulting to max width as defined on AM335x */
++#define TILCDC_DEFAULT_MAX_WIDTH 1366
++/* This may need some tweaking, but want to allow at least 1280x1024@60 */
++#define TILCDC_DEFAULT_MAX_BANDWIDTH (1366*1024*60)
++
+ struct tilcdc_drm_private {
+ void __iomem *mmio;
+
+@@ -43,6 +50,13 @@ struct tilcdc_drm_private {
+
+ /* don't attempt resolutions w/ higher W * H * Hz: */
+ uint32_t max_bandwidth;
++ /* Pixel Clock will be restricted to some value as defined in the device datasheet */
++ /* measured in KHz */
++ uint32_t max_pixelclock;
++ /* Max allowable width is limited on a per device basis */
++ /* measured in pixels */
++ uint32_t max_width;
++
+ int allow_non_rblank; /* ATM we don't support non reduced blank modes */
+
+ /* register contents saved across suspend/resume: */
diff --git a/patches/linux-3.8.13/0374-add-WIP-support-LCD4-rev-00A4.patch b/patches/linux-3.8.13/0374-add-WIP-support-LCD4-rev-00A4.patch
new file mode 100644
index 0000000..a1714cd
--- /dev/null
+++ b/patches/linux-3.8.13/0374-add-WIP-support-LCD4-rev-00A4.patch
@@ -0,0 +1,269 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 25 Mar 2013 13:35:38 +0100
+Subject: [PATCH] add WIP support LCD4 rev 00A4
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 240 +++++++++++++++++++++++++++++++
+ 2 files changed, 241 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-LCD7-01-00A4.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 1a81f3f..68f620c 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -148,6 +148,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-lcd3-00A0.dtbo \
+ cape-bone-lcd3-00A2.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
++ BB-BONE-LCD7-01-00A4.dtbo \
+ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+new file mode 100644
+index 0000000..e0a0677
+--- /dev/null
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -0,0 +1,240 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-LCD7-01";
++ version = "00A4";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_lcd7_cape_led_00A4_pins: pinmux_bone_lcd7_cape_led_00A4_pins {
++ pinctrl-single,pins = <
++ 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ pwm_bl_pins: pinmux_pwm_bl_pins {
++ pinctrl-single,pins = <
++ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
++ pinctrl-single,pins = <
++ //0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 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_lcd7_cape_keys_00A4_pins: pinmux_bone_lcd7_cape_keys_00A4_pins {
++ pinctrl-single,pins = <
++ 0x040 0x2f /* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
++ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
++ 0x1a4 0x2f /* TSC_INTn mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
++ // gpio3_16 KEY_DOWN
++ >;
++ };
++
++ };
++ };
++
++ fragment@1 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_bl_pins>;
++ status = "okay";
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "LCD7";
++ 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 */
++ };
++
++ gpio-leds-cape-lcd7 {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++
++ pinctrl-0 = <&bone_lcd7_cape_led_00A4_pins>;
++
++ lcd7-led0 {
++ label = "lcd7:green:usr0";
++ gpios = <&gpio2 28 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd7_cape_keys_00A4_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 = <&gpio2 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio4 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 3 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++
++ /* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */
++ panel {
++ compatible = "tilcdc,panel";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd7_cape_lcd_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 800x480 {
++ hactive = <800>;
++ vactive = <480>;
++ hback-porch = <39>;
++ hfront-porch = <39>;
++ hsync-len = <47>;
++ vback-porch = <29>;
++ vfront-porch = <13>;
++ vsync-len = <2>;
++ clock-frequency = <30000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
++ };
++ };
++ };
++
++ fb {
++ compatible = "ti,am33xx-tilcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio2 31 0x0>;
++ ti,allow-non-reduced-blanking-modes;
++ };
++
++ };
++ };
++
++ fragment@4 {
++ target = <&i2c2>;
++
++ __overlay__ {
++ /* needed to avoid gripping by DTC */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ maxtouch@4a {
++ compatible = "mXT224";
++ reg = <0x4a>;
++ interrupt-parent = <&gpio4>;
++ interrupts = <19 0x0>;
++ atmel,irq-gpio = <&gpio4 19 0>;
++ };
++
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0375-add-eMMC-cape-support.patch b/patches/linux-3.8.13/0375-add-eMMC-cape-support.patch
new file mode 100644
index 0000000..b885685
--- /dev/null
+++ b/patches/linux-3.8.13/0375-add-eMMC-cape-support.patch
@@ -0,0 +1,82 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 25 Mar 2013 19:48:34 +0100
+Subject: [PATCH] add eMMC cape support
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/BB-BONE-eMMC1-01-00A0.dts | 53 ++++++++++++++++++++++++++++++
+ 2 files changed, 54 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 68f620c..3f41d45 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -149,6 +149,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-lcd3-00A2.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
+ BB-BONE-LCD7-01-00A4.dtbo \
++ BB-BONE-eMMC1-01-00A0.dtbo \
+ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo
+
+diff --git a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+new file mode 100644
+index 0000000..ebac267
+--- /dev/null
++++ b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+@@ -0,0 +1,53 @@
++/*
++* 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-eMMC1-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ emmc2_pins: pinmux_emmc2_pins {
++ pinctrl-single,pins = <
++ 0x80 0x32 /* gpmc_csn1.mmc1_clk, INPUT_PULLUP | MODE2 */
++ 0x84 0x32 /* gpmc_csn1.mmc1_cmd, INPUT_PULLUP | MODE2 */
++ 0x00 0x31 /* gpmc_ad0.mmc1_dat0, INPUT_PULLUP | MODE1 */
++ 0x04 0x31 /* gpmc_ad1.mmc1_dat1, INPUT_PULLUP | MODE1 */
++ 0x08 0x31 /* gpmc_ad2.mmc1_dat2, INPUT_PULLUP | MODE1 */
++ 0x0c 0x31 /* gpmc_ad3.mmc1_dat3, INPUT_PULLUP | MODE1 */
++ 0x10 0x31 /* gpmc_ad4.mmc1_dat4, INPUT_PULLUP | MODE1 */
++ 0x14 0x31 /* gpmc_ad5.mmc1_dat5, INPUT_PULLUP | MODE1 */
++ 0x18 0x31 /* gpmc_ad6.mmc1_dat6, INPUT_PULLUP | MODE1 */
++ 0x1c 0x31 /* gpmc_ad7.mmc1_dat7, INPUT_PULLUP | MODE1 */
++
++ /* the reset */
++ 0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */
++ >;
++ };
++ };
++ };
++ fragment@1 {
++ target = <&mmc2>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&emmc2_pins>; /* wrong numbering */
++ vmmc-supply = <&ldo3_reg>;
++ bus-width = <8>;
++ ti,non-removable;
++ status = "okay";
++ reset-gpios = <&gpio2 20 1>; /* active low */
++ ti,vcc-aux-disable-is-sleep;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0376-Remove-UART-pins-from-the-expansion-set.patch b/patches/linux-3.8.13/0376-Remove-UART-pins-from-the-expansion-set.patch
new file mode 100644
index 0000000..1ad389e
--- /dev/null
+++ b/patches/linux-3.8.13/0376-Remove-UART-pins-from-the-expansion-set.patch
@@ -0,0 +1,34 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 25 Mar 2013 12:53:22 +0200
+Subject: [PATCH] Remove UART pins from the expansion set
+
+---
+ firmware/capes/cape-bone-tester-00A0.dts | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index 333849c..cf0b5a8 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -101,8 +101,8 @@
+ 0x164 0x2f /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
+
+ /* the UART pins */
+- 0x184 0x2f /* 24 UART1_TXD uart1_txd.gpio0[15] */
+- 0x180 0x2f /* 26 UART1_RXD uart1_rxd.gpio0[14] */
++ // 0x184 0x2f /* 24 UART1_TXD uart1_txd.gpio0[15] */
++ // 0x180 0x2f /* 26 UART1_RXD uart1_rxd.gpio0[14] */
+ >;
+ };
+
+@@ -181,8 +181,8 @@
+ 0x164 0x07 /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
+
+ /* the uart pins */
+- 0x184 0x07 /* 24 UART1_TXD uart1_txd.gpio0[15] */
+- 0x180 0x07 /* 26 UART1_RXD uart1_rxd.gpio0[14] */
++ // 0x184 0x07 /* 24 UART1_TXD uart1_txd.gpio0[15] */
++ // 0x180 0x07 /* 26 UART1_RXD uart1_rxd.gpio0[14] */
+ >;
+ };
+
diff --git a/patches/linux-3.8.13/0377-Remove-LCD-pins-from-the-expansion-test-part.patch b/patches/linux-3.8.13/0377-Remove-LCD-pins-from-the-expansion-test-part.patch
new file mode 100644
index 0000000..4713ac7
--- /dev/null
+++ b/patches/linux-3.8.13/0377-Remove-LCD-pins-from-the-expansion-test-part.patch
@@ -0,0 +1,106 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 25 Mar 2013 15:20:06 +0200
+Subject: [PATCH] Remove LCD pins from the expansion test part
+
+---
+ firmware/capes/cape-bone-tester-00A0.dts | 80 +++++++++++++++---------------
+ 1 file changed, 40 insertions(+), 40 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index cf0b5a8..1f36284 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -54,26 +54,26 @@
+ 0x004 0x2f /* 24 GPIO1_1 gpmc_ad1 .gpio1[1] */
+ 0x000 0x2f /* 25 GPIO1_0 gpmc_ad0 .gpio1[0] */
+ 0x07C 0x2f /* 26 GPIO1_29 gpmc_csn0.gpio1[29] */
+- 0x0E0 0x2f /* 27 GPIO2_22 lcd_vsync.gpio2[22] */
+- 0x0E8 0x2f /* 28 GPIO2_24 lcd_pclk .gpio2[24] */
+- 0x0E4 0x2f /* 29 GPIO2_23 lcd_hsync.gpio2[23] */
+- 0x0EC 0x2f /* 30 GPIO2_25 lcd_ac_bias_en.gpio2[25] */
+- 0x0D8 0x2f /* 31 UART5_CTSN lcd_data14.gpio0[10] */
+- 0x0DC 0x2f /* 32 UART5_RTSN lcd_data15.gpio0[11] */
+- 0x0D4 0x2f /* 33 UART4_RTSN lcd_data13.gpio0[9] */
+- 0x0CC 0x2f /* 34 UART3_RTSN lcd_data11.gpio2[17] */
+- 0x0D0 0x2f /* 35 UART4_CTSN lcd_data12.gpio0[8] */
+- 0x0C8 0x2f /* 36 UART3_CTSN lcd_data10.gpio2[16] */
+- 0x0C0 0x2f /* 37 UART5_TXD lcd_data8.gpio2[14] */
+- 0x0C4 0x2f /* 38 UART5_RXD lcd_data9.gpio2[15] */
+- 0x0B8 0x2f /* 39 GPIO2_12 lcd_data6.gpio2[12] */
+- 0x0BC 0x2f /* 40 GPIO2_13 lcd_data7.gpio2[13] */
+- 0x0B0 0x2f /* 41 GPIO2_10 lcd_data4.gpio2[10] */
+- 0x0B4 0x2f /* 42 GPIO2_11 lcd_data5.gpio2[11] */
+- 0x0A8 0x2f /* 43 GPIO2_8 lcd_data2.gpio2[8] */
+- 0x0AC 0x2f /* 44 GPIO2_9 lcd_data3.gpio2[9] */
+- 0x0A0 0x2f /* 45 GPIO2_6 lcd_data0.gpio2[6] */
+- 0x0A4 0x2f /* 46 GPIO2_7 lcd_data1.gpio2[7] */
++ // 0x0E0 0x2f /* 27 GPIO2_22 lcd_vsync.gpio2[22] */
++ // 0x0E8 0x2f /* 28 GPIO2_24 lcd_pclk .gpio2[24] */
++ // 0x0E4 0x2f /* 29 GPIO2_23 lcd_hsync.gpio2[23] */
++ // 0x0EC 0x2f /* 30 GPIO2_25 lcd_ac_bias_en.gpio2[25] */
++ // 0x0D8 0x2f /* 31 UART5_CTSN lcd_data14.gpio0[10] */
++ // 0x0DC 0x2f /* 32 UART5_RTSN lcd_data15.gpio0[11] */
++ // 0x0D4 0x2f /* 33 UART4_RTSN lcd_data13.gpio0[9] */
++ // 0x0CC 0x2f /* 34 UART3_RTSN lcd_data11.gpio2[17] */
++ // 0x0D0 0x2f /* 35 UART4_CTSN lcd_data12.gpio0[8] */
++ // 0x0C8 0x2f /* 36 UART3_CTSN lcd_data10.gpio2[16] */
++ // 0x0C0 0x2f /* 37 UART5_TXD lcd_data8.gpio2[14] */
++ // 0x0C4 0x2f /* 38 UART5_RXD lcd_data9.gpio2[15] */
++ // 0x0B8 0x2f /* 39 GPIO2_12 lcd_data6.gpio2[12] */
++ // 0x0BC 0x2f /* 40 GPIO2_13 lcd_data7.gpio2[13] */
++ // 0x0B0 0x2f /* 41 GPIO2_10 lcd_data4.gpio2[10] */
++ // 0x0B4 0x2f /* 42 GPIO2_11 lcd_data5.gpio2[11] */
++ // 0x0A8 0x2f /* 43 GPIO2_8 lcd_data2.gpio2[8] */
++ // 0x0AC 0x2f /* 44 GPIO2_9 lcd_data3.gpio2[9] */
++ // 0x0A0 0x2f /* 45 GPIO2_6 lcd_data0.gpio2[6] */
++ // 0x0A4 0x2f /* 46 GPIO2_7 lcd_data1.gpio2[7] */
+
+ /* P9 connector on the bone */
+ /* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
+@@ -134,26 +134,26 @@
+ 0x004 0x07 /* 24 GPIO1_1 gpmc_ad1 .gpio1[1] */
+ 0x000 0x07 /* 25 GPIO1_0 gpmc_ad0 .gpio1[0] */
+ 0x07C 0x07 /* 26 GPIO1_29 gpmc_csn0.gpio1[29] */
+- 0x0E0 0x07 /* 27 GPIO2_22 lcd_vsync.gpio2[22] */
+- 0x0E8 0x07 /* 28 GPIO2_24 lcd_pclk .gpio2[24] */
+- 0x0E4 0x07 /* 29 GPIO2_23 lcd_hsync.gpio2[23] */
+- 0x0EC 0x07 /* 30 GPIO2_25 lcd_ac_bias_en.gpio2[25] */
+- 0x0D8 0x07 /* 31 UART5_CTSN lcd_data14.gpio0[10] */
+- 0x0DC 0x07 /* 32 UART5_RTSN lcd_data15.gpio0[11] */
+- 0x0D4 0x07 /* 33 UART4_RTSN lcd_data13.gpio0[9] */
+- 0x0CC 0x07 /* 34 UART3_RTSN lcd_data11.gpio2[17] */
+- 0x0D0 0x07 /* 35 UART4_CTSN lcd_data12.gpio0[8] */
+- 0x0C8 0x07 /* 36 UART3_CTSN lcd_data10.gpio2[16] */
+- 0x0C0 0x07 /* 37 UART5_TXD lcd_data8.gpio2[14] */
+- 0x0C4 0x07 /* 38 UART5_RXD lcd_data9.gpio2[15] */
+- 0x0B8 0x07 /* 39 GPIO2_12 lcd_data6.gpio2[12] */
+- 0x0BC 0x07 /* 40 GPIO2_13 lcd_data7.gpio2[13] */
+- 0x0B0 0x07 /* 41 GPIO2_10 lcd_data4.gpio2[10] */
+- 0x0B4 0x07 /* 42 GPIO2_11 lcd_data5.gpio2[11] */
+- 0x0A8 0x07 /* 43 GPIO2_8 lcd_data2.gpio2[8] */
+- 0x0AC 0x07 /* 44 GPIO2_9 lcd_data3.gpio2[9] */
+- 0x0A0 0x07 /* 45 GPIO2_6 lcd_data0.gpio2[6] */
+- 0x0A4 0x07 /* 46 GPIO2_7 lcd_data1.gpio2[7] */
++ // 0x0E0 0x07 /* 27 GPIO2_22 lcd_vsync.gpio2[22] */
++ // 0x0E8 0x07 /* 28 GPIO2_24 lcd_pclk .gpio2[24] */
++ // 0x0E4 0x07 /* 29 GPIO2_23 lcd_hsync.gpio2[23] */
++ // 0x0EC 0x07 /* 30 GPIO2_25 lcd_ac_bias_en.gpio2[25] */
++ // 0x0D8 0x07 /* 31 UART5_CTSN lcd_data14.gpio0[10] */
++ // 0x0DC 0x07 /* 32 UART5_RTSN lcd_data15.gpio0[11] */
++ // 0x0D4 0x07 /* 33 UART4_RTSN lcd_data13.gpio0[9] */
++ // 0x0CC 0x07 /* 34 UART3_RTSN lcd_data11.gpio2[17] */
++ // 0x0D0 0x07 /* 35 UART4_CTSN lcd_data12.gpio0[8] */
++ // 0x0C8 0x07 /* 36 UART3_CTSN lcd_data10.gpio2[16] */
++ // 0x0C0 0x07 /* 37 UART5_TXD lcd_data8.gpio2[14] */
++ // 0x0C4 0x07 /* 38 UART5_RXD lcd_data9.gpio2[15] */
++ // 0x0B8 0x07 /* 39 GPIO2_12 lcd_data6.gpio2[12] */
++ // 0x0BC 0x07 /* 40 GPIO2_13 lcd_data7.gpio2[13] */
++ // 0x0B0 0x07 /* 41 GPIO2_10 lcd_data4.gpio2[10] */
++ // 0x0B4 0x07 /* 42 GPIO2_11 lcd_data5.gpio2[11] */
++ // 0x0A8 0x07 /* 43 GPIO2_8 lcd_data2.gpio2[8] */
++ // 0x0AC 0x07 /* 44 GPIO2_9 lcd_data3.gpio2[9] */
++ // 0x0A0 0x07 /* 45 GPIO2_6 lcd_data0.gpio2[6] */
++ // 0x0A4 0x07 /* 46 GPIO2_7 lcd_data1.gpio2[7] */
+
+ /* P9 connector on the bone */
+ /* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
diff --git a/patches/linux-3.8.13/0378-Remove-I2C2-pins-from-expansion-test.patch b/patches/linux-3.8.13/0378-Remove-I2C2-pins-from-expansion-test.patch
new file mode 100644
index 0000000..141cd1f
--- /dev/null
+++ b/patches/linux-3.8.13/0378-Remove-I2C2-pins-from-expansion-test.patch
@@ -0,0 +1,36 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 25 Mar 2013 15:47:28 +0200
+Subject: [PATCH] Remove I2C2 pins from expansion test
+
+It's too difficult for now to see how to test those.
+Temporarily take it out.
+---
+ firmware/capes/cape-bone-tester-00A0.dts | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index 1f36284..4d7dc68 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -86,8 +86,8 @@
+
+ /* err, those two are used for I2C2 on the beaglebone */
+ /* you should boot with I2C2 disabled on the tester */
+- 0x17C 0x2f /* 19 I2C2_SCL uart1_rtsn.gpio0[13] */
+- 0x178 0x2f /* 20 I2C2_SDA uart1_ctsn.gpio0[12] */
++ // 0x17C 0x2f /* 19 I2C2_SCL uart1_rtsn.gpio0[13] */
++ // 0x178 0x2f /* 20 I2C2_SDA uart1_ctsn.gpio0[12] */
+
+ 0x154 0x2f /* 21 UART2_TXD spi0_d0.gpio0[3] */
+ 0x150 0x2f /* 22 UART2_RXD spi0_sclk.gpio0[2] */
+@@ -166,8 +166,8 @@
+
+ /* err, those two are used for I2C2 on the beaglebone */
+ /* you should boot with I2C2 disabled on the tester */
+- 0x17C 0x07 /* 19 I2C2_SCL uart1_rtsn.gpio0[13] */
+- 0x178 0x07 /* 20 I2C2_SDA uart1_ctsn.gpio0[12] */
++ // 0x17C 0x07 /* 19 I2C2_SCL uart1_rtsn.gpio0[13] */
++ // 0x178 0x07 /* 20 I2C2_SDA uart1_ctsn.gpio0[12] */
+
+ 0x154 0x07 /* 21 UART2_TXD spi0_d0.gpio0[3] */
+ 0x150 0x07 /* 22 UART2_RXD spi0_sclk.gpio0[2] */
diff --git a/patches/linux-3.8.13/0379-Add-expansion-test-cape-fragment.patch b/patches/linux-3.8.13/0379-Add-expansion-test-cape-fragment.patch
new file mode 100644
index 0000000..637e15f
--- /dev/null
+++ b/patches/linux-3.8.13/0379-Add-expansion-test-cape-fragment.patch
@@ -0,0 +1,185 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 25 Mar 2013 22:46:14 +0200
+Subject: [PATCH] Add expansion test cape fragment.
+
+Not working yet, since more changes needed, but it's a start.
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/cape-bone-2g-emmc1.dts | 2 +-
+ firmware/capes/cape-bone-exptest-00A0.dts | 140 +++++++++++++++++++++++++++++
+ 3 files changed, 143 insertions(+), 2 deletions(-)
+ create mode 100644 firmware/capes/cape-bone-exptest-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 3f41d45..6d156da 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -151,7 +151,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-LCD7-01-00A4.dtbo \
+ BB-BONE-eMMC1-01-00A0.dtbo \
+ cape-bone-iio-00A0.dtbo \
+- cape-bone-pinmux-test-00A0.dtbo
++ cape-bone-pinmux-test-00A0.dtbo \
++ cape-bone-exptest-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/cape-bone-2g-emmc1.dts b/firmware/capes/cape-bone-2g-emmc1.dts
+index 17ea449..69bb684 100644
+--- a/firmware/capes/cape-bone-2g-emmc1.dts
++++ b/firmware/capes/cape-bone-2g-emmc1.dts
+@@ -22,7 +22,7 @@
+ emmc2_pins: pinmux_emmc2_pins {
+ pinctrl-single,pins = <
+ 0x80 0x32 /* gpmc_csn1.mmc1_clk, INPUT_PULLUP | MODE2 */
+- 0x84 0x32 /* gpmc_csn1.mmc1_cmd, INPUT_PULLUP | MODE2 */
++ 0x84 0x32 /* gpmc_csn2.mmc1_cmd, INPUT_PULLUP | MODE2 */
+ 0x00 0x31 /* gpmc_ad0.mmc1_dat0, INPUT_PULLUP | MODE1 */
+ 0x04 0x31 /* gpmc_ad1.mmc1_dat1, INPUT_PULLUP | MODE1 */
+ 0x08 0x31 /* gpmc_ad2.mmc1_dat2, INPUT_PULLUP | MODE1 */
+diff --git a/firmware/capes/cape-bone-exptest-00A0.dts b/firmware/capes/cape-bone-exptest-00A0.dts
+new file mode 100644
+index 0000000..0d6618c
+--- /dev/null
++++ b/firmware/capes/cape-bone-exptest-00A0.dts
+@@ -0,0 +1,140 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-EXPTEST";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bone_exp_input_gpio_pins: pinmux_bone_exp_input_gpio_pins {
++ pinctrl-single,pins = <
++ /* P8 connector on the bone */
++ /* P3 - P46 pins, B_A3-B_A46, INPUT | PULLDIS | MODE7 */
++ // 0x018 0x2f /* 3 GPIO1_6 gpmc_ad6.gpio1[6] */
++ // 0x01C 0x2f /* 4 GPIO1_7 gpmc_ad7.gpio1[7] */
++ // 0x008 0x2f /* 5 GPIO1_2 gpmc_ad2.gpio1[2] */
++ // 0x00C 0x2f /* 6 GPIO1_3 gpmc_ad3.gpio1[3] */
++ 0x090 0x2f /* 7 TIMER4 gpmc_advn_ale.gpio2[2] */
++ 0x094 0x2f /* 8 TIMER7 gpmc_oen_ren.gpio2[3] */
++ 0x09C 0x2f /* 9 TIMER5 gpmc_ben0_cle.gpio2[5] */
++ 0x098 0x2f /* 10 TIMER6 gpmc_wen.gpio2[4] */
++ 0x034 0x2f /* 11 GPIO1_13 gpmc_ad13.gpio1[13] */
++ 0x030 0x2f /* 12 GPIO1_12 gpmc_ad12.gpio1[12] */
++ 0x024 0x2f /* 13 EHRPWM2B gpmc_ad9 .gpio0[23] */
++ 0x028 0x2f /* 14 GPIO0_26 gpmc_ad10.gpio0[26] */
++ 0x03C 0x2f /* 15 GPIO1_15 gpmc_ad15.gpio1[15] */
++ 0x038 0x2f /* 16 GPIO1_14 gpmc_ad14.gpio1[14] */
++ 0x02C 0x2f /* 17 GPIO0_27 gpmc_ad11.gpio0[27] */
++ 0x08C 0x2f /* 18 GPIO2_1 gpmc_clk .gpio2[1] */
++ 0x020 0x2f /* 19 EHRPWM2A gpmc_ad8 .gpio0[22] */
++ // 0x084 0x2f /* 20 GPIO1_31 gpmc_csn2.gpio1[31] */
++ // 0x080 0x2f /* 21 GPIO1_30 gpmc_csn1.gpio1[30] */
++ // 0x014 0x2f /* 22 GPIO1_5 gpmc_ad5 .gpio1[5] */
++ // 0x010 0x2f /* 23 GPIO1_4 gpmc_ad4 .gpio1[4] */
++ // 0x004 0x2f /* 24 GPIO1_1 gpmc_ad1 .gpio1[1] */
++ // 0x000 0x2f /* 25 GPIO1_0 gpmc_ad0 .gpio1[0] */
++ 0x07C 0x2f /* 26 GPIO1_29 gpmc_csn0.gpio1[29] */
++
++ /* P9 connector on the bone */
++ /* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
++ 0x070 0x2f /* 11 UART4_RXD gpmc_wait0.gpio0[30] */
++ 0x078 0x2f /* 12 GPIO1_28 gpmc_be1n.gpio1[28] */
++ 0x074 0x2f /* 13 UART4_TXD gpmc_wpn.gpio0[31] */
++ 0x048 0x2f /* 14 EHRPWM1A gpmc_a2.gpio1[18] */
++ 0x040 0x2f /* 15 GPIO1_16 gpmc_a0.gpio1[16] */
++ 0x04C 0x2f /* 16 EHRPWM1B gpmc_a3.gpio1[19] */
++
++ 0x154 0x2f /* 21 UART2_TXD spi0_d0.gpio0[3] */
++ 0x150 0x2f /* 22 UART2_RXD spi0_sclk.gpio0[2] */
++ 0x044 0x2f /* 23 GPIO1_17 gpmc_a1.gpio1[17] */
++ 0x1AC 0x2f /* 25 GPIO3_21 mcasp0_ahclkx.gpio3[21]*/
++ 0x1A4 0x2f /* 27 GPIO3_19 mcasp0_fsr.gpio3[19] */
++ 0x19C 0x2f /* 28 SPI1_CS0 mcasp0_ahclkr.gpio3[17]*/
++ 0x198 0x2f /* 30 SPI1_D1 mcasp0_axr0.gpio3[16] */
++ 0x190 0x2f /* 31 SPI1_SCLK mcasp0_aclkx.gpio3[14] */
++ 0x1B4 0x2f /* 41 CLKOUT2 xdma_event_intr1.gpio0[20]*/
++ 0x164 0x2f /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
++ >;
++ };
++
++ bone_exp_output_gpio_pins: pinmux_bone_exp_output_gpio_pins {
++ pinctrl-single,pins = <
++ /* P8 connector on the bone */
++ /* P3 - P46 pins, B_A3-B_A46, OUTPUT | MODE7 */
++ // 0x018 0x07 /* 3 GPIO1_6 gpmc_ad6.gpio1[6] */
++ // 0x01C 0x07 /* 4 GPIO1_7 gpmc_ad7.gpio1[7] */
++ // 0x008 0x07 /* 5 GPIO1_2 gpmc_ad2.gpio1[2] */
++ // 0x00C 0x07 /* 6 GPIO1_3 gpmc_ad3.gpio1[3] */
++ 0x090 0x07 /* 7 TIMER4 gpmc_advn_ale.gpio2[2] */
++ 0x094 0x07 /* 8 TIMER7 gpmc_oen_ren.gpio2[3] */
++ 0x09C 0x07 /* 9 TIMER5 gpmc_ben0_cle.gpio2[5] */
++ 0x098 0x07 /* 10 TIMER6 gpmc_wen.gpio2[4] */
++ 0x034 0x07 /* 11 GPIO1_13 gpmc_ad13.gpio1[13] */
++ 0x030 0x07 /* 12 GPIO1_12 gpmc_ad12.gpio1[12] */
++ 0x024 0x07 /* 13 EHRPWM2B gpmc_ad9 .gpio0[23] */
++ 0x028 0x07 /* 14 GPIO0_26 gpmc_ad10.gpio0[26] */
++ 0x03C 0x07 /* 15 GPIO1_15 gpmc_ad15.gpio1[15] */
++ 0x038 0x07 /* 16 GPIO1_14 gpmc_ad14.gpio1[14] */
++ 0x02C 0x07 /* 17 GPIO0_27 gpmc_ad11.gpio0[27] */
++ 0x08C 0x07 /* 18 GPIO2_1 gpmc_clk .gpio2[1] */
++ 0x020 0x07 /* 19 EHRPWM2A gpmc_ad8 .gpio0[22] */
++ // 0x084 0x07 /* 20 GPIO1_31 gpmc_csn2.gpio1[31] */
++ // 0x080 0x07 /* 21 GPIO1_30 gpmc_csn1.gpio1[30] */
++ // 0x014 0x07 /* 22 GPIO1_5 gpmc_ad5 .gpio1[5] */
++ // 0x010 0x07 /* 23 GPIO1_4 gpmc_ad4 .gpio1[4] */
++ // 0x004 0x07 /* 24 GPIO1_1 gpmc_ad1 .gpio1[1] */
++ // 0x000 0x07 /* 25 GPIO1_0 gpmc_ad0 .gpio1[0] */
++ 0x07C 0x07 /* 26 GPIO1_29 gpmc_csn0.gpio1[29] */
++
++ /* P9 connector on the bone */
++ /* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
++ 0x070 0x07 /* 11 UART4_RXD gpmc_wait0.gpio0[30] */
++ 0x078 0x07 /* 12 GPIO1_28 gpmc_be1n.gpio1[28] */
++ 0x074 0x07 /* 13 UART4_TXD gpmc_wpn.gpio0[31] */
++ 0x048 0x07 /* 14 EHRPWM1A gpmc_a2.gpio1[18] */
++ 0x040 0x07 /* 15 GPIO1_16 gpmc_a0.gpio1[16] */
++ 0x04C 0x07 /* 16 EHRPWM1B gpmc_a3.gpio1[19] */
++
++ 0x154 0x07 /* 21 UART2_TXD spi0_d0.gpio0[3] */
++ 0x150 0x07 /* 22 UART2_RXD spi0_sclk.gpio0[2] */
++ 0x044 0x07 /* 23 GPIO1_17 gpmc_a1.gpio1[17] */
++ 0x1AC 0x07 /* 25 GPIO3_21 mcasp0_ahclkx.gpio3[21]*/
++ 0x1A4 0x07 /* 27 GPIO3_19 mcasp0_fsr.gpio3[19] */
++ 0x19C 0x07 /* 28 SPI1_CS0 mcasp0_ahclkr.gpio3[17]*/
++ 0x198 0x07 /* 30 SPI1_D1 mcasp0_axr0.gpio3[16] */
++ 0x190 0x07 /* 31 SPI1_SCLK mcasp0_aclkx.gpio3[14] */
++ 0x1B4 0x07 /* 41 CLKOUT2 xdma_event_intr1.gpio0[20]*/
++ 0x164 0x07 /* 42 GPIO0_7 eCAP0_in_PWM0_out.gpio0[7]*/
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ exp_test_pinmux_helper {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++
++ pinctrl-names = "input", "output";
++ pinctrl-0 = <&bone_exp_input_gpio_pins>;
++ pinctrl-1 = <&bone_exp_output_gpio_pins>;
++ };
++
++ };
++
++ };
++};
diff --git a/patches/linux-3.8.13/0380-tilcdc-added-some-extra-debug-and-softened-the-wordi.patch b/patches/linux-3.8.13/0380-tilcdc-added-some-extra-debug-and-softened-the-wordi.patch
new file mode 100644
index 0000000..524c5f9
--- /dev/null
+++ b/patches/linux-3.8.13/0380-tilcdc-added-some-extra-debug-and-softened-the-wordi.patch
@@ -0,0 +1,48 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Fri, 22 Mar 2013 15:47:50 -0500
+Subject: [PATCH] tilcdc added some extra debug, and softened the wording of
+ the debug messages when deciding if a mode is supported or
+ not
+
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index edafddc..a98b094 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -449,13 +449,14 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ /* some devices have a maximum allowed pixel clock */
+ /* configured from the DT */
+ if(mode->clock > priv->max_pixelclock) {
+- DBG("Rejecting mode, pixel clock too high");
++ DBG("Pruning mode, pixel clock too high");
+ return MODE_BAD;
+ }
+
+ /* some devices further limit the max horizontal resolution */
+ /* configured from the DT */
+ if(mode->hdisplay > priv->max_width) {
++ DBG("Pruning mode, above max width of %d supported by device", priv->max_width);
+ return MODE_BAD;
+ }
+
+@@ -463,7 +464,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ /* configured from the DT */
+ bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode);
+ if (bandwidth > priv->max_bandwidth) {
+- DBG("Rejecting mode, exceeds defined bandwidth limit");
++ DBG("Pruning mode, exceeds defined bandwidth limit");
+ return MODE_BAD;
+ }
+
+@@ -475,7 +476,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ (mode->hsync_end - mode->hsync_start == 32) &&
+ (mode->vsync_start - mode->vdisplay == 3);
+ if (!rb) {
+- DBG("Throwing away because we only support reduced blanking");
++ DBG("Pruning mode, only support reduced blanking modes");
+ return MODE_BAD;
+ }
+ }
diff --git a/patches/linux-3.8.13/0381-Make-sure-various-timings-fit-within-the-bits-availa.patch b/patches/linux-3.8.13/0381-Make-sure-various-timings-fit-within-the-bits-availa.patch
new file mode 100644
index 0000000..79b661c
--- /dev/null
+++ b/patches/linux-3.8.13/0381-Make-sure-various-timings-fit-within-the-bits-availa.patch
@@ -0,0 +1,137 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Mon, 25 Mar 2013 16:12:14 -0500
+Subject: [PATCH] Make sure various timings fit within the bits available in
+ the LCD controller, otherwise prune the mode. Also adjust
+ the timing values to behave as the TRM indicates with 0
+ representing 1 in some cases.
+
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 75 +++++++++++++++++++++++++++-------
+ 1 file changed, 60 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index a98b094..69675e6 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -289,31 +289,38 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
+ reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
+ LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
++
++ /* subtract one from hfp, hbp, hsw because the hardware uses a value of 0 as 1 */
+ if (priv->rev == 2) {
+- reg |= (hfp & 0x300) >> 8;
+- reg |= (hbp & 0x300) >> 4;
+- reg |= (hsw & 0x3c0) << 21;
++ reg |= ((hfp-1) & 0x300) >> 8;
++ reg |= ((hbp-1) & 0x300) >> 4;
++ reg |= ((hsw-1) & 0x3c0) << 21;
+ }
+ tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
+
++ /* subtract one from hfp, hbp, hsw because the hardware uses a value of 0 as 1 */
++ /* weirdly on BeagleBone Black) the hbp is still wrong when analyzed on hdmi timing tool */
++ /* all other values come out correct - need to look into why this is happening */
++ /* might be something that is happening after the LCD output in the hdmi encoder */
+ reg = (((mode->hdisplay >> 4) - 1) << 4) |
+- ((hbp & 0xff) << 24) |
+- ((hfp & 0xff) << 16) |
+- ((hsw & 0x3f) << 10);
++ (((hbp-1) & 0xff) << 24) |
++ (((hfp-1) & 0xff) << 16) |
++ (((hsw-1) & 0x3f) << 10);
+ if (priv->rev == 2)
+- reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
++ reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
+ tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
+-
++
++ /* only the vertical sync width maps 0 as 1 so only subtract 1 from vsw */
+ reg = ((mode->vdisplay - 1) & 0x3ff) |
+- ((vbp & 0xff) << 24) |
+- ((vfp & 0xff) << 16) |
+- ((vsw & 0x3f) << 10);
++ ((vbp & 0xff) << 24) |
++ ((vfp & 0xff) << 16) |
++ (((vsw-1) & 0x3f) << 10);
+ tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
+
+ /* Configure display type: */
+ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
+- ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
+- LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000);
++ ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
++ LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000);
+ reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
+ if (info->tft_alt_mode)
+ reg |= LCDC_TFT_ALT_ENABLE;
+@@ -325,7 +332,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ case 16:
+ break;
+ case 32:
+- reg |= LCDC_V2_TFT_24BPP_UNPACK;
++ reg |= LCDC_V2_TFT_24BPP_UNPACK;
+ /* fallthrough */
+ case 24:
+ reg |= LCDC_V2_TFT_24BPP_MODE;
+@@ -427,6 +434,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ {
+ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+ unsigned int bandwidth;
++ uint32_t hbp, hfp, hsw, vbp, vfp, vsw;
+
+ int rb;
+
+@@ -446,6 +454,44 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ DBG("Processing mode %dx%d@%d with pixel clock %d",
+ mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), mode->clock);
+
++
++ hbp = mode->htotal - mode->hsync_end;
++ hfp = mode->hsync_start - mode->hdisplay;
++ hsw = mode->hsync_end - mode->hsync_start;
++ vbp = mode->vtotal - mode->vsync_end;
++ vfp = mode->vsync_start - mode->vdisplay;
++ vsw = mode->vsync_end - mode->vsync_start;
++
++ if(hbp & ~0x3ff) {
++ DBG("Pruning mode : Horizontal Back Porch out of range\n");
++ return MODE_BAD;
++ }
++
++ if(hfp & ~0x3ff) {
++ DBG("Pruning mode : Horizontal Front Porch out of range\n");
++ return MODE_BAD;
++ }
++
++ if(hsw & ~0x3ff) {
++ DBG("Pruning mode : Horizontal Sync Width out of range\n");
++ return MODE_BAD;
++ }
++
++ if(vbp & ~0xff) {
++ DBG("Pruning mode : Vertical Back Porch out of range\n");
++ return MODE_BAD;
++ }
++
++ if(vfp & ~0xff) {
++ DBG("Pruning mode : Vertical Front Porch out of range\n");
++ return MODE_BAD;
++ }
++
++ if(vsw & ~0x3f) {
++ DBG("Pruning mode : Vertical Sync Width out of range\n");
++ return MODE_BAD;
++ }
++
+ /* some devices have a maximum allowed pixel clock */
+ /* configured from the DT */
+ if(mode->clock > priv->max_pixelclock) {
+@@ -468,7 +514,6 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ return MODE_BAD;
+ }
+
+-
+ if (rb_check) {
+ /* we only support reduced blanking modes */
+ rb = (mode->htotal - mode->hdisplay == 160) &&
diff --git a/patches/linux-3.8.13/0382-fix-cape-bone-hexy.patch b/patches/linux-3.8.13/0382-fix-cape-bone-hexy.patch
new file mode 100644
index 0000000..1a3c23b
--- /dev/null
+++ b/patches/linux-3.8.13/0382-fix-cape-bone-hexy.patch
@@ -0,0 +1,91 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 26 Mar 2013 17:01:09 +0100
+Subject: [PATCH] fix cape-bone-hexy
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/cape-bone-hexy-00A0.dts | 64 ++++++++++++++++++--------------
+ 1 file changed, 37 insertions(+), 27 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-hexy-00A0.dts b/firmware/capes/cape-bone-hexy-00A0.dts
+index 4a13484..abc1255 100644
+--- a/firmware/capes/cape-bone-hexy-00A0.dts
++++ b/firmware/capes/cape-bone-hexy-00A0.dts
+@@ -25,13 +25,13 @@
+ */
+
+ / {
+- compatible = "ti,beaglebone", "ti,beaglebone-black";
+- part-number = "BB-BONE-HEXY-01";
+- version = "00A0";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "BB-BONE-HEXY-01";
++ version = "00A0";
+
+- fragment@0 {
+- target = <&am33xx_pinmux>;
+- __overlay__ {
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
+ pwm_backlight_pins: pinmux_pwm_backlight_pins {
+ pinctrl-single,pins = <
+ 0x020 0x4 /* gpmc_ad8.gpio0_22 | MODE4 */
+@@ -125,26 +125,36 @@
+ };
+
+ fragment@5 {
+- target = <&i2c2>;
+-
+- __overlay__ {
+- /* needed to avoid gripping by DTC */
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- lsm303dlhc_magn@1e {
+- compatible = "st,lsm303dlhc_magn";
+- reg = <0x1E>;
+- };
+-
+- lsm303dlh_accel@1e {
+- compatible = "st,lsm303dlhc_accel";
+- reg = <0x19>;
+- };
+- vcnl4000@13 {
+- compatible = "vishay,vcnl4000";
+- reg = <0x13>;
+- };
+- };
++ target = <&i2c2>;
++
++ __overlay__ {
++ /* needed to avoid gripping by DTC */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ lsm303dlhc_magn@1e {
++ compatible = "st,lsm303dlhc_magn";
++ reg = <0x1E>;
++ };
++
++ lsm303dlh_accel@1e {
++ compatible = "st,lsm303dlhc_accel";
++ reg = <0x19>;
++ };
++
++ vcnl4000@13 {
++ compatible = "vishay,vcnl4000";
++ reg = <0x13>;
++ };
++
++ ssd1306: oled@3c {
++ compatible = "solomon,ssd1306fb-i2c";
++ reg = <0x3c>;
++ reset-gpios = <&gpio4 19 0>;
++ solomon,height = <32>;
++ solomon,width = <128>;
++ solomon,page-offset = <0>;
++ };
++ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0383-firmware-DT-Fragment-for-MRF24J40-BeagleBone-Cape.patch b/patches/linux-3.8.13/0383-firmware-DT-Fragment-for-MRF24J40-BeagleBone-Cape.patch
new file mode 100644
index 0000000..c24f229
--- /dev/null
+++ b/patches/linux-3.8.13/0383-firmware-DT-Fragment-for-MRF24J40-BeagleBone-Cape.patch
@@ -0,0 +1,109 @@
+From: Alan Ott <alan@signal11.us>
+Date: Thu, 14 Mar 2013 09:36:14 -0400
+Subject: [PATCH] firmware: DT Fragment for MRF24J40 BeagleBone Cape
+
+Support for the Signal 11 MRF24J40 BeagleBone Cape.
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/cape-bone-mrf24j40-00A0.dts | 78 ++++++++++++++++++++++++++++
+ 2 files changed, 80 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/cape-bone-mrf24j40-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 6d156da..36a0dbb 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -152,7 +152,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-eMMC1-01-00A0.dtbo \
+ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo \
+- cape-bone-exptest-00A0.dtbo
++ cape-bone-exptest-00A0.dtbo \
++ cape-bone-mrf24j40-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/cape-bone-mrf24j40-00A0.dts b/firmware/capes/cape-bone-mrf24j40-00A0.dts
+new file mode 100644
+index 0000000..cdef7e2
+--- /dev/null
++++ b/firmware/capes/cape-bone-mrf24j40-00A0.dts
+@@ -0,0 +1,78 @@
++/*
++ * Copyright (C) 2013 Alan Ott <alan@signal11.us>
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti-beaglebone-black";
++
++ /* Identification */
++ part-number = "BB-BONE-MRF24J40";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ mrf24j40_cape_pins: pinmux_mrf24j40_cape_pins {
++ pinctrl-single,pins = <
++ /* Pinmux comes from TRM section
++ 9.3.1: CONTROL_MODULE Regusters. */
++ //0x44 0x2f /* gpmc_a1.gpio1_17 INPUT,no-pull,mode7 */
++ //0x1A4 0x2f /* mcasp0_fsr.gpio3_19 INPUT,no-pull,mode7 */
++ //0x00 0x2f /* gpmc_ad0.gpio1_0 */
++
++ //so use GPIO1_13 (rst), GPIO1_14 (wake), then SPI1_CS0 (CS), and GPIO1_29 (INT)
++ 0x34 0x37 /* gpmc_ad13.gpio1_13 input, pull up, mode 7 */
++ 0x38 0x2f /* gpmc_ad14.gpio1_14 input, no pull, mode 7 */
++ //0x13c 0x2f /* gpmc_ad15.gpio1_15 input, no pull, mode 7 */
++ 0x7c 0x2f /* gpmc_csn0.gpio1_29 input, no pull, mode 7 */
++ >;
++ };
++ };
++
++ };
++
++
++ fragment@1 {
++ target = <&spi1>;
++
++ __overlay__ {
++ /* needed to avoid DTC warnings */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi1_pins_s0>;
++
++ mrf24j40@0 {
++ compatible = "mrf24j40ma";
++ reg = <0>; /* CHIPSEL */
++ spi-max-frequency = <20000000>;
++ mode = <0>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&mrf24j40_cape_pins>;
++
++ interrupt-parent = <&gpio2>;
++ interrupts = <29>;
++
++ // also working feb 9
++ //interrupt-parent = <&gpio2>;
++ //interrupts = <0>;
++
++ //working configuration
++ //interrupt-parent = <&gpio2>;
++ //interrupts = <17>;
++
++ //mrf24j40-wake = <&gpio4 19>;
++ //mrf24j40-reset = <gpio21 0>;
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0384-firmware-capes-Update-MRF24J40-cape-to-work-with-lat.patch b/patches/linux-3.8.13/0384-firmware-capes-Update-MRF24J40-cape-to-work-with-lat.patch
new file mode 100644
index 0000000..83c5b85
--- /dev/null
+++ b/patches/linux-3.8.13/0384-firmware-capes-Update-MRF24J40-cape-to-work-with-lat.patch
@@ -0,0 +1,70 @@
+From: Alan Ott <alan@signal11.us>
+Date: Fri, 29 Mar 2013 16:49:27 -0400
+Subject: [PATCH] firmware: capes: Update MRF24J40 cape to work with latest
+ bone dtsi
+
+am335x-bone-common.dtsi has removed the pinmux settings for SPI1.
+Add them to the MRF24J40 cape dts fragment
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+---
+ firmware/capes/cape-bone-mrf24j40-00A0.dts | 25 ++++++++++---------------
+ 1 file changed, 10 insertions(+), 15 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-mrf24j40-00A0.dts b/firmware/capes/cape-bone-mrf24j40-00A0.dts
+index cdef7e2..0fc2aea 100644
+--- a/firmware/capes/cape-bone-mrf24j40-00A0.dts
++++ b/firmware/capes/cape-bone-mrf24j40-00A0.dts
+@@ -23,19 +23,22 @@
+ pinctrl-single,pins = <
+ /* Pinmux comes from TRM section
+ 9.3.1: CONTROL_MODULE Regusters. */
+- //0x44 0x2f /* gpmc_a1.gpio1_17 INPUT,no-pull,mode7 */
+- //0x1A4 0x2f /* mcasp0_fsr.gpio3_19 INPUT,no-pull,mode7 */
+- //0x00 0x2f /* gpmc_ad0.gpio1_0 */
+
+- //so use GPIO1_13 (rst), GPIO1_14 (wake), then SPI1_CS0 (CS), and GPIO1_29 (INT)
++ /* so use GPIO1_13 (rst), GPIO1_14 (wake), then SPI1_CS0 (CS), and GPIO1_29 (INT) */
+ 0x34 0x37 /* gpmc_ad13.gpio1_13 input, pull up, mode 7 */
+ 0x38 0x2f /* gpmc_ad14.gpio1_14 input, no pull, mode 7 */
+- //0x13c 0x2f /* gpmc_ad15.gpio1_15 input, no pull, mode 7 */
+ 0x7c 0x2f /* gpmc_csn0.gpio1_29 input, no pull, mode 7 */
+ >;
+ };
++ bone_mrf24j40_spi1_pins: pinmux_bone_mrf24j40_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, RX_ENABLED | PULLUP | MODE3 */
++ 0x194 0x33 /* mcasp0_fsx.spi1_d0, RX_ENABLED | PULLUP | MODE3 */
++ 0x198 0x33 /* mcasp0_axr0.spi1_d1, RX_ENABLED | PULLUP | MODE3 */
++ 0x19c 0x33 /* mcasp0_ahclkr.spi1_cs0, RX_ENABLED | PULLUP | MODE3 */
++ >;
++ };
+ };
+-
+ };
+
+
+@@ -49,7 +52,7 @@
+
+ status = "okay";
+ pinctrl-names = "default";
+- pinctrl-0 = <&spi1_pins_s0>;
++ pinctrl-0 = <&bone_mrf24j40_spi1_pins>;
+
+ mrf24j40@0 {
+ compatible = "mrf24j40ma";
+@@ -62,14 +65,6 @@
+ interrupt-parent = <&gpio2>;
+ interrupts = <29>;
+
+- // also working feb 9
+- //interrupt-parent = <&gpio2>;
+- //interrupts = <0>;
+-
+- //working configuration
+- //interrupt-parent = <&gpio2>;
+- //interrupts = <17>;
+-
+ //mrf24j40-wake = <&gpio4 19>;
+ //mrf24j40-reset = <gpio21 0>;
+ };
diff --git a/patches/linux-3.8.13/0385-am335x-bone-common-DT-Override-for-MRF24J40-Cape.patch b/patches/linux-3.8.13/0385-am335x-bone-common-DT-Override-for-MRF24J40-Cape.patch
new file mode 100644
index 0000000..abdc330
--- /dev/null
+++ b/patches/linux-3.8.13/0385-am335x-bone-common-DT-Override-for-MRF24J40-Cape.patch
@@ -0,0 +1,52 @@
+From: Alan Ott <alan@signal11.us>
+Date: Fri, 29 Mar 2013 16:48:42 -0400
+Subject: [PATCH] am335x-bone-common: DT Override for MRF24J40 Cape
+
+Signed-off-by: Alan Ott <alan@signal11.us>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 3dfbb86..29e72a6 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -196,6 +196,15 @@
+ manufacturer = "Koen Kooi";
+ part-number = "BB-BONE-HEXY-01";
+ };
++ /* MRF24J40 Cape Override */
++ slot@11 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-MRF24J40";
++ version = "00A0";
++ manufacturer = "Signal 11 Software";
++ part-number = "BB-BONE-MRF24J40";
++ };
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -272,7 +281,6 @@
+ dtbo = "cape-bone-nixie-00A0.dtbo";
+ };
+ };
+-
+ cape@7 {
+ part-number = "BB-BONE-TFT-01";
+ version@00A0 {
+@@ -296,6 +304,14 @@
+ dtbo = "cape-bone-hexy-00A0.dtbo";
+ };
+ };
++ /* mrf24j40 cape */
++ cape@10 {
++ part-number = "BB-BONE-MRF24J40";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-mrf24j40-00A0.dtbo";
++ };
++ };
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0386-beaglebone-black-limit-LDO3-to-1.8V.patch b/patches/linux-3.8.13/0386-beaglebone-black-limit-LDO3-to-1.8V.patch
new file mode 100644
index 0000000..1cb4c23
--- /dev/null
+++ b/patches/linux-3.8.13/0386-beaglebone-black-limit-LDO3-to-1.8V.patch
@@ -0,0 +1,26 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Sat, 30 Mar 2013 08:37:26 +0100
+Subject: [PATCH] beaglebone black: limit LDO3 to 1.8V
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-boneblack.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index e88723c..3274dbd 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -26,6 +26,12 @@
+ >;
+ };
+
++&ldo3_reg {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ regulator-always-on;
++};
++
+ &mmc2 {
+ vmmc-supply = <&ldo3_reg>;
+ bus-width = <8>;
diff --git a/patches/linux-3.8.13/0387-beaglebone-black-add-new-fixed-regulator-for-uSD-eMM.patch b/patches/linux-3.8.13/0387-beaglebone-black-add-new-fixed-regulator-for-uSD-eMM.patch
new file mode 100644
index 0000000..289a68a
--- /dev/null
+++ b/patches/linux-3.8.13/0387-beaglebone-black-add-new-fixed-regulator-for-uSD-eMM.patch
@@ -0,0 +1,47 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 1 Apr 2013 09:36:22 +0200
+Subject: [PATCH] beaglebone black: add new fixed regulator for uSD/eMMC
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 8 ++++++++
+ arch/arm/boot/dts/am335x-boneblack.dts | 6 +++++-
+ 2 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 29e72a6..6974fcd 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -314,6 +314,14 @@
+ };
+ };
+ };
++
++ vmmcsd_fixed: fixedregulator@0 {
++ compatible = "regulator-fixed";
++ regulator-name = "vmmcsd_fixed";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ };
++
+ };
+
+ &i2c0 {
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index 3274dbd..5434bfd 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -32,8 +32,12 @@
+ regulator-always-on;
+ };
+
++&mmc1 {
++ vmmc-supply = <&vmmcsd_fixed>;
++};
++
+ &mmc2 {
+- vmmc-supply = <&ldo3_reg>;
++ vmmc-supply = <&vmmcsd_fixed>;
+ bus-width = <8>;
+ ti,non-removable;
+ status = "okay";
diff --git a/patches/linux-3.8.13/0388-capemgr-Implement-disable-overrides-on-the-cmd-line.patch b/patches/linux-3.8.13/0388-capemgr-Implement-disable-overrides-on-the-cmd-line.patch
new file mode 100644
index 0000000..bab309d
--- /dev/null
+++ b/patches/linux-3.8.13/0388-capemgr-Implement-disable-overrides-on-the-cmd-line.patch
@@ -0,0 +1,218 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 1 Apr 2013 18:20:35 +0300
+Subject: [PATCH] capemgr: Implement disable overrides on the cmd line
+
+Allow capes to be disabled on the kernel command line.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 133 +++++++++++++++++++++-----------
+ 1 file changed, 88 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 2ee7b11..5d87088 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -47,7 +47,14 @@
+ /* extra command line overrides */
+ static char *extra_override = NULL;
+ module_param(extra_override, charp, 0444);
+-MODULE_PARM_DESC(extra_override, "Comma delimited list of PART-NUMBER[:REV] overrides");
++MODULE_PARM_DESC(extra_override,
++ "Comma delimited list of PART-NUMBER[:REV] overrides");
++
++/* disabled capes */
++static char *disable_partno = NULL;
++module_param(disable_partno, charp, 0444);
++MODULE_PARM_DESC(disable_partno,
++ "Comma delimited list of PART-NUMBER[:REV] of disabled capes");
+
+ struct bone_capemgr_info;
+
+@@ -547,51 +554,19 @@ slot_fail_check:
+ return 0;
+ }
+
+-/* check an override slot node if it's compatible */
+-static int bone_is_compatible_override(struct device_node *node,
+- const char *compatible_name)
++/* return 0 if not matched,, 1 if matched */
++static int bone_match_cape(const char *match,
++ const char *part_number, const char *version)
+ {
+- struct property *prop;
+- char *buf, *s, *e, *sn;
+- const char *part_number;
+- const char *version;
+ char *tmp_part_number, *tmp_version;
++ char *buf, *s, *e, *sn;
+ int found;
+
+- /* check if the slot is compatible with the board */
+- prop = of_find_property(node, "compatible", NULL);
+-
+- /* no prop, it's something that's compatible with everything */
+- if (prop == NULL)
+- return 1;
+-
+- /* check if it's directly compatible with the baseboard */
+- if (of_multi_prop_cmp(prop, compatible_name) == 0)
+- return 1;
+-
+- /* forced override? */
+- if (of_multi_prop_cmp(prop, "force") == 0)
+- return 1;
+-
+- /* final try, check if it's specified in the kernel command line */
+- if (extra_override == NULL)
+- return 0;
+-
+- /* the compatible name should have kernel-command-line in it */
+- if (of_multi_prop_cmp(prop, "kernel-command-line") != 0)
+- return 0;
+-
+- /* we must have at least the part-name */
+- if (of_property_read_string(node, "part-number",
+- &part_number) != 0)
++ if (match == NULL || part_number == NULL)
+ return 0;
+
+- /* read the version (if it exists) */
+- if (of_property_read_string(node, "version", &version) != 0)
+- version = NULL;
+-
+ /* copy the argument to work on it */
+- buf = kstrdup(extra_override, GFP_KERNEL);
++ buf = kstrdup(match, GFP_KERNEL);
+
+ /* no memory, too bad... */
+ if (buf == NULL)
+@@ -617,12 +592,6 @@ static int bone_is_compatible_override(struct device_node *node,
+ if (strcmp(tmp_part_number, part_number) != 0)
+ continue;
+
+- pr_info("override: part-number='%s' version='%s' "
+- "tmp_version='%s'\n",
+- part_number,
+- version ? version : "N/A",
+- tmp_version ? tmp_version : "N/A");
+-
+ /* if there's no version, match any */
+ if (version == NULL || tmp_version == NULL ||
+ strcmp(version, tmp_version) == 0) {
+@@ -636,6 +605,50 @@ static int bone_is_compatible_override(struct device_node *node,
+ return found;
+ }
+
++/* check an override slot node if it's compatible */
++static int bone_is_compatible_override(struct device_node *node,
++ const char *compatible_name)
++{
++ struct property *prop;
++ const char *part_number;
++ const char *version;
++
++ /* check if the slot is compatible with the board */
++ prop = of_find_property(node, "compatible", NULL);
++
++ /* no prop, it's something that's compatible with everything */
++ if (prop == NULL)
++ return 1;
++
++ /* check if it's directly compatible with the baseboard */
++ if (of_multi_prop_cmp(prop, compatible_name) == 0)
++ return 1;
++
++ /* forced override? */
++ if (of_multi_prop_cmp(prop, "force") == 0)
++ return 1;
++
++ /* final try, check if it's specified in the kernel command line */
++ if (extra_override == NULL)
++ return 0;
++
++ /* the compatible name should have kernel-command-line in it */
++ if (of_multi_prop_cmp(prop, "kernel-command-line") != 0)
++ return 0;
++
++ /* we must have at least the part-name */
++ if (of_property_read_string(node, "part-number",
++ &part_number) != 0)
++ return 0;
++
++ /* read the version (if it exists) */
++ if (of_property_read_string(node, "version", &version) != 0)
++ version = NULL;
++
++ /* match on the extra override */
++ return bone_match_cape(extra_override, part_number, version);
++}
++
+ static int bone_is_compatible_runtime_override(struct device_node *node,
+ const char *req_part_number, const char *req_version)
+ {
+@@ -1045,6 +1058,15 @@ found:
+ part_number, version))
+ continue;
+
++ /* if matches the disabled ones skip */
++ if (bone_match_cape(disable_partno,
++ part_number, NULL)) {
++ dev_info(&pdev->dev,
++ "Skipping disabled cape with "
++ "part# %s\n", part_number);
++ continue;
++ }
++
+ slot = bone_capemgr_add_slot(info, node,
+ part_number, version);
+ if (IS_ERR(slot)) {
+@@ -1522,6 +1544,7 @@ bone_capemgr_add_slot(struct bone_capemgr_info *info, struct device_node *node,
+ slotno);
+ /* but all is fine */
+ } else {
++
+ dev_info(dev, "slot #%d: '%s'\n",
+ slotno, slot->text_id);
+
+@@ -1701,6 +1724,15 @@ bone_capemgr_probe(struct platform_device *pdev)
+ &part_number) != 0)
+ continue;
+
++ /* if matches the disabled ones skip */
++ if (bone_match_cape(disable_partno,
++ part_number, NULL)) {
++ dev_info(&pdev->dev,
++ "Skipping disabled cape with "
++ "part# %s\n", part_number);
++ continue;
++ }
++
+ len = sizeof(*capemap) + strlen(part_number) + 1;
+ capemap = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+ if (capemap == NULL) {
+@@ -1741,6 +1773,7 @@ bone_capemgr_probe(struct platform_device *pdev)
+ ret = PTR_ERR(slot);
+ goto err_exit;
+ }
++ /* note that slot may be NULL (means it was disabled) */
+ }
+ of_node_put(slots_node);
+ }
+@@ -1760,6 +1793,16 @@ bone_capemgr_probe(struct platform_device *pdev)
+ /* now load each (take lock to be sure */
+ mutex_lock(&info->slots_list_mutex);
+ list_for_each_entry(slot, &info->slot_list, node) {
++
++ /* if matches the disabled ones skip */
++ if (bone_match_cape(disable_partno,
++ slot->part_number, NULL)) {
++ dev_info(&pdev->dev,
++ "Skipping loading of disabled cape with "
++ "part# %s\n", slot->part_number);
++ continue;
++ }
++
+ if (!slot->probe_failed && !slot->loaded) {
+ slot->loading = 1;
+ slot->loader_thread = kthread_run(bone_capemgr_loader,
diff --git a/patches/linux-3.8.13/0389-tilcdc-Enable-pinmux-states.patch b/patches/linux-3.8.13/0389-tilcdc-Enable-pinmux-states.patch
new file mode 100644
index 0000000..cc480c7
--- /dev/null
+++ b/patches/linux-3.8.13/0389-tilcdc-Enable-pinmux-states.patch
@@ -0,0 +1,492 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 29 Mar 2013 19:32:29 +0200
+Subject: [PATCH] tilcdc: Enable pinmux states
+
+Things like the boot switch are on the LCD data pins.
+Allows us to change pinmuxing on runtime.
+---
+ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 113 +++++++++++++++++++++++++-
+ drivers/gpu/drm/tilcdc/tilcdc_slave.c | 114 +++++++++++++++++++++++++-
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 115 ++++++++++++++++++++++++++-
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 8 +-
+ 4 files changed, 337 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+index 2496ee4..361c569 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+@@ -31,6 +31,8 @@ struct panel_module {
+ struct display_timings *timings;
+ struct backlight_device *backlight;
+ int gpio;
++ struct pinctrl *pinctrl;
++ char *selected_state_name;
+ };
+ #define to_panel_module(x) container_of(x, struct panel_module, base)
+
+@@ -355,14 +357,83 @@ static struct tilcdc_panel_info * of_get_panel_info(struct device_node *np)
+
+ static struct of_device_id panel_of_match[];
+
++static ssize_t pinmux_show_state(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct panel_module *panel_mod = platform_get_drvdata(pdev);
++ const char *name;
++
++ name = panel_mod->selected_state_name;
++ if (name == NULL || strlen(name) == 0)
++ name = "none";
++ return sprintf(buf, "%s\n", name);
++}
++
++static ssize_t pinmux_store_state(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct panel_module *panel_mod = platform_get_drvdata(pdev);
++ struct pinctrl_state *state;
++ char *state_name;
++ char *s;
++ int err;
++
++ /* duplicate (as a null terminated string) */
++ state_name = kmalloc(count + 1, GFP_KERNEL);
++ if (state_name == NULL)
++ return -ENOMEM;
++ memcpy(state_name, buf, count);
++ state_name[count] = '\0';
++
++ /* and chop off newline */
++ s = strchr(state_name, '\n');
++ if (s != NULL)
++ *s = '\0';
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(panel_mod->pinctrl, state_name);
++ if (!IS_ERR(state)) {
++ err = pinctrl_select_state(panel_mod->pinctrl, state);
++ if (err != 0)
++ dev_err(dev, "Failed to select state %s\n",
++ state_name);
++ } else {
++ dev_err(dev, "Failed to find state %s\n", state_name);
++ err = PTR_RET(state);
++ }
++
++ if (err == 0) {
++ kfree(panel_mod->selected_state_name);
++ panel_mod->selected_state_name = state_name;
++ }
++
++ return err ? err : count;
++}
++
++static DEVICE_ATTR(pinmux_state, S_IWUSR | S_IRUGO,
++ pinmux_show_state, pinmux_store_state);
++
++static struct attribute *pinmux_attributes[] = {
++ &dev_attr_pinmux_state.attr,
++ NULL
++};
++
++static const struct attribute_group pinmux_attr_group = {
++ .attrs = pinmux_attributes,
++};
++
+ static int panel_probe(struct platform_device *pdev)
+ {
++ struct device *dev = &pdev->dev;
+ struct device_node *node = pdev->dev.of_node;
+ struct panel_module *panel_mod;
+ struct tilcdc_module *mod;
+- struct pinctrl *pinctrl;
++ struct pinctrl_state *state;
+ enum of_gpio_flags ofgpioflags;
+ unsigned long gpioflags;
++ char *state_name;
+ int ret = -EINVAL;
+
+ /* bail out early if no DT data: */
+@@ -375,14 +446,48 @@ static int panel_probe(struct platform_device *pdev)
+ if (!panel_mod)
+ return -ENOMEM;
+
++ platform_set_drvdata(pdev, panel_mod);
++
+ mod = &panel_mod->base;
+
+ tilcdc_module_init(mod, "panel", &panel_module_ops);
+
+- pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+- if (IS_ERR(pinctrl))
+- dev_warn(&pdev->dev, "pins are not configured\n");
++ state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
++ GFP_KERNEL);
++ if (state_name == NULL) {
++ dev_err(dev, "Failed to allocate state name\n");
++ ret = -ENOMEM;
++ goto fail;
++ }
++ panel_mod->selected_state_name = state_name;
++ strcpy(panel_mod->selected_state_name, PINCTRL_STATE_DEFAULT);
+
++ panel_mod->pinctrl = devm_pinctrl_get(dev);
++ if (IS_ERR(panel_mod->pinctrl)) {
++ dev_err(dev, "Failed to get pinctrl\n");
++ ret = PTR_RET(panel_mod->pinctrl);
++ goto fail;
++ }
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(panel_mod->pinctrl,
++ panel_mod->selected_state_name);
++ if (!IS_ERR(state)) {
++ ret = pinctrl_select_state(panel_mod->pinctrl, state);
++ if (ret != 0) {
++ dev_err(dev, "Failed to select default state\n");
++ goto fail;
++ }
++ } else {
++ panel_mod->selected_state_name = '\0';
++ }
++
++ /* Register sysfs hooks */
++ ret = sysfs_create_group(&dev->kobj, &pinmux_attr_group);
++ if (ret) {
++ dev_err(dev, "Failed to create sysfs group\n");
++ goto fail;
++ }
+
+ panel_mod->timings = of_get_display_timings(node);
+ if (!panel_mod->timings) {
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+index a2d86ac..17252ef 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+@@ -26,6 +26,8 @@
+ struct slave_module {
+ struct tilcdc_module base;
+ struct i2c_adapter *i2c;
++ struct pinctrl *pinctrl;
++ char *selected_state_name;
+ };
+ #define to_slave_module(x) container_of(x, struct slave_module, base)
+
+@@ -291,14 +293,83 @@ static const struct tilcdc_module_ops slave_module_ops = {
+
+ static struct of_device_id slave_of_match[];
+
++static ssize_t pinmux_show_state(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct slave_module *slave_mod = platform_get_drvdata(pdev);
++ const char *name;
++
++ name = slave_mod->selected_state_name;
++ if (name == NULL || strlen(name) == 0)
++ name = "none";
++ return sprintf(buf, "%s\n", name);
++}
++
++static ssize_t pinmux_store_state(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct slave_module *slave_mod = platform_get_drvdata(pdev);
++ struct pinctrl_state *state;
++ char *state_name;
++ char *s;
++ int err;
++
++ /* duplicate (as a null terminated string) */
++ state_name = kmalloc(count + 1, GFP_KERNEL);
++ if (state_name == NULL)
++ return -ENOMEM;
++ memcpy(state_name, buf, count);
++ state_name[count] = '\0';
++
++ /* and chop off newline */
++ s = strchr(state_name, '\n');
++ if (s != NULL)
++ *s = '\0';
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(slave_mod->pinctrl, state_name);
++ if (!IS_ERR(state)) {
++ err = pinctrl_select_state(slave_mod->pinctrl, state);
++ if (err != 0)
++ dev_err(dev, "Failed to select state %s\n",
++ state_name);
++ } else {
++ dev_err(dev, "Failed to find state %s\n", state_name);
++ err = PTR_RET(state);
++ }
++
++ if (err == 0) {
++ kfree(slave_mod->selected_state_name);
++ slave_mod->selected_state_name = state_name;
++ }
++
++ return err ? err : count;
++}
++
++static DEVICE_ATTR(pinmux_state, S_IWUSR | S_IRUGO,
++ pinmux_show_state, pinmux_store_state);
++
++static struct attribute *pinmux_attributes[] = {
++ &dev_attr_pinmux_state.attr,
++ NULL
++};
++
++static const struct attribute_group pinmux_attr_group = {
++ .attrs = pinmux_attributes,
++};
++
+ static int slave_probe(struct platform_device *pdev)
+ {
++ struct device *dev = &pdev->dev;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *i2c_node;
+ struct slave_module *slave_mod;
+ struct tilcdc_module *mod;
+- struct pinctrl *pinctrl;
++ struct pinctrl_state *state;
+ uint32_t i2c_phandle;
++ char *state_name;
+ int ret = -EINVAL;
+
+ /* bail out early if no DT data: */
+@@ -311,13 +382,48 @@ static int slave_probe(struct platform_device *pdev)
+ if (!slave_mod)
+ return -ENOMEM;
+
++ platform_set_drvdata(pdev, slave_mod);
++
+ mod = &slave_mod->base;
+
+ tilcdc_module_init(mod, "slave", &slave_module_ops);
+
+- pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+- if (IS_ERR(pinctrl))
+- dev_warn(&pdev->dev, "pins are not configured\n");
++ state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
++ GFP_KERNEL);
++ if (state_name == NULL) {
++ dev_err(dev, "Failed to allocate state name\n");
++ ret = -ENOMEM;
++ goto fail;
++ }
++ slave_mod->selected_state_name = state_name;
++ strcpy(slave_mod->selected_state_name, PINCTRL_STATE_DEFAULT);
++
++ slave_mod->pinctrl = devm_pinctrl_get(dev);
++ if (IS_ERR(slave_mod->pinctrl)) {
++ dev_err(dev, "Failed to get pinctrl\n");
++ ret = PTR_RET(slave_mod->pinctrl);
++ goto fail;
++ }
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(slave_mod->pinctrl,
++ slave_mod->selected_state_name);
++ if (!IS_ERR(state)) {
++ ret = pinctrl_select_state(slave_mod->pinctrl, state);
++ if (ret != 0) {
++ dev_err(dev, "Failed to select default state\n");
++ goto fail;
++ }
++ } else {
++ slave_mod->selected_state_name = '\0';
++ }
++
++ /* Register sysfs hooks */
++ ret = sysfs_create_group(&dev->kobj, &pinmux_attr_group);
++ if (ret) {
++ dev_err(dev, "Failed to create sysfs group\n");
++ goto fail;
++ }
+
+ if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
+ dev_err(&pdev->dev, "could not get i2c bus phandle\n");
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+index 6f9d727..9d9796f 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+@@ -29,6 +29,8 @@ struct tfp410_module {
+ struct i2c_adapter *i2c;
+ enum of_gpio_flags ofgpioflags;
+ int gpio;
++ struct pinctrl *pinctrl;
++ char *selected_state_name;
+ };
+ #define to_tfp410_module(x) container_of(x, struct tfp410_module, base)
+
+@@ -328,15 +330,84 @@ static const struct tilcdc_module_ops tfp410_module_ops = {
+
+ static struct of_device_id tfp410_of_match[];
+
++static ssize_t pinmux_show_state(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct tfp410_module *tfp410_mod = platform_get_drvdata(pdev);
++ const char *name;
++
++ name = tfp410_mod->selected_state_name;
++ if (name == NULL || strlen(name) == 0)
++ name = "none";
++ return sprintf(buf, "%s\n", name);
++}
++
++static ssize_t pinmux_store_state(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct tfp410_module *tfp410_mod = platform_get_drvdata(pdev);
++ struct pinctrl_state *state;
++ char *state_name;
++ char *s;
++ int err;
++
++ /* duplicate (as a null terminated string) */
++ state_name = kmalloc(count + 1, GFP_KERNEL);
++ if (state_name == NULL)
++ return -ENOMEM;
++ memcpy(state_name, buf, count);
++ state_name[count] = '\0';
++
++ /* and chop off newline */
++ s = strchr(state_name, '\n');
++ if (s != NULL)
++ *s = '\0';
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(tfp410_mod->pinctrl, state_name);
++ if (!IS_ERR(state)) {
++ err = pinctrl_select_state(tfp410_mod->pinctrl, state);
++ if (err != 0)
++ dev_err(dev, "Failed to select state %s\n",
++ state_name);
++ } else {
++ dev_err(dev, "Failed to find state %s\n", state_name);
++ err = PTR_RET(state);
++ }
++
++ if (err == 0) {
++ kfree(tfp410_mod->selected_state_name);
++ tfp410_mod->selected_state_name = state_name;
++ }
++
++ return err ? err : count;
++}
++
++static DEVICE_ATTR(pinmux_state, S_IWUSR | S_IRUGO,
++ pinmux_show_state, pinmux_store_state);
++
++static struct attribute *pinmux_attributes[] = {
++ &dev_attr_pinmux_state.attr,
++ NULL
++};
++
++static const struct attribute_group pinmux_attr_group = {
++ .attrs = pinmux_attributes,
++};
++
+ static int tfp410_probe(struct platform_device *pdev)
+ {
++ struct device *dev = &pdev->dev;
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *i2c_node;
+ struct tfp410_module *tfp410_mod;
+ struct tilcdc_module *mod;
+- struct pinctrl *pinctrl;
++ struct pinctrl_state *state;
+ uint32_t i2c_phandle;
+ unsigned long gpioflags;
++ char *state_name;
+ int ret = -EINVAL;
+
+ /* bail out early if no DT data: */
+@@ -349,13 +420,49 @@ static int tfp410_probe(struct platform_device *pdev)
+ if (!tfp410_mod)
+ return -ENOMEM;
+
++ platform_set_drvdata(pdev, tfp410_mod);
++
+ mod = &tfp410_mod->base;
+
+ tilcdc_module_init(mod, "tfp410", &tfp410_module_ops);
+
+- pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+- if (IS_ERR(pinctrl))
+- dev_warn(&pdev->dev, "pins are not configured\n");
++ state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
++ GFP_KERNEL);
++ if (state_name == NULL) {
++ dev_err(dev, "Failed to allocate state name\n");
++ ret = -ENOMEM;
++ goto fail;
++ }
++ tfp410_mod->selected_state_name = state_name;
++ strcpy(tfp410_mod->selected_state_name, PINCTRL_STATE_DEFAULT);
++
++ tfp410_mod->pinctrl = devm_pinctrl_get(dev);
++ if (IS_ERR(tfp410_mod->pinctrl)) {
++ dev_err(dev, "Failed to get pinctrl\n");
++ ret = PTR_RET(tfp410_mod->pinctrl);
++ goto fail;
++ }
++
++ /* try to select default state at first (if it exists) */
++ state = pinctrl_lookup_state(tfp410_mod->pinctrl,
++ tfp410_mod->selected_state_name);
++ if (!IS_ERR(state)) {
++ ret = pinctrl_select_state(tfp410_mod->pinctrl, state);
++ if (ret != 0) {
++ dev_err(dev, "Failed to select default state\n");
++ goto fail;
++ }
++ } else {
++ tfp410_mod->selected_state_name = '\0';
++ }
++
++ /* Register sysfs hooks */
++ ret = sysfs_create_group(&dev->kobj, &pinmux_attr_group);
++ if (ret) {
++ dev_err(dev, "Failed to create sysfs group\n");
++ goto fail;
++ }
++
+
+ if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
+ dev_err(&pdev->dev, "could not get i2c bus phandle\n");
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index 02bcb93..ee36d0e 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -41,6 +41,11 @@
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ >;
+ };
++ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
++ pinctrl-single,pins = <
++ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
++ >;
++ };
+ };
+ };
+
+@@ -55,8 +60,9 @@
+ hdmi {
+ compatible = "tilcdc,slave";
+ i2c = <&i2c0>;
+- pinctrl-names = "default";
++ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
++ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+ };
+
+ fb {
diff --git a/patches/linux-3.8.13/0390-cape-Add-a-simple-cape-for-handling-the-uSD-button.patch b/patches/linux-3.8.13/0390-cape-Add-a-simple-cape-for-handling-the-uSD-button.patch
new file mode 100644
index 0000000..f7cd84c
--- /dev/null
+++ b/patches/linux-3.8.13/0390-cape-Add-a-simple-cape-for-handling-the-uSD-button.patch
@@ -0,0 +1,84 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 29 Mar 2013 17:44:02 +0200
+Subject: [PATCH] cape: Add a simple cape for handling the uSD button.
+
+Doesn't work ofcourse due to conflict with the HDMI.
+
+Conflicts:
+ firmware/Makefile
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/BB-BONELT-BT-00A0.dts | 50 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 52 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONELT-BT-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 36a0dbb..f9f0294 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -153,7 +153,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo \
+ cape-bone-exptest-00A0.dtbo \
+- cape-bone-mrf24j40-00A0.dtbo
++ cape-bone-mrf24j40-00A0.dtbo \
++ BB-BONELT-BT-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONELT-BT-00A0.dts b/firmware/capes/BB-BONELT-BT-00A0.dts
+new file mode 100644
+index 0000000..f32d6f5
+--- /dev/null
++++ b/firmware/capes/BB-BONELT-BT-00A0.dts
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONELT-BT";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_bt_cape_key_pins: pinmux_bone_bt_cape_key_pins {
++ pinctrl-single,pins = <
++ 0x0a8 0x27 /* P8.43 lcd_data2.gpio2[8] */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ bt_gpio_key {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_bt_cape_key_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ button@1 {
++ debounce_interval = <1>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio3 8 0x0>;
++ };
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0391-beaglebone-add-support-for-DVI-00A3.patch b/patches/linux-3.8.13/0391-beaglebone-add-support-for-DVI-00A3.patch
new file mode 100644
index 0000000..82d55d9
--- /dev/null
+++ b/patches/linux-3.8.13/0391-beaglebone-add-support-for-DVI-00A3.patch
@@ -0,0 +1,42 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 3 Apr 2013 15:39:38 +0200
+Subject: [PATCH] beaglebone: add support for DVI 00A3
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 8 ++++++++
+ firmware/capes/cape-bone-dvi-00A2.dts | 2 +-
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 6974fcd..524bf03 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -221,6 +221,14 @@
+ version = "00A1", "01";
+ dtbo = "cape-bone-dvi-00A1.dtbo";
+ };
++ version@00A2 {
++ version = "00A2", "A2";
++ dtbo = "cape-bone-dvi-00A2.dtbo";
++ };
++ version@00A3 {
++ version = "00A3";
++ dtbo = "cape-bone-dvi-00A2.dtbo";
++ };
+ };
+
+ /* beaglebone black emmc on board */
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+index fb2dcf0..34ced98 100644
+--- a/firmware/capes/cape-bone-dvi-00A2.dts
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -13,7 +13,7 @@
+
+ /* identification */
+ part-number = "BB-BONE-DVID-01";
+- version = "00A2", "A2";
++ version = "00A3", "00A2", "A2";
+
+ fragment@0 {
+ target = <&am33xx_pinmux>;
diff --git a/patches/linux-3.8.13/0392-beaglebone-remove-audio-section-from-DVID-rev-2-and-.patch b/patches/linux-3.8.13/0392-beaglebone-remove-audio-section-from-DVID-rev-2-and-.patch
new file mode 100644
index 0000000..faf35ed
--- /dev/null
+++ b/patches/linux-3.8.13/0392-beaglebone-remove-audio-section-from-DVID-rev-2-and-.patch
@@ -0,0 +1,90 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 3 Apr 2013 15:59:07 +0200
+Subject: [PATCH] beaglebone: remove audio section from DVID rev 2 and 3 capes
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/cape-bone-dvi-00A2.dts | 65 ---------------------------------
+ 1 file changed, 65 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+index 34ced98..a3cd39d 100644
+--- a/firmware/capes/cape-bone-dvi-00A2.dts
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -52,16 +52,6 @@
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+ >;
+ };
+-
+- bone_dvi_cape_audio_pins: pinmux_bone_dvi_cape_audio_pins {
+- pinctrl-single,pins = <
+- 0x190 0x20 /* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
+- 0x194 0x20 /* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
+- 0x19c 0x22 /* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
+- 0x1ac 0x22 /* mcasp0_ahclkx.mcasp0_axr3, INPUT | MODE2 */
+-
+- >;
+- };
+ };
+ };
+
+@@ -112,59 +102,4 @@
+
+ };
+ };
+-
+- fragment@2 {
+- target = <&i2c2>;
+- __overlay__ {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- tlv320aic3x: tlv320aic3x@1b {
+- compatible = "ti,tlv320aic3x";
+- reg = <0x1b>;
+- status = "okay";
+- };
+- };
+- };
+-
+- fragment@3 {
+- target = <&mcasp0>;
+- __overlay__ {
+- pinctrl-names = "default";
+- pinctrl-0 = <&bone_dvi_cape_audio_pins>;
+-
+- status = "okay";
+-
+- op-mode = <0>; /* MCASP_IIS_MODE */
+- tdm-slots = <2>;
+- num-serializer = <16>;
+- serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
+- 0 0 2 1
+- 0 0 0 0
+- 0 0 0 0
+- 0 0 0 0
+- >;
+- tx-num-evt = <1>;
+- rx-num-evt = <1>;
+- };
+- };
+-
+- fragment@4 {
+- target = <&ocp>;
+- __overlay__ {
+- sound {
+- compatible = "ti,da830-evm-audio";
+- ti,model = "DA830 EVM";
+- ti,audio-codec = <&tlv320aic3x>;
+- ti,mcasp-controller = <&mcasp0>;
+- ti,codec-clock-rate = <12000000>;
+- ti,audio-routing =
+- "Headphone Jack", "HPLOUT",
+- "Headphone Jack", "HPROUT",
+- "LINE1L", "Line In",
+- "LINE1R", "Line In";
+- };
+- };
+-
+- };
+ };
diff --git a/patches/linux-3.8.13/0393-beaglebone-add-dts-for-audio-cape.patch b/patches/linux-3.8.13/0393-beaglebone-add-dts-for-audio-cape.patch
new file mode 100644
index 0000000..a5d1324
--- /dev/null
+++ b/patches/linux-3.8.13/0393-beaglebone-add-dts-for-audio-cape.patch
@@ -0,0 +1,154 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 4 Apr 2013 10:24:06 +0200
+Subject: [PATCH] beaglebone: add dts for audio cape
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/BB-BONE-AUDI-01-00A0.dts | 125 +++++++++++++++++++++++++++++++
+ 2 files changed, 126 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-AUDI-01-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index f9f0294..d4403b5 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -147,6 +147,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-hexy-00A0.dtbo \
+ cape-bone-lcd3-00A0.dtbo \
+ cape-bone-lcd3-00A2.dtbo \
++ BB-BONE-AUDI-01-00A0.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
+ BB-BONE-LCD7-01-00A4.dtbo \
+ BB-BONE-eMMC1-01-00A0.dtbo \
+diff --git a/firmware/capes/BB-BONE-AUDI-01-00A0.dts b/firmware/capes/BB-BONE-AUDI-01-00A0.dts
+new file mode 100644
+index 0000000..8e1256e
+--- /dev/null
++++ b/firmware/capes/BB-BONE-AUDI-01-00A0.dts
+@@ -0,0 +1,125 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-AUDI-01";
++ version = "00A0", "A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_audio_cape_led_pins: pinmux_bone_audio_cape_led_pins {
++ pinctrl-single,pins = <
++ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
++ 0x4c 0x07 /* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_audio_cape_audio_pins: pinmux_bone_audio_cape_audio_pins {
++ pinctrl-single,pins = <
++ 0x190 0x20 /* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
++ 0x194 0x20 /* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
++ 0x19c 0x22 /* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
++ 0x1ac 0x22 /* mcasp0_ahclkx.mcasp0_axr3, INPUT | MODE2 */
++
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ gpio-leds-cape-audio {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_audio_cape_led_pins>;
++
++ audio-led0 {
++ label = "audio:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ audio-led1 {
++ label = "audio:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "mmc0";
++ default-state = "off";
++ };
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&i2c2>;
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ tlv320aic3x: tlv320aic3x@1b {
++ compatible = "ti,tlv320aic3x";
++ reg = <0x1b>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&mcasp0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_audio_cape_audio_pins>;
++
++ status = "okay";
++
++ op-mode = <0>; /* MCASP_IIS_MODE */
++ tdm-slots = <2>;
++ num-serializer = <16>;
++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
++ 0 0 2 1
++ 0 0 0 0
++ 0 0 0 0
++ 0 0 0 0
++ >;
++ tx-num-evt = <1>;
++ rx-num-evt = <1>;
++ };
++ };
++
++ fragment@4 {
++ target = <&ocp>;
++ __overlay__ {
++ sound {
++ compatible = "ti,da830-evm-audio";
++ ti,model = "DA830 EVM";
++ ti,audio-codec = <&tlv320aic3x>;
++ ti,mcasp-controller = <&mcasp0>;
++ ti,codec-clock-rate = <12000000>;
++ ti,audio-routing =
++ "Headphone Jack", "HPLOUT",
++ "Headphone Jack", "HPROUT",
++ "LINE1L", "Line In",
++ "LINE1R", "Line In";
++ };
++ };
++
++ };
++};
diff --git a/patches/linux-3.8.13/0394-cape-bone-hexy-add-iio-helper.patch b/patches/linux-3.8.13/0394-cape-bone-hexy-add-iio-helper.patch
new file mode 100644
index 0000000..1f66241
--- /dev/null
+++ b/patches/linux-3.8.13/0394-cape-bone-hexy-add-iio-helper.patch
@@ -0,0 +1,48 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 5 Apr 2013 12:07:30 +0200
+Subject: [PATCH] cape-bone-hexy: add iio helper
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/cape-bone-hexy-00A0.dts | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/firmware/capes/cape-bone-hexy-00A0.dts b/firmware/capes/cape-bone-hexy-00A0.dts
+index abc1255..0e90904 100644
+--- a/firmware/capes/cape-bone-hexy-00A0.dts
++++ b/firmware/capes/cape-bone-hexy-00A0.dts
+@@ -157,4 +157,34 @@
+ };
+ };
+ };
++
++ fragment@6 {
++ target = <&ocp>;
++ __overlay__ {
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ adc {
++ ti,adc-channels = <0 1 2 3 4 5 6 7>;
++ };
++ };
++
++ test_helper: helper {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ vsense-scale = <100 100 100 100 100 100 100 100>;
++ status = "okay";
++ };
++ };
++ };
+ };
diff --git a/patches/linux-3.8.13/0395-cape-Add-CAPE-BONE-EXPTEST-to-capemaps.patch b/patches/linux-3.8.13/0395-cape-Add-CAPE-BONE-EXPTEST-to-capemaps.patch
new file mode 100644
index 0000000..77e9d86
--- /dev/null
+++ b/patches/linux-3.8.13/0395-cape-Add-CAPE-BONE-EXPTEST-to-capemaps.patch
@@ -0,0 +1,27 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 5 Apr 2013 14:34:31 +0300
+Subject: [PATCH] cape: Add CAPE-BONE-EXPTEST to capemaps
+
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 524bf03..1c91d7d 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -320,6 +320,14 @@
+ dtbo = "cape-bone-mrf24j40-00A0.dtbo";
+ };
+ };
++ /* expansion test */
++ cape@11 {
++ part-number = "BB-BONE-EXPTEST";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-exptest-00A0.dtbo";
++ };
++ };
+ };
+ };
+
diff --git a/patches/linux-3.8.13/0396-tester-button-cape.patch b/patches/linux-3.8.13/0396-tester-button-cape.patch
new file mode 100644
index 0000000..1b381d9
--- /dev/null
+++ b/patches/linux-3.8.13/0396-tester-button-cape.patch
@@ -0,0 +1,31 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 8 Apr 2013 22:35:55 +0300
+Subject: [PATCH] tester: button cape
+
+Disable pull up on the pinmux.
+---
+ firmware/capes/BB-BONELT-BT-00A0.dts | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/firmware/capes/BB-BONELT-BT-00A0.dts b/firmware/capes/BB-BONELT-BT-00A0.dts
+index f32d6f5..94b9a12 100644
+--- a/firmware/capes/BB-BONELT-BT-00A0.dts
++++ b/firmware/capes/BB-BONELT-BT-00A0.dts
+@@ -21,7 +21,7 @@
+
+ bone_bt_cape_key_pins: pinmux_bone_bt_cape_key_pins {
+ pinctrl-single,pins = <
+- 0x0a8 0x27 /* P8.43 lcd_data2.gpio2[8] */
++ 0x0a8 0x2f /* P8.43 lcd_data2.gpio2[8] DISABLE internal pullup */
+ >;
+ };
+ };
+@@ -39,7 +39,7 @@
+ #size-cells = <0>;
+
+ button@1 {
+- debounce_interval = <1>;
++ debounce_interval = <0>;
+ linux,code = <28>;
+ label = "enter";
+ gpios = <&gpio3 8 0x0>;
diff --git a/patches/linux-3.8.13/0397-pwm_test-fix-some-issues.patch b/patches/linux-3.8.13/0397-pwm_test-fix-some-issues.patch
new file mode 100644
index 0000000..3ffb8ae
--- /dev/null
+++ b/patches/linux-3.8.13/0397-pwm_test-fix-some-issues.patch
@@ -0,0 +1,89 @@
+From: Jack Mitchell <jack@embed.me.uk>
+Date: Tue, 9 Apr 2013 16:47:31 +0200
+Subject: [PATCH] pwm_test: fix some issues
+
+---
+ drivers/pwm/pwm_test.c | 39 ++++++++++++++++++++++++++++++---------
+ 1 file changed, 30 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c
+index d9948db..3da1890 100644
+--- a/drivers/pwm/pwm_test.c
++++ b/drivers/pwm/pwm_test.c
+@@ -91,6 +91,11 @@ static ssize_t pwm_test_store_config(struct device *dev,
+ struct pwm_test *pwm_test = dev_get_drvdata(dev);
+ int ret;
+
++ if (pwm_test->pwm == NULL) {
++ pr_err("PWM Device has not been requested\n");
++ return -ENODEV;
++ }
++
+ if (pwm_test->duty_s == 0) {
+ ret = pwm_config(pwm_test->pwm, 0, pwm_test->period_s);
+ if (ret) {
+@@ -199,6 +204,12 @@ static ssize_t pwm_test_store_request(struct device *dev,
+ return rc;
+
+ if (pwm_test->requested_s) {
++
++ if (pwm_test->pwm) {
++ pr_info("PWM already requested!\n");
++ return count;
++ }
++
+ pwm_test->pwm = pwm_get(dev, NULL);
+
+ if (IS_ERR(pwm_test->pwm)) {
+@@ -206,9 +217,9 @@ static ssize_t pwm_test_store_request(struct device *dev,
+ PTR_ERR(pwm_test->pwm));
+ rc = -EINVAL;
+ }
+- } else {
+- pwm_free(pwm_test->pwm);
+- pwm_test->polarity = 0;
++ } else if (pwm_test->pwm != NULL) {
++
++ pwm_test->polarity = 0;
+ pwm_test->run = 0;
+ pwm_test->duty = 0;
+ pwm_test->period = 0;
+@@ -218,8 +229,18 @@ static ssize_t pwm_test_store_request(struct device *dev,
+ pwm_test->duty_s = 0;
+ pwm_test->period_s = 0;
+ pwm_test->config_s = 0;
++
++ pwm_config(pwm_test->pwm, pwm_test->duty_s,
++ pwm_test->period_s);
++
++ pwm_disable(pwm_test->pwm);
++
+ rc = 0;
+ }
++ else {
++ pr_info("PWM was already unrequested\n");
++ }
++
+
+ if (rc) {
+ pr_err("operation failed %d\n", rc);
+@@ -231,13 +252,13 @@ static ssize_t pwm_test_store_request(struct device *dev,
+ 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,
++static DEVICE_ATTR(duty, S_IRUSR | S_IWUSR, pwm_test_show_duty, pwm_test_store_duty);
++static DEVICE_ATTR(period, S_IRUSR | S_IWUSR, pwm_test_show_period, pwm_test_store_period);
++static DEVICE_ATTR(polarity, S_IRUSR | S_IWUSR, 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 DEVICE_ATTR(config, S_IRUSR | S_IWUSR , pwm_test_show_config, pwm_test_store_config);
++static DEVICE_ATTR(run, S_IRUSR | S_IWUSR , pwm_test_show_run, pwm_test_store_run);
++static DEVICE_ATTR(request, S_IRUSR | S_IWUSR , pwm_test_show_request, pwm_test_store_request);
+
+ static const struct attribute *pwm_attrs[] = {
+ &dev_attr_duty.attr,
diff --git a/patches/linux-3.8.13/0398-pwm_test-Clean-up-and-make-it-work-on-DT-correctly.patch b/patches/linux-3.8.13/0398-pwm_test-Clean-up-and-make-it-work-on-DT-correctly.patch
new file mode 100644
index 0000000..336826c
--- /dev/null
+++ b/patches/linux-3.8.13/0398-pwm_test-Clean-up-and-make-it-work-on-DT-correctly.patch
@@ -0,0 +1,467 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 9 Apr 2013 22:14:29 +0300
+Subject: [PATCH] pwm_test: Clean-up and make it work on DT correctly
+
+Clean up and DTify the pwm_test driver into something that's reasonably
+useful.
+Based on work done by Elias & Jack Mitchel.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/pwm/pwm_test.c | 312 ++++++++++++++++++++++++------------------------
+ 1 file changed, 155 insertions(+), 157 deletions(-)
+
+diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c
+index 3da1890..9c07880 100644
+--- a/drivers/pwm/pwm_test.c
++++ b/drivers/pwm/pwm_test.c
+@@ -26,21 +26,23 @@
+ #include <linux/err.h>
+ #include <linux/clk.h>
+ #include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.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;
++ int period;
++ int duty;
++ enum pwm_polarity polarity;
++ int run;
+ };
+
+ 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);
++
++ return sprintf(buf, "%d\n", pwm_test->duty);
+ }
+
+ static ssize_t pwm_test_store_duty(struct device *dev,
+@@ -48,10 +50,23 @@ static ssize_t pwm_test_store_duty(struct device *dev,
+ {
+ int rc;
+ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ int duty;
+
+- rc = kstrtoul(buf, 0, &pwm_test->duty_s);
++ rc = kstrtoint(buf, 0, &duty);
+ if (rc)
+ return rc;
++
++ if (duty < 0)
++ return -EINVAL;
++
++ rc = pwm_config(pwm_test->pwm, duty, pwm_test->period);
++ if (rc) {
++ dev_err(dev, "pwm_config() failed\n");
++ return rc;
++ }
++
++ pwm_test->duty = duty;
++
+ return count;
+ }
+
+@@ -60,7 +75,7 @@ static ssize_t pwm_test_show_period(struct device *dev,
+ {
+ struct pwm_test *pwm_test = dev_get_drvdata(dev);
+
+- return sprintf(buf, "%lu\n", pwm_test->period);
++ return sprintf(buf, "%d\n", pwm_test->period);
+ }
+
+ static ssize_t pwm_test_store_period(struct device *dev,
+@@ -68,60 +83,27 @@ static ssize_t pwm_test_store_period(struct device *dev,
+ {
+ int rc;
+ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ int period;
+
+- rc = kstrtoul(buf, 0, &pwm_test->period_s);
++ rc = kstrtoint(buf, 0, &period);
+ if (rc)
+ return rc;
+
+- return count;
+-}
++ if (period < 0)
++ return -EINVAL;
+
+-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->pwm == NULL) {
+- pr_err("PWM Device has not been requested\n");
+- return -ENODEV;
+- }
+-
+- 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;
++ /* same period? just return */
++ if (pwm_test->period == period)
++ return count;
++
++ rc = pwm_config(pwm_test->pwm, pwm_test->duty, period);
++ if (rc) {
++ dev_err(dev, "pwm_config() failed\n");
++ return rc;
+ }
++
++ pwm_test->period = period;
++
+ return count;
+ }
+
+@@ -129,7 +111,8 @@ 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");
++
++ return sprintf(buf, "%d\n", pwm_test->run);
+ }
+
+ static ssize_t pwm_test_store_run(struct device *dev,
+@@ -137,23 +120,31 @@ static ssize_t pwm_test_store_run(struct device *dev,
+ {
+ int rc;
+ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ int run;
+
+- rc = kstrtoul(buf, 0, &pwm_test->run_s);
++ rc = kstrtoint(buf, 0, &run);
+ if (rc)
+ return rc;
+
+- if (pwm_test->run_s)
++ /* only 0 & 1 allowed */
++ if (run != 0 && run != 1)
++ return -EINVAL;
++
++ /* same state, don't bother */
++ if (run == pwm_test->run)
++ return count;
++
++ if (run) {
+ rc = pwm_enable(pwm_test->pwm);
+- else
++ if (rc != 0) {
++ dev_err(dev, "pwm_enable failed\n");
++ return rc;
++ }
++ } 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 = run;
+
+- pwm_test->run = pwm_test->run_s;
+ return count;
+ }
+
+@@ -161,9 +152,8 @@ 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");
++
++ return sprintf(buf, "%u\n", pwm_test->polarity);
+ }
+
+ static ssize_t pwm_test_store_polarity(struct device *dev,
+@@ -171,84 +161,40 @@ static ssize_t pwm_test_store_polarity(struct device *dev,
+ {
+ int rc;
+ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ int val;
++ enum pwm_polarity polarity;
+
+- rc = kstrtoul(buf, 0, &pwm_test->polarity_s);
++ rc = kstrtoint(buf, 0, &val);
+ 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;
+- }
++ /* only zero and one allowed */
++ if (val != 0 && val != 1)
++ return -EINVAL;
+
+- pwm_test->polarity = pwm_test->polarity_s;
+- return count;
+-}
++ polarity = val ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
+
+-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");
+-}
++ /* same? don't do anything */
++ if (polarity == pwm_test->polarity)
++ return count;
+
+-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);
++ /* polarity can only change when we stop the pwm */
++ if (pwm_test->run)
++ pwm_disable(pwm_test->pwm);
+
+- rc = kstrtoul(buf, 0, &pwm_test->requested_s);
+- if (rc)
++ rc = pwm_set_polarity(pwm_test->pwm, polarity);
++ if (rc) {
++ dev_err(dev, "pwm_set_polarity failed\n");
++ if (pwm_test->run)
++ pwm_enable(pwm_test->pwm);
+ return rc;
+-
+- if (pwm_test->requested_s) {
+-
+- if (pwm_test->pwm) {
+- pr_info("PWM already requested!\n");
+- return count;
+- }
+-
+- 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 if (pwm_test->pwm != NULL) {
+-
+- 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;
+-
+- pwm_config(pwm_test->pwm, pwm_test->duty_s,
+- pwm_test->period_s);
+-
+- pwm_disable(pwm_test->pwm);
+-
+- rc = 0;
+ }
+- else {
+- pr_info("PWM was already unrequested\n");
+- }
+
++ if (pwm_test->run)
++ pwm_enable(pwm_test->pwm);
+
+- if (rc) {
+- pr_err("operation failed %d\n", rc);
+- pwm_test->requested_s = pwm_test->requested;
+- return rc;
+- }
++ pwm_test->polarity = polarity;
+
+- pwm_test->requested = pwm_test->requested_s;
+ return count;
+ }
+
+@@ -256,16 +202,12 @@ static DEVICE_ATTR(duty, S_IRUSR | S_IWUSR, pwm_test_show_duty, pwm_test_store_d
+ static DEVICE_ATTR(period, S_IRUSR | S_IWUSR, pwm_test_show_period, pwm_test_store_period);
+ static DEVICE_ATTR(polarity, S_IRUSR | S_IWUSR, pwm_test_show_polarity,
+ pwm_test_store_polarity);
+-static DEVICE_ATTR(config, S_IRUSR | S_IWUSR , pwm_test_show_config, pwm_test_store_config);
+ static DEVICE_ATTR(run, S_IRUSR | S_IWUSR , pwm_test_show_run, pwm_test_store_run);
+-static DEVICE_ATTR(request, S_IRUSR | S_IWUSR , 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,
+ };
+@@ -274,30 +216,89 @@ 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 device *dev = &pdev->dev;
++ struct device_node *node = dev->of_node;
+ struct pwm_test *pwm_test;
++ struct of_phandle_args args;
++ struct pinctrl *pinctrl;
++ u32 val;
++ int rc;
+
+- pwm_test = devm_kzalloc(&pdev->dev, sizeof(*pwm_test), GFP_KERNEL);
++ if (node == NULL) {
++ dev_err(dev, "Non DT platforms not supported\n");
++ return -EINVAL;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "Unable to select pin group\n");
+
++ pwm_test = devm_kzalloc(&pdev->dev, sizeof(*pwm_test), GFP_KERNEL);
+ if (!pwm_test) {
+ dev_err(&pdev->dev, "memory error\n");
+ return -ENOMEM;
+ }
++ platform_set_drvdata(pdev, pwm_test);
+
+- if (pwm_test_class_init(&pdev->dev)) {
+- dev_err(&pdev->dev, "sysfs creation failed\n");
+- return -EINVAL;
++ /* now do the probe time config */
++ pwm_test->pwm = devm_pwm_get(&pdev->dev, NULL);
++ if (IS_ERR(pwm_test->pwm)) {
++ dev_err(dev, "unable to request PWM\n");
++ return PTR_ERR(pwm_test->pwm);
+ }
+- dev_set_drvdata(&pdev->dev, pwm_test);
+- platform_set_drvdata(pdev, pwm_test);
++
++ rc = of_parse_phandle_with_args(node, "pwms", "#pwm-cells", 0, &args);
++ if (rc != 0) {
++ dev_err(dev, "of_parse_phandle_with_args() failed\n");
++ return rc;
++ }
++
++ /* read the period */
++ pwm_test->period = args.args[1];
++
++ /* should be at least 2, but 3 is possible to store polarity */
++ pwm_test->polarity = PWM_POLARITY_NORMAL;
++ /* PWM_SPEC_POLARITY is (1 << 0) */
++ if (args.args_count >= 3 && (args.args[2] & (1 << 0)) != 0)
++ pwm_test->polarity = PWM_POLARITY_INVERSED;
++
++ /* Determine the duty from the device tree */
++ rc = of_property_read_u32(node, "duty", &val);
++ if (rc != 0)
++ val = 0; /* default is 0 */
++ pwm_test->duty = val;
++
++ /* polarity is already set */
++ rc = pwm_config(pwm_test->pwm, pwm_test->duty, pwm_test->period);
++ if (rc) {
++ dev_err(dev, "pwm_config() failed\n");
++ return rc;
++ }
++
++ /* Determine running or not from the device tree */
++ rc = of_property_read_u32(node, "enabled", &val);
++ if (rc < 0)
++ val = 0; /* default is disabled */
++
++ /* single bit */
++ pwm_test->run = !!val;
++
++ if (pwm_test->run) {
++ rc = pwm_enable(pwm_test->pwm);
++ if (rc < 0) {
++ dev_err(dev, "pwm_enable failed\n");
++ return rc;
++ }
++ }
++
++ rc = sysfs_create_group(&dev->kobj, &pwm_device_attr_group);
++ if (rc != 0) {
++ dev_err(dev, "Unable to create sysfs entries\n");
++ return rc;
++ }
++
+ return 0;
+ }
+
+@@ -305,17 +306,14 @@ static int pwm_test_remove(struct platform_device *pdev)
+ {
+ struct pwm_test *pwm_test = platform_get_drvdata(pdev);
+
+- if (!pwm_test->ret) {
++ sysfs_remove_group(&pdev->dev.kobj, &pwm_device_attr_group);
++
++ if (pwm_test->run) {
+ 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);
++ devm_pwm_put(&pdev->dev, pwm_test->pwm);
+ return 0;
+ }
+
diff --git a/patches/linux-3.8.13/0399-capes-Add-PWM-test-example-cape.patch b/patches/linux-3.8.13/0399-capes-Add-PWM-test-example-cape.patch
new file mode 100644
index 0000000..e23dbae
--- /dev/null
+++ b/patches/linux-3.8.13/0399-capes-Add-PWM-test-example-cape.patch
@@ -0,0 +1,89 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 9 Apr 2013 22:52:14 +0300
+Subject: [PATCH] capes: Add PWM test example cape
+
+A simple example of a PWM test based cape.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/BB-BONE-PWMT-00A0.dts | 56 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 58 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-PWMT-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index d4403b5..098b4b4 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -155,7 +155,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-pinmux-test-00A0.dtbo \
+ cape-bone-exptest-00A0.dtbo \
+ cape-bone-mrf24j40-00A0.dtbo \
+- BB-BONELT-BT-00A0.dtbo
++ BB-BONELT-BT-00A0.dtbo \
++ BB-BONE-PWMT-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-PWMT-00A0.dts b/firmware/capes/BB-BONE-PWMT-00A0.dts
+new file mode 100644
+index 0000000..fb2b8b1
+--- /dev/null
++++ b/firmware/capes/BB-BONE-PWMT-00A0.dts
+@@ -0,0 +1,56 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-PWMT";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_test_pins: pinmux_pwm_test_pins {
++ pinctrl-single,pins = <0x150 0x3>; /* spi0_sclk = ehrpwm0A = P9_14 = Heater_HBP | MODE 3 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&epwmss0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_test_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm0 0 500000 1>;
++ pwm-names = "PWM0";
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0400-Sync-tester-DTS-with-am335x-common.patch b/patches/linux-3.8.13/0400-Sync-tester-DTS-with-am335x-common.patch
new file mode 100644
index 0000000..5aad332
--- /dev/null
+++ b/patches/linux-3.8.13/0400-Sync-tester-DTS-with-am335x-common.patch
@@ -0,0 +1,134 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Apr 2013 19:37:08 +0300
+Subject: [PATCH] Sync tester DTS with am335x-common
+
+---
+ arch/arm/boot/dts/am335x-tester.dts | 87 ++++++++++++++++++++++++++++++++---
+ 1 file changed, 80 insertions(+), 7 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-tester.dts b/arch/arm/boot/dts/am335x-tester.dts
+index 1fdba03..5059988 100644
+--- a/arch/arm/boot/dts/am335x-tester.dts
++++ b/arch/arm/boot/dts/am335x-tester.dts
+@@ -177,15 +177,43 @@
+ part-number = "BB-BONE-NIXIE";
+ };
+
+- /* geiger cape version A0 without an EEPROM */
++ /* adafruit 1.8" TFT prototype cape */
+ slot@8 {
+ ti,cape-override;
+ compatible = "kernel-command-line", "runtime";
+- board-name = "Bone-Tester";
++ board-name = "Bone-TFT";
++ version = "00A0";
++ manufacturer = "Adafruit";
++ part-number = "BB-BONE-TFT-01";
++ };
++
++ /* adafruit RTC DS1307 prototype cape */
++ slot@9 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-RTC";
+ version = "00A0";
+- part-number = "BB-BONE-TESTER";
++ manufacturer = "Adafruit";
++ part-number = "BB-BONE-RTC-01";
+ };
+
++ slot@10 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-Hexy";
++ version = "00A0";
++ manufacturer = "Koen Kooi";
++ part-number = "BB-BONE-HEXY-01";
++ };
++ /* MRF24J40 Cape Override */
++ slot@11 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "Bone-MRF24J40";
++ version = "00A0";
++ manufacturer = "Signal 11 Software";
++ part-number = "BB-BONE-MRF24J40";
++ };
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -202,6 +230,14 @@
+ version = "00A1", "01";
+ dtbo = "cape-bone-dvi-00A1.dtbo";
+ };
++ version@00A2 {
++ version = "00A2", "A2";
++ dtbo = "cape-bone-dvi-00A2.dtbo";
++ };
++ version@00A3 {
++ version = "00A3";
++ dtbo = "cape-bone-dvi-00A2.dtbo";
++ };
+ };
+
+ /* beaglebone black emmc on board */
+@@ -262,18 +298,55 @@
+ dtbo = "cape-bone-nixie-00A0.dtbo";
+ };
+ };
+-
+- /* tester */
+ cape@7 {
+- part-number = "BB-BONE-TESTER";
++ part-number = "BB-BONE-TFT-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-adafruit-lcd-00A0.dtbo";
++ };
++ };
++
++ cape@8 {
++ part-number = "BB-BONE-RTC-01";
+ version@00A0 {
+ version = "00A0";
+- dtbo = "cape-bone-tester-00A0.dtbo";
++ dtbo = "cape-bone-adafruit-rtc-00A0.dtbo";
+ };
+ };
+
++ cape@9 {
++ part-number = "BB-BONE-HEXY-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-hexy-00A0.dtbo";
++ };
++ };
++ /* mrf24j40 cape */
++ cape@10 {
++ part-number = "BB-BONE-MRF24J40";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-mrf24j40-00A0.dtbo";
++ };
++ };
++ /* expansion test */
++ cape@11 {
++ part-number = "BB-BONE-EXPTEST";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-exptest-00A0.dtbo";
++ };
++ };
+ };
+ };
++
++ vmmcsd_fixed: fixedregulator@0 {
++ compatible = "regulator-fixed";
++ regulator-name = "vmmcsd_fixed";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ };
++
+ };
+
+ &i2c0 {
diff --git a/patches/linux-3.8.13/0401-Add-in-missing-cape-bone-tester-back-in.patch b/patches/linux-3.8.13/0401-Add-in-missing-cape-bone-tester-back-in.patch
new file mode 100644
index 0000000..10a33dc
--- /dev/null
+++ b/patches/linux-3.8.13/0401-Add-in-missing-cape-bone-tester-back-in.patch
@@ -0,0 +1,28 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Apr 2013 21:19:13 +0300
+Subject: [PATCH] Add in missing cape-bone-tester back in.
+
+---
+ arch/arm/boot/dts/am335x-tester.dts | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-tester.dts b/arch/arm/boot/dts/am335x-tester.dts
+index 5059988..4a5ae294 100644
+--- a/arch/arm/boot/dts/am335x-tester.dts
++++ b/arch/arm/boot/dts/am335x-tester.dts
+@@ -240,6 +240,15 @@
+ };
+ };
+
++ /* tester */
++ cape@100 {
++ part-number = "BB-BONE-TESTER";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-bone-tester-00A0.dtbo";
++ };
++ };
++
+ /* beaglebone black emmc on board */
+ cape@1 {
+ /* board-name = "BeagleBone 2G eMMC1 CAPE"; */
diff --git a/patches/linux-3.8.13/0402-cape-bone-hexy-move-OLED-to-different-reset-gpio.patch b/patches/linux-3.8.13/0402-cape-bone-hexy-move-OLED-to-different-reset-gpio.patch
new file mode 100644
index 0000000..d8a21c1
--- /dev/null
+++ b/patches/linux-3.8.13/0402-cape-bone-hexy-move-OLED-to-different-reset-gpio.patch
@@ -0,0 +1,22 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 12 Apr 2013 14:22:04 +0200
+Subject: [PATCH] cape-bone-hexy: move OLED to different reset gpio
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/cape-bone-hexy-00A0.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/firmware/capes/cape-bone-hexy-00A0.dts b/firmware/capes/cape-bone-hexy-00A0.dts
+index 0e90904..f02abd7 100644
+--- a/firmware/capes/cape-bone-hexy-00A0.dts
++++ b/firmware/capes/cape-bone-hexy-00A0.dts
+@@ -150,7 +150,7 @@
+ ssd1306: oled@3c {
+ compatible = "solomon,ssd1306fb-i2c";
+ reg = <0x3c>;
+- reset-gpios = <&gpio4 19 0>;
++ reset-gpios = <&gpio2 17 0>;
+ solomon,height = <32>;
+ solomon,width = <128>;
+ solomon,page-offset = <0>;
diff --git a/patches/linux-3.8.13/0403-firmware-capes-added-dts-file-for-every-PWM-pin.patch b/patches/linux-3.8.13/0403-firmware-capes-added-dts-file-for-every-PWM-pin.patch
new file mode 100644
index 0000000..0ebeb04
--- /dev/null
+++ b/patches/linux-3.8.13/0403-firmware-capes-added-dts-file-for-every-PWM-pin.patch
@@ -0,0 +1,830 @@
+From: Jason Kridner <jdk@ti.com>
+Date: Fri, 12 Apr 2013 13:38:27 +0000
+Subject: [PATCH] firmware/capes: added dts file for every PWM pin
+
+---
+ firmware/Makefile | 15 +++++++
+ firmware/capes/am33xx_pwm-00A0.dts | 74 ++++++++++++++++++++++++++++++++
+ firmware/capes/bone_pwm_P8_13-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P8_19-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P8_34-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P8_36-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P8_45-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P8_46-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_14-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_16-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_21-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_22-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_28-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_29-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_31-00A0.dts | 43 +++++++++++++++++++
+ firmware/capes/bone_pwm_P9_42-00A0.dts | 43 +++++++++++++++++++
+ 16 files changed, 691 insertions(+)
+ create mode 100644 firmware/capes/am33xx_pwm-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P8_13-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P8_19-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P8_34-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P8_36-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P8_45-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P8_46-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_14-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_16-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_21-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_22-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_28-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_29-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_31-00A0.dts
+ create mode 100644 firmware/capes/bone_pwm_P9_42-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 098b4b4..88a4e82 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -156,6 +156,21 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-exptest-00A0.dtbo \
+ cape-bone-mrf24j40-00A0.dtbo \
+ BB-BONELT-BT-00A0.dtbo \
++ am33xx_pwm-00A0.dtbo \
++ bone_pwm_P8_13-00A0.dtbo \
++ bone_pwm_P8_19-00A0.dtbo \
++ bone_pwm_P8_34-00A0.dtbo \
++ bone_pwm_P8_36-00A0.dtbo \
++ bone_pwm_P8_45-00A0.dtbo \
++ bone_pwm_P8_46-00A0.dtbo \
++ bone_pwm_P9_14-00A0.dtbo \
++ bone_pwm_P9_16-00A0.dtbo \
++ bone_pwm_P9_21-00A0.dtbo \
++ bone_pwm_P9_22-00A0.dtbo \
++ bone_pwm_P9_28-00A0.dtbo \
++ bone_pwm_P9_29-00A0.dtbo \
++ bone_pwm_P9_31-00A0.dtbo \
++ bone_pwm_P9_42-00A0.dtbo \
+ BB-BONE-PWMT-00A0.dtbo
+
+ # the geiger cape
+diff --git a/firmware/capes/am33xx_pwm-00A0.dts b/firmware/capes/am33xx_pwm-00A0.dts
+new file mode 100644
+index 0000000..609c1db
+--- /dev/null
++++ b/firmware/capes/am33xx_pwm-00A0.dts
+@@ -0,0 +1,74 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "test1";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&epwmss0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@1 {
++ target = <&ehrpwm0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ecap0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@4 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@5 {
++ target = <&epwmss2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@6 {
++ target = <&ehrpwm2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@7 {
++ target = <&ecap2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P8_13-00A0.dts b/firmware/capes/bone_pwm_P8_13-00A0.dts
+new file mode 100644
+index 0000000..6c2168a
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P8_13-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P8_13";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P8_13: pinmux_pwm_P8_13_pins {
++ pinctrl-single,pins = <0x024 0x4>; /* P8_13 (ZCZ ball T10) | MODE 4 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P8_13 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm2 1 500000 1>;
++ pwm-names = "PWM_P8_13";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_13>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P8_19-00A0.dts b/firmware/capes/bone_pwm_P8_19-00A0.dts
+new file mode 100644
+index 0000000..f5f7454
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P8_19-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P8_19";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P8_19: pinmux_pwm_P8_19_pins {
++ pinctrl-single,pins = <0x020 0x4>; /* P8_19 (ZCZ ball U10) | MODE 4 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P8_19 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm2 0 500000 1>;
++ pwm-names = "PWM_P8_19";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_19>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P8_34-00A0.dts b/firmware/capes/bone_pwm_P8_34-00A0.dts
+new file mode 100644
+index 0000000..be227bf
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P8_34-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P8_34";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P8_34: pinmux_pwm_P8_34_pins {
++ pinctrl-single,pins = <0x0cc 0x2>; /* P8_34 (ZCZ ball U4) | MODE 2 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P8_34 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm1 1 500000 1>;
++ pwm-names = "PWM_P8_34";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_34>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P8_36-00A0.dts b/firmware/capes/bone_pwm_P8_36-00A0.dts
+new file mode 100644
+index 0000000..7ca8694c
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P8_36-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P8_36";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P8_36: pinmux_pwm_P8_36_pins {
++ pinctrl-single,pins = <0x0c8 0x2>; /* P8_36 (ZCZ ball U3) | MODE 2 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P8_36 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm1 0 500000 1>;
++ pwm-names = "PWM_P8_36";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_36>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P8_45-00A0.dts b/firmware/capes/bone_pwm_P8_45-00A0.dts
+new file mode 100644
+index 0000000..3bc8103
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P8_45-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P8_45";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P8_45: pinmux_pwm_P8_45_pins {
++ pinctrl-single,pins = <0x0a0 0x3>; /* P8_45 (ZCZ ball R1) | MODE 3 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P8_45 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm2 0 500000 1>;
++ pwm-names = "PWM_P8_45";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_45>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P8_46-00A0.dts b/firmware/capes/bone_pwm_P8_46-00A0.dts
+new file mode 100644
+index 0000000..4cc6170
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P8_46-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P8_46";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P8_46: pinmux_pwm_P8_46_pins {
++ pinctrl-single,pins = <0x0a4 0x3>; /* P8_46 (ZCZ ball R2) | MODE 3 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P8_46 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm2 1 500000 1>;
++ pwm-names = "PWM_P8_46";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_46>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_14-00A0.dts b/firmware/capes/bone_pwm_P9_14-00A0.dts
+new file mode 100644
+index 0000000..6a6c01a
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_14-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_14";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_14: pinmux_pwm_P9_14_pins {
++ pinctrl-single,pins = <0x048 0x6>; /* P9_14 (ZCZ ball U14) | MODE 6 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_14 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm1 0 500000 1>;
++ pwm-names = "PWM_P9_14";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_14>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_16-00A0.dts b/firmware/capes/bone_pwm_P9_16-00A0.dts
+new file mode 100644
+index 0000000..a1ee9d8
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_16-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_16";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_16: pinmux_pwm_P9_16_pins {
++ pinctrl-single,pins = <0x04c 0x6>; /* P9_16 (ZCZ ball T14) | MODE 6 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_16 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm1 1 500000 1>;
++ pwm-names = "PWM_P9_16";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_16>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_21-00A0.dts b/firmware/capes/bone_pwm_P9_21-00A0.dts
+new file mode 100644
+index 0000000..e667f81
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_21-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_21";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_21: pinmux_pwm_P9_21_pins {
++ pinctrl-single,pins = <0x154 0x3>; /* P9_21 (ZCZ ball B17) | MODE 3 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_21 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm0 1 500000 1>;
++ pwm-names = "PWM_P9_21";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_21>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_22-00A0.dts b/firmware/capes/bone_pwm_P9_22-00A0.dts
+new file mode 100644
+index 0000000..f7c5ed2
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_22-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_22";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_22: pinmux_pwm_P9_22_pins {
++ pinctrl-single,pins = <0x150 0x3>; /* P9_22 (ZCZ ball A17) | MODE 3 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_22 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm0 0 500000 1>;
++ pwm-names = "PWM_P9_22";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_22>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_28-00A0.dts b/firmware/capes/bone_pwm_P9_28-00A0.dts
+new file mode 100644
+index 0000000..96df33d
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_28-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_28";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_28: pinmux_pwm_P9_28_pins {
++ pinctrl-single,pins = <0x19c 0x4>; /* P9_28 (ZCZ ball C12) | MODE 4 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_28 {
++ compatible = "pwm_test";
++ pwms = <&ecap2 0 500000 1>;
++ pwm-names = "PWM_P9_28";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_28>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_29-00A0.dts b/firmware/capes/bone_pwm_P9_29-00A0.dts
+new file mode 100644
+index 0000000..5cff5a8
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_29-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_29";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_29: pinmux_pwm_P9_29_pins {
++ pinctrl-single,pins = <0x194 0x1>; /* P9_29 (ZCZ ball B13) | MODE 1 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_29 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm0 1 500000 1>;
++ pwm-names = "PWM_P9_29";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_29>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_31-00A0.dts b/firmware/capes/bone_pwm_P9_31-00A0.dts
+new file mode 100644
+index 0000000..8126597
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_31-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_31";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_31: pinmux_pwm_P9_31_pins {
++ pinctrl-single,pins = <0x190 0x1>; /* P9_31 (ZCZ ball A13) | MODE 1 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_31 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm0 0 500000 1>;
++ pwm-names = "PWM_P9_31";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_31>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/bone_pwm_P9_42-00A0.dts b/firmware/capes/bone_pwm_P9_42-00A0.dts
+new file mode 100644
+index 0000000..7ffcb9b
+--- /dev/null
++++ b/firmware/capes/bone_pwm_P9_42-00A0.dts
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ * Copyright (C) 2013 Texas Instruments
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "bone_pwm_P9_42";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pwm_P9_42: pinmux_pwm_P9_42_pins {
++ pinctrl-single,pins = <0x164 0x0>; /* P9_42 (ZCZ ball C18) | MODE 0 */
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ pwm_test_P9_42 {
++ compatible = "pwm_test";
++ pwms = <&ecap0 0 500000 1>;
++ pwm-names = "PWM_P9_42";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P9_42>;
++ enabled = <1>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0404-capes-add-LCD7-A3.patch b/patches/linux-3.8.13/0404-capes-add-LCD7-A3.patch
new file mode 100644
index 0000000..8e47e8c
--- /dev/null
+++ b/patches/linux-3.8.13/0404-capes-add-LCD7-A3.patch
@@ -0,0 +1,271 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 23 Apr 2013 15:12:00 +0200
+Subject: [PATCH] capes: add LCD7 A3
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 242 +++++++++++++++++++++++++++++++
+ 2 files changed, 243 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-LCD7-01-00A3.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 88a4e82..0ba37c6 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -149,6 +149,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-lcd3-00A2.dtbo \
+ BB-BONE-AUDI-01-00A0.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
++ BB-BONE-LCD7-01-00A3.dtbo \
+ BB-BONE-LCD7-01-00A4.dtbo \
+ BB-BONE-eMMC1-01-00A0.dtbo \
+ cape-bone-iio-00A0.dtbo \
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+new file mode 100644
+index 0000000..805a6c0
+--- /dev/null
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -0,0 +1,242 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-LCD7-01";
++ version = "00A3";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_lcd7_cape_led_00A3_pins: pinmux_bone_lcd7_cape_led_00A3_pins {
++ pinctrl-single,pins = <
++ 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ pwm_bl_pins: pinmux_pwm_bl_pins {
++ pinctrl-single,pins = <
++ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
++ pinctrl-single,pins = <
++ //0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa3 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_data3.lcd_data3, 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_lcd7_cape_keys_00A3_pins: pinmux_bone_lcd7_cape_keys_00A3_pins {
++ pinctrl-single,pins = <
++ 0x040 0x2f /* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
++ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
++ 0x1a3 0x2f /* TSC_INTn mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
++ // gpio3_16 KEY_DOWN
++ >;
++ };
++
++ };
++ };
++
++ fragment@1 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_bl_pins>;
++ status = "okay";
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "LCD7";
++ 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 */
++ };
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ tsc {
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,coordinate-readouts = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
++ };
++
++ adc {
++ ti,adc-channels = <4>;
++ };
++ };
++
++ gpio-leds-cape-lcd7 {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++
++ pinctrl-0 = <&bone_lcd7_cape_led_00A3_pins>;
++
++ lcd7-led0 {
++ label = "lcd7:green:usr0";
++ gpios = <&gpio2 28 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd7_cape_keys_00A3_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 = <&gpio2 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio4 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 3 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++
++ /* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */
++ panel {
++ compatible = "tilcdc,panel";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd7_cape_lcd_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <16>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 800x480 {
++ hactive = <800>;
++ vactive = <480>;
++ hback-porch = <39>;
++ hfront-porch = <39>;
++ hsync-len = <47>;
++ vback-porch = <29>;
++ vfront-porch = <13>;
++ vsync-len = <2>;
++ clock-frequency = <30000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
++ };
++ };
++ };
++
++ fb {
++ compatible = "ti,am33xx-tilcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio2 31 0x0>;
++ ti,allow-non-reduced-blanking-modes;
++ };
++
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0405-capes-add-basic-support-for-LCD4-capes.patch b/patches/linux-3.8.13/0405-capes-add-basic-support-for-LCD4-capes.patch
new file mode 100644
index 0000000..5dc4436
--- /dev/null
+++ b/patches/linux-3.8.13/0405-capes-add-basic-support-for-LCD4-capes.patch
@@ -0,0 +1,440 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 25 Apr 2013 09:28:32 +0200
+Subject: [PATCH] capes: add basic support for LCD4 capes
+
+Picture only, TS is broken
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 2 +
+ firmware/capes/BB-BONE-LCD4-01-00A0.dts | 161 +++++++++++++++++++++
+ firmware/capes/BB-BONE-LCD4-01-00A1.dts | 239 +++++++++++++++++++++++++++++++
+ 3 files changed, 402 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-LCD4-01-00A0.dts
+ create mode 100644 firmware/capes/BB-BONE-LCD4-01-00A1.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 0ba37c6..1c8c844 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -148,6 +148,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-lcd3-00A0.dtbo \
+ cape-bone-lcd3-00A2.dtbo \
+ BB-BONE-AUDI-01-00A0.dtbo \
++ BB-BONE-LCD4-01-00A0.dtbo \
++ BB-BONE-LCD4-01-00A1.dtbo \
+ BB-BONE-LCD7-01-00A2.dtbo \
+ BB-BONE-LCD7-01-00A3.dtbo \
+ BB-BONE-LCD7-01-00A4.dtbo \
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A0.dts b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+new file mode 100644
+index 0000000..b1c7e00
+--- /dev/null
++++ b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+@@ -0,0 +1,161 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-LCD4-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_lcd4_cape_led_00A0_pins: pinmux_bone_lcd4_cape_led_00A0_pins {
++ pinctrl-single,pins = <
++ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_lcd4_cape_lcd_pins: pinmux_bone_lcd4_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 */
++ 0x4c 0x27 /* TSC_INT gpmc_a3.gpio1_19, INPUT | MODE7 */
++ >;
++ };
++
++ };
++ };
++
++ fragment@1 {
++ target = <&tps>;
++ __overlay__ {
++ backlight {
++ compatible = "not-tps65217-backlight";
++ isel = <1>;
++ fdim = <200>;
++ brightness = <100>;
++ tps = <&tps>;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ tsc {
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,coordinate-readouts = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
++ };
++
++ adc {
++ ti,adc-channels = <4>;
++ };
++ };
++
++ gpio-leds-cape-lcd4 {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++
++ pinctrl-0 = <&bone_lcd4_cape_led_00A0_pins>;
++
++ lcd4-led0 {
++ label = "lcd4:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++ };
++
++ /* Settings for NHD-4.3-ATXI#-T-1 / LCD4 cape: */
++ panel {
++ compatible = "tilcdc,panel";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd4_cape_lcd_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <24>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 480x272 {
++ hactive = <480>;
++ vactive = <272>;
++ hback-porch = <43>;
++ hfront-porch = <8>;
++ hsync-len = <4>;
++ vback-porch = <12>;
++ vfront-porch = <4>;
++ vsync-len = <10>;
++ clock-frequency = <9000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
++ };
++ };
++ };
++
++ fb {
++ compatible = "ti,am33xx-tilcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ };
++
++ };
++ };
++};
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A1.dts b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+new file mode 100644
+index 0000000..2744c27
+--- /dev/null
++++ b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+@@ -0,0 +1,239 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-LCD4-01";
++ version = "00A1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_lcd4_cape_led_00A2_pins: pinmux_bone_lcd4_cape_led_00A2_pins {
++ pinctrl-single,pins = <
++ 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ pwm_bl_pins: pinmux_pwm_bl_pins {
++ pinctrl-single,pins = <
++ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_lcd4_cape_lcd_pins: pinmux_bone_lcd4_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 */
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT | MODE7 LCD DISEN */
++ >;
++ };
++
++ bone_lcd4_cape_keys_00A2_pins: pinmux_bone_lcd4_cape_keys_00A2_pins {
++ pinctrl-single,pins = <
++ 0x040 0x2f /* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ 0x044 0x2f /* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
++ 0x04c 0x2f /* gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
++ 0x154 0x2f /* P9_21 spi0_d0.gpio0_3 INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ };
++ };
++
++ fragment@1 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@2 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@3 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_bl_pins>;
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "LCD4";
++ 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 */
++ status = "okay";
++ };
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ tsc {
++ ti,wires = <4>;
++ ti,x-plate-resistance = <200>;
++ ti,coordinate-readouts = <5>;
++ ti,wire-config = <0x00 0x11 0x22 0x33>;
++ };
++
++ adc {
++ ti,adc-channels = <4>;
++ };
++ };
++
++ gpio-leds-cape-lcd4 {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++
++ pinctrl-0 = <&bone_lcd4_cape_led_00A2_pins>;
++
++ lcd4-led0 {
++ label = "lcd4:green:usr0";
++ gpios = <&gpio2 28 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd4_cape_keys_00A2_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 = <&gpio2 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio4 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 15 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++
++ /* Settings for NHD-4.3-ATXI#-T-1 / LCD4 cape: */
++ panel {
++ compatible = "tilcdc,panel";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd4_cape_lcd_pins>;
++ panel-info {
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ bpp = <24>;
++ fdd = <0x80>;
++ tft-alt-mode = <0>;
++ stn-565-mode = <0>;
++ mono-8bit-mode = <0>;
++ sync-edge = <0>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ };
++ display-timings {
++ native-mode = <&timing0>;
++ timing0: 480x272 {
++ hactive = <480>;
++ vactive = <272>;
++ hback-porch = <43>;
++ hfront-porch = <8>;
++ hsync-len = <4>;
++ vback-porch = <12>;
++ vfront-porch = <4>;
++ vsync-len = <10>;
++ clock-frequency = <9000000>;
++ hsync-active = <0>;
++ vsync-active = <0>;
++ };
++ };
++ };
++
++ fb {
++ compatible = "ti,am33xx-tilcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ };
++
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0406-OF-overlay-Add-depth-option-for-device-creation.patch b/patches/linux-3.8.13/0406-OF-overlay-Add-depth-option-for-device-creation.patch
new file mode 100644
index 0000000..924f5a2
--- /dev/null
+++ b/patches/linux-3.8.13/0406-OF-overlay-Add-depth-option-for-device-creation.patch
@@ -0,0 +1,83 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 16:43:05 +0300
+Subject: [PATCH] OF-overlay: Add depth option for device creation.
+
+Add a depth option for device creation. Normally all nodes that
+represent devices are created, but some devices like gpmc for instance,
+perform their own device creation.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/of/overlay.c | 25 +++++++++++++++++++++++++
+ include/linux/of.h | 1 +
+ 2 files changed, 26 insertions(+)
+
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index 29078c7..f09fe56 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -271,6 +271,8 @@ static int of_overlay_notify(struct notifier_block *nb,
+ struct of_prop_reconfig *pr;
+ struct platform_device *pdev;
+ struct i2c_client *client;
++ struct device_node *tnode;
++ int depth;
+ int prevstate, state;
+ int err = 0;
+
+@@ -359,6 +361,21 @@ static int of_overlay_notify(struct notifier_block *nb,
+ return notifier_from_errno(0);
+ }
+
++ /* find depth */
++ depth = 1;
++ tnode = node;
++ while (tnode != NULL && tnode != ovinfo->target) {
++ tnode = tnode->parent;
++ depth++;
++ }
++
++ /* respect overlay's maximum depth */
++ if (ovinfo->device_depth != 0 && depth > ovinfo->device_depth) {
++ pr_debug("OF: skipping device creation for node=%s depth=%d\n",
++ node->name, depth);
++ goto out;
++ }
++
+ if (state == 0) {
+ pdev = of_find_device_by_node(node);
+ client = of_find_i2c_device_by_node(node);
+@@ -366,6 +383,7 @@ static int of_overlay_notify(struct notifier_block *nb,
+
+ of_overlay_device_entry_entry_add(ovinfo, node, pdev, client,
+ prevstate, state);
++out:
+
+ return notifier_from_errno(err);
+ }
+@@ -749,6 +767,13 @@ int of_fill_overlay_info(struct device_node *info_node,
+ if (ovinfo->overlay == NULL)
+ goto err_fail;
+
++ ret = of_property_read_u32(info_node, "depth", &val);
++ if (ret == 0)
++ ovinfo->device_depth = val;
++ else
++ ovinfo->device_depth = 0;
++
++
+ return 0;
+
+ err_fail:
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 73cfde5..6c72d94 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -735,6 +735,7 @@ struct of_overlay_info {
+ struct list_head le_list;
+ struct list_head de_list;
+ struct notifier_block notifier;
++ int device_depth;
+ };
+
+ #ifdef CONFIG_OF_OVERLAY
diff --git a/patches/linux-3.8.13/0407-capes-Add-BB-BONE-GPEVT-cape.patch b/patches/linux-3.8.13/0407-capes-Add-BB-BONE-GPEVT-cape.patch
new file mode 100644
index 0000000..b496ddb
--- /dev/null
+++ b/patches/linux-3.8.13/0407-capes-Add-BB-BONE-GPEVT-cape.patch
@@ -0,0 +1,72 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 16:52:20 +0300
+Subject: [PATCH] capes: Add BB-BONE-GPEVT cape
+
+Add a virtual cape for the GPEVT dma test driver.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/BB-BONE-GPEVT-00A0.dts | 41 +++++++++++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-GPEVT-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 1c8c844..d122aa1 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -154,6 +154,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-LCD7-01-00A3.dtbo \
+ BB-BONE-LCD7-01-00A4.dtbo \
+ BB-BONE-eMMC1-01-00A0.dtbo \
++ BB-BONE-GPEVT-00A0.dtbo \
+ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo \
+ cape-bone-exptest-00A0.dtbo \
+diff --git a/firmware/capes/BB-BONE-GPEVT-00A0.dts b/firmware/capes/BB-BONE-GPEVT-00A0.dts
+new file mode 100644
+index 0000000..80f9016
+--- /dev/null
++++ b/firmware/capes/BB-BONE-GPEVT-00A0.dts
+@@ -0,0 +1,41 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-GPEVT";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ gpevt_pins_s0: pinmux_gpevt_pins_s0 {
++ pinctrl-single,pins = <
++ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ gpevt {
++ compatible = "gpevt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpevt_pins_s0>;
++
++ dmas = <&edma 12>;
++ dma-names = "gpioevt";
++ gpio-evt = <&gpio3 2 0>;
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0408-clock-Export-__clock_set_parent.patch b/patches/linux-3.8.13/0408-clock-Export-__clock_set_parent.patch
new file mode 100644
index 0000000..872fc98
--- /dev/null
+++ b/patches/linux-3.8.13/0408-clock-Export-__clock_set_parent.patch
@@ -0,0 +1,47 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 18:19:26 +0300
+Subject: [PATCH] clock: Export __clock_set_parent
+
+We need this exported for the manipulation of the clkout2 external
+clock. As part of clock rate selection, the parent must change.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/clk/clk.c | 3 ++-
+ include/linux/clk-provider.h | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 251e45d..8cb8b08 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -1077,7 +1077,7 @@ out:
+ __clk_recalc_rates(clk, POST_RATE_CHANGE);
+ }
+
+-static int __clk_set_parent(struct clk *clk, struct clk *parent)
++int __clk_set_parent(struct clk *clk, struct clk *parent)
+ {
+ struct clk *old_parent;
+ unsigned long flags;
+@@ -1136,6 +1136,7 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent)
+ out:
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(__clk_set_parent);
+
+ /**
+ * clk_set_parent - switch the parent of a mux clk
+diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
+index 1c09481..8c6dadc 100644
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -369,6 +369,8 @@ void __clk_unprepare(struct clk *clk);
+ void __clk_reparent(struct clk *clk, struct clk *new_parent);
+ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
+
++int __clk_set_parent(struct clk *clk, struct clk *parent);
++
+ struct of_device_id;
+
+ typedef void (*of_clk_init_cb_t)(struct device_node *);
diff --git a/patches/linux-3.8.13/0409-omap-clk-Add-adjustable-clkout2.patch b/patches/linux-3.8.13/0409-omap-clk-Add-adjustable-clkout2.patch
new file mode 100644
index 0000000..fb19d10
--- /dev/null
+++ b/patches/linux-3.8.13/0409-omap-clk-Add-adjustable-clkout2.patch
@@ -0,0 +1,276 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 18:32:29 +0300
+Subject: [PATCH] omap-clk: Add adjustable clkout2
+
+The way clkout2 work is no good for external devices needing the clock.
+A way to select rate, that translates to selecting a parent clock is
+required for drivers to work.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/cclock33xx_data.c | 239 +++++++++++++++++++++++++++++++++
+ 1 file changed, 239 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
+index 7e29317..c028220 100644
+--- a/arch/arm/mach-omap2/cclock33xx_data.c
++++ b/arch/arm/mach-omap2/cclock33xx_data.c
+@@ -818,6 +818,242 @@ DEFINE_CLK_DIVIDER_TABLE(clkout2_div_ck, "sysclkout_pre_ck", &sysclkout_pre_ck,
+ DEFINE_CLK_GATE(clkout2_ck, "clkout2_div_ck", &clkout2_div_ck, 0x0,
+ AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2EN_SHIFT, 0x0, NULL);
+
++/********************************************/
++
++static const char *adjustable_sysclkout_ck_parents[] = {
++ "clk_32768_ck", "l3_gclk", "dpll_ddr_m2_ck", "dpll_per_m2_ck",
++ "lcd_gclk",
++};
++
++static const struct clksel foo_sysclkout_pre_sel[] = {
++ { .parent = &clk_32768_ck, .rates = div_1_0_rates },
++ { .parent = &l3_gclk, .rates = div_1_1_rates },
++ { .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
++ { .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
++ { .parent = &lcd_gclk, .rates = div_1_4_rates },
++ { .parent = NULL },
++};
++
++struct clkout_match {
++ unsigned long best_rate;
++ unsigned long parent_rate;
++ const struct clksel *best_clks;
++ const struct clksel_rate *best_clkr;
++ const struct clk_div_table *best_clkd;
++};
++
++struct clk_hw_clkout {
++ struct clk_hw_omap omap_hw;
++ void __iomem *div_reg;
++ u32 div_mask;
++ const struct clk_div_table *div_table;
++ struct clkout_match match;
++};
++
++#define to_clk_hw_clkout(_hw) container_of(_hw, struct clk_hw_clkout, omap_hw.hw)
++
++static int clkout_clk_enable(struct clk_hw *hw)
++{
++ return omap2_dflt_clk_enable(hw);
++}
++
++static void clkout_clk_disable(struct clk_hw *hw)
++{
++ omap2_dflt_clk_enable(hw);
++}
++
++static int clkout_clk_is_enabled(struct clk_hw *hw)
++{
++ return omap2_dflt_clk_is_enabled(hw);
++}
++
++static int clkout_find_match(struct clk_hw *hw, unsigned long target_rate,
++ struct clkout_match *m)
++{
++ struct clk_hw_clkout *clkout_clk = to_clk_hw_clkout(hw);
++ struct clk_hw_omap *omap_clk = to_clk_hw_omap(hw);
++ struct clk *pclk;
++ unsigned long prate, test_rate;
++ const struct clksel *clks;
++ const struct clksel_rate *clkr;
++ const struct clk_div_table *clkd;
++
++ memset(m, 0, sizeof(*m));
++
++ /* iterate over all the clksel */
++ for (clks = omap_clk->clksel; (pclk = clks->parent) != NULL; clks++) {
++ prate = __clk_get_rate(pclk);
++ for (clkr = clks->rates; clkr->div; clkr++) {
++ if (!(clkr->flags & cpu_mask))
++ continue;
++ for (clkd = clkout_clk->div_table; clkd->div; clkd++) {
++ test_rate = (prate / clkr->div) / clkd->div;
++
++ if (abs(test_rate - target_rate) < abs(m->best_rate - target_rate)) {
++ m->parent_rate = prate / clkr->div;
++ m->best_rate = test_rate;
++ m->best_clks = clks;
++ m->best_clkr = clkr;
++ m->best_clkd = clkd;
++ }
++ }
++ }
++ }
++
++ if (!m->best_clks || !m->best_clkr || !m->best_clkd) {
++ pr_err("%s: Failed to find a best match\n", __func__);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int clkout_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long parent_rate)
++{
++ struct clk_hw_clkout *clkout_clk = to_clk_hw_clkout(hw);
++ struct clk_hw_omap *omap_clk = to_clk_hw_omap(hw);
++ struct clkout_match *m = &clkout_clk->match;
++ struct clk *clk = hw->clk;
++ int ret;
++ u32 v;
++
++ ret = clkout_find_match(hw, rate, m);
++ if (ret != 0)
++ return ret;
++
++ /* have to be exact now */
++ if (rate != m->best_rate) {
++ pr_err("%s: Failed to find exact rate %lu (was %lu)\n",
++ __func__, rate, m->best_rate);
++ return -EINVAL;
++ }
++
++ /* switch parent */
++ if (m->best_clks->parent != __clk_get_parent(clk)) {
++ __clk_set_parent(clk, m->best_clks->parent);
++ __clk_reparent(clk, m->best_clks->parent);
++ parent_rate = __clk_get_rate(__clk_get_parent(clk));
++ }
++
++ /* we need to write the new value */
++ if (omap_clk->clksel_reg != clkout_clk->div_reg) {
++ v = __raw_readl(omap_clk->clksel_reg);
++ v &= ~omap_clk->clksel_mask;
++ v |= m->best_clkr->val << __ffs(omap_clk->clksel_mask);
++ __raw_writel(v, omap_clk->clksel_reg);
++ v = __raw_readl(omap_clk->clksel_reg); /* OCP barrier */
++
++ v = __raw_readl(clkout_clk->div_reg);
++ v &= ~clkout_clk->div_mask;
++ v |= m->best_clkd->val << __ffs(clkout_clk->div_mask);
++ __raw_writel(v, clkout_clk->div_reg);
++ v = __raw_readl(clkout_clk->div_reg); /* OCP barrier */
++ } else {
++ v = __raw_readl(omap_clk->clksel_reg);
++ v &= ~(omap_clk->clksel_mask | clkout_clk->div_mask);
++ v |= (m->best_clkr->val << __ffs(omap_clk->clksel_mask)) |
++ (m->best_clkd->val << __ffs(clkout_clk->div_mask));
++ __raw_writel(v, omap_clk->clksel_reg);
++ v = __raw_readl(omap_clk->clksel_reg); /* OCP barrier */
++ }
++
++ return ret;
++}
++
++static long clkout_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
++ unsigned long *parent_rate)
++{
++ struct clkout_match m;
++ long ret;
++
++ ret = clkout_find_match(hw, target_rate, &m);
++ if (ret != 0) {
++ pr_err("%s: Failed to find a best match\n", __func__);
++ return (unsigned long)-1;
++ }
++
++ *parent_rate = __clk_get_rate(m.best_clks->parent);
++
++ return m.best_rate;
++}
++
++static unsigned long clkout_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
++{
++ struct clk_hw_clkout *clkout_clk = to_clk_hw_clkout(hw);
++ struct clk_hw_omap *omap_clk = to_clk_hw_omap(hw);
++ u32 v;
++ unsigned int divr, divd;
++
++ v = __raw_readl(omap_clk->clksel_reg);
++ v &= omap_clk->clksel_mask;
++ v >>= __ffs(omap_clk->clksel_mask);
++ divr = v;
++
++ v = __raw_readl(clkout_clk->div_reg);
++ v &= clkout_clk->div_mask;
++ v >>= __ffs(clkout_clk->div_mask);
++ divd = v;
++
++ return clkout_clk->match.best_rate;
++}
++
++static u8 clkout_clksel_find_parent_index(struct clk_hw *hw)
++{
++ return omap2_clksel_find_parent_index(hw);
++}
++
++static int clkout_clksel_set_parent(struct clk_hw *hw, u8 field_val)
++{
++ return omap2_clksel_set_parent(hw, field_val);
++}
++
++static void clkout_init_clk_clkdm(struct clk_hw *hw)
++{
++ omap2_init_clk_clkdm(hw);
++}
++
++static const struct clk_ops adjustable_sysclkout_ck_clk_ops = {
++ .enable = &clkout_clk_enable,
++ .disable = &clkout_clk_disable,
++ .is_enabled = &clkout_clk_is_enabled,
++ .set_rate = &clkout_clksel_set_rate,
++ .round_rate = &clkout_clksel_round_rate,
++ .recalc_rate = &clkout_clksel_recalc,
++ .get_parent = &clkout_clksel_find_parent_index,
++ .set_parent = &clkout_clksel_set_parent,
++ .init = &clkout_init_clk_clkdm,
++};
++
++static struct clk adjustable_clkout2_ck;
++static struct clk_hw_clkout adjustable_clkout2_ck_hw = {
++ .omap_hw = {
++ .hw = {
++ .clk = &adjustable_clkout2_ck,
++ },
++ .ops = NULL,
++ .enable_reg = AM33XX_CM_CLKOUT_CTRL,
++ .enable_bit = AM33XX_CLKOUT2EN_SHIFT,
++ .clksel = foo_sysclkout_pre_sel,
++ .clksel_reg = AM33XX_CM_CLKOUT_CTRL,
++ .clksel_mask = AM33XX_CLKOUT2SOURCE_MASK,
++ .clkdm_name = NULL,
++ },
++ .div_reg = AM33XX_CM_CLKOUT_CTRL,
++ .div_mask = AM33XX_CLKOUT2DIV_MASK,
++ .div_table = div8_rates,
++};
++static struct clk adjustable_clkout2_ck = {
++ .name = "adjustable_clkout2_ck",
++ .hw = &adjustable_clkout2_ck_hw.omap_hw.hw,
++ .parent_names = adjustable_sysclkout_ck_parents,
++ .num_parents = ARRAY_SIZE(adjustable_sysclkout_ck_parents),
++ .ops = &adjustable_sysclkout_ck_clk_ops,
++ .flags = CLK_GET_RATE_NOCACHE | CLK_SET_PARENT_GATE | CLK_SET_RATE_GATE
++};
++
++/********************************************/
++
+ static const char *wdt_ck_parents[] = {
+ "clk_rc32k_ck", "clkdiv32k_ick",
+ };
+@@ -947,12 +1183,15 @@ static struct omap_clk am33xx_clks[] = {
+ CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX),
+ CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX),
+ CLK(NULL, "clkout2_div_ck", &clkout2_div_ck, CK_AM33XX),
++ 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("48300200.ehrpwm", "tbclk", &ehrpwm0_tbclk, CK_AM33XX),
+ CLK("48302200.ehrpwm", "tbclk", &ehrpwm1_tbclk, CK_AM33XX),
+ CLK("48304200.ehrpwm", "tbclk", &ehrpwm2_tbclk, CK_AM33XX),
+ CLK("4830e000.fb", "fck", &lcd_gclk, CK_AM33XX),
++ /* magical adjustable clkout2 without mult/div */
++ CLK(NULL, "adjustable_clkout2_ck", &adjustable_clkout2_ck,CK_AM33XX),
+ };
+
+
diff --git a/patches/linux-3.8.13/0410-am33xx-Update-DTS-EDMA.patch b/patches/linux-3.8.13/0410-am33xx-Update-DTS-EDMA.patch
new file mode 100644
index 0000000..485679c
--- /dev/null
+++ b/patches/linux-3.8.13/0410-am33xx-Update-DTS-EDMA.patch
@@ -0,0 +1,48 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 18:36:32 +0300
+Subject: [PATCH] am33xx: Update DTS EDMA
+
+Update EDMA bindings to work the same way as on the 3.2 kernel
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 3 ++-
+ arch/arm/boot/dts/am33xx.dtsi | 4 ++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 1c91d7d..92e3fb6 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -447,7 +447,8 @@
+ };
+
+ &edma {
+- ti,edma-xbar-event-map = <32 12>;
++ ti,edma-xbar-event-map = <32 12>, /* gpevt2 -> 12 */
++ <30 20>; /* xdma_event_intr2 -> 20 */
+ };
+
+ &sham {
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 797f421..9bf0d2c 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -95,7 +95,7 @@
+ compatible = "ti,edma3";
+ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
+ reg = <0x49000000 0x10000>,
+- <0x44e10f90 0x10>;
++ <0x44e10f90 0x40>;
+ interrupt-parent = <&intc>;
+ interrupts = <12 13 14>;
+ #dma-cells = <1>;
+@@ -108,7 +108,7 @@
+ ti,edma-queue-priority-map = <0 0
+ 1 1
+ 2 2>;
+- ti,edma-default-queue = <0>;
++ ti,edma-default-queue = <1>;
+ };
+
+ gpio1: gpio@44e07000 {
diff --git a/patches/linux-3.8.13/0411-bone-Added-RS232-prototype-cape-DT-object.patch b/patches/linux-3.8.13/0411-bone-Added-RS232-prototype-cape-DT-object.patch
new file mode 100644
index 0000000..4f6b581
--- /dev/null
+++ b/patches/linux-3.8.13/0411-bone-Added-RS232-prototype-cape-DT-object.patch
@@ -0,0 +1,110 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Tue, 23 Apr 2013 17:18:34 +0000
+Subject: [PATCH] bone: Added RS232 prototype cape DT object
+
+Added UART device tree object to setup UART3 and pinmux.
+This should work with the RS232 cape that currently exists.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 19 +++++++++++++-
+ firmware/Makefile | 1 +
+ firmware/capes/BB-BONE-RS232-00A0.dts | 39 +++++++++++++++++++++++++++++
+ 3 files changed, 58 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-RS232-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 92e3fb6..d525195 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -205,8 +205,18 @@
+ manufacturer = "Signal 11 Software";
+ part-number = "BB-BONE-MRF24J40";
+ };
+- };
+
++ /* RS232 cape */
++ slot@12 {
++ ti,cape-override;
++ compatible = "kernel-command-line", "runtime";
++ board-name = "BB-BONE-RS232";
++ version = "00A0";
++ manufacturer = "Adafruit";
++ part-number = "BB-BONE-RS232-01";
++ };
++ };
++
+ /* mapping between board names and dtb objects */
+ capemaps {
+ /* DVI cape */
+@@ -328,6 +338,13 @@
+ dtbo = "cape-bone-exptest-00A0.dtbo";
+ };
+ };
++ cape@12 {
++ part-number = "BB-BONE-RS232-01";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "BB-BONE-RS232-00A0.dtbo";
++ };
++ };
+ };
+ };
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index d122aa1..3a4f126 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -155,6 +155,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-LCD7-01-00A4.dtbo \
+ BB-BONE-eMMC1-01-00A0.dtbo \
+ BB-BONE-GPEVT-00A0.dtbo \
++ BB-BONE-RS232-00A0.dtbo \
+ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo \
+ cape-bone-exptest-00A0.dtbo \
+diff --git a/firmware/capes/BB-BONE-RS232-00A0.dts b/firmware/capes/BB-BONE-RS232-00A0.dts
+new file mode 100644
+index 0000000..220c85d
+--- /dev/null
++++ b/firmware/capes/BB-BONE-RS232-00A0.dts
+@@ -0,0 +1,39 @@
++/*
++ * Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-RS232";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ uart_pins: pinmux_uart_pins {
++ pinctrl-single,pins = <
++ 0x150 0x21 /* spi0_sclk.uart2_rxd | MODE1 | PULL_UP */
++ 0x154 0x01 /* spi0_d0.uart2_txd | MODE1 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&uart3>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&uart_pins>;
++ };
++ };
++
++};
diff --git a/patches/linux-3.8.13/0412-Add-support-for-BB-BONE_SERL-01-00A1-CanBus-cape.patch b/patches/linux-3.8.13/0412-Add-support-for-BB-BONE_SERL-01-00A1-CanBus-cape.patch
new file mode 100644
index 0000000..eabeb8f
--- /dev/null
+++ b/patches/linux-3.8.13/0412-Add-support-for-BB-BONE_SERL-01-00A1-CanBus-cape.patch
@@ -0,0 +1,66 @@
+From: Martin Gysel <me@bearsh.org>
+Date: Wed, 15 May 2013 16:48:34 +0200
+Subject: [PATCH] Add support for BB-BONE_SERL-01-00A1 CanBus cape
+
+Signed-off-by: Martin Gysel <me@bearsh.org>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/BB-BONE-SERL-01-00A1.dts | 37 +++++++++++++++++++++++++++++++
+ 2 files changed, 38 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-SERL-01-00A1.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 3a4f126..3497631 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -156,6 +156,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-eMMC1-01-00A0.dtbo \
+ BB-BONE-GPEVT-00A0.dtbo \
+ BB-BONE-RS232-00A0.dtbo \
++ BB-BONE-SERL-01-00A1.dtbo \
+ cape-bone-iio-00A0.dtbo \
+ cape-bone-pinmux-test-00A0.dtbo \
+ cape-bone-exptest-00A0.dtbo \
+diff --git a/firmware/capes/BB-BONE-SERL-01-00A1.dts b/firmware/capes/BB-BONE-SERL-01-00A1.dts
+new file mode 100644
+index 0000000..b0459c8
+--- /dev/null
++++ b/firmware/capes/BB-BONE-SERL-01-00A1.dts
+@@ -0,0 +1,37 @@
++/*
++* Copyright (C) 2013 Martin Gysel <me@bearsh.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.
++*/
++/dts-v1/;
++/plugin/;
++
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "BB-BONE-SERL-01";
++ version = "00A1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bone_serl_01_dcan1_pins: bone_serl_01_dcan1_pins {
++ pinctrl-single,pins = <
++ 0x180 0x02 /* uart1_rxd.d_can1_tx", OUTPUT | MODE2 */
++ 0x184 0x32 /* uart1_txd.d_can1_rx", INPUT_PULLUP | MODE2 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&dcan1>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_serl_01_dcan1_pins>;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0413-capes-Add-virtual-capes-serving-as-examples.patch b/patches/linux-3.8.13/0413-capes-Add-virtual-capes-serving-as-examples.patch
new file mode 100644
index 0000000..3c06b53
--- /dev/null
+++ b/patches/linux-3.8.13/0413-capes-Add-virtual-capes-serving-as-examples.patch
@@ -0,0 +1,676 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 30 May 2013 15:44:07 +0300
+Subject: [PATCH] capes: Add virtual capes serving as examples
+
+Example capes for UART/I2C/SPI.
+
+Conflicts:
+ firmware/Makefile
+---
+ firmware/Makefile | 19 +++++++++
+ firmware/capes/BB-I2C1-00A0.dts | 65 +++++++++++++++++++++++++++++
+ firmware/capes/BB-I2C1A1-00A0.dts | 65 +++++++++++++++++++++++++++++
+ firmware/capes/BB-SPI0-00A0.dts | 79 ++++++++++++++++++++++++++++++++++++
+ firmware/capes/BB-SPI1-00A0.dts | 79 ++++++++++++++++++++++++++++++++++++
+ firmware/capes/BB-SPI1A1-00A0.dts | 81 +++++++++++++++++++++++++++++++++++++
+ firmware/capes/BB-UART1-00A0.dts | 48 ++++++++++++++++++++++
+ firmware/capes/BB-UART2-00A0.dts | 48 ++++++++++++++++++++++
+ firmware/capes/BB-UART4-00A0.dts | 48 ++++++++++++++++++++++
+ firmware/capes/BB-UART5-00A0.dts | 49 ++++++++++++++++++++++
+ 10 files changed, 581 insertions(+)
+ create mode 100644 firmware/capes/BB-I2C1-00A0.dts
+ create mode 100644 firmware/capes/BB-I2C1A1-00A0.dts
+ create mode 100644 firmware/capes/BB-SPI0-00A0.dts
+ create mode 100644 firmware/capes/BB-SPI1-00A0.dts
+ create mode 100644 firmware/capes/BB-SPI1A1-00A0.dts
+ create mode 100644 firmware/capes/BB-UART1-00A0.dts
+ create mode 100644 firmware/capes/BB-UART2-00A0.dts
+ create mode 100644 firmware/capes/BB-UART4-00A0.dts
+ create mode 100644 firmware/capes/BB-UART5-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 3497631..b039188 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -196,6 +196,25 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-boneblack-hdmi-00A0.dtbo
+ # the Tester cape (tester-side)
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-tester-00A0.dtbo
+
++# the virtual peripheral capes for the UARTs
++# UART3 is not routed to the connectors, no cape for it
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ BB-UART1-00A0.dtbo BB-UART2-00A0.dtbo \
++ BB-UART4-00A0.dtbo BB-UART5-00A0.dtbo
++
++# the virtual peripheral capes for the I2Cs
++# I2C0 & I2C2 are enabled by default, no capes for them
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ BB-I2C1-00A0.dtbo BB-I2C1A1-00A0.dtbo
++
++# the virtual peripheral capes for the SPIs
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ BB-SPI0-00A0.dtbo BB-SPI1-00A0.dtbo BB-SPI1A1-00A0.dtbo
++
++# PRU firmware
++#fw-shipped-$(CONFIG_PRU_RPROC) += \
++# prutest.bin
++
+ fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+
+ # Directories which we _might_ need to create, so we have a rule for them.
+diff --git a/firmware/capes/BB-I2C1-00A0.dts b/firmware/capes/BB-I2C1-00A0.dts
+new file mode 100644
+index 0000000..9e74f26
+--- /dev/null
++++ b/firmware/capes/BB-I2C1-00A0.dts
+@@ -0,0 +1,65 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for I2C1 on connector pins P9.17 P9.18
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-I2C1";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.18", /* i2c1_sda */
++ "P9.17", /* i2c1_scl */
++ /* the hardware ip uses */
++ "i2c1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bb_i2c1_pins: pinmux_bb_i2c1_pins {
++ pinctrl-single,pins = <
++ 0x158 0x72 /* spi0_d1.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
++ 0x15c 0x72 /* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c1>; /* i2c1 is numbered correctly */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_i2c1_pins>;
++
++ /* this is the configuration part */
++ clock-frequency = <100000>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* add any i2c devices on the bus here */
++
++ // commented out example of a touchscreen (taken from BB-BONE-LCD7-01-00A4) */
++ // maxtouch@4a {
++ // compatible = "mXT224";
++ // reg = <0x4a>;
++ // interrupt-parent = <&gpio4>;
++ // interrupts = <19 0x0>;
++ // atmel,irq-gpio = <&gpio4 19 0>;
++ // };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-I2C1A1-00A0.dts b/firmware/capes/BB-I2C1A1-00A0.dts
+new file mode 100644
+index 0000000..4a2b1bd
+--- /dev/null
++++ b/firmware/capes/BB-I2C1A1-00A0.dts
+@@ -0,0 +1,65 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for I2C1 on connector pins P9.26 P9.24 (ALT config #1)
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-I2C1A1";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.26", /* i2c1_sda */
++ "P9.24", /* i2c1_scl */
++ /* the hardware ip uses */
++ "i2c1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bb_i2c1a1_pins: pinmux_bb_i2c1a1_pins {
++ pinctrl-single,pins = <
++ 0x180 0x73 /* uart1_rxd.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ 0x184 0x73 /* uart1_txdi2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&i2c1>; /* i2c1 is numbered correctly */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_i2c1a1_pins>;
++
++ /* this is the configuration part */
++ clock-frequency = <100000>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* add any i2c devices on the bus here */
++
++ // commented out example of a touchscreen (taken from BB-BONE-LCD7-01-00A4) */
++ // maxtouch@4a {
++ // compatible = "mXT224";
++ // reg = <0x4a>;
++ // interrupt-parent = <&gpio4>;
++ // interrupts = <19 0x0>;
++ // atmel,irq-gpio = <&gpio4 19 0>;
++ // };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-SPI0-00A0.dts b/firmware/capes/BB-SPI0-00A0.dts
+new file mode 100644
+index 0000000..547efce
+--- /dev/null
++++ b/firmware/capes/BB-SPI0-00A0.dts
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for SPI0 on connector pins P9.22 P9.21 P9.18 P9.17
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-SPI0";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.17", /* spi0_cs0 */
++ "P9.18", /* spi0_d1 */
++ "P9.21", /* spi0_d0 */
++ "P9.22", /* spi0_sclk */
++ /* the hardware ip uses */
++ "spi0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ /* default state has all gpios released and mode set to uart1 */
++ bb_spi0_pins: pinmux_bb_spi0_pins {
++ pinctrl-single,pins = <
++ 0x150 0x30 /* spi0_sclk.spi0_sclk, INPUT_PULLUP | MODE0 */
++ 0x154 0x30 /* spi0_d0.spi0_d0, INPUT_PULLUP | MODE0 */
++ 0x158 0x10 /* spi0_d1.spi0_d1, OUTPUT_PULLUP | MODE0 */
++ 0x15c 0x10 /* spi0_cs0.spi0_cs0, OUTPUT_PULLUP | MODE0 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&spi0>; /* spi0 is numbered correctly */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_spi0_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* add any spi devices connected here */
++ /* note that you can do direct SPI via spidev now */
++
++ // commented out example of an adafruit 1.8" TFT display
++ // from firmare/capes/cape-bone-adafruit-lcd-00A0.dts
++ // lcd@0 {
++ // #address-cells = <1>;
++ // #size-cells = <0>;
++ //
++ // compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
++ // reg = <0>;
++ //
++ // spi-max-frequency = <8000000>;
++ // spi-cpol;
++ // spi-cpha;
++ //
++ // pinctrl-names = "default";
++ // pinctrl-0 = <&bone_adafruit_lcd_pins>;
++ //
++ // st7735-rst = <&gpio4 19 0>;
++ // st7735-dc = <&gpio4 21 0>;
++ // };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-SPI1-00A0.dts b/firmware/capes/BB-SPI1-00A0.dts
+new file mode 100644
+index 0000000..e26f346
+--- /dev/null
++++ b/firmware/capes/BB-SPI1-00A0.dts
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for SPI1 on connector pins P9.29 P9.31 P9.30 P9.28
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-SPI1";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.31", /* spi1_sclk */
++ "P9.29", /* spi1_d0 */
++ "P9.30", /* spi1_d1 */
++ "P9.28", /* spi1_cs0 */
++ /* the hardware ip uses */
++ "spi1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ /* default state has all gpios released and mode set to uart1 */
++ bb_spi1_pins: pinmux_bb_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, INPUT_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 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&spi1>; /* spi1 is numbered correctly */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_spi1_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* add any spi devices connected here */
++ /* note that you can do direct SPI via spidev now */
++
++ // commented out example of an adafruit 1.8" TFT display
++ // from firmare/capes/cape-bone-adafruit-lcd-00A0.dts
++ // lcd@0 {
++ // #address-cells = <1>;
++ // #size-cells = <0>;
++ //
++ // compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
++ // reg = <0>;
++ //
++ // spi-max-frequency = <8000000>;
++ // spi-cpol;
++ // spi-cpha;
++ //
++ // pinctrl-names = "default";
++ // pinctrl-0 = <&bone_adafruit_lcd_pins>;
++ //
++ // st7735-rst = <&gpio4 19 0>;
++ // st7735-dc = <&gpio4 21 0>;
++ // };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-SPI1A1-00A0.dts b/firmware/capes/BB-SPI1A1-00A0.dts
+new file mode 100644
+index 0000000..ba98e73
+--- /dev/null
++++ b/firmware/capes/BB-SPI1A1-00A0.dts
+@@ -0,0 +1,81 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for SPI1 (ALT #1) on connector pins
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-SPI1";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.42", /* spi1_sclk */
++ "P9.29", /* spi1_d0 */
++ "P9.30", /* spi1_d1 */
++ "P9.20", /* spi1_cs0 */
++ /* the hardware ip uses */
++ "spi1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ /* default state has all gpios released and mode set to uart1 */
++ bb_spi1_pins: pinmux_bb_spi1_pins {
++ pinctrl-single,pins = <
++ 0x164 0x34 /* eCAP0_in_PWM0_out.spi1_sclk, INPUT_PULLUP | MODE4 */
++ /* NOTE: P9.42 is connected to two pads */
++ // 0x1A0 0x27 /* set the other pad to gpio input */
++ 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
++ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
++ 0x178 0x14 /* uart1_ctsn.spi1_cs0, OUTPUT_PULLUP | MODE4 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&spi1>; /* spi1 is numbered correctly */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_spi1_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* add any spi devices connected here */
++ /* note that you can do direct SPI via spidev now */
++
++ // commented out example of an adafruit 1.8" TFT display
++ // from firmare/capes/cape-bone-adafruit-lcd-00A0.dts
++ // lcd@0 {
++ // #address-cells = <1>;
++ // #size-cells = <0>;
++ //
++ // compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
++ // reg = <0>;
++ //
++ // spi-max-frequency = <8000000>;
++ // spi-cpol;
++ // spi-cpha;
++ //
++ // pinctrl-names = "default";
++ // pinctrl-0 = <&bone_adafruit_lcd_pins>;
++ //
++ // st7735-rst = <&gpio4 19 0>;
++ // st7735-dc = <&gpio4 21 0>;
++ // };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-UART1-00A0.dts b/firmware/capes/BB-UART1-00A0.dts
+new file mode 100644
+index 0000000..ce2b3d1
+--- /dev/null
++++ b/firmware/capes/BB-UART1-00A0.dts
+@@ -0,0 +1,48 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for UART1 on connector pins P9.24 P9.26
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-UART1";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.24", /* uart1_txd */
++ "P9.26", /* uart1_rxd */
++ /* the hardware ip uses */
++ "uart1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bb_uart1_pins: pinmux_bb_uart1_pins {
++ pinctrl-single,pins = <
++ 0x184 0x20 /* P9.24 uart1_txd.uart1_txd OUTPUT */
++ 0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd INPUT */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&uart2>; /* really uart1 */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_uart1_pins>;
++ };
++ };
++};
+diff --git a/firmware/capes/BB-UART2-00A0.dts b/firmware/capes/BB-UART2-00A0.dts
+new file mode 100644
+index 0000000..7534495
+--- /dev/null
++++ b/firmware/capes/BB-UART2-00A0.dts
+@@ -0,0 +1,48 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for UART2 on connector pins P9.21 P9.22
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-UART2";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.21", /* uart2_txd */
++ "P9.22", /* uart2_rxd */
++ /* the hardware ip uses */
++ "uart2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bb_uart2_pins: pinmux_bb_uart2_pins {
++ pinctrl-single,pins = <
++ 0x150 0x21 /* spi0_sclk.uart2_rxd | MODE1 */
++ 0x154 0x01 /* spi0_d0.uart2_txd | MODE1 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&uart3>; /* really uart2 */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_uart2_pins>;
++ };
++ };
++};
+diff --git a/firmware/capes/BB-UART4-00A0.dts b/firmware/capes/BB-UART4-00A0.dts
+new file mode 100644
+index 0000000..cfd7947
+--- /dev/null
++++ b/firmware/capes/BB-UART4-00A0.dts
+@@ -0,0 +1,48 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for UART4 on connector pins P9.13 P9.11
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-UART4";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.13", /* uart4_txd */
++ "P9.11", /* uart4_rxd */
++ /* the hardware ip uses */
++ "uart4";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bb_uart4_pins: pinmux_bb_uart4_pins {
++ pinctrl-single,pins = <
++ 0x070 0x26 /* gpmc_wait0.uart4_rxd | MODE6 */
++ 0x074 0x06 /* gpmc_wpn.uart4_txd | MODE6 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&uart5>; /* really uart4 */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_uart4_pins>;
++ };
++ };
++};
+diff --git a/firmware/capes/BB-UART5-00A0.dts b/firmware/capes/BB-UART5-00A0.dts
+new file mode 100644
+index 0000000..e067068
+--- /dev/null
++++ b/firmware/capes/BB-UART5-00A0.dts
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * Virtual cape for UART5 on connector pins P9.37 P8.38
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-UART5";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.37", /* uart5_txd */
++ "P8.38", /* uart5_rxd */
++ /* the hardware ip uses */
++ "uart5";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bb_uart5_pins: pinmux_bb_uart5_pins {
++ pinctrl-single,pins = <
++ /* the uart pins */
++ 0x0C4 0x24 /* lcd_data9.uart5_rxd | MODE4 */
++ 0x0C0 0x04 /* lcd_data8.uart5_txd | MODE4 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&uart6>; /* really uart5 */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_uart5_pins>;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0414-capes-Add-TowerTech-TT3201-CAN-Bus-Cape-TT3201-001-3.patch b/patches/linux-3.8.13/0414-capes-Add-TowerTech-TT3201-CAN-Bus-Cape-TT3201-001-3.patch
new file mode 100644
index 0000000..df4b6f0
--- /dev/null
+++ b/patches/linux-3.8.13/0414-capes-Add-TowerTech-TT3201-CAN-Bus-Cape-TT3201-001-3.patch
@@ -0,0 +1,175 @@
+From: Alessandro Zummo <a.zummo@towertech.it>
+Date: Sat, 25 May 2013 19:18:07 +0200
+Subject: [PATCH] capes: Add TowerTech TT3201 CAN Bus Cape (TT3201-001, 3
+ channels) Rev 01 and 02
+
+--
+
+firmware/Makefile | 3 +-
+ firmware/capes/TT3201-001-01.dts | 134 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 136 insertions(+), 1 deletion(-)
+---
+ firmware/Makefile | 8 ++-
+ firmware/capes/TT3201-001-01.dts | 134 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 141 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/TT3201-001-01.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index b039188..6d896d2 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -177,7 +177,13 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ bone_pwm_P9_29-00A0.dtbo \
+ bone_pwm_P9_31-00A0.dtbo \
+ bone_pwm_P9_42-00A0.dtbo \
+- BB-BONE-PWMT-00A0.dtbo
++ BB-BONE-PWMT-00A0.dtbo \
++ BB-BONE-PRU-01-00A0.dtbo \
++ BB-BONE-PRU-02-00A0.dtbo \
++ BB-BONE-RST-00A0.dtbo \
++ BB-BONE-RST2-00A0.dtbo \
++ BB-BONE-CAM3-01-00A2.dtbo \
++ TT3201-001-01.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/TT3201-001-01.dts b/firmware/capes/TT3201-001-01.dts
+new file mode 100644
+index 0000000..d1f950c
+--- /dev/null
++++ b/firmware/capes/TT3201-001-01.dts
+@@ -0,0 +1,134 @@
++/*
++* Copyright (C) 2013 Tower Technologies
++* Written by Alessandro Zummo <a.zummo@towertech.it>
++*
++* 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/;
++/plugin/;
++
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "TT3201-001";
++ version = "01";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.27", /* spi irq: gpio3_19 */
++ "P9.25", /* spi irq: gpio3_21 */
++ "P9.31", /* spi: spi1_sclk */
++ "P9.29", /* spi: spi1_d0 */
++ "P9.30", /* spi: spi1_d1 */
++ "P9.28", /* spi: spi1_cs0 */
++ "P9.42", /* spi: spi1_cs1 */
++ "P9.26", /* dcan1: dcan1_tx */
++ "P9.24", /* dcan1: dcan1_rx */
++ /* the hardware IP uses */
++ "gpio3_19",
++ "gpio3_21",
++ "spi1",
++ "dcan1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bone_tt3201_dcan1_pins: bone_tt3201_dcan1_pins {
++ pinctrl-single,pins = <
++ 0x180 0x02 /* uart1_rxd.d_can1_tx", OUTPUT | MODE2 */
++ 0x184 0x32 /* uart1_txd.d_can1_rx", INPUT_PULLUP | MODE2 */
++ >;
++ };
++
++ bone_tt3201_spi1_pins: pinmux_bone_tt3201_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x33 /* mcasp0_aclkx.spi1_sclk, RX_ENABLED | PULLUP | MODE3 */
++ 0x194 0x33 /* mcasp0_fsx.spi1_d0, RX_ENABLED | PULLUP | MODE3 */
++ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
++ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
++ 0x164 0x12 /* ecap0_in_pwm0_out.spi1_cs1, OUTPUT_PULLUP | MODE2 */
++ >;
++ };
++
++ bone_tt3201_mcp2515_0_pins: pinmux_bone_tt3201_0_mcp2515_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x37 /* mcasp0_fsr.gpio3_19, RX_ENABLED | PULLUP | MODE7 */
++ >;
++ };
++
++ bone_tt3201_mcp2515_1_pins: pinmux_bone_tt3201_1_mcp2515_pins {
++ pinctrl-single,pins = <
++ 0x1ac 0x37 /* mcasp0_ahclkx.gpio3_21, RX_ENABLED | PULLUP | MODE7 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&spi1>;
++
++ __overlay__ {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_tt3201_spi1_pins>;
++
++ cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>;
++
++ mcp2515@0 {
++
++ compatible = "microchip,mcp2515";
++ reg = <1>; /* cs1 */
++ mode = <0>;
++
++ spi-max-frequency = <10000000>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_tt3201_mcp2515_1_pins>;
++
++ interrupt-parent = <&gpio4>;
++ interrupts = <21>;
++
++ mcp251x,oscillator-frequency = <16000000>;
++ mcp251x,irq-gpios = <&gpio4 21 0>;
++ mcp251x,stay-awake = <1>;
++ };
++
++ mcp2515@1 {
++
++ compatible = "microchip,mcp2515";
++ reg = <0>; /* cs0 */
++ mode = <0>;
++
++ spi-max-frequency = <10000000>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_tt3201_mcp2515_0_pins>;
++
++ interrupt-parent = <&gpio4>;
++ interrupts = <19>;
++
++ mcp251x,oscillator-frequency = <16000000>;
++ mcp251x,irq-gpios = <&gpio4 19 0>;
++ mcp251x,stay-awake = <1>;
++ mcp251x,enable-clkout = <1>;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&dcan1>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_tt3201_dcan1_pins>;
++ };
++ };
++};
++
diff --git a/patches/linux-3.8.13/0415-capes-Add-commented-out-example-of-use-of-spi1_cs1.patch b/patches/linux-3.8.13/0415-capes-Add-commented-out-example-of-use-of-spi1_cs1.patch
new file mode 100644
index 0000000..5774cce
--- /dev/null
+++ b/patches/linux-3.8.13/0415-capes-Add-commented-out-example-of-use-of-spi1_cs1.patch
@@ -0,0 +1,28 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 30 May 2013 16:38:42 +0300
+Subject: [PATCH] capes: Add commented out example of use of spi1_cs1
+
+---
+ firmware/capes/BB-SPI1-00A0.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/firmware/capes/BB-SPI1-00A0.dts b/firmware/capes/BB-SPI1-00A0.dts
+index e26f346..1ead983 100644
+--- a/firmware/capes/BB-SPI1-00A0.dts
++++ b/firmware/capes/BB-SPI1-00A0.dts
+@@ -24,6 +24,7 @@
+ "P9.29", /* spi1_d0 */
+ "P9.30", /* spi1_d1 */
+ "P9.28", /* spi1_cs0 */
++ // "P9.42", /* spi1_cs1 */
+ /* the hardware ip uses */
+ "spi1";
+
+@@ -37,6 +38,7 @@
+ 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 */
++ // 0x164 0x12 /* eCAP0_in_PWM0_out.spi1_cs1 OUTPUT_PULLUP | MODE2 */
+ >;
+ };
+ };
diff --git a/patches/linux-3.8.13/0416-cape-LCD4-Correct-key-active-polarity.patch b/patches/linux-3.8.13/0416-cape-LCD4-Correct-key-active-polarity.patch
new file mode 100644
index 0000000..f06193c
--- /dev/null
+++ b/patches/linux-3.8.13/0416-cape-LCD4-Correct-key-active-polarity.patch
@@ -0,0 +1,57 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 3 Jun 2013 15:59:04 +0300
+Subject: [PATCH] cape: LCD4: Correct key active polarity
+
+---
+ firmware/capes/BB-BONE-LCD4-01-00A1.dts | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A1.dts b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+index 2744c27..bd3c2a8 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A1.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+@@ -152,7 +152,7 @@
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+- gpios = <&gpio2 16 0x0>;
++ gpios = <&gpio2 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -160,7 +160,7 @@
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+- gpios = <&gpio2 17 0x0>;
++ gpios = <&gpio2 17 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -168,7 +168,7 @@
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+- gpios = <&gpio2 19 0x0>;
++ gpios = <&gpio2 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -176,7 +176,7 @@
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+- gpios = <&gpio4 16 0x0>;
++ gpios = <&gpio4 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -184,7 +184,7 @@
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+- gpios = <&gpio1 15 0x0>;
++ gpios = <&gpio1 15 0x1>;
+ gpio-key,wakeup;
+ };
+ };
diff --git a/patches/linux-3.8.13/0417-capes-lcd3-Correct-button-polarity.patch b/patches/linux-3.8.13/0417-capes-lcd3-Correct-button-polarity.patch
new file mode 100644
index 0000000..c0a8091
--- /dev/null
+++ b/patches/linux-3.8.13/0417-capes-lcd3-Correct-button-polarity.patch
@@ -0,0 +1,107 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 3 Jun 2013 16:42:22 +0300
+Subject: [PATCH] capes: lcd3: Correct button polarity
+
+---
+ firmware/capes/cape-bone-lcd3-00A0.dts | 10 +++++-----
+ firmware/capes/cape-bone-lcd3-00A2.dts | 10 +++++-----
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index ca31bc3..1ac8462 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -140,7 +140,7 @@
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+- gpios = <&gpio2 16 0x0>;
++ gpios = <&gpio2 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -148,7 +148,7 @@
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+- gpios = <&gpio2 17 0x0>;
++ gpios = <&gpio2 17 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -156,7 +156,7 @@
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+- gpios = <&gpio4 19 0x0>;
++ gpios = <&gpio4 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -164,7 +164,7 @@
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+- gpios = <&gpio2 28 0x0>;
++ gpios = <&gpio2 28 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -172,7 +172,7 @@
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+- gpios = <&gpio1 7 0x0>;
++ gpios = <&gpio1 7 0x1>;
+ gpio-key,wakeup;
+ };
+ };
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index ce72c17..9c7bb17 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -151,7 +151,7 @@
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+- gpios = <&gpio2 16 0x0>;
++ gpios = <&gpio2 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -159,7 +159,7 @@
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+- gpios = <&gpio2 17 0x0>;
++ gpios = <&gpio2 17 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -167,7 +167,7 @@
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+- gpios = <&gpio2 19 0x0>;
++ gpios = <&gpio2 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -175,7 +175,7 @@
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+- gpios = <&gpio4 16 0x0>;
++ gpios = <&gpio4 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -183,7 +183,7 @@
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+- gpios = <&gpio1 3 0x0>;
++ gpios = <&gpio1 3 0x1>;
+ gpio-key,wakeup;
+ };
+ };
diff --git a/patches/linux-3.8.13/0418-cape-Fix-LCD7-keys-polarity.patch b/patches/linux-3.8.13/0418-cape-Fix-LCD7-keys-polarity.patch
new file mode 100644
index 0000000..24638eb
--- /dev/null
+++ b/patches/linux-3.8.13/0418-cape-Fix-LCD7-keys-polarity.patch
@@ -0,0 +1,157 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 3 Jun 2013 18:19:12 +0300
+Subject: [PATCH] cape: Fix LCD7 keys polarity
+
+---
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 10 +++++-----
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 10 +++++-----
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 10 +++++-----
+ 3 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index dc31da7..d1eac3b 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -153,7 +153,7 @@
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+- gpios = <&gpio2 16 0x0>;
++ gpios = <&gpio2 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -161,7 +161,7 @@
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+- gpios = <&gpio2 17 0x0>;
++ gpios = <&gpio2 17 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -169,7 +169,7 @@
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+- gpios = <&gpio2 19 0x0>;
++ gpios = <&gpio2 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -177,7 +177,7 @@
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+- gpios = <&gpio4 16 0x0>;
++ gpios = <&gpio4 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -185,7 +185,7 @@
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+- gpios = <&gpio4 19 0x0>;
++ gpios = <&gpio4 19 0x1>;
+ gpio-key,wakeup;
+ };
+ };
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index 805a6c0..979fd73 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -153,7 +153,7 @@
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+- gpios = <&gpio2 16 0x0>;
++ gpios = <&gpio2 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -161,7 +161,7 @@
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+- gpios = <&gpio2 17 0x0>;
++ gpios = <&gpio2 17 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -169,7 +169,7 @@
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+- gpios = <&gpio2 19 0x0>;
++ gpios = <&gpio2 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -177,7 +177,7 @@
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+- gpios = <&gpio4 16 0x0>;
++ gpios = <&gpio4 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -185,7 +185,7 @@
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+- gpios = <&gpio1 3 0x0>;
++ gpios = <&gpio1 3 0x1>;
+ gpio-key,wakeup;
+ };
+ };
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+index e0a0677..6f34b79 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A4.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -132,7 +132,7 @@
+ debounce_interval = <50>;
+ linux,code = <105>;
+ label = "left";
+- gpios = <&gpio2 16 0x0>;
++ gpios = <&gpio2 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -140,7 +140,7 @@
+ debounce_interval = <50>;
+ linux,code = <106>;
+ label = "right";
+- gpios = <&gpio2 17 0x0>;
++ gpios = <&gpio2 17 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -148,7 +148,7 @@
+ debounce_interval = <50>;
+ linux,code = <103>;
+ label = "up";
+- gpios = <&gpio2 19 0x0>;
++ gpios = <&gpio2 19 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -156,7 +156,7 @@
+ debounce_interval = <50>;
+ linux,code = <108>;
+ label = "down";
+- gpios = <&gpio4 16 0x0>;
++ gpios = <&gpio4 16 0x1>;
+ gpio-key,wakeup;
+ autorepeat;
+ };
+@@ -164,7 +164,7 @@
+ debounce_interval = <50>;
+ linux,code = <28>;
+ label = "enter";
+- gpios = <&gpio1 3 0x0>;
++ gpios = <&gpio1 3 0x1>;
+ gpio-key,wakeup;
+ };
+ };
diff --git a/patches/linux-3.8.13/0419-gpio-Introduce-GPIO-OF-helper.patch b/patches/linux-3.8.13/0419-gpio-Introduce-GPIO-OF-helper.patch
new file mode 100644
index 0000000..049064a
--- /dev/null
+++ b/patches/linux-3.8.13/0419-gpio-Introduce-GPIO-OF-helper.patch
@@ -0,0 +1,470 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 4 Jun 2013 16:23:59 +0300
+Subject: [PATCH] gpio: Introduce GPIO OF helper
+
+A gpio OF helper driver that allows configuration to be done via
+DT.
+---
+ drivers/gpio/Kconfig | 14 ++
+ drivers/gpio/Makefile | 1 +
+ drivers/gpio/gpio-of-helper.c | 414 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 429 insertions(+)
+ create mode 100644 drivers/gpio/gpio-of-helper.c
+
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 682de75..6b5fc42 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -79,6 +79,20 @@ config GPIO_SYSFS
+ Kernel drivers may also request that a particular GPIO be
+ exported to userspace; this can be useful when debugging.
+
++config GPIO_OF_HELPER
++ bool "GPIO OF helper device"
++ depends on OF_GPIO && EXPERIMENTAL
++ help
++ Say Y here to add an GPIO OF helper driver
++
++ Allows you specify a GPIO helper based on OF
++ which allows simple export of GPIO functionality
++ in user-space.
++
++ Features include, value set/get, direction control,
++ interrupt/value change poll support, event counting
++ and others.
++
+ config GPIO_GENERIC
+ tristate
+
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+index c5aebd0..126e2cb 100644
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
+ obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o
+ obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
+ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
++obj-$(CONFIG_GPIO_OF_HELPER) += gpio-of-helper.o
+
+ # Device drivers. Generally keep list sorted alphabetically
+ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
+diff --git a/drivers/gpio/gpio-of-helper.c b/drivers/gpio/gpio-of-helper.c
+new file mode 100644
+index 0000000..16a607f
+--- /dev/null
++++ b/drivers/gpio/gpio-of-helper.c
+@@ -0,0 +1,414 @@
++/*
++ * GPIO OF based helper
++ *
++ * A simple DT based driver to provide access to GPIO functionality
++ * to user-space via sysfs.
++ *
++ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 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 <linux/interrupt.h>
++#include <linux/math64.h>
++#include <linux/atomic.h>
++#include <linux/idr.h>
++
++/* fwd decl. */
++struct gpio_of_helper_info;
++
++enum gpio_type {
++ GPIO_TYPE_INPUT = 0,
++ GPIO_TYPE_OUTPUT = 1,
++};
++
++struct gpio_of_entry {
++ int id;
++ struct gpio_of_helper_info *info;
++ struct device_node *node;
++ enum gpio_type type;
++ int gpio;
++ enum of_gpio_flags gpio_flags;
++ int irq;
++ const char *name;
++ atomic64_t counter;
++ unsigned int count_flags;
++#define COUNT_RISING_EDGE (1 << 0)
++#define COUNT_FALLING_EDGE (1 << 1)
++};
++
++struct gpio_of_helper_info {
++ struct platform_device *pdev;
++ struct idr idr;
++};
++
++static const struct of_device_id gpio_of_helper_of_match[] = {
++ {
++ .compatible = "gpio-of-helper",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, gpio_of_helper_of_match);
++
++static ssize_t gpio_of_helper_show_status(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct gpio_of_helper_info *info = platform_get_drvdata(pdev);
++ struct gpio_of_entry *entry;
++ char *p, *e;
++ int id, n;
++
++ p = buf;
++ e = p + PAGE_SIZE;
++ n = 0;
++ idr_for_each_entry(&info->idr, entry, id) {
++ switch (entry->type) {
++ case GPIO_TYPE_INPUT:
++ n = snprintf(p, e - p, "%2d %-24s %3d %-3s %llu\n",
++ entry->id, entry->name, entry->gpio, "IN",
++ (unsigned long long)
++ atomic64_read(&entry->counter));
++ break;
++ case GPIO_TYPE_OUTPUT:
++ n = snprintf(p, e - p, "%2d %-24s %3d %-3s\n",
++ entry->id, entry->name, entry->gpio, "OUT");
++ break;
++ }
++ p += n;
++ }
++
++ return p - buf;
++}
++
++static DEVICE_ATTR(status, S_IRUGO,
++ gpio_of_helper_show_status, NULL);
++
++static irqreturn_t gpio_of_helper_handler(int irq, void *ptr)
++{
++ struct gpio_of_entry *entry = ptr;
++
++ /* caution - low speed interfaces only! */
++ atomic64_inc(&entry->counter);
++
++ return IRQ_HANDLED;
++}
++
++static struct gpio_of_entry *
++gpio_of_entry_create(struct gpio_of_helper_info *info,
++ struct device_node *node)
++{
++ struct platform_device *pdev = info->pdev;
++ struct device *dev = &pdev->dev;
++ struct gpio_of_entry *entry;
++ int err, gpio, irq;
++ unsigned int req_flags, count_flags, irq_flags;
++ enum gpio_type type;
++ enum of_gpio_flags gpio_flags;
++ const char *name;
++
++ /* get the type of the node first */
++ if (of_property_read_bool(node, "input"))
++ type = GPIO_TYPE_INPUT;
++ else if (of_property_read_bool(node, "output"))
++ type = GPIO_TYPE_OUTPUT;
++ else {
++ dev_err(dev, "Not valid gpio node type\n");
++ err = -EINVAL;
++ goto err_bad_node;
++ }
++
++ /* get the name */
++ err = of_property_read_string(node, "gpio-name", &name);
++ if (err != 0) {
++ dev_err(dev, "Failed to get name property\n");
++ goto err_bad_node;
++ }
++
++ err = of_get_named_gpio_flags(node, "gpio", 0, &gpio_flags);
++ if (IS_ERR_VALUE(err)) {
++ dev_err(dev, "Failed to get gpio property of '%s'\n", name);
++ goto err_bad_node;
++ }
++ gpio = err;
++
++ req_flags = 0;
++ count_flags = 0;
++
++ /* set the request flags */
++ switch (type) {
++ case GPIO_TYPE_INPUT:
++ req_flags = GPIOF_DIR_IN | GPIOF_EXPORT;
++ if (of_property_read_bool(node, "count-falling-edge"))
++ count_flags |= COUNT_FALLING_EDGE;
++ if (of_property_read_bool(node, "count-rising-edge"))
++ count_flags |= COUNT_RISING_EDGE;
++ break;
++ case GPIO_TYPE_OUTPUT:
++ req_flags = GPIOF_DIR_OUT | GPIOF_EXPORT;
++ if (of_property_read_bool(node, "init-high"))
++ req_flags |= GPIOF_OUT_INIT_HIGH;
++ else if (of_property_read_bool(node, "init-low"))
++ req_flags |= GPIOF_OUT_INIT_LOW;
++ break;
++ }
++
++ /* request the gpio */
++ err = devm_gpio_request_one(dev, gpio, req_flags, name);
++ if (err != 0) {
++ dev_err(dev, "Failed to request gpio '%s'\n", name);
++ goto err_bad_node;
++ }
++
++ irq = -1;
++ irq_flags = 0;
++
++ /* counter mode requested - need an interrupt */
++ if (count_flags != 0) {
++ irq = gpio_to_irq(gpio);
++ if (IS_ERR_VALUE(irq)) {
++ dev_err(dev, "Failed to request gpio '%s'\n", name);
++ goto err_bad_node;
++ }
++
++ if (count_flags & COUNT_RISING_EDGE)
++ irq_flags |= IRQF_TRIGGER_RISING;
++ if (count_flags & COUNT_FALLING_EDGE)
++ irq_flags |= IRQF_TRIGGER_FALLING;
++ }
++
++ if (!idr_pre_get(&info->idr, GFP_KERNEL)) {
++ dev_err(dev, "Failed on idr_pre_get of '%s'\n", name);
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++
++ entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
++ if (entry == NULL) {
++ dev_err(dev, "Failed to allocate gpio entry of '%s'\n", name);
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++
++ entry->id = -1;
++ entry->info = info;
++ entry->node = of_node_get(node); /* get node reference */
++ entry->type = type;
++ entry->gpio = gpio;
++ entry->gpio_flags = gpio_flags;
++ entry->irq = irq;
++ entry->name = name;
++
++ /* interrupt enable is last thing done */
++ if (irq >= 0) {
++ atomic64_set(&entry->counter, 0);
++ entry->count_flags = count_flags;
++ err = devm_request_irq(dev, irq, gpio_of_helper_handler,
++ irq_flags, name, entry);
++ if (err != 0) {
++ dev_err(dev, "Failed to request irq of '%s'\n", name);
++ goto err_no_irq;
++ }
++ }
++
++ /* all done; insert */
++ err = idr_get_new(&info->idr, entry, &entry->id);
++ if (IS_ERR_VALUE(err)) {
++ dev_err(dev, "Failed to idr_get_new of '%s'\n", name);
++ goto err_fail_idr;
++ }
++
++ dev_info(dev, "Allocated GPIO id=%d\n", entry->id);
++
++ return entry;
++
++err_fail_idr:
++ /* nothing to do */
++err_no_irq:
++ /* release node ref */
++ of_node_put(node);
++ /* nothing else needs to be done, devres handles it */
++err_no_mem:
++err_bad_node:
++ return ERR_PTR(err);
++}
++
++static int gpio_of_entry_destroy(struct gpio_of_entry *entry)
++{
++ struct gpio_of_helper_info *info = entry->info;
++ struct platform_device *pdev = info->pdev;
++ struct device *dev = &pdev->dev;
++
++ dev_info(dev, "Destroying GPIO id=%d\n", entry->id);
++
++ /* remove from the IDR */
++ idr_remove(&info->idr, entry->id);
++
++ /* remove node ref */
++ of_node_put(entry->node);
++
++ /* free gpio */
++ devm_gpio_free(dev, entry->gpio);
++
++ /* gree irq */
++ if (entry->irq >= 0)
++ devm_free_irq(dev, entry->irq, entry);
++
++ /* and free */
++ devm_kfree(dev, entry);
++
++ return 0;
++}
++
++static int gpio_of_helper_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct gpio_of_helper_info *info;
++ struct gpio_of_entry *entry;
++ struct device_node *pnode = pdev->dev.of_node;
++ struct device_node *cnode;
++ struct pinctrl *pinctrl;
++ int err;
++
++ /* we only support OF */
++ if (pnode == NULL) {
++ dev_err(&pdev->dev, "No platform of_node!\n");
++ return -ENODEV;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl)) {
++ /* special handling for probe defer */
++ if (PTR_ERR(pinctrl) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++ }
++
++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate info\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ platform_set_drvdata(pdev, info);
++ info->pdev = pdev;
++
++ idr_init(&info->idr);
++
++ err = device_create_file(dev, &dev_attr_status);
++ if (err != 0) {
++ dev_err(dev, "Failed to create status sysfs attribute\n");
++ goto err_no_sysfs;
++ }
++
++ for_each_child_of_node(pnode, cnode) {
++
++ entry = gpio_of_entry_create(info, cnode);
++ if (IS_ERR_OR_NULL(entry)) {
++ dev_err(dev, "Failed to create gpio entry\n");
++ err = PTR_ERR(entry);
++ goto err_fail_entry;
++ }
++ }
++
++ dev_info(&pdev->dev, "ready\n");
++
++ return 0;
++err_fail_entry:
++ device_remove_file(&pdev->dev, &dev_attr_status);
++err_no_sysfs:
++err_no_mem:
++ return err;
++}
++
++static int gpio_of_helper_remove(struct platform_device *pdev)
++{
++ struct gpio_of_helper_info *info = platform_get_drvdata(pdev);
++ struct gpio_of_entry *entry;
++ int id;
++
++ dev_info(&pdev->dev, "removing\n");
++
++ device_remove_file(&pdev->dev, &dev_attr_status);
++
++ id = 0;
++ idr_for_each_entry(&info->idr, entry, id) {
++ /* destroy each and every one */
++ gpio_of_entry_destroy(entry);
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++#ifdef CONFIG_PM_RUNTIME
++static int gpio_of_helper_runtime_suspend(struct device *dev)
++{
++ /* place holder */
++ return 0;
++}
++
++static int gpio_of_helper_runtime_resume(struct device *dev)
++{
++ /* place holder */
++ return 0;
++}
++#endif /* CONFIG_PM_RUNTIME */
++
++static struct dev_pm_ops gpio_of_helper_pm_ops = {
++ SET_RUNTIME_PM_OPS(gpio_of_helper_runtime_suspend,
++ gpio_of_helper_runtime_resume, NULL)
++};
++#define GPIO_OF_HELPER_PM_OPS (&gpio_of_helper_pm_ops)
++#else
++#define GPIO_OF_HELPER_PM_OPS NULL
++#endif /* CONFIG_PM */
++
++struct platform_driver gpio_of_helper_driver = {
++ .probe = gpio_of_helper_probe,
++ .remove = gpio_of_helper_remove,
++ .driver = {
++ .name = "gpio-of-helper",
++ .owner = THIS_MODULE,
++ .pm = GPIO_OF_HELPER_PM_OPS,
++ .of_match_table = gpio_of_helper_of_match,
++ },
++};
++
++module_platform_driver(gpio_of_helper_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
++MODULE_DESCRIPTION("GPIO OF Helper driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:gpio-of-helper");
diff --git a/patches/linux-3.8.13/0420-capes-ADC-GPIO-helper-capes.patch b/patches/linux-3.8.13/0420-capes-ADC-GPIO-helper-capes.patch
new file mode 100644
index 0000000..538b89b
--- /dev/null
+++ b/patches/linux-3.8.13/0420-capes-ADC-GPIO-helper-capes.patch
@@ -0,0 +1,168 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 4 Jun 2013 16:25:24 +0300
+Subject: [PATCH] capes: ADC & GPIO helper capes
+
+---
+ firmware/Makefile | 8 +++++
+ firmware/capes/BB-ADC-00A0.dts | 59 +++++++++++++++++++++++++++++++
+ firmware/capes/BB-GPIOHELP-00A0.dts | 66 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 133 insertions(+)
+ create mode 100644 firmware/capes/BB-ADC-00A0.dts
+ create mode 100644 firmware/capes/BB-GPIOHELP-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 6d896d2..d82fb9b 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -217,6 +217,14 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-SPI0-00A0.dtbo BB-SPI1-00A0.dtbo BB-SPI1A1-00A0.dtbo
+
++# the virtual peripheral capes for ADC
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ BB-ADC-00A0.dtbo
++
++# the virtual peripheral capes for GPIO
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ BB-GPIOHELP-00A0.dtbo
++
+ # PRU firmware
+ #fw-shipped-$(CONFIG_PRU_RPROC) += \
+ # prutest.bin
+diff --git a/firmware/capes/BB-ADC-00A0.dts b/firmware/capes/BB-ADC-00A0.dts
+new file mode 100644
+index 0000000..88f6fc6
+--- /dev/null
++++ b/firmware/capes/BB-ADC-00A0.dts
+@@ -0,0 +1,59 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-ADC";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.39", /* AIN0 */
++ "P9.40", /* AIN1 */
++ "P9.37", /* AIN2 */
++ "P9.38", /* AIN3 */
++ "P9.33", /* AIN4 */
++ "P9.36", /* AIN5 */
++ "P9.35", /* AIN6 */
++ /* the hardware IP uses */
++ "tscadc";
++
++ fragment@0 {
++ target = <&ocp>;
++ __overlay__ {
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ adc {
++ ti,adc-channels = <0 1 2 3 4 5 6 7>;
++ };
++ };
++
++ test_helper: helper {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ vsense-scale = <100 100 100 100 100 100 100 100>;
++ status = "okay";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-GPIOHELP-00A0.dts b/firmware/capes/BB-GPIOHELP-00A0.dts
+new file mode 100644
+index 0000000..d7e0b4b
+--- /dev/null
++++ b/firmware/capes/BB-GPIOHELP-00A0.dts
+@@ -0,0 +1,66 @@
++/*
++* Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-PRU-01";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.27", /* gpio */
++ "P9.28", /* gpio */
++ /* the hardware IP uses */
++ "gpio3_19", "gpio3_17";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ gpio_helper_pins: pinmux_gpio_helper_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x0f /* P9 27 GPIO3_19: mcasp0_fsr.gpio3_19 | MODE7 | OUTPUT */
++ 0x19c 0x2f /* P9 28 SPI1_CS0: mcasp0_ahclkr.gpio3_17 | MODE7 | INPUT */
++ >;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++
++ gpio_helper {
++ compatible = "gpio-of-helper";
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpio_helper_pins>;
++
++ /* declare your gpios */
++ test_led {
++ gpio-name = "test_led";
++ gpio = <&gpio4 19 0x00>; /* gpio4 is gpio3 */
++ output;
++ init-high;
++ };
++
++ test_input {
++ gpio-name = "test_input";
++ gpio = <&gpio4 17 0x00>; /* gpio4 is gpio3 */
++ input;
++ count-rising-edge;
++ count-falling-edge;
++ };
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0421-capes-RS232-Cape-support-added.patch b/patches/linux-3.8.13/0421-capes-RS232-Cape-support-added.patch
new file mode 100644
index 0000000..d075339
--- /dev/null
+++ b/patches/linux-3.8.13/0421-capes-RS232-Cape-support-added.patch
@@ -0,0 +1,81 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Jun 2013 19:06:09 +0300
+Subject: [PATCH] capes: RS232 Cape support added
+
+Add support for the default configuration of the cape at UART2.
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/BB-BONE-SERL-03-00A1.dts | 50 +++++++++++++++++++++++++++++++
+ 2 files changed, 52 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-SERL-03-00A1.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index d82fb9b..0727ec9 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -183,7 +183,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-RST-00A0.dtbo \
+ BB-BONE-RST2-00A0.dtbo \
+ BB-BONE-CAM3-01-00A2.dtbo \
+- TT3201-001-01.dtbo
++ TT3201-001-01.dtbo \
++ BB-BONE-SERL-03-00A1.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-SERL-03-00A1.dts b/firmware/capes/BB-BONE-SERL-03-00A1.dts
+new file mode 100644
+index 0000000..47d9890
+--- /dev/null
++++ b/firmware/capes/BB-BONE-SERL-03-00A1.dts
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2013 CircuitCo
++ *
++ * RS232 cape for the default configuration on UART2
++ * Use one of the BB-UART* examples if you modify the default
++ * configuration.
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-SERL-03";
++ version = "00A1";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.21", /* uart2_txd */
++ "P9.22", /* uart2_rxd */
++ /* the hardware ip uses */
++ "uart2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ bb_uart2_pins: pinmux_bb_uart2_pins {
++ pinctrl-single,pins = <
++ 0x150 0x21 /* spi0_sclk.uart2_rxd | MODE1 */
++ 0x154 0x01 /* spi0_d0.uart2_txd | MODE1 */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&uart3>; /* really uart2 */
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bb_uart2_pins>;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0422-uio-uio_pruss-port-to-AM33xx.patch b/patches/linux-3.8.13/0422-uio-uio_pruss-port-to-AM33xx.patch
new file mode 100644
index 0000000..aa081fc
--- /dev/null
+++ b/patches/linux-3.8.13/0422-uio-uio_pruss-port-to-AM33xx.patch
@@ -0,0 +1,189 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Thu, 17 Jan 2013 16:02:47 -0800
+Subject: [PATCH] uio: uio_pruss: port to AM33xx
+
+Add ifdefery hacks to only use SRAM on Davinci. This
+needs to be cleaned up with a sane generic SRAM allocator
+(like the DT based driver available that can't be used on
+Davinci which is just starting DT conversion) before it
+can go upstream.
+
+Adds DT, pinctrl, and runtime PM support for use on
+AM33xx.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/uio/Kconfig | 4 ++--
+ drivers/uio/uio_pruss.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 61 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
+index f56d185..a991a08 100644
+--- a/drivers/uio/Kconfig
++++ b/drivers/uio/Kconfig
+@@ -112,10 +112,10 @@ config UIO_NETX
+
+ config UIO_PRUSS
+ tristate "Texas Instruments PRUSS driver"
+- depends on ARCH_DAVINCI_DA850
++ depends on ARCH_DAVINCI_DA850 || SOC_AM33XX
+ select GENERIC_ALLOCATOR
+ help
+- PRUSS driver for OMAPL138/DA850/AM18XX devices
++ PRUSS driver for OMAPL138/DA850/AM18XX and AM33XX devices
+ PRUSS driver requires user space components, examples and user space
+ driver is available from below SVN repo - you may use anonymous login
+
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 6e2ab00..2bb1d7a 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -26,6 +26,11 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/slab.h>
+ #include <linux/genalloc.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
++#include <linux/pm_runtime.h>
+
+ #define DRV_NAME "pruss_uio"
+ #define DRV_VERSION "1.0"
+@@ -106,10 +111,12 @@ static void pruss_cleanup(struct platform_device *dev,
+ dma_free_coherent(&dev->dev, extram_pool_sz, gdev->ddr_vaddr,
+ gdev->ddr_paddr);
+ }
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ if (gdev->sram_vaddr)
+ gen_pool_free(gdev->sram_pool,
+ gdev->sram_vaddr,
+ sram_pool_sz);
++#endif
+ kfree(gdev->info);
+ clk_put(gdev->pruss_clk);
+ kfree(gdev);
+@@ -120,8 +127,10 @@ static int pruss_probe(struct platform_device *dev)
+ struct uio_info *p;
+ struct uio_pruss_dev *gdev;
+ struct resource *regs_prussio;
++ struct resource res;
+ int ret = -ENODEV, cnt = 0, len;
+ struct uio_pruss_pdata *pdata = dev->dev.platform_data;
++ struct pinctrl *pinctrl;
+
+ gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
+ if (!gdev)
+@@ -132,6 +141,7 @@ static int pruss_probe(struct platform_device *dev)
+ kfree(gdev);
+ return -ENOMEM;
+ }
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ /* Power on PRU in case its not done as part of boot-loader */
+ gdev->pruss_clk = clk_get(&dev->dev, "pruss");
+ if (IS_ERR(gdev->pruss_clk)) {
+@@ -143,6 +153,28 @@ static int pruss_probe(struct platform_device *dev)
+ } else {
+ clk_enable(gdev->pruss_clk);
+ }
++#endif
++
++ if (dev->dev.of_node) {
++ pm_runtime_enable(&dev->dev);
++ ret = pm_runtime_get_sync(&dev->dev);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(&dev->dev, "pm_runtime_get_sync() failed\n");
++ return ret;
++ }
++
++ ret = of_address_to_resource(dev->dev.of_node, 0, &res);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(&dev->dev, "failed to parse DT reg\n");
++ return ret;
++ }
++ regs_prussio = &res;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&dev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&dev->dev,
++ "pins are not configured from the driver\n");
+
+ regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!regs_prussio) {
+@@ -157,12 +189,14 @@ static int pruss_probe(struct platform_device *dev)
+
+ if (pdata->sram_pool) {
+ gdev->sram_pool = pdata->sram_pool;
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ gdev->sram_vaddr =
+ gen_pool_alloc(gdev->sram_pool, sram_pool_sz);
+ if (!gdev->sram_vaddr) {
+ dev_err(&dev->dev, "Could not allocate SRAM pool\n");
+ goto out_free;
+ }
++#endif
+ gdev->sram_paddr =
+ gen_pool_virt_to_phys(gdev->sram_pool,
+ gdev->sram_vaddr);
+@@ -182,7 +216,17 @@ static int pruss_probe(struct platform_device *dev)
+ goto out_free;
+ }
+
+- gdev->pintc_base = pdata->pintc_base;
++ if (dev->dev.of_node) {
++ ret = of_property_read_u32(dev->dev.of_node,
++ "ti,pintc-offset",
++ &gdev->pintc_base);
++ if (ret < 0) {
++ dev_err(&dev->dev,
++ "Can't parse ti,pintc-offset property\n");
++ goto out_free;
++ }
++ } else
++ gdev->pintc_base = pdata->pintc_base;
+ gdev->hostirq_start = platform_get_irq(dev, 0);
+
+ for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+@@ -190,6 +234,7 @@ static int pruss_probe(struct platform_device *dev)
+ p->mem[0].size = resource_size(regs_prussio);
+ p->mem[0].memtype = UIO_MEM_PHYS;
+
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ p->mem[1].addr = gdev->sram_paddr;
+ p->mem[1].size = sram_pool_sz;
+ p->mem[1].memtype = UIO_MEM_PHYS;
+@@ -197,6 +242,11 @@ static int pruss_probe(struct platform_device *dev)
+ p->mem[2].addr = gdev->ddr_paddr;
+ p->mem[2].size = extram_pool_sz;
+ p->mem[2].memtype = UIO_MEM_PHYS;
++#else
++ p->mem[1].addr = gdev->ddr_paddr;
++ p->mem[1].size = extram_pool_sz;
++ p->mem[1].memtype = UIO_MEM_PHYS;
++#endif
+
+ p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
+ p->version = DRV_VERSION;
+@@ -228,12 +278,20 @@ static int pruss_remove(struct platform_device *dev)
+ return 0;
+ }
+
++static const struct of_device_id pruss_dt_ids[] = {
++ { .compatible = "ti,pruss-v1", .data = NULL, },
++ { .compatible = "ti,pruss-v2", .data = NULL, },
++ {},
++};
++MODULE_DEVICE_TABLE(of, pruss_dt_ids);
++
+ static struct platform_driver pruss_driver = {
+ .probe = pruss_probe,
+ .remove = pruss_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
++ .of_match_table = pruss_dt_ids,
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0423-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch b/patches/linux-3.8.13/0423-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch
new file mode 100644
index 0000000..700d47a
--- /dev/null
+++ b/patches/linux-3.8.13/0423-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch
@@ -0,0 +1,94 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Thu, 17 Jan 2013 16:02:48 -0800
+Subject: [PATCH] ARM: omap: add DT support for deasserting hardware reset
+ lines
+
+ This optional binding extension allows specification of a hwmod
+ and associate hardware reset line which should be deasserted for
+ the device to be functional.
+
+ The implementation works for reference as to the problem that
+ exists for utilizing uio_pruss on AM33xx but is suboptimal. The
+ problem is that this deassertion occurs before clocks are enabled
+ and we are warned that the hard reset failed. Ideally the list of
+ rst lines requested to be deasserted would be cached and used within
+ the hwmod enable sequencing (instead of it just returning if any
+ hardware reset line is asserted).
+
+ Signed-off-by: Matt Porter <mporter@ti.com>
+ Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ .../devicetree/bindings/arm/omap/omap.txt | 2 ++
+ arch/arm/mach-omap2/omap_device.c | 25 ++++++++++++++++++--
+ drivers/uio/uio_pruss.c | 2 +-
+ 3 files changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
+index d0051a7..3133a4b 100644
+--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
++++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
+@@ -21,6 +21,8 @@ Required properties:
+ Optional properties:
+ - ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+ during suspend.
++- ti,deassert-hard-reset: list of hwmod and hardware reset line name pairs
++ (ascii strings) to be deasserted upon device instantiation.
+
+
+ Example:
+diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
+index 0d7b065..2cf12c1 100644
+--- a/arch/arm/mach-omap2/omap_device.c
++++ b/arch/arm/mach-omap2/omap_device.c
+@@ -329,8 +329,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
+ struct omap_device *od;
+ struct omap_hwmod *oh;
+ struct device_node *node = pdev->dev.of_node;
+- const char *oh_name;
+- int oh_cnt, i, ret = 0;
++ const char *oh_name, *rst_name;
++ int oh_cnt, dstr_cnt, i, ret = 0;
+
+ oh_cnt = of_property_count_strings(node, "ti,hwmods");
+ if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+@@ -375,6 +375,27 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
+ if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
+ omap_device_disable_idle_on_suspend(pdev);
+
++ dstr_cnt =
++ of_property_count_strings(node, "ti,deassert-hard-reset");
++ if (dstr_cnt > 0) {
++ for (i = 0; i < dstr_cnt; i += 2) {
++ of_property_read_string_index(
++ node, "ti,deassert-hard-reset", i,
++ &oh_name);
++ of_property_read_string_index(
++ node, "ti,deassert-hard-reset", i+1,
++ &rst_name);
++ oh = omap_hwmod_lookup(oh_name);
++ if (!oh) {
++ dev_warn(&pdev->dev,
++ "Cannot parse deassert property for '%s'\n",
++ oh_name);
++ break;
++ }
++ omap_hwmod_deassert_hardreset(oh, rst_name);
++ }
++ }
++
+ pdev->dev.pm_domain = &omap_device_pm_domain;
+
+ odbfd_exit1:
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 2bb1d7a..563a337 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -187,7 +187,7 @@ static int pruss_probe(struct platform_device *dev)
+ goto out_free;
+ }
+
+- if (pdata->sram_pool) {
++ if (pdata && pdata->sram_pool) {
+ gdev->sram_pool = pdata->sram_pool;
+ #ifdef CONFIG_ARCH_DAVINCI_DA850
+ gdev->sram_vaddr =
diff --git a/patches/linux-3.8.13/0424-ARM-dts-AM33xx-PRUSS-support.patch b/patches/linux-3.8.13/0424-ARM-dts-AM33xx-PRUSS-support.patch
new file mode 100644
index 0000000..144f5d8
--- /dev/null
+++ b/patches/linux-3.8.13/0424-ARM-dts-AM33xx-PRUSS-support.patch
@@ -0,0 +1,34 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Thu, 17 Jan 2013 16:02:49 -0800
+Subject: [PATCH] ARM: dts: AM33xx PRUSS support
+
+Adds a pruss node and an example of use on Beaglebone.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 9bf0d2c..5d4f913 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -347,6 +347,17 @@
+ ti,timer-pwm;
+ };
+
++ pruss: pruss@4a300000 {
++ compatible = "ti,pruss-v2";
++ ti,hwmods = "pruss";
++ ti,deassert-hard-reset = "pruss", "pruss";
++ reg = <0x4a300000 0x080000>;
++ ti,pintc-offset = <0x20000>;
++ interrupt-parent = <&intc>;
++ status = "disabled";
++ interrupts = <20 21 22 23 24 25 26 27>;
++ };
++
+ rtc@44e3e000 {
+ compatible = "ti,da830-rtc";
+ reg = <0x44e3e000 0x1000>;
diff --git a/patches/linux-3.8.13/0425-uio_pruss-add-dt-support-replicape-00A1.patch b/patches/linux-3.8.13/0425-uio_pruss-add-dt-support-replicape-00A1.patch
new file mode 100644
index 0000000..7cdb706
--- /dev/null
+++ b/patches/linux-3.8.13/0425-uio_pruss-add-dt-support-replicape-00A1.patch
@@ -0,0 +1,75 @@
+From: Elias Bakken <elias.bakken@gmail.com>
+Date: Thu, 4 Apr 2013 11:38:53 -0500
+Subject: [PATCH] uio_pruss: add dt support (replicape-00A1)
+
+Signed-off-by: Elias Bakken <elias.bakken@gmail.com>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/uio/uio_pruss.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 563a337..6f49ea1 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -19,6 +19,7 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/platform_device.h>
++#include <linux/of_gpio.h>
+ #include <linux/uio_driver.h>
+ #include <linux/platform_data/uio_pruss.h>
+ #include <linux/io.h>
+@@ -132,6 +133,10 @@ static int pruss_probe(struct platform_device *dev)
+ struct uio_pruss_pdata *pdata = dev->dev.platform_data;
+ struct pinctrl *pinctrl;
+
++ int count;
++ struct device_node *child;
++ const char *pin_name;
++
+ gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
+ if (!gdev)
+ return -ENOMEM;
+@@ -175,6 +180,41 @@ static int pruss_probe(struct platform_device *dev)
+ if (IS_ERR(pinctrl))
+ dev_warn(&dev->dev,
+ "pins are not configured from the driver\n");
++ else{
++ count = of_get_child_count(dev->dev.of_node);
++ if (!count){
++ dev_info(&dev->dev, "No children\n");
++ return -ENODEV;
++ }
++ // Run through all children. They have lables for easy reference.
++ for_each_child_of_node(dev->dev.of_node, child){
++ enum of_gpio_flags flags;
++ unsigned gpio;
++
++ count = of_gpio_count(child);
++
++ ret = of_property_count_strings(child, "pin-names");
++ if (ret < 0) {
++ dev_err(&dev->dev, "Failed to get pin-names\n");
++ continue;
++ }
++ if(count != ret){
++ dev_err(&dev->dev, "The number of gpios (%d) does not match"\
++ " the number of pin names (%d)\n", count, ret);
++ continue;
++ }
++
++ dev_dbg(&dev->dev, "Child has %u gpios\n", count);
++ for(cnt=0; cnt<count; cnt++){
++ ret = of_property_read_string_index(child,
++ "pin-names", cnt, &pin_name);
++ if (ret != 0)
++ dev_err(&dev->dev, "Error on pin-name #%d\n", cnt);
++ gpio = of_get_gpio_flags(child, cnt, &flags);
++ ret = devm_gpio_request_one(&dev->dev, gpio, flags, pin_name);
++ }
++ }
++ }
+
+ regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!regs_prussio) {
diff --git a/patches/linux-3.8.13/0426-pruss-Make-sure-it-works-when-no-child-nodes-are-pre.patch b/patches/linux-3.8.13/0426-pruss-Make-sure-it-works-when-no-child-nodes-are-pre.patch
new file mode 100644
index 0000000..55e1baa
--- /dev/null
+++ b/patches/linux-3.8.13/0426-pruss-Make-sure-it-works-when-no-child-nodes-are-pre.patch
@@ -0,0 +1,79 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 15 May 2013 20:44:34 +0300
+Subject: [PATCH] pruss: Make sure it works when no child nodes are present
+
+Pruss shouldn't fail when no child nodes are present.
+---
+ drivers/uio/uio_pruss.c | 58 +++++++++++++++++++++--------------------------
+ 1 file changed, 26 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 6f49ea1..5de4f11 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -180,39 +180,33 @@ static int pruss_probe(struct platform_device *dev)
+ if (IS_ERR(pinctrl))
+ dev_warn(&dev->dev,
+ "pins are not configured from the driver\n");
+- else{
+- count = of_get_child_count(dev->dev.of_node);
+- if (!count){
+- dev_info(&dev->dev, "No children\n");
+- return -ENODEV;
++
++ // Run through all children. They have lables for easy reference.
++ for_each_child_of_node(dev->dev.of_node, child) {
++ enum of_gpio_flags flags;
++ unsigned gpio;
++
++ count = of_gpio_count(child);
++
++ ret = of_property_count_strings(child, "pin-names");
++ if (ret < 0) {
++ dev_err(&dev->dev, "Failed to get pin-names\n");
++ continue;
++ }
++ if(count != ret){
++ dev_err(&dev->dev, "The number of gpios (%d) does not match"\
++ " the number of pin names (%d)\n", count, ret);
++ continue;
+ }
+- // Run through all children. They have lables for easy reference.
+- for_each_child_of_node(dev->dev.of_node, child){
+- enum of_gpio_flags flags;
+- unsigned gpio;
+-
+- count = of_gpio_count(child);
+-
+- ret = of_property_count_strings(child, "pin-names");
+- if (ret < 0) {
+- dev_err(&dev->dev, "Failed to get pin-names\n");
+- continue;
+- }
+- if(count != ret){
+- dev_err(&dev->dev, "The number of gpios (%d) does not match"\
+- " the number of pin names (%d)\n", count, ret);
+- continue;
+- }
+-
+- dev_dbg(&dev->dev, "Child has %u gpios\n", count);
+- for(cnt=0; cnt<count; cnt++){
+- ret = of_property_read_string_index(child,
+- "pin-names", cnt, &pin_name);
+- if (ret != 0)
+- dev_err(&dev->dev, "Error on pin-name #%d\n", cnt);
+- gpio = of_get_gpio_flags(child, cnt, &flags);
+- ret = devm_gpio_request_one(&dev->dev, gpio, flags, pin_name);
+- }
++
++ dev_dbg(&dev->dev, "Child has %u gpios\n", count);
++ for(cnt=0; cnt<count; cnt++){
++ ret = of_property_read_string_index(child,
++ "pin-names", cnt, &pin_name);
++ if (ret != 0)
++ dev_err(&dev->dev, "Error on pin-name #%d\n", cnt);
++ gpio = of_get_gpio_flags(child, cnt, &flags);
++ ret = devm_gpio_request_one(&dev->dev, gpio, flags, pin_name);
+ }
+ }
+
diff --git a/patches/linux-3.8.13/0427-am33xx-pru-Very-simple-led-cape-via-GPO-of-the-PRU.patch b/patches/linux-3.8.13/0427-am33xx-pru-Very-simple-led-cape-via-GPO-of-the-PRU.patch
new file mode 100644
index 0000000..53091f3
--- /dev/null
+++ b/patches/linux-3.8.13/0427-am33xx-pru-Very-simple-led-cape-via-GPO-of-the-PRU.patch
@@ -0,0 +1,76 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 14 May 2013 14:18:47 +0300
+Subject: [PATCH] am33xx: pru: Very simple led cape via GPO of the PRU
+
+Simple cape definition for a cape that works on all beaglebones
+---
+ firmware/Makefile | 3 ++-
+ firmware/capes/BB-BONE-PRU-01-00A0.dts | 45 ++++++++++++++++++++++++++++++++
+ 2 files changed, 47 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-PRU-01-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 0727ec9..1a353ce 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -184,7 +184,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-RST2-00A0.dtbo \
+ BB-BONE-CAM3-01-00A2.dtbo \
+ TT3201-001-01.dtbo \
+- BB-BONE-SERL-03-00A1.dtbo
++ BB-BONE-SERL-03-00A1.dtbo \
++ BB-BONE-PRU-01-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-PRU-01-00A0.dts b/firmware/capes/BB-BONE-PRU-01-00A0.dts
+new file mode 100644
+index 0000000..29ab671
+--- /dev/null
++++ b/firmware/capes/BB-BONE-PRU-01-00A0.dts
+@@ -0,0 +1,45 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-PRU-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ pru_gpio_pins: pinmux_pru_gpio_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x0f /* P9 27 GPIO3_19: mcasp0_fsr.gpio3[19] | MODE7 | OUTPUT */
++ >;
++ };
++
++ pru_pru_pins: pinmux_pru_pru_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x25 /* mcasp0_fsr.pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU */
++ >;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&pruss>;
++ __overlay__ {
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pru_pru_pins>;
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0428-PRU-remote-proc-wip.patch b/patches/linux-3.8.13/0428-PRU-remote-proc-wip.patch
new file mode 100644
index 0000000..45f00be
--- /dev/null
+++ b/patches/linux-3.8.13/0428-PRU-remote-proc-wip.patch
@@ -0,0 +1,355 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 16 May 2013 10:37:39 +0300
+Subject: [PATCH] PRU remote proc wip
+
+---
+ drivers/remoteproc/Kconfig | 11 ++
+ drivers/remoteproc/Makefile | 1 +
+ drivers/remoteproc/pru_rproc.c | 240 ++++++++++++++++++++++++++++++++
+ firmware/capes/BB-BONE-PRU-02-00A0.dts | 61 ++++++++
+ 4 files changed, 313 insertions(+)
+ create mode 100644 drivers/remoteproc/pru_rproc.c
+ create mode 100644 firmware/capes/BB-BONE-PRU-02-00A0.dts
+
+diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
+index a936efb..690097b 100644
+--- a/drivers/remoteproc/Kconfig
++++ b/drivers/remoteproc/Kconfig
+@@ -41,4 +41,15 @@ config STE_MODEM_RPROC
+ This can be either built-in or a loadable module.
+ If unsure say N.
+
++config PRU_RPROC
++ tristate "AM33xx PRU remoteproc support"
++ depends on EXPERIMENTAL
++ depends on HAS_DMA && SOC_AM33XX
++ select REMOTEPROC
++ default n
++ help
++ Say y or m here to support AM33xx PRU
++ This can be either built-in or a loadable module.
++ If unsure say N.
++
+ endmenu
+diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
+index 391b651..9042660 100644
+--- a/drivers/remoteproc/Makefile
++++ b/drivers/remoteproc/Makefile
+@@ -9,3 +9,4 @@ remoteproc-y += remoteproc_virtio.o
+ remoteproc-y += remoteproc_elf_loader.o
+ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o
+ obj-$(CONFIG_STE_MODEM_RPROC) += ste_modem_rproc.o
++obj-$(CONFIG_PRU_RPROC) += pru_rproc.o
+diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
+new file mode 100644
+index 0000000..113ad80
+--- /dev/null
++++ b/drivers/remoteproc/pru_rproc.c
+@@ -0,0 +1,240 @@
++/*
++ * PRU driver for TI's AM33xx series of SoCs
++ *
++ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include <linux/module.h>
++#include <linux/err.h>
++#include <linux/dma-mapping.h>
++#include <linux/remoteproc.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/genalloc.h>
++#include <linux/of.h>
++#include <linux/of_platform.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/io.h>
++
++#include "remoteproc_internal.h"
++
++/* PRU control structure */
++struct pruproc {
++ struct rproc *rproc;
++ struct platform_device *pdev;
++ struct resource_table *table;
++ void __iomem *vaddr;
++ dma_addr_t paddr;
++};
++
++/* Loads the firmware to shared memory. */
++static int pruproc_load_segments(struct rproc *rproc, const struct firmware *fw)
++{
++ struct pruproc *pruproc = rproc->priv;
++
++ dev_dbg(&pruproc->pdev->dev, "%s\n", __func__);
++
++ return 0;
++}
++
++/* Find the resource table inside the remote processor's firmware. */
++static struct resource_table *
++pruproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
++ int *tablesz)
++{
++ struct pruproc *pruproc = rproc->priv;
++ struct resource_table *table;
++
++ table = devm_kzalloc(&pruproc->pdev->dev, sizeof(*table), GFP_KERNEL);
++
++ dev_dbg(&pruproc->pdev->dev, "%s\n", __func__);
++
++ return table;
++}
++
++static int pruproc_sanity_check(struct rproc *rproc, const struct firmware *fw)
++{
++ return 0;
++}
++
++/* PRU firmware handler operations */
++const struct rproc_fw_ops pruproc_fw_ops = {
++ .find_rsc_table = pruproc_find_rsc_table,
++ .load = pruproc_load_segments,
++ .sanity_check = pruproc_sanity_check,
++};
++
++/* Kick the modem with specified notification id */
++static void pruproc_kick(struct rproc *rproc, int vqid)
++{
++ struct pruproc *pruproc = rproc->priv;
++
++ dev_dbg(&pruproc->pdev->dev, "kick vqid:%d\n", vqid);
++}
++
++/* Start the PRU modem */
++static int pruproc_start(struct rproc *rproc)
++{
++ struct pruproc *pruproc = rproc->priv;
++
++ dev_dbg(&pruproc->pdev->dev, "start pru\n");
++
++ return 0;
++}
++
++/* Stop the PRU modem */
++static int pruproc_stop(struct rproc *rproc)
++{
++ struct pruproc *pruproc = rproc->priv;
++
++ dev_dbg(&pruproc->pdev->dev, "stop PRU\n");
++
++ return 0;
++}
++
++static struct rproc_ops pruproc_ops = {
++ .start = pruproc_start,
++ .stop = pruproc_stop,
++ .kick = pruproc_kick,
++};
++
++/* PRU is unregistered */
++static int pruproc_remove(struct platform_device *pdev)
++{
++ struct pruproc *pruproc = platform_get_drvdata(pdev);
++
++ dev_dbg(&pdev->dev, "remove pru\n");
++
++ /* Unregister as remoteproc device */
++ rproc_del(pruproc->rproc);
++ rproc_put(pruproc->rproc);
++
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++/* Handle probe of a modem device */
++static int pruproc_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct pruproc *pruproc;
++ struct rproc *rproc;
++ struct resource *res;
++ struct pinctrl *pinctrl;
++ int err;
++
++ dev_dbg(dev, "probe pru\n");
++
++ /* get pinctrl */
++ pinctrl = devm_pinctrl_get_select_default(dev);
++ if (IS_ERR(pinctrl)) {
++ err = PTR_ERR(pinctrl);
++ /* deferring probe */
++ if (err == -EPROBE_DEFER) {
++ dev_warn(dev, "deferring proble\n");
++ return err;
++ }
++ dev_warn(dev, "pins are not configured from the driver\n");
++ }
++
++ /* we only work on OF */
++ if (dev->of_node == NULL) {
++ dev_err(dev, "Only OF configuration supported\n");
++ err = -ENODEV;
++ goto fail_of_node;
++ }
++
++ pm_runtime_enable(dev);
++ err = pm_runtime_get_sync(dev);
++ if (err != 0) {
++ dev_err(dev, "pm_runtime_get_sync failed\n");
++ goto fail_pm_runtime_get_sync;
++ }
++
++ err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
++ if (err) {
++ dev_err(dev, "dma_set_coherent_mask: %d\n", err);
++ goto fail_dma_set_coherent_mask;
++ }
++
++ rproc = rproc_alloc(dev, pdev->name, &pruproc_ops,
++ "prutest.bin", sizeof(*pruproc));
++ if (!rproc) {
++ dev_err(dev, "rproc_alloc failed\n");
++ err = -ENOMEM;
++ goto fail_rproc_alloc;
++ }
++
++ pruproc = rproc->priv;
++ pruproc->pdev = pdev;
++ pruproc->rproc = rproc;
++
++ platform_set_drvdata(pdev, pruproc);
++
++ /* Set the PRU specific firmware handler */
++ rproc->fw_ops = &pruproc_fw_ops;
++
++ /* Register as a remoteproc device */
++ err = rproc_add(rproc);
++ if (err) {
++ dev_err(dev, "rproc_add failed\n");
++ goto fail_rproc_add;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(dev, "failed to parse MEM resource\n");
++ goto fail_platform_get_resource;
++ }
++
++ pruproc->vaddr = devm_ioremap(dev, res->start, resource_size(res));
++ if (pruproc->vaddr == NULL) {
++ dev_err(dev, "failed to parse MEM resource\n");
++ goto fail_devm_ioremap;
++ }
++
++ dev_info(dev, "Loaded OK\n");
++
++ return 0;
++fail_devm_ioremap:
++fail_platform_get_resource:
++ rproc_del(rproc);
++fail_rproc_add:
++ platform_set_drvdata(pdev, NULL);
++ rproc_put(rproc);
++fail_rproc_alloc:
++fail_dma_set_coherent_mask:
++fail_of_node:
++ pm_runtime_disable(dev);
++fail_pm_runtime_get_sync:
++ return err;
++}
++
++static const struct of_device_id pru_rproc_dt_ids[] = {
++ { .compatible = "ti,pru-rproc", .data = NULL, },
++ {},
++};
++MODULE_DEVICE_TABLE(of, pruss_dt_ids);
++
++static struct platform_driver pruproc_driver = {
++ .driver = {
++ .name = "pru-rproc",
++ .owner = THIS_MODULE,
++ .of_match_table = pru_rproc_dt_ids,
++ },
++ .probe = pruproc_probe,
++ .remove = pruproc_remove,
++};
++
++module_platform_driver(pruproc_driver);
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("PRU Remote Processor control driver");
++MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+diff --git a/firmware/capes/BB-BONE-PRU-02-00A0.dts b/firmware/capes/BB-BONE-PRU-02-00A0.dts
+new file mode 100644
+index 0000000..ddb63f7
+--- /dev/null
++++ b/firmware/capes/BB-BONE-PRU-02-00A0.dts
+@@ -0,0 +1,61 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-PRU-01";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ pru_gpio_pins: pinmux_pru_gpio_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x0f /* P9 27 GPIO3_19: mcasp0_fsr.gpio3[19] | MODE7 | OUTPUT */
++ >;
++ };
++
++ pru_pru_pins: pinmux_pru_pru_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x25 /* mcasp0_fsr.pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU */
++ >;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ prurproc {
++ compatible = "ti,pru-rproc";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pru_pru_pins>;
++
++ ti,hwmods = "pruss";
++ ti,deassert-hard-reset = "pruss", "pruss";
++ reg = <0x4a300000 0x080000>;
++ ti,pintc-offset = <0x20000>;
++ interrupt-parent = <&intc>;
++ status = "okay";
++ interrupts = <20 21 22 23 24 25 26 27>;
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0429-Add-sysfs-entry-for-DDR-sync.patch b/patches/linux-3.8.13/0429-Add-sysfs-entry-for-DDR-sync.patch
new file mode 100644
index 0000000..1e32fa1
--- /dev/null
+++ b/patches/linux-3.8.13/0429-Add-sysfs-entry-for-DDR-sync.patch
@@ -0,0 +1,64 @@
+From: Chris Micali <chrismicali@gmail.com>
+Date: Mon, 20 May 2013 13:10:58 -0400
+Subject: [PATCH] Add sysfs entry for DDR sync
+
+---
+ drivers/uio/uio_pruss.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 5de4f11..54f4781 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -78,6 +78,32 @@ struct uio_pruss_dev {
+ struct gen_pool *sram_pool;
+ };
+
++static ssize_t store_sync_ddr(struct device *dev, struct device_attribute *attr, char *buf, size_t count) {
++ struct uio_pruss_dev *gdev;
++ gdev = dev_get_drvdata(dev);
++ dma_sync_single_for_cpu(dev, gdev->ddr_paddr, extram_pool_sz, DMA_FROM_DEVICE);
++ return count;
++}
++static DEVICE_ATTR(sync_ddr, S_IWUSR, NULL, store_sync_ddr);
++
++static const struct attribute *uio_sysfs_attrs[] = {
++ &dev_attr_sync_ddr.attr,
++ NULL
++};
++
++static int uio_sysfs_init(struct platform_device *pdev) {
++ int error;
++ error = sysfs_create_files(&pdev->dev.kobj, uio_sysfs_attrs);
++ if (error) {
++ dev_err(&pdev->dev, "Failed to create sysfs entries");
++ }
++ return error;
++}
++
++static void uio_sysfs_cleanup(struct platform_device *pdev) {
++ sysfs_remove_files(&pdev->dev.kobj, uio_sysfs_attrs);
++}
++
+ static irqreturn_t pruss_handler(int irq, struct uio_info *info)
+ {
+ struct uio_pruss_dev *gdev = info->priv;
+@@ -103,6 +129,8 @@ static void pruss_cleanup(struct platform_device *dev,
+ int cnt;
+ struct uio_info *p = gdev->info;
+
++ uio_sysfs_cleanup(dev);
++
+ for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+ uio_unregister_device(p);
+ kfree(p->name);
+@@ -295,6 +323,9 @@ static int pruss_probe(struct platform_device *dev)
+ goto out_free;
+ }
+
++ if (uio_sysfs_init(dev))
++ goto out_free;
++
+ platform_set_drvdata(dev, gdev);
+ return 0;
+
diff --git a/patches/linux-3.8.13/0430-virtio-ring-Introduce-dma-mapping-for-real-devices.patch b/patches/linux-3.8.13/0430-virtio-ring-Introduce-dma-mapping-for-real-devices.patch
new file mode 100644
index 0000000..5799e7c
--- /dev/null
+++ b/patches/linux-3.8.13/0430-virtio-ring-Introduce-dma-mapping-for-real-devices.patch
@@ -0,0 +1,227 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 2 Jul 2013 22:13:27 +0300
+Subject: [PATCH] virtio: ring: Introduce dma mapping for real devices
+
+Real hardware devices need to use the dma mapping functions to work.
+Blindly calling sg_phys and expecting it to work on any address
+is a fool's errand.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/virtio/virtio_ring.c | 120 +++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 112 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
+index ffd7e7d..1c7ad01 100644
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -19,6 +19,8 @@
+ #include <linux/virtio.h>
+ #include <linux/virtio_ring.h>
+ #include <linux/virtio_config.h>
++#include <linux/virtio_ids.h>
++#include <linux/dma-mapping.h>
+ #include <linux/device.h>
+ #include <linux/slab.h>
+ #include <linux/module.h>
+@@ -74,6 +76,13 @@
+ #define END_USE(vq)
+ #endif
+
++struct vring_sg {
++ struct scatterlist sg;
++ void *va;
++ dma_addr_t dma;
++ enum dma_data_direction dir;
++};
++
+ struct vring_virtqueue
+ {
+ struct virtqueue vq;
+@@ -113,12 +122,83 @@ struct vring_virtqueue
+ ktime_t last_add_time;
+ #endif
+
++ /* copy of the scatter list */
++ struct vring_sg *vsg;
++
+ /* Tokens for callbacks. */
+ void *data[];
+ };
+
+ #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
+
++/* gross hack */
++#define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC)
++
++static inline bool vdev_needs_mapping(const struct virtio_device *vdev)
++{
++ return is_rproc_enabled && vdev->id.device == VIRTIO_ID_RPROC_SERIAL;
++}
++
++static inline bool vring_needs_mapping(const struct virtqueue *vq)
++{
++ return vdev_needs_mapping(vq->vdev);
++}
++
++dma_addr_t vring_map_single(struct virtqueue *vq, int pos,
++ struct scatterlist *sg, enum dma_data_direction dir)
++{
++ struct device *dev;
++ struct vring_sg *vsg;
++ struct vring_virtqueue *vvq;
++
++ if (!vring_needs_mapping(vq))
++ return sg_phys(sg);
++
++ /* grab the ancestor (this is vdev->rproc->pdev) */
++ if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent)
++ return DMA_ERROR_CODE;
++ dev = vq->vdev->dev.parent->parent;
++
++ vvq = to_vvq(vq);
++
++ vsg = &vvq->vsg[pos];
++
++ /* copy the whole structure */
++ vsg->sg = *sg;
++ vsg->va = sg_virt(sg);
++ vsg->dir = dir;
++ vsg->dma = dma_map_single(dev, vsg->va, vsg->sg.length, dir);
++
++ /* could be dma_mapping_error */
++ return vsg->dma;
++}
++
++int vring_unmap_single(struct virtqueue *vq, int pos)
++{
++ struct device *dev;
++ struct vring_sg *vsg;
++ struct vring_virtqueue *vvq;
++
++ if (!vring_needs_mapping(vq))
++ return 0;
++
++ /* grab the ancestor (this is vdev->rproc->pdev) */
++ if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent)
++ return -EINVAL;
++
++ dev = vq->vdev->dev.parent->parent;
++
++ vvq = to_vvq(vq);
++
++ vsg = &vvq->vsg[pos];
++
++ dma_unmap_single(dev, vsg->dma, vsg->sg.length, vsg->dir);
++
++ memset(vsg, 0, sizeof(*vsg));
++
++ return 0;
++}
++
+ /* Set up an indirect table of descriptors and add it to the queue. */
+ static int vring_add_indirect(struct vring_virtqueue *vq,
+ struct scatterlist sg[],
+@@ -219,8 +299,10 @@ int virtqueue_add_buf(struct virtqueue *_vq,
+ #endif
+
+ /* If the host supports indirect descriptor tables, and we have multiple
+- * buffers, then go indirect. FIXME: tune this threshold */
+- if (vq->indirect && (out + in) > 1 && vq->vq.num_free) {
++ * buffers, then go indirect; but only if we don't need dma mapping.
++ * FIXME: tune this threshold */
++ if (vq->indirect && (out + in) > 1 && vq->vq.num_free &&
++ !vring_needs_mapping(_vq)) {
+ head = vring_add_indirect(vq, sg, out, in, gfp);
+ if (likely(head >= 0))
+ goto add_head;
+@@ -247,14 +329,14 @@ int virtqueue_add_buf(struct virtqueue *_vq,
+ head = vq->free_head;
+ for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
+ vq->vring.desc[i].flags = VRING_DESC_F_NEXT;
+- vq->vring.desc[i].addr = sg_phys(sg);
++ vq->vring.desc[i].addr = vring_map_single(_vq, i, sg, DMA_TO_DEVICE);
+ vq->vring.desc[i].len = sg->length;
+ prev = i;
+ sg++;
+ }
+ for (; in; i = vq->vring.desc[i].next, in--) {
+ vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
+- vq->vring.desc[i].addr = sg_phys(sg);
++ vq->vring.desc[i].addr = vring_map_single(_vq, i, sg, DMA_FROM_DEVICE);
+ vq->vring.desc[i].len = sg->length;
+ prev = i;
+ sg++;
+@@ -371,7 +453,8 @@ EXPORT_SYMBOL_GPL(virtqueue_kick);
+
+ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
+ {
+- unsigned int i;
++ unsigned int i, out, in;
++ u16 flags;
+
+ /* Clear data ptr. */
+ vq->data[head] = NULL;
+@@ -383,15 +466,21 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
+ if (vq->vring.desc[i].flags & VRING_DESC_F_INDIRECT)
+ kfree(phys_to_virt(vq->vring.desc[i].addr));
+
+- while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) {
++ out = 0;
++ in = 0;
++ while ((flags = vq->vring.desc[i].flags) & VRING_DESC_F_NEXT) {
+ i = vq->vring.desc[i].next;
+ vq->vq.num_free++;
++
++ vring_unmap_single(&vq->vq, i);
+ }
+
+ vq->vring.desc[i].next = vq->free_head;
+ vq->free_head = head;
+ /* Plus final descriptor */
+ vq->vq.num_free++;
++
++ vring_unmap_single(&vq->vq, i);
+ }
+
+ static inline bool more_used(const struct vring_virtqueue *vq)
+@@ -629,7 +718,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
+ const char *name)
+ {
+ struct vring_virtqueue *vq;
+- unsigned int i;
++ unsigned int i, size, size_vsg;
+
+ /* We assume num is a power of 2. */
+ if (num & (num - 1)) {
+@@ -637,7 +726,16 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
+ return NULL;
+ }
+
+- vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL);
++ size = sizeof(*vq) + sizeof(void *)*num;
++ /* align size to dma_addr_t */
++ size = ALIGN(size, sizeof(struct vring_sg));
++
++ /* add the size of the sg array (if needed) */
++ if (vdev_needs_mapping(vdev))
++ size_vsg = sizeof(struct vring_sg) * num;
++ else
++ size_vsg = 0;
++ vq = kmalloc(size + size_vsg, GFP_KERNEL);
+ if (!vq)
+ return NULL;
+
+@@ -673,6 +771,12 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
+ }
+ vq->data[i] = NULL;
+
++ /* initialize everything to zero */
++ if (size_vsg > 0) {
++ vq->vsg = (void *)vq + size;
++ memset(vq->vsg, 0, size_vsg);
++ }
++
+ return &vq->vq;
+ }
+ EXPORT_SYMBOL_GPL(vring_new_virtqueue);
diff --git a/patches/linux-3.8.13/0431-virtio_console-Simplify-virtio_console-for-h-w-devic.patch b/patches/linux-3.8.13/0431-virtio_console-Simplify-virtio_console-for-h-w-devic.patch
new file mode 100644
index 0000000..46c3899
--- /dev/null
+++ b/patches/linux-3.8.13/0431-virtio_console-Simplify-virtio_console-for-h-w-devic.patch
@@ -0,0 +1,81 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 2 Jul 2013 22:15:02 +0300
+Subject: [PATCH] virtio_console: Simplify virtio_console for h/w devices.
+
+Now that virtio_ring properly maps the buffers there is no need
+for special handling of rproc_serial, nor any need to use
+dma_alloc_coherent for the buffers; the standard mapping works,
+plus sg_phys() on a piece of dma_alloc_coherent memory is bogus.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/char/virtio_console.c | 49 +++++++----------------------------------
+ 1 file changed, 8 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
+index a4b7aa0..2e9808b 100644
+--- a/drivers/char/virtio_console.c
++++ b/drivers/char/virtio_console.c
+@@ -375,25 +375,7 @@ static void free_buf(struct port_buffer *buf, bool can_sleep)
+ put_page(page);
+ }
+
+- if (!buf->dev) {
+- kfree(buf->buf);
+- } else if (is_rproc_enabled) {
+- unsigned long flags;
+-
+- /* dma_free_coherent requires interrupts to be enabled. */
+- if (!can_sleep) {
+- /* queue up dma-buffers to be freed later */
+- spin_lock_irqsave(&dma_bufs_lock, flags);
+- list_add_tail(&buf->list, &pending_free_dma_bufs);
+- spin_unlock_irqrestore(&dma_bufs_lock, flags);
+- return;
+- }
+- dma_free_coherent(buf->dev, buf->size, buf->buf, buf->dma);
+-
+- /* Release device refcnt and allow it to be freed */
+- put_device(buf->dev);
+- }
+-
++ kfree(buf->buf);
+ kfree(buf);
+ }
+
+@@ -442,28 +424,13 @@ static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
+ return buf;
+ }
+
+- if (is_rproc_serial(vq->vdev)) {
+- /*
+- * Allocate DMA memory from ancestor. When a virtio
+- * device is created by remoteproc, the DMA memory is
+- * associated with the grandparent device:
+- * vdev => rproc => platform-dev.
+- * The code here would have been less quirky if
+- * DMA_MEMORY_INCLUDES_CHILDREN had been supported
+- * in dma-coherent.c
+- */
+- if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent)
+- goto free_buf;
+- buf->dev = vq->vdev->dev.parent->parent;
+-
+- /* Increase device refcnt to avoid freeing it */
+- get_device(buf->dev);
+- buf->buf = dma_alloc_coherent(buf->dev, buf_size, &buf->dma,
+- GFP_KERNEL);
+- } else {
+- buf->dev = NULL;
+- buf->buf = kmalloc(buf_size, GFP_KERNEL);
+- }
++ /* NOTE: No more dma_alloc_coherent for rproc_serial
++ * It was bogus anyway, since you ended up calling sg_phys()
++ * on a dma_alloc_coherent address. With vring supporting
++ * dma mapping regular kmalloc memory is fine.
++ */
++ buf->dev = NULL; /* FIXME: Perhaps revisit? */
++ buf->buf = kmalloc(buf_size, GFP_KERNEL);
+
+ if (!buf->buf)
+ goto free_buf;
diff --git a/patches/linux-3.8.13/0432-rpmsg-Make-the-buffers-number-and-size-configurable.patch b/patches/linux-3.8.13/0432-rpmsg-Make-the-buffers-number-and-size-configurable.patch
new file mode 100644
index 0000000..acc6952
--- /dev/null
+++ b/patches/linux-3.8.13/0432-rpmsg-Make-the-buffers-number-and-size-configurable.patch
@@ -0,0 +1,59 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 23 May 2013 20:22:52 +0300
+Subject: [PATCH] rpmsg: Make the buffers number and size configurable
+
+The defaults are just too much for small devices. Make them
+configurable (by a kernel config option for now).
+---
+ drivers/rpmsg/Kconfig | 14 ++++++++++++++
+ drivers/rpmsg/virtio_rpmsg_bus.c | 14 ++++++++++++--
+ 2 files changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
+index 2bd911f..e3d09d2 100644
+--- a/drivers/rpmsg/Kconfig
++++ b/drivers/rpmsg/Kconfig
+@@ -6,4 +6,18 @@ config RPMSG
+ select VIRTIO
+ depends on EXPERIMENTAL
+
++config RPMSG_NUM_BUFS
++ int "RPMSG number of buffers"
++ depends on RPMSG
++ default 512
++ help
++ Configure rpmsg number of bufs (default is 512)
++
++config RPMSG_BUF_SIZE
++ int "RPMSG size of buffers"
++ depends on RPMSG
++ default 512
++ help
++ Configure rpmsg buffer size (default is 512)
++
+ endmenu
+diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
+index f1e3239..1ca8700 100644
+--- a/drivers/rpmsg/virtio_rpmsg_bus.c
++++ b/drivers/rpmsg/virtio_rpmsg_bus.c
+@@ -102,8 +102,18 @@ struct rpmsg_channel_info {
+ * can change this without changing anything in the firmware of the remote
+ * processor.
+ */
+-#define RPMSG_NUM_BUFS (512)
+-#define RPMSG_BUF_SIZE (512)
++#ifndef CONFIG_RPMSG_NUM_BUFS
++#define RPMSG_NUM_BUFS 512
++#else
++#define RPMSG_NUM_BUFS CONFIG_RPMSG_NUM_BUFS
++#endif
++
++#ifndef CONFIG_RPMSG_BUF_SIZE
++#define RPMSG_BUF_SIZE 512
++#else
++#define RPMSG_BUF_SIZE CONFIG_RPMSG_BUF_SIZE
++#endif
++
+ #define RPMSG_TOTAL_BUF_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE)
+
+ /*
diff --git a/patches/linux-3.8.13/0433-remoteproc-Use-driver-ops-for-allocation-of-virtqueu.patch b/patches/linux-3.8.13/0433-remoteproc-Use-driver-ops-for-allocation-of-virtqueu.patch
new file mode 100644
index 0000000..31aeaf8
--- /dev/null
+++ b/patches/linux-3.8.13/0433-remoteproc-Use-driver-ops-for-allocation-of-virtqueu.patch
@@ -0,0 +1,167 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 24 May 2013 15:01:19 +0300
+Subject: [PATCH] remoteproc: Use driver ops for allocation of virtqueus
+
+Virtqueues can not always be dynamically allocated.
+In many cases they should be placed in driver controlled areas.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/remoteproc/remoteproc_core.c | 64 ++++++++++++++++++++++++++--------
+ include/linux/remoteproc.h | 9 +++++
+ 2 files changed, 59 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
+index 752b507..7c56d0a 100644
+--- a/drivers/remoteproc/remoteproc_core.c
++++ b/drivers/remoteproc/remoteproc_core.c
+@@ -187,31 +187,59 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+ }
+ EXPORT_SYMBOL(rproc_da_to_va);
+
++static inline void *rproc_alloc_vring_internal(struct rproc *rproc,
++ const struct fw_rsc_vdev_vring *vring,
++ int size, dma_addr_t *dma)
++{
++ struct device *dev = &rproc->dev;
++
++ /* Custom vring allocator */
++ if (rproc->ops->alloc_vring != NULL)
++ return rproc->ops->alloc_vring(rproc, vring, size, dma);
++
++ /*
++ * Allocate non-cacheable memory for the vring. In the future
++ * this call will also configure the IOMMU for us
++ * TODO: let the rproc know the da of this vring
++ */
++ return dma_alloc_coherent(dev->parent, PAGE_ALIGN(size),
++ dma, GFP_KERNEL);
++}
++
++static inline void rproc_free_vring_internal(struct rproc *rproc,
++ const struct fw_rsc_vdev_vring *vring,
++ int size, void *va, dma_addr_t dma)
++{
++ struct device *dev = &rproc->dev;
++
++ /* Custom vring allocator */
++ if (rproc->ops->free_vring != NULL)
++ rproc->ops->free_vring(rproc, vring, size, va, dma);
++ else
++ dma_free_coherent(dev->parent,
++ PAGE_ALIGN(size), va, dma);
++}
++
+ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
+ {
+ struct rproc *rproc = rvdev->rproc;
+ struct device *dev = &rproc->dev;
+ struct rproc_vring *rvring = &rvdev->vring[i];
++ struct fw_rsc_vdev_vring *vring = rvring->rsc_vring;
+ dma_addr_t dma;
+ void *va;
+ int ret, size, notifyid;
+
+- /* actual size of vring (in bytes) */
+- size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
+-
+ if (!idr_pre_get(&rproc->notifyids, GFP_KERNEL)) {
+ dev_err(dev, "idr_pre_get failed\n");
+ return -ENOMEM;
+ }
+
+- /*
+- * Allocate non-cacheable memory for the vring. In the future
+- * this call will also configure the IOMMU for us
+- * TODO: let the rproc know the da of this vring
+- */
+- va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL);
++ size = vring_size(rvring->len, rvring->align);
++
++ va = rproc_alloc_vring_internal(rproc, vring, size, &dma);
+ if (!va) {
+- dev_err(dev->parent, "dma_alloc_coherent failed\n");
++ dev_err(dev->parent, "rproc alloc of vring #%d failed\n", i);
+ return -EINVAL;
+ }
+
+@@ -224,7 +252,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
+ ret = idr_get_new(&rproc->notifyids, rvring, &notifyid);
+ if (ret) {
+ dev_err(dev, "idr_get_new failed: %d\n", ret);
+- dma_free_coherent(dev->parent, size, va, dma);
++ rproc_free_vring_internal(rproc, vring, size, va, dma);
+ return ret;
+ }
+
+@@ -269,6 +297,9 @@ rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
+ rvring->align = vring->align;
+ rvring->rvdev = rvdev;
+
++ /* point to the resource */
++ rvring->rsc_vring = vring;
++
+ return 0;
+ }
+
+@@ -281,11 +312,13 @@ static int rproc_max_notifyid(int id, void *p, void *data)
+
+ void rproc_free_vring(struct rproc_vring *rvring)
+ {
+- int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
+- struct rproc *rproc = rvring->rvdev->rproc;
++ int size = vring_size(rvring->len, rvring->align);
++ struct rproc_vdev *rvdev = rvring->rvdev;
++ struct rproc *rproc = rvdev->rproc;
+ int maxid = 0;
+
+- dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma);
++ rproc_free_vring_internal(rproc, rvring->rsc_vring,
++ size, rvring->va, rvring->dma);
+ idr_remove(&rproc->notifyids, rvring->notifyid);
+
+ /* Find the largest remaining notifyid */
+@@ -355,6 +388,9 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
+
+ rvdev->rproc = rproc;
+
++ /* point to the resource */
++ rvdev->rsc_vdev = rsc;
++
+ /* parse the vrings */
+ for (i = 0; i < rsc->num_of_vrings; i++) {
+ ret = rproc_parse_vring(rvdev, rsc, i);
+diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
+index faf3332..c8573fd 100644
+--- a/include/linux/remoteproc.h
++++ b/include/linux/remoteproc.h
+@@ -335,6 +335,13 @@ struct rproc_ops {
+ int (*start)(struct rproc *rproc);
+ int (*stop)(struct rproc *rproc);
+ void (*kick)(struct rproc *rproc, int vqid);
++
++ void *(*alloc_vring)(struct rproc *rproc,
++ const struct fw_rsc_vdev_vring *vring,
++ int size, dma_addr_t *dma);
++ void (*free_vring)(struct rproc *rproc,
++ const struct fw_rsc_vdev_vring *vring,
++ int size, void *va, dma_addr_t dma);
+ };
+
+ /**
+@@ -454,6 +461,7 @@ struct rproc_vring {
+ int notifyid;
+ struct rproc_vdev *rvdev;
+ struct virtqueue *vq;
++ struct fw_rsc_vdev_vring *rsc_vring;
+ };
+
+ /**
+@@ -472,6 +480,7 @@ struct rproc_vdev {
+ struct rproc_vring vring[RVDEV_NUM_VRINGS];
+ unsigned long dfeatures;
+ unsigned long gfeatures;
++ struct fw_rsc_vdev *rsc_vdev;
+ };
+
+ struct rproc *rproc_alloc(struct device *dev, const char *name,
diff --git a/patches/linux-3.8.13/0434-rproc-core-Allow-bootup-without-resources.patch b/patches/linux-3.8.13/0434-rproc-core-Allow-bootup-without-resources.patch
new file mode 100644
index 0000000..75fe5c5
--- /dev/null
+++ b/patches/linux-3.8.13/0434-rproc-core-Allow-bootup-without-resources.patch
@@ -0,0 +1,40 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 10 Jul 2013 00:13:03 +0300
+Subject: [PATCH] rproc: core: Allow bootup without resources
+
+Not every core has a need to communicate with the host via VDEVS.
+Allow booting without a resource table.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/remoteproc/remoteproc_core.c | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
+index 7c56d0a..76ca36a 100644
+--- a/drivers/remoteproc/remoteproc_core.c
++++ b/drivers/remoteproc/remoteproc_core.c
+@@ -868,16 +868,13 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
+
+ /* look for the resource table */
+ table = rproc_find_rsc_table(rproc, fw, &tablesz);
+- if (!table) {
+- ret = -EINVAL;
+- goto clean_up;
+- }
+-
+- /* handle fw resources which are required to boot rproc */
+- ret = rproc_handle_boot_rsc(rproc, table, tablesz);
+- if (ret) {
+- dev_err(dev, "Failed to process resources: %d\n", ret);
+- goto clean_up;
++ if (table != NULL) {
++ /* handle fw resources which are required to boot rproc */
++ ret = rproc_handle_boot_rsc(rproc, table, tablesz);
++ if (ret) {
++ dev_err(dev, "Failed to process resources: %d\n", ret);
++ goto clean_up;
++ }
+ }
+
+ /* load the ELF segments to memory */
diff --git a/patches/linux-3.8.13/0435-tools-virtio-fix-build-for-3.8.patch b/patches/linux-3.8.13/0435-tools-virtio-fix-build-for-3.8.patch
new file mode 100644
index 0000000..36aedd5
--- /dev/null
+++ b/patches/linux-3.8.13/0435-tools-virtio-fix-build-for-3.8.patch
@@ -0,0 +1,87 @@
+From: "Michael S. Tsirkin" <mst@redhat.com>
+Date: Mon, 18 Mar 2013 13:22:18 +1030
+Subject: [PATCH] tools/virtio: fix build for 3.8
+
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
+---
+ drivers/vhost/test.c | 4 +++-
+ tools/virtio/Makefile | 2 +-
+ tools/virtio/linux/virtio.h | 7 ++++++-
+ tools/virtio/virtio_test.c | 3 ++-
+ 4 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
+index 91d6f06..329d302 100644
+--- a/drivers/vhost/test.c
++++ b/drivers/vhost/test.c
+@@ -275,7 +275,9 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
+ return vhost_test_reset_owner(n);
+ default:
+ mutex_lock(&n->dev.mutex);
+- r = vhost_dev_ioctl(&n->dev, ioctl, arg);
++ r = vhost_dev_ioctl(&n->dev, ioctl, argp);
++ if (r == -ENOIOCTLCMD)
++ r = vhost_vring_ioctl(&n->dev, ioctl, argp);
+ vhost_test_flush(n);
+ mutex_unlock(&n->dev.mutex);
+ return r;
+diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
+index d1d442e..b48c432 100644
+--- a/tools/virtio/Makefile
++++ b/tools/virtio/Makefile
+@@ -1,7 +1,7 @@
+ all: test mod
+ test: virtio_test
+ virtio_test: virtio_ring.o virtio_test.o
+-CFLAGS += -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -MMD
++CFLAGS += -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD
+ vpath %.c ../../drivers/virtio
+ mod:
+ ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test
+diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
+index 81847dd..390c4cb 100644
+--- a/tools/virtio/linux/virtio.h
++++ b/tools/virtio/linux/virtio.h
+@@ -85,6 +85,8 @@ typedef __u16 u16;
+ typedef enum {
+ GFP_KERNEL,
+ GFP_ATOMIC,
++ __GFP_HIGHMEM,
++ __GFP_HIGH
+ } gfp_t;
+ typedef enum {
+ IRQ_NONE,
+@@ -163,6 +165,8 @@ struct virtqueue {
+ void (*callback)(struct virtqueue *vq);
+ const char *name;
+ struct virtio_device *vdev;
++ unsigned int index;
++ unsigned int num_free;
+ void *priv;
+ };
+
+@@ -206,7 +210,8 @@ bool virtqueue_enable_cb(struct virtqueue *vq);
+ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
+
+ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
+-struct virtqueue *vring_new_virtqueue(unsigned int num,
++struct virtqueue *vring_new_virtqueue(unsigned int index,
++ unsigned int num,
+ unsigned int vring_align,
+ struct virtio_device *vdev,
+ bool weak_barriers,
+diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
+index fcc9aa2..faf3f0c 100644
+--- a/tools/virtio/virtio_test.c
++++ b/tools/virtio/virtio_test.c
+@@ -92,7 +92,8 @@ static void vq_info_add(struct vdev_info *dev, int num)
+ assert(r >= 0);
+ memset(info->ring, 0, vring_size(num, 4096));
+ vring_init(&info->vring, num, info->ring, 4096);
+- info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev,
++ info->vq = vring_new_virtqueue(info->idx,
++ info->vring.num, 4096, &dev->vdev,
+ true, info->ring,
+ vq_notify, vq_callback, "test");
+ assert(info->vq);
diff --git a/patches/linux-3.8.13/0436-rproc-pru-PRU-remoteproc-updated-to-work-with-virtio.patch b/patches/linux-3.8.13/0436-rproc-pru-PRU-remoteproc-updated-to-work-with-virtio.patch
new file mode 100644
index 0000000..974ae66
--- /dev/null
+++ b/patches/linux-3.8.13/0436-rproc-pru-PRU-remoteproc-updated-to-work-with-virtio.patch
@@ -0,0 +1,2487 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Jul 2013 19:38:54 +0300
+Subject: [PATCH] rproc: pru: PRU remoteproc updated to work with virtio +
+ complex h/w setup
+
+Major update for the PRU rproc driver. Implemented logic for interrupt event
+routing, virtio support, dual PRU support, system calls and many more.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/remoteproc/Kconfig | 1 +
+ drivers/remoteproc/pru_rproc.c | 2370 ++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 2251 insertions(+), 120 deletions(-)
+
+diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
+index 690097b..13cb3ca 100644
+--- a/drivers/remoteproc/Kconfig
++++ b/drivers/remoteproc/Kconfig
+@@ -46,6 +46,7 @@ config PRU_RPROC
+ depends on EXPERIMENTAL
+ depends on HAS_DMA && SOC_AM33XX
+ select REMOTEPROC
++ select RPMSG
+ default n
+ help
+ Say y or m here to support AM33xx PRU
+diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
+index 113ad80..e3ec63b 100644
+--- a/drivers/remoteproc/pru_rproc.c
++++ b/drivers/remoteproc/pru_rproc.c
+@@ -1,6 +1,6 @@
+ /*
+ * PRU driver for TI's AM33xx series of SoCs
+- *
++ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+@@ -22,199 +22,2329 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/io.h>
++#include <plat/mailbox.h>
++#include <linux/virtio_ids.h>
++#include <linux/elf.h>
++#include <linux/byteorder/generic.h>
++#include <linux/virtio.h>
++#include <linux/virtio_ring.h>
++#include <asm/atomic.h>
+
+ #include "remoteproc_internal.h"
+
++/* PRU_EVTOUT0 is halt (system call) */
++
++/* maximum PRUs */
++#define MAX_PRUS 2
++
++/* sysevent targets (ARM + PRU) */
++#define MAX_TARGETS (1 + MAX_PRUS)
++
++/* sysevent target ids */
++#define TARGET_ARM 0
++#define TARGET_PRU(x) (1 + (x))
++#define TARGET_PRU_TO_PRU_IDX(x) ({ \
++ unsigned int _x = (x) - TARGET_PRU(0); \
++ _x < MAX_PRUS ? _x : -1; \
++ })
++#define TARGET_FROM_TO_IDX(_from, _to) \
++ ((_from) * MAX_TARGETS + (_to))
++#define TARGET_ARM_TO_PRU_IDX(x) \
++ TARGET_FROM_TO_IDX(TARGET_ARM, TARGET_PRU(x))
++#define TARGET_PRU_TO_ARM_IDX(x) \
++ TARGET_FROM_TO_IDX(TARGET_PRU(x), TARGET_ARM)
++
++/* maximum interrupts routed to host */
++#define MAX_ARM_PRU_INTS 8
++
++/* maximum number of sys events */
++#define MAX_PRU_SYS_EVENTS 64
++
++/* maximum number of interrupt channels */
++#define MAX_PRU_CHANNELS 10
++
++/* maximum number of host interrupts (ARM + 1 for each PRU) */
++#define MIN_PRU_HOST_INT 2
++#define MAX_PRU_HOST_INT 10
++
++struct pruproc;
++struct pruproc_core;
++
++/* maximum 4 vdevs per PRU */
++#define PRU_VDEV_MAX 4
++#define PRU_VRING_MAX (RVDEV_NUM_VRINGS * PRU_VDEV_MAX)
++
++struct pru_vring_info {
++ struct fw_rsc_vdev_vring *rsc;
++ struct vring vr;
++ void __iomem *va;
++ dma_addr_t pa;
++ u32 da;
++ struct rproc_vring *rvring;
++};
++
++/* per PRU core control structure */
++struct pruproc_core {
++ int idx;
++ struct pruproc *pruproc;
++ struct rproc *rproc;
++
++ u32 pctrl;
++ u32 pdbg;
++
++ u32 iram, iram_sz, iram_da; /* global, size, own */
++ u32 dram, dram_sz, dram_da, dram_oda; /* global, size, own, other */
++
++ const char *fw_name;
++ unsigned int is_elf : 1;
++ u32 entry_point;
++
++ struct resource_table *table;
++ int table_size;
++ /* copy of the resource table in device accessible area */
++ void * __iomem dev_table_va;
++ dma_addr_t dev_table_pa;
++
++ int num_vdevs;
++ struct fw_rsc_vdev *rsc_vdev[PRU_VDEV_MAX];
++ int vdev_vring_start[PRU_VDEV_MAX];
++ int vdev_vring_count[PRU_VDEV_MAX];
++
++ /* total for all the vdevs */
++ int num_vrings;
++ struct pru_vring_info vring_info[PRU_VRING_MAX];
++
++ /* sysevent the host generates when kicking any vring */
++ int host_vring_sysev;
++
++ /* sysevent the pru generates when kicking any vring */
++ int pru_vring_sysev;
++
++ /* boots */
++ atomic_t bootcnt;
++};
++
++struct pru_sysev_target {
++ unsigned int valid : 1; /* sysevent is valid */
++ unsigned int vring : 1; /* sysevent is vring related */
++ int source; /* 0=ARM, 1=PRU0, 2=PRU1 */
++ int target; /* 0=ARM, 1=PRU0, 2=PRU1 */
++};
++
+ /* PRU control structure */
+ struct pruproc {
+- struct rproc *rproc;
+ struct platform_device *pdev;
+- struct resource_table *table;
+ void __iomem *vaddr;
+ dma_addr_t paddr;
++ struct omap_mbox *mbox;
++ struct notifier_block nb;
++ u32 pintc;
++ u32 pdram, pdram_sz, pdram_da;
++
++ int num_irqs;
++ int irqs[MAX_ARM_PRU_INTS];
++ int events[MAX_ARM_PRU_INTS];
++ int sysev_to_ch[MAX_PRU_SYS_EVENTS];
++ int ch_to_host[MAX_PRU_CHANNELS];
++ int target_to_sysev[MAX_TARGETS * MAX_TARGETS];
++
++ /* map an incoming sysevent to kind and handler */
++ struct pru_sysev_target sysev_to_target[MAX_PRU_SYS_EVENTS];
++
++ /* number of prus */
++ u32 num_prus;
++ struct pruproc_core **pruc;
++ struct pruproc_core *pru_to_pruc[MAX_PRUS];
+ };
+
+-/* Loads the firmware to shared memory. */
+-static int pruproc_load_segments(struct rproc *rproc, const struct firmware *fw)
++/* global memory map (for am33xx) (almost the same as local) */
++#define PRU_DATA_RAM0 0x00000
++#define PRU_DATA_RAM1 0x02000
++#define PRU_SHARED_DATA_RAM 0x10000
++#define PRU_INTC 0x20000
++#define PRU_PRU0_CONTROL 0x22000
++#define PRU_PRU0_DEBUG 0x22400
++#define PRU_PRU1_CONTROL 0x24000
++#define PRU_PRU1_DEBUG 0x24400
++#define PRU_CFG 0x26000
++#define PRU_UART0 0x28000
++#define PRU_IEP 0x2E000
++#define PRU_ECAP0 0x30000
++#define PRU_MII_RT_CFG 0x32000
++#define PRU_MII_MDIO 0x32400
++#define PRU_INSN_RAM0 0x34000
++#define PRU_INSN_RAM1 0x38000
++
++/* PRU CONTROL */
++#define PCTRL_CONTROL 0x0000
++#define CONTROL_SOFT_RST_N 0x0001
++#define CONTROL_ENABLE 0x0002
++#define CONTROL_SLEEPING 0x0004
++#define CONTROL_COUNTER_ENABLE 0x0008
++#define CONTROL_SINGLE_STEP 0x0100
++#define CONTROL_RUNSTATE 0x4000
++
++#define PCTRL_STATUS 0x0004
++#define PCTRL_WAKEUP_EN 0x0008
++#define PCTRL_CYCLE 0x000C
++#define PCTRL_STALL 0x0010
++#define PCTRL_CTBIR0 0x0020
++#define PCTRL_CTBIR1 0x0024
++#define PCTRL_CTPPR0 0x0028
++#define PCTRL_CTPPR1 0x002C
++
++/* PRU DEBUG */
++#define PDBG_GPREG(x) (0x0000 + (x) * 4)
++#define PDBG_CT_REG(x) (0x0080 + (x) * 4)
++
++/* PRU INTC */
++#define PINTC_REVID 0x0000
++#define PINTC_CR 0x0004
++#define PINTC_GER 0x0010
++#define PINTC_GNLR 0x001C
++#define PINTC_SISR 0x0020
++#define PINTC_SICR 0x0024
++#define PINTC_EISR 0x0028
++#define PINTC_EICR 0x002C
++#define PINTC_HIEISR 0x0034
++#define PINTC_HIDISR 0x0038
++#define PINTC_GPIR 0x0080
++#define PINTC_SRSR0 0x0200
++#define PINTC_SRSR1 0x0204
++#define PINTC_SECR0 0x0280
++#define PINTC_SECR1 0x0284
++#define PINTC_ESR0 0x0300
++#define PINTC_ESR1 0x0304
++#define PINTC_ECR0 0x0380
++#define PINTC_ECR1 0x0384
++#define PINTC_CMR0 0x0400
++#define PINTC_CMR1 0x0404
++#define PINTC_CMR2 0x0408
++#define PINTC_CMR3 0x040C
++#define PINTC_CMR4 0x0410
++#define PINTC_CMR5 0x0414
++#define PINTC_CMR6 0x0418
++#define PINTC_CMR7 0x041C
++#define PINTC_CMR8 0x0420
++#define PINTC_CMR9 0x0424
++#define PINTC_CMR10 0x0428
++#define PINTC_CMR11 0x042C
++#define PINTC_CMR12 0x0430
++#define PINTC_CMR13 0x0434
++#define PINTC_CMR14 0x0438
++#define PINTC_CMR15 0x043C
++#define PINTC_HMR0 0x0800
++#define PINTC_HMR1 0x0804
++#define PINTC_HMR2 0x0808
++#define PINTC_HIPIR0 0x0900
++#define PINTC_HIPIR1 0x0904
++#define PINTC_HIPIR2 0x0908
++#define PINTC_HIPIR3 0x090C
++#define PINTC_HIPIR4 0x0910
++#define PINTC_HIPIR5 0x0914
++#define PINTC_HIPIR6 0x0918
++#define PINTC_HIPIR7 0x091C
++#define PINTC_HIPIR8 0x0920
++#define PINTC_HIPIR9 0x0924
++#define PINTC_SIPR0 0x0D00
++#define PINTC_SIPR1 0x0D04
++#define PINTC_SITR0 0x0D80
++#define PINTC_SITR1 0x0D84
++#define PINTC_HINLR0 0x1100
++#define PINTC_HINLR1 0x1104
++#define PINTC_HINLR2 0x1108
++#define PINTC_HINLR3 0x110C
++#define PINTC_HINLR4 0x1110
++#define PINTC_HINLR5 0x1114
++#define PINTC_HINLR6 0x1118
++#define PINTC_HINLR7 0x111C
++#define PINTC_HINLR8 0x1120
++#define PINTC_HINLR9 0x1124
++#define PINTC_HIER 0x1500
++
++#define HIPIR_NOPEND 0x80000000
++
++static inline u32 pru_read_reg(struct pruproc *pp, unsigned int reg)
+ {
+- struct pruproc *pruproc = rproc->priv;
++ return __raw_readl(pp->vaddr + reg);
++}
+
+- dev_dbg(&pruproc->pdev->dev, "%s\n", __func__);
++static inline void pru_write_reg(struct pruproc *pp, unsigned int reg,
++ u32 val)
++{
++ __raw_writel(val, pp->vaddr + reg);
++}
+
+- return 0;
++static inline u32 pintc_read_reg(struct pruproc *pp, unsigned int reg)
++{
++ return pru_read_reg(pp, reg + pp->pintc);
+ }
+
+-/* Find the resource table inside the remote processor's firmware. */
+-static struct resource_table *
+-pruproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
+- int *tablesz)
++static inline void pintc_write_reg(struct pruproc *pp, unsigned int reg,
++ u32 val)
+ {
+- struct pruproc *pruproc = rproc->priv;
+- struct resource_table *table;
++ return pru_write_reg(pp, reg + pp->pintc, val);
++}
+
+- table = devm_kzalloc(&pruproc->pdev->dev, sizeof(*table), GFP_KERNEL);
++static inline u32 pcntrl_read_reg(struct pruproc_core *ppc, unsigned int reg)
++{
++ return pru_read_reg(ppc->pruproc, reg + ppc->pctrl);
++}
+
+- dev_dbg(&pruproc->pdev->dev, "%s\n", __func__);
++static inline void pcntrl_write_reg(struct pruproc_core *ppc, unsigned int reg,
++ u32 val)
++{
++ return pru_write_reg(ppc->pruproc, reg + ppc->pctrl, val);
++}
+
+- return table;
++static inline u32 pdbg_read_reg(struct pruproc_core *ppc, unsigned int reg)
++{
++ return pru_read_reg(ppc->pruproc, reg + ppc->pdbg);
+ }
+
+-static int pruproc_sanity_check(struct rproc *rproc, const struct firmware *fw)
++static inline void pdbg_write_reg(struct pruproc_core *ppc, unsigned int reg,
++ u32 val)
+ {
+- return 0;
++ return pru_write_reg(ppc->pruproc, reg + ppc->pdbg, val);
+ }
+
+-/* PRU firmware handler operations */
+-const struct rproc_fw_ops pruproc_fw_ops = {
+- .find_rsc_table = pruproc_find_rsc_table,
+- .load = pruproc_load_segments,
+- .sanity_check = pruproc_sanity_check,
+-};
++/* convert 32 bit Data device address to a virtual (and physical) host addr */
++static void * __iomem pru_d_da_to_va(struct pruproc_core *ppc, u32 da,
++ dma_addr_t *pa)
++{
++ struct pruproc *pp = ppc->pruproc;
++ u32 offset;
+
+-/* Kick the modem with specified notification id */
+-static void pruproc_kick(struct rproc *rproc, int vqid)
++ /* check own data ram first */
++ if (da >= ppc->dram_da && da < ppc->dram_da + ppc->dram_sz)
++ offset = ppc->dram + da - ppc->dram_da;
++ /* check other's data ram */
++ else if (da >= ppc->dram_oda && da < ppc->dram_oda + ppc->dram_sz)
++ offset = ppc->dram + da - ppc->dram_oda;
++ /* shared data */
++ else if (da >= pp->pdram_da && da < pp->pdram_da + pp->pdram_sz)
++ offset = pp->pdram + da - pp->pdram_da;
++ else
++ return NULL;
++
++ if (pa)
++ *pa = pp->paddr + offset;
++ return pp->vaddr + offset;
++}
++
++/* convert physical address to device address */
++static u32 pru_d_pa_to_da(struct pruproc_core *ppc, dma_addr_t pa)
+ {
+- struct pruproc *pruproc = rproc->priv;
++ /* we don't support mapping in the GPMC space */
++ if (pa < 0x00080000)
++ return 0xffffffff;
++
++ /* we also don't map internal memories */
+
+- dev_dbg(&pruproc->pdev->dev, "kick vqid:%d\n", vqid);
++ return (u32)pa;
+ }
+
+-/* Start the PRU modem */
+-static int pruproc_start(struct rproc *rproc)
++static void * __iomem pru_i_da_to_va(struct pruproc_core *ppc, u32 da,
++ dma_addr_t *pa)
++{
++ struct pruproc *pp = ppc->pruproc;
++ u32 offset;
++
++ /* check whether is within the iram space */
++ if (da >= ppc->iram_da && da < ppc->iram-da + ppc->iram_sz)
++ offset = ppc->iram + da - ppc->iram_da;
++ else
++ return NULL;
++
++ if (pa)
++ *pa = pp->paddr + offset;
++ return pp->vaddr + offset;
++}
++
++static void * __iomem pru_d_da_to_va_block(struct pruproc_core *ppc, u32 da,
++ dma_addr_t *pa, int size)
++{
++ void * __iomem va_start;
++ void * __iomem va_end;
++
++ /* make sure size is not bogus */
++ if (size <= 0)
++ return NULL;
++
++ /* get start vaddr of device address (D) */
++ va_start = pru_d_da_to_va(ppc, da, pa);
++ if (va_start == NULL)
++ return NULL;
++
++ /* get end vaddr of device address (D) */
++ va_end = pru_d_da_to_va(ppc, da + size - 1, NULL);
++ if (va_end == NULL)
++ return NULL;
++
++ /* for the block to be valid the VAs must be consecutive */
++ if ((va_end - va_start) != (size - 1))
++ return NULL;
++
++ /* all good */
++ return va_start;
++}
++
++static void * __iomem pru_i_da_to_va_block(struct pruproc_core *ppc, u32 da,
++ dma_addr_t *pa, int size)
++{
++ void * __iomem va_start;
++ void * __iomem va_end;
++
++ /* make sure size is not bogus */
++ if (size <= 0)
++ return NULL;
++
++ /* get start vaddr of device address (I) */
++ va_start = pru_i_da_to_va(ppc, da, pa);
++ if (va_start == NULL)
++ return NULL;
++
++ /* get end vaddr of device address (I) */
++ va_end = pru_i_da_to_va(ppc, da + size - 1, NULL);
++ if (va_end == NULL)
++ return NULL;
++
++ /* for the block to be valid the VAs must be consecutive */
++ if ((va_end - va_start) != (size - 1))
++ return NULL;
++
++ /* all good */
++ return va_start;
++}
++
++static int pru_i_read_u32(struct pruproc_core *ppc, u32 da, u32 *val)
+ {
+- struct pruproc *pruproc = rproc->priv;
++ void * __iomem va;
++
++ /* verify it's a word address */
++ if (da & 3)
++ return -EINVAL;
+
+- dev_dbg(&pruproc->pdev->dev, "start pru\n");
++ /* get vaddr of device address (I) */
++ va = pru_i_da_to_va_block(ppc, da, NULL, sizeof(u32));
++ if (va == NULL)
++ return -EFAULT;
++
++ if (val)
++ *val = le32_to_cpu(*(u32 *)va);
+
+ return 0;
+ }
+
+-/* Stop the PRU modem */
+-static int pruproc_stop(struct rproc *rproc)
++static int pru_d_read_u32(struct pruproc_core *ppc, u32 da, u32 *val)
+ {
+- struct pruproc *pruproc = rproc->priv;
++ void * __iomem va;
++
++ /* verify it's a word address */
++ if (da & 3)
++ return -EINVAL;
+
+- dev_dbg(&pruproc->pdev->dev, "stop PRU\n");
++ /* get vaddr of device address (I) */
++ va = pru_d_da_to_va_block(ppc, da, NULL, sizeof(u32));
++ if (va == NULL)
++ return -EINVAL;
++
++ if (val)
++ *val = le32_to_cpu(*(u32 *)va);
+
+ return 0;
+ }
+
+-static struct rproc_ops pruproc_ops = {
+- .start = pruproc_start,
+- .stop = pruproc_stop,
+- .kick = pruproc_kick,
+-};
++static int pru_i_write_u32(struct pruproc_core *ppc, u32 da, u32 val)
++{
++ void * __iomem va;
+
+-/* PRU is unregistered */
+-static int pruproc_remove(struct platform_device *pdev)
++ /* verify it's a word address */
++ if (da & 3)
++ return -EINVAL;
++
++ /* get vaddr of device address (I) */
++ va = pru_i_da_to_va_block(ppc, da, NULL, sizeof(u32));
++ if (va == NULL)
++ return -EINVAL;
++
++ *(u32 *)va = cpu_to_le32(val);
++
++ return 0;
++}
++
++static int pru_d_write_u32(struct pruproc_core *ppc, u32 da, u32 val)
+ {
+- struct pruproc *pruproc = platform_get_drvdata(pdev);
++ void * __iomem va;
+
+- dev_dbg(&pdev->dev, "remove pru\n");
++ /* verify it's a word address */
++ if (da & 3)
++ return -EINVAL;
+
+- /* Unregister as remoteproc device */
+- rproc_del(pruproc->rproc);
+- rproc_put(pruproc->rproc);
++ /* get vaddr of device address (I) */
++ va = pru_d_da_to_va_block(ppc, da, NULL, sizeof(u32));
++ if (va == NULL)
++ return -EINVAL;
+
+- platform_set_drvdata(pdev, NULL);
++ *(u32 *)va = cpu_to_le32(val);
++ return 0;
++}
+
++static int pruproc_bin_sanity_check(struct rproc *rproc, const struct firmware *fw)
++{
+ return 0;
+ }
+
+-/* Handle probe of a modem device */
+-static int pruproc_probe(struct platform_device *pdev)
++/* Loads the firmware to shared memory. */
++static int pruproc_bin_load_segments(struct rproc *rproc, const struct firmware *fw)
+ {
+- struct device *dev = &pdev->dev;
+- struct pruproc *pruproc;
+- struct rproc *rproc;
+- struct resource *res;
+- struct pinctrl *pinctrl;
+- int err;
++ struct pruproc_core *ppc = rproc->priv;
++ struct device *dev = &rproc->dev;
++ void __iomem *va;
+
+- dev_dbg(dev, "probe pru\n");
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, CONTROL_SOFT_RST_N);
+
+- /* get pinctrl */
+- pinctrl = devm_pinctrl_get_select_default(dev);
+- if (IS_ERR(pinctrl)) {
+- err = PTR_ERR(pinctrl);
+- /* deferring probe */
+- if (err == -EPROBE_DEFER) {
+- dev_warn(dev, "deferring proble\n");
+- return err;
+- }
+- dev_warn(dev, "pins are not configured from the driver\n");
++ /* binary starts from 0 */
++ ppc->entry_point = 0;
++
++ va = pru_i_da_to_va_block(ppc, ppc->entry_point, NULL, fw->size);
++ if (va == NULL) {
++ dev_err(dev, "FW is larger than available space (%u)\n",
++ fw->size);
++ return -ENOMEM;
+ }
+
+- /* we only work on OF */
+- if (dev->of_node == NULL) {
+- dev_err(dev, "Only OF configuration supported\n");
+- err = -ENODEV;
+- goto fail_of_node;
++ /* just copy */
++ memcpy(va, fw->data, fw->size);
++
++ return 0;
++}
++
++static int
++pruproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
++{
++ const char *name = rproc->firmware;
++ struct device *dev = &rproc->dev;
++ struct elf32_hdr *ehdr;
++ char class;
++
++ if (!fw) {
++ dev_err(dev, "failed to load %s\n", name);
++ return -EINVAL;
+ }
+
+- pm_runtime_enable(dev);
+- err = pm_runtime_get_sync(dev);
+- if (err != 0) {
+- dev_err(dev, "pm_runtime_get_sync failed\n");
+- goto fail_pm_runtime_get_sync;
++ if (fw->size < sizeof(struct elf32_hdr)) {
++ dev_err(dev, "Image is too small\n");
++ return -EINVAL;
+ }
+
+- err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+- if (err) {
+- dev_err(dev, "dma_set_coherent_mask: %d\n", err);
+- goto fail_dma_set_coherent_mask;
++ ehdr = (struct elf32_hdr *)fw->data;
++
++ /* We only support ELF32 at this point */
++ class = ehdr->e_ident[EI_CLASS];
++ if (class != ELFCLASS32) {
++ dev_err(dev, "Unsupported class: %d\n", class);
++ return -EINVAL;
+ }
+
+- rproc = rproc_alloc(dev, pdev->name, &pruproc_ops,
+- "prutest.bin", sizeof(*pruproc));
+- if (!rproc) {
+- dev_err(dev, "rproc_alloc failed\n");
+- err = -ENOMEM;
+- goto fail_rproc_alloc;
++ /* PRU is little endian */
++ if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
++ dev_err(dev, "Unsupported firmware endianness\n");
++ return -EINVAL;
+ }
+
+- pruproc = rproc->priv;
+- pruproc->pdev = pdev;
+- pruproc->rproc = rproc;
++ if (fw->size < le32_to_cpu(ehdr->e_shoff) +
++ sizeof(struct elf32_shdr)) {
++ dev_err(dev, "Image is too small\n");
++ return -EINVAL;
++ }
+
+- platform_set_drvdata(pdev, pruproc);
++ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
++ dev_err(dev, "Image is corrupted (bad magic)\n");
++ return -EINVAL;
++ }
+
+- /* Set the PRU specific firmware handler */
+- rproc->fw_ops = &pruproc_fw_ops;
++ if (le16_to_cpu(ehdr->e_phnum) == 0) {
++ dev_err(dev, "No loadable segments\n");
++ return -EINVAL;
++ }
+
+- /* Register as a remoteproc device */
+- err = rproc_add(rproc);
+- if (err) {
+- dev_err(dev, "rproc_add failed\n");
+- goto fail_rproc_add;
++ if (le32_to_cpu(ehdr->e_phoff) > fw->size) {
++ dev_err(dev, "Firmware size is too small\n");
++ return -EINVAL;
+ }
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (res == NULL) {
+- dev_err(dev, "failed to parse MEM resource\n");
+- goto fail_platform_get_resource;
++ return 0;
++}
++
++static int
++pruproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
++{
++ struct device *dev = &rproc->dev;
++ struct pruproc_core *ppc = rproc->priv;
++ struct elf32_hdr *ehdr;
++ struct elf32_phdr *phdr;
++ int i, ret = 0;
++ const u8 *elf_data = fw->data;
++ u32 da, memsz, filesz, offset, flags;
++ void * __iomem va;
++
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, CONTROL_SOFT_RST_N);
++
++ ehdr = (struct elf32_hdr *)elf_data;
++ phdr = (struct elf32_phdr *)(elf_data + le32_to_cpu(ehdr->e_phoff));
++
++ /* go through the available ELF segments */
++ for (i = 0; i < le16_to_cpu(ehdr->e_phnum); i++, phdr++) {
++
++ da = le32_to_cpu(phdr->p_paddr);
++ memsz = le32_to_cpu(phdr->p_memsz);
++ filesz = le32_to_cpu(phdr->p_filesz);
++ offset = le32_to_cpu(phdr->p_offset);
++ flags = le32_to_cpu(phdr->p_flags);
++
++ if (le32_to_cpu(phdr->p_type) != PT_LOAD)
++ continue;
++
++ dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x"
++ " flags %c%c%c\n",
++ le32_to_cpu(phdr->p_type),
++ da, memsz, filesz,
++ (flags & PF_R) ? 'R' : '-',
++ (flags & PF_W) ? 'W' : '-',
++ (flags & PF_X) ? 'E' : '-');
++
++ /* PRU is not a unified address space architecture */
++ /* we need to map differently executable & data segments */
++
++ if (filesz > memsz) {
++ dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
++ filesz, memsz);
++ ret = -EINVAL;
++ break;
++ }
++
++ if (offset + filesz > fw->size) {
++ dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
++ offset + filesz, fw->size);
++ ret = -EINVAL;
++ break;
++ }
++
++ /* we can't use rproc_da_to_va (it relies on carveouts) */
++
++ /* text? to code area */
++ if (flags & PF_X)
++ va = pru_i_da_to_va_block(ppc, da, NULL, memsz);
++ else
++ va = pru_d_da_to_va_block(ppc, da, NULL, memsz);
++
++ /* check if valid section */
++ if (va == NULL) {
++ dev_err(dev, "fw: #%d @0x%x sz 0x%x bad\n",
++ i, da, memsz);
++ ret = -EINVAL;
++ break;
++ }
++
++ /* put the segment where the remote processor expects it */
++ if (filesz > 0)
++ memcpy(va, elf_data + offset, filesz);
++ else
++ memset(va, 0, memsz);
+ }
+
+- pruproc->vaddr = devm_ioremap(dev, res->start, resource_size(res));
+- if (pruproc->vaddr == NULL) {
+- dev_err(dev, "failed to parse MEM resource\n");
+- goto fail_devm_ioremap;
++ ppc->entry_point = le32_to_cpu(ehdr->e_entry);
++
++ return ret;
++}
++
++static
++u32 pruproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
++{
++ struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
++
++ return le32_to_cpu(ehdr->e_entry);
++}
++
++/* just return the built-firmware resources */
++static struct resource_table *
++pruproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
++ int *tablesz)
++{
++ struct pruproc_core *ppc = rproc->priv;
++
++ /* no resource table for this PRU */
++ if (ppc->table == NULL) {
++ *tablesz = 0;
++ return NULL;
+ }
+
+- dev_info(dev, "Loaded OK\n");
++ *tablesz = ppc->table_size;
++ return ppc->table;
++}
++
++void *get_resource_type(struct resource_table *res,
++ int type, int idx)
++{
++ struct fw_rsc_hdr *rsc_hdr;
++ int i, j;
++
++ j = 0;
++ for (i = 0; i < res->num; i++) {
++ rsc_hdr = (void *)res + res->offset[i];
++ if (type >= 0 && rsc_hdr->type != type)
++ continue;
++ if (j == idx)
++ return &rsc_hdr->data[0];
++ j++;
++ }
++
++ return NULL;
++}
++
++/* update the device's firmware resource with the allocated values */
++static int update_dev_rsc_table(struct pruproc_core *ppc)
++{
++ struct rproc *rproc = ppc->rproc;
++ struct device *dev = &rproc->dev;
++ struct rproc_vdev *rvdev;
++ struct rproc_vring *rvring;
++ struct pru_vring_info *vri;
++ struct fw_rsc_vdev *rsc_vdev;
++ int vdev_idx, i, cnt, err, j, vring_start, num_vrings;
++
++ /* no table; do nothing */
++ if (ppc->table == NULL)
++ return 0;
++
++ /* copy the resource table here */
++ memcpy(ppc->dev_table_va, ppc->table, ppc->table_size);
++
++ /* everything is initialized; fill in the real da & notify ids */
++ for (vdev_idx = 0; vdev_idx < ppc->num_vdevs; vdev_idx++) {
++ vring_start = ppc->vdev_vring_start[vdev_idx];
++ num_vrings = ppc->vdev_vring_count[vdev_idx];
++
++ /* find rvdev */
++ cnt = 0;
++ list_for_each_entry(rvdev, &rproc->rvdevs, node) {
++ if (cnt == vdev_idx)
++ break;
++ cnt++;
++ }
++ if (cnt != vdev_idx) {
++ dev_warn(dev, "rsc_vdev not found (continuing anyway)\n");
++ rvdev = NULL;
++ }
++
++ /* locate the vdev resource in the device memory */
++ rsc_vdev = get_resource_type(ppc->dev_table_va, RSC_VDEV,
++ vdev_idx);
++ if (rsc_vdev == NULL) {
++ dev_err(dev, "PRU#%d Failed to get RSV_VDEV #%d\n",
++ ppc->idx, vdev_idx);
++ err = -EINVAL;
++ goto err_fail;
++ }
++
++ for (i = 0; i < num_vrings; i++) {
++ j = vring_start + i;
++
++ vri = &ppc->vring_info[j];
++
++ if (rvdev != NULL)
++ rvring = &rvdev->vring[i];
++ else
++ rvring = NULL;
++
++ /* keep track of rproc's rvring */
++ vri->rvring = rvring;
++
++ rsc_vdev->vring[i].da = vri->da;
++ if (rvring != NULL)
++ rsc_vdev->vring[i].notifyid = rvring->notifyid;
++ else
++ rsc_vdev->vring[i].notifyid = -1; /* mark that it's not ready yet */
++
++ dev_info(dev, "VDEV#%d VR#%d da=0x%08x notifyid=0x%08x\n",
++ vdev_idx, i, vri->da, rvring->notifyid);
++ }
++ }
++
++#if 0
++ j = 0;
++ list_for_each_entry(rvdev, &rproc->rvdevs, node) {
++
++ /* get copied resource's VDEV */
++ rsc_vdev = get_resource_type(ppc->dev_table_va, RSC_VDEV,
++ vdev_idx);
++ if (rsc_vdev == NULL) {
++ dev_err(dev, "Failed to get RSV_VDEV #%d\n", vdev_idx);
++ err = -EINVAL;
++ goto err_fail;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(rvdev->vring); i++) {
++ rvring = &rvdev->vring[i];
++
++ if (j >= ARRAY_SIZE(ppc->vring_info)) {
++ dev_err(dev, "Too many vrings\n");
++ err = -ENOENT;
++ goto err_fail;
++ }
++
++ vri = &ppc->vring_info[j];
++
++ /* keep track of rproc's rvring */
++ vri->rvring = rvring;
++
++ rsc_vdev->vring[i].da = vri->da;
++ rsc_vdev->vring[i].notifyid = rvring->notifyid;
++
++ dev_info(dev, "VDEV#%d VR#%d da=0x%08x notifyid=0x%08x\n",
++ vdev_idx, i, vri->da, rvring->notifyid);
++
++ j++;
++ }
++
++ vdev_idx++;
++ }
++#endif
+
+ return 0;
+-fail_devm_ioremap:
+-fail_platform_get_resource:
+- rproc_del(rproc);
+-fail_rproc_add:
+- platform_set_drvdata(pdev, NULL);
+- rproc_put(rproc);
+-fail_rproc_alloc:
+-fail_dma_set_coherent_mask:
+-fail_of_node:
+- pm_runtime_disable(dev);
+-fail_pm_runtime_get_sync:
++err_fail:
++ return err;
++
++}
++
++/* PRU binary firmware handler operations */
++const struct rproc_fw_ops pruproc_bin_fw_ops = {
++ .find_rsc_table = pruproc_find_rsc_table,
++ .load = pruproc_bin_load_segments,
++ .sanity_check = pruproc_bin_sanity_check,
++};
++
++/* PRU elf handler operations */
++const struct rproc_fw_ops pruproc_elf_fw_ops = {
++ .find_rsc_table = pruproc_find_rsc_table,
++ .load = pruproc_elf_load_segments,
++ .sanity_check = pruproc_elf_sanity_check,
++ .get_boot_addr = pruproc_elf_get_boot_addr,
++};
++
++void dump_vring(struct vring *vring)
++{
++ int i;
++ struct vring_desc *vd;
++
++ pr_info("vring: num=%u desc @%p\n", vring->num, vring->desc);
++
++ for (i = 0; i < vring->num; i++) {
++ vd = &vring->desc[i];
++ pr_info(" d#%2d: a 0x%016llx l 0x%08x f 0x%04x n 0x%04x\n",
++ i, vd->addr, vd->len, vd->flags, vd->next);
++ }
++ pr_info(" avail: flags 0x%04x idx 0x%04x\n",
++ vring->avail->flags, vring->avail->idx);
++ for (i = 0; i < vring->num; i++) {
++ pr_info(" a#%2d: ring 0x%04x\n", i,
++ vring->avail->ring[i]);
++ }
++ pr_info(" avail: used_event_idx 0x%04x\n",
++ vring->avail->ring[vring->num]);
++
++ pr_info(" used: flags 0x%04x idx 0x%04x\n",
++ vring->used->flags, vring->used->idx);
++ for (i = 0; i < vring->num; i++) {
++ pr_info(" u#%2d: id 0x%08x len 0x%08x\n", i,
++ vring->used->ring[i].id,
++ vring->used->ring[i].len);
++ }
++}
++
++void dump_all_vrings(struct pruproc_core *ppc)
++{
++ struct device *dev = &ppc->rproc->dev;
++ struct vring *vr;
++ struct fw_rsc_vdev_vring *rsc_vr;
++ struct pru_vring_info *vri;
++ int i;
++
++ for (i = 0; i < ppc->num_vrings; i++) {
++ vri = &ppc->vring_info[i];
++
++ vr = &vri->vr;
++ rsc_vr = vri->rsc;
++
++ dev_dbg(dev, "VRING #%d (size %d)\n", i,
++ vring_size(vr->num, rsc_vr->align));
++ dump_vring(vr);
++ dev_dbg(dev, "\n");
++ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,
++ 16, 4, vr->desc,
++ vring_size(vr->num, rsc_vr->align),
++ false);
++ }
++}
++
++/* Kick the modem with specified notification id */
++static void pruproc_kick(struct rproc *rproc, int vqid)
++{
++ struct device *dev = &rproc->dev;
++ struct pruproc_core *ppc = rproc->priv;
++ struct pruproc *pp = ppc->pruproc;
++ int sysint;
++
++ dev_dbg(dev, "kick #%d vqid:%d\n", ppc->idx, vqid);
++
++ /* ARM to PRUx system event */
++ sysint = pp->target_to_sysev[TARGET_ARM_TO_PRU_IDX(ppc->idx)];
++
++ /* signal event */
++ if (sysint < 32)
++ pintc_write_reg(pp, PINTC_SRSR0, 1 << sysint);
++ else
++ pintc_write_reg(pp, PINTC_SRSR1, 1 << (sysint - 32));
++
++ // dump_all_vrings(ppc);
++}
++
++void dump_resource_table(const struct resource_table *res)
++{
++ const struct fw_rsc_hdr *rsc_hdr;
++ const struct fw_rsc_vdev *rsc_vdev;
++ const struct fw_rsc_vdev_vring *rsc_vring;
++ int i, j;
++
++ /* do nothing if given nothing */
++ if (res == NULL)
++ return;
++
++ pr_info("resource_table @%p\n", res);
++ pr_info(" .ver = 0x%08x\n", res->ver);
++ pr_info(" .num = 0x%08x\n", res->num);
++ for (i = 0; i < res->num; i++) {
++ rsc_hdr = (void *)res + res->offset[i];
++ pr_info(" rsc_hdr#%d: .type = 0x%08x\n", i,
++ rsc_hdr->type);
++ switch (rsc_hdr->type) {
++ case RSC_CARVEOUT:
++ pr_info(" CARVEOUT:\n");
++ break;
++ case RSC_DEVMEM:
++ pr_info(" DEVMEM:\n");
++ break;
++ case RSC_TRACE:
++ pr_info(" TRACE:\n");
++ break;
++ case RSC_VDEV:
++ pr_info(" VDEV:\n");
++ rsc_vdev = (void *)&rsc_hdr->data[0];
++ pr_info(" .id = 0x%08x\n", rsc_vdev->id);
++ pr_info(" .notifyid = 0x%08x\n", rsc_vdev->notifyid);
++ pr_info(" .dfeatures = 0x%08x\n", rsc_vdev->dfeatures);
++ pr_info(" .gfeatures = 0x%08x\n", rsc_vdev->gfeatures);
++ pr_info(" .config_len = 0x%08x\n", rsc_vdev->config_len);
++ pr_info(" .status = 0x%02x\n", rsc_vdev->status);
++ pr_info(" .num_of_vrings = 0x%02x\n", rsc_vdev->num_of_vrings);
++ for (j = 0; j < rsc_vdev->num_of_vrings; j++) {
++ rsc_vring = &rsc_vdev->vring[j];
++ pr_info(" VRING #%d:\n", j);
++ pr_info(" .da = 0x%08x\n",
++ rsc_vring->da);
++ pr_info(" .align = 0x%08x\n",
++ rsc_vring->align);
++ pr_info(" .num = 0x%08x\n",
++ rsc_vring->num);
++ pr_info(" .notifyid = 0x%08x\n",
++ rsc_vring->notifyid);
++ }
++ break;
++ }
++ }
++}
++
++/* Start the PRU modem */
++static int pruproc_start(struct rproc *rproc)
++{
++ struct device *dev = &rproc->dev;
++ struct pruproc_core *ppc = rproc->priv;
++ u32 val;
++ int err;
++
++ /* start the processors only when all devices have booted */
++ if (ppc->num_vdevs == 0 || atomic_inc_return(&ppc->bootcnt) == 1) {
++
++ dev_info(dev, "start PRU #%d entry-point 0x%x\n",
++ ppc->idx, ppc->entry_point);
++
++#if 1
++ if (ppc->table)
++ dump_resource_table(ppc->table);
++
++ err = update_dev_rsc_table(ppc);
++ if (err != 0) {
++ dev_err(dev, "failed to update resource table\n");
++ return err;
++ }
++
++ if (ppc->dev_table_va)
++ dump_resource_table(ppc->dev_table_va);
++
++#endif
++
++
++ val = CONTROL_ENABLE | ((ppc->entry_point >> 2) << 16);
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, val);
++ }
++
++ return 0;
++}
++
++/* Stop the PRU modem */
++static int pruproc_stop(struct rproc *rproc)
++{
++ struct device *dev = &rproc->dev;
++ struct pruproc_core *ppc = rproc->priv;
++ u32 val;
++
++ /* we have to copy the resource table and update the device addresses */
++ if (1 || ppc->num_vdevs == 0 || atomic_dec_return(&ppc->bootcnt) == 0) {
++
++ dev_info(dev, "PRU#%d stop\n", ppc->idx);
++
++ val = pcntrl_read_reg(ppc, PCTRL_CONTROL);
++ val &= ~CONTROL_ENABLE;
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, val);
++ }
++
++ return 0;
++}
++
++static void *pruproc_alloc_vring(struct rproc *rproc,
++ const struct fw_rsc_vdev_vring *rsc_vring,
++ int size, dma_addr_t *dma)
++{
++ struct device *dev = &rproc->dev;
++ struct pruproc_core *ppc = rproc->priv;
++ struct pru_vring_info *vri;
++ struct vring *vring;
++ void * __iomem va;
++ dma_addr_t dma_tmp;
++ int i;
++
++ dev_dbg(dev, "PRU#%d alloc rsc_vring %p\n",
++ ppc->idx, rsc_vring);
++
++ /* find vring index */
++ for (i = 0; i < ppc->num_vrings; i++) {
++ if (rsc_vring == ppc->vring_info[i].rsc)
++ break;
++ }
++
++ if (i >= ppc->num_vrings) {
++ dev_err(dev, "PRU #%d could not find rsc_vring at %p\n",
++ ppc->idx, rsc_vring);
++ return NULL;
++ }
++
++ if (dma == NULL)
++ dma = &dma_tmp;
++
++ if (rsc_vring->da != 0) {
++ dev_dbg(dev, "PRU #%d alloc vring #%d from internal memory\n",
++ ppc->idx, i);
++ va = pru_d_da_to_va_block(ppc, rsc_vring->da, dma, size);
++ } else {
++ dev_dbg(dev, "PRU #%d alloc vring #%d dma_alloc_coherent\n",
++ ppc->idx, i);
++ va = dma_alloc_coherent(dev->parent, PAGE_ALIGN(size),
++ dma, GFP_KERNEL);
++ }
++
++ if (va == NULL) {
++ dev_err(dev, "PRU #%d could not allocate vring %p\n",
++ ppc->idx, rsc_vring);
++ return NULL;
++ }
++
++ /* setup vring for use */
++ vri = &ppc->vring_info[i];
++ vring = &vri->vr;
++ vring_init(vring, rsc_vring->num, va, rsc_vring->align);
++
++ /* save VA & PA */
++ vri->va = va;
++ vri->pa = *dma;
++ vri->da = pru_d_pa_to_da(ppc, *dma);
++
++ dev_dbg(dev, "PRU #%d vring #%d da=0x%x, va=%p, dma=0x%llx size=%u\n",
++ ppc->idx, i, rsc_vring->da, va, (unsigned long long)*dma, size);
++
++ return va;
++}
++
++static void pruproc_free_vring(struct rproc *rproc,
++ const struct fw_rsc_vdev_vring *rsc_vring,
++ int size, void *va, dma_addr_t dma)
++{
++ struct device *dev = &rproc->dev;
++
++ /* if DA is NULL, means we allocated via dma_alloc_coherent */
++ if (rsc_vring->da == 0)
++ dma_free_coherent(dev->parent, PAGE_ALIGN(size), va, dma);
++}
++
++static struct rproc_ops pruproc_ops = {
++ .start = pruproc_start,
++ .stop = pruproc_stop,
++ .kick = pruproc_kick,
++
++ .alloc_vring = pruproc_alloc_vring,
++ .free_vring = pruproc_free_vring,
++};
++
++static ssize_t pruproc_store_load(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pruproc *pp = platform_get_drvdata(pdev);
++ struct pruproc_core *ppc;
++ char *fw_name[MAX_PRUS];
++ const char *s, *e, *t;
++ int i, pru_idx, sz, err;
++ const struct firmware *fw;
++ u32 val;
++
++ memset(fw_name, 0, sizeof(fw_name));
++
++ s = buf;
++ while (*s != '\0' && *s != '\n') {
++ e = strchr(s, ',');
++ if (e == NULL) {
++ e = s + strlen(s);
++ while (e > buf && e[-1] == '\n')
++ e--;
++ }
++ t = strchr(s, ':');
++ if (t == NULL) {
++ t = s;
++ pru_idx = 0;
++ } else {
++ t++;
++ pru_idx = simple_strtoul(s, NULL, 10);
++ }
++
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ if (pru_idx == ppc->idx)
++ break;
++ }
++ if (i >= pp->num_prus) {
++ dev_err(dev, "Can not find PRU#%d\n", pru_idx);
++ return -EINVAL;
++ }
++
++ sz = e - t;
++ fw_name[pru_idx] = kzalloc(sz + 1, GFP_KERNEL);
++ if (fw_name[pru_idx] == NULL)
++ return -ENOMEM;
++ memcpy(fw_name[pru_idx], t, sz);
++ fw_name[pru_idx][sz] = '\0';
++
++ s = e;
++ if (*s == ',')
++ s++;
++ }
++
++ /* first halt every PRU affected */
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++
++ if (fw_name[ppc->idx] == NULL)
++ continue;
++
++ /* keep it in reset */
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, CONTROL_SOFT_RST_N);
++
++ dev_info(dev, "PRU#%d halted\n", ppc->idx);
++
++ }
++
++ /* load every PRU */
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ if (fw_name[ppc->idx] == NULL)
++ continue;
++
++ dev_info(dev, "PRU#%d loading %s\n", ppc->idx, fw_name[ppc->idx]);
++
++ /* note this is not the rproc device */
++ err = request_firmware(&fw, fw_name[ppc->idx], dev);
++ if (err != 0) {
++ dev_err(dev, "PRU#%d Failed to load firmware %s\n",
++ ppc->idx, fw_name[ppc->idx]);
++ return err;
++ }
++
++ err = pruproc_elf_load_segments(ppc->rproc, fw);
++ if (err != 0) {
++ dev_err(dev, "PRU#%d Failed to update firmware %s\n",
++ ppc->idx, fw_name[ppc->idx]);
++ return err;
++ }
++
++ release_firmware(fw);
++ }
++
++ /* start every PRU affected */
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ if (fw_name[ppc->idx] == NULL)
++ continue;
++
++ dev_info(dev, "PRU#%d starting %s\n", ppc->idx, fw_name[ppc->idx]);
++
++ val = CONTROL_ENABLE | ((ppc->entry_point >> 2) << 16);
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, val);
++
++ /* and free */
++ kfree(fw_name[ppc->idx]);
++ fw_name[ppc->idx] = NULL;
++ };
++
++ return strlen(buf);
++}
++
++static ssize_t pruproc_store_reset(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pruproc *pp = platform_get_drvdata(pdev);
++ struct pruproc_core *ppc;
++ int i;
++ u32 val;
++
++ /* first halt every PRU affected */
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ /* keep it in reset */
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, CONTROL_SOFT_RST_N);
++ }
++
++ /* start every PRU affected */
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ val = CONTROL_ENABLE | ((ppc->entry_point >> 2) << 16);
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, val);
++
++ };
++
++ return strlen(buf);
++}
++
++static DEVICE_ATTR(load, S_IWUSR, NULL, pruproc_store_load);
++static DEVICE_ATTR(reset, S_IWUSR, NULL, pruproc_store_reset);
++
++/* PRU is unregistered */
++static int pruproc_remove(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct pruproc *pp = platform_get_drvdata(pdev);
++ struct pruproc_core *ppc;
++ int i;
++
++ dev_dbg(dev, "remove pru\n");
++
++ device_remove_file(dev, &dev_attr_reset);
++ device_remove_file(dev, &dev_attr_load);
++
++ /* Unregister as remoteproc device */
++ for (i = pp->num_prus - 1; i >= 0; i--) {
++ ppc = pp->pruc[i];
++ rproc_del(ppc->rproc);
++ rproc_put(ppc->rproc);
++
++ if (ppc->dev_table_va != NULL)
++ dma_free_coherent(dev, PAGE_ALIGN(ppc->table_size),
++ ppc->dev_table_va, ppc->dev_table_pa);
++ }
++
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++#define PRU_HALT_INSN 0x2a000000
++
++#define PRU_SC_HALT 0
++#define PRU_SC_PUTC 1
++#define PRU_SC_EXIT 2
++#define PRU_SC_PUTS 3
++#define PRU_SC_GET_CFG 4
++#define PRU_SC_GET_CFG_VRING_NR 0
++#define PRU_SC_GET_CFG_VRING_INFO 1
++#define PRU_SC_GET_CFG_RESOURCE_TABLE 2
++
++struct pru_dev_vring_info {
++ u32 paddr;
++ u32 num;
++ u32 align;
++ u32 pad;
++};
++
++static int pru_handle_syscall(struct pruproc_core *ppc)
++{
++ struct pruproc *pp = ppc->pruproc;
++ struct device *dev = &pp->pdev->dev;
++ u32 val, addr, scno, arg0, arg1, arg2, ret;
++ int err, valid_sc;
++ void * __iomem va;
++ struct pru_vring_info *vri;
++ struct pru_dev_vring_info *dvri;
++
++ /* check whether it's halted */
++ val = pcntrl_read_reg(ppc, PCTRL_CONTROL);
++ if ((val & CONTROL_RUNSTATE) != 0) {
++ dev_dbg(dev, "PRU #%d not halted\n",
++ ppc->idx);
++ return -EINVAL;
++ }
++
++ /* read the instruction */
++ addr = pcntrl_read_reg(ppc, PCTRL_STATUS) * 4;
++ err = pru_i_read_u32(ppc, addr, &val);
++ if (err != 0) {
++ dev_err(dev, "PRU #%d halted PC 0x%x bad\n", ppc->idx, addr);
++ return err;
++ }
++
++ /* check whether it's a halt instruction */
++ if (val != PRU_HALT_INSN) {
++ dev_err(dev, "PRU #%d not in halt insn (addr=0x%x val 0x%08x)\n",
++ ppc->idx, addr, val);
++ return -EFAULT;
++ }
++
++ valid_sc = 0;
++ scno = pdbg_read_reg(ppc, PDBG_GPREG(14));
++ arg0 = pdbg_read_reg(ppc, PDBG_GPREG(15));
++ arg1 = pdbg_read_reg(ppc, PDBG_GPREG(16));
++ arg2 = pdbg_read_reg(ppc, PDBG_GPREG(17));
++ ret = 0; /* by default we return 0 */
++
++ switch (scno) {
++ case PRU_SC_HALT:
++ dev_info(dev, "P%d HALT\n",
++ ppc->idx);
++ return 1;
++
++ case PRU_SC_PUTC:
++ dev_info(dev, "P%d PUTC '%c'\n",
++ ppc->idx, (char)(arg0 & 0xff));
++ break;
++
++ case PRU_SC_EXIT:
++ dev_info(dev, "P%d EXIT %d\n",
++ ppc->idx, (int)arg0);
++ return 1;
++
++ case PRU_SC_PUTS:
++ /* pointers can only be in own data ram */
++ va = pru_d_da_to_va(ppc, arg0, NULL);
++ if (va == NULL) {
++ dev_err(dev, "PRU #%d SC PUTS bad 0x%x\n",
++ ppc->idx, arg0);
++ ret = (u32)-1;
++ } else {
++ dev_info(dev, "P%d PUTS '%s'\n",
++ ppc->idx, (char *)va);
++ }
++ break;
++
++ case PRU_SC_GET_CFG:
++ switch (arg0) {
++ case PRU_SC_GET_CFG_VRING_NR:
++ ret = ppc->num_vrings; /* two rings */
++ dev_dbg(dev, "P%d GET_CFG VRING_NR %d\n",
++ ppc->idx, (int)ret);
++ break;
++ case PRU_SC_GET_CFG_VRING_INFO:
++ if (arg1 >= ppc->num_vrings) {
++ dev_err(dev, "PRU #%d SC "
++ "GET_CFG_VRING_INFO "
++ "bad idx %d\n",
++ ppc->idx, arg1);
++ }
++
++ va = pru_d_da_to_va(ppc, arg2, NULL);
++ if (va == NULL) {
++ dev_err(dev, "PRU #%d SC "
++ "GET_CFG_VRING_INFO "
++ "bad 0x%x\n",
++ ppc->idx, arg2);
++ ret = (u32)-1;
++ break;
++ }
++ dvri = va;
++ vri = &ppc->vring_info[arg1];
++
++ /* fill it in */
++ dvri->paddr = vri->pa;
++ dvri->num = vri->rsc->num;
++ dvri->align = vri->rsc->align;
++ dvri->pad = 0;
++
++ dev_dbg(dev, "P%d GET_CFG VRING_INFO %d\n",
++ ppc->idx, (int)ret);
++ break;
++
++ case PRU_SC_GET_CFG_RESOURCE_TABLE:
++ /* just return the physical address */
++ ret = (u32)ppc->dev_table_pa;
++ dev_dbg(dev, "P%d GET_CFG RESOURCE_TABLE 0x%x\n",
++ ppc->idx, ret);
++ break;
++
++ default:
++ dev_err(dev, "PRU #%d SC "
++ "GET_CFG bad 0x%x\n",
++ ppc->idx, arg1);
++ ret = (u32)-1;
++ break;
++ }
++ break;
++
++ default:
++ dev_err(dev, "PRU #%d SC Unknown (%d)\n",
++ ppc->idx, scno);
++ return 1;
++ }
++
++ /* return code */
++ pdbg_write_reg(ppc, PDBG_GPREG(14), ret);
++
++ /* skip over the HALT insn */
++ val = pcntrl_read_reg(ppc, PCTRL_CONTROL);
++ val &= 0xffff;
++ addr = pcntrl_read_reg(ppc, PCTRL_STATUS);
++ val |= ((addr + 1) << 16) | CONTROL_ENABLE;
++ val &= ~CONTROL_SOFT_RST_N;
++
++ /* dev_dbg(dev, "PRU#%d new PCTRL_CONTROL=0x%08x\n",
++ ppc->idx, val); */
++
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, val);
++
++ return 0;
++}
++
++static irqreturn_t pru_handler(int irq, void *data)
++{
++ struct pruproc *pp = data;
++ struct pruproc_core *ppc;
++ struct pru_sysev_target *pst;
++ struct rproc *rproc;
++ struct device *dev = &pp->pdev->dev;
++ int pru_idx, i, ev, sysint, handled, ret;
++ struct pru_vring_info *vri;
++ u32 val;
++
++ /* find out which IRQ we got */
++ for (i = 0; i < pp->num_irqs; i++)
++ if (irq == pp->irqs[i])
++ break;
++ if (i >= pp->num_irqs)
++ return IRQ_NONE;
++
++ ev = pp->events[i];
++
++ /* first, check whether the interrupt is enabled */
++ val = pintc_read_reg(pp, PINTC_HIER);
++ if ((val & (1 << ev)) == 0)
++ return IRQ_NONE;
++
++ /* check non-pending bit of specific event */
++ val = pintc_read_reg(pp, PINTC_HIPIR0 + (ev << 2));
++ if ((val & HIPIR_NOPEND) != 0)
++ return IRQ_NONE;
++
++ sysint = val & 0x3f;
++
++ /* clear event */
++ if (sysint < 32)
++ pintc_write_reg(pp, PINTC_SECR0, 1 << sysint);
++ else
++ pintc_write_reg(pp, PINTC_SECR1, 1 << (sysint - 32));
++
++ /* get the source of the sysevent */
++ pst = &pp->sysev_to_target[sysint];
++ if (pst->valid == 0 || pst->source < -1 || pst->target < -1) {
++ dev_warn(dev, "sysevent not handled %d; disabling\n",
++ sysint);
++ goto disable_int;
++ }
++
++ /* target self? not handled */
++ if (pst->source == TARGET_ARM) {
++ dev_warn(dev, "sysevent %d has host as source; disabling\n",
++ sysint);
++ goto disable_int;
++ }
++
++ /* find out which PRU was it */
++ pru_idx = TARGET_PRU_TO_PRU_IDX(pst->source);
++ ppc = pp->pru_to_pruc[pru_idx];
++ if (ppc == NULL) {
++ dev_warn(dev, "systevent %d from bad PRU; disabling\n",
++ sysint);
++ goto disable_int;
++ }
++
++ /* ok, got the source PRU */
++ rproc = ppc->rproc;
++
++ handled = 0;
++
++ /* we either handle a vring or not */
++ if (!pst->vring) {
++ ret = pru_handle_syscall(ppc);
++ if (ret == 0) /* system call handled */
++ handled++;
++ } else {
++ /* handle any vrings action */
++ for (i = 0; i < ppc->num_vrings; i++) {
++ vri = &ppc->vring_info[i];
++ if (vri->rvring == NULL)
++ continue;
++ ret = rproc_vq_interrupt(rproc, vri->rvring->notifyid);
++ if (ret == IRQ_HANDLED) {
++ dev_dbg(dev, "PRU #%d; vring irq handled\n",
++ ppc->idx);
++ handled++;
++ }
++
++ }
++ }
++
++#if 0
++ if (!handled) {
++ dev_err(dev, "sysint not handled; disabling interrupt\n");
++ goto disable_int;
++
++ }
++#endif
++
++ return IRQ_HANDLED;
++
++disable_int:
++ /* disable the interrupt */
++ pintc_write_reg(pp, PINTC_HIDISR, ev);
++ return IRQ_HANDLED;
++}
++
++static int build_rsc_table(struct platform_device *pdev,
++ struct device_node *node, struct pruproc_core *ppc)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *rnode = NULL; /* resource table node */
++ struct device_node *rvnode = NULL; /* vdev node */
++ // struct pruproc *pp = ppc->pruproc;
++ struct resource_table *rsc;
++ struct fw_rsc_hdr *rsc_hdr;
++ struct fw_rsc_vdev *rsc_vdev;
++ struct pru_vring_info *vri;
++ char vring_name[16];
++ u32 vring_data[4], val;
++ struct fw_rsc_vdev_vring *rsc_vring;
++ void *table, *p;
++ int i, err, table_size, num_vrings, num_vdevs, vdev_idx, vring_start;
++
++ /* verify OF data */
++
++ /* first find a valid resource-table node */
++ for_each_child_of_node(node, rnode) {
++ if (of_property_read_bool(rnode, "resource-table"))
++ break;
++ }
++
++ /* no resource node found */
++ if (rnode == NULL) {
++ dev_warn(dev, "No resource-table node node; slave PRU\n");
++ return 0;
++ }
++
++ /* count number of vdevs & vrings */
++
++ table_size = sizeof(struct resource_table);
++
++ num_vdevs = 0;
++ num_vrings = 0;
++ for_each_child_of_node(rnode, rvnode) {
++
++ if (!of_property_read_bool(rvnode, "vdev-rproc-serial") &&
++ !of_property_read_bool(rvnode, "vdev-rpmsg"))
++ continue;
++
++ /* size per each vdev */
++ table_size += sizeof(u32) +
++ sizeof(struct fw_rsc_hdr) +
++ sizeof(struct fw_rsc_vdev);
++
++ ppc->vdev_vring_start[num_vdevs] = num_vrings;
++ for (i = 0; num_vrings < ARRAY_SIZE(ppc->vring_info); i++) {
++ snprintf(vring_name, sizeof(vring_name), "vring-%d", i);
++ if (of_property_read_u32_array(rvnode, vring_name,
++ vring_data, ARRAY_SIZE(vring_data)) != 0)
++ break;
++ num_vrings++;
++ }
++ ppc->vdev_vring_count[num_vdevs] = i;
++
++ /* size for the rings */
++ table_size += i * sizeof(struct fw_rsc_vdev_vring);
++
++ num_vdevs++;
++ }
++
++ dev_info(dev, "PRU%d #%d vdevs, #%d vrings total\n",
++ ppc->idx, num_vdevs, num_vrings);
++
++ table = devm_kzalloc(dev, table_size, GFP_KERNEL);
++ if (table == NULL) {
++ dev_err(dev, "Failed to allocate resource table\n");
++ err = -ENOMEM;
++ goto err_fail;
++ }
++ ppc->table = table;
++ ppc->table_size = table_size;
++ ppc->num_vdevs = num_vdevs;
++ ppc->num_vrings = num_vrings;
++
++ p = table; /* pointer at start */
++
++ /* resource table */
++ rsc = p;
++ p += sizeof(*rsc);
++ rsc->ver = 1; /* resource table version 1 */
++ rsc->num = ppc->num_vdevs;
++
++ p += rsc->num * sizeof(u32); /* point after offsets */
++
++ vdev_idx = 0;
++
++ /* now loop over the vdevs */
++ for_each_child_of_node(rnode, rvnode) {
++
++ if (!of_property_read_bool(rvnode, "vdev-rproc-serial") &&
++ !of_property_read_bool(rvnode, "vdev-rpmsg"))
++ continue;
++
++ rsc_hdr = p;
++ rsc->offset[vdev_idx] = p - table;
++ /* resource header */
++ p += sizeof(*rsc_hdr);
++
++ rsc_hdr->type = RSC_VDEV;
++
++ /* vdev */
++ rsc_vdev = p;
++ p += sizeof(*rsc_vdev);
++ ppc->rsc_vdev[vdev_idx] = rsc_vdev;
++
++ if (of_property_read_bool(rvnode, "vdev-rproc-serial")) {
++ rsc_vdev->id = VIRTIO_ID_RPROC_SERIAL;
++ /* extra configuration possible here */
++ } else if (of_property_read_bool(rvnode, "vdev-rpmsg")) {
++ rsc_vdev->id = VIRTIO_ID_RPMSG;
++ /* extra configuration possible here */
++ }
++
++ err = of_property_read_u32(rvnode, "notifyid", &val);
++ if (err != 0) {
++ dev_err(dev, "no notifyid vdev property\n");
++ goto err_fail;
++ }
++ rsc_vdev->notifyid = val;
++ rsc_vdev->dfeatures = 0;
++ rsc_vdev->gfeatures = 0;
++ rsc_vdev->config_len = 0;
++ rsc_vdev->status = 0;
++
++ /* start and count for vrings for this vdev */
++ vring_start = ppc->vdev_vring_start[vdev_idx];
++ num_vrings = ppc->vdev_vring_count[vdev_idx];
++
++ rsc_vdev->num_of_vrings = num_vrings;
++
++ for (i = 0; i < num_vrings; i++) {
++ rsc_vring = p;
++ p += sizeof(*rsc_vring);
++
++ vri = &ppc->vring_info[i + vring_start];
++
++ vri->rsc = rsc_vring;
++
++ snprintf(vring_name, sizeof(vring_name), "vring-%d",
++ i);
++ err = of_property_read_u32_array(rvnode, vring_name,
++ vring_data, ARRAY_SIZE(vring_data));
++ if (err != 0) {
++ dev_err(dev, "no %s property\n", vring_name);
++ goto err_fail;
++ }
++ rsc_vring->da = vring_data[0];
++ rsc_vring->align = vring_data[1];
++ rsc_vring->num = vring_data[2];
++ rsc_vring->notifyid = vring_data[3];
++ }
++
++ vdev_idx++;
++ }
++
++ /* all done, create the device copy */
++ ppc->dev_table_va = dma_alloc_coherent(dev,
++ PAGE_ALIGN(ppc->table_size), &ppc->dev_table_pa,
++ GFP_KERNEL);
++ if (ppc->dev_table_va == NULL) {
++ dev_err(dev, "Failed to dma_alloc dev resource table\n");
++ err = -ENOMEM;
++ goto err_fail;
++ }
++
++ err = 0;
++
++err_fail:
++ of_node_put(rnode);
++
++ return err;
++}
++
++static int read_map_property(struct device *dev,
++ struct device_node *node, const char *propname,
++ int *map, int max_idx, int max_val)
++{
++ struct property *prop;
++ int i, idx, val, cnt, proplen, err;
++ u32 *arr, *p;
++
++ /* check node & propname */
++ if (node == NULL || propname == NULL) {
++ dev_err(dev, "Bad arguments\n");
++ return -EINVAL;
++ }
++
++ /* find property */
++ prop = of_find_property(node, propname, &proplen);
++ if (prop == NULL) {
++ dev_err(dev, "Can't find %s property\n", propname);
++ return -ENOENT;
++ }
++
++ /* verify valid size (must be pairs of u32 items) */
++ if ((proplen % (sizeof(u32) * 2)) != 0) {
++ dev_err(dev, "Bad length (%d) of %s property\n",
++ proplen, propname);
++ return -EINVAL;
++ }
++
++ /* allocate temporary buffer */
++ arr = devm_kzalloc(dev, proplen, GFP_KERNEL);
++ if (arr == NULL) {
++ dev_err(dev, "Alloc failed on %s property\n", propname);
++ return -ENOMEM;
++ }
++
++ /* the number of pairs */
++ cnt = proplen / (sizeof(arr[0]) * 2);
++
++ /* now read it */
++ err = of_property_read_u32_array(node, propname, arr, cnt * 2);
++ if (err != 0) {
++ dev_err(dev, "Failed to read %s property\n", propname);
++ return err;
++ }
++
++ /* now read pairs and fill in the map */
++ for (i = 0, p = arr; i < cnt; i++, p += 2) {
++ idx = p[0];
++ val = p[1];
++ if ((unsigned int)idx >= max_idx) {
++ dev_err(dev, "%s[%d] bad map idx %d\n",
++ propname, i, idx);
++ return err;
++ }
++ if ((unsigned int)val >= max_val) {
++ dev_err(dev, "%s[%d] bad map val %d\n",
++ propname, i, val);
++ return err;
++ }
++ /* fill in map */
++ map[idx] = val;
++ dev_info(dev, "%s [%d] <- %d\n", propname, idx, val);
++ }
++
++ devm_kfree(dev, arr);
++
++ return 0;
++}
++
++static int configure_pintc(struct platform_device *pdev, struct pruproc *pp)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *node = dev->of_node;
++ int err, i, idx, ch, host;
++ uint64_t sysevt_mask;
++ uint32_t ch_mask;
++ uint32_t host_mask;
++ u32 val;
++
++ /* retreive the maps */
++ err = read_map_property(dev, node, "sysevent-to-channel-map",
++ pp->sysev_to_ch, ARRAY_SIZE(pp->sysev_to_ch),
++ MAX_PRU_CHANNELS);
++ if (err != 0)
++ return err;
++
++ err = read_map_property(dev, node, "channel-to-host-interrupt-map",
++ pp->ch_to_host, ARRAY_SIZE(pp->ch_to_host),
++ MAX_PRU_HOST_INT);
++ if (err != 0)
++ return err;
++
++ err = of_property_read_u32_array(node, "target-to-sysevent-map",
++ pp->target_to_sysev, ARRAY_SIZE(pp->target_to_sysev));
++ if (err != 0)
++ return err;
++
++ /* now configure the pintc appropriately */
++
++ /* configure polarity and type (all active high & pulse) */
++ pintc_write_reg(pp, PINTC_SIPR0, 0xffffffff);
++ pintc_write_reg(pp, PINTC_SIPR1, 0xffffffff);
++
++ /* clear all channel mapping registers */
++ for (i = PINTC_CMR0; i <= PINTC_CMR15; i += 4)
++ pintc_write_reg(pp, i, 0);
++
++ sysevt_mask = 0;
++ ch_mask = 0;
++ host_mask = 0;
++
++ /* set channel mapping registers we have */
++ for (i = 0; i < ARRAY_SIZE(pp->sysev_to_ch); i++) {
++
++ ch = pp->sysev_to_ch[i];
++ if (ch < 0)
++ continue;
++
++ /* CMR format: ---CH3---CH2---CH1---CH0 */
++
++ /* 4 settings in each register */
++ idx = i / 4;
++
++ /* update CMR entry */
++ val = pintc_read_reg(pp, PINTC_CMR0 + idx * 4);
++ val |= (u32)ch << ((i & 3) * 8);
++ pintc_write_reg(pp, PINTC_CMR0 + idx * 4, val);
++
++ /* set bit in the sysevent mask */
++ sysevt_mask |= 1LLU << i;
++ /* set bit in the channel mask */
++ ch_mask |= 1U << ch;
++
++ dev_dbg(dev, "SYSEV%d -> CH%d (CMR%d 0x%08x)\n",
++ i, ch, idx,
++ pintc_read_reg(pp, PINTC_CMR0 + idx * 4));
++ }
++
++ /* clear all host mapping registers */
++ for (i = PINTC_HMR0; i <= PINTC_HMR2; i += 4)
++ pintc_write_reg(pp, i, 0);
++
++ /* set host mapping registers we have */
++ for (i = 0; i < ARRAY_SIZE(pp->ch_to_host); i++) {
++
++ host = pp->ch_to_host[i];
++ if (host < 0)
++ continue;
++
++ /* HMR format: ---HI3---HI2---HI1---HI0 */
++
++ /* 4 settings in each register */
++ idx = i / 4;
++
++ /* update HMR entry */
++ val = pintc_read_reg(pp, PINTC_HMR0 + idx * 4);
++ val |= (u32)host << ((i & 3) * 8);
++ pintc_write_reg(pp, PINTC_HMR0 + idx * 4, val);
++
++ /* set bit in the channel mask */
++ ch_mask |= 1U << i;
++ /* set bit in the sysevent mask */
++ host_mask |= 1U << host;
++
++ dev_dbg(dev, "CH%d -> HOST%d (HMR%d 0x%08x)\n",
++ i, host, idx,
++ pintc_read_reg(pp, PINTC_HMR0 + idx * 4));
++ }
++
++ /* configure polarity and type (all active high & pulse) */
++ pintc_write_reg(pp, PINTC_SITR0, 0);
++ pintc_write_reg(pp, PINTC_SITR1, 0);
++
++ dev_dbg(dev, "sysevt_mask=0x%016llx ch_mask=0x%08x host_mask=0x%08x\n",
++ sysevt_mask, ch_mask, host_mask);
++
++ /* enable sys-events */
++ pintc_write_reg(pp, PINTC_ESR0, (u32)sysevt_mask);
++ pintc_write_reg(pp, PINTC_SECR0, (u32)sysevt_mask);
++ pintc_write_reg(pp, PINTC_ESR1, (u32)(sysevt_mask >> 32));
++ pintc_write_reg(pp, PINTC_SECR1, (u32)(sysevt_mask >> 32));
++
++ /* enable host interrupts */
++ for (i = 0; i < MAX_PRU_HOST_INT; i++) {
++ if ((host_mask & (1 << i)) != 0)
++ pintc_write_reg(pp, PINTC_HIEISR, i);
++ }
++
++ /* global interrupt enable */
++ pintc_write_reg(pp, PINTC_GER, 1);
++
++ return 0;
++}
++
++static int pruproc_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *node = dev->of_node;
++ struct device_node *pnode = NULL;
++ struct pruproc *pp;
++ struct pruproc_core *ppc;
++ struct pru_sysev_target *pst;
++ const char *fw_name;
++ int pm_get = 0;
++ struct rproc *rproc = NULL;
++ struct resource *res;
++ struct pinctrl *pinctrl;
++ int err, i, j, irq, sysev;
++ u32 tmparr[4], pru_idx;
++ u32 tmpev[MAX_ARM_PRU_INTS];
++
++ /* get pinctrl */
++ pinctrl = devm_pinctrl_get_select_default(dev);
++ if (IS_ERR(pinctrl)) {
++ err = PTR_ERR(pinctrl);
++ /* deferring probe */
++ if (err == -EPROBE_DEFER) {
++ dev_warn(dev, "deferring proble\n");
++ return err;
++ }
++ dev_warn(dev, "pins are not configured from the driver\n");
++ }
++
++ /* we only work on OF */
++ if (node == NULL) {
++ dev_err(dev, "Only OF configuration supported\n");
++ err = -ENODEV;
++ goto err_fail;
++ }
++
++ pm_runtime_enable(dev);
++ err = pm_runtime_get_sync(dev);
++ if (err != 0) {
++ dev_err(dev, "pm_runtime_get_sync failed\n");
++ goto err_fail;
++ }
++ pm_get = 1;
++
++ err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
++ if (err) {
++ dev_err(dev, "dma_set_coherent_mask: %d\n", err);
++ goto err_fail;
++ }
++
++ pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
++ if (pp == NULL) {
++ dev_err(dev, "failed to allocate pruproc\n");
++ err = -ENOMEM;
++ goto err_fail;
++
++ }
++
++ /* link the device with the pruproc */
++ platform_set_drvdata(pdev, pp);
++ pp->pdev = pdev;
++
++ /* prepare the irqs */
++ for (i = 0; i < ARRAY_SIZE(pp->irqs); i++)
++ pp->irqs[i] = -1;
++
++ /* prepare the events */
++ for (i = 0; i < ARRAY_SIZE(pp->events); i++)
++ pp->events[i] = -1;
++
++ /* prepare the sysevevent to channel map */
++ for (i = 0; i < ARRAY_SIZE(pp->sysev_to_ch); i++)
++ pp->sysev_to_ch[i] = -1;
++
++ /* prepare the channel to hostint map */
++ for (i = 0; i < ARRAY_SIZE(pp->ch_to_host); i++)
++ pp->ch_to_host[i] = -1;
++
++ /* finally register the interrupts */
++ for (i = 0; i < ARRAY_SIZE(pp->irqs); i++) {
++
++ err = platform_get_irq(pdev, i);
++ if (err < 0)
++ break;
++ irq = err;
++ pp->irqs[i] = irq;
++ }
++ pp->num_irqs = i;
++ dev_info(dev, "#%d PRU interrupts registered\n", pp->num_irqs);
++
++ /* make sure this fits */
++ if (pp->num_irqs > ARRAY_SIZE(tmpev)) {
++ dev_err(dev, "Too many irqs (%d)\n", pp->num_irqs);
++ goto err_fail;
++ }
++
++ /* read the events (host ints) */
++ err = of_property_read_u32_array(node, "events", tmpev, pp->num_irqs);
++ if (err != 0) {
++ dev_err(dev, "Failed to read events array\n");
++ goto err_fail;
++ }
++
++ /* assign and check */
++ for (i = 0; i < pp->num_irqs; i++) {
++ if (tmpev[i] < MIN_PRU_HOST_INT ||
++ tmpev[i] >= MAX_PRU_HOST_INT) {
++ dev_err(dev, "Bad event property entry %u\n", tmpev[i]);
++ goto err_fail;
++ }
++ pp->events[i] = tmpev[i];
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(dev, "failed to parse MEM resource\n");
++ goto err_fail;
++ }
++
++ pp->paddr = res->start;
++ pp->vaddr = devm_ioremap(dev, res->start, resource_size(res));
++ if (pp->vaddr == NULL) {
++ dev_err(dev, "failed to parse MEM resource\n");
++ goto err_fail;
++ }
++
++ err = of_property_read_u32(node, "pintc", &pp->pintc);
++ if (err != 0) {
++ dev_err(dev, "no pintc property\n");
++ goto err_fail;
++ }
++
++ /* read pdram property global, size, local */
++ err = of_property_read_u32_array(node, "pdram", tmparr, 3);
++ if (err != 0) {
++ dev_err(dev, "no pintc property\n");
++ goto err_fail;
++ }
++ pp->pdram = tmparr[0];
++ pp->pdram_sz = tmparr[1];
++ pp->pdram_da = tmparr[2];
++
++ /* configure PRU interrupt controller from DT */
++ err = configure_pintc(pdev, pp);
++ if (err != 0) {
++ dev_err(dev, "failed to configure pintc\n");
++ goto err_fail;
++ }
++
++ /* count number of child nodes with a firmwary property */
++ pp->num_prus = 0;
++ for_each_child_of_node(node, pnode) {
++ if (of_find_property(pnode, "firmware", NULL))
++ pp->num_prus++;
++ }
++ pnode = NULL;
++
++ /* found any? */
++ if (pp->num_prus == 0) {
++ dev_err(dev, "no pru nodes found\n");
++ err = -EINVAL;
++ goto err_fail;
++ }
++ /* found too many? */
++ if (pp->num_prus > MAX_PRUS) {
++ dev_err(dev, "Only 2 PRU nodes are supported\n");
++ err = -EINVAL;
++ goto err_fail;
++ }
++ dev_info(dev, "found #%d PRUs\n", pp->num_prus);
++
++ /* allocate pointers */
++ pp->pruc = devm_kzalloc(dev, sizeof(*pp->pruc) * pp->num_prus,
++ GFP_KERNEL);
++ if (pp->pruc == NULL) {
++ dev_err(dev, "Failed to allocate PRU table\n");
++ err = -ENOMEM;
++ goto err_fail;
++ }
++
++ /* now iterate over all the pru nodes */
++ i = 0;
++ for_each_child_of_node(node, pnode) {
++
++ /* only nodes with firmware are PRU nodes */
++ if (of_find_property(pnode, "firmware", NULL) == NULL)
++ continue;
++
++ /* get the hardware index of the PRU */
++ err = of_property_read_u32(pnode, "pru-index", &pru_idx);
++ if (err != 0) {
++ dev_err(dev, "can't find property %s\n", "pru-index");
++ of_node_put(pnode);
++ goto err_fail;
++ }
++
++ /* verify the index */
++ if (pru_idx >= MAX_PRUS) {
++ dev_err(dev, "Illegal pru-index property %u\n",
++ pru_idx);
++ of_node_put(pnode);
++ goto err_fail;
++ }
++
++ /* get the firmware */
++ err = of_property_read_string(pnode, "firmware", &fw_name);
++ if (err != 0) {
++ dev_err(dev, "can't find property %s\n", "firmware");
++ of_node_put(pnode);
++ goto err_fail;
++ }
++
++ /* allocate the remote proc + our private data */
++ rproc = rproc_alloc(dev, pdev->name, &pruproc_ops, fw_name,
++ sizeof(*ppc));
++ if (!rproc) {
++ dev_err(dev, "rproc_alloc failed\n");
++ err = -ENOMEM;
++ goto err_fail;
++ }
++ ppc = rproc->priv;
++ ppc->idx = pru_idx;
++ ppc->pruproc = pp;
++ ppc->rproc = rproc;
++
++ atomic_set(&ppc->bootcnt, 0);
++
++ err = of_property_read_u32_array(pnode, "iram", tmparr, 3);
++ if (err != 0) {
++ dev_err(dev, "no iram property\n");
++ goto err_fail;
++ }
++ ppc->iram = tmparr[0];
++ ppc->iram_sz = tmparr[1];
++ ppc->iram_da = tmparr[2];
++
++ err = of_property_read_u32_array(pnode, "dram", tmparr, 4);
++ if (err != 0) {
++ dev_err(dev, "no dram property\n");
++ goto err_fail;
++ }
++ ppc->dram = tmparr[0];
++ ppc->dram_sz = tmparr[1];
++ ppc->dram_da = tmparr[2];
++ ppc->dram_oda = tmparr[3];
++
++ err = of_property_read_u32(pnode, "pctrl", &ppc->pctrl);
++ if (err != 0) {
++ dev_err(dev, "no pctrl property\n");
++ goto err_fail;
++ }
++
++ err = of_property_read_u32(pnode, "pdbg", &ppc->pdbg);
++ if (err != 0) {
++ dev_err(dev, "no pdbg property\n");
++ goto err_fail;
++ }
++
++ /* read vring sysevent array */
++ err = of_property_read_u32_array(pnode, "vring-sysev", tmparr, 2);
++ if (err == 0) {
++ /* verify */
++ if (tmparr[0] >= MAX_PRU_SYS_EVENTS ||
++ tmparr[1] >= MAX_PRU_SYS_EVENTS) {
++ dev_err(dev, "illegal vring-sysev property\n");
++ goto err_fail;
++ }
++ ppc->pru_vring_sysev = tmparr[0];
++ ppc->host_vring_sysev = tmparr[1];
++ } else {
++ ppc->pru_vring_sysev = -1;
++ ppc->host_vring_sysev = -1;
++ }
++
++ /* check firmware type */
++ ppc->is_elf = of_property_read_bool(pnode, "firmware-elf");
++
++ /* build the resource table from DT */
++ err = build_rsc_table(pdev, pnode, ppc);
++ if (err != 0) {
++ dev_err(dev, "failed to build resource table\n");
++ goto err_fail;
++ }
++
++ /* Set the PRU specific firmware handler */
++ if (!ppc->is_elf)
++ rproc->fw_ops = &pruproc_bin_fw_ops;
++ else
++ rproc->fw_ops = &pruproc_elf_fw_ops;
++
++ pp->pruc[i] = ppc;
++ pp->pru_to_pruc[pru_idx] = ppc;
++ i++;
++ }
++ pnode = NULL;
++
++ /* clean up the sysev to target map */
++ memset(pp->sysev_to_target, 0, sizeof(pp->sysev_to_target));
++ for (i = 0; i < ARRAY_SIZE(pp->sysev_to_target); i++) {
++ pst = &pp->sysev_to_target[i];
++ pst->source = -1;
++ pst->target = -1;
++ }
++
++ /* fill in the sysev target map for std. signaling */
++ for (i = 0; i < MAX_TARGETS; i++) {
++ for (j = 0; j < MAX_TARGETS; j++) {
++ /* target self? don't care*/
++ if (i == j)
++ continue;
++ sysev = pp->target_to_sysev[i * MAX_TARGETS + j];
++ if (sysev >= MAX_PRU_SYS_EVENTS) {
++ dev_err(dev, "Bad SYSEV %d\n", sysev);
++ goto err_fail;
++ }
++ pst = &pp->sysev_to_target[sysev];
++ if (pst->valid) {
++ dev_err(dev, "SYSEV %d overlap\n", sysev);
++ goto err_fail;
++ }
++ pst->source = i;
++ pst->target = j;
++ pst->vring = 0;
++ pst->valid = 1;
++ }
++ }
++
++ /* fill in the sysev target map from vring info */
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ pru_idx = ppc->idx;
++
++ sysev = ppc->host_vring_sysev;
++ if (sysev != -1) {
++ pst = &pp->sysev_to_target[sysev];
++ if (pst->valid) {
++ dev_err(dev, "SYSEV %d overlap\n", sysev);
++ goto err_fail;
++ }
++ pst->source = TARGET_PRU(pru_idx);
++ pst->target = TARGET_ARM;
++ pst->vring = 1;
++ pst->valid = 1;
++ }
++
++ sysev = ppc->pru_vring_sysev;
++ if (sysev != -1) {
++ pst = &pp->sysev_to_target[sysev];
++ if (pst->valid) {
++ dev_err(dev, "SYSEV %d overlap\n", sysev);
++ goto err_fail;
++ }
++ pst->source = TARGET_ARM;
++ pst->target = TARGET_PRU(pru_idx);
++ pst->vring = 1;
++ pst->valid = 1;
++ }
++ }
++
++ /* dump the sysev target map */
++ for (i = 0; i < ARRAY_SIZE(pp->sysev_to_target); i++) {
++ pst = &pp->sysev_to_target[i];
++ if (!pst->valid)
++ continue;
++ dev_dbg(dev, "SYSEV#%d <- VR %d SRC %d TRG %d\n",
++ i, pst->vring, pst->source, pst->target);
++ }
++
++ /* register the interrupts */
++ for (i = 0; i < pp->num_irqs; i++) {
++
++ irq = pp->irqs[i];
++ err = devm_request_irq(dev, irq, pru_handler, 0,
++ dev_name(dev), pp);
++ if (err != 0) {
++ dev_err(dev, "Failed to register irq %d\n", irq);
++ goto err_fail;
++ }
++ }
++
++ /* start the remote procs */
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++
++ /* Register as a remoteproc device */
++ err = rproc_add(ppc->rproc);
++ if (err) {
++ dev_err(dev, "rproc_add failed\n");
++ goto err_fail;
++ }
++
++ /* directly boot all processors that don't have VDEVs */
++ if (ppc->num_vdevs == 0) {
++ err = rproc_boot(ppc->rproc);
++ if (err) {
++ dev_err(dev, "rproc_boot failed\n");
++ goto err_fail;
++ }
++ }
++ }
++
++ err = device_create_file(dev, &dev_attr_load);
++ if (err != 0) {
++ dev_err(dev, "device_create_file failed\n");
++ goto err_fail;
++ }
++
++ err = device_create_file(dev, &dev_attr_reset);
++ if (err != 0) {
++ dev_err(dev, "device_create_file failed\n");
++ goto err_fail;
++ }
++
++ dev_info(dev, "Loaded OK\n");
++
++ (void)pru_d_read_u32;
++ (void)pru_i_write_u32;
++ (void)pru_d_write_u32;
++
++ return 0;
++err_fail:
++ /* NULL is OK */
++ of_node_put(pnode);
++
++ if (rproc)
++ rproc_put(rproc);
++ if (pm_get)
++ pm_runtime_disable(dev);
+ return err;
+ }
+
diff --git a/patches/linux-3.8.13/0437-capes-pru-Update-with-PRU-03-PRU-04.patch b/patches/linux-3.8.13/0437-capes-pru-Update-with-PRU-03-PRU-04.patch
new file mode 100644
index 0000000..96bb31e
--- /dev/null
+++ b/patches/linux-3.8.13/0437-capes-pru-Update-with-PRU-03-PRU-04.patch
@@ -0,0 +1,547 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Jul 2013 19:41:07 +0300
+Subject: [PATCH] capes: pru: Update with PRU-03 & PRU-04
+
+Complex PRU capes.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/Makefile | 2 +
+ firmware/capes/BB-BONE-PRU-03-00A0.dts | 210 ++++++++++++++++++++++
+ firmware/capes/BB-BONE-PRU-04-00A0.dts | 297 ++++++++++++++++++++++++++++++++
+ 3 files changed, 509 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-PRU-03-00A0.dts
+ create mode 100644 firmware/capes/BB-BONE-PRU-04-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 1a353ce..646eea5 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -180,6 +180,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-PWMT-00A0.dtbo \
+ BB-BONE-PRU-01-00A0.dtbo \
+ BB-BONE-PRU-02-00A0.dtbo \
++ BB-BONE-PRU-03-00A0.dtbo \
++ BB-BONE-PRU-04-00A0.dtbo \
+ BB-BONE-RST-00A0.dtbo \
+ BB-BONE-RST2-00A0.dtbo \
+ BB-BONE-CAM3-01-00A2.dtbo \
+diff --git a/firmware/capes/BB-BONE-PRU-03-00A0.dts b/firmware/capes/BB-BONE-PRU-03-00A0.dts
+new file mode 100644
+index 0000000..7d7ba99
+--- /dev/null
++++ b/firmware/capes/BB-BONE-PRU-03-00A0.dts
+@@ -0,0 +1,210 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-PRU-03";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.27", /* pru0: pr1_pru0_pru_r30_5 */
++ /* the hardware IP uses */
++ "pru0";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ pru_gpio_pins: pinmux_pru_gpio_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x0f /* P9 27 GPIO3_19: mcasp0_fsr.gpio3[19] | MODE7 | OUTPUT */
++ >;
++ };
++
++ pru_pru_pins: pinmux_pru_pru_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x25 /* mcasp0_fsr.pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU */
++ >;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ prurproc {
++ compatible = "ti,pru-rproc";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pru_pru_pins>;
++
++ reg = <0x4a300000 0x080000>;
++
++ status = "okay";
++
++ ti,hwmods = "pruss";
++ ti,deassert-hard-reset = "pruss", "pruss";
++ interrupt-parent = <&intc>;
++
++ /* interrupts on the host */
++ interrupts = <20 21 22 23 24 25 26 27>;
++
++ /* events these interrupts map to (host interrupt) */
++ events = <2 3 4 5 6 7 8 9>;
++
++ /* PRU interrupt controller offset */
++ pintc = <0x20000>;
++
++ /* 12K Shared Data RAM global, size, local */
++ pdram = <0x10000 0x03000 0x10000>;
++
++ /*
++ * SYSEVENT ids
++ *
++ * - PRU/ARM communication
++ * PRU0_PRU1 17
++ * PRU1_PRU0 18
++ * PRU0_ARM 19
++ * PRU1_ARM 20
++ * ARM_PRU0 21
++ * ARM_PRU1 22
++ *
++ * Full SYSEVENT list
++ *
++ * parity_err_intr_pend 0
++ * pru0_r31_status_cnt16 1
++ * pru1_r31_status_cnt16 2
++ * uart_urxevt_intr_req 4
++ * uart_utxevt_intr_req 5
++ * uart_uint_intr_req 6
++ * iep_tim_cap_cmp_pend 7
++ * ecap_intr_req 15
++ * pru_mst_intr[0-15]_intr_req 16-31
++ * nirq 32 (UART1)
++ * mcasp_x_intr_pend 33 (MCASP1)
++ * mcasp_r_intr_pend 34 (MCASP1)
++ * ecap_intr_intr_pend 35 (ECAP1)
++ * ecap_intr_intr_pend 36 (ECAP2)
++ * epwm_intr_intr_pend 37 (eHRPWM2)
++ * dcan_uerr 38 (DCAN0)
++ * dcan_int1 39 (DCAN0)
++ * dcan_intr 40 (DCAN0)
++ * POINTRPEND 41 (I2C0)
++ * ecap_intr_intr_pend 42 (ECAP0)
++ * epwm_intr_intr_pend 43 (eHRPWM0)
++ * SINTERRUPTN 44 (McSPI0)
++ * eqep_intr_intr_pend 45 (eQEP0)
++ * epwm_intr_intr_pend 46 (eHRPWM1)
++ * c0_misc_pend 47 3PGSW (GEMAC)
++ * c0_tx_pend 48 3PGSW (GEMAC)
++ * c0_rx_pend 49 3PGSW (GEMAC)
++ * c0_rx_thresh_pend 50 3PGSW (GEMAC)
++ * nirq 51 (UART0)
++ * nirq 52 (UART2)
++ * gen_intr_pend 53 (ADC_TSC)
++ * mcasp_r_intr_pend 54 (McASP0)
++ * mcasp_x_intr_pend 55 (McASP1)
++ * pwm_trip_zone 56 (eHRPWM0/eHRPWM1/eHRP WM2)
++ * POINTRPEND1 57 (GPIO0)
++ * Emulation Suspend Signal 58 (Debugss)
++ * initiator_sinterrupt_q_n2 59 (Mbox0 - mail_u2_irq (mailbox interrupt for pru1))
++ * initiator_sinterrupt_q_n1 60 (Mbox0 - mail_u1_irq (mailbox interrupt for pru0))
++ * tptc_erint_pend_po 61 (TPTC0 (EDMA))
++ * tpcc_errint_pend_po 62 (TPCC (EDMA))
++ * tpcc_int_pend_po1 63 (TPCC (EDMA))
++ *
++ * HOST interrupt ids
++ *
++ * PRU0 0
++ * PRU1 1
++ * EVTOUT0-7 2-9
++ */
++
++ /* sysevent map to intc channel */
++ sysevent-to-channel-map =
++ <17 1>, /* PRU0_PRU1 -> CH1 */
++ <18 0>, /* PRU1_PRU0 -> CH0 */
++ <19 2>, /* PRU0_ARM -> CH2 */
++ <20 3>, /* PRU1_ARM -> CH3 */
++ <21 0>, /* ARM_PRU0 -> CH0 */
++ <22 1>, /* ARM_PRU1 -> CH1 */
++ <24 4>, /* VRING Host->PRU0 -> CH4 */
++ <25 5>, /* VRING PRU0->Host -> CH5 */
++ <26 6>, /* VRING Host->PRU1 -> CH6 */
++ <27 7>; /* VRING PRU1->Host -> CH7 */
++
++ /* channel to host interrupt map */
++ channel-to-host-interrupt-map =
++ <0 0>, /* CH0 -> PRU0 */
++ <1 1>, /* CH1 -> PRU1 */
++ <2 2>, /* CH2 -> EVTOUT0 */
++ <3 3>, /* CH3 -> EVTOUT1 */
++ <4 0>, /* CH4 -> PRU0 */
++ <5 6>, /* CH5 -> EVTOUT4 */
++ <6 1>, /* CH6 -> PRU1 */
++ <7 7>; /* CH7 -> EVTOUT5 */
++
++ /* indices are ARM=0, PRU0=1, PRU1=2 */
++ target-to-sysevent-map =
++ <0xffffffff 21 22>, /* ARM: DONTCARE, ARM_PRU0, ARM_PRU1 */
++ < 19 0xffffffff 17>, /* PRU0: PRU0_ARM, DONTCARE, PRU0_PRU1 */
++ < 20 18 0xffffffff>; /* PRU1: PRU1_ARM, PRU1_PRU0, DONTCARE */
++
++ /* definition for the first PRU */
++ pru0 {
++ pru-index = <0>;
++
++ /* offset, size, local */
++ iram = <0x34000 0x02000 0x00000>; /* code ram (8K) */
++
++ /* offset, size, local, other */
++ dram = <0x00000 0x02000 0x00000 0x10000>; /* data ram (8K) */
++
++ pctrl = <0x22000>;
++ pdbg = <0x22400>;
++
++ firmware-elf;
++ firmware = "prutest.elf";
++
++ /* sysevents signaling ring activity (host, pru)*/
++ vring-sysev = <24 25>;
++
++ resource_table {
++ resource-table;
++ version = <1>;
++
++ pru0_rproc_serial: pru0_vdev_rproc_serial {
++ vdev-rproc-serial;
++
++ /* notification IDs are totally bogus */
++ /* rproc will idr_alloc anyway */
++
++ notifyid = <8>; /* <- bogus */
++ /* da align num notifyid */
++ vring-0 = <0 16 8 0>;
++ vring-1 = <0 16 8 0>;
++ };
++ };
++ };
++
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-BONE-PRU-04-00A0.dts b/firmware/capes/BB-BONE-PRU-04-00A0.dts
+new file mode 100644
+index 0000000..2ad0ff1
+--- /dev/null
++++ b/firmware/capes/BB-BONE-PRU-04-00A0.dts
+@@ -0,0 +1,297 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-PRU-04";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.27", /* pru0: pr1_pru0_pru_r30_5 */
++
++ "P8.11", /* pru0: pr1_pru0_pru_r30_15 */
++ "P8.12", /* pru0: pr1_pru0_pru_r30_14 */
++ "P9.25", /* pru0: pr1_pru0_pru_r30_7 */
++ "P9.41", /* pru0: pr1_pru0_pru_r30_6 */
++ "P9.42", /* pru0: pr1_pru0_pru_r30_4 */
++ "P9.28", /* pru0: pr1_pru0_pru_r30_3 */
++ "P9.30", /* pru0: pr1_pru0_pru_r30_2 */
++ "P9.29", /* pru0: pr1_pru0_pru_r30_1 */
++ "P9.31", /* pru0: pr1_pru0_pru_r30_0 */
++ /* pru0: pr1_pru0_pru_r30_13 is on MMC0_CMD */
++ /* pru0: pr1_pru0_pru_r30_12 is on MMC0_CLK */
++ /* pru0: pr1_pru0_pru_r30_11 is on MMC0_DAT0 */
++ /* pru0: pr1_pru0_pru_r30_10 is on MMC0_DAT1 */
++ /* pru0: pr1_pru0_pru_r30_9 is on MMC0_DAT2 */
++ /* pru0: pr1_pru0_pru_r30_8 is on MMC0_DAT3 */
++
++ "P8.20", /* pru1: pr1_pru1_pru_r30_13 */
++
++ "P8.21", /* pru1: pr1_pru1_pru_r30_12 */
++ "P8.27", /* pru1: pr1_pru1_pru_r30_8 */
++ "P8.28", /* pru1: pr1_pru1_pru_r30_10 */
++ "P8.29", /* pru1: pr1_pru1_pru_r30_9 */
++ "P8.30", /* pru1: pr1_pru1_pru_r30_11 */
++ "P8.39", /* pru1: pr1_pru1_pru_r30_6 */
++ "P8.40", /* pru1: pr1_pru1_pru_r30_7 */
++ "P8.41", /* pru1: pr1_pru1_pru_r30_4 */
++ "P8.42", /* pru1: pr1_pru1_pru_r30_5 */
++ "P8.43", /* pru1: pr1_pru1_pru_r30_2 */
++ "P8.44", /* pru1: pr1_pru1_pru_r30_3 */
++ "P8.45", /* pru1: pr1_pru1_pru_r30_0 */
++ "P8.46", /* pru1: pr1_pru1_pru_r30_1 */
++ /* pru1: pr1_pru1_pru_r30_14 is on UART0_RXD */
++ /* pru1: pr1_pru1_pru_r30_15 is on UART0_TXD */
++ /* the hardware IP uses */
++ "pru0",
++ "pru1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ pru_gpio_pins: pinmux_pru_gpio_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x0f /* P9 27 GPIO3_19: mcasp0_fsr.gpio3[19] | MODE7 | OUTPUT */
++ >;
++ };
++
++ pru_pru_pins: pinmux_pru_pru_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x25 /* mcasp0_fsr.pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU */
++ 0x034 0x26 /* gpmc_ad13.pr1_pru0_pru_r30_15, MODE6 | OUTPUT | PRU */
++ 0x030 0x26 /* gpmc_ad12.pr1_pru0_pru_r30_14, MODE6 | OUTPUT | PRU */
++ 0x1ac 0x25 /* mcasp0_ahclkx.pr1_pru0_pru_r30_7, MODE5 | OUTPUT | PRU */
++ 0x1a8 0x25 /* mcasp0_axr1.pr1_pru0_pru_r30_6, MODE5 | OUTPUT | PRU */
++ 0x1a0 0x25 /* mcasp0_aclkr.pr1_pru0_pru_r30_4, MODE5 | OUTPUT | PRU */
++ 0x19c 0x25 /* mcasp0_ahclkr.pr1_pru0_pru_r30_3, MODE5 | OUTPUT | PRU */
++ 0x198 0x25 /* mcasp0_axr0.pr1_pru0_pru_r30_2, MODE5 | OUTPUT | PRU */
++ 0x194 0x25 /* mcasp0_fsx.pr1_pru0_pru_r30_1, MODE5 | OUTPUT | PRU */
++ 0x190 0x25 /* mcasp0_aclkx.pr1_pru0_pru_r30_0, MODE5 | OUTPUT | PRU */
++
++ 0x084 0x25 /* gpmc_csn2.pr1_pru1_pru_r30_13, MODE5 | OUTPUT | PRU */
++ 0x080 0x25 /* gpmc_csn1.pr1_pru1_pru_r30_12, MODE5 | OUTPUT | PRU */
++ 0x0e0 0x25 /* lcd_vsync.pr1_pru1_pru_r30_8, MODE5 | OUTPUT | PRU */
++ 0x0e8 0x25 /* lcd_pclk.pr1_pru1_pru_r30_10, MODE5 | OUTPUT | PRU */
++ 0x0e4 0x25 /* lcd_hsync.pr1_pru1_pru_r30_9, MODE5 | OUTPUT | PRU */
++ 0x0ec 0x25 /* lcd_ac_bias_en.pr1_pru1_pru_r30_11, MODE5 | OUTPUT | PRU */
++ 0x0bc 0x25 /* lcd_data7.pr1_pru1_pru_r30_7, MODE5 | OUTPUT | PRU */
++ 0x0b0 0x25 /* lcd_data4.pr1_pru1_pru_r30_4, MODE5 | OUTPUT | PRU */
++ 0x0b4 0x25 /* lcd_data5.pr1_pru1_pru_r30_5, MODE5 | OUTPUT | PRU */
++ 0x0ac 0x25 /* lcd_data3.pr1_pru1_pru_r30_3, MODE5 | OUTPUT | PRU */
++ 0x0a0 0x25 /* lcd_data0.pr1_pru1_pru_r30_0, MODE5 | OUTPUT | PRU */
++ 0x0a4 0x25 /* lcd_data1.pr1_pru1_pru_r30_1, MODE5 | OUTPUT | PRU */
++ >;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ prurproc {
++ compatible = "ti,pru-rproc";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pru_pru_pins>;
++
++ reg = <0x4a300000 0x080000>;
++
++ status = "okay";
++
++ ti,hwmods = "pruss";
++ ti,deassert-hard-reset = "pruss", "pruss";
++ interrupt-parent = <&intc>;
++
++ /* interrupts on the host */
++ interrupts = <20 21 22 23 24 25 26 27>;
++
++ /* events these interrupts map to (host interrupt) */
++ events = <2 3 4 5 6 7 8 9>;
++
++ /* PRU interrupt controller offset */
++ pintc = <0x20000>;
++
++ /* 12K Shared Data RAM global, size, local */
++ pdram = <0x10000 0x03000 0x10000>;
++
++ /*
++ * SYSEVENT ids
++ *
++ * - PRU/ARM communication
++ * PRU0_PRU1 17
++ * PRU1_PRU0 18
++ * PRU0_ARM 19
++ * PRU1_ARM 20
++ * ARM_PRU0 21
++ * ARM_PRU1 22
++ *
++ * Full SYSEVENT list
++ *
++ * parity_err_intr_pend 0
++ * pru0_r31_status_cnt16 1
++ * pru1_r31_status_cnt16 2
++ * uart_urxevt_intr_req 4
++ * uart_utxevt_intr_req 5
++ * uart_uint_intr_req 6
++ * iep_tim_cap_cmp_pend 7
++ * ecap_intr_req 15
++ * pru_mst_intr[0-15]_intr_req 16-31
++ * nirq 32 (UART1)
++ * mcasp_x_intr_pend 33 (MCASP1)
++ * mcasp_r_intr_pend 34 (MCASP1)
++ * ecap_intr_intr_pend 35 (ECAP1)
++ * ecap_intr_intr_pend 36 (ECAP2)
++ * epwm_intr_intr_pend 37 (eHRPWM2)
++ * dcan_uerr 38 (DCAN0)
++ * dcan_int1 39 (DCAN0)
++ * dcan_intr 40 (DCAN0)
++ * POINTRPEND 41 (I2C0)
++ * ecap_intr_intr_pend 42 (ECAP0)
++ * epwm_intr_intr_pend 43 (eHRPWM0)
++ * SINTERRUPTN 44 (McSPI0)
++ * eqep_intr_intr_pend 45 (eQEP0)
++ * epwm_intr_intr_pend 46 (eHRPWM1)
++ * c0_misc_pend 47 3PGSW (GEMAC)
++ * c0_tx_pend 48 3PGSW (GEMAC)
++ * c0_rx_pend 49 3PGSW (GEMAC)
++ * c0_rx_thresh_pend 50 3PGSW (GEMAC)
++ * nirq 51 (UART0)
++ * nirq 52 (UART2)
++ * gen_intr_pend 53 (ADC_TSC)
++ * mcasp_r_intr_pend 54 (McASP0)
++ * mcasp_x_intr_pend 55 (McASP1)
++ * pwm_trip_zone 56 (eHRPWM0/eHRPWM1/eHRP WM2)
++ * POINTRPEND1 57 (GPIO0)
++ * Emulation Suspend Signal 58 (Debugss)
++ * initiator_sinterrupt_q_n2 59 (Mbox0 - mail_u2_irq (mailbox interrupt for pru1))
++ * initiator_sinterrupt_q_n1 60 (Mbox0 - mail_u1_irq (mailbox interrupt for pru0))
++ * tptc_erint_pend_po 61 (TPTC0 (EDMA))
++ * tpcc_errint_pend_po 62 (TPCC (EDMA))
++ * tpcc_int_pend_po1 63 (TPCC (EDMA))
++ *
++ * HOST interrupt ids
++ *
++ * PRU0 0
++ * PRU1 1
++ * EVTOUT0-7 2-9
++ */
++
++ /* sysevent map to intc channel */
++ sysevent-to-channel-map =
++ <17 1>, /* PRU0_PRU1 -> CH1 */
++ <18 0>, /* PRU1_PRU0 -> CH0 */
++ <19 2>, /* PRU0_ARM -> CH2 */
++ <20 3>, /* PRU1_ARM -> CH3 */
++ <21 0>, /* ARM_PRU0 -> CH0 */
++ <22 1>, /* ARM_PRU1 -> CH1 */
++ <24 4>, /* VRING Host->PRU0 -> CH4 */
++ <25 5>, /* VRING PRU0->Host -> CH5 */
++ <26 6>, /* VRING Host->PRU1 -> CH6 */
++ <27 7>; /* VRING PRU1->Host -> CH7 */
++
++ /* channel to host interrupt map */
++ channel-to-host-interrupt-map =
++ <0 0>, /* CH0 -> PRU0 */
++ <1 1>, /* CH1 -> PRU1 */
++ <2 2>, /* CH2 -> EVTOUT0 */
++ <3 3>, /* CH3 -> EVTOUT1 */
++ <4 0>, /* CH4 -> PRU0 */
++ <5 6>, /* CH5 -> EVTOUT4 */
++ <6 1>, /* CH6 -> PRU1 */
++ <7 7>; /* CH7 -> EVTOUT5 */
++
++ /* indices are ARM=0, PRU0=1, PRU1=2 */
++ target-to-sysevent-map =
++ <0xffffffff 21 22>, /* ARM: DONTCARE, ARM_PRU0, ARM_PRU1 */
++ < 19 0xffffffff 17>, /* PRU0: PRU0_ARM, DONTCARE, PRU0_PRU1 */
++ < 20 18 0xffffffff>; /* PRU1: PRU1_ARM, PRU1_PRU0, DONTCARE */
++
++ /* definition for the first PRU */
++ pru0 {
++ pru-index = <0>;
++
++ /* offset, size, local */
++ iram = <0x34000 0x02000 0x00000>; /* code ram (8K) */
++
++ /* offset, size, local, other */
++ dram = <0x00000 0x02000 0x00000 0x10000>; /* data ram (8K) */
++
++ pctrl = <0x22000>;
++ pdbg = <0x22400>;
++
++ firmware-elf;
++ firmware = "testpru0";
++
++ /* sysevents signaling ring activity (host, pru)*/
++ vring-sysev = <24 25>;
++
++ resource_table {
++ resource-table;
++ version = <1>;
++
++ pru0_rproc_serial: pru0_vdev_rproc_serial {
++ vdev-rproc-serial;
++
++ /* notification IDs are totally bogus */
++ /* rproc will idr_alloc anyway */
++
++ notifyid = <8>; /* <- bogus */
++ /* da align num notifyid */
++ vring-0 = <0 16 8 0>;
++ vring-1 = <0 16 8 0>;
++ };
++
++// pru0_rproc_rpmsg: pru0_vdev_rproc_rpmsg {
++// vdev-rpmsg;
++//
++// /* notification IDs are totally bogus */
++// /* rproc will idr_alloc anyway */
++//
++// notifyid = <9>; /* <- bogus */
++// /* da align num notifyid */
++// vring-0 = <0 16 512 0>;
++// vring-1 = <0 16 512 0>;
++// };
++ };
++ };
++
++ /* definition for the second PRU */
++ pru1 {
++ pru-index = <1>;
++
++ /* offset, size, local */
++ iram = <0x38000 0x02000 0x00000>; /* code ram (8K) */
++
++ /* offset, size, local, other */
++ dram = <0x02000 0x02000 0x00000 0x10000>; /* data ram (8K) */
++
++ pctrl = <0x24000>;
++ pdbg = <0x24400>;
++
++ firmware-elf;
++ firmware = "testpru1";
++
++ /* NOTE: no resource table, no vrings for this one */
++ };
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0438-rproc-PRU-Add-downcall-RPC-capability.patch b/patches/linux-3.8.13/0438-rproc-PRU-Add-downcall-RPC-capability.patch
new file mode 100644
index 0000000..8a69b38
--- /dev/null
+++ b/patches/linux-3.8.13/0438-rproc-PRU-Add-downcall-RPC-capability.patch
@@ -0,0 +1,587 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 12 Jul 2013 19:05:58 +0300
+Subject: [PATCH] rproc: PRU: Add downcall RPC capability.
+
+Let's face it, using queues to do stuff like configuration is a drag.
+Instead use the new downcall capability to communicate with the PRU
+using synchronous RPC. Much faster and easier.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/remoteproc/pru_rproc.c | 354 ++++++++++++++++++++++++++++++++++------
+ 1 file changed, 307 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
+index e3ec63b..ad2dfc7 100644
+--- a/drivers/remoteproc/pru_rproc.c
++++ b/drivers/remoteproc/pru_rproc.c
+@@ -74,6 +74,8 @@ struct pruproc_core;
+ #define PRU_VDEV_MAX 4
+ #define PRU_VRING_MAX (RVDEV_NUM_VRINGS * PRU_VDEV_MAX)
+
++#define PRU_HALT_INSN 0x2a000000
++
+ struct pru_vring_info {
+ struct fw_rsc_vdev_vring *rsc;
+ struct vring vr;
+@@ -122,6 +124,15 @@ struct pruproc_core {
+
+ /* boots */
+ atomic_t bootcnt;
++
++ /* downcall lock */
++ struct mutex dc_lock;
++ wait_queue_head_t dc_waitq;
++ unsigned long dc_flags;
++#define PRU_DCF_DOWNCALL_REQ 0
++#define PRU_DCF_DOWNCALL_ACK 1
++#define PRU_DCF_DOWNCALL_ISSUE 2
++#define PRU_DCF_DOWNCALL_DONE 3
+ };
+
+ struct pru_sysev_target {
+@@ -898,16 +909,17 @@ static void pruproc_kick(struct rproc *rproc, int vqid)
+
+ dev_dbg(dev, "kick #%d vqid:%d\n", ppc->idx, vqid);
+
+- /* ARM to PRUx system event */
+- sysint = pp->target_to_sysev[TARGET_ARM_TO_PRU_IDX(ppc->idx)];
++ sysint = ppc->pru_vring_sysev;
++ if (sysint < 0) {
++ dev_err(dev, "PRU#%d no vring_sysev to kick with\n", ppc->idx);
++ return;
++ }
+
+ /* signal event */
+ if (sysint < 32)
+ pintc_write_reg(pp, PINTC_SRSR0, 1 << sysint);
+ else
+ pintc_write_reg(pp, PINTC_SRSR1, 1 << (sysint - 32));
+-
+- // dump_all_vrings(ppc);
+ }
+
+ void dump_resource_table(const struct resource_table *res)
+@@ -973,10 +985,13 @@ static int pruproc_start(struct rproc *rproc)
+ u32 val;
+ int err;
+
++ dev_info(dev, "PRU#%d bootcnt=%d\n",
++ ppc->idx, atomic_read(&ppc->bootcnt));
++
+ /* start the processors only when all devices have booted */
+ if (ppc->num_vdevs == 0 || atomic_inc_return(&ppc->bootcnt) == 1) {
+
+- dev_info(dev, "start PRU #%d entry-point 0x%x\n",
++ dev_info(dev, "PRU#%d entry-point 0x%x\n",
+ ppc->idx, ppc->entry_point);
+
+ #if 1
+@@ -1044,7 +1059,7 @@ static void *pruproc_alloc_vring(struct rproc *rproc,
+ }
+
+ if (i >= ppc->num_vrings) {
+- dev_err(dev, "PRU #%d could not find rsc_vring at %p\n",
++ dev_err(dev, "PRU#%d could not find rsc_vring at %p\n",
+ ppc->idx, rsc_vring);
+ return NULL;
+ }
+@@ -1053,18 +1068,18 @@ static void *pruproc_alloc_vring(struct rproc *rproc,
+ dma = &dma_tmp;
+
+ if (rsc_vring->da != 0) {
+- dev_dbg(dev, "PRU #%d alloc vring #%d from internal memory\n",
++ dev_dbg(dev, "PRU#%d alloc vring #%d from internal memory\n",
+ ppc->idx, i);
+ va = pru_d_da_to_va_block(ppc, rsc_vring->da, dma, size);
+ } else {
+- dev_dbg(dev, "PRU #%d alloc vring #%d dma_alloc_coherent\n",
++ dev_dbg(dev, "PRU#%d alloc vring #%d dma_alloc_coherent\n",
+ ppc->idx, i);
+ va = dma_alloc_coherent(dev->parent, PAGE_ALIGN(size),
+ dma, GFP_KERNEL);
+ }
+
+ if (va == NULL) {
+- dev_err(dev, "PRU #%d could not allocate vring %p\n",
++ dev_err(dev, "PRU#%d could not allocate vring %p\n",
+ ppc->idx, rsc_vring);
+ return NULL;
+ }
+@@ -1079,7 +1094,7 @@ static void *pruproc_alloc_vring(struct rproc *rproc,
+ vri->pa = *dma;
+ vri->da = pru_d_pa_to_da(ppc, *dma);
+
+- dev_dbg(dev, "PRU #%d vring #%d da=0x%x, va=%p, dma=0x%llx size=%u\n",
++ dev_dbg(dev, "PRU#%d vring #%d da=0x%x, va=%p, dma=0x%llx size=%u\n",
+ ppc->idx, i, rsc_vring->da, va, (unsigned long long)*dma, size);
+
+ return va;
+@@ -1246,9 +1261,53 @@ static ssize_t pruproc_store_reset(struct device *dev,
+ return strlen(buf);
+ }
+
++static int pru_downcall(struct pruproc_core *ppc,
++ u32 nr, u32 arg0, u32 arg1, u32 arg2);
++
++static ssize_t pruproc_store_downcall(int idx,
++ struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pruproc *pp = platform_get_drvdata(pdev);
++ struct pruproc_core *ppc = NULL;
++ int i, ret;
++
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ if (ppc->idx == idx)
++ break;
++ }
++ if (i >= pp->num_prus)
++ return -EINVAL;
++
++ ret = pru_downcall(ppc, 0x5, 0xaa55, 0x1234, 0x98ff);
++
++ dev_info(dev, "PRU#%d downcall test - ret = %d\n", ppc->idx, ret);
++
++ return strlen(buf);
++}
++
++static ssize_t pruproc_store_downcall0(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ return pruproc_store_downcall(0, dev, attr, buf, count);
++}
++
++static ssize_t pruproc_store_downcall1(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ return pruproc_store_downcall(1, dev, attr, buf, count);
++}
++
+ static DEVICE_ATTR(load, S_IWUSR, NULL, pruproc_store_load);
+ static DEVICE_ATTR(reset, S_IWUSR, NULL, pruproc_store_reset);
+
++static DEVICE_ATTR(downcall0, S_IWUSR, NULL, pruproc_store_downcall0);
++static DEVICE_ATTR(downcall1, S_IWUSR, NULL, pruproc_store_downcall1);
++
+ /* PRU is unregistered */
+ static int pruproc_remove(struct platform_device *pdev)
+ {
+@@ -1278,8 +1337,6 @@ static int pruproc_remove(struct platform_device *pdev)
+ return 0;
+ }
+
+-#define PRU_HALT_INSN 0x2a000000
+-
+ #define PRU_SC_HALT 0
+ #define PRU_SC_PUTC 1
+ #define PRU_SC_EXIT 2
+@@ -1289,6 +1346,9 @@ static int pruproc_remove(struct platform_device *pdev)
+ #define PRU_SC_GET_CFG_VRING_INFO 1
+ #define PRU_SC_GET_CFG_RESOURCE_TABLE 2
+
++#define PRU_SC_DOWNCALL_READY 254 /* host requested a downcall, ack it, and execute */
++#define PRU_SC_DOWNCALL_DONE 255 /* call is performed, inform the host */
++
+ struct pru_dev_vring_info {
+ u32 paddr;
+ u32 num;
+@@ -1296,44 +1356,87 @@ struct pru_dev_vring_info {
+ u32 pad;
+ };
+
+-static int pru_handle_syscall(struct pruproc_core *ppc)
++/* verify that the PRU is halted */
++static int pru_is_halted(struct pruproc_core *ppc, u32 *addrp)
+ {
+ struct pruproc *pp = ppc->pruproc;
+ struct device *dev = &pp->pdev->dev;
+- u32 val, addr, scno, arg0, arg1, arg2, ret;
+- int err, valid_sc;
+- void * __iomem va;
+- struct pru_vring_info *vri;
+- struct pru_dev_vring_info *dvri;
++ u32 val, addr;
++ int err;
+
+ /* check whether it's halted */
+ val = pcntrl_read_reg(ppc, PCTRL_CONTROL);
+ if ((val & CONTROL_RUNSTATE) != 0) {
+- dev_dbg(dev, "PRU #%d not halted\n",
++ dev_err(dev, "PRU#%d not halted\n",
+ ppc->idx);
+ return -EINVAL;
+ }
+
+ /* read the instruction */
+- addr = pcntrl_read_reg(ppc, PCTRL_STATUS) * 4;
++ addr = pcntrl_read_reg(ppc, PCTRL_STATUS) << 2;
+ err = pru_i_read_u32(ppc, addr, &val);
+ if (err != 0) {
+- dev_err(dev, "PRU #%d halted PC 0x%x bad\n", ppc->idx, addr);
++ dev_err(dev, "PRU#%d halted PC 0x%x bad\n", ppc->idx, addr);
+ return err;
+ }
+
+ /* check whether it's a halt instruction */
+ if (val != PRU_HALT_INSN) {
+- dev_err(dev, "PRU #%d not in halt insn (addr=0x%x val 0x%08x)\n",
++ dev_err(dev, "PRU#%d not in halt insn (addr=0x%x val 0x%08x)\n",
+ ppc->idx, addr, val);
+ return -EFAULT;
+ }
+
++ if (addrp != NULL)
++ *addrp = addr;
++
++ return 0;
++}
++
++static u32 pru_read_cpu_reg(struct pruproc_core *ppc, int reg)
++{
++ return pdbg_read_reg(ppc, PDBG_GPREG(reg));
++}
++
++static void pru_write_cpu_reg(struct pruproc_core *ppc, int reg, u32 val)
++{
++ pdbg_write_reg(ppc, PDBG_GPREG(reg), val);
++}
++
++/* it is assumed that the PRU is halted */
++static void pru_resume(struct pruproc_core *ppc, u32 addr)
++{
++ u32 val;
++
++ val = pcntrl_read_reg(ppc, PCTRL_CONTROL);
++ val &= 0xffff;
++ val |= ((addr >> 2) << 16) | CONTROL_ENABLE;
++ val &= ~CONTROL_SOFT_RST_N;
++ pcntrl_write_reg(ppc, PCTRL_CONTROL, val);
++}
++
++/* handle a PRU syscall */
++static int pru_handle_syscall(struct pruproc_core *ppc)
++{
++ struct pruproc *pp = ppc->pruproc;
++ struct device *dev = &pp->pdev->dev;
++ u32 addr, scno, arg0, arg1, arg2, ret;
++ int valid_sc;
++ void * __iomem va;
++ struct pru_vring_info *vri;
++ struct pru_dev_vring_info *dvri;
++
++ ret = pru_is_halted(ppc, &addr);
++ if (ret != 0) {
++ dev_err(dev, "PRU#%d not halted\n", ppc->idx);
++ return ret;
++ }
++
+ valid_sc = 0;
+- scno = pdbg_read_reg(ppc, PDBG_GPREG(14));
+- arg0 = pdbg_read_reg(ppc, PDBG_GPREG(15));
+- arg1 = pdbg_read_reg(ppc, PDBG_GPREG(16));
+- arg2 = pdbg_read_reg(ppc, PDBG_GPREG(17));
++ scno = pru_read_cpu_reg(ppc, 14);
++ arg0 = pru_read_cpu_reg(ppc, 15);
++ arg1 = pru_read_cpu_reg(ppc, 16);
++ arg2 = pru_read_cpu_reg(ppc, 17);
+ ret = 0; /* by default we return 0 */
+
+ switch (scno) {
+@@ -1356,7 +1459,7 @@ static int pru_handle_syscall(struct pruproc_core *ppc)
+ /* pointers can only be in own data ram */
+ va = pru_d_da_to_va(ppc, arg0, NULL);
+ if (va == NULL) {
+- dev_err(dev, "PRU #%d SC PUTS bad 0x%x\n",
++ dev_err(dev, "PRU#%d SC PUTS bad 0x%x\n",
+ ppc->idx, arg0);
+ ret = (u32)-1;
+ } else {
+@@ -1374,7 +1477,7 @@ static int pru_handle_syscall(struct pruproc_core *ppc)
+ break;
+ case PRU_SC_GET_CFG_VRING_INFO:
+ if (arg1 >= ppc->num_vrings) {
+- dev_err(dev, "PRU #%d SC "
++ dev_err(dev, "PRU#%d SC "
+ "GET_CFG_VRING_INFO "
+ "bad idx %d\n",
+ ppc->idx, arg1);
+@@ -1382,7 +1485,7 @@ static int pru_handle_syscall(struct pruproc_core *ppc)
+
+ va = pru_d_da_to_va(ppc, arg2, NULL);
+ if (va == NULL) {
+- dev_err(dev, "PRU #%d SC "
++ dev_err(dev, "PRU#%d SC "
+ "GET_CFG_VRING_INFO "
+ "bad 0x%x\n",
+ ppc->idx, arg2);
+@@ -1410,7 +1513,7 @@ static int pru_handle_syscall(struct pruproc_core *ppc)
+ break;
+
+ default:
+- dev_err(dev, "PRU #%d SC "
++ dev_err(dev, "PRU#%d SC "
+ "GET_CFG bad 0x%x\n",
+ ppc->idx, arg1);
+ ret = (u32)-1;
+@@ -1418,30 +1521,175 @@ static int pru_handle_syscall(struct pruproc_core *ppc)
+ }
+ break;
+
++ case PRU_SC_DOWNCALL_READY:
++ /* if we were waiting for it, wake up */
++ if (test_and_clear_bit(PRU_DCF_DOWNCALL_REQ, &ppc->dc_flags)) {
++ set_bit(PRU_DCF_DOWNCALL_ACK, &ppc->dc_flags);
++ wake_up_interruptible(&ppc->dc_waitq);
++ return 1;
++ }
++ dev_err(dev, "P%d No-one expected downcall; halting\n",
++ ppc->idx);
++ return 1;
++
++ case PRU_SC_DOWNCALL_DONE:
++ /* if we were waiting for it, wake up */
++ if (test_and_clear_bit(PRU_DCF_DOWNCALL_ISSUE, &ppc->dc_flags)) {
++ set_bit(PRU_DCF_DOWNCALL_DONE, &ppc->dc_flags);
++ wake_up_interruptible(&ppc->dc_waitq);
++ return 1;
++ }
++ dev_err(dev, "P%d No-one expected downcall; halting\n",
++ ppc->idx);
++ return 1;
++
+ default:
+- dev_err(dev, "PRU #%d SC Unknown (%d)\n",
++ dev_err(dev, "PRU#%d SC Unknown (%d)\n",
+ ppc->idx, scno);
+ return 1;
+ }
+
+ /* return code */
+- pdbg_write_reg(ppc, PDBG_GPREG(14), ret);
++ pru_write_cpu_reg(ppc, 14, ret);
+
+ /* skip over the HALT insn */
+- val = pcntrl_read_reg(ppc, PCTRL_CONTROL);
+- val &= 0xffff;
+- addr = pcntrl_read_reg(ppc, PCTRL_STATUS);
+- val |= ((addr + 1) << 16) | CONTROL_ENABLE;
+- val &= ~CONTROL_SOFT_RST_N;
++ pru_resume(ppc, addr + 4);
+
+- /* dev_dbg(dev, "PRU#%d new PCTRL_CONTROL=0x%08x\n",
+- ppc->idx, val); */
++ return 0;
++}
+
+- pcntrl_write_reg(ppc, PCTRL_CONTROL, val);
++/*
++ * The source of the downcall part on the PRU
++ *
++ * .global sc_downcall
++ *sc_downcall:
++ * MOV R0.w0, R14.w0 ;* save the pointer to the function
++ * ;* first issue the downcall ready
++ * LDI R14, DOWNCALL_READY
++ * LDI R31, SYSCALL_VALUE
++ * HALT ;* host must save R3.w0 locally
++ * ;* the host will manipulate our state so that the arguments are correct
++ * JAL R3.w0, R0.w0 ;* call
++ * MOV R0, R14 ;* save the return code
++ * ;* when we return here, we will inform the host of the result
++ * LDI R14, DOWNCALL_DONE ;
++ * LDI R31, SYSCALL_VALUE
++ * HALT ;* host must return to save R3.w0
++ */
+
+- return 0;
++/* perform the downcall */
++static int pru_downcall(struct pruproc_core *ppc,
++ u32 nr, u32 arg0, u32 arg1, u32 arg2)
++{
++ struct pruproc *pp = ppc->pruproc;
++ struct device *dev = &pp->pdev->dev;
++ int sysint;
++ int ret;
++ long intr;
++ u32 addr, r3in;
++
++ sysint = pp->target_to_sysev[TARGET_ARM_TO_PRU_IDX(ppc->idx)];
++ if (sysint == -1)
++ return -EINVAL;
++
++ /* we might sleep, warn with a backtrace */
++ might_sleep();
++
++ mutex_lock(&ppc->dc_lock);
++
++ /* state machine out of sync */
++ if (ppc->dc_flags != 0) {
++ ret = -EBUSY;
++ goto ret_unlock;
++ }
++
++ if (test_and_set_bit(PRU_DCF_DOWNCALL_REQ, &ppc->dc_flags) != 0) {
++ dev_err(dev, "PRU#%d downcall failed due to mangled req bit\n",
++ ppc->idx);
++ ret = -EBUSY;
++ goto ret_unlock;
++ }
++
++ /* signal downcall event */
++ if (sysint < 32)
++ pintc_write_reg(pp, PINTC_SRSR0, 1 << sysint);
++ else
++ pintc_write_reg(pp, PINTC_SRSR1, 1 << (sysint - 32));
++
++ /* now waiting until we get the downcall ready (maximum 100ms) */
++ intr = wait_event_interruptible_timeout(ppc->dc_waitq,
++ test_and_clear_bit(PRU_DCF_DOWNCALL_ACK, &ppc->dc_flags),
++ HZ / 10);
++ if (intr < 0) {
++ ret = (int)intr;
++ dev_err(dev, "PRU#%d error waiting for downcall ready (%d)\n",
++ ppc->idx, ret);
++ goto ret_call_failed;
++ }
++ if (intr == 0) {
++ dev_err(dev, "PRU#%d failed to issue downcall ready in 100ms\n",
++ ppc->idx);
++ ret = -ETIMEDOUT;
++ goto ret_call_failed;
++ }
++ dev_dbg(dev, "PRU#%d got downcall ready\n", ppc->idx);
++
++ ret = pru_is_halted(ppc, &addr);
++ if (ret != 0) {
++ dev_err(dev, "PRU#%d not halted\n",
++ ppc->idx);
++ ret = -EFAULT;
++ goto ret_call_failed;
++ }
++
++ /* get the actual return address */
++ r3in = pru_read_cpu_reg(ppc, 3) << 2;
++
++ /* write the arguments */
++ pru_write_cpu_reg(ppc, 14, nr);
++ pru_write_cpu_reg(ppc, 15, arg0);
++ pru_write_cpu_reg(ppc, 16, arg1);
++ pru_write_cpu_reg(ppc, 17, arg2);
++
++ set_bit(PRU_DCF_DOWNCALL_ISSUE, &ppc->dc_flags);
++
++ /* skip over the HALT insn */
++ pru_resume(ppc, addr + 4);
++
++ /* now waiting until we get the downcall ready (maximum 100ms) */
++ intr = wait_event_interruptible_timeout(ppc->dc_waitq,
++ test_and_clear_bit(PRU_DCF_DOWNCALL_DONE, &ppc->dc_flags),
++ HZ / 10);
++ if (intr < 0) {
++ ret = (int)intr;
++ dev_err(dev, "PRU#%d error waiting for downcall done (%d)\n",
++ ppc->idx, ret);
++ goto ret_call_failed;
++ }
++ if (intr == 0) {
++ dev_err(dev, "PRU#%d failed to issue downcall done in 100ms\n",
++ ppc->idx);
++ ret = -ETIMEDOUT;
++ goto ret_call_failed;
++ }
++ dev_dbg(dev, "PRU#%d got downcall done\n", ppc->idx);
++
++ /* return */
++ ret = pru_read_cpu_reg(ppc, 0);
++
++ /* and we're done */
++ pru_resume(ppc, r3in);
++
++ret_call_failed:
++ ppc->dc_flags = 0;
++
++ret_unlock:
++ mutex_unlock(&ppc->dc_lock);
++
++ return ret;
+ }
+
++
+ static irqreturn_t pru_handler(int irq, void *data)
+ {
+ struct pruproc *pp = data;
+@@ -1512,7 +1760,7 @@ static irqreturn_t pru_handler(int irq, void *data)
+ /* we either handle a vring or not */
+ if (!pst->vring) {
+ ret = pru_handle_syscall(ppc);
+- if (ret == 0) /* system call handled */
++ if (ret >= 0) /* system call handled */
+ handled++;
+ } else {
+ /* handle any vrings action */
+@@ -1522,7 +1770,7 @@ static irqreturn_t pru_handler(int irq, void *data)
+ continue;
+ ret = rproc_vq_interrupt(rproc, vri->rvring->notifyid);
+ if (ret == IRQ_HANDLED) {
+- dev_dbg(dev, "PRU #%d; vring irq handled\n",
++ dev_dbg(dev, "PRU#%d; vring irq handled\n",
+ ppc->idx);
+ handled++;
+ }
+@@ -1530,13 +1778,11 @@ static irqreturn_t pru_handler(int irq, void *data)
+ }
+ }
+
+-#if 0
+ if (!handled) {
+ dev_err(dev, "sysint not handled; disabling interrupt\n");
+- goto disable_int;
++ return IRQ_NONE;
+
+ }
+-#endif
+
+ return IRQ_HANDLED;
+
+@@ -1552,7 +1798,6 @@ static int build_rsc_table(struct platform_device *pdev,
+ struct device *dev = &pdev->dev;
+ struct device_node *rnode = NULL; /* resource table node */
+ struct device_node *rvnode = NULL; /* vdev node */
+- // struct pruproc *pp = ppc->pruproc;
+ struct resource_table *rsc;
+ struct fw_rsc_hdr *rsc_hdr;
+ struct fw_rsc_vdev *rsc_vdev;
+@@ -2144,6 +2389,9 @@ static int pruproc_probe(struct platform_device *pdev)
+
+ atomic_set(&ppc->bootcnt, 0);
+
++ mutex_init(&ppc->dc_lock);
++ init_waitqueue_head(&ppc->dc_waitq);
++
+ err = of_property_read_u32_array(pnode, "iram", tmparr, 3);
+ if (err != 0) {
+ dev_err(dev, "no iram property\n");
+@@ -2330,6 +2578,18 @@ static int pruproc_probe(struct platform_device *pdev)
+ goto err_fail;
+ }
+
++ err = device_create_file(dev, &dev_attr_downcall0);
++ if (err != 0) {
++ dev_err(dev, "device_create_file failed\n");
++ goto err_fail;
++ }
++
++ err = device_create_file(dev, &dev_attr_downcall1);
++ if (err != 0) {
++ dev_err(dev, "device_create_file failed\n");
++ goto err_fail;
++ }
++
+ dev_info(dev, "Loaded OK\n");
+
+ (void)pru_d_read_u32;
diff --git a/patches/linux-3.8.13/0439-rproc-pru-Implement-a-software-defined-PWM-channel-s.patch b/patches/linux-3.8.13/0439-rproc-pru-Implement-a-software-defined-PWM-channel-s.patch
new file mode 100644
index 0000000..861e3ea
--- /dev/null
+++ b/patches/linux-3.8.13/0439-rproc-pru-Implement-a-software-defined-PWM-channel-s.patch
@@ -0,0 +1,326 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 12 Jul 2013 20:51:16 +0300
+Subject: [PATCH] rproc: pru: Implement a software defined PWM channel set
+
+Implement a fully working PWM software defined peripheral.
+Your Linux client only see a standard PWM interface, while
+everything is implemented by software on the PRUs.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/remoteproc/pru_rproc.c | 223 +++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 208 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
+index ad2dfc7..6e42db6 100644
+--- a/drivers/remoteproc/pru_rproc.c
++++ b/drivers/remoteproc/pru_rproc.c
+@@ -30,6 +30,8 @@
+ #include <linux/virtio_ring.h>
+ #include <asm/atomic.h>
+
++#include <linux/pwm.h>
++
+ #include "remoteproc_internal.h"
+
+ /* PRU_EVTOUT0 is halt (system call) */
+@@ -76,6 +78,15 @@ struct pruproc_core;
+
+ #define PRU_HALT_INSN 0x2a000000
+
++/* down call IDs */
++#define DC_PWM_CONFIG 0 /* pwm, hi, lo */
++#define DC_PWM_ENABLE 1 /* pwm */
++#define DC_PWM_DISABLE 2 /* pwm */
++#define DC_PWM_MAX 3
++
++/* maximum PWMs */
++#define PRU_PWM_MAX 32
++
+ struct pru_vring_info {
+ struct fw_rsc_vdev_vring *rsc;
+ struct vring vr;
+@@ -166,6 +177,18 @@ struct pruproc {
+ u32 num_prus;
+ struct pruproc_core **pruc;
+ struct pruproc_core *pru_to_pruc[MAX_PRUS];
++
++ /* PRU clock period in ns */
++ u32 clock_freq;
++
++ /* the actual linux devices */
++ struct {
++ struct pwm_chip chip;
++ int count;
++ u32 map[PRU_PWM_MAX]; /* maximum pwm channels is 32 */
++ int controller;
++ u32 dc_ids[DC_PWM_MAX];
++ } pwm;
+ };
+
+ /* global memory map (for am33xx) (almost the same as local) */
+@@ -1262,7 +1285,10 @@ static ssize_t pruproc_store_reset(struct device *dev,
+ }
+
+ static int pru_downcall(struct pruproc_core *ppc,
+- u32 nr, u32 arg0, u32 arg1, u32 arg2);
++ u32 nr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
++
++static int pru_downcall_idx(struct pruproc *pp, int idx,
++ u32 nr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+
+ static ssize_t pruproc_store_downcall(int idx,
+ struct device *dev, struct device_attribute *attr,
+@@ -1270,20 +1296,11 @@ static ssize_t pruproc_store_downcall(int idx,
+ {
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pruproc *pp = platform_get_drvdata(pdev);
+- struct pruproc_core *ppc = NULL;
+- int i, ret;
+-
+- for (i = 0; i < pp->num_prus; i++) {
+- ppc = pp->pruc[i];
+- if (ppc->idx == idx)
+- break;
+- }
+- if (i >= pp->num_prus)
+- return -EINVAL;
++ int ret;
+
+- ret = pru_downcall(ppc, 0x5, 0xaa55, 0x1234, 0x98ff);
++ ret = pru_downcall_idx(pp, idx, 0x5, 0xaa55, 0x1234, 0x98ff, 0, 0);
+
+- dev_info(dev, "PRU#%d downcall test - ret = %d\n", ppc->idx, ret);
++ dev_info(dev, "PRU#%d downcall test - ret = %d\n", idx, ret);
+
+ return strlen(buf);
+ }
+@@ -1579,7 +1596,7 @@ static int pru_handle_syscall(struct pruproc_core *ppc)
+
+ /* perform the downcall */
+ static int pru_downcall(struct pruproc_core *ppc,
+- u32 nr, u32 arg0, u32 arg1, u32 arg2)
++ u32 nr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+ {
+ struct pruproc *pp = ppc->pruproc;
+ struct device *dev = &pp->pdev->dev;
+@@ -1650,6 +1667,8 @@ static int pru_downcall(struct pruproc_core *ppc,
+ pru_write_cpu_reg(ppc, 15, arg0);
+ pru_write_cpu_reg(ppc, 16, arg1);
+ pru_write_cpu_reg(ppc, 17, arg2);
++ pru_write_cpu_reg(ppc, 18, arg3);
++ pru_write_cpu_reg(ppc, 19, arg4);
+
+ set_bit(PRU_DCF_DOWNCALL_ISSUE, &ppc->dc_flags);
+
+@@ -1689,6 +1708,22 @@ ret_unlock:
+ return ret;
+ }
+
++static int pru_downcall_idx(struct pruproc *pp, int idx,
++ u32 nr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
++{
++ struct pruproc_core *ppc = NULL;
++ int i;
++
++ for (i = 0; i < pp->num_prus; i++) {
++ ppc = pp->pruc[i];
++ if (ppc->idx == idx)
++ break;
++ }
++ if (i >= pp->num_prus)
++ return -EINVAL;
++
++ return pru_downcall(ppc, nr, arg0, arg1, arg2, arg3, arg4);
++}
+
+ static irqreturn_t pru_handler(int irq, void *data)
+ {
+@@ -2162,6 +2197,153 @@ static int configure_pintc(struct platform_device *pdev, struct pruproc *pp)
+ return 0;
+ }
+
++static int pru_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
++ int duty_ns, int period_ns)
++{
++ struct device *dev = chip->dev;
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pruproc *pp = platform_get_drvdata(pdev);
++ int hwpwm, prupwm, ret;
++ u32 hi, lo;
++
++ hwpwm = pwm->hwpwm;
++ if (hwpwm >= pp->pwm.count)
++ return -EINVAL;
++ prupwm = pp->pwm.map[hwpwm];
++
++ dev_dbg(&pdev->dev, "%s (%d/%d) duty_ns=%d period_ns=%d\n", __func__,
++ hwpwm, prupwm, duty_ns, period_ns);
++
++ hi = div_u64((u64)duty_ns * pp->clock_freq, 1000000000);
++ lo = div_u64((u64)(period_ns - duty_ns) * pp->clock_freq, 1000000000);
++ ret = pru_downcall_idx(pp, pp->pwm.controller,
++ pp->pwm.dc_ids[DC_PWM_CONFIG], prupwm, hi, lo, 0, 0);
++ return ret;
++}
++
++static int pru_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct device *dev = chip->dev;
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pruproc *pp = platform_get_drvdata(pdev);
++ int hwpwm, prupwm, ret;
++
++ hwpwm = pwm->hwpwm;
++ if (hwpwm >= pp->pwm.count)
++ return -EINVAL;
++ prupwm = pp->pwm.map[hwpwm];
++
++ dev_dbg(&pdev->dev, "%s (%d/%d)\n", __func__, hwpwm, prupwm);
++
++ ret = pru_downcall_idx(pp, pp->pwm.controller,
++ pp->pwm.dc_ids[DC_PWM_ENABLE], prupwm, 0, 0, 0, 0);
++ return ret;
++}
++
++static void pru_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct device *dev = chip->dev;
++ struct platform_device *pdev = to_platform_device(dev);
++ struct pruproc *pp = platform_get_drvdata(pdev);
++ int hwpwm, prupwm;
++
++ hwpwm = pwm->hwpwm;
++ if (hwpwm >= pp->pwm.count)
++ return;
++ prupwm = pp->pwm.map[hwpwm];
++
++ dev_dbg(&pdev->dev, "%s (%d/%d)\n", __func__, hwpwm, prupwm);
++
++ pru_downcall_idx(pp, pp->pwm.controller,
++ pp->pwm.dc_ids[DC_PWM_DISABLE], prupwm, 0, 0, 0, 0);
++}
++
++static const struct pwm_ops pru_pwm_ops = {
++ .config = pru_pwm_config,
++ .enable = pru_pwm_enable,
++ .disable = pru_pwm_disable,
++};
++
++static int pruproc_create_pwm_devices(struct pruproc *pp)
++{
++ struct platform_device *pdev = pp->pdev;
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct property *prop;
++ u32 val;
++ int err, i, cnt, proplen;
++
++ /* pwms */
++
++ /* find property */
++ prop = of_find_property(np, "pru-pwm-channels", &proplen);
++ if (prop == NULL)
++ return 0;
++
++ cnt = proplen / sizeof(u32);
++ if (cnt >= ARRAY_SIZE(pp->pwm.map)) {
++ dev_err(dev, "Too many PWMs %d (max %d)\n",
++ cnt, ARRAY_SIZE(pp->pwm.map));
++ return -EINVAL;
++ }
++ pp->pwm.count = cnt;
++
++ /* now read it */
++ err = of_property_read_u32_array(np, "pru-pwm-channels",
++ pp->pwm.map, cnt);
++ if (err != 0) {
++ dev_err(dev, "Failed to read %s property\n",
++ "pru-pwm-channels");
++ return err;
++ }
++
++ if (of_property_read_u32(np, "pru-pwm-controller", &val) == 0)
++ pp->pwm.controller = val;
++ else
++ pp->pwm.controller = 0; /* default is PRU0 */
++
++ /* verify they are sane */
++ for (i = 0; i < cnt; i++) {
++ if (pp->pwm.map[i] >= ARRAY_SIZE(pp->pwm.map)) {
++ dev_err(dev, "Bad PWM number\n");
++ return -EINVAL;
++ }
++ }
++
++ /* get the PWM DC IDs */
++ err = of_property_read_u32_array(np, "pru-pwm-dc-ids",
++ pp->pwm.dc_ids, ARRAY_SIZE(pp->pwm.dc_ids));
++ if (err != 0) {
++ dev_err(dev, "Failed to read %s array\n",
++ "pru-pwm-dc-ids");
++ return err;
++ }
++
++ pp->pwm.chip.dev = dev;
++ pp->pwm.chip.ops = &pru_pwm_ops;
++ pp->pwm.chip.base = pdev->id; /* ? */
++ pp->pwm.chip.npwm = cnt;
++
++ /* add the pwms */
++ err = pwmchip_add(&pp->pwm.chip);
++ if (err != 0) {
++ dev_err(dev, "pwmchip_add failed\n");
++ return err;
++ }
++
++ return 0;
++}
++
++/* after all is configured create the linux devices */
++static int pruproc_create_devices(struct pruproc *pp)
++{
++ int ret;
++
++ ret = pruproc_create_pwm_devices(pp);
++
++ return ret;
++}
++
+ static int pruproc_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -2176,7 +2358,7 @@ static int pruproc_probe(struct platform_device *pdev)
+ struct resource *res;
+ struct pinctrl *pinctrl;
+ int err, i, j, irq, sysev;
+- u32 tmparr[4], pru_idx;
++ u32 tmparr[4], pru_idx, val;
+ u32 tmpev[MAX_ARM_PRU_INTS];
+
+ /* get pinctrl */
+@@ -2304,6 +2486,14 @@ static int pruproc_probe(struct platform_device *pdev)
+ pp->pdram_sz = tmparr[1];
+ pp->pdram_da = tmparr[2];
+
++ /* get the clock frequency */
++ err = of_property_read_u32(node, "clock-freq", &val);
++ if (err != 0) {
++ dev_warn(dev, "no clock-freq property; assuming default 200MHz\n");
++ val = 200000000;
++ }
++ pp->clock_freq = val;
++
+ /* configure PRU interrupt controller from DT */
+ err = configure_pintc(pdev, pp);
+ if (err != 0) {
+@@ -2592,6 +2782,9 @@ static int pruproc_probe(struct platform_device *pdev)
+
+ dev_info(dev, "Loaded OK\n");
+
++ /* creating devices */
++ pruproc_create_devices(pp);
++
+ (void)pru_d_read_u32;
+ (void)pru_i_write_u32;
+ (void)pru_d_write_u32;
diff --git a/patches/linux-3.8.13/0440-capes-PRU-PWM-channels-information.patch b/patches/linux-3.8.13/0440-capes-PRU-PWM-channels-information.patch
new file mode 100644
index 0000000..414c56a
--- /dev/null
+++ b/patches/linux-3.8.13/0440-capes-PRU-PWM-channels-information.patch
@@ -0,0 +1,59 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 15 Jul 2013 15:29:11 +0300
+Subject: [PATCH] capes: PRU: PWM channels information
+
+---
+ firmware/capes/BB-BONE-PRU-03-00A0.dts | 5 ++++-
+ firmware/capes/BB-BONE-PRU-04-00A0.dts | 13 ++++++++++++-
+ 2 files changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-PRU-03-00A0.dts b/firmware/capes/BB-BONE-PRU-03-00A0.dts
+index 7d7ba99..ae2d033 100644
+--- a/firmware/capes/BB-BONE-PRU-03-00A0.dts
++++ b/firmware/capes/BB-BONE-PRU-03-00A0.dts
+@@ -1,5 +1,5 @@
+ /*
+-* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
++* Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.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
+@@ -167,6 +167,9 @@
+ < 19 0xffffffff 17>, /* PRU0: PRU0_ARM, DONTCARE, PRU0_PRU1 */
+ < 20 18 0xffffffff>; /* PRU1: PRU1_ARM, PRU1_PRU0, DONTCARE */
+
++ /* both the PRUs have 200MHz frequency so period is 5ns */
++ clock-freq = <200000000>;
++
+ /* definition for the first PRU */
+ pru0 {
+ pru-index = <0>;
+diff --git a/firmware/capes/BB-BONE-PRU-04-00A0.dts b/firmware/capes/BB-BONE-PRU-04-00A0.dts
+index 2ad0ff1..bf96ccf 100644
+--- a/firmware/capes/BB-BONE-PRU-04-00A0.dts
++++ b/firmware/capes/BB-BONE-PRU-04-00A0.dts
+@@ -1,5 +1,5 @@
+ /*
+-* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
++* Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.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
+@@ -224,6 +224,17 @@
+ < 19 0xffffffff 17>, /* PRU0: PRU0_ARM, DONTCARE, PRU0_PRU1 */
+ < 20 18 0xffffffff>; /* PRU1: PRU1_ARM, PRU1_PRU0, DONTCARE */
+
++ /* both the PRUs have 200MHz frequency so period is 5ns */
++ clock-freq = <200000000>;
++
++ /* the linux pwms we support */
++ pru-pwm-channels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 21>;
++ /* first PRU controls the PWMs */
++ pru-pwm-controller = <0>;
++ /* the IDs of the downcalls the firmware expects for PWMs */
++ /* CONFIG=0, ENABLE=1, DISABLE=2 */
++ pru-pwm-dc-ids = <0 1 2>;
++
+ /* definition for the first PRU */
+ pru0 {
+ pru-index = <0>;
diff --git a/patches/linux-3.8.13/0441-drivers-usb-phy-add-a-new-driver-for-usb-part-of-con.patch b/patches/linux-3.8.13/0441-drivers-usb-phy-add-a-new-driver-for-usb-part-of-con.patch
new file mode 100644
index 0000000..3bf60c9
--- /dev/null
+++ b/patches/linux-3.8.13/0441-drivers-usb-phy-add-a-new-driver-for-usb-part-of-con.patch
@@ -0,0 +1,377 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 15 Jan 2013 08:42:52 +0000
+Subject: [PATCH] drivers: usb: phy: add a new driver for usb part of control
+ module
+
+Added a new driver for the usb part of control module. This has an API
+to power on the USB2 phy and an API to write to the mailbox depending on
+whether MUSB has to act in host mode or in device mode.
+
+Writing to control module registers for doing the above task which was
+previously done in omap glue and in omap-usb2 phy will be removed.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ Documentation/devicetree/bindings/usb/omap-usb.txt | 21 +-
+ drivers/usb/phy/Kconfig | 9 +
+ drivers/usb/phy/Makefile | 1 +
+ drivers/usb/phy/omap-control-usb.c | 204 ++++++++++++++++++++
+ include/linux/usb/omap_control_usb.h | 73 +++++++
+ 5 files changed, 307 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/usb/phy/omap-control-usb.c
+ create mode 100644 include/linux/usb/omap_control_usb.h
+
+diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
+index 29a043e..d58dae3 100644
+--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
++++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
+@@ -1,4 +1,4 @@
+-OMAP GLUE
++OMAP GLUE AND OTHER OMAP SPECIFIC COMPONENTS
+
+ OMAP MUSB GLUE
+ - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
+@@ -31,3 +31,22 @@ Board specific device node entry
+ mode = <3>;
+ power = <50>;
+ };
++
++OMAP CONTROL USB
++
++Required properties:
++ - compatible: Should be "ti,omap-control-usb"
++ - reg : Address and length of the register set for the device. It contains
++ the address of "control_dev_conf" and "otghs_control".
++ - reg-names: The names of the register addresses corresponding to the registers
++ filled in "reg".
++ - ti,has_mailbox: This is used to specify if the platform uses mailbox in
++ control module.
++
++omap_control_usb@4a002300 {
++ compatible = "ti,omap-control-usb";
++ reg = <0x4a002300 0x4>,
++ <0x4a00233c 0x4>;
++ reg-names = "control_dev_conf", "otghs_control";
++ ti,has_mailbox;
++};
+diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
+index 5de6e7f..a7277ee 100644
+--- a/drivers/usb/phy/Kconfig
++++ b/drivers/usb/phy/Kconfig
+@@ -14,6 +14,15 @@ config OMAP_USB2
+ The USB OTG controller communicates with the comparator using this
+ driver.
+
++config OMAP_CONTROL_USB
++ tristate "OMAP CONTROL USB Driver"
++ depends on ARCH_OMAP2PLUS
++ help
++ Enable this to add support for the USB part present in the control
++ module. This driver has API to power on the PHY and to write to the
++ mailbox. The mailbox is present only in omap4 and the register to
++ power on the PHY is present in omap4 and omap5.
++
+ config USB_ISP1301
+ tristate "NXP ISP1301 USB transceiver support"
+ depends on USB || USB_GADGET
+diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
+index 1a579a8..0dea4d2 100644
+--- a/drivers/usb/phy/Makefile
++++ b/drivers/usb/phy/Makefile
+@@ -5,6 +5,7 @@
+ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
+
+ obj-$(CONFIG_OMAP_USB2) += omap-usb2.o
++obj-$(CONFIG_OMAP_CONTROL_USB) += omap-control-usb.o
+ obj-$(CONFIG_USB_ISP1301) += isp1301.o
+ obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o
+ obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o
+diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/omap-control-usb.c
+new file mode 100644
+index 0000000..bed41a9
+--- /dev/null
++++ b/drivers/usb/phy/omap-control-usb.c
+@@ -0,0 +1,204 @@
++/*
++ * omap-control-usb.c - The USB part of control module.
++ *
++ * Copyright (C) 2013 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * Author: Kishon Vijay Abraham I <kishon@ti.com>
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/of.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/usb/omap_control_usb.h>
++
++static struct omap_control_usb *control_usb;
++
++/**
++ * get_omap_control_dev - returns the device pointer for this control device
++ *
++ * This API should be called to get the device pointer for this control
++ * module device. This device pointer should be passed to all other API's
++ * in this driver.
++ *
++ * To be used by PHY driver and glue driver
++ */
++struct device *get_omap_control_dev(void)
++{
++ if (!control_usb)
++ return ERR_PTR(-ENODEV);
++
++ return control_usb->dev;
++}
++EXPORT_SYMBOL_GPL(get_omap_control_dev);
++
++/**
++ * omap_control_usb_phy_power - power on/off the phy using control module reg
++ * @dev: the control module device
++ * @on: 0 or 1, based on powering on or off the PHY
++ */
++void omap_control_usb_phy_power(struct device *dev, int on)
++{
++ u32 val;
++ struct omap_control_usb *control_usb = dev_get_drvdata(dev);
++
++ if (on) {
++ val = readl(control_usb->dev_conf);
++ if (val & PHY_PD)
++ writel(~PHY_PD, control_usb->dev_conf);
++ } else {
++ writel(PHY_PD, control_usb->dev_conf);
++ }
++}
++EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
++
++/**
++ * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
++ * @dev: struct device *
++ *
++ * This is an API to write to the mailbox register to notify the usb core that
++ * a usb device has been connected.
++ */
++void omap_control_usb_host_mode(struct device *dev)
++{
++ u32 val;
++ struct omap_control_usb *control_usb = dev_get_drvdata(dev);
++
++ val = AVALID | VBUSVALID;
++
++ writel(val, control_usb->otghs_control);
++}
++EXPORT_SYMBOL_GPL(omap_control_usb_host_mode);
++
++/**
++ * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
++ * impedance
++ * @dev: struct device *
++ *
++ * This is an API to write to the mailbox register to notify the usb core that
++ * it has been connected to a usb host.
++ */
++void omap_control_usb_device_mode(struct device *dev)
++{
++ u32 val;
++ struct omap_control_usb *control_usb = dev_get_drvdata(dev);
++
++ val = IDDIG | AVALID | VBUSVALID;
++
++ writel(val, control_usb->otghs_control);
++}
++EXPORT_SYMBOL_GPL(omap_control_usb_device_mode);
++
++/**
++ * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
++ * impedance
++ * @dev: struct device *
++ *
++ * This is an API to write to the mailbox register to notify the usb core
++ * it's now in disconnected state.
++ */
++void omap_control_usb_set_sessionend(struct device *dev)
++{
++ u32 val;
++ struct omap_control_usb *control_usb = dev_get_drvdata(dev);
++
++ val = SESSEND | IDDIG;
++
++ writel(val, control_usb->otghs_control);
++}
++EXPORT_SYMBOL_GPL(omap_control_usb_set_sessionend);
++
++static int omap_control_usb_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ struct device_node *np = pdev->dev.of_node;
++ struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data;
++
++ control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
++ GFP_KERNEL);
++ if (!control_usb) {
++ dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
++ return -ENOMEM;
++ }
++
++ if (np) {
++ control_usb->has_mailbox = of_property_read_bool(np,
++ "ti,has_mailbox");
++ } else if (pdata) {
++ control_usb->has_mailbox = pdata->has_mailbox;
++ } else {
++ dev_err(&pdev->dev, "no pdata present\n");
++ return -EINVAL;
++ }
++
++ control_usb->dev = &pdev->dev;
++
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ "control_dev_conf");
++ control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
++ if (control_usb->dev_conf == NULL) {
++ dev_err(&pdev->dev, "Failed to obtain io memory\n");
++ return -ENXIO;
++ }
++
++ if (control_usb->has_mailbox) {
++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ "otghs_control");
++ control_usb->otghs_control = devm_request_and_ioremap(
++ &pdev->dev, res);
++ if (control_usb->otghs_control == NULL) {
++ dev_err(&pdev->dev, "Failed to obtain io memory\n");
++ return -ENXIO;
++ }
++ }
++
++ dev_set_drvdata(control_usb->dev, control_usb);
++
++ return 0;
++}
++
++#ifdef CONFIG_OF
++static const struct of_device_id omap_control_usb_id_table[] = {
++ { .compatible = "ti,omap-control-usb" },
++ {}
++};
++MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
++#endif
++
++static struct platform_driver omap_control_usb_driver = {
++ .probe = omap_control_usb_probe,
++ .driver = {
++ .name = "omap-control-usb",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(omap_control_usb_id_table),
++ },
++};
++
++static int __init omap_control_usb_init(void)
++{
++ return platform_driver_register(&omap_control_usb_driver);
++}
++subsys_initcall(omap_control_usb_init);
++
++static void __exit omap_control_usb_exit(void)
++{
++ platform_driver_unregister(&omap_control_usb_driver);
++}
++module_exit(omap_control_usb_exit);
++
++MODULE_ALIAS("platform: omap_control_usb");
++MODULE_AUTHOR("Texas Instruments Inc.");
++MODULE_DESCRIPTION("OMAP CONTROL USB DRIVER");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/usb/omap_control_usb.h b/include/linux/usb/omap_control_usb.h
+new file mode 100644
+index 0000000..fbc7407
+--- /dev/null
++++ b/include/linux/usb/omap_control_usb.h
+@@ -0,0 +1,73 @@
++/*
++ * omap_control_usb.h - Header file for the USB part of control module.
++ *
++ * Copyright (C) 2013 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; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * Author: Kishon Vijay Abraham I <kishon@ti.com>
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#ifndef __OMAP_CONTROL_USB_H__
++#define __OMAP_CONTROL_USB_H__
++
++struct omap_control_usb {
++ struct device *dev;
++
++ u32 __iomem *dev_conf;
++ u32 __iomem *otghs_control;
++
++ u8 has_mailbox:1;
++};
++
++struct omap_control_usb_platform_data {
++ u8 has_mailbox:1;
++};
++
++#define PHY_PD BIT(0)
++
++#define AVALID BIT(0)
++#define BVALID BIT(1)
++#define VBUSVALID BIT(2)
++#define SESSEND BIT(3)
++#define IDDIG BIT(4)
++
++#if (defined(CONFIG_OMAP_CONTROL_USB) || \
++ defined(CONFIG_OMAP_CONTROL_USB_MODULE))
++extern struct device *get_omap_control_dev(void);
++extern void omap_control_usb_phy_power(struct device *dev, int on);
++extern void omap_control_usb_host_mode(struct device *dev);
++extern void omap_control_usb_device_mode(struct device *dev);
++extern void omap_control_usb_set_sessionend(struct device *dev);
++#else
++static inline struct device *get_omap_control_dev()
++{
++ return ERR_PTR(-ENODEV);
++}
++
++static inline void omap_control_usb_phy_power(struct device *dev, int on)
++{
++}
++
++static inline void omap_control_usb_host_mode(struct device *dev)
++{
++}
++
++static inline void omap_control_usb_device_mode(struct device *dev)
++{
++}
++
++static inline void omap_control_usb_set_sessionend(struct device *dev)
++{
++}
++#endif
++
++#endif /* __OMAP_CONTROL_USB_H__ */
diff --git a/patches/linux-3.8.13/0442-drivers-usb-start-using-the-control-module-driver.patch b/patches/linux-3.8.13/0442-drivers-usb-start-using-the-control-module-driver.patch
new file mode 100644
index 0000000..ac7e56e
--- /dev/null
+++ b/patches/linux-3.8.13/0442-drivers-usb-start-using-the-control-module-driver.patch
@@ -0,0 +1,404 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 15 Jan 2013 08:42:55 +0000
+Subject: [PATCH] drivers: usb: start using the control module driver
+
+Start using the control module driver for powering on the PHY and for
+writing to the mailbox instead of writing to the control module
+registers on their own.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ Documentation/devicetree/bindings/usb/omap-usb.txt | 4 ++
+ Documentation/devicetree/bindings/usb/usb-phy.txt | 7 +--
+ arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 13 ----
+ drivers/usb/musb/Kconfig | 1 +
+ drivers/usb/musb/omap2430.c | 64 ++++++++------------
+ drivers/usb/musb/omap2430.h | 9 ---
+ drivers/usb/phy/Kconfig | 1 +
+ drivers/usb/phy/omap-usb2.c | 38 +++---------
+ include/linux/usb/omap_usb.h | 4 +-
+ 9 files changed, 42 insertions(+), 99 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
+index d58dae3..3f0152b 100644
+--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
++++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
+@@ -3,6 +3,9 @@ OMAP GLUE AND OTHER OMAP SPECIFIC COMPONENTS
+ OMAP MUSB GLUE
+ - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
+ - ti,hwmods : must be "usb_otg_hs"
++ - ti,has_mailbox : to specify that omap uses an external mailbox
++ (in control module) to communicate with the musb core during device connect
++ and disconnect.
+ - multipoint : Should be "1" indicating the musb controller supports
+ multipoint. This is a MUSB configuration-specific setting.
+ - num_eps : Specifies the number of endpoints. This is also a
+@@ -20,6 +23,7 @@ SOC specific device node entry
+ usb_otg_hs: usb_otg_hs@4a0ab000 {
+ compatible = "ti,omap4-musb";
+ ti,hwmods = "usb_otg_hs";
++ ti,has_mailbox;
+ multipoint = <1>;
+ num_eps = <16>;
+ ram_bits = <12>;
+diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
+index 80d4148..ee14cb7 100644
+--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
++++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
+@@ -4,14 +4,11 @@ OMAP USB2 PHY
+
+ Required properties:
+ - compatible: Should be "ti,omap-usb2"
+- - reg : Address and length of the register set for the device. Also
+-add the address of control module dev conf register until a driver for
+-control module is added
++ - reg : Address and length of the register set for the device.
+
+ This is usually a subnode of ocp2scp to which it is connected.
+
+ usb2phy@4a0ad080 {
+ compatible = "ti,omap-usb2";
+- reg = <0x4a0ad080 0x58>,
+- <0x4a002300 0x4>;
++ reg = <0x4a0ad080 0x58>;
+ };
+diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+index 793f54a..624a7e8 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+@@ -2702,13 +2702,6 @@ static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
+ .end = 0x4a0ae000,
+ .flags = IORESOURCE_MEM,
+ },
+- {
+- /* XXX: Remove this once control module driver is in place */
+- .name = "ctrl_dev",
+- .start = 0x4a002300,
+- .end = 0x4a002303,
+- .flags = IORESOURCE_MEM,
+- },
+ { }
+ };
+
+@@ -6156,12 +6149,6 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
+ .pa_end = 0x4a0ab7ff,
+ .flags = ADDR_TYPE_RT
+ },
+- {
+- /* XXX: Remove this once control module driver is in place */
+- .pa_start = 0x4a00233c,
+- .pa_end = 0x4a00233f,
+- .flags = ADDR_TYPE_RT
+- },
+ { }
+ };
+
+diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
+index 23a0b7f..de6e5ce 100644
+--- a/drivers/usb/musb/Kconfig
++++ b/drivers/usb/musb/Kconfig
+@@ -11,6 +11,7 @@ config USB_MUSB_HDRC
+ select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)
+ select TWL4030_USB if MACH_OMAP_3430SDP
+ select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
++ select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
+ select USB_OTG_UTILS
+ help
+ Say Y here if your system has a dual role high speed USB
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index d7772856..6a7e400 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -37,6 +37,7 @@
+ #include <linux/err.h>
+ #include <linux/delay.h>
+ #include <linux/usb/musb-omap.h>
++#include <linux/usb/omap_control_usb.h>
+
+ #include "musb_core.h"
+ #include "omap2430.h"
+@@ -46,7 +47,7 @@ struct omap2430_glue {
+ struct platform_device *musb;
+ enum omap_musb_vbus_id_status status;
+ struct work_struct omap_musb_mailbox_work;
+- u32 __iomem *control_otghs;
++ struct device *control_otghs;
+ };
+ #define glue_to_musb(g) platform_get_drvdata(g->musb)
+
+@@ -54,26 +55,6 @@ struct omap2430_glue *_glue;
+
+ static struct timer_list musb_idle_timer;
+
+-/**
+- * omap4_usb_phy_mailbox - write to usb otg mailbox
+- * @glue: struct omap2430_glue *
+- * @val: the value to be written to the mailbox
+- *
+- * On detection of a device (ID pin is grounded), this API should be called
+- * to set AVALID, VBUSVALID and ID pin is grounded.
+- *
+- * When OMAP is connected to a host (OMAP in device mode), this API
+- * is called to set AVALID, VBUSVALID and ID pin in high impedance.
+- *
+- * XXX: This function will be removed once we have a seperate driver for
+- * control module
+- */
+-static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val)
+-{
+- if (glue->control_otghs)
+- writel(val, glue->control_otghs);
+-}
+-
+ static void musb_do_idle(unsigned long _musb)
+ {
+ struct musb *musb = (void *)_musb;
+@@ -269,7 +250,6 @@ EXPORT_SYMBOL_GPL(omap_musb_mailbox);
+
+ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
+ {
+- u32 val;
+ struct musb *musb = glue_to_musb(glue);
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *pdata = dev->platform_data;
+@@ -285,8 +265,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
+ musb->xceiv->last_event = USB_EVENT_ID;
+ if (musb->gadget_driver) {
+ pm_runtime_get_sync(dev);
+- val = AVALID | VBUSVALID;
+- omap4_usb_phy_mailbox(glue, val);
++ if (!IS_ERR(glue->control_otghs))
++ omap_control_usb_host_mode(glue->control_otghs);
+ omap2430_musb_set_vbus(musb, 1);
+ }
+ break;
+@@ -299,8 +279,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
+ musb->xceiv->last_event = USB_EVENT_VBUS;
+ if (musb->gadget_driver)
+ pm_runtime_get_sync(dev);
+- val = IDDIG | AVALID | VBUSVALID;
+- omap4_usb_phy_mailbox(glue, val);
++ if (!IS_ERR(glue->control_otghs))
++ omap_control_usb_device_mode(glue->control_otghs);
+ break;
+
+ case OMAP_MUSB_ID_FLOAT:
+@@ -317,8 +297,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
+ if (musb->xceiv->otg->set_vbus)
+ otg_set_vbus(musb->xceiv->otg, 0);
+ }
+- val = SESSEND | IDDIG;
+- omap4_usb_phy_mailbox(glue, val);
++ if (!IS_ERR(glue->control_otghs))
++ omap_control_usb_set_sessionend(glue->control_otghs);
+ break;
+ default:
+ dev_dbg(dev, "ID float\n");
+@@ -415,7 +395,6 @@ err1:
+ static void omap2430_musb_enable(struct musb *musb)
+ {
+ u8 devctl;
+- u32 val;
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+ struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+@@ -425,8 +404,8 @@ static void omap2430_musb_enable(struct musb *musb)
+ switch (glue->status) {
+
+ case OMAP_MUSB_ID_GROUND:
+- val = AVALID | VBUSVALID;
+- omap4_usb_phy_mailbox(glue, val);
++ if (!IS_ERR(glue->control_otghs))
++ omap_control_usb_host_mode(glue->control_otghs);
+ if (data->interface_type != MUSB_INTERFACE_UTMI)
+ break;
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+@@ -445,8 +424,8 @@ static void omap2430_musb_enable(struct musb *musb)
+ break;
+
+ case OMAP_MUSB_VBUS_VALID:
+- val = IDDIG | AVALID | VBUSVALID;
+- omap4_usb_phy_mailbox(glue, val);
++ if (!IS_ERR(glue->control_otghs))
++ omap_control_usb_device_mode(glue->control_otghs);
+ break;
+
+ default:
+@@ -456,13 +435,12 @@ static void omap2430_musb_enable(struct musb *musb)
+
+ static void omap2430_musb_disable(struct musb *musb)
+ {
+- u32 val;
+ struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+
+ if (glue->status != OMAP_MUSB_UNKNOWN) {
+- val = SESSEND | IDDIG;
+- omap4_usb_phy_mailbox(glue, val);
++ if (!IS_ERR(glue->control_otghs))
++ omap_control_usb_set_sessionend(glue->control_otghs);
+ }
+ }
+
+@@ -523,9 +501,6 @@ static int omap2430_probe(struct platform_device *pdev)
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+- glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res);
+- if (glue->control_otghs == NULL)
+- dev_dbg(&pdev->dev, "Failed to obtain control memory\n");
+
+ if (np) {
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+@@ -558,11 +533,22 @@ static int omap2430_probe(struct platform_device *pdev)
+ of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
+ of_property_read_u32(np, "power", (u32 *)&pdata->power);
+ config->multipoint = of_property_read_bool(np, "multipoint");
++ pdata->has_mailbox = of_property_read_bool(np,
++ "ti,has_mailbox");
+
+ pdata->board_data = data;
+ pdata->config = config;
+ }
+
++ if (pdata->has_mailbox) {
++ glue->control_otghs = get_omap_control_dev();
++ if (IS_ERR(glue->control_otghs)) {
++ dev_vdbg(&pdev->dev, "Failed to get control device\n");
++ return -ENODEV;
++ }
++ } else {
++ glue->control_otghs = ERR_PTR(-ENODEV);
++ }
+ pdata->platform_ops = &omap2430_ops;
+
+ platform_set_drvdata(pdev, glue);
+diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
+index 8ef6566..1b5e83a 100644
+--- a/drivers/usb/musb/omap2430.h
++++ b/drivers/usb/musb/omap2430.h
+@@ -49,13 +49,4 @@
+ #define OTG_FORCESTDBY 0x414
+ # define ENABLEFORCE (1 << 0)
+
+-/*
+- * Control Module bit definitions
+- * XXX: Will be removed once we have a driver for control module.
+- */
+-#define AVALID BIT(0)
+-#define BVALID BIT(1)
+-#define VBUSVALID BIT(2)
+-#define SESSEND BIT(3)
+-#define IDDIG BIT(4)
+ #endif /* __MUSB_OMAP243X_H__ */
+diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
+index a7277ee..16bdaca 100644
+--- a/drivers/usb/phy/Kconfig
++++ b/drivers/usb/phy/Kconfig
+@@ -8,6 +8,7 @@ config OMAP_USB2
+ tristate "OMAP USB2 PHY Driver"
+ depends on ARCH_OMAP2PLUS
+ select USB_OTG_UTILS
++ select OMAP_CONTROL_USB
+ help
+ Enable this to support the transceiver that is part of SOC. This
+ driver takes care of all the PHY functionality apart from comparator.
+diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
+index 26ae8f4..2152ce4 100644
+--- a/drivers/usb/phy/omap-usb2.c
++++ b/drivers/usb/phy/omap-usb2.c
+@@ -27,6 +27,7 @@
+ #include <linux/err.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/delay.h>
++#include <linux/usb/omap_control_usb.h>
+
+ /**
+ * omap_usb2_set_comparator - links the comparator present in the sytem with
+@@ -52,29 +53,6 @@ int omap_usb2_set_comparator(struct phy_companion *comparator)
+ }
+ EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
+
+-/**
+- * omap_usb_phy_power - power on/off the phy using control module reg
+- * @phy: struct omap_usb *
+- * @on: 0 or 1, based on powering on or off the PHY
+- *
+- * XXX: Remove this function once control module driver gets merged
+- */
+-static void omap_usb_phy_power(struct omap_usb *phy, int on)
+-{
+- u32 val;
+-
+- if (on) {
+- val = readl(phy->control_dev);
+- if (val & PHY_PD) {
+- writel(~PHY_PD, phy->control_dev);
+- /* XXX: add proper documentation for this delay */
+- mdelay(200);
+- }
+- } else {
+- writel(PHY_PD, phy->control_dev);
+- }
+-}
+-
+ static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
+ {
+ struct omap_usb *phy = phy_to_omapusb(otg->phy);
+@@ -124,7 +102,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+ struct omap_usb *phy = phy_to_omapusb(x);
+
+ if (suspend && !phy->is_suspended) {
+- omap_usb_phy_power(phy, 0);
++ omap_control_usb_phy_power(phy->control_dev, 0);
+ pm_runtime_put_sync(phy->dev);
+ phy->is_suspended = 1;
+ } else if (!suspend && phy->is_suspended) {
+@@ -134,7 +112,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+ ret);
+ return ret;
+ }
+- omap_usb_phy_power(phy, 1);
++ omap_control_usb_phy_power(phy->control_dev, 1);
+ phy->is_suspended = 0;
+ }
+
+@@ -168,14 +146,14 @@ static int omap_usb2_probe(struct platform_device *pdev)
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+- phy->control_dev = devm_request_and_ioremap(&pdev->dev, res);
+- if (phy->control_dev == NULL) {
+- dev_err(&pdev->dev, "Failed to obtain io memory\n");
+- return -ENXIO;
++ phy->control_dev = get_omap_control_dev();
++ if (IS_ERR(phy->control_dev)) {
++ dev_dbg(&pdev->dev, "Failed to get control device\n");
++ return -ENODEV;
+ }
+
+ phy->is_suspended = 1;
+- omap_usb_phy_power(phy, 0);
++ omap_control_usb_phy_power(phy->control_dev, 0);
+
+ otg->set_host = omap_usb_set_host;
+ otg->set_peripheral = omap_usb_set_peripheral;
+diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
+index 0ea17f8..3db9b53 100644
+--- a/include/linux/usb/omap_usb.h
++++ b/include/linux/usb/omap_usb.h
+@@ -25,13 +25,11 @@ struct omap_usb {
+ struct usb_phy phy;
+ struct phy_companion *comparator;
+ struct device *dev;
+- u32 __iomem *control_dev;
++ struct device *control_dev;
+ struct clk *wkupclk;
+ u8 is_suspended:1;
+ };
+
+-#define PHY_PD 0x1
+-
+ #define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
+
+ #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
diff --git a/patches/linux-3.8.13/0443-usb-otg-Add-an-API-to-bind-the-USB-controller-and-PH.patch b/patches/linux-3.8.13/0443-usb-otg-Add-an-API-to-bind-the-USB-controller-and-PH.patch
new file mode 100644
index 0000000..966afa0
--- /dev/null
+++ b/patches/linux-3.8.13/0443-usb-otg-Add-an-API-to-bind-the-USB-controller-and-PH.patch
@@ -0,0 +1,118 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 22 Jan 2013 09:58:09 +0000
+Subject: [PATCH] usb: otg: Add an API to bind the USB controller and PHY
+
+In order to support platforms which has multiple PHY's (of same type) and
+which has multiple USB controllers, a new design is adopted wherin the binding
+information (between the PHY and the USB controller) should be passed to the
+PHY library from platform specific file (board file).
+So added a new API to pass the binding information.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ drivers/usb/otg/otg.c | 37 +++++++++++++++++++++++++++++++++++++
+ include/linux/usb/phy.h | 22 ++++++++++++++++++++++
+ 2 files changed, 59 insertions(+)
+
+diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
+index a30c041..492ba2f 100644
+--- a/drivers/usb/otg/otg.c
++++ b/drivers/usb/otg/otg.c
+@@ -18,6 +18,7 @@
+ #include <linux/usb/otg.h>
+
+ static LIST_HEAD(phy_list);
++static LIST_HEAD(phy_bind_list);
+ static DEFINE_SPINLOCK(phy_lock);
+
+ static struct usb_phy *__usb_find_phy(struct list_head *list,
+@@ -201,6 +202,42 @@ void usb_remove_phy(struct usb_phy *x)
+ }
+ EXPORT_SYMBOL(usb_remove_phy);
+
++/**
++ * usb_bind_phy - bind the phy and the controller that uses the phy
++ * @dev_name: the device name of the device that will bind to the phy
++ * @index: index to specify the port number
++ * @phy_dev_name: the device name of the phy
++ *
++ * Fills the phy_bind structure with the dev_name and phy_dev_name. This will
++ * be used when the phy driver registers the phy and when the controller
++ * requests this phy.
++ *
++ * To be used by platform specific initialization code.
++ */
++struct usb_phy_bind __init *usb_bind_phy(const char *dev_name, u8 index,
++ const char *phy_dev_name)
++{
++ struct usb_phy_bind *phy_bind;
++ unsigned long flags;
++
++ phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL);
++ if (!phy_bind) {
++ pr_err("phy_bind(): No memory for phy_bind");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ phy_bind->dev_name = dev_name;
++ phy_bind->phy_dev_name = phy_dev_name;
++ phy_bind->index = index;
++
++ spin_lock_irqsave(&phy_lock, flags);
++ list_add_tail(&phy_bind->list, &phy_bind_list);
++ spin_unlock_irqrestore(&phy_lock, flags);
++
++ return phy_bind;
++}
++EXPORT_SYMBOL_GPL(usb_bind_phy);
++
+ const char *otg_state_string(enum usb_otg_state state)
+ {
+ switch (state) {
+diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
+index a29ae1e..fbeab1a 100644
+--- a/include/linux/usb/phy.h
++++ b/include/linux/usb/phy.h
+@@ -106,6 +106,21 @@ struct usb_phy {
+ enum usb_device_speed speed);
+ };
+
++/**
++ * struct usb_phy_bind - represent the binding for the phy
++ * @dev_name: the device name of the device that will bind to the phy
++ * @phy_dev_name: the device name of the phy
++ * @index: used if a single controller uses multiple phys
++ * @phy: reference to the phy
++ * @list: to maintain a linked list of the binding information
++ */
++struct usb_phy_bind {
++ const char *dev_name;
++ const char *phy_dev_name;
++ u8 index;
++ struct usb_phy *phy;
++ struct list_head list;
++};
+
+ /* for board-specific init logic */
+ extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
+@@ -151,6 +166,8 @@ extern struct usb_phy *devm_usb_get_phy(struct device *dev,
+ enum usb_phy_type type);
+ extern void usb_put_phy(struct usb_phy *);
+ extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
++extern struct usb_phy_bind *usb_bind_phy(const char *dev_name, u8 index,
++ const char *phy_dev_name);
+ #else
+ static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
+ {
+@@ -171,6 +188,11 @@ static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
+ {
+ }
+
++static inline struct usb_phy_bind *usb_bind_phy(const char *dev_name, u8 index,
++ const char *phy_dev_name)
++{
++ return NULL;
++}
+ #endif
+
+ static inline int
diff --git a/patches/linux-3.8.13/0444-usb-otg-utils-add-facilities-in-phy-lib-to-support-m.patch b/patches/linux-3.8.13/0444-usb-otg-utils-add-facilities-in-phy-lib-to-support-m.patch
new file mode 100644
index 0000000..240af40
--- /dev/null
+++ b/patches/linux-3.8.13/0444-usb-otg-utils-add-facilities-in-phy-lib-to-support-m.patch
@@ -0,0 +1,209 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 22 Jan 2013 09:58:10 +0000
+Subject: [PATCH] usb: otg: utils: add facilities in phy lib to support
+ multiple PHYs of same type
+
+In order to add support for multipe PHY's of the same type, new API's
+for adding PHY and getting PHY has been added. Now the binding
+information for the PHY and controller should be done in platform file
+using usb_bind_phy API. And for getting a PHY, the device pointer of the
+USB controller and an index should be passed. Based on the binding
+information that is added in the platform file, usb_get_phy_dev will return the
+appropriate PHY.
+Already existing API's to add and get phy by type is not removed. These
+API's are deprecated and will be removed once all the platforms start to
+use the new API.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ drivers/usb/otg/otg.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++-
+ include/linux/usb/phy.h | 13 ++++++
+ 2 files changed, 126 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
+index 492ba2f..1f30b22 100644
+--- a/drivers/usb/otg/otg.c
++++ b/drivers/usb/otg/otg.c
+@@ -36,6 +36,20 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,
+ return ERR_PTR(-ENODEV);
+ }
+
++static struct usb_phy *__usb_find_phy_dev(struct device *dev,
++ struct list_head *list, u8 index)
++{
++ struct usb_phy_bind *phy_bind = NULL;
++
++ list_for_each_entry(phy_bind, list, list) {
++ if (!(strcmp(phy_bind->dev_name, dev_name(dev))) &&
++ phy_bind->index == index)
++ return phy_bind->phy;
++ }
++
++ return ERR_PTR(-ENODEV);
++}
++
+ static void devm_usb_phy_release(struct device *dev, void *res)
+ {
+ struct usb_phy *phy = *(struct usb_phy **)res;
+@@ -112,6 +126,69 @@ err0:
+ EXPORT_SYMBOL(usb_get_phy);
+
+ /**
++ * usb_get_phy_dev - find the USB PHY
++ * @dev - device that requests this phy
++ * @index - the index of the phy
++ *
++ * Returns the phy driver, after getting a refcount to it; or
++ * -ENODEV if there is no such phy. The caller is responsible for
++ * calling usb_put_phy() to release that count.
++ *
++ * For use by USB host and peripheral drivers.
++ */
++struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
++{
++ struct usb_phy *phy = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&phy_lock, flags);
++
++ phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
++ if (IS_ERR(phy)) {
++ pr_err("unable to find transceiver\n");
++ goto err0;
++ }
++
++ get_device(phy->dev);
++
++err0:
++ spin_unlock_irqrestore(&phy_lock, flags);
++
++ return phy;
++}
++EXPORT_SYMBOL(usb_get_phy_dev);
++
++/**
++ * devm_usb_get_phy_dev - find the USB PHY using device ptr and index
++ * @dev - device that requests this phy
++ * @index - the index of the phy
++ *
++ * Gets the phy using usb_get_phy_dev(), and associates a device with it 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_dev(struct device *dev, u8 index)
++{
++ struct usb_phy **ptr, *phy;
++
++ ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
++ if (!ptr)
++ return NULL;
++
++ phy = usb_get_phy_dev(dev, index);
++ if (!IS_ERR(phy)) {
++ *ptr = phy;
++ devres_add(dev, ptr);
++ } else
++ devres_free(ptr);
++
++ return phy;
++}
++EXPORT_SYMBOL(devm_usb_get_phy_dev);
++
++/**
+ * 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()
+@@ -186,6 +263,36 @@ out:
+ EXPORT_SYMBOL(usb_add_phy);
+
+ /**
++ * usb_add_phy_dev - declare the USB PHY
++ * @x: the USB phy to be used; or NULL
++ *
++ * This call is exclusively for use by phy drivers, which
++ * coordinate the activities of drivers for host and peripheral
++ * controllers, and in some cases for VBUS current regulation.
++ */
++int usb_add_phy_dev(struct usb_phy *x)
++{
++ struct usb_phy_bind *phy_bind;
++ unsigned long flags;
++
++ if (!x->dev) {
++ dev_err(x->dev, "no device provided for PHY\n");
++ return -EINVAL;
++ }
++
++ spin_lock_irqsave(&phy_lock, flags);
++ list_for_each_entry(phy_bind, &phy_bind_list, list)
++ if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev))))
++ phy_bind->phy = x;
++
++ list_add_tail(&x->head, &phy_list);
++
++ spin_unlock_irqrestore(&phy_lock, flags);
++ return 0;
++}
++EXPORT_SYMBOL(usb_add_phy_dev);
++
++/**
+ * usb_remove_phy - remove the OTG PHY
+ * @x: the USB OTG PHY to be removed;
+ *
+@@ -194,10 +301,15 @@ EXPORT_SYMBOL(usb_add_phy);
+ void usb_remove_phy(struct usb_phy *x)
+ {
+ unsigned long flags;
++ struct usb_phy_bind *phy_bind;
+
+ spin_lock_irqsave(&phy_lock, flags);
+- if (x)
++ if (x) {
++ list_for_each_entry(phy_bind, &phy_bind_list, list)
++ if (phy_bind->phy == x)
++ phy_bind->phy = NULL;
+ list_del(&x->head);
++ }
+ spin_unlock_irqrestore(&phy_lock, flags);
+ }
+ EXPORT_SYMBOL(usb_remove_phy);
+diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
+index fbeab1a..3a9ae3e 100644
+--- a/include/linux/usb/phy.h
++++ b/include/linux/usb/phy.h
+@@ -124,6 +124,7 @@ struct usb_phy_bind {
+
+ /* for board-specific init logic */
+ extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
++extern int usb_add_phy_dev(struct usb_phy *);
+ extern void usb_remove_phy(struct usb_phy *);
+
+ /* helpers for direct access thru low-level io interface */
+@@ -164,6 +165,8 @@ usb_phy_shutdown(struct usb_phy *x)
+ 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 *usb_get_phy_dev(struct device *dev, u8 index);
++extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index);
+ extern void usb_put_phy(struct usb_phy *);
+ extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
+ extern struct usb_phy_bind *usb_bind_phy(const char *dev_name, u8 index,
+@@ -180,6 +183,16 @@ static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
+ return NULL;
+ }
+
++static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
++{
++ return NULL;
++}
++
++static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
++{
++ return NULL;
++}
++
+ static inline void usb_put_phy(struct usb_phy *x)
+ {
+ }
diff --git a/patches/linux-3.8.13/0445-ARM-OMAP-USB-Add-phy-binding-information.patch b/patches/linux-3.8.13/0445-ARM-OMAP-USB-Add-phy-binding-information.patch
new file mode 100644
index 0000000..e1993b2
--- /dev/null
+++ b/patches/linux-3.8.13/0445-ARM-OMAP-USB-Add-phy-binding-information.patch
@@ -0,0 +1,371 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 22 Jan 2013 09:58:11 +0000
+Subject: [PATCH] ARM: OMAP: USB: Add phy binding information
+
+This is w.r.t the changes in PHY library to support adding and getting
+multiple PHYs of the same type. In the new design, the
+binding information between the PHY and the USB controller should be
+specified in the platform specific initialization code. So it's been
+done here for OMAP platforms.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ arch/arm/mach-omap2/board-2430sdp.c | 2 ++
+ arch/arm/mach-omap2/board-3430sdp.c | 2 ++
+ arch/arm/mach-omap2/board-4430sdp.c | 2 ++
+ arch/arm/mach-omap2/board-cm-t35.c | 2 ++
+ arch/arm/mach-omap2/board-devkit8000.c | 2 ++
+ arch/arm/mach-omap2/board-igep0020.c | 2 ++
+ arch/arm/mach-omap2/board-ldp.c | 2 ++
+ arch/arm/mach-omap2/board-omap3beagle.c | 2 ++
+ arch/arm/mach-omap2/board-omap3evm.c | 2 ++
+ arch/arm/mach-omap2/board-omap3logic.c | 2 ++
+ arch/arm/mach-omap2/board-omap3pandora.c | 2 ++
+ arch/arm/mach-omap2/board-omap3stalker.c | 2 ++
+ arch/arm/mach-omap2/board-omap3touchbook.c | 2 ++
+ arch/arm/mach-omap2/board-omap4panda.c | 2 ++
+ arch/arm/mach-omap2/board-overo.c | 2 ++
+ arch/arm/mach-omap2/board-rm680.c | 2 ++
+ arch/arm/mach-omap2/board-zoom-peripherals.c | 2 ++
+ 17 files changed, 34 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
+index 4815ea6..1337f2c 100644
+--- a/arch/arm/mach-omap2/board-2430sdp.c
++++ b/arch/arm/mach-omap2/board-2430sdp.c
+@@ -27,6 +27,7 @@
+ #include <linux/clk.h>
+ #include <linux/io.h>
+ #include <linux/gpio.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -263,6 +264,7 @@ static void __init omap_2430sdp_init(void)
+ omap_hsmmc_init(mmc);
+
+ omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+
+ board_smc91x_init();
+diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
+index bb73afc..8a2e242 100644
+--- a/arch/arm/mach-omap2/board-3430sdp.c
++++ b/arch/arm/mach-omap2/board-3430sdp.c
+@@ -25,6 +25,7 @@
+ #include <linux/gpio.h>
+ #include <linux/mmc/host.h>
+ #include <linux/platform_data/spi-omap2-mcspi.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -579,6 +580,7 @@ static void __init omap_3430sdp_init(void)
+ omap_ads7846_init(1, gpio_pendown, 310, NULL);
+ omap_serial_init();
+ omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ board_smc91x_init();
+ board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
+diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
+index 1cc6696..8e8efcc 100644
+--- a/arch/arm/mach-omap2/board-4430sdp.c
++++ b/arch/arm/mach-omap2/board-4430sdp.c
+@@ -28,6 +28,7 @@
+ #include <linux/leds_pwm.h>
+ #include <linux/platform_data/omap4-keypad.h>
+ #include <linux/usb/musb.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/hardware/gic.h>
+ #include <asm/mach-types.h>
+@@ -696,6 +697,7 @@ static void __init omap_4430sdp_init(void)
+ omap4_sdp4430_wifi_init();
+ omap4_twl6030_hsmmc_init(mmc);
+
++ usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto");
+ usb_musb_init(&musb_board_data);
+
+ status = omap_ethernet_init();
+diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
+index b3102c2..f1172f2 100644
+--- a/arch/arm/mach-omap2/board-cm-t35.c
++++ b/arch/arm/mach-omap2/board-cm-t35.c
+@@ -30,6 +30,7 @@
+ #include <linux/regulator/fixed.h>
+ #include <linux/regulator/machine.h>
+ #include <linux/mmc/host.h>
++#include <linux/usb/phy.h>
+
+ #include <linux/spi/spi.h>
+ #include <linux/spi/tdo24m.h>
+@@ -724,6 +725,7 @@ static void __init cm_t3x_common_init(void)
+ cm_t35_init_display();
+ omap_twl4030_audio_init("cm-t3x");
+
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ cm_t35_init_usbh();
+ cm_t35_init_camera();
+diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
+index 12865af..77cade52 100644
+--- a/arch/arm/mach-omap2/board-devkit8000.c
++++ b/arch/arm/mach-omap2/board-devkit8000.c
+@@ -29,6 +29,7 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mmc/host.h>
++#include <linux/usb/phy.h>
+
+ #include <linux/regulator/machine.h>
+ #include <linux/i2c/twl.h>
+@@ -622,6 +623,7 @@ static void __init devkit8000_init(void)
+
+ omap_ads7846_init(2, OMAP3_DEVKIT_TS_GPIO, 0, NULL);
+
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(devkit8000_nand_partitions,
+diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
+index 0f24cb8..15e5881 100644
+--- a/arch/arm/mach-omap2/board-igep0020.c
++++ b/arch/arm/mach-omap2/board-igep0020.c
+@@ -18,6 +18,7 @@
+ #include <linux/gpio.h>
+ #include <linux/interrupt.h>
+ #include <linux/input.h>
++#include <linux/usb/phy.h>
+
+ #include <linux/regulator/machine.h>
+ #include <linux/regulator/fixed.h>
+@@ -625,6 +626,7 @@ static void __init igep_init(void)
+ omap_serial_init();
+ omap_sdrc_init(m65kxxxxam_sdrc_params,
+ m65kxxxxam_sdrc_params);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+
+ igep_flash_init();
+diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
+index 0869f4f..3b5510a 100644
+--- a/arch/arm/mach-omap2/board-ldp.c
++++ b/arch/arm/mach-omap2/board-ldp.c
+@@ -28,6 +28,7 @@
+ #include <linux/io.h>
+ #include <linux/smsc911x.h>
+ #include <linux/mmc/host.h>
++#include <linux/usb/phy.h>
+ #include <linux/platform_data/spi-omap2-mcspi.h>
+
+ #include <asm/mach-types.h>
+@@ -418,6 +419,7 @@ static void __init omap_ldp_init(void)
+ omap_ads7846_init(1, 54, 310, NULL);
+ omap_serial_init();
+ omap_sdrc_init(NULL, NULL);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
+ ZOOM_NAND_CS, 0, nand_default_timings);
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 20b4e1b..a5cb58c 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -31,6 +31,7 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mmc/host.h>
++#include <linux/usb/phy.h>
+
+ #include <linux/regulator/machine.h>
+ #include <linux/regulator/fixed.h>
+@@ -1267,6 +1268,7 @@ static void __init omap3_beagle_init(void)
+ #endif
+ }
+
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(omap3beagle_nand_partitions,
+diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
+index 3985f35..a198b61 100644
+--- a/arch/arm/mach-omap2/board-omap3evm.c
++++ b/arch/arm/mach-omap2/board-omap3evm.c
+@@ -41,6 +41,7 @@
+ #include <linux/regulator/machine.h>
+ #include <linux/mmc/host.h>
+ #include <linux/export.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -734,6 +735,7 @@ static void __init omap3_evm_init(void)
+ omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
+ usbhs_bdata.reset_gpio_port[1] = 135;
+ }
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(&musb_board_data);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(omap3evm_nand_partitions,
+diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
+index 2a065ba..9409eb8 100644
+--- a/arch/arm/mach-omap2/board-omap3logic.c
++++ b/arch/arm/mach-omap2/board-omap3logic.c
+@@ -29,6 +29,7 @@
+
+ #include <linux/i2c/twl.h>
+ #include <linux/mmc/host.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -215,6 +216,7 @@ static void __init omap3logic_init(void)
+ board_mmc_init();
+ board_smsc911x_init();
+
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+
+ /* Ensure SDRC pins are mux'd for self-refresh */
+diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
+index a53a668..1ac3e81 100644
+--- a/arch/arm/mach-omap2/board-omap3pandora.c
++++ b/arch/arm/mach-omap2/board-omap3pandora.c
+@@ -35,6 +35,7 @@
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/card.h>
+ #include <linux/regulator/fixed.h>
++#include <linux/usb/phy.h>
+ #include <linux/platform_data/spi-omap2-mcspi.h>
+
+ #include <asm/mach-types.h>
+@@ -601,6 +602,7 @@ static void __init omap3pandora_init(void)
+ ARRAY_SIZE(omap3pandora_spi_board_info));
+ omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
+ usbhs_init(&usbhs_bdata);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ gpmc_nand_init(&pandora_nand_data, NULL);
+
+diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
+index 53a6cbc..63cb204 100644
+--- a/arch/arm/mach-omap2/board-omap3stalker.c
++++ b/arch/arm/mach-omap2/board-omap3stalker.c
+@@ -33,6 +33,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/smsc911x.h>
+ #include <linux/i2c/at24.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -404,6 +405,7 @@ static void __init omap3_stalker_init(void)
+
+ omap_serial_init();
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
+diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
+index 263cb9c..6b22ce3 100644
+--- a/arch/arm/mach-omap2/board-omap3touchbook.c
++++ b/arch/arm/mach-omap2/board-omap3touchbook.c
+@@ -28,6 +28,7 @@
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/nand.h>
+ #include <linux/mmc/host.h>
++#include <linux/usb/phy.h>
+
+ #include <linux/platform_data/spi-omap2-mcspi.h>
+ #include <linux/spi/spi.h>
+@@ -365,6 +366,7 @@ static void __init omap3_touchbook_init(void)
+
+ /* Touchscreen and accelerometer */
+ omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ board_nand_init(omap3touchbook_nand_partitions,
+diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
+index 769c1fe..40184cc 100644
+--- a/arch/arm/mach-omap2/board-omap4panda.c
++++ b/arch/arm/mach-omap2/board-omap4panda.c
+@@ -30,6 +30,7 @@
+ #include <linux/regulator/fixed.h>
+ #include <linux/ti_wilink_st.h>
+ #include <linux/usb/musb.h>
++#include <linux/usb/phy.h>
+ #include <linux/wl12xx.h>
+ #include <linux/platform_data/omap-abe-twl6040.h>
+
+@@ -447,6 +448,7 @@ static void __init omap4_panda_init(void)
+ omap_sdrc_init(NULL, NULL);
+ omap4_twl6030_hsmmc_init(mmc);
+ omap4_ehci_init();
++ usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto");
+ usb_musb_init(&musb_board_data);
+ omap4_panda_display_init();
+ }
+diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
+index c8fde3e..7e43ff3 100644
+--- a/arch/arm/mach-omap2/board-overo.c
++++ b/arch/arm/mach-omap2/board-overo.c
+@@ -36,6 +36,7 @@
+ #include <linux/mtd/nand.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/mmc/host.h>
++#include <linux/usb/phy.h>
+
+ #include <linux/platform_data/mtd-nand-omap2.h>
+ #include <linux/platform_data/spi-omap2-mcspi.h>
+@@ -499,6 +500,7 @@ static void __init overo_init(void)
+ mt46h32m32lf6_sdrc_params);
+ board_nand_init(overo_nand_partitions,
+ ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ overo_spi_init();
+diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
+index 0c777b7..f8a272c 100644
+--- a/arch/arm/mach-omap2/board-rm680.c
++++ b/arch/arm/mach-omap2/board-rm680.c
+@@ -18,6 +18,7 @@
+ #include <linux/regulator/machine.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/platform_data/mtd-onenand-omap2.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach-types.h>
+@@ -134,6 +135,7 @@ static void __init rm680_init(void)
+ sdrc_params = nokia_get_sdram_timings();
+ omap_sdrc_init(sdrc_params, sdrc_params);
+
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ rm680_peripherals_init();
+ }
+diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
+index 26e07ad..dc5498b 100644
+--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
++++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
+@@ -20,6 +20,7 @@
+ #include <linux/wl12xx.h>
+ #include <linux/mmc/host.h>
+ #include <linux/platform_data/gpio-omap.h>
++#include <linux/usb/phy.h>
+
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+@@ -298,6 +299,7 @@ void __init zoom_peripherals_init(void)
+ omap_hsmmc_init(mmc);
+ omap_i2c_init();
+ platform_device_register(&omap_vwlan_device);
++ usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
+ usb_musb_init(NULL);
+ enable_board_wakeup_source();
+ omap_serial_init();
diff --git a/patches/linux-3.8.13/0446-drivers-usb-musb-omap-make-use-of-the-new-PHY-lib-AP.patch b/patches/linux-3.8.13/0446-drivers-usb-musb-omap-make-use-of-the-new-PHY-lib-AP.patch
new file mode 100644
index 0000000..a9e5886
--- /dev/null
+++ b/patches/linux-3.8.13/0446-drivers-usb-musb-omap-make-use-of-the-new-PHY-lib-AP.patch
@@ -0,0 +1,72 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 22 Jan 2013 09:58:12 +0000
+Subject: [PATCH] drivers: usb: musb: omap: make use of the new PHY lib APIs
+
+New PHY lib APIs like usb_add_phy_dev() and devm_usb_get_phy_dev() are
+used in MUSB (OMAP), in order to make use of the binding information
+provided in the board file (of OMAP platforms).
+All the platforms should be modified similar to this to add and get the
+PHY.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ drivers/usb/musb/omap2430.c | 2 +-
+ drivers/usb/otg/twl4030-usb.c | 3 ++-
+ drivers/usb/phy/omap-usb2.c | 3 ++-
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 6a7e400..97ae52e 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -346,7 +346,7 @@ static int omap2430_musb_init(struct musb *musb)
+ * up through ULPI. TWL4030-family PMICs include one,
+ * which needs a driver, drivers aren't always needed.
+ */
+- musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
++ musb->xceiv = devm_usb_get_phy_dev(dev, 0);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
+ pr_err("HS USB OTG: no transceiver configured\n");
+ return -EPROBE_DEFER;
+diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
+index 0a70193..a994715 100644
+--- a/drivers/usb/otg/twl4030-usb.c
++++ b/drivers/usb/otg/twl4030-usb.c
+@@ -610,6 +610,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
+ twl->phy.dev = twl->dev;
+ twl->phy.label = "twl4030";
+ twl->phy.otg = otg;
++ twl->phy.type = USB_PHY_TYPE_USB2;
+ twl->phy.set_suspend = twl4030_set_suspend;
+
+ otg->phy = &twl->phy;
+@@ -624,7 +625,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "ldo init failed\n");
+ return err;
+ }
+- usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
++ usb_add_phy_dev(&twl->phy);
+
+ platform_set_drvdata(pdev, twl);
+ if (device_create_file(&pdev->dev, &dev_attr_vbus))
+diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
+index 2152ce4..46c79c6 100644
+--- a/drivers/usb/phy/omap-usb2.c
++++ b/drivers/usb/phy/omap-usb2.c
+@@ -143,6 +143,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
+ phy->phy.label = "omap-usb2";
+ phy->phy.set_suspend = omap_usb2_suspend;
+ phy->phy.otg = otg;
++ phy->phy.type = USB_PHY_TYPE_USB2;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+@@ -168,7 +169,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
+ }
+ clk_prepare(phy->wkupclk);
+
+- usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
++ usb_add_phy_dev(&phy->phy);
+
+ platform_set_drvdata(pdev, phy);
+
diff --git a/patches/linux-3.8.13/0447-usb-otg-add-device-tree-support-to-otg-library.patch b/patches/linux-3.8.13/0447-usb-otg-add-device-tree-support-to-otg-library.patch
new file mode 100644
index 0000000..37b526e
--- /dev/null
+++ b/patches/linux-3.8.13/0447-usb-otg-add-device-tree-support-to-otg-library.patch
@@ -0,0 +1,145 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 22 Jan 2013 09:58:13 +0000
+Subject: [PATCH] usb: otg: add device tree support to otg library
+
+Added an API devm_usb_get_phy_by_phandle(), to get usb phy by passing a
+device node phandle value. This function will return a pointer to
+the phy on success, -EPROBE_DEFER if there is a device_node for the phandle,
+but the phy has not been added, or a ERR_PTR() otherwise.
+
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ drivers/usb/otg/otg.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/usb/phy.h | 8 +++++
+ 2 files changed, 85 insertions(+)
+
+diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
+index 1f30b22..67daf8c 100644
+--- a/drivers/usb/otg/otg.c
++++ b/drivers/usb/otg/otg.c
+@@ -13,7 +13,9 @@
+ #include <linux/export.h>
+ #include <linux/err.h>
+ #include <linux/device.h>
++#include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/of.h>
+
+ #include <linux/usb/otg.h>
+
+@@ -50,6 +52,20 @@ static struct usb_phy *__usb_find_phy_dev(struct device *dev,
+ return ERR_PTR(-ENODEV);
+ }
+
++static struct usb_phy *__of_usb_find_phy(struct device_node *node)
++{
++ struct usb_phy *phy;
++
++ list_for_each_entry(phy, &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;
+@@ -125,6 +141,67 @@ 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
++ * @index - the index of the phy
++ *
++ * Returns the phy driver associated with the given phandle value,
++ * after getting a refcount to it, -ENODEV if there is no such phy or
++ * -EPROBE_DEFER if there is a phandle to the phy, but the device is
++ * not yet loaded. 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, u8 index)
++{
++ 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);
++ }
++
++ node = of_parse_phandle(dev->of_node, phandle, index);
++ if (!node) {
++ dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
++ dev->of_node->full_name);
++ return ERR_PTR(-ENODEV);
++ }
++
++ 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);
++
++ phy = __of_usb_find_phy(node);
++ if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
++ phy = ERR_PTR(-EPROBE_DEFER);
++ devres_free(ptr);
++ goto err0;
++ }
++
++ *ptr = phy;
++ devres_add(dev, ptr);
++
++ get_device(phy->dev);
++
++err0:
++ spin_unlock_irqrestore(&phy_lock, flags);
++
++ return phy;
++}
++EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
++
+ /**
+ * usb_get_phy_dev - find the USB PHY
+ * @dev - device that requests this phy
+diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
+index 3a9ae3e..c7f5a98 100644
+--- a/include/linux/usb/phy.h
++++ b/include/linux/usb/phy.h
+@@ -167,6 +167,8 @@ extern struct usb_phy *devm_usb_get_phy(struct device *dev,
+ enum usb_phy_type type);
+ extern struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index);
+ extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index);
++extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle, u8 index);
+ extern void usb_put_phy(struct usb_phy *);
+ extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
+ extern struct usb_phy_bind *usb_bind_phy(const char *dev_name, u8 index,
+@@ -193,6 +195,12 @@ static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
+ return NULL;
+ }
+
++static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle, u8 index)
++{
++ return NULL;
++}
++
+ static inline void usb_put_phy(struct usb_phy *x)
+ {
+ }
diff --git a/patches/linux-3.8.13/0448-USB-MUSB-OMAP-get-PHY-by-phandle-for-dt-boot.patch b/patches/linux-3.8.13/0448-USB-MUSB-OMAP-get-PHY-by-phandle-for-dt-boot.patch
new file mode 100644
index 0000000..8ebbba8
--- /dev/null
+++ b/patches/linux-3.8.13/0448-USB-MUSB-OMAP-get-PHY-by-phandle-for-dt-boot.patch
@@ -0,0 +1,29 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Tue, 22 Jan 2013 09:58:14 +0000
+Subject: [PATCH] USB: MUSB: OMAP: get PHY by phandle for dt boot
+
+The OMAP glue has been modified to get PHY by phandle for dt boot.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+---
+ drivers/usb/musb/omap2430.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
+index 97ae52e..05ab371 100644
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -346,7 +346,12 @@ static int omap2430_musb_init(struct musb *musb)
+ * up through ULPI. TWL4030-family PMICs include one,
+ * which needs a driver, drivers aren't always needed.
+ */
+- musb->xceiv = devm_usb_get_phy_dev(dev, 0);
++ if (dev->parent->of_node)
++ musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
++ "usb_phy", 0);
++ else
++ musb->xceiv = devm_usb_get_phy_dev(dev, 0);
++
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
+ pr_err("HS USB OTG: no transceiver configured\n");
+ return -EPROBE_DEFER;
diff --git a/patches/linux-3.8.13/0449-MUSB-Hack-around-to-make-host-port-to-work.patch b/patches/linux-3.8.13/0449-MUSB-Hack-around-to-make-host-port-to-work.patch
new file mode 100644
index 0000000..bb6aee8
--- /dev/null
+++ b/patches/linux-3.8.13/0449-MUSB-Hack-around-to-make-host-port-to-work.patch
@@ -0,0 +1,234 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 22 Jan 2013 22:25:06 +0200
+Subject: [PATCH] MUSB: Hack around to make host port to work.
+
+It sort of works, but it doesn't handle hotplug.
+After removing the device, issue lsusb to cause it to scan the bus again.
+
+Crappy, I know, but at least works.
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 6 ++++
+ arch/arm/boot/dts/am33xx.dtsi | 9 ++++--
+ drivers/usb/musb/musb_core.c | 45 +++++++++++++++++++++++---
+ drivers/usb/musb/musb_dsps.c | 49 +++++++++++++++++++++++++++--
+ drivers/usb/musb/musb_host.c | 7 +++--
+ 5 files changed, 105 insertions(+), 11 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index d525195..90178e2 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -475,3 +475,9 @@
+ &aes {
+ status = "okay";
+ };
++
++&usb_otg_hs {
++ interface_type = <1>;
++ power = <500>;
++ status = "okay";
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 5d4f913..6b71632 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -399,11 +399,15 @@
+
+ };
+
+- nop-phy {
++ nop-phy@0 {
+ compatible = "nop-xceiv-usb";
+ };
+
+- usb@47400000 {
++ nop-phy@1 {
++ compatible = "nop-xceiv-usb";
++ };
++
++ usb_otg_hs: usb@47400000 {
+ compatible = "ti,musb-am33xx";
+ reg = <0x47400000 0x1000 /* usbss */
+ 0x47401000 0x800 /* musb instance 0 */
+@@ -418,6 +422,7 @@
+ port1-mode = <1>;
+ power = <250>;
+ ti,hwmods = "usb_otg_hs";
++ status = "disabled";
+ };
+
+ mac: ethernet@4a100000 {
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 60b41cc..4afa92a 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -1955,11 +1955,43 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ musb_write_ulpi_buscontrol(musb->mregs, busctl);
+ }
+
+- MUSB_DEV_MODE(musb);
+- musb->xceiv->otg->default_a = 0;
+- musb->xceiv->state = OTG_STATE_B_IDLE;
++ dev_info(dev, "*** mode=%d\n", plat->mode);
++ dev_info(dev, "*** power=%d\n", plat->power);
+
+- status = musb_gadget_setup(musb);
++ /* 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 (plat->mode == MUSB_HOST) { /* host mode */
++
++ del_timer(&musb->otg_timer);
++
++ MUSB_HST_MODE(musb);
++ musb->xceiv->otg->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
++
++ status = usb_add_hcd(hcd, 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 {
++ MUSB_DEV_MODE(musb);
++ musb->xceiv->otg->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
++
++ status = musb_gadget_setup(musb);
++
++ dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n",
++ plat->mode == MUSB_OTG ? "OTG" : "PERIPHERAL",
++ status,
++ musb_readb(musb->mregs, MUSB_DEVCTL));
++ }
+
+ if (status < 0)
+ goto fail3;
+@@ -1982,7 +2014,10 @@ fail5:
+ musb_exit_debugfs(musb);
+
+ fail4:
+- musb_gadget_cleanup(musb);
++ if (plat->mode == MUSB_HOST)
++ usb_remove_hcd(hcd);
++ else
++ musb_gadget_cleanup(musb);
+
+ fail3:
+ pm_runtime_put_sync(musb->controller);
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 341a4b5..85a4502 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -415,19 +415,30 @@ static int dsps_musb_init(struct musb *musb)
+ /* mentor core register starts at offset of 0x400 from musb base */
+ musb->mregs += wrp->musb_core_offset;
+
++#if 1
+ /* NOP driver needs change if supporting dual instance */
+ usb_nop_xceiv_register();
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+- if (IS_ERR_OR_NULL(musb->xceiv))
++#else
++ /* Get the NOP PHY */
++ sprintf(name, "usb%d-phy", pdev->id);
++ musb->xceiv = devm_usb_get_phy_by_phandle(&parent_pdev->dev, name);
++#endif
++ if (IS_ERR_OR_NULL(musb->xceiv)) {
++ dev_err(dev, "%s:%d %s: FAIL\n", __FILE__, __LINE__, __func__);
+ return -EPROBE_DEFER;
++ }
+
+ /* Returns zero if e.g. not clocked */
+ rev = dsps_readl(reg_base, wrp->revision);
+ if (!rev) {
++ dev_err(dev, "%s:%d %s: FAIL\n", __FILE__, __LINE__, __func__);
+ status = -ENODEV;
+ goto err0;
+ }
+
++ dev_info(dev, "pdev->id = %d\n", pdev->id);
++
+ setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb);
+
+ /* Reset the musb */
+@@ -446,6 +457,8 @@ static int dsps_musb_init(struct musb *musb)
+ /* clear level interrupt */
+ dsps_writel(reg_base, wrp->eoi, 0);
+
++ dev_info(dev, "%s:%d %s: OK\n", __FILE__, __LINE__, __func__);
++
+ return 0;
+ err0:
+ usb_put_phy(musb->xceiv);
+@@ -761,9 +774,41 @@ static const struct platform_device_id musb_dsps_id_table[] = {
+ MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
+
+ #ifdef CONFIG_OF
++
++static const struct dsps_musb_wrapper am33xx_driver_data = {
++ .revision = 0x00,
++ .control = 0x14,
++ .status = 0x18,
++ .eoi = 0x24,
++ .epintr_set = 0x38,
++ .epintr_clear = 0x40,
++ .epintr_status = 0x30,
++ .coreintr_set = 0x3c,
++ .coreintr_clear = 0x44,
++ .coreintr_status = 0x34,
++ .phy_utmi = 0xe0,
++ .mode = 0xe8,
++ .reset = 0,
++ .otg_disable = 21,
++ .iddig = 8,
++ .usb_shift = 0,
++ .usb_mask = 0x1ff,
++ .usb_bitmap = (0x1ff << 0),
++ .drvvbus = 8,
++ .txep_shift = 0,
++ .txep_mask = 0xffff,
++ .txep_bitmap = (0xffff << 0),
++ .rxep_shift = 16,
++ .rxep_mask = 0xfffe,
++ .rxep_bitmap = (0xfffe << 16),
++ .musb_core_offset = 0x400,
++ .poll_seconds = 2,
++ .instances = 2,
++};
++
+ static const struct of_device_id musb_dsps_of_match[] = {
+ { .compatible = "ti,musb-am33xx",
+- .data = (void *) &ti81xx_driver_data, },
++ .data = (void *) &am33xx_driver_data, },
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index e9f0fd9..86442a2 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -2431,12 +2431,15 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
+ break;
+ }
+
++#if 0
+ if (musb->is_active) {
+ WARNING("trying to suspend as %s while active\n",
+ otg_state_string(musb->xceiv->state));
+ return -EBUSY;
+- } else
+- return 0;
++ }
++#endif
++
++ return 0;
+ }
+
+ static int musb_bus_resume(struct usb_hcd *hcd)
diff --git a/patches/linux-3.8.13/0450-make-sure-we-register-unregister-the-NOP-xceiver-onl.patch b/patches/linux-3.8.13/0450-make-sure-we-register-unregister-the-NOP-xceiver-onl.patch
new file mode 100644
index 0000000..db41380
--- /dev/null
+++ b/patches/linux-3.8.13/0450-make-sure-we-register-unregister-the-NOP-xceiver-onl.patch
@@ -0,0 +1,46 @@
+From: Vladimir Pantelic <vladoman@gmail.com>
+Date: Mon, 18 Mar 2013 13:48:33 +0100
+Subject: [PATCH] make sure we register/unregister the NOP xceiver only once
+
+Signed-off-by: Vladimir Pantelic <vladoman@gmail.com>
+---
+ drivers/usb/musb/musb_dsps.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 85a4502..077c1e7 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -417,7 +417,9 @@ static int dsps_musb_init(struct musb *musb)
+
+ #if 1
+ /* NOP driver needs change if supporting dual instance */
+- usb_nop_xceiv_register();
++ if(!pdev->id) {
++ usb_nop_xceiv_register();
++ }
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ #else
+ /* Get the NOP PHY */
+@@ -462,7 +464,9 @@ static int dsps_musb_init(struct musb *musb)
+ return 0;
+ err0:
+ usb_put_phy(musb->xceiv);
+- usb_nop_xceiv_unregister();
++ if(!pdev->id) {
++ usb_nop_xceiv_unregister();
++ }
+ return status;
+ }
+
+@@ -479,7 +483,9 @@ static int dsps_musb_exit(struct musb *musb)
+
+ /* NOP driver needs change if supporting dual instance */
+ usb_put_phy(musb->xceiv);
+- usb_nop_xceiv_unregister();
++ if(!pdev->id) {
++ usb_nop_xceiv_unregister();
++ }
+
+ return 0;
+ }
diff --git a/patches/linux-3.8.13/0451-ARM-OMAP-am335x-musb-use-250-for-power.patch b/patches/linux-3.8.13/0451-ARM-OMAP-am335x-musb-use-250-for-power.patch
new file mode 100644
index 0000000..a3cc4ad
--- /dev/null
+++ b/patches/linux-3.8.13/0451-ARM-OMAP-am335x-musb-use-250-for-power.patch
@@ -0,0 +1,42 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Wed, 3 Apr 2013 13:25:38 -0500
+Subject: [PATCH] ARM: OMAP: am335x: musb use 250 for power
+
+Issue first noticed by: Randy Rodes <randyrodesnn@gmail.com>
+https://groups.google.com/d/msg/beagleboard/qzlwO9ldULE/kXzFAY9rv8cJ
+
+According to the docs, the power value is only 8 bits, to specify 500mA
+this needs to be set to a value of 250: value * 2 = XmA
+
+Documentation/devicetree/bindings/usb/omap-usb.txt
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 2 +-
+ arch/arm/boot/dts/am335x-tester.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 90178e2..89ec6f2 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -478,6 +478,6 @@
+
+ &usb_otg_hs {
+ interface_type = <1>;
+- power = <500>;
++ power = <250>;
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/am335x-tester.dts b/arch/arm/boot/dts/am335x-tester.dts
+index 4a5ae294..c6ac8bf 100644
+--- a/arch/arm/boot/dts/am335x-tester.dts
++++ b/arch/arm/boot/dts/am335x-tester.dts
+@@ -478,6 +478,6 @@
+
+ &usb_otg_hs {
+ interface_type = <1>;
+- power = <500>;
++ power = <250>;
+ status = "okay";
+ };
diff --git a/patches/linux-3.8.13/0452-ARM-OMAP2-MUSB-Specify-omap4-has-mailbox.patch b/patches/linux-3.8.13/0452-ARM-OMAP2-MUSB-Specify-omap4-has-mailbox.patch
new file mode 100644
index 0000000..4f2f001
--- /dev/null
+++ b/patches/linux-3.8.13/0452-ARM-OMAP2-MUSB-Specify-omap4-has-mailbox.patch
@@ -0,0 +1,42 @@
+From: Kishon Vijay Abraham I <kishon@ti.com>
+Date: Wed, 6 Feb 2013 13:28:49 +0000
+Subject: [PATCH] ARM: OMAP2: MUSB: Specify omap4 has mailbox
+
+Added has_mailbox to the musb platform data to specify that omap uses
+an external mailbox (in control module) to communicate with the musb
+core during device connect and disconnect.
+
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/usb-musb.c | 3 +++
+ include/linux/usb/musb.h | 2 ++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
+index 7b33b37..9d27e3f 100644
+--- a/arch/arm/mach-omap2/usb-musb.c
++++ b/arch/arm/mach-omap2/usb-musb.c
+@@ -85,6 +85,9 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
+ musb_plat.mode = board_data->mode;
+ musb_plat.extvbus = board_data->extvbus;
+
++ if (cpu_is_omap44xx())
++ musb_plat.has_mailbox = true;
++
+ if (soc_is_am35xx()) {
+ oh_name = "am35x_otg_hs";
+ name = "musb-am35x";
+diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
+index eb50525..053c268 100644
+--- a/include/linux/usb/musb.h
++++ b/include/linux/usb/musb.h
+@@ -99,6 +99,8 @@ struct musb_hdrc_platform_data {
+ /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
+ u8 mode;
+
++ u8 has_mailbox:1;
++
+ /* for clk_get() */
+ const char *clock;
+
diff --git a/patches/linux-3.8.13/0453-usb-musb-avoid-stopping-the-session-in-host-mode.patch b/patches/linux-3.8.13/0453-usb-musb-avoid-stopping-the-session-in-host-mode.patch
new file mode 100644
index 0000000..1f24bc4
--- /dev/null
+++ b/patches/linux-3.8.13/0453-usb-musb-avoid-stopping-the-session-in-host-mode.patch
@@ -0,0 +1,30 @@
+From: Jan Luebbe <jlu@pengutronix.de>
+Date: Wed, 15 May 2013 16:41:04 +0200
+Subject: [PATCH] usb: musb: avoid stopping the session in host mode
+
+Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
+---
+ drivers/usb/musb/musb_dsps.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 077c1e7..c9946b9 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -230,8 +230,14 @@ static void otg_timer(unsigned long _musb)
+ spin_lock_irqsave(&musb->lock, flags);
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+- devctl &= ~MUSB_DEVCTL_SESSION;
+- dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
++ /*
++ * We need to avoid stopping the session in host mode,
++ * otherwise we don't see any newly connected devices
++ */
++ if (!is_host_active(musb)) {
++ devctl &= ~MUSB_DEVCTL_SESSION;
++ dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
++ }
+
+ devctl = dsps_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
diff --git a/patches/linux-3.8.13/0454-beaglebone-black-1ghz-hack.patch b/patches/linux-3.8.13/0454-beaglebone-black-1ghz-hack.patch
new file mode 100644
index 0000000..f5a24a8
--- /dev/null
+++ b/patches/linux-3.8.13/0454-beaglebone-black-1ghz-hack.patch
@@ -0,0 +1,47 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 22 Jan 2013 17:52:18 +0100
+Subject: [PATCH] beaglebone black: 1ghz hack
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-boneblack.dts | 16 ++++++++++++++++
+ arch/arm/boot/dts/am33xx.dtsi | 2 +-
+ 2 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index 5434bfd..1abf267 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -43,3 +43,19 @@
+ status = "okay";
+ };
+
++
++&cpu {
++ /*
++ * 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 */
++ 1000000 1350000
++ 800000 1300000
++ 600000 1112000
++ 300000 969000
++ >;
++};
++
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 6b71632..6c24c9b 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -24,7 +24,7 @@
+ };
+
+ cpus {
+- cpu@0 {
++ cpu: cpu@0 {
+ compatible = "arm,cortex-a8";
+
+ /*
diff --git a/patches/linux-3.8.13/0455-ARM-AM33xx-Add-SoC-specific-restart-hook.patch b/patches/linux-3.8.13/0455-ARM-AM33xx-Add-SoC-specific-restart-hook.patch
new file mode 100644
index 0000000..061980a
--- /dev/null
+++ b/patches/linux-3.8.13/0455-ARM-AM33xx-Add-SoC-specific-restart-hook.patch
@@ -0,0 +1,100 @@
+From: "Jean-Sebastien A. Beaudry" <jsabeaudry@handyem.com>
+Date: Wed, 23 Jan 2013 21:02:40 +0000
+Subject: [PATCH] ARM: AM33xx: Add SoC specific restart hook
+
+Add restart hook so that DTS based AM33xx builds can restart
+the platform.
+
+Tested-by: Nishanth Menon <nm@ti.com>
+Signed-off-by: Jean-Sebastien A. Beaudry <jsabeaudry@handyem.com>
+---
+ arch/arm/mach-omap2/Makefile | 1 +
+ arch/arm/mach-omap2/am33xx-restart.c | 34 ++++++++++++++++++++++++++++++++++
+ arch/arm/mach-omap2/board-generic.c | 1 +
+ arch/arm/mach-omap2/common.h | 8 ++++++++
+ 4 files changed, 44 insertions(+)
+ create mode 100644 arch/arm/mach-omap2/am33xx-restart.c
+
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index 6cde196..afecbbc 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -53,6 +53,7 @@ AFLAGS_sram34xx.o :=-Wa,-march=armv7-a
+ # Restart code (OMAP4/5 currently in omap4-common.c)
+ obj-$(CONFIG_SOC_OMAP2420) += omap2-restart.o
+ obj-$(CONFIG_SOC_OMAP2430) += omap2-restart.o
++obj-$(CONFIG_SOC_AM33XX) += am33xx-restart.o
+ obj-$(CONFIG_ARCH_OMAP3) += omap3-restart.o
+
+ # Pin multiplexing
+diff --git a/arch/arm/mach-omap2/am33xx-restart.c b/arch/arm/mach-omap2/am33xx-restart.c
+new file mode 100644
+index 0000000..88e4fa8
+--- /dev/null
++++ b/arch/arm/mach-omap2/am33xx-restart.c
+@@ -0,0 +1,34 @@
++/*
++ * am33xx-restart.c - Code common to all AM33xx machines.
++ *
++ * 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/kernel.h>
++
++#include "common.h"
++#include "prm-regbits-33xx.h"
++#include "prm33xx.h"
++
++/**
++ * am3xx_restart - trigger a software restart of the SoC
++ * @mode: the "reboot mode", see arch/arm/kernel/{setup,process}.c
++ * @cmd: passed from the userspace program rebooting the system (if provided)
++ *
++ * Resets the SoC. For @cmd, see the 'reboot' syscall in
++ * kernel/sys.c. No return value.
++ */
++void am33xx_restart(char mode, const char *cmd)
++{
++ /* TODO: Handle mode and cmd if necessary */
++
++ am33xx_prm_rmw_reg_bits(AM33XX_GLOBAL_WARM_SW_RST_MASK,
++ AM33XX_GLOBAL_WARM_SW_RST_MASK,
++ AM33XX_PRM_DEVICE_MOD,
++ AM33XX_PRM_RSTCTRL_OFFSET);
++
++ /* OCP barrier */
++ (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
++ AM33XX_PRM_RSTCTRL_OFFSET);
++}
+diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
+index 53cb380b..fac00f0 100644
+--- a/arch/arm/mach-omap2/board-generic.c
++++ b/arch/arm/mach-omap2/board-generic.c
+@@ -141,6 +141,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
+ .init_machine = omap_generic_init,
+ .timer = &omap3_am33xx_timer,
+ .dt_compat = am33xx_boards_compat,
++ .restart = am33xx_restart,
+ MACHINE_END
+ #endif
+
+diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
+index b9adf69..f077fbd 100644
+--- a/arch/arm/mach-omap2/common.h
++++ b/arch/arm/mach-omap2/common.h
+@@ -119,6 +119,14 @@ static inline void omap2xxx_restart(char mode, const char *cmd)
+ }
+ #endif
+
++#ifdef CONFIG_SOC_AM33XX
++void am33xx_restart(char mode, const char *cmd);
++#else
++static inline void am33xx_restart(char mode, const char *cmd)
++{
++}
++#endif
++
+ #ifdef CONFIG_ARCH_OMAP3
+ void omap3xxx_restart(char mode, const char *cmd);
+ #else
diff --git a/patches/linux-3.8.13/0456-iio-common-Add-STMicroelectronics-common-library.patch b/patches/linux-3.8.13/0456-iio-common-Add-STMicroelectronics-common-library.patch
new file mode 100644
index 0000000..27b1cad
--- /dev/null
+++ b/patches/linux-3.8.13/0456-iio-common-Add-STMicroelectronics-common-library.patch
@@ -0,0 +1,1312 @@
+From: Denis Ciocca <denis.ciocca@gmail.com>
+Date: Fri, 25 Jan 2013 23:44:00 +0000
+Subject: [PATCH] iio:common: Add STMicroelectronics common library
+
+This patch add a generic library for STMicroelectronics 3-axis sensors.
+
+Signed-off-by: Denis Ciocca <denis.ciocca@st.com>
+Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/common/Kconfig | 1 +
+ drivers/iio/common/Makefile | 1 +
+ drivers/iio/common/st_sensors/Kconfig | 14 +
+ drivers/iio/common/st_sensors/Makefile | 10 +
+ drivers/iio/common/st_sensors/st_sensors_buffer.c | 116 +++++
+ drivers/iio/common/st_sensors/st_sensors_core.c | 460 ++++++++++++++++++++
+ drivers/iio/common/st_sensors/st_sensors_i2c.c | 81 ++++
+ drivers/iio/common/st_sensors/st_sensors_spi.c | 128 ++++++
+ drivers/iio/common/st_sensors/st_sensors_trigger.c | 77 ++++
+ include/linux/iio/common/st_sensors.h | 274 ++++++++++++
+ include/linux/iio/common/st_sensors_i2c.h | 20 +
+ include/linux/iio/common/st_sensors_spi.h | 20 +
+ 12 files changed, 1202 insertions(+)
+ create mode 100644 drivers/iio/common/st_sensors/Kconfig
+ create mode 100644 drivers/iio/common/st_sensors/Makefile
+ create mode 100644 drivers/iio/common/st_sensors/st_sensors_buffer.c
+ create mode 100644 drivers/iio/common/st_sensors/st_sensors_core.c
+ create mode 100644 drivers/iio/common/st_sensors/st_sensors_i2c.c
+ create mode 100644 drivers/iio/common/st_sensors/st_sensors_spi.c
+ create mode 100644 drivers/iio/common/st_sensors/st_sensors_trigger.c
+ create mode 100644 include/linux/iio/common/st_sensors.h
+ create mode 100644 include/linux/iio/common/st_sensors_i2c.h
+ create mode 100644 include/linux/iio/common/st_sensors_spi.h
+
+diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
+index ed45ee5..0b6e97d 100644
+--- a/drivers/iio/common/Kconfig
++++ b/drivers/iio/common/Kconfig
+@@ -3,3 +3,4 @@
+ #
+
+ source "drivers/iio/common/hid-sensors/Kconfig"
++source "drivers/iio/common/st_sensors/Kconfig"
+diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
+index 8158400..c2352be 100644
+--- a/drivers/iio/common/Makefile
++++ b/drivers/iio/common/Makefile
+@@ -7,3 +7,4 @@
+ #
+
+ obj-y += hid-sensors/
++obj-y += st_sensors/
+diff --git a/drivers/iio/common/st_sensors/Kconfig b/drivers/iio/common/st_sensors/Kconfig
+new file mode 100644
+index 0000000..84b2dca
+--- /dev/null
++++ b/drivers/iio/common/st_sensors/Kconfig
+@@ -0,0 +1,14 @@
++#
++# Hid Sensor common modules
++#
++
++config IIO_ST_SENSORS_I2C
++ tristate
++
++config IIO_ST_SENSORS_SPI
++ tristate
++
++config IIO_ST_SENSORS_CORE
++ tristate
++ select IIO_ST_SENSORS_I2C if I2C
++ select IIO_ST_SENSORS_SPI if SPI_MASTER
+diff --git a/drivers/iio/common/st_sensors/Makefile b/drivers/iio/common/st_sensors/Makefile
+new file mode 100644
+index 0000000..9f3e24f
+--- /dev/null
++++ b/drivers/iio/common/st_sensors/Makefile
+@@ -0,0 +1,10 @@
++#
++# Makefile for the STMicroelectronics sensor common modules.
++#
++
++obj-$(CONFIG_IIO_ST_SENSORS_I2C) += st_sensors_i2c.o
++obj-$(CONFIG_IIO_ST_SENSORS_SPI) += st_sensors_spi.o
++obj-$(CONFIG_IIO_ST_SENSORS_CORE) += st_sensors.o
++st_sensors-y := st_sensors_core.o
++st_sensors-$(CONFIG_IIO_BUFFER) += st_sensors_buffer.o
++st_sensors-$(CONFIG_IIO_TRIGGER) += st_sensors_trigger.o
+diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c
+new file mode 100644
+index 0000000..09b236d
+--- /dev/null
++++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c
+@@ -0,0 +1,116 @@
++/*
++ * STMicroelectronics sensors buffer library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++#include <linux/interrupt.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/triggered_buffer.h>
++#include <linux/irqreturn.h>
++
++#include <linux/iio/common/st_sensors.h>
++
++
++int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
++{
++ int i, n = 0, len;
++ u8 addr[ST_SENSORS_NUMBER_DATA_CHANNELS];
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ for (i = 0; i < ST_SENSORS_NUMBER_DATA_CHANNELS; i++) {
++ if (test_bit(i, indio_dev->active_scan_mask)) {
++ addr[n] = indio_dev->channels[i].address;
++ n++;
++ }
++ }
++ switch (n) {
++ case 1:
++ len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
++ addr[0], ST_SENSORS_BYTE_FOR_CHANNEL, buf,
++ sdata->multiread_bit);
++ break;
++ case 2:
++ if ((addr[1] - addr[0]) == ST_SENSORS_BYTE_FOR_CHANNEL) {
++ len = sdata->tf->read_multiple_byte(&sdata->tb,
++ sdata->dev, addr[0],
++ ST_SENSORS_BYTE_FOR_CHANNEL*n,
++ buf, sdata->multiread_bit);
++ } else {
++ u8 rx_array[ST_SENSORS_BYTE_FOR_CHANNEL*
++ ST_SENSORS_NUMBER_DATA_CHANNELS];
++ len = sdata->tf->read_multiple_byte(&sdata->tb,
++ sdata->dev, addr[0],
++ ST_SENSORS_BYTE_FOR_CHANNEL*
++ ST_SENSORS_NUMBER_DATA_CHANNELS,
++ rx_array, sdata->multiread_bit);
++ if (len < 0)
++ goto read_data_channels_error;
++
++ for (i = 0; i < n * ST_SENSORS_NUMBER_DATA_CHANNELS;
++ i++) {
++ if (i < n)
++ buf[i] = rx_array[i];
++ else
++ buf[i] = rx_array[n + i];
++ }
++ len = ST_SENSORS_BYTE_FOR_CHANNEL*n;
++ }
++ break;
++ case 3:
++ len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
++ addr[0], ST_SENSORS_BYTE_FOR_CHANNEL*
++ ST_SENSORS_NUMBER_DATA_CHANNELS,
++ buf, sdata->multiread_bit);
++ break;
++ default:
++ len = -EINVAL;
++ goto read_data_channels_error;
++ }
++ if (len != ST_SENSORS_BYTE_FOR_CHANNEL*n) {
++ len = -EIO;
++ goto read_data_channels_error;
++ }
++
++read_data_channels_error:
++ return len;
++}
++EXPORT_SYMBOL(st_sensors_get_buffer_element);
++
++irqreturn_t st_sensors_trigger_handler(int irq, void *p)
++{
++ int len;
++ struct iio_poll_func *pf = p;
++ struct iio_dev *indio_dev = pf->indio_dev;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data);
++ if (len < 0)
++ goto st_sensors_get_buffer_element_error;
++
++ if (indio_dev->scan_timestamp)
++ *(s64 *)((u8 *)sdata->buffer_data +
++ ALIGN(len, sizeof(s64))) = pf->timestamp;
++
++ iio_push_to_buffers(indio_dev, sdata->buffer_data);
++
++st_sensors_get_buffer_element_error:
++ iio_trigger_notify_done(indio_dev->trig);
++
++ return IRQ_HANDLED;
++}
++EXPORT_SYMBOL(st_sensors_trigger_handler);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics ST-sensors buffer");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
+new file mode 100644
+index 0000000..fba6d68
+--- /dev/null
++++ b/drivers/iio/common/st_sensors/st_sensors_core.c
+@@ -0,0 +1,460 @@
++/*
++ * STMicroelectronics sensors core library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/iio/iio.h>
++#include <asm/unaligned.h>
++
++#include <linux/iio/common/st_sensors.h>
++
++
++#define ST_SENSORS_WAI_ADDRESS 0x0f
++
++static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
++ u8 reg_addr, u8 mask, u8 data)
++{
++ int err;
++ u8 new_data;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data);
++ if (err < 0)
++ goto st_sensors_write_data_with_mask_error;
++
++ new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask));
++ err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data);
++
++st_sensors_write_data_with_mask_error:
++ return err;
++}
++
++int st_sensors_get_sampling_frequency_avl(struct iio_dev *indio_dev, char *buf)
++{
++ int i, len = 0;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ mutex_lock(&indio_dev->mlock);
++ for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
++ if (sdata->sensor->odr.odr_avl[i].hz == 0)
++ break;
++
++ len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
++ sdata->sensor->odr.odr_avl[i].hz);
++ }
++ mutex_unlock(&indio_dev->mlock);
++ buf[len - 1] = '\n';
++
++ return len;
++}
++EXPORT_SYMBOL(st_sensors_get_sampling_frequency_avl);
++
++int st_sensors_get_scale_avl(struct iio_dev *indio_dev, char *buf)
++{
++ int i, len = 0;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ mutex_lock(&indio_dev->mlock);
++ for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
++ if (sdata->sensor->fs.fs_avl[i].num == 0)
++ break;
++
++ len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
++ sdata->sensor->fs.fs_avl[i].gain);
++ }
++ mutex_unlock(&indio_dev->mlock);
++ buf[len - 1] = '\n';
++
++ return len;
++}
++EXPORT_SYMBOL(st_sensors_get_scale_avl);
++
++static int st_sensors_match_odr(struct st_sensors *sensor,
++ unsigned int odr, struct st_sensor_odr_avl *odr_out)
++{
++ int i, ret = -EINVAL;
++
++ for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
++ if (sensor->odr.odr_avl[i].hz == 0)
++ goto st_sensors_match_odr_error;
++
++ if (sensor->odr.odr_avl[i].hz == odr) {
++ odr_out->hz = sensor->odr.odr_avl[i].hz;
++ odr_out->value = sensor->odr.odr_avl[i].value;
++ ret = 0;
++ break;
++ }
++ }
++
++st_sensors_match_odr_error:
++ return ret;
++}
++
++int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
++{
++ int err;
++ struct st_sensor_odr_avl odr_out;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ err = st_sensors_match_odr(sdata->sensor, odr, &odr_out);
++ if (err < 0)
++ goto st_sensors_match_odr_error;
++
++ if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
++ (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
++ if (sdata->enabled == true) {
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->odr.addr,
++ sdata->sensor->odr.mask,
++ odr_out.value);
++ } else {
++ err = 0;
++ }
++ } else {
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->odr.addr, sdata->sensor->odr.mask,
++ odr_out.value);
++ }
++ if (err >= 0)
++ sdata->odr = odr_out.hz;
++
++st_sensors_match_odr_error:
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_set_odr);
++
++static int st_sensors_match_fs(struct st_sensors *sensor,
++ unsigned int fs, int *index_fs_avl)
++{
++ int i, ret = -EINVAL;
++
++ for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
++ if (sensor->fs.fs_avl[i].num == 0)
++ goto st_sensors_match_odr_error;
++
++ if (sensor->fs.fs_avl[i].num == fs) {
++ *index_fs_avl = i;
++ ret = 0;
++ break;
++ }
++ }
++
++st_sensors_match_odr_error:
++ return ret;
++}
++
++static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
++{
++ int err, i;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ err = st_sensors_match_fs(sdata->sensor, fs, &i);
++ if (err < 0)
++ goto st_accel_set_fullscale_error;
++
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->fs.addr,
++ sdata->sensor->fs.mask,
++ sdata->sensor->fs.fs_avl[i].value);
++ if (err < 0)
++ goto st_accel_set_fullscale_error;
++
++ sdata->current_fullscale = (struct st_sensor_fullscale_avl *)
++ &sdata->sensor->fs.fs_avl[i];
++ return err;
++
++st_accel_set_fullscale_error:
++ dev_err(&indio_dev->dev, "failed to set new fullscale.\n");
++ return err;
++}
++
++int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable)
++{
++ bool found;
++ u8 tmp_value;
++ int err = -EINVAL;
++ struct st_sensor_odr_avl odr_out;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ if (enable) {
++ found = false;
++ tmp_value = sdata->sensor->pw.value_on;
++ if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
++ (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
++ err = st_sensors_match_odr(sdata->sensor,
++ sdata->odr, &odr_out);
++ if (err < 0)
++ goto set_enable_error;
++ tmp_value = odr_out.value;
++ found = true;
++ }
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->pw.addr,
++ sdata->sensor->pw.mask, tmp_value);
++ if (err < 0)
++ goto set_enable_error;
++
++ sdata->enabled = true;
++
++ if (found)
++ sdata->odr = odr_out.hz;
++ } else {
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->pw.addr,
++ sdata->sensor->pw.mask,
++ sdata->sensor->pw.value_off);
++ if (err < 0)
++ goto set_enable_error;
++
++ sdata->enabled = false;
++ }
++
++set_enable_error:
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_set_enable);
++
++int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
++{
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ return st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->enable_axis.addr,
++ sdata->sensor->enable_axis.mask, axis_enable);
++}
++EXPORT_SYMBOL(st_sensors_set_axis_enable);
++
++int st_sensors_init_sensor(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ mutex_init(&sdata->tb.buf_lock);
++
++ err = st_sensors_set_enable(indio_dev, false);
++ if (err < 0)
++ goto init_error;
++
++ err = st_sensors_set_fullscale(indio_dev,
++ sdata->current_fullscale->num);
++ if (err < 0)
++ goto init_error;
++
++ err = st_sensors_set_odr(indio_dev, sdata->odr);
++ if (err < 0)
++ goto init_error;
++
++ /* set BDU */
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->bdu.addr, sdata->sensor->bdu.mask, true);
++ if (err < 0)
++ goto init_error;
++
++ err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
++
++init_error:
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_init_sensor);
++
++int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
++{
++ int err;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ /* Enable/Disable the interrupt generator 1. */
++ if (sdata->sensor->drdy_irq.ig1.en_addr > 0) {
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->drdy_irq.ig1.en_addr,
++ sdata->sensor->drdy_irq.ig1.en_mask, (int)enable);
++ if (err < 0)
++ goto st_accel_set_dataready_irq_error;
++ }
++
++ /* Enable/Disable the interrupt generator for data ready. */
++ err = st_sensors_write_data_with_mask(indio_dev,
++ sdata->sensor->drdy_irq.addr,
++ sdata->sensor->drdy_irq.mask, (int)enable);
++
++st_accel_set_dataready_irq_error:
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_set_dataready_irq);
++
++int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale)
++{
++ int err = -EINVAL, i;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
++ if ((sdata->sensor->fs.fs_avl[i].gain == scale) &&
++ (sdata->sensor->fs.fs_avl[i].gain != 0)) {
++ err = 0;
++ break;
++ }
++ }
++ if (err < 0)
++ goto st_sensors_match_scale_error;
++
++ err = st_sensors_set_fullscale(indio_dev,
++ sdata->sensor->fs.fs_avl[i].num);
++
++st_sensors_match_scale_error:
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain);
++
++static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
++ u8 ch_addr, int *data)
++{
++ int err;
++ u8 outdata[ST_SENSORS_BYTE_FOR_CHANNEL];
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
++ ch_addr, ST_SENSORS_BYTE_FOR_CHANNEL,
++ outdata, sdata->multiread_bit);
++ if (err < 0)
++ goto read_error;
++
++ *data = (s16)get_unaligned_le16(outdata);
++
++read_error:
++ return err;
++}
++
++int st_sensors_read_info_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *ch, int *val)
++{
++ int err;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ mutex_lock(&indio_dev->mlock);
++ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
++ err = -EBUSY;
++ goto read_error;
++ } else {
++ err = st_sensors_set_enable(indio_dev, true);
++ if (err < 0)
++ goto read_error;
++
++ msleep((sdata->sensor->bootime * 1000) / sdata->odr);
++ err = st_sensors_read_axis_data(indio_dev, ch->address, val);
++ if (err < 0)
++ goto read_error;
++
++ *val = *val >> ch->scan_type.shift;
++ }
++ mutex_unlock(&indio_dev->mlock);
++
++ return err;
++
++read_error:
++ mutex_unlock(&indio_dev->mlock);
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_read_info_raw);
++
++int st_sensors_check_device_support(struct iio_dev *indio_dev,
++ int num_sensors_list, const struct st_sensors *sensors)
++{
++ u8 wai;
++ int i, n, err;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
++ ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai);
++ if (err < 0) {
++ dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
++ goto read_wai_error;
++ }
++
++ for (i = 0; i < num_sensors_list; i++) {
++ if (sensors[i].wai == wai)
++ break;
++ }
++ if (i == num_sensors_list)
++ goto device_not_supported;
++
++ for (n = 0; n < ARRAY_SIZE(sensors[i].sensors_supported); n++) {
++ if (strcmp(indio_dev->name,
++ &sensors[i].sensors_supported[n][0]) == 0)
++ break;
++ }
++ if (n == ARRAY_SIZE(sensors[i].sensors_supported)) {
++ dev_err(&indio_dev->dev, "device name and WhoAmI mismatch.\n");
++ goto sensor_name_mismatch;
++ }
++
++ sdata->sensor = (struct st_sensors *)&sensors[i];
++
++ return i;
++
++device_not_supported:
++ dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai);
++sensor_name_mismatch:
++ err = -ENODEV;
++read_wai_error:
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_check_device_support);
++
++ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev));
++
++ return sprintf(buf, "%d\n", adata->odr);
++}
++EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency);
++
++ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ int err;
++ unsigned int odr;
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++
++ err = kstrtoint(buf, 10, &odr);
++ if (err < 0)
++ goto conversion_error;
++
++ mutex_lock(&indio_dev->mlock);
++ err = st_sensors_set_odr(indio_dev, odr);
++ mutex_unlock(&indio_dev->mlock);
++
++conversion_error:
++ return err < 0 ? err : size;
++}
++EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency);
++
++ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++
++ return st_sensors_get_sampling_frequency_avl(indio_dev, buf);
++}
++EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail);
++
++ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++
++ return st_sensors_get_scale_avl(indio_dev, buf);
++}
++EXPORT_SYMBOL(st_sensors_sysfs_scale_avail);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics ST-sensors core");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
+new file mode 100644
+index 0000000..38af944
+--- /dev/null
++++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
+@@ -0,0 +1,81 @@
++/*
++ * STMicroelectronics sensors i2c library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/iio/iio.h>
++
++#include <linux/iio/common/st_sensors_i2c.h>
++
++
++#define ST_SENSORS_I2C_MULTIREAD 0x80
++
++static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev)
++{
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ return to_i2c_client(sdata->dev)->irq;
++}
++
++static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, u8 *res_byte)
++{
++ int err;
++
++ err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr);
++ if (err < 0)
++ goto st_accel_i2c_read_byte_error;
++
++ *res_byte = err & 0xff;
++
++st_accel_i2c_read_byte_error:
++ return err < 0 ? err : 0;
++}
++
++static int st_sensors_i2c_read_multiple_byte(
++ struct st_sensor_transfer_buffer *tb, struct device *dev,
++ u8 reg_addr, int len, u8 *data, bool multiread_bit)
++{
++ if (multiread_bit)
++ reg_addr |= ST_SENSORS_I2C_MULTIREAD;
++
++ return i2c_smbus_read_i2c_block_data(to_i2c_client(dev),
++ reg_addr, len, data);
++}
++
++static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, u8 data)
++{
++ return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data);
++}
++
++static const struct st_sensor_transfer_function st_sensors_tf_i2c = {
++ .read_byte = st_sensors_i2c_read_byte,
++ .write_byte = st_sensors_i2c_write_byte,
++ .read_multiple_byte = st_sensors_i2c_read_multiple_byte,
++};
++
++void st_sensors_i2c_configure(struct iio_dev *indio_dev,
++ struct i2c_client *client, struct st_sensor_data *sdata)
++{
++ i2c_set_clientdata(client, indio_dev);
++
++ indio_dev->dev.parent = &client->dev;
++ indio_dev->name = client->name;
++
++ sdata->tf = &st_sensors_tf_i2c;
++ sdata->get_irq_data_ready = st_sensors_i2c_get_irq;
++}
++EXPORT_SYMBOL(st_sensors_i2c_configure);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
+new file mode 100644
+index 0000000..f0aa2f1
+--- /dev/null
++++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
+@@ -0,0 +1,128 @@
++/*
++ * STMicroelectronics sensors spi library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/iio/iio.h>
++
++#include <linux/iio/common/st_sensors_spi.h>
++
++
++#define ST_SENSORS_SPI_MULTIREAD 0xc0
++#define ST_SENSORS_SPI_READ 0x80
++
++static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
++{
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ return to_spi_device(sdata->dev)->irq;
++}
++
++static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit)
++{
++ struct spi_message msg;
++ int err;
++
++ struct spi_transfer xfers[] = {
++ {
++ .tx_buf = tb->tx_buf,
++ .bits_per_word = 8,
++ .len = 1,
++ },
++ {
++ .rx_buf = tb->rx_buf,
++ .bits_per_word = 8,
++ .len = len,
++ }
++ };
++
++ mutex_lock(&tb->buf_lock);
++ if ((multiread_bit) && (len > 1))
++ tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD;
++ else
++ tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ;
++
++ spi_message_init(&msg);
++ spi_message_add_tail(&xfers[0], &msg);
++ spi_message_add_tail(&xfers[1], &msg);
++ err = spi_sync(to_spi_device(dev), &msg);
++ if (err)
++ goto acc_spi_read_error;
++
++ memcpy(data, tb->rx_buf, len*sizeof(u8));
++ mutex_unlock(&tb->buf_lock);
++ return len;
++
++acc_spi_read_error:
++ mutex_unlock(&tb->buf_lock);
++ return err;
++}
++
++static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, u8 *res_byte)
++{
++ return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false);
++}
++
++static int st_sensors_spi_read_multiple_byte(
++ struct st_sensor_transfer_buffer *tb, struct device *dev,
++ u8 reg_addr, int len, u8 *data, bool multiread_bit)
++{
++ return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit);
++}
++
++static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, u8 data)
++{
++ struct spi_message msg;
++ int err;
++
++ struct spi_transfer xfers = {
++ .tx_buf = tb->tx_buf,
++ .bits_per_word = 8,
++ .len = 2,
++ };
++
++ mutex_lock(&tb->buf_lock);
++ tb->tx_buf[0] = reg_addr;
++ tb->tx_buf[1] = data;
++
++ spi_message_init(&msg);
++ spi_message_add_tail(&xfers, &msg);
++ err = spi_sync(to_spi_device(dev), &msg);
++ mutex_unlock(&tb->buf_lock);
++
++ return err;
++}
++
++static const struct st_sensor_transfer_function st_sensors_tf_spi = {
++ .read_byte = st_sensors_spi_read_byte,
++ .write_byte = st_sensors_spi_write_byte,
++ .read_multiple_byte = st_sensors_spi_read_multiple_byte,
++};
++
++void st_sensors_spi_configure(struct iio_dev *indio_dev,
++ struct spi_device *spi, struct st_sensor_data *sdata)
++{
++ spi_set_drvdata(spi, indio_dev);
++
++ indio_dev->dev.parent = &spi->dev;
++ indio_dev->name = spi->modalias;
++
++ sdata->tf = &st_sensors_tf_spi;
++ sdata->get_irq_data_ready = st_sensors_spi_get_irq;
++}
++EXPORT_SYMBOL(st_sensors_spi_configure);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics ST-sensors spi driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
+new file mode 100644
+index 0000000..139ed03
+--- /dev/null
++++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
+@@ -0,0 +1,77 @@
++/*
++ * STMicroelectronics sensors trigger library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++#include <linux/interrupt.h>
++
++#include <linux/iio/common/st_sensors.h>
++
++
++int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
++ const struct iio_trigger_ops *trigger_ops)
++{
++ int err;
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name);
++ if (sdata->trig == NULL) {
++ err = -ENOMEM;
++ dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n");
++ goto iio_trigger_alloc_error;
++ }
++
++ err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
++ iio_trigger_generic_data_rdy_poll,
++ NULL,
++ IRQF_TRIGGER_RISING,
++ sdata->trig->name,
++ sdata->trig);
++ if (err)
++ goto request_irq_error;
++
++ sdata->trig->private_data = indio_dev;
++ sdata->trig->ops = trigger_ops;
++ sdata->trig->dev.parent = sdata->dev;
++
++ err = iio_trigger_register(sdata->trig);
++ if (err < 0) {
++ dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
++ goto iio_trigger_register_error;
++ }
++ indio_dev->trig = sdata->trig;
++
++ return 0;
++
++iio_trigger_register_error:
++ free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig);
++request_irq_error:
++ iio_trigger_free(sdata->trig);
++iio_trigger_alloc_error:
++ return err;
++}
++EXPORT_SYMBOL(st_sensors_allocate_trigger);
++
++void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
++{
++ struct st_sensor_data *sdata = iio_priv(indio_dev);
++
++ iio_trigger_unregister(sdata->trig);
++ free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig);
++ iio_trigger_free(sdata->trig);
++}
++EXPORT_SYMBOL(st_sensors_deallocate_trigger);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics ST-sensors trigger");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
+new file mode 100644
+index 0000000..3cc8571
+--- /dev/null
++++ b/include/linux/iio/common/st_sensors.h
+@@ -0,0 +1,274 @@
++/*
++ * STMicroelectronics sensors library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#ifndef ST_SENSORS_H
++#define ST_SENSORS_H
++
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <linux/irqreturn.h>
++#include <linux/iio/trigger.h>
++
++#define ST_SENSORS_TX_MAX_LENGTH 2
++#define ST_SENSORS_RX_MAX_LENGTH 6
++
++#define ST_SENSORS_ODR_LIST_MAX 10
++#define ST_SENSORS_FULLSCALE_AVL_MAX 10
++
++#define ST_SENSORS_NUMBER_ALL_CHANNELS 4
++#define ST_SENSORS_NUMBER_DATA_CHANNELS 3
++#define ST_SENSORS_ENABLE_ALL_AXIS 0x07
++#define ST_SENSORS_BYTE_FOR_CHANNEL 2
++#define ST_SENSORS_SCAN_X 0
++#define ST_SENSORS_SCAN_Y 1
++#define ST_SENSORS_SCAN_Z 2
++#define ST_SENSORS_DEFAULT_12_REALBITS 12
++#define ST_SENSORS_DEFAULT_16_REALBITS 16
++#define ST_SENSORS_DEFAULT_POWER_ON_VALUE 0x01
++#define ST_SENSORS_DEFAULT_POWER_OFF_VALUE 0x00
++#define ST_SENSORS_DEFAULT_WAI_ADDRESS 0x0f
++#define ST_SENSORS_DEFAULT_AXIS_ADDR 0x20
++#define ST_SENSORS_DEFAULT_AXIS_MASK 0x07
++#define ST_SENSORS_DEFAULT_AXIS_N_BIT 3
++
++#define ST_SENSORS_MAX_NAME 17
++#define ST_SENSORS_MAX_4WAI 7
++
++#define ST_SENSORS_LSM_CHANNELS(device_type, index, mod, endian, bits, addr) \
++{ \
++ .type = device_type, \
++ .modified = 1, \
++ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
++ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
++ .scan_index = index, \
++ .channel2 = mod, \
++ .address = addr, \
++ .scan_type = { \
++ .sign = 's', \
++ .realbits = bits, \
++ .shift = 16 - bits, \
++ .storagebits = 16, \
++ .endianness = endian, \
++ }, \
++}
++
++#define ST_SENSOR_DEV_ATTR_SAMP_FREQ() \
++ IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, \
++ st_sensors_sysfs_get_sampling_frequency, \
++ st_sensors_sysfs_set_sampling_frequency)
++
++#define ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL() \
++ IIO_DEV_ATTR_SAMP_FREQ_AVAIL( \
++ st_sensors_sysfs_sampling_frequency_avail)
++
++#define ST_SENSORS_DEV_ATTR_SCALE_AVAIL(name) \
++ IIO_DEVICE_ATTR(name, S_IRUGO, \
++ st_sensors_sysfs_scale_avail, NULL , 0);
++
++struct st_sensor_odr_avl {
++ unsigned int hz;
++ u8 value;
++};
++
++struct st_sensor_odr {
++ u8 addr;
++ u8 mask;
++ struct st_sensor_odr_avl odr_avl[ST_SENSORS_ODR_LIST_MAX];
++};
++
++struct st_sensor_power {
++ u8 addr;
++ u8 mask;
++ u8 value_off;
++ u8 value_on;
++};
++
++struct st_sensor_axis {
++ u8 addr;
++ u8 mask;
++};
++
++struct st_sensor_fullscale_avl {
++ unsigned int num;
++ u8 value;
++ unsigned int gain;
++ unsigned int gain2;
++};
++
++struct st_sensor_fullscale {
++ u8 addr;
++ u8 mask;
++ struct st_sensor_fullscale_avl fs_avl[ST_SENSORS_FULLSCALE_AVL_MAX];
++};
++
++/**
++ * struct st_sensor_bdu - ST sensor device block data update
++ * @addr: address of the register.
++ * @mask: mask to write the block data update flag.
++ */
++struct st_sensor_bdu {
++ u8 addr;
++ u8 mask;
++};
++
++/**
++ * struct st_sensor_data_ready_irq - ST sensor device data-ready interrupt
++ * @addr: address of the register.
++ * @mask: mask to write the on/off value.
++ * struct ig1 - represents the Interrupt Generator 1 of sensors.
++ * @en_addr: address of the enable ig1 register.
++ * @en_mask: mask to write the on/off value for enable.
++ */
++struct st_sensor_data_ready_irq {
++ u8 addr;
++ u8 mask;
++ struct {
++ u8 en_addr;
++ u8 en_mask;
++ } ig1;
++};
++
++/**
++ * struct st_sensor_transfer_buffer - ST sensor device I/O buffer
++ * @buf_lock: Mutex to protect rx and tx buffers.
++ * @tx_buf: Buffer used by SPI transfer function to send data to the sensors.
++ * This buffer is used to avoid DMA not-aligned issue.
++ * @rx_buf: Buffer used by SPI transfer to receive data from sensors.
++ * This buffer is used to avoid DMA not-aligned issue.
++ */
++struct st_sensor_transfer_buffer {
++ struct mutex buf_lock;
++ u8 rx_buf[ST_SENSORS_RX_MAX_LENGTH];
++ u8 tx_buf[ST_SENSORS_TX_MAX_LENGTH] ____cacheline_aligned;
++};
++
++/**
++ * struct st_sensor_transfer_function - ST sensor device I/O function
++ * @read_byte: Function used to read one byte.
++ * @write_byte: Function used to write one byte.
++ * @read_multiple_byte: Function used to read multiple byte.
++ */
++struct st_sensor_transfer_function {
++ int (*read_byte) (struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, u8 *res_byte);
++ int (*write_byte) (struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, u8 data);
++ int (*read_multiple_byte) (struct st_sensor_transfer_buffer *tb,
++ struct device *dev, u8 reg_addr, int len, u8 *data,
++ bool multiread_bit);
++};
++
++/**
++ * struct st_sensors - ST sensors list
++ * @wai: Contents of WhoAmI register.
++ * @sensors_supported: List of supported sensors by struct itself.
++ * @ch: IIO channels for the sensor.
++ * @odr: Output data rate register and ODR list available.
++ * @pw: Power register of the sensor.
++ * @enable_axis: Enable one or more axis of the sensor.
++ * @fs: Full scale register and full scale list available.
++ * @bdu: Block data update register.
++ * @drdy_irq: Data ready register of the sensor.
++ * @multi_read_bit: Use or not particular bit for [I2C/SPI] multi-read.
++ * @bootime: samples to discard when sensor passing from power-down to power-up.
++ */
++struct st_sensors {
++ u8 wai;
++ char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
++ struct iio_chan_spec *ch;
++ struct st_sensor_odr odr;
++ struct st_sensor_power pw;
++ struct st_sensor_axis enable_axis;
++ struct st_sensor_fullscale fs;
++ struct st_sensor_bdu bdu;
++ struct st_sensor_data_ready_irq drdy_irq;
++ bool multi_read_bit;
++ unsigned int bootime;
++};
++
++/**
++ * struct st_sensor_data - ST sensor device status
++ * @dev: Pointer to instance of struct device (I2C or SPI).
++ * @trig: The trigger in use by the core driver.
++ * @sensor: Pointer to the current sensor struct in use.
++ * @current_fullscale: Maximum range of measure by the sensor.
++ * @enabled: Status of the sensor (false->off, true->on).
++ * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread.
++ * @buffer_data: Data used by buffer part.
++ * @odr: Output data rate of the sensor [Hz].
++ * @get_irq_data_ready: Function to get the IRQ used for data ready signal.
++ * @tf: Transfer function structure used by I/O operations.
++ * @tb: Transfer buffers and mutex used by I/O operations.
++ */
++struct st_sensor_data {
++ struct device *dev;
++ struct iio_trigger *trig;
++ struct st_sensors *sensor;
++ struct st_sensor_fullscale_avl *current_fullscale;
++
++ bool enabled;
++ bool multiread_bit;
++
++ char *buffer_data;
++
++ unsigned int odr;
++
++ unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev);
++
++ const struct st_sensor_transfer_function *tf;
++ struct st_sensor_transfer_buffer tb;
++};
++
++#ifdef CONFIG_IIO_BUFFER
++int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
++ const struct iio_trigger_ops *trigger_ops);
++
++void st_sensors_deallocate_trigger(struct iio_dev *indio_dev);
++
++irqreturn_t st_sensors_trigger_handler(int irq, void *p);
++
++int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
++#endif
++
++int st_sensors_init_sensor(struct iio_dev *indio_dev);
++
++int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable);
++
++int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable);
++
++int st_sensors_get_sampling_frequency_avl(struct iio_dev *indio_dev, char *buf);
++
++int st_sensors_get_scale_avl(struct iio_dev *indio_dev, char *buf);
++
++int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr);
++
++int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable);
++
++int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale);
++
++int st_sensors_read_info_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *ch, int *val);
++
++int st_sensors_check_device_support(struct iio_dev *indio_dev,
++ int num_sensors_list, const struct st_sensors *sensors);
++
++ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
++ struct device_attribute *attr, char *buf);
++
++ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size);
++
++ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
++ struct device_attribute *attr, char *buf);
++
++ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
++ struct device_attribute *attr, char *buf);
++
++#endif /* ST_SENSORS_H */
+diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h
+new file mode 100644
+index 0000000..67d8453
+--- /dev/null
++++ b/include/linux/iio/common/st_sensors_i2c.h
+@@ -0,0 +1,20 @@
++/*
++ * STMicroelectronics sensors i2c library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#ifndef ST_SENSORS_I2C_H
++#define ST_SENSORS_I2C_H
++
++#include <linux/i2c.h>
++#include <linux/iio/common/st_sensors.h>
++
++void st_sensors_i2c_configure(struct iio_dev *indio_dev,
++ struct i2c_client *client, struct st_sensor_data *sdata);
++
++#endif /* ST_SENSORS_I2C_H */
+diff --git a/include/linux/iio/common/st_sensors_spi.h b/include/linux/iio/common/st_sensors_spi.h
+new file mode 100644
+index 0000000..d964a35
+--- /dev/null
++++ b/include/linux/iio/common/st_sensors_spi.h
+@@ -0,0 +1,20 @@
++/*
++ * STMicroelectronics sensors spi library driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#ifndef ST_SENSORS_SPI_H
++#define ST_SENSORS_SPI_H
++
++#include <linux/spi/spi.h>
++#include <linux/iio/common/st_sensors.h>
++
++void st_sensors_spi_configure(struct iio_dev *indio_dev,
++ struct spi_device *spi, struct st_sensor_data *sdata);
++
++#endif /* ST_SENSORS_SPI_H */
diff --git a/patches/linux-3.8.13/0457-iio-accel-Add-STMicroelectronics-accelerometers-driv.patch b/patches/linux-3.8.13/0457-iio-accel-Add-STMicroelectronics-accelerometers-driv.patch
new file mode 100644
index 0000000..9c6a09f
--- /dev/null
+++ b/patches/linux-3.8.13/0457-iio-accel-Add-STMicroelectronics-accelerometers-driv.patch
@@ -0,0 +1,950 @@
+From: Denis Ciocca <denis.ciocca@gmail.com>
+Date: Fri, 25 Jan 2013 23:44:00 +0000
+Subject: [PATCH] iio:accel: Add STMicroelectronics accelerometers driver
+
+This patch adds a generic accelerometer driver for STMicroelectronics
+accelerometers, currently it supports:
+LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
+LIS331DLH, LSM303DL, LSM303DLM, LSM330.
+
+Signed-off-by: Denis Ciocca <denis.ciocca@st.com>
+Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/accel/Kconfig | 38 +++
+ drivers/iio/accel/Makefile | 9 +
+ drivers/iio/accel/st_accel.h | 47 ++++
+ drivers/iio/accel/st_accel_buffer.c | 114 ++++++++
+ drivers/iio/accel/st_accel_core.c | 495 +++++++++++++++++++++++++++++++++++
+ drivers/iio/accel/st_accel_i2c.c | 87 ++++++
+ drivers/iio/accel/st_accel_spi.c | 86 ++++++
+ 7 files changed, 876 insertions(+)
+ create mode 100644 drivers/iio/accel/st_accel.h
+ create mode 100644 drivers/iio/accel/st_accel_buffer.c
+ create mode 100644 drivers/iio/accel/st_accel_core.c
+ create mode 100644 drivers/iio/accel/st_accel_i2c.c
+ create mode 100644 drivers/iio/accel/st_accel_spi.c
+
+diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
+index 05e996f..bb59496 100644
+--- a/drivers/iio/accel/Kconfig
++++ b/drivers/iio/accel/Kconfig
+@@ -14,4 +14,42 @@ config HID_SENSOR_ACCEL_3D
+ Say yes here to build support for the HID SENSOR
+ accelerometers 3D.
+
++config KXSD9
++ tristate "Kionix KXSD9 Accelerometer Driver"
++ depends on SPI
++ help
++ Say yes here to build support for the Kionix KXSD9 accelerometer.
++ Currently this only supports the device via an SPI interface.
++
++config IIO_ST_ACCEL_3AXIS
++ tristate "STMicroelectronics accelerometers 3-Axis Driver"
++ depends on (I2C || SPI_MASTER) && SYSFS
++ select IIO_ST_SENSORS_CORE
++ select IIO_ST_ACCEL_I2C_3AXIS if (I2C)
++ select IIO_ST_ACCEL_SPI_3AXIS if (SPI_MASTER)
++ select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
++ select IIO_ST_ACCEL_BUFFER if (IIO_TRIGGERED_BUFFER)
++ help
++ Say yes here to build support for STMicroelectronics accelerometers:
++ LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
++ LIS331DLH, LSM303DL, LSM303DLM, LSM330.
++
++ This driver can also be built as a module. If so, will be created
++ these modules:
++ - st_accel (core functions for the driver [it is mandatory]);
++ - st_accel_i2c (necessary for the I2C devices [optional*]);
++ - st_accel_spi (necessary for the SPI devices [optional*]);
++
++ (*) one of these is necessary to do something.
++
++config IIO_ST_ACCEL_I2C_3AXIS
++ tristate
++ depends on IIO_ST_ACCEL_3AXIS
++ depends on IIO_ST_SENSORS_I2C
++
++config IIO_ST_ACCEL_SPI_3AXIS
++ tristate
++ depends on IIO_ST_ACCEL_3AXIS
++ depends on IIO_ST_SENSORS_SPI
++
+ endmenu
+diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
+index 5bc6855..87d8fa2 100644
+--- a/drivers/iio/accel/Makefile
++++ b/drivers/iio/accel/Makefile
+@@ -3,3 +3,12 @@
+ #
+
+ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
++
++obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
++st_accel-y := st_accel_core.o
++st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.o
++
++obj-$(CONFIG_IIO_ST_ACCEL_I2C_3AXIS) += st_accel_i2c.o
++obj-$(CONFIG_IIO_ST_ACCEL_SPI_3AXIS) += st_accel_spi.o
++
++obj-$(CONFIG_KXSD9) += kxsd9.o
+diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
+new file mode 100644
+index 0000000..37949b9
+--- /dev/null
++++ b/drivers/iio/accel/st_accel.h
+@@ -0,0 +1,47 @@
++/*
++ * STMicroelectronics accelerometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ * v. 1.0.0
++ * Licensed under the GPL-2.
++ */
++
++#ifndef ST_ACCEL_H
++#define ST_ACCEL_H
++
++#include <linux/types.h>
++#include <linux/iio/common/st_sensors.h>
++
++#define LSM303DLHC_ACCEL_DEV_NAME "lsm303dlhc_accel"
++#define LIS3DH_ACCEL_DEV_NAME "lis3dh"
++#define LSM330D_ACCEL_DEV_NAME "lsm330d_accel"
++#define LSM330DL_ACCEL_DEV_NAME "lsm330dl_accel"
++#define LSM330DLC_ACCEL_DEV_NAME "lsm330dlc_accel"
++#define LIS331DLH_ACCEL_DEV_NAME "lis331dlh"
++#define LSM303DL_ACCEL_DEV_NAME "lsm303dl_accel"
++#define LSM303DLH_ACCEL_DEV_NAME "lsm303dlh_accel"
++#define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel"
++#define LSM330_ACCEL_DEV_NAME "lsm330_accel"
++
++int st_accel_common_probe(struct iio_dev *indio_dev);
++void st_accel_common_remove(struct iio_dev *indio_dev);
++
++#ifdef CONFIG_IIO_BUFFER
++int st_accel_allocate_ring(struct iio_dev *indio_dev);
++void st_accel_deallocate_ring(struct iio_dev *indio_dev);
++int st_accel_trig_set_state(struct iio_trigger *trig, bool state);
++#define ST_ACCEL_TRIGGER_SET_STATE (&st_accel_trig_set_state)
++#else /* CONFIG_IIO_BUFFER */
++static inline int st_accel_allocate_ring(struct iio_dev *indio_dev)
++{
++ return 0;
++}
++static inline void st_accel_deallocate_ring(struct iio_dev *indio_dev)
++{
++}
++#define ST_ACCEL_TRIGGER_SET_STATE NULL
++#endif /* CONFIG_IIO_BUFFER */
++
++#endif /* ST_ACCEL_H */
+diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c
+new file mode 100644
+index 0000000..6bd82c7
+--- /dev/null
++++ b/drivers/iio/accel/st_accel_buffer.c
+@@ -0,0 +1,114 @@
++/*
++ * STMicroelectronics accelerometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/triggered_buffer.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include "st_accel.h"
++
++int st_accel_trig_set_state(struct iio_trigger *trig, bool state)
++{
++ struct iio_dev *indio_dev = trig->private_data;
++
++ return st_sensors_set_dataready_irq(indio_dev, state);
++}
++
++static int st_accel_buffer_preenable(struct iio_dev *indio_dev)
++{
++ int err;
++
++ err = st_sensors_set_enable(indio_dev, true);
++ if (err < 0)
++ goto st_accel_set_enable_error;
++
++ err = iio_sw_buffer_preenable(indio_dev);
++
++st_accel_set_enable_error:
++ return err;
++}
++
++static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *adata = iio_priv(indio_dev);
++
++ adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
++ if (adata->buffer_data == NULL) {
++ err = -ENOMEM;
++ goto allocate_memory_error;
++ }
++
++ err = st_sensors_set_axis_enable(indio_dev,
++ (u8)indio_dev->active_scan_mask[0]);
++ if (err < 0)
++ goto st_accel_buffer_postenable_error;
++
++ err = iio_triggered_buffer_postenable(indio_dev);
++ if (err < 0)
++ goto st_accel_buffer_postenable_error;
++
++ return err;
++
++st_accel_buffer_postenable_error:
++ kfree(adata->buffer_data);
++allocate_memory_error:
++ return err;
++}
++
++static int st_accel_buffer_predisable(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *adata = iio_priv(indio_dev);
++
++ err = iio_triggered_buffer_predisable(indio_dev);
++ if (err < 0)
++ goto st_accel_buffer_predisable_error;
++
++ err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
++ if (err < 0)
++ goto st_accel_buffer_predisable_error;
++
++ err = st_sensors_set_enable(indio_dev, false);
++
++st_accel_buffer_predisable_error:
++ kfree(adata->buffer_data);
++ return err;
++}
++
++static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = {
++ .preenable = &st_accel_buffer_preenable,
++ .postenable = &st_accel_buffer_postenable,
++ .predisable = &st_accel_buffer_predisable,
++};
++
++int st_accel_allocate_ring(struct iio_dev *indio_dev)
++{
++ return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
++ &st_sensors_trigger_handler, &st_accel_buffer_setup_ops);
++}
++
++void st_accel_deallocate_ring(struct iio_dev *indio_dev)
++{
++ iio_triggered_buffer_cleanup(indio_dev);
++}
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics accelerometers buffer");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
+new file mode 100644
+index 0000000..a235de2
+--- /dev/null
++++ b/drivers/iio/accel/st_accel_core.c
+@@ -0,0 +1,495 @@
++/*
++ * STMicroelectronics accelerometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/mutex.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/gpio.h>
++#include <linux/irq.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/sysfs.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/buffer.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include "st_accel.h"
++
++/* DEFAULT VALUE FOR SENSORS */
++#define ST_ACCEL_DEFAULT_OUT_X_L_ADDR 0x28
++#define ST_ACCEL_DEFAULT_OUT_Y_L_ADDR 0x2a
++#define ST_ACCEL_DEFAULT_OUT_Z_L_ADDR 0x2c
++
++/* FULLSCALE */
++#define ST_ACCEL_FS_AVL_2G 2
++#define ST_ACCEL_FS_AVL_4G 4
++#define ST_ACCEL_FS_AVL_6G 6
++#define ST_ACCEL_FS_AVL_8G 8
++#define ST_ACCEL_FS_AVL_16G 16
++
++/* CUSTOM VALUES FOR SENSOR 1 */
++#define ST_ACCEL_1_WAI_EXP 0x33
++#define ST_ACCEL_1_ODR_ADDR 0x20
++#define ST_ACCEL_1_ODR_MASK 0xf0
++#define ST_ACCEL_1_ODR_AVL_1HZ_VAL 0x01
++#define ST_ACCEL_1_ODR_AVL_10HZ_VAL 0x02
++#define ST_ACCEL_1_ODR_AVL_25HZ_VAL 0x03
++#define ST_ACCEL_1_ODR_AVL_50HZ_VAL 0x04
++#define ST_ACCEL_1_ODR_AVL_100HZ_VAL 0x05
++#define ST_ACCEL_1_ODR_AVL_200HZ_VAL 0x06
++#define ST_ACCEL_1_ODR_AVL_400HZ_VAL 0x07
++#define ST_ACCEL_1_ODR_AVL_1600HZ_VAL 0x08
++#define ST_ACCEL_1_FS_ADDR 0x23
++#define ST_ACCEL_1_FS_MASK 0x30
++#define ST_ACCEL_1_FS_AVL_2_VAL 0x00
++#define ST_ACCEL_1_FS_AVL_4_VAL 0x01
++#define ST_ACCEL_1_FS_AVL_8_VAL 0x02
++#define ST_ACCEL_1_FS_AVL_16_VAL 0x03
++#define ST_ACCEL_1_FS_AVL_2_GAIN IIO_G_TO_M_S_2(1000)
++#define ST_ACCEL_1_FS_AVL_4_GAIN IIO_G_TO_M_S_2(2000)
++#define ST_ACCEL_1_FS_AVL_8_GAIN IIO_G_TO_M_S_2(4000)
++#define ST_ACCEL_1_FS_AVL_16_GAIN IIO_G_TO_M_S_2(12000)
++#define ST_ACCEL_1_BDU_ADDR 0x23
++#define ST_ACCEL_1_BDU_MASK 0x80
++#define ST_ACCEL_1_DRDY_IRQ_ADDR 0x22
++#define ST_ACCEL_1_DRDY_IRQ_MASK 0x10
++#define ST_ACCEL_1_MULTIREAD_BIT true
++
++/* CUSTOM VALUES FOR SENSOR 2 */
++#define ST_ACCEL_2_WAI_EXP 0x32
++#define ST_ACCEL_2_ODR_ADDR 0x20
++#define ST_ACCEL_2_ODR_MASK 0x18
++#define ST_ACCEL_2_ODR_AVL_50HZ_VAL 0x00
++#define ST_ACCEL_2_ODR_AVL_100HZ_VAL 0x01
++#define ST_ACCEL_2_ODR_AVL_400HZ_VAL 0x02
++#define ST_ACCEL_2_ODR_AVL_1000HZ_VAL 0x03
++#define ST_ACCEL_2_PW_ADDR 0x20
++#define ST_ACCEL_2_PW_MASK 0xe0
++#define ST_ACCEL_2_FS_ADDR 0x23
++#define ST_ACCEL_2_FS_MASK 0x30
++#define ST_ACCEL_2_FS_AVL_2_VAL 0X00
++#define ST_ACCEL_2_FS_AVL_4_VAL 0X01
++#define ST_ACCEL_2_FS_AVL_8_VAL 0x03
++#define ST_ACCEL_2_FS_AVL_2_GAIN IIO_G_TO_M_S_2(1000)
++#define ST_ACCEL_2_FS_AVL_4_GAIN IIO_G_TO_M_S_2(2000)
++#define ST_ACCEL_2_FS_AVL_8_GAIN IIO_G_TO_M_S_2(3900)
++#define ST_ACCEL_2_BDU_ADDR 0x23
++#define ST_ACCEL_2_BDU_MASK 0x80
++#define ST_ACCEL_2_DRDY_IRQ_ADDR 0x22
++#define ST_ACCEL_2_DRDY_IRQ_MASK 0x02
++#define ST_ACCEL_2_MULTIREAD_BIT true
++
++/* CUSTOM VALUES FOR SENSOR 3 */
++#define ST_ACCEL_3_WAI_EXP 0x40
++#define ST_ACCEL_3_ODR_ADDR 0x20
++#define ST_ACCEL_3_ODR_MASK 0xf0
++#define ST_ACCEL_3_ODR_AVL_3HZ_VAL 0x01
++#define ST_ACCEL_3_ODR_AVL_6HZ_VAL 0x02
++#define ST_ACCEL_3_ODR_AVL_12HZ_VAL 0x03
++#define ST_ACCEL_3_ODR_AVL_25HZ_VAL 0x04
++#define ST_ACCEL_3_ODR_AVL_50HZ_VAL 0x05
++#define ST_ACCEL_3_ODR_AVL_100HZ_VAL 0x06
++#define ST_ACCEL_3_ODR_AVL_200HZ_VAL 0x07
++#define ST_ACCEL_3_ODR_AVL_400HZ_VAL 0x08
++#define ST_ACCEL_3_ODR_AVL_800HZ_VAL 0x09
++#define ST_ACCEL_3_ODR_AVL_1600HZ_VAL 0x0a
++#define ST_ACCEL_3_FS_ADDR 0x24
++#define ST_ACCEL_3_FS_MASK 0x38
++#define ST_ACCEL_3_FS_AVL_2_VAL 0X00
++#define ST_ACCEL_3_FS_AVL_4_VAL 0X01
++#define ST_ACCEL_3_FS_AVL_6_VAL 0x02
++#define ST_ACCEL_3_FS_AVL_8_VAL 0x03
++#define ST_ACCEL_3_FS_AVL_16_VAL 0x04
++#define ST_ACCEL_3_FS_AVL_2_GAIN IIO_G_TO_M_S_2(61)
++#define ST_ACCEL_3_FS_AVL_4_GAIN IIO_G_TO_M_S_2(122)
++#define ST_ACCEL_3_FS_AVL_6_GAIN IIO_G_TO_M_S_2(183)
++#define ST_ACCEL_3_FS_AVL_8_GAIN IIO_G_TO_M_S_2(244)
++#define ST_ACCEL_3_FS_AVL_16_GAIN IIO_G_TO_M_S_2(732)
++#define ST_ACCEL_3_BDU_ADDR 0x20
++#define ST_ACCEL_3_BDU_MASK 0x08
++#define ST_ACCEL_3_DRDY_IRQ_ADDR 0x23
++#define ST_ACCEL_3_DRDY_IRQ_MASK 0x80
++#define ST_ACCEL_3_IG1_EN_ADDR 0x23
++#define ST_ACCEL_3_IG1_EN_MASK 0x08
++#define ST_ACCEL_3_MULTIREAD_BIT false
++
++static const struct iio_chan_spec st_accel_12bit_channels[] = {
++ ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
++ ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
++ ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
++ ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
++ IIO_CHAN_SOFT_TIMESTAMP(3)
++};
++
++static const struct iio_chan_spec st_accel_16bit_channels[] = {
++ ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
++ IIO_CHAN_SOFT_TIMESTAMP(3)
++};
++
++static const struct st_sensors st_accel_sensors[] = {
++ {
++ .wai = ST_ACCEL_1_WAI_EXP,
++ .sensors_supported = {
++ [0] = LIS3DH_ACCEL_DEV_NAME,
++ [1] = LSM303DLHC_ACCEL_DEV_NAME,
++ [2] = LSM330D_ACCEL_DEV_NAME,
++ [3] = LSM330DL_ACCEL_DEV_NAME,
++ [4] = LSM330DLC_ACCEL_DEV_NAME,
++ },
++ .ch = (struct iio_chan_spec *)st_accel_12bit_channels,
++ .odr = {
++ .addr = ST_ACCEL_1_ODR_ADDR,
++ .mask = ST_ACCEL_1_ODR_MASK,
++ .odr_avl = {
++ { 1, ST_ACCEL_1_ODR_AVL_1HZ_VAL, },
++ { 10, ST_ACCEL_1_ODR_AVL_10HZ_VAL, },
++ { 25, ST_ACCEL_1_ODR_AVL_25HZ_VAL, },
++ { 50, ST_ACCEL_1_ODR_AVL_50HZ_VAL, },
++ { 100, ST_ACCEL_1_ODR_AVL_100HZ_VAL, },
++ { 200, ST_ACCEL_1_ODR_AVL_200HZ_VAL, },
++ { 400, ST_ACCEL_1_ODR_AVL_400HZ_VAL, },
++ { 1600, ST_ACCEL_1_ODR_AVL_1600HZ_VAL, },
++ },
++ },
++ .pw = {
++ .addr = ST_ACCEL_1_ODR_ADDR,
++ .mask = ST_ACCEL_1_ODR_MASK,
++ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
++ },
++ .enable_axis = {
++ .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
++ .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
++ },
++ .fs = {
++ .addr = ST_ACCEL_1_FS_ADDR,
++ .mask = ST_ACCEL_1_FS_MASK,
++ .fs_avl = {
++ [0] = {
++ .num = ST_ACCEL_FS_AVL_2G,
++ .value = ST_ACCEL_1_FS_AVL_2_VAL,
++ .gain = ST_ACCEL_1_FS_AVL_2_GAIN,
++ },
++ [1] = {
++ .num = ST_ACCEL_FS_AVL_4G,
++ .value = ST_ACCEL_1_FS_AVL_4_VAL,
++ .gain = ST_ACCEL_1_FS_AVL_4_GAIN,
++ },
++ [2] = {
++ .num = ST_ACCEL_FS_AVL_8G,
++ .value = ST_ACCEL_1_FS_AVL_8_VAL,
++ .gain = ST_ACCEL_1_FS_AVL_8_GAIN,
++ },
++ [3] = {
++ .num = ST_ACCEL_FS_AVL_16G,
++ .value = ST_ACCEL_1_FS_AVL_16_VAL,
++ .gain = ST_ACCEL_1_FS_AVL_16_GAIN,
++ },
++ },
++ },
++ .bdu = {
++ .addr = ST_ACCEL_1_BDU_ADDR,
++ .mask = ST_ACCEL_1_BDU_MASK,
++ },
++ .drdy_irq = {
++ .addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
++ .mask = ST_ACCEL_1_DRDY_IRQ_MASK,
++ },
++ .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
++ .bootime = 2,
++ },
++ {
++ .wai = ST_ACCEL_2_WAI_EXP,
++ .sensors_supported = {
++ [0] = LIS331DLH_ACCEL_DEV_NAME,
++ [1] = LSM303DL_ACCEL_DEV_NAME,
++ [2] = LSM303DLH_ACCEL_DEV_NAME,
++ [3] = LSM303DLM_ACCEL_DEV_NAME,
++ },
++ .ch = (struct iio_chan_spec *)st_accel_12bit_channels,
++ .odr = {
++ .addr = ST_ACCEL_2_ODR_ADDR,
++ .mask = ST_ACCEL_2_ODR_MASK,
++ .odr_avl = {
++ { 50, ST_ACCEL_2_ODR_AVL_50HZ_VAL, },
++ { 100, ST_ACCEL_2_ODR_AVL_100HZ_VAL, },
++ { 400, ST_ACCEL_2_ODR_AVL_400HZ_VAL, },
++ { 1000, ST_ACCEL_2_ODR_AVL_1000HZ_VAL, },
++ },
++ },
++ .pw = {
++ .addr = ST_ACCEL_2_PW_ADDR,
++ .mask = ST_ACCEL_2_PW_MASK,
++ .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
++ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
++ },
++ .enable_axis = {
++ .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
++ .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
++ },
++ .fs = {
++ .addr = ST_ACCEL_2_FS_ADDR,
++ .mask = ST_ACCEL_2_FS_MASK,
++ .fs_avl = {
++ [0] = {
++ .num = ST_ACCEL_FS_AVL_2G,
++ .value = ST_ACCEL_2_FS_AVL_2_VAL,
++ .gain = ST_ACCEL_2_FS_AVL_2_GAIN,
++ },
++ [1] = {
++ .num = ST_ACCEL_FS_AVL_4G,
++ .value = ST_ACCEL_2_FS_AVL_4_VAL,
++ .gain = ST_ACCEL_2_FS_AVL_4_GAIN,
++ },
++ [2] = {
++ .num = ST_ACCEL_FS_AVL_8G,
++ .value = ST_ACCEL_2_FS_AVL_8_VAL,
++ .gain = ST_ACCEL_2_FS_AVL_8_GAIN,
++ },
++ },
++ },
++ .bdu = {
++ .addr = ST_ACCEL_2_BDU_ADDR,
++ .mask = ST_ACCEL_2_BDU_MASK,
++ },
++ .drdy_irq = {
++ .addr = ST_ACCEL_2_DRDY_IRQ_ADDR,
++ .mask = ST_ACCEL_2_DRDY_IRQ_MASK,
++ },
++ .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
++ .bootime = 2,
++ },
++ {
++ .wai = ST_ACCEL_3_WAI_EXP,
++ .sensors_supported = {
++ [0] = LSM330_ACCEL_DEV_NAME,
++ },
++ .ch = (struct iio_chan_spec *)st_accel_16bit_channels,
++ .odr = {
++ .addr = ST_ACCEL_3_ODR_ADDR,
++ .mask = ST_ACCEL_3_ODR_MASK,
++ .odr_avl = {
++ { 3, ST_ACCEL_3_ODR_AVL_3HZ_VAL },
++ { 6, ST_ACCEL_3_ODR_AVL_6HZ_VAL, },
++ { 12, ST_ACCEL_3_ODR_AVL_12HZ_VAL, },
++ { 25, ST_ACCEL_3_ODR_AVL_25HZ_VAL, },
++ { 50, ST_ACCEL_3_ODR_AVL_50HZ_VAL, },
++ { 100, ST_ACCEL_3_ODR_AVL_100HZ_VAL, },
++ { 200, ST_ACCEL_3_ODR_AVL_200HZ_VAL, },
++ { 400, ST_ACCEL_3_ODR_AVL_400HZ_VAL, },
++ { 800, ST_ACCEL_3_ODR_AVL_800HZ_VAL, },
++ { 1600, ST_ACCEL_3_ODR_AVL_1600HZ_VAL, },
++ },
++ },
++ .pw = {
++ .addr = ST_ACCEL_3_ODR_ADDR,
++ .mask = ST_ACCEL_3_ODR_MASK,
++ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
++ },
++ .enable_axis = {
++ .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
++ .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
++ },
++ .fs = {
++ .addr = ST_ACCEL_3_FS_ADDR,
++ .mask = ST_ACCEL_3_FS_MASK,
++ .fs_avl = {
++ [0] = {
++ .num = ST_ACCEL_FS_AVL_2G,
++ .value = ST_ACCEL_3_FS_AVL_2_VAL,
++ .gain = ST_ACCEL_3_FS_AVL_2_GAIN,
++ },
++ [1] = {
++ .num = ST_ACCEL_FS_AVL_4G,
++ .value = ST_ACCEL_3_FS_AVL_4_VAL,
++ .gain = ST_ACCEL_3_FS_AVL_4_GAIN,
++ },
++ [2] = {
++ .num = ST_ACCEL_FS_AVL_6G,
++ .value = ST_ACCEL_3_FS_AVL_6_VAL,
++ .gain = ST_ACCEL_3_FS_AVL_6_GAIN,
++ },
++ [3] = {
++ .num = ST_ACCEL_FS_AVL_8G,
++ .value = ST_ACCEL_3_FS_AVL_8_VAL,
++ .gain = ST_ACCEL_3_FS_AVL_8_GAIN,
++ },
++ [4] = {
++ .num = ST_ACCEL_FS_AVL_16G,
++ .value = ST_ACCEL_3_FS_AVL_16_VAL,
++ .gain = ST_ACCEL_3_FS_AVL_16_GAIN,
++ },
++ },
++ },
++ .bdu = {
++ .addr = ST_ACCEL_3_BDU_ADDR,
++ .mask = ST_ACCEL_3_BDU_MASK,
++ },
++ .drdy_irq = {
++ .addr = ST_ACCEL_3_DRDY_IRQ_ADDR,
++ .mask = ST_ACCEL_3_DRDY_IRQ_MASK,
++ .ig1 = {
++ .en_addr = ST_ACCEL_3_IG1_EN_ADDR,
++ .en_mask = ST_ACCEL_3_IG1_EN_MASK,
++ },
++ },
++ .multi_read_bit = ST_ACCEL_3_MULTIREAD_BIT,
++ .bootime = 2,
++ },
++};
++
++static int st_accel_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *ch, int *val,
++ int *val2, long mask)
++{
++ int err;
++ struct st_sensor_data *adata = iio_priv(indio_dev);
++
++ switch (mask) {
++ case IIO_CHAN_INFO_RAW:
++ err = st_sensors_read_info_raw(indio_dev, ch, val);
++ if (err < 0)
++ goto read_error;
++
++ return IIO_VAL_INT;
++ case IIO_CHAN_INFO_SCALE:
++ *val = 0;
++ *val2 = adata->current_fullscale->gain;
++ return IIO_VAL_INT_PLUS_MICRO;
++ default:
++ return -EINVAL;
++ }
++
++read_error:
++ return err;
++}
++
++static int st_accel_write_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan, int val, int val2, long mask)
++{
++ int err;
++
++ switch (mask) {
++ case IIO_CHAN_INFO_SCALE:
++ err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return err;
++}
++
++static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
++static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
++static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
++
++static struct attribute *st_accel_attributes[] = {
++ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
++ &iio_dev_attr_in_accel_scale_available.dev_attr.attr,
++ &iio_dev_attr_sampling_frequency.dev_attr.attr,
++ NULL,
++};
++
++static const struct attribute_group st_accel_attribute_group = {
++ .attrs = st_accel_attributes,
++};
++
++static const struct iio_info accel_info = {
++ .driver_module = THIS_MODULE,
++ .attrs = &st_accel_attribute_group,
++ .read_raw = &st_accel_read_raw,
++ .write_raw = &st_accel_write_raw,
++};
++
++static const struct iio_trigger_ops st_accel_trigger_ops = {
++ .owner = THIS_MODULE,
++ .set_trigger_state = ST_ACCEL_TRIGGER_SET_STATE,
++};
++
++int st_accel_common_probe(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *adata = iio_priv(indio_dev);
++
++ indio_dev->modes = INDIO_DIRECT_MODE;
++ indio_dev->info = &accel_info;
++
++ err = st_sensors_check_device_support(indio_dev,
++ ARRAY_SIZE(st_accel_sensors), st_accel_sensors);
++ if (err < 0)
++ goto st_accel_common_probe_error;
++
++ adata->multiread_bit = adata->sensor->multi_read_bit;
++ indio_dev->channels = adata->sensor->ch;
++ indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
++
++ adata->current_fullscale = (struct st_sensor_fullscale_avl *)
++ &adata->sensor->fs.fs_avl[0];
++ adata->odr = adata->sensor->odr.odr_avl[0].hz;
++
++ err = st_sensors_init_sensor(indio_dev);
++ if (err < 0)
++ goto st_accel_common_probe_error;
++
++ if (adata->get_irq_data_ready(indio_dev) > 0) {
++ err = st_accel_allocate_ring(indio_dev);
++ if (err < 0)
++ goto st_accel_common_probe_error;
++
++ err = st_sensors_allocate_trigger(indio_dev,
++ &st_accel_trigger_ops);
++ if (err < 0)
++ goto st_accel_probe_trigger_error;
++ }
++
++ err = iio_device_register(indio_dev);
++ if (err)
++ goto st_accel_device_register_error;
++
++ return err;
++
++st_accel_device_register_error:
++ if (adata->get_irq_data_ready(indio_dev) > 0)
++ st_sensors_deallocate_trigger(indio_dev);
++st_accel_probe_trigger_error:
++ if (adata->get_irq_data_ready(indio_dev) > 0)
++ st_accel_deallocate_ring(indio_dev);
++st_accel_common_probe_error:
++ return err;
++}
++EXPORT_SYMBOL(st_accel_common_probe);
++
++void st_accel_common_remove(struct iio_dev *indio_dev)
++{
++ struct st_sensor_data *adata = iio_priv(indio_dev);
++
++ iio_device_unregister(indio_dev);
++ if (adata->get_irq_data_ready(indio_dev) > 0) {
++ st_sensors_deallocate_trigger(indio_dev);
++ st_accel_deallocate_ring(indio_dev);
++ }
++ iio_device_free(indio_dev);
++}
++EXPORT_SYMBOL(st_accel_common_remove);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics accelerometers driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
+new file mode 100644
+index 0000000..90b8ddf
+--- /dev/null
++++ b/drivers/iio/accel/st_accel_i2c.c
+@@ -0,0 +1,87 @@
++/*
++ * STMicroelectronics accelerometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include <linux/iio/common/st_sensors_i2c.h>
++#include "st_accel.h"
++
++static int st_accel_i2c_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct iio_dev *indio_dev;
++ struct st_sensor_data *adata;
++ int err;
++
++ indio_dev = iio_device_alloc(sizeof(*adata));
++ if (indio_dev == NULL) {
++ err = -ENOMEM;
++ goto iio_device_alloc_error;
++ }
++
++ adata = iio_priv(indio_dev);
++ adata->dev = &client->dev;
++
++ st_sensors_i2c_configure(indio_dev, client, adata);
++
++ err = st_accel_common_probe(indio_dev);
++ if (err < 0)
++ goto st_accel_common_probe_error;
++
++ return 0;
++
++st_accel_common_probe_error:
++ iio_device_free(indio_dev);
++iio_device_alloc_error:
++ return err;
++}
++
++static int st_accel_i2c_remove(struct i2c_client *client)
++{
++ st_accel_common_remove(i2c_get_clientdata(client));
++
++ return 0;
++}
++
++static const struct i2c_device_id st_accel_id_table[] = {
++ { LSM303DLH_ACCEL_DEV_NAME },
++ { LSM303DLHC_ACCEL_DEV_NAME },
++ { LIS3DH_ACCEL_DEV_NAME },
++ { LSM330D_ACCEL_DEV_NAME },
++ { LSM330DL_ACCEL_DEV_NAME },
++ { LSM330DLC_ACCEL_DEV_NAME },
++ { LIS331DLH_ACCEL_DEV_NAME },
++ { LSM303DL_ACCEL_DEV_NAME },
++ { LSM303DLM_ACCEL_DEV_NAME },
++ { LSM330_ACCEL_DEV_NAME },
++ {},
++};
++MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
++
++static struct i2c_driver st_accel_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "st-accel-i2c",
++ },
++ .probe = st_accel_i2c_probe,
++ .remove = st_accel_i2c_remove,
++ .id_table = st_accel_id_table,
++};
++module_i2c_driver(st_accel_driver);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics accelerometers i2c driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
+new file mode 100644
+index 0000000..dbd45c0
+--- /dev/null
++++ b/drivers/iio/accel/st_accel_spi.c
+@@ -0,0 +1,86 @@
++/*
++ * STMicroelectronics accelerometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/spi/spi.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include <linux/iio/common/st_sensors_spi.h>
++#include "st_accel.h"
++
++static int st_accel_spi_probe(struct spi_device *spi)
++{
++ struct iio_dev *indio_dev;
++ struct st_sensor_data *adata;
++ int err;
++
++ indio_dev = iio_device_alloc(sizeof(*adata));
++ if (indio_dev == NULL) {
++ err = -ENOMEM;
++ goto iio_device_alloc_error;
++ }
++
++ adata = iio_priv(indio_dev);
++ adata->dev = &spi->dev;
++
++ st_sensors_spi_configure(indio_dev, spi, adata);
++
++ err = st_accel_common_probe(indio_dev);
++ if (err < 0)
++ goto st_accel_common_probe_error;
++
++ return 0;
++
++st_accel_common_probe_error:
++ iio_device_free(indio_dev);
++iio_device_alloc_error:
++ return err;
++}
++
++static int st_accel_spi_remove(struct spi_device *spi)
++{
++ st_accel_common_remove(spi_get_drvdata(spi));
++
++ return 0;
++}
++
++static const struct spi_device_id st_accel_id_table[] = {
++ { LSM303DLH_ACCEL_DEV_NAME },
++ { LSM303DLHC_ACCEL_DEV_NAME },
++ { LIS3DH_ACCEL_DEV_NAME },
++ { LSM330D_ACCEL_DEV_NAME },
++ { LSM330DL_ACCEL_DEV_NAME },
++ { LSM330DLC_ACCEL_DEV_NAME },
++ { LIS331DLH_ACCEL_DEV_NAME },
++ { LSM303DL_ACCEL_DEV_NAME },
++ { LSM303DLM_ACCEL_DEV_NAME },
++ { LSM330_ACCEL_DEV_NAME },
++ {},
++};
++MODULE_DEVICE_TABLE(spi, st_accel_id_table);
++
++static struct spi_driver st_accel_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "st-accel-spi",
++ },
++ .probe = st_accel_spi_probe,
++ .remove = st_accel_spi_remove,
++ .id_table = st_accel_id_table,
++};
++module_spi_driver(st_accel_driver);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics accelerometers spi driver");
++MODULE_LICENSE("GPL v2");
diff --git a/patches/linux-3.8.13/0458-iio-gyro-Add-STMicroelectronics-gyroscopes-driver.patch b/patches/linux-3.8.13/0458-iio-gyro-Add-STMicroelectronics-gyroscopes-driver.patch
new file mode 100644
index 0000000..a6bee82
--- /dev/null
+++ b/patches/linux-3.8.13/0458-iio-gyro-Add-STMicroelectronics-gyroscopes-driver.patch
@@ -0,0 +1,801 @@
+From: Denis Ciocca <denis.ciocca@gmail.com>
+Date: Fri, 25 Jan 2013 23:44:00 +0000
+Subject: [PATCH] iio:gyro: Add STMicroelectronics gyroscopes driver
+
+This patch adds a generic gyroscope driver for STMicroelectronics
+gyroscopes, currently it supports:
+L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
+
+Signed-off-by: Denis Ciocca <denis.ciocca@st.com>
+Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/gyro/Kconfig | 30 +++
+ drivers/iio/gyro/Makefile | 7 +
+ drivers/iio/gyro/st_gyro.h | 45 +++++
+ drivers/iio/gyro/st_gyro_buffer.c | 114 ++++++++++++
+ drivers/iio/gyro/st_gyro_core.c | 363 +++++++++++++++++++++++++++++++++++++
+ drivers/iio/gyro/st_gyro_i2c.c | 85 +++++++++
+ drivers/iio/gyro/st_gyro_spi.c | 84 +++++++++
+ 7 files changed, 728 insertions(+)
+ create mode 100644 drivers/iio/gyro/st_gyro.h
+ create mode 100644 drivers/iio/gyro/st_gyro_buffer.c
+ create mode 100644 drivers/iio/gyro/st_gyro_core.c
+ create mode 100644 drivers/iio/gyro/st_gyro_i2c.c
+ create mode 100644 drivers/iio/gyro/st_gyro_spi.c
+
+diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
+index 96b68f6..e852a202 100644
+--- a/drivers/iio/gyro/Kconfig
++++ b/drivers/iio/gyro/Kconfig
+@@ -23,4 +23,34 @@ config HID_SENSOR_GYRO_3D
+ Say yes here to build support for the HID SENSOR
+ Gyroscope 3D.
+
++config IIO_ST_GYRO_3AXIS
++ tristate "STMicroelectronics gyroscopes 3-Axis Driver"
++ depends on (I2C || SPI_MASTER) && SYSFS
++ select IIO_ST_SENSORS_CORE
++ select IIO_ST_GYRO_I2C_3AXIS if (I2C)
++ select IIO_ST_GYRO_SPI_3AXIS if (SPI_MASTER)
++ select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
++ select IIO_ST_GYRO_BUFFER if (IIO_TRIGGERED_BUFFER)
++ help
++ Say yes here to build support for STMicroelectronics gyroscopes:
++ L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
++
++ This driver can also be built as a module. If so, will be created
++ these modules:
++ - st_gyro (core functions for the driver [it is mandatory]);
++ - st_gyro_i2c (necessary for the I2C devices [optional*]);
++ - st_gyro_spi (necessary for the SPI devices [optional*]);
++
++ (*) one of these is necessary to do something.
++
++config IIO_ST_GYRO_I2C_3AXIS
++ tristate
++ depends on IIO_ST_GYRO_3AXIS
++ depends on IIO_ST_SENSORS_I2C
++
++config IIO_ST_GYRO_SPI_3AXIS
++ tristate
++ depends on IIO_ST_GYRO_3AXIS
++ depends on IIO_ST_SENSORS_SPI
++
+ endmenu
+diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
+index 702a058..b932f17 100644
+--- a/drivers/iio/gyro/Makefile
++++ b/drivers/iio/gyro/Makefile
+@@ -4,3 +4,10 @@
+
+ obj-$(CONFIG_ADIS16136) += adis16136.o
+ obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
++
++obj-$(CONFIG_IIO_ST_GYRO_3AXIS) += st_gyro.o
++st_gyro-y := st_gyro_core.o
++st_gyro-$(CONFIG_IIO_BUFFER) += st_gyro_buffer.o
++
++obj-$(CONFIG_IIO_ST_GYRO_I2C_3AXIS) += st_gyro_i2c.o
++obj-$(CONFIG_IIO_ST_GYRO_SPI_3AXIS) += st_gyro_spi.o
+diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
+new file mode 100644
+index 0000000..3ad9907
+--- /dev/null
++++ b/drivers/iio/gyro/st_gyro.h
+@@ -0,0 +1,45 @@
++/*
++ * STMicroelectronics gyroscopes driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ * v. 1.0.0
++ * Licensed under the GPL-2.
++ */
++
++#ifndef ST_GYRO_H
++#define ST_GYRO_H
++
++#include <linux/types.h>
++#include <linux/iio/common/st_sensors.h>
++
++#define L3G4200D_GYRO_DEV_NAME "l3g4200d"
++#define LSM330D_GYRO_DEV_NAME "lsm330d_gyro"
++#define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro"
++#define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro"
++#define L3GD20_GYRO_DEV_NAME "l3gd20"
++#define L3GD20H_GYRO_DEV_NAME "l3gd20h"
++#define L3G4IS_GYRO_DEV_NAME "l3g4is_ui"
++#define LSM330_GYRO_DEV_NAME "lsm330_gyro"
++
++int st_gyro_common_probe(struct iio_dev *indio_dev);
++void st_gyro_common_remove(struct iio_dev *indio_dev);
++
++#ifdef CONFIG_IIO_BUFFER
++int st_gyro_allocate_ring(struct iio_dev *indio_dev);
++void st_gyro_deallocate_ring(struct iio_dev *indio_dev);
++int st_gyro_trig_set_state(struct iio_trigger *trig, bool state);
++#define ST_GYRO_TRIGGER_SET_STATE (&st_gyro_trig_set_state)
++#else /* CONFIG_IIO_BUFFER */
++static inline int st_gyro_allocate_ring(struct iio_dev *indio_dev)
++{
++ return 0;
++}
++static inline void st_gyro_deallocate_ring(struct iio_dev *indio_dev)
++{
++}
++#define ST_GYRO_TRIGGER_SET_STATE NULL
++#endif /* CONFIG_IIO_BUFFER */
++
++#endif /* ST_GYRO_H */
+diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c
+new file mode 100644
+index 0000000..da4d122
+--- /dev/null
++++ b/drivers/iio/gyro/st_gyro_buffer.c
+@@ -0,0 +1,114 @@
++/*
++ * STMicroelectronics gyroscopes driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/triggered_buffer.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include "st_gyro.h"
++
++int st_gyro_trig_set_state(struct iio_trigger *trig, bool state)
++{
++ struct iio_dev *indio_dev = trig->private_data;
++
++ return st_sensors_set_dataready_irq(indio_dev, state);
++}
++
++static int st_gyro_buffer_preenable(struct iio_dev *indio_dev)
++{
++ int err;
++
++ err = st_sensors_set_enable(indio_dev, true);
++ if (err < 0)
++ goto st_gyro_set_enable_error;
++
++ err = iio_sw_buffer_preenable(indio_dev);
++
++st_gyro_set_enable_error:
++ return err;
++}
++
++static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *gdata = iio_priv(indio_dev);
++
++ gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
++ if (gdata->buffer_data == NULL) {
++ err = -ENOMEM;
++ goto allocate_memory_error;
++ }
++
++ err = st_sensors_set_axis_enable(indio_dev,
++ (u8)indio_dev->active_scan_mask[0]);
++ if (err < 0)
++ goto st_gyro_buffer_postenable_error;
++
++ err = iio_triggered_buffer_postenable(indio_dev);
++ if (err < 0)
++ goto st_gyro_buffer_postenable_error;
++
++ return err;
++
++st_gyro_buffer_postenable_error:
++ kfree(gdata->buffer_data);
++allocate_memory_error:
++ return err;
++}
++
++static int st_gyro_buffer_predisable(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *gdata = iio_priv(indio_dev);
++
++ err = iio_triggered_buffer_predisable(indio_dev);
++ if (err < 0)
++ goto st_gyro_buffer_predisable_error;
++
++ err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
++ if (err < 0)
++ goto st_gyro_buffer_predisable_error;
++
++ err = st_sensors_set_enable(indio_dev, false);
++
++st_gyro_buffer_predisable_error:
++ kfree(gdata->buffer_data);
++ return err;
++}
++
++static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = {
++ .preenable = &st_gyro_buffer_preenable,
++ .postenable = &st_gyro_buffer_postenable,
++ .predisable = &st_gyro_buffer_predisable,
++};
++
++int st_gyro_allocate_ring(struct iio_dev *indio_dev)
++{
++ return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
++ &st_sensors_trigger_handler, &st_gyro_buffer_setup_ops);
++}
++
++void st_gyro_deallocate_ring(struct iio_dev *indio_dev)
++{
++ iio_triggered_buffer_cleanup(indio_dev);
++}
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics gyroscopes buffer");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
+new file mode 100644
+index 0000000..0a09998
+--- /dev/null
++++ b/drivers/iio/gyro/st_gyro_core.c
+@@ -0,0 +1,363 @@
++/*
++ * STMicroelectronics gyroscopes driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/mutex.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/gpio.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/sysfs.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/buffer.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include "st_gyro.h"
++
++/* DEFAULT VALUE FOR SENSORS */
++#define ST_GYRO_DEFAULT_OUT_X_L_ADDR 0x28
++#define ST_GYRO_DEFAULT_OUT_Y_L_ADDR 0x2a
++#define ST_GYRO_DEFAULT_OUT_Z_L_ADDR 0x2c
++
++/* FULLSCALE */
++#define ST_GYRO_FS_AVL_250DPS 250
++#define ST_GYRO_FS_AVL_500DPS 500
++#define ST_GYRO_FS_AVL_2000DPS 2000
++
++/* CUSTOM VALUES FOR SENSOR 1 */
++#define ST_GYRO_1_WAI_EXP 0xd3
++#define ST_GYRO_1_ODR_ADDR 0x20
++#define ST_GYRO_1_ODR_MASK 0xc0
++#define ST_GYRO_1_ODR_AVL_100HZ_VAL 0x00
++#define ST_GYRO_1_ODR_AVL_200HZ_VAL 0x01
++#define ST_GYRO_1_ODR_AVL_400HZ_VAL 0x02
++#define ST_GYRO_1_ODR_AVL_800HZ_VAL 0x03
++#define ST_GYRO_1_PW_ADDR 0x20
++#define ST_GYRO_1_PW_MASK 0x08
++#define ST_GYRO_1_FS_ADDR 0x23
++#define ST_GYRO_1_FS_MASK 0x30
++#define ST_GYRO_1_FS_AVL_250_VAL 0x00
++#define ST_GYRO_1_FS_AVL_500_VAL 0x01
++#define ST_GYRO_1_FS_AVL_2000_VAL 0x02
++#define ST_GYRO_1_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750)
++#define ST_GYRO_1_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500)
++#define ST_GYRO_1_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000)
++#define ST_GYRO_1_BDU_ADDR 0x23
++#define ST_GYRO_1_BDU_MASK 0x80
++#define ST_GYRO_1_DRDY_IRQ_ADDR 0x22
++#define ST_GYRO_1_DRDY_IRQ_MASK 0x08
++#define ST_GYRO_1_MULTIREAD_BIT true
++
++/* CUSTOM VALUES FOR SENSOR 2 */
++#define ST_GYRO_2_WAI_EXP 0xd4
++#define ST_GYRO_2_ODR_ADDR 0x20
++#define ST_GYRO_2_ODR_MASK 0xc0
++#define ST_GYRO_2_ODR_AVL_95HZ_VAL 0x00
++#define ST_GYRO_2_ODR_AVL_190HZ_VAL 0x01
++#define ST_GYRO_2_ODR_AVL_380HZ_VAL 0x02
++#define ST_GYRO_2_ODR_AVL_760HZ_VAL 0x03
++#define ST_GYRO_2_PW_ADDR 0x20
++#define ST_GYRO_2_PW_MASK 0x08
++#define ST_GYRO_2_FS_ADDR 0x23
++#define ST_GYRO_2_FS_MASK 0x30
++#define ST_GYRO_2_FS_AVL_250_VAL 0x00
++#define ST_GYRO_2_FS_AVL_500_VAL 0x01
++#define ST_GYRO_2_FS_AVL_2000_VAL 0x02
++#define ST_GYRO_2_FS_AVL_250_GAIN IIO_DEGREE_TO_RAD(8750)
++#define ST_GYRO_2_FS_AVL_500_GAIN IIO_DEGREE_TO_RAD(17500)
++#define ST_GYRO_2_FS_AVL_2000_GAIN IIO_DEGREE_TO_RAD(70000)
++#define ST_GYRO_2_BDU_ADDR 0x23
++#define ST_GYRO_2_BDU_MASK 0x80
++#define ST_GYRO_2_DRDY_IRQ_ADDR 0x22
++#define ST_GYRO_2_DRDY_IRQ_MASK 0x08
++#define ST_GYRO_2_MULTIREAD_BIT true
++
++static const struct iio_chan_spec st_gyro_16bit_channels[] = {
++ ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_X,
++ IIO_MOD_X, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
++ ST_GYRO_DEFAULT_OUT_X_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_Y,
++ IIO_MOD_Y, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
++ ST_GYRO_DEFAULT_OUT_Y_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_Z,
++ IIO_MOD_Z, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
++ ST_GYRO_DEFAULT_OUT_Z_L_ADDR),
++ IIO_CHAN_SOFT_TIMESTAMP(3)
++};
++
++static const struct st_sensors st_gyro_sensors[] = {
++ {
++ .wai = ST_GYRO_1_WAI_EXP,
++ .sensors_supported = {
++ [0] = L3G4200D_GYRO_DEV_NAME,
++ [1] = LSM330DL_GYRO_DEV_NAME,
++ },
++ .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
++ .odr = {
++ .addr = ST_GYRO_1_ODR_ADDR,
++ .mask = ST_GYRO_1_ODR_MASK,
++ .odr_avl = {
++ { 100, ST_GYRO_1_ODR_AVL_100HZ_VAL, },
++ { 200, ST_GYRO_1_ODR_AVL_200HZ_VAL, },
++ { 400, ST_GYRO_1_ODR_AVL_400HZ_VAL, },
++ { 800, ST_GYRO_1_ODR_AVL_800HZ_VAL, },
++ },
++ },
++ .pw = {
++ .addr = ST_GYRO_1_PW_ADDR,
++ .mask = ST_GYRO_1_PW_MASK,
++ .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
++ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
++ },
++ .enable_axis = {
++ .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
++ .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
++ },
++ .fs = {
++ .addr = ST_GYRO_1_FS_ADDR,
++ .mask = ST_GYRO_1_FS_MASK,
++ .fs_avl = {
++ [0] = {
++ .num = ST_GYRO_FS_AVL_250DPS,
++ .value = ST_GYRO_1_FS_AVL_250_VAL,
++ .gain = ST_GYRO_1_FS_AVL_250_GAIN,
++ },
++ [1] = {
++ .num = ST_GYRO_FS_AVL_500DPS,
++ .value = ST_GYRO_1_FS_AVL_500_VAL,
++ .gain = ST_GYRO_1_FS_AVL_500_GAIN,
++ },
++ [2] = {
++ .num = ST_GYRO_FS_AVL_2000DPS,
++ .value = ST_GYRO_1_FS_AVL_2000_VAL,
++ .gain = ST_GYRO_1_FS_AVL_2000_GAIN,
++ },
++ },
++ },
++ .bdu = {
++ .addr = ST_GYRO_1_BDU_ADDR,
++ .mask = ST_GYRO_1_BDU_MASK,
++ },
++ .drdy_irq = {
++ .addr = ST_GYRO_1_DRDY_IRQ_ADDR,
++ .mask = ST_GYRO_1_DRDY_IRQ_MASK,
++ },
++ .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
++ .bootime = 2,
++ },
++ {
++ .wai = ST_GYRO_2_WAI_EXP,
++ .sensors_supported = {
++ [0] = L3GD20_GYRO_DEV_NAME,
++ [1] = L3GD20H_GYRO_DEV_NAME,
++ [2] = LSM330D_GYRO_DEV_NAME,
++ [3] = LSM330DLC_GYRO_DEV_NAME,
++ [4] = L3G4IS_GYRO_DEV_NAME,
++ [5] = LSM330_GYRO_DEV_NAME,
++ },
++ .ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
++ .odr = {
++ .addr = ST_GYRO_2_ODR_ADDR,
++ .mask = ST_GYRO_2_ODR_MASK,
++ .odr_avl = {
++ { 95, ST_GYRO_2_ODR_AVL_95HZ_VAL, },
++ { 190, ST_GYRO_2_ODR_AVL_190HZ_VAL, },
++ { 380, ST_GYRO_2_ODR_AVL_380HZ_VAL, },
++ { 760, ST_GYRO_2_ODR_AVL_760HZ_VAL, },
++ },
++ },
++ .pw = {
++ .addr = ST_GYRO_2_PW_ADDR,
++ .mask = ST_GYRO_2_PW_MASK,
++ .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
++ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
++ },
++ .enable_axis = {
++ .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
++ .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
++ },
++ .fs = {
++ .addr = ST_GYRO_2_FS_ADDR,
++ .mask = ST_GYRO_2_FS_MASK,
++ .fs_avl = {
++ [0] = {
++ .num = ST_GYRO_FS_AVL_250DPS,
++ .value = ST_GYRO_2_FS_AVL_250_VAL,
++ .gain = ST_GYRO_2_FS_AVL_250_GAIN,
++ },
++ [1] = {
++ .num = ST_GYRO_FS_AVL_500DPS,
++ .value = ST_GYRO_2_FS_AVL_500_VAL,
++ .gain = ST_GYRO_2_FS_AVL_500_GAIN,
++ },
++ [2] = {
++ .num = ST_GYRO_FS_AVL_2000DPS,
++ .value = ST_GYRO_2_FS_AVL_2000_VAL,
++ .gain = ST_GYRO_2_FS_AVL_2000_GAIN,
++ },
++ },
++ },
++ .bdu = {
++ .addr = ST_GYRO_2_BDU_ADDR,
++ .mask = ST_GYRO_2_BDU_MASK,
++ },
++ .drdy_irq = {
++ .addr = ST_GYRO_2_DRDY_IRQ_ADDR,
++ .mask = ST_GYRO_2_DRDY_IRQ_MASK,
++ },
++ .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
++ .bootime = 2,
++ },
++};
++
++static int st_gyro_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *ch, int *val,
++ int *val2, long mask)
++{
++ int err;
++ struct st_sensor_data *gdata = iio_priv(indio_dev);
++
++ switch (mask) {
++ case IIO_CHAN_INFO_RAW:
++ err = st_sensors_read_info_raw(indio_dev, ch, val);
++ if (err < 0)
++ goto read_error;
++
++ return IIO_VAL_INT;
++ case IIO_CHAN_INFO_SCALE:
++ *val = 0;
++ *val2 = gdata->current_fullscale->gain;
++ return IIO_VAL_INT_PLUS_MICRO;
++ default:
++ return -EINVAL;
++ }
++
++read_error:
++ return err;
++}
++
++static int st_gyro_write_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan, int val, int val2, long mask)
++{
++ int err;
++
++ switch (mask) {
++ case IIO_CHAN_INFO_SCALE:
++ err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
++ break;
++ default:
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
++static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
++static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
++
++static struct attribute *st_gyro_attributes[] = {
++ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
++ &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
++ &iio_dev_attr_sampling_frequency.dev_attr.attr,
++ NULL,
++};
++
++static const struct attribute_group st_gyro_attribute_group = {
++ .attrs = st_gyro_attributes,
++};
++
++static const struct iio_info gyro_info = {
++ .driver_module = THIS_MODULE,
++ .attrs = &st_gyro_attribute_group,
++ .read_raw = &st_gyro_read_raw,
++ .write_raw = &st_gyro_write_raw,
++};
++
++static const struct iio_trigger_ops st_gyro_trigger_ops = {
++ .owner = THIS_MODULE,
++ .set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
++};
++
++int st_gyro_common_probe(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *gdata = iio_priv(indio_dev);
++
++ indio_dev->modes = INDIO_DIRECT_MODE;
++ indio_dev->info = &gyro_info;
++
++ err = st_sensors_check_device_support(indio_dev,
++ ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors);
++ if (err < 0)
++ goto st_gyro_common_probe_error;
++
++ gdata->multiread_bit = gdata->sensor->multi_read_bit;
++ indio_dev->channels = gdata->sensor->ch;
++ indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
++
++ gdata->current_fullscale = (struct st_sensor_fullscale_avl *)
++ &gdata->sensor->fs.fs_avl[0];
++ gdata->odr = gdata->sensor->odr.odr_avl[0].hz;
++
++ err = st_sensors_init_sensor(indio_dev);
++ if (err < 0)
++ goto st_gyro_common_probe_error;
++
++ if (gdata->get_irq_data_ready(indio_dev) > 0) {
++ err = st_gyro_allocate_ring(indio_dev);
++ if (err < 0)
++ goto st_gyro_common_probe_error;
++
++ err = st_sensors_allocate_trigger(indio_dev,
++ &st_gyro_trigger_ops);
++ if (err < 0)
++ goto st_gyro_probe_trigger_error;
++ }
++
++ err = iio_device_register(indio_dev);
++ if (err)
++ goto st_gyro_device_register_error;
++
++ return err;
++
++st_gyro_device_register_error:
++ if (gdata->get_irq_data_ready(indio_dev) > 0)
++ st_sensors_deallocate_trigger(indio_dev);
++st_gyro_probe_trigger_error:
++ if (gdata->get_irq_data_ready(indio_dev) > 0)
++ st_gyro_deallocate_ring(indio_dev);
++st_gyro_common_probe_error:
++ return err;
++}
++EXPORT_SYMBOL(st_gyro_common_probe);
++
++void st_gyro_common_remove(struct iio_dev *indio_dev)
++{
++ struct st_sensor_data *gdata = iio_priv(indio_dev);
++
++ iio_device_unregister(indio_dev);
++ if (gdata->get_irq_data_ready(indio_dev) > 0) {
++ st_sensors_deallocate_trigger(indio_dev);
++ st_gyro_deallocate_ring(indio_dev);
++ }
++ iio_device_free(indio_dev);
++}
++EXPORT_SYMBOL(st_gyro_common_remove);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics gyroscopes driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
+new file mode 100644
+index 0000000..a44b5b4
+--- /dev/null
++++ b/drivers/iio/gyro/st_gyro_i2c.c
+@@ -0,0 +1,85 @@
++/*
++ * STMicroelectronics gyroscopes driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include <linux/iio/common/st_sensors_i2c.h>
++#include "st_gyro.h"
++
++static int st_gyro_i2c_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct iio_dev *indio_dev;
++ struct st_sensor_data *gdata;
++ int err;
++
++ indio_dev = iio_device_alloc(sizeof(*gdata));
++ if (indio_dev == NULL) {
++ err = -ENOMEM;
++ goto iio_device_alloc_error;
++ }
++
++ gdata = iio_priv(indio_dev);
++ gdata->dev = &client->dev;
++
++ st_sensors_i2c_configure(indio_dev, client, gdata);
++
++ err = st_gyro_common_probe(indio_dev);
++ if (err < 0)
++ goto st_gyro_common_probe_error;
++
++ return 0;
++
++st_gyro_common_probe_error:
++ iio_device_free(indio_dev);
++iio_device_alloc_error:
++ return err;
++}
++
++static int st_gyro_i2c_remove(struct i2c_client *client)
++{
++ st_gyro_common_remove(i2c_get_clientdata(client));
++
++ return 0;
++}
++
++static const struct i2c_device_id st_gyro_id_table[] = {
++ { L3G4200D_GYRO_DEV_NAME },
++ { LSM330D_GYRO_DEV_NAME },
++ { LSM330DL_GYRO_DEV_NAME },
++ { LSM330DLC_GYRO_DEV_NAME },
++ { L3GD20_GYRO_DEV_NAME },
++ { L3GD20H_GYRO_DEV_NAME },
++ { L3G4IS_GYRO_DEV_NAME },
++ { LSM330_GYRO_DEV_NAME },
++ {},
++};
++MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
++
++static struct i2c_driver st_gyro_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "st-gyro-i2c",
++ },
++ .probe = st_gyro_i2c_probe,
++ .remove = st_gyro_i2c_remove,
++ .id_table = st_gyro_id_table,
++};
++module_i2c_driver(st_gyro_driver);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics gyroscopes i2c driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
+new file mode 100644
+index 0000000..8b4dcc5
+--- /dev/null
++++ b/drivers/iio/gyro/st_gyro_spi.c
+@@ -0,0 +1,84 @@
++/*
++ * STMicroelectronics gyroscopes driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/spi/spi.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include <linux/iio/common/st_sensors_spi.h>
++#include "st_gyro.h"
++
++static int st_gyro_spi_probe(struct spi_device *spi)
++{
++ struct iio_dev *indio_dev;
++ struct st_sensor_data *gdata;
++ int err;
++
++ indio_dev = iio_device_alloc(sizeof(*gdata));
++ if (indio_dev == NULL) {
++ err = -ENOMEM;
++ goto iio_device_alloc_error;
++ }
++
++ gdata = iio_priv(indio_dev);
++ gdata->dev = &spi->dev;
++
++ st_sensors_spi_configure(indio_dev, spi, gdata);
++
++ err = st_gyro_common_probe(indio_dev);
++ if (err < 0)
++ goto st_gyro_common_probe_error;
++
++ return 0;
++
++st_gyro_common_probe_error:
++ iio_device_free(indio_dev);
++iio_device_alloc_error:
++ return err;
++}
++
++static int st_gyro_spi_remove(struct spi_device *spi)
++{
++ st_gyro_common_remove(spi_get_drvdata(spi));
++
++ return 0;
++}
++
++static const struct spi_device_id st_gyro_id_table[] = {
++ { L3G4200D_GYRO_DEV_NAME },
++ { LSM330D_GYRO_DEV_NAME },
++ { LSM330DL_GYRO_DEV_NAME },
++ { LSM330DLC_GYRO_DEV_NAME },
++ { L3GD20_GYRO_DEV_NAME },
++ { L3GD20H_GYRO_DEV_NAME },
++ { L3G4IS_GYRO_DEV_NAME },
++ { LSM330_GYRO_DEV_NAME },
++ {},
++};
++MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
++
++static struct spi_driver st_gyro_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "st-gyro-spi",
++ },
++ .probe = st_gyro_spi_probe,
++ .remove = st_gyro_spi_remove,
++ .id_table = st_gyro_id_table,
++};
++module_spi_driver(st_gyro_driver);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics gyroscopes spi driver");
++MODULE_LICENSE("GPL v2");
diff --git a/patches/linux-3.8.13/0459-iio-magnetometer-Add-STMicroelectronics-magnetometer.patch b/patches/linux-3.8.13/0459-iio-magnetometer-Add-STMicroelectronics-magnetometer.patch
new file mode 100644
index 0000000..c57d9b2
--- /dev/null
+++ b/patches/linux-3.8.13/0459-iio-magnetometer-Add-STMicroelectronics-magnetometer.patch
@@ -0,0 +1,808 @@
+From: Denis Ciocca <denis.ciocca@gmail.com>
+Date: Fri, 25 Jan 2013 23:44:00 +0000
+Subject: [PATCH] iio:magnetometer: Add STMicroelectronics magnetometers
+ driver
+
+This patch adds a generic magnetometer driver for STMicroelectronics
+magnetometers, currently it supports:
+LSM303DLHC, LSM303DLM, LIS3MDL.
+
+Signed-off-by: Denis Ciocca <denis.ciocca@st.com>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/magnetometer/Kconfig | 30 +++
+ drivers/iio/magnetometer/Makefile | 7 +
+ drivers/iio/magnetometer/st_magn.h | 45 ++++
+ drivers/iio/magnetometer/st_magn_buffer.c | 98 +++++++
+ drivers/iio/magnetometer/st_magn_core.c | 394 +++++++++++++++++++++++++++++
+ drivers/iio/magnetometer/st_magn_i2c.c | 81 ++++++
+ drivers/iio/magnetometer/st_magn_spi.c | 80 ++++++
+ 7 files changed, 735 insertions(+)
+ create mode 100644 drivers/iio/magnetometer/st_magn.h
+ create mode 100644 drivers/iio/magnetometer/st_magn_buffer.c
+ create mode 100644 drivers/iio/magnetometer/st_magn_core.c
+ create mode 100644 drivers/iio/magnetometer/st_magn_i2c.c
+ create mode 100644 drivers/iio/magnetometer/st_magn_spi.c
+
+diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
+index ff11d68..cd29be5 100644
+--- a/drivers/iio/magnetometer/Kconfig
++++ b/drivers/iio/magnetometer/Kconfig
+@@ -14,4 +14,34 @@ config HID_SENSOR_MAGNETOMETER_3D
+ Say yes here to build support for the HID SENSOR
+ Magnetometer 3D.
+
++config IIO_ST_MAGN_3AXIS
++ tristate "STMicroelectronics magnetometers 3-Axis Driver"
++ depends on (I2C || SPI_MASTER) && SYSFS
++ select IIO_ST_SENSORS_CORE
++ select IIO_ST_MAGN_I2C_3AXIS if (I2C)
++ select IIO_ST_MAGN_SPI_3AXIS if (SPI_MASTER)
++ select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
++ select IIO_ST_MAGN_BUFFER if (IIO_TRIGGERED_BUFFER)
++ help
++ Say yes here to build support for STMicroelectronics magnetometers:
++ LSM303DLHC, LSM303DLM, LIS3MDL.
++
++ This driver can also be built as a module. If so, will be created
++ these modules:
++ - st_magn (core functions for the driver [it is mandatory]);
++ - st_magn_i2c (necessary for the I2C devices [optional*]);
++ - st_magn_spi (necessary for the SPI devices [optional*]);
++
++ (*) one of these is necessary to do something.
++
++config IIO_ST_MAGN_I2C_3AXIS
++ tristate
++ depends on IIO_ST_MAGN_3AXIS
++ depends on IIO_ST_SENSORS_I2C
++
++config IIO_ST_MAGN_SPI_3AXIS
++ tristate
++ depends on IIO_ST_MAGN_3AXIS
++ depends on IIO_ST_SENSORS_SPI
++
+ endmenu
+diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
+index 60dc4f2..e786728 100644
+--- a/drivers/iio/magnetometer/Makefile
++++ b/drivers/iio/magnetometer/Makefile
+@@ -3,3 +3,10 @@
+ #
+
+ obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
++
++obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o
++st_magn-y := st_magn_core.o
++st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o
++
++obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o
++obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o
+diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
+new file mode 100644
+index 0000000..7e81d00
+--- /dev/null
++++ b/drivers/iio/magnetometer/st_magn.h
+@@ -0,0 +1,45 @@
++/*
++ * STMicroelectronics magnetometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ * v. 1.0.0
++ * Licensed under the GPL-2.
++ */
++
++#ifndef ST_MAGN_H
++#define ST_MAGN_H
++
++#include <linux/types.h>
++#include <linux/iio/common/st_sensors.h>
++
++#define LSM303DLHC_MAGN_DEV_NAME "lsm303dlhc_magn"
++#define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn"
++#define LIS3MDL_MAGN_DEV_NAME "lis3mdl"
++
++int st_magn_common_probe(struct iio_dev *indio_dev);
++void st_magn_common_remove(struct iio_dev *indio_dev);
++
++#ifdef CONFIG_IIO_BUFFER
++int st_magn_allocate_ring(struct iio_dev *indio_dev);
++void st_magn_deallocate_ring(struct iio_dev *indio_dev);
++#else /* CONFIG_IIO_BUFFER */
++static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
++{
++ return 0;
++}
++static inline void st_magn_remove_trigger(struct iio_dev *indio_dev, int irq)
++{
++ return;
++}
++static inline int st_magn_allocate_ring(struct iio_dev *indio_dev)
++{
++ return 0;
++}
++static inline void st_magn_deallocate_ring(struct iio_dev *indio_dev)
++{
++}
++#endif /* CONFIG_IIO_BUFFER */
++
++#endif /* ST_MAGN_H */
+diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c
+new file mode 100644
+index 0000000..708857b
+--- /dev/null
++++ b/drivers/iio/magnetometer/st_magn_buffer.c
+@@ -0,0 +1,98 @@
++/*
++ * STMicroelectronics magnetometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/triggered_buffer.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include "st_magn.h"
++
++static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
++{
++ int err;
++
++ err = st_sensors_set_enable(indio_dev, true);
++ if (err < 0)
++ goto st_magn_set_enable_error;
++
++ err = iio_sw_buffer_preenable(indio_dev);
++
++st_magn_set_enable_error:
++ return err;
++}
++
++static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *mdata = iio_priv(indio_dev);
++
++ mdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
++ if (mdata->buffer_data == NULL) {
++ err = -ENOMEM;
++ goto allocate_memory_error;
++ }
++
++ err = iio_triggered_buffer_postenable(indio_dev);
++ if (err < 0)
++ goto st_magn_buffer_postenable_error;
++
++ return err;
++
++st_magn_buffer_postenable_error:
++ kfree(mdata->buffer_data);
++allocate_memory_error:
++ return err;
++}
++
++static int st_magn_buffer_predisable(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *mdata = iio_priv(indio_dev);
++
++ err = iio_triggered_buffer_predisable(indio_dev);
++ if (err < 0)
++ goto st_magn_buffer_predisable_error;
++
++ err = st_sensors_set_enable(indio_dev, false);
++
++st_magn_buffer_predisable_error:
++ kfree(mdata->buffer_data);
++ return err;
++}
++
++static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = {
++ .preenable = &st_magn_buffer_preenable,
++ .postenable = &st_magn_buffer_postenable,
++ .predisable = &st_magn_buffer_predisable,
++};
++
++int st_magn_allocate_ring(struct iio_dev *indio_dev)
++{
++ return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
++ &st_sensors_trigger_handler, &st_magn_buffer_setup_ops);
++}
++
++void st_magn_deallocate_ring(struct iio_dev *indio_dev)
++{
++ iio_triggered_buffer_cleanup(indio_dev);
++}
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics magnetometers buffer");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
+new file mode 100644
+index 0000000..1dfcb41
+--- /dev/null
++++ b/drivers/iio/magnetometer/st_magn_core.c
+@@ -0,0 +1,394 @@
++/*
++ * STMicroelectronics magnetometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/mutex.h>
++#include <linux/interrupt.h>
++#include <linux/i2c.h>
++#include <linux/gpio.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/sysfs.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/buffer.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include "st_magn.h"
++
++/* DEFAULT VALUE FOR SENSORS */
++#define ST_MAGN_DEFAULT_OUT_X_L_ADDR 0X04
++#define ST_MAGN_DEFAULT_OUT_Y_L_ADDR 0X08
++#define ST_MAGN_DEFAULT_OUT_Z_L_ADDR 0X06
++
++/* FULLSCALE */
++#define ST_MAGN_FS_AVL_1300MG 1300
++#define ST_MAGN_FS_AVL_1900MG 1900
++#define ST_MAGN_FS_AVL_2500MG 2500
++#define ST_MAGN_FS_AVL_4000MG 4000
++#define ST_MAGN_FS_AVL_4700MG 4700
++#define ST_MAGN_FS_AVL_5600MG 5600
++#define ST_MAGN_FS_AVL_8000MG 8000
++#define ST_MAGN_FS_AVL_8100MG 8100
++#define ST_MAGN_FS_AVL_10000MG 10000
++
++/* CUSTOM VALUES FOR SENSOR 1 */
++#define ST_MAGN_1_WAI_EXP 0x3c
++#define ST_MAGN_1_ODR_ADDR 0x00
++#define ST_MAGN_1_ODR_MASK 0x1c
++#define ST_MAGN_1_ODR_AVL_1HZ_VAL 0x00
++#define ST_MAGN_1_ODR_AVL_2HZ_VAL 0x01
++#define ST_MAGN_1_ODR_AVL_3HZ_VAL 0x02
++#define ST_MAGN_1_ODR_AVL_8HZ_VAL 0x03
++#define ST_MAGN_1_ODR_AVL_15HZ_VAL 0x04
++#define ST_MAGN_1_ODR_AVL_30HZ_VAL 0x05
++#define ST_MAGN_1_ODR_AVL_75HZ_VAL 0x06
++#define ST_MAGN_1_ODR_AVL_220HZ_VAL 0x07
++#define ST_MAGN_1_PW_ADDR 0x02
++#define ST_MAGN_1_PW_MASK 0x03
++#define ST_MAGN_1_PW_ON 0x00
++#define ST_MAGN_1_PW_OFF 0x03
++#define ST_MAGN_1_FS_ADDR 0x01
++#define ST_MAGN_1_FS_MASK 0xe0
++#define ST_MAGN_1_FS_AVL_1300_VAL 0x01
++#define ST_MAGN_1_FS_AVL_1900_VAL 0x02
++#define ST_MAGN_1_FS_AVL_2500_VAL 0x03
++#define ST_MAGN_1_FS_AVL_4000_VAL 0x04
++#define ST_MAGN_1_FS_AVL_4700_VAL 0x05
++#define ST_MAGN_1_FS_AVL_5600_VAL 0x06
++#define ST_MAGN_1_FS_AVL_8100_VAL 0x07
++#define ST_MAGN_1_FS_AVL_1300_GAIN_XY 1100
++#define ST_MAGN_1_FS_AVL_1900_GAIN_XY 855
++#define ST_MAGN_1_FS_AVL_2500_GAIN_XY 670
++#define ST_MAGN_1_FS_AVL_4000_GAIN_XY 450
++#define ST_MAGN_1_FS_AVL_4700_GAIN_XY 400
++#define ST_MAGN_1_FS_AVL_5600_GAIN_XY 330
++#define ST_MAGN_1_FS_AVL_8100_GAIN_XY 230
++#define ST_MAGN_1_FS_AVL_1300_GAIN_Z 980
++#define ST_MAGN_1_FS_AVL_1900_GAIN_Z 760
++#define ST_MAGN_1_FS_AVL_2500_GAIN_Z 600
++#define ST_MAGN_1_FS_AVL_4000_GAIN_Z 400
++#define ST_MAGN_1_FS_AVL_4700_GAIN_Z 355
++#define ST_MAGN_1_FS_AVL_5600_GAIN_Z 295
++#define ST_MAGN_1_FS_AVL_8100_GAIN_Z 205
++#define ST_MAGN_1_MULTIREAD_BIT false
++
++/* CUSTOM VALUES FOR SENSOR 2 */
++#define ST_MAGN_2_WAI_EXP 0x3d
++#define ST_MAGN_2_ODR_ADDR 0x20
++#define ST_MAGN_2_ODR_MASK 0x1c
++#define ST_MAGN_2_ODR_AVL_1HZ_VAL 0x00
++#define ST_MAGN_2_ODR_AVL_2HZ_VAL 0x01
++#define ST_MAGN_2_ODR_AVL_3HZ_VAL 0x02
++#define ST_MAGN_2_ODR_AVL_5HZ_VAL 0x03
++#define ST_MAGN_2_ODR_AVL_10HZ_VAL 0x04
++#define ST_MAGN_2_ODR_AVL_20HZ_VAL 0x05
++#define ST_MAGN_2_ODR_AVL_40HZ_VAL 0x06
++#define ST_MAGN_2_ODR_AVL_80HZ_VAL 0x07
++#define ST_MAGN_2_PW_ADDR 0x22
++#define ST_MAGN_2_PW_MASK 0x03
++#define ST_MAGN_2_PW_ON 0x00
++#define ST_MAGN_2_PW_OFF 0x03
++#define ST_MAGN_2_FS_ADDR 0x21
++#define ST_MAGN_2_FS_MASK 0x60
++#define ST_MAGN_2_FS_AVL_4000_VAL 0x00
++#define ST_MAGN_2_FS_AVL_8000_VAL 0x01
++#define ST_MAGN_2_FS_AVL_10000_VAL 0x02
++#define ST_MAGN_2_FS_AVL_4000_GAIN 430
++#define ST_MAGN_2_FS_AVL_8000_GAIN 230
++#define ST_MAGN_2_FS_AVL_10000_GAIN 230
++#define ST_MAGN_2_MULTIREAD_BIT false
++#define ST_MAGN_2_OUT_X_L_ADDR 0x28
++#define ST_MAGN_2_OUT_Y_L_ADDR 0x2a
++#define ST_MAGN_2_OUT_Z_L_ADDR 0x2c
++
++static const struct iio_chan_spec st_magn_16bit_channels[] = {
++ ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_X_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_Y_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_Z_L_ADDR),
++ IIO_CHAN_SOFT_TIMESTAMP(3)
++};
++
++static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
++ ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_X_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_Y_L_ADDR),
++ ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
++ ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_Z_L_ADDR),
++ IIO_CHAN_SOFT_TIMESTAMP(3)
++};
++
++static const struct st_sensors st_magn_sensors[] = {
++ {
++ .wai = ST_MAGN_1_WAI_EXP,
++ .ch = (struct iio_chan_spec *)st_magn_16bit_channels,
++ .odr = {
++ .addr = ST_MAGN_1_ODR_ADDR,
++ .mask = ST_MAGN_1_ODR_MASK,
++ .odr_avl = {
++ { 1, ST_MAGN_1_ODR_AVL_1HZ_VAL, },
++ { 2, ST_MAGN_1_ODR_AVL_2HZ_VAL, },
++ { 3, ST_MAGN_1_ODR_AVL_3HZ_VAL, },
++ { 8, ST_MAGN_1_ODR_AVL_8HZ_VAL, },
++ { 15, ST_MAGN_1_ODR_AVL_15HZ_VAL, },
++ { 30, ST_MAGN_1_ODR_AVL_30HZ_VAL, },
++ { 75, ST_MAGN_1_ODR_AVL_75HZ_VAL, },
++ { 220, ST_MAGN_1_ODR_AVL_220HZ_VAL, },
++ },
++ },
++ .pw = {
++ .addr = ST_MAGN_1_PW_ADDR,
++ .mask = ST_MAGN_1_PW_MASK,
++ .value_on = ST_MAGN_1_PW_ON,
++ .value_off = ST_MAGN_1_PW_OFF,
++ },
++ .fs = {
++ .addr = ST_MAGN_1_FS_ADDR,
++ .mask = ST_MAGN_1_FS_MASK,
++ .fs_avl = {
++ [0] = {
++ .num = ST_MAGN_FS_AVL_1300MG,
++ .value = ST_MAGN_1_FS_AVL_1300_VAL,
++ .gain = ST_MAGN_1_FS_AVL_1300_GAIN_XY,
++ .gain2 = ST_MAGN_1_FS_AVL_1300_GAIN_Z,
++ },
++ [1] = {
++ .num = ST_MAGN_FS_AVL_1900MG,
++ .value = ST_MAGN_1_FS_AVL_1900_VAL,
++ .gain = ST_MAGN_1_FS_AVL_1900_GAIN_XY,
++ .gain2 = ST_MAGN_1_FS_AVL_1900_GAIN_Z,
++ },
++ [2] = {
++ .num = ST_MAGN_FS_AVL_2500MG,
++ .value = ST_MAGN_1_FS_AVL_2500_VAL,
++ .gain = ST_MAGN_1_FS_AVL_2500_GAIN_XY,
++ .gain2 = ST_MAGN_1_FS_AVL_2500_GAIN_Z,
++ },
++ [3] = {
++ .num = ST_MAGN_FS_AVL_4000MG,
++ .value = ST_MAGN_1_FS_AVL_4000_VAL,
++ .gain = ST_MAGN_1_FS_AVL_4000_GAIN_XY,
++ .gain2 = ST_MAGN_1_FS_AVL_4000_GAIN_Z,
++ },
++ [4] = {
++ .num = ST_MAGN_FS_AVL_4700MG,
++ .value = ST_MAGN_1_FS_AVL_4700_VAL,
++ .gain = ST_MAGN_1_FS_AVL_4700_GAIN_XY,
++ .gain2 = ST_MAGN_1_FS_AVL_4700_GAIN_Z,
++ },
++ [5] = {
++ .num = ST_MAGN_FS_AVL_5600MG,
++ .value = ST_MAGN_1_FS_AVL_5600_VAL,
++ .gain = ST_MAGN_1_FS_AVL_5600_GAIN_XY,
++ .gain2 = ST_MAGN_1_FS_AVL_5600_GAIN_Z,
++ },
++ [6] = {
++ .num = ST_MAGN_FS_AVL_8100MG,
++ .value = ST_MAGN_1_FS_AVL_8100_VAL,
++ .gain = ST_MAGN_1_FS_AVL_8100_GAIN_XY,
++ .gain2 = ST_MAGN_1_FS_AVL_8100_GAIN_Z,
++ },
++ },
++ },
++ .multi_read_bit = ST_MAGN_1_MULTIREAD_BIT,
++ .bootime = 2,
++ },
++ {
++ .wai = ST_MAGN_2_WAI_EXP,
++ .ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,
++ .odr = {
++ .addr = ST_MAGN_2_ODR_ADDR,
++ .mask = ST_MAGN_2_ODR_MASK,
++ .odr_avl = {
++ { 1, ST_MAGN_2_ODR_AVL_1HZ_VAL, },
++ { 2, ST_MAGN_2_ODR_AVL_2HZ_VAL, },
++ { 3, ST_MAGN_2_ODR_AVL_3HZ_VAL, },
++ { 5, ST_MAGN_2_ODR_AVL_5HZ_VAL, },
++ { 10, ST_MAGN_2_ODR_AVL_10HZ_VAL, },
++ { 20, ST_MAGN_2_ODR_AVL_20HZ_VAL, },
++ { 40, ST_MAGN_2_ODR_AVL_40HZ_VAL, },
++ { 80, ST_MAGN_2_ODR_AVL_80HZ_VAL, },
++ },
++ },
++ .pw = {
++ .addr = ST_MAGN_2_PW_ADDR,
++ .mask = ST_MAGN_2_PW_MASK,
++ .value_on = ST_MAGN_2_PW_ON,
++ .value_off = ST_MAGN_2_PW_OFF,
++ },
++ .fs = {
++ .addr = ST_MAGN_2_FS_ADDR,
++ .mask = ST_MAGN_2_FS_MASK,
++ .fs_avl = {
++ [0] = {
++ .num = ST_MAGN_FS_AVL_4000MG,
++ .value = ST_MAGN_2_FS_AVL_4000_VAL,
++ .gain = ST_MAGN_2_FS_AVL_4000_GAIN,
++ },
++ [1] = {
++ .num = ST_MAGN_FS_AVL_8000MG,
++ .value = ST_MAGN_2_FS_AVL_8000_VAL,
++ .gain = ST_MAGN_2_FS_AVL_8000_GAIN,
++ },
++ [2] = {
++ .num = ST_MAGN_FS_AVL_10000MG,
++ .value = ST_MAGN_2_FS_AVL_10000_VAL,
++ .gain = ST_MAGN_2_FS_AVL_10000_GAIN,
++ },
++ },
++ },
++ .multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
++ .bootime = 2,
++ },
++};
++
++static int st_magn_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *ch, int *val,
++ int *val2, long mask)
++{
++ int err;
++ struct st_sensor_data *mdata = iio_priv(indio_dev);
++
++ switch (mask) {
++ case IIO_CHAN_INFO_RAW:
++ err = st_sensors_read_info_raw(indio_dev, ch, val);
++ if (err < 0)
++ goto read_error;
++
++ return IIO_VAL_INT;
++ case IIO_CHAN_INFO_SCALE:
++ *val = 0;
++ if ((ch->scan_index == ST_SENSORS_SCAN_Z) &&
++ (mdata->current_fullscale->gain2 != 0))
++ *val2 = mdata->current_fullscale->gain2;
++ else
++ *val2 = mdata->current_fullscale->gain;
++ return IIO_VAL_INT_PLUS_MICRO;
++ default:
++ return -EINVAL;
++ }
++
++read_error:
++ return err;
++}
++
++static int st_magn_write_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan, int val, int val2, long mask)
++{
++ int err;
++
++ switch (mask) {
++ case IIO_CHAN_INFO_SCALE:
++ err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
++ break;
++ default:
++ err = -EINVAL;
++ }
++
++ return err;
++}
++
++static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
++static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
++static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
++
++static struct attribute *st_magn_attributes[] = {
++ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
++ &iio_dev_attr_in_magn_scale_available.dev_attr.attr,
++ &iio_dev_attr_sampling_frequency.dev_attr.attr,
++ NULL,
++};
++
++static const struct attribute_group st_magn_attribute_group = {
++ .attrs = st_magn_attributes,
++};
++
++static const struct iio_info magn_info = {
++ .driver_module = THIS_MODULE,
++ .attrs = &st_magn_attribute_group,
++ .read_raw = &st_magn_read_raw,
++ .write_raw = &st_magn_write_raw,
++};
++
++int st_magn_common_probe(struct iio_dev *indio_dev)
++{
++ int err;
++ struct st_sensor_data *mdata = iio_priv(indio_dev);
++
++ indio_dev->modes = INDIO_DIRECT_MODE;
++ indio_dev->info = &magn_info;
++
++ err = st_sensors_check_device_support(indio_dev,
++ ARRAY_SIZE(st_magn_sensors), st_magn_sensors);
++ if (err < 0)
++ goto st_magn_common_probe_error;
++
++ mdata->multiread_bit = mdata->sensor->multi_read_bit;
++ indio_dev->channels = mdata->sensor->ch;
++ indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
++
++ mdata->current_fullscale = (struct st_sensor_fullscale_avl *)
++ &mdata->sensor->fs.fs_avl[0];
++ mdata->odr = mdata->sensor->odr.odr_avl[0].hz;
++
++ err = st_sensors_init_sensor(indio_dev);
++ if (err < 0)
++ goto st_magn_common_probe_error;
++
++ if (mdata->get_irq_data_ready(indio_dev) > 0) {
++ err = st_magn_allocate_ring(indio_dev);
++ if (err < 0)
++ goto st_magn_common_probe_error;
++ err = st_sensors_allocate_trigger(indio_dev, NULL);
++ if (err < 0)
++ goto st_magn_probe_trigger_error;
++ }
++
++ err = iio_device_register(indio_dev);
++ if (err)
++ goto st_magn_device_register_error;
++
++ return err;
++
++st_magn_device_register_error:
++ if (mdata->get_irq_data_ready(indio_dev) > 0)
++ st_sensors_deallocate_trigger(indio_dev);
++st_magn_probe_trigger_error:
++ if (mdata->get_irq_data_ready(indio_dev) > 0)
++ st_magn_deallocate_ring(indio_dev);
++st_magn_common_probe_error:
++ return err;
++}
++EXPORT_SYMBOL(st_magn_common_probe);
++
++void st_magn_common_remove(struct iio_dev *indio_dev)
++{
++ struct st_sensor_data *mdata = iio_priv(indio_dev);
++
++ iio_device_unregister(indio_dev);
++ if (mdata->get_irq_data_ready(indio_dev) > 0) {
++ st_sensors_deallocate_trigger(indio_dev);
++ st_magn_deallocate_ring(indio_dev);
++ }
++ iio_device_free(indio_dev);
++}
++EXPORT_SYMBOL(st_magn_common_remove);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics magnetometers driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
+new file mode 100644
+index 0000000..710b256a5
+--- /dev/null
++++ b/drivers/iio/magnetometer/st_magn_i2c.c
+@@ -0,0 +1,81 @@
++/*
++ * STMicroelectronics magnetometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include <linux/iio/common/st_sensors_i2c.h>
++#include "st_magn.h"
++
++static int st_magn_i2c_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct iio_dev *indio_dev;
++ struct st_sensor_data *mdata;
++ int err;
++
++ indio_dev = iio_device_alloc(sizeof(*mdata));
++ if (indio_dev == NULL) {
++ err = -ENOMEM;
++ goto iio_device_alloc_error;
++ }
++
++ mdata = iio_priv(indio_dev);
++ mdata->dev = &client->dev;
++
++ st_sensors_i2c_configure(indio_dev, client, mdata);
++
++ err = st_magn_common_probe(indio_dev);
++ if (err < 0)
++ goto st_magn_common_probe_error;
++
++ return 0;
++
++st_magn_common_probe_error:
++ iio_device_free(indio_dev);
++iio_device_alloc_error:
++ return err;
++}
++
++static int st_magn_i2c_remove(struct i2c_client *client)
++{
++ struct iio_dev *indio_dev = i2c_get_clientdata(client);
++ st_magn_common_remove(indio_dev);
++
++ return 0;
++}
++
++static const struct i2c_device_id st_magn_id_table[] = {
++ { LSM303DLHC_MAGN_DEV_NAME },
++ { LSM303DLM_MAGN_DEV_NAME },
++ { LIS3MDL_MAGN_DEV_NAME },
++ {},
++};
++MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
++
++static struct i2c_driver st_magn_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "st-magn-i2c",
++ },
++ .probe = st_magn_i2c_probe,
++ .remove = st_magn_i2c_remove,
++ .id_table = st_magn_id_table,
++};
++module_i2c_driver(st_magn_driver);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics magnetometers i2c driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
+new file mode 100644
+index 0000000..94547e7
+--- /dev/null
++++ b/drivers/iio/magnetometer/st_magn_spi.c
+@@ -0,0 +1,80 @@
++/*
++ * STMicroelectronics magnetometers driver
++ *
++ * Copyright 2012-2013 STMicroelectronics Inc.
++ *
++ * Denis Ciocca <denis.ciocca@st.com>
++ *
++ * Licensed under the GPL-2.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/spi/spi.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/trigger.h>
++
++#include <linux/iio/common/st_sensors.h>
++#include <linux/iio/common/st_sensors_spi.h>
++#include "st_magn.h"
++
++static int st_magn_spi_probe(struct spi_device *spi)
++{
++ struct iio_dev *indio_dev;
++ struct st_sensor_data *mdata;
++ int err;
++
++ indio_dev = iio_device_alloc(sizeof(*mdata));
++ if (indio_dev == NULL) {
++ err = -ENOMEM;
++ goto iio_device_alloc_error;
++ }
++
++ mdata = iio_priv(indio_dev);
++ mdata->dev = &spi->dev;
++
++ st_sensors_spi_configure(indio_dev, spi, mdata);
++
++ err = st_magn_common_probe(indio_dev);
++ if (err < 0)
++ goto st_magn_common_probe_error;
++
++ return 0;
++
++st_magn_common_probe_error:
++ iio_device_free(indio_dev);
++iio_device_alloc_error:
++ return err;
++}
++
++static int st_magn_spi_remove(struct spi_device *spi)
++{
++ struct iio_dev *indio_dev = spi_get_drvdata(spi);
++ st_magn_common_remove(indio_dev);
++
++ return 0;
++}
++
++static const struct spi_device_id st_magn_id_table[] = {
++ { LSM303DLHC_MAGN_DEV_NAME },
++ { LSM303DLM_MAGN_DEV_NAME },
++ { LIS3MDL_MAGN_DEV_NAME },
++ {},
++};
++MODULE_DEVICE_TABLE(spi, st_magn_id_table);
++
++static struct spi_driver st_magn_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "st-magn-spi",
++ },
++ .probe = st_magn_spi_probe,
++ .remove = st_magn_spi_remove,
++ .id_table = st_magn_id_table,
++};
++module_spi_driver(st_magn_driver);
++
++MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
++MODULE_DESCRIPTION("STMicroelectronics magnetometers spi driver");
++MODULE_LICENSE("GPL v2");
diff --git a/patches/linux-3.8.13/0460-iio-magn-Add-sensors_supported-in-st_magn_sensors.patch b/patches/linux-3.8.13/0460-iio-magn-Add-sensors_supported-in-st_magn_sensors.patch
new file mode 100644
index 0000000..936b0e8
--- /dev/null
+++ b/patches/linux-3.8.13/0460-iio-magn-Add-sensors_supported-in-st_magn_sensors.patch
@@ -0,0 +1,34 @@
+From: Denis Ciocca <denis.ciocca@st.com>
+Date: Tue, 29 Jan 2013 12:27:30 +0100
+Subject: [PATCH] iio:magn: Add sensors_supported in st_magn_sensors
+
+This patch add sensors_supported struct to st_magn_sensors. Without this the probe can't match the WhoAmI and sensor name.
+---
+ drivers/iio/magnetometer/st_magn_core.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
+index 1dfcb41..a69fbe1 100644
+--- a/drivers/iio/magnetometer/st_magn_core.c
++++ b/drivers/iio/magnetometer/st_magn_core.c
+@@ -136,6 +136,10 @@ static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
+ static const struct st_sensors st_magn_sensors[] = {
+ {
+ .wai = ST_MAGN_1_WAI_EXP,
++ .sensors_supported = {
++ [0] = LSM303DLHC_MAGN_DEV_NAME,
++ [1] = LSM303DLM_MAGN_DEV_NAME,
++ },
+ .ch = (struct iio_chan_spec *)st_magn_16bit_channels,
+ .odr = {
+ .addr = ST_MAGN_1_ODR_ADDR,
+@@ -210,6 +214,9 @@ static const struct st_sensors st_magn_sensors[] = {
+ },
+ {
+ .wai = ST_MAGN_2_WAI_EXP,
++ .sensors_supported = {
++ [0] = LIS3MDL_MAGN_DEV_NAME,
++ },
+ .ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,
+ .odr = {
+ .addr = ST_MAGN_2_ODR_ADDR,
diff --git a/patches/linux-3.8.13/0461-pwm-pca9685-skeleton-i2c-client-driver-for-PCA9685-1.patch b/patches/linux-3.8.13/0461-pwm-pca9685-skeleton-i2c-client-driver-for-PCA9685-1.patch
new file mode 100644
index 0000000..52c73fb
--- /dev/null
+++ b/patches/linux-3.8.13/0461-pwm-pca9685-skeleton-i2c-client-driver-for-PCA9685-1.patch
@@ -0,0 +1,223 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 21 Jan 2013 12:47:26 +0100
+Subject: [PATCH] pwm-pca9685: skeleton i2c client driver for PCA9685 16
+ channel PWM driver
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/pwm/Kconfig | 10 +++
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/pwm-pca9685.c | 171 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 182 insertions(+)
+ create mode 100644 drivers/pwm/pwm-pca9685.c
+
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index 6755f2b..3175564 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -97,6 +97,16 @@ config PWM_MXS
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-mxs.
+
++config PWM_PCA9685
++ tristate "NXP PCA9685 PWM support"
++ depends on I2C
++ help
++ Generic PWM framework driver for PCA9685. The PCA9685 has 16
++ PWM controller.
++
++ To compile this driver as a module, choose M here: the module
++ will be called pca-9685.
++
+ config PWM_PUV3
+ tristate "PKUnity NetBook-0916 PWM support"
+ depends on ARCH_PUV3
+diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
+index 8ddb432..92ec413 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -5,6 +5,7 @@ obj-$(CONFIG_PWM_IMX) += pwm-imx.o
+ obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
+ obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
+ obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
++obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
+ obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o
+ obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
+ obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
+diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
+new file mode 100644
+index 0000000..fe504ab
+--- /dev/null
++++ b/drivers/pwm/pwm-pca9685.c
+@@ -0,0 +1,171 @@
++/* drivers/pwm/pwm-pca9685.c
++ *
++ * Copyright (C) 2013 Koen Kooi
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that is will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABLILITY of FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Genernal Public License for more details.
++ *
++ */
++
++
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/pwm.h>
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/i2c.h>
++#include <linux/interrupt.h>
++
++
++#define PCA9685_REG_PSC 0xFE
++#define PCA9685_REG_LED_ON(led) 0x6 + (led >> 2)
++#define PCA9685_REG_LED_OFF(led) 0x7 + (led >> 2)
++
++#define NUM_PWM_CHANNEL 16 /* PCA9685 channels */
++
++struct pca9685_pwm_chip {
++ struct pwm_chip chip;
++ unsigned long period_cycles[NUM_PWM_CHANNEL];
++ enum pwm_polarity polarity[NUM_PWM_CHANNEL];
++};
++
++struct pca9685_device {
++ struct i2c_client *client;
++ /* TODO */
++};
++
++static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
++ int duty_ns, int period_ns)
++{
++ pr_info("PWM config");
++ return 0;
++}
++
++static int pca9685_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
++ enum pwm_polarity polarity)
++{
++ pr_info("PWM set polarity");
++ return 0;
++}
++
++static int pca9685_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ pr_info("PWM enable");
++ return 0;
++}
++
++static void pca9685_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ pr_info("PWM disable");
++}
++
++static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ pr_info("PWM free");
++ if (test_bit(PWMF_ENABLED, &pwm->flags)) {
++ dev_warn(chip->dev, "Removing PWM device without disabling\n");
++ }
++}
++
++static const struct pwm_ops pca9685_pwm_ops = {
++ .free = pca9685_pwm_free,
++ .config = pca9685_pwm_config,
++ .set_polarity = pca9685_pwm_set_polarity,
++ .enable = pca9685_pwm_enable,
++ .disable = pca9685_pwm_disable,
++ .owner = THIS_MODULE,
++};
++
++/* TODO */
++
++static int pca9685_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct pca9685_device *dev;
++ struct pca9685_pwm_chip *pc;
++ int ret;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
++ I2C_FUNC_SMBUS_I2C_BLOCK)) {
++ printk(KERN_ERR "%s: needed i2c functionality is not supported\n", __func__);
++ return -ENODEV;
++ }
++
++ dev = kzalloc(sizeof(struct pca9685_device), GFP_KERNEL);
++ if (dev == NULL) {
++ printk(KERN_ERR "%s: no memory\n", __func__);
++ return -ENOMEM;
++ }
++
++ dev->client = client;
++ i2c_set_clientdata(client, dev);
++
++ pc = kzalloc(sizeof(struct pca9685_pwm_chip), GFP_KERNEL);
++ if (pc == NULL) {
++ printk(KERN_ERR "%s: no memory\n", __func__);
++ return -ENOMEM;
++ }
++
++ pc->chip.dev = &client->dev;
++ pc->chip.ops = &pca9685_pwm_ops;
++ pc->chip.base = -1;
++ pc->chip.npwm = 16;
++
++ ret = pwmchip_add(&pc->chip);
++ if (ret < 0) {
++ pr_err("pwm-pca9685: pwmchip_add() failed: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int pca9685_remove(struct i2c_client *client)
++{
++ struct pca9685_client *dev = i2c_get_clientdata(client);
++
++ /* TODO: do something */
++
++ kfree(dev);
++ return 0;
++}
++
++static const struct i2c_device_id pca9685_id[] = {
++ { "pwm-pca9685", 0 },
++ { }
++};
++
++static struct i2c_driver pca9685_driver = {
++ .probe = pca9685_probe,
++ .remove = pca9685_remove,
++ .id_table = pca9685_id,
++ .driver = {
++ .name = "pca9685",
++ },
++};
++
++static int __init pca9685_init_driver(void)
++{
++ return i2c_add_driver(&pca9685_driver);
++}
++
++static void __exit pca9685_exit_driver(void)
++{
++ i2c_del_driver(&pca9685_driver);
++}
++
++module_init(pca9685_init_driver);
++module_exit(pca9685_exit_driver);
++
++MODULE_AUTHOR("Koen Kooi <koen@dominion.thruhere.net>");
++MODULE_DESCRIPTION("PCA9685 I2C 16 channel PWM driver");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.8.13/0462-Invensense-MPU6050-Device-Driver.patch b/patches/linux-3.8.13/0462-Invensense-MPU6050-Device-Driver.patch
new file mode 100644
index 0000000..d06ad8a
--- /dev/null
+++ b/patches/linux-3.8.13/0462-Invensense-MPU6050-Device-Driver.patch
@@ -0,0 +1,1553 @@
+From: Ge Gao <ggao@invensense.com>
+Date: Sat, 2 Feb 2013 00:26:00 +0000
+Subject: [PATCH] Invensense MPU6050 Device Driver.
+
+This the basic functional Invensense MPU6050 Device driver.
+
+Signed-off-by: Ge Gao <ggao@invensense.com>
+Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+---
+ Documentation/ABI/testing/sysfs-bus-iio-mpu6050 | 13 +
+ drivers/iio/imu/Kconfig | 2 +
+ drivers/iio/imu/Makefile | 2 +
+ drivers/iio/imu/inv_mpu6050/Kconfig | 13 +
+ drivers/iio/imu/inv_mpu6050/Makefile | 6 +
+ drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 795 ++++++++++++++++++++++
+ drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 246 +++++++
+ drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 196 ++++++
+ drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 155 +++++
+ include/linux/platform_data/invensense_mpu6050.h | 31 +
+ 10 files changed, 1459 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-mpu6050
+ create mode 100644 drivers/iio/imu/inv_mpu6050/Kconfig
+ create mode 100644 drivers/iio/imu/inv_mpu6050/Makefile
+ create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+ create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+ create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+ create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+ create mode 100644 include/linux/platform_data/invensense_mpu6050.h
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-iio-mpu6050 b/Documentation/ABI/testing/sysfs-bus-iio-mpu6050
+new file mode 100644
+index 0000000..cb53737
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-iio-mpu6050
+@@ -0,0 +1,13 @@
++What: /sys/bus/iio/devices/iio:deviceX/in_gyro_matrix
++What: /sys/bus/iio/devices/iio:deviceX/in_accel_matrix
++What: /sys/bus/iio/devices/iio:deviceX/in_magn_matrix
++KernelVersion: 3.4.0
++Contact: linux-iio@vger.kernel.org
++Description:
++ This is mounting matrix for motion sensors. Mounting matrix
++ is a 3x3 unitary matrix. A typical mounting matrix would look like
++ [0, 1, 0; 1, 0, 0; 0, 0, -1]. Using this information, it would be
++ easy to tell the relative positions among sensors as well as their
++ positions relative to the board that holds these sensors. Identity matrix
++ [1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and device are perfectly
++ aligned with each other. All axes are exactly the same.
+diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
+index 3d79a40..723563b 100644
+--- a/drivers/iio/imu/Kconfig
++++ b/drivers/iio/imu/Kconfig
+@@ -25,3 +25,5 @@ config IIO_ADIS_LIB_BUFFER
+ help
+ A set of buffer helper functions for the Analog Devices ADIS* device
+ family.
++
++source "drivers/iio/imu/inv_mpu6050/Kconfig"
+diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
+index cfe5763..1b41584 100644
+--- a/drivers/iio/imu/Makefile
++++ b/drivers/iio/imu/Makefile
+@@ -8,3 +8,5 @@ adis_lib-y += adis.o
+ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o
+ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
+ obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
++
++obj-y += inv_mpu6050/
+diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
+new file mode 100644
+index 0000000..b5cfa3a
+--- /dev/null
++++ b/drivers/iio/imu/inv_mpu6050/Kconfig
+@@ -0,0 +1,13 @@
++#
++# inv-mpu6050 drivers for Invensense MPU devices and combos
++#
++
++config INV_MPU6050_IIO
++ tristate "Invensense MPU6050 devices"
++ depends on I2C && SYSFS
++ select IIO_TRIGGERED_BUFFER
++ help
++ This driver supports the Invensense MPU6050 devices.
++ It is a gyroscope/accelerometer combo device.
++ This driver can be built as a module. The module will be called
++ inv-mpu6050.
+diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile
+new file mode 100644
+index 0000000..3a677c7
+--- /dev/null
++++ b/drivers/iio/imu/inv_mpu6050/Makefile
+@@ -0,0 +1,6 @@
++#
++# Makefile for Invensense MPU6050 device.
++#
++
++obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o
++inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o
+diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+new file mode 100644
+index 0000000..37ca05b
+--- /dev/null
++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+@@ -0,0 +1,795 @@
++/*
++* Copyright (C) 2012 Invensense, Inc.
++*
++* This software is licensed under the terms of the GNU General Public
++* License version 2, as published by the Free Software Foundation, and
++* may be copied, distributed, and modified under those terms.
++*
++* This program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*/
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/delay.h>
++#include <linux/sysfs.h>
++#include <linux/jiffies.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/kfifo.h>
++#include <linux/spinlock.h>
++#include "inv_mpu_iio.h"
++
++/*
++ * this is the gyro scale translated from dynamic range plus/minus
++ * {250, 500, 1000, 2000} to rad/s
++ */
++static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724};
++
++/*
++ * this is the accel scale translated from dynamic range plus/minus
++ * {2, 4, 8, 16} to m/s^2
++ */
++static const int accel_scale[] = {598, 1196, 2392, 4785};
++
++static const struct inv_mpu6050_reg_map reg_set_6050 = {
++ .sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV,
++ .lpf = INV_MPU6050_REG_CONFIG,
++ .user_ctrl = INV_MPU6050_REG_USER_CTRL,
++ .fifo_en = INV_MPU6050_REG_FIFO_EN,
++ .gyro_config = INV_MPU6050_REG_GYRO_CONFIG,
++ .accl_config = INV_MPU6050_REG_ACCEL_CONFIG,
++ .fifo_count_h = INV_MPU6050_REG_FIFO_COUNT_H,
++ .fifo_r_w = INV_MPU6050_REG_FIFO_R_W,
++ .raw_gyro = INV_MPU6050_REG_RAW_GYRO,
++ .raw_accl = INV_MPU6050_REG_RAW_ACCEL,
++ .temperature = INV_MPU6050_REG_TEMPERATURE,
++ .int_enable = INV_MPU6050_REG_INT_ENABLE,
++ .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1,
++ .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2,
++};
++
++static const struct inv_mpu6050_chip_config chip_config_6050 = {
++ .fsr = INV_MPU6050_FSR_2000DPS,
++ .lpf = INV_MPU6050_FILTER_20HZ,
++ .fifo_rate = INV_MPU6050_INIT_FIFO_RATE,
++ .gyro_fifo_enable = false,
++ .accl_fifo_enable = false,
++ .accl_fs = INV_MPU6050_FS_02G,
++};
++
++static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = {
++ {
++ .num_reg = 117,
++ .name = "MPU6050",
++ .reg = &reg_set_6050,
++ .config = &chip_config_6050,
++ },
++};
++
++int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d)
++{
++ return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d);
++}
++
++int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
++{
++ u8 d, mgmt_1;
++ int result;
++
++ /* switch clock needs to be careful. Only when gyro is on, can
++ clock source be switched to gyro. Otherwise, it must be set to
++ internal clock */
++ if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
++ result = i2c_smbus_read_i2c_block_data(st->client,
++ st->reg->pwr_mgmt_1, 1, &mgmt_1);
++ if (result != 1)
++ return result;
++
++ mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK;
++ }
++
++ if ((INV_MPU6050_BIT_PWR_GYRO_STBY == mask) && (!en)) {
++ /* turning off gyro requires switch to internal clock first.
++ Then turn off gyro engine */
++ mgmt_1 |= INV_CLK_INTERNAL;
++ result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1);
++ if (result)
++ return result;
++ }
++
++ result = i2c_smbus_read_i2c_block_data(st->client,
++ st->reg->pwr_mgmt_2, 1, &d);
++ if (result != 1)
++ return result;
++ if (en)
++ d &= ~mask;
++ else
++ d |= mask;
++ result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d);
++ if (result)
++ return result;
++
++ if (en) {
++ /* Wait for output stablize */
++ msleep(INV_MPU6050_TEMP_UP_TIME);
++ if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
++ /* switch internal clock to PLL */
++ mgmt_1 |= INV_CLK_PLL;
++ result = inv_mpu6050_write_reg(st,
++ st->reg->pwr_mgmt_1, mgmt_1);
++ if (result)
++ return result;
++ }
++ }
++
++ return 0;
++}
++
++int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
++{
++ int result;
++
++ if (power_on)
++ result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0);
++ else
++ result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
++ INV_MPU6050_BIT_SLEEP);
++ if (result)
++ return result;
++
++ if (power_on)
++ msleep(INV_MPU6050_REG_UP_TIME);
++
++ return 0;
++}
++
++/**
++ * inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
++ *
++ * Initial configuration:
++ * FSR: ± 2000DPS
++ * DLPF: 20Hz
++ * FIFO rate: 50Hz
++ * Clock source: Gyro PLL
++ */
++static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
++{
++ int result;
++ u8 d;
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ result = inv_mpu6050_set_power_itg(st, true);
++ if (result)
++ return result;
++ d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
++ result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
++ if (result)
++ return result;
++
++ d = INV_MPU6050_FILTER_20HZ;
++ result = inv_mpu6050_write_reg(st, st->reg->lpf, d);
++ if (result)
++ return result;
++
++ d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1;
++ result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
++ if (result)
++ return result;
++
++ d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
++ result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
++ if (result)
++ return result;
++
++ memcpy(&st->chip_config, hw_info[st->chip_type].config,
++ sizeof(struct inv_mpu6050_chip_config));
++ result = inv_mpu6050_set_power_itg(st, false);
++
++ return result;
++}
++
++static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg,
++ int axis, int *val)
++{
++ int ind, result;
++ __be16 d;
++
++ ind = (axis - IIO_MOD_X) * 2;
++ result = i2c_smbus_read_i2c_block_data(st->client, reg + ind, 2,
++ (u8 *)&d);
++ if (result != 2)
++ return -EINVAL;
++ *val = (short)be16_to_cpup(&d);
++
++ return IIO_VAL_INT;
++}
++
++static int inv_mpu6050_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan,
++ int *val,
++ int *val2,
++ long mask) {
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ switch (mask) {
++ case IIO_CHAN_INFO_RAW:
++ {
++ int ret, result;
++
++ ret = IIO_VAL_INT;
++ result = 0;
++ mutex_lock(&indio_dev->mlock);
++ if (!st->chip_config.enable) {
++ result = inv_mpu6050_set_power_itg(st, true);
++ if (result)
++ goto error_read_raw;
++ }
++ /* when enable is on, power is already on */
++ switch (chan->type) {
++ case IIO_ANGL_VEL:
++ if (!st->chip_config.gyro_fifo_enable ||
++ !st->chip_config.enable) {
++ result = inv_mpu6050_switch_engine(st, true,
++ INV_MPU6050_BIT_PWR_GYRO_STBY);
++ if (result)
++ goto error_read_raw;
++ }
++ ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
++ chan->channel2, val);
++ if (!st->chip_config.gyro_fifo_enable ||
++ !st->chip_config.enable) {
++ result = inv_mpu6050_switch_engine(st, false,
++ INV_MPU6050_BIT_PWR_GYRO_STBY);
++ if (result)
++ goto error_read_raw;
++ }
++ break;
++ case IIO_ACCEL:
++ if (!st->chip_config.accl_fifo_enable ||
++ !st->chip_config.enable) {
++ result = inv_mpu6050_switch_engine(st, true,
++ INV_MPU6050_BIT_PWR_ACCL_STBY);
++ if (result)
++ goto error_read_raw;
++ }
++ ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
++ chan->channel2, val);
++ if (!st->chip_config.accl_fifo_enable ||
++ !st->chip_config.enable) {
++ result = inv_mpu6050_switch_engine(st, false,
++ INV_MPU6050_BIT_PWR_ACCL_STBY);
++ if (result)
++ goto error_read_raw;
++ }
++ break;
++ case IIO_TEMP:
++ /* wait for stablization */
++ msleep(INV_MPU6050_SENSOR_UP_TIME);
++ inv_mpu6050_sensor_show(st, st->reg->temperature,
++ IIO_MOD_X, val);
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++error_read_raw:
++ if (!st->chip_config.enable)
++ result |= inv_mpu6050_set_power_itg(st, false);
++ mutex_unlock(&indio_dev->mlock);
++ if (result)
++ return result;
++
++ return ret;
++ }
++ case IIO_CHAN_INFO_SCALE:
++ switch (chan->type) {
++ case IIO_ANGL_VEL:
++ *val = 0;
++ *val2 = gyro_scale_6050[st->chip_config.fsr];
++
++ return IIO_VAL_INT_PLUS_NANO;
++ case IIO_ACCEL:
++ *val = 0;
++ *val2 = accel_scale[st->chip_config.accl_fs];
++
++ return IIO_VAL_INT_PLUS_MICRO;
++ case IIO_TEMP:
++ *val = 0;
++ *val2 = INV_MPU6050_TEMP_SCALE;
++
++ return IIO_VAL_INT_PLUS_MICRO;
++ default:
++ return -EINVAL;
++ }
++ case IIO_CHAN_INFO_OFFSET:
++ switch (chan->type) {
++ case IIO_TEMP:
++ *val = INV_MPU6050_TEMP_OFFSET;
++
++ return IIO_VAL_INT;
++ default:
++ return -EINVAL;
++ }
++ default:
++ return -EINVAL;
++ }
++}
++
++static int inv_mpu6050_write_fsr(struct inv_mpu6050_state *st, int fsr)
++{
++ int result;
++ u8 d;
++
++ if (fsr < 0 || fsr > INV_MPU6050_MAX_GYRO_FS_PARAM)
++ return -EINVAL;
++ if (fsr == st->chip_config.fsr)
++ return 0;
++
++ d = (fsr << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
++ result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
++ if (result)
++ return result;
++ st->chip_config.fsr = fsr;
++
++ return 0;
++}
++
++static int inv_mpu6050_write_accel_fs(struct inv_mpu6050_state *st, int fs)
++{
++ int result;
++ u8 d;
++
++ if (fs < 0 || fs > INV_MPU6050_MAX_ACCL_FS_PARAM)
++ return -EINVAL;
++ if (fs == st->chip_config.accl_fs)
++ return 0;
++
++ d = (fs << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
++ result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
++ if (result)
++ return result;
++ st->chip_config.accl_fs = fs;
++
++ return 0;
++}
++
++static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan,
++ int val,
++ int val2,
++ long mask) {
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++ int result;
++
++ mutex_lock(&indio_dev->mlock);
++ /* we should only update scale when the chip is disabled, i.e.,
++ not running */
++ if (st->chip_config.enable) {
++ result = -EBUSY;
++ goto error_write_raw;
++ }
++ result = inv_mpu6050_set_power_itg(st, true);
++ if (result)
++ goto error_write_raw;
++
++ switch (mask) {
++ case IIO_CHAN_INFO_SCALE:
++ switch (chan->type) {
++ case IIO_ANGL_VEL:
++ result = inv_mpu6050_write_fsr(st, val);
++ break;
++ case IIO_ACCEL:
++ result = inv_mpu6050_write_accel_fs(st, val);
++ break;
++ default:
++ result = -EINVAL;
++ break;
++ }
++ break;
++ default:
++ result = -EINVAL;
++ break;
++ }
++
++error_write_raw:
++ result |= inv_mpu6050_set_power_itg(st, false);
++ mutex_unlock(&indio_dev->mlock);
++
++ return result;
++}
++
++/**
++ * inv_mpu6050_set_lpf() - set low pass filer based on fifo rate.
++ *
++ * Based on the Nyquist principle, the sampling rate must
++ * exceed twice of the bandwidth of the signal, or there
++ * would be alising. This function basically search for the
++ * correct low pass parameters based on the fifo rate, e.g,
++ * sampling frequency.
++ */
++static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
++{
++ const int hz[] = {188, 98, 42, 20, 10, 5};
++ const int d[] = {INV_MPU6050_FILTER_188HZ, INV_MPU6050_FILTER_98HZ,
++ INV_MPU6050_FILTER_42HZ, INV_MPU6050_FILTER_20HZ,
++ INV_MPU6050_FILTER_10HZ, INV_MPU6050_FILTER_5HZ};
++ int i, h, result;
++ u8 data;
++
++ h = (rate >> 1);
++ i = 0;
++ while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
++ i++;
++ data = d[i];
++ result = inv_mpu6050_write_reg(st, st->reg->lpf, data);
++ if (result)
++ return result;
++ st->chip_config.lpf = data;
++
++ return 0;
++}
++
++/**
++ * inv_mpu6050_fifo_rate_store() - Set fifo rate.
++ */
++static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ s32 fifo_rate;
++ u8 d;
++ int result;
++ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ if (kstrtoint(buf, 10, &fifo_rate))
++ return -EINVAL;
++ if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE ||
++ fifo_rate > INV_MPU6050_MAX_FIFO_RATE)
++ return -EINVAL;
++ if (fifo_rate == st->chip_config.fifo_rate)
++ return count;
++
++ mutex_lock(&indio_dev->mlock);
++ if (st->chip_config.enable) {
++ result = -EBUSY;
++ goto fifo_rate_fail;
++ }
++ result = inv_mpu6050_set_power_itg(st, true);
++ if (result)
++ goto fifo_rate_fail;
++
++ d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
++ result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
++ if (result)
++ goto fifo_rate_fail;
++ st->chip_config.fifo_rate = fifo_rate;
++
++ result = inv_mpu6050_set_lpf(st, fifo_rate);
++ if (result)
++ goto fifo_rate_fail;
++
++fifo_rate_fail:
++ result |= inv_mpu6050_set_power_itg(st, false);
++ mutex_unlock(&indio_dev->mlock);
++ if (result)
++ return result;
++
++ return count;
++}
++
++/**
++ * inv_fifo_rate_show() - Get the current sampling rate.
++ */
++static ssize_t inv_fifo_rate_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
++
++ return sprintf(buf, "%d\n", st->chip_config.fifo_rate);
++}
++
++/**
++ * inv_attr_show() - calling this function will show current
++ * parameters.
++ */
++static ssize_t inv_attr_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
++ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
++ s8 *m;
++
++ switch (this_attr->address) {
++ /* In MPU6050, the two matrix are the same because gyro and accel
++ are integrated in one chip */
++ case ATTR_GYRO_MATRIX:
++ case ATTR_ACCL_MATRIX:
++ m = st->plat_data.orientation;
++
++ return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n",
++ m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
++ default:
++ return -EINVAL;
++ }
++}
++
++/**
++ * inv_mpu6050_validate_trigger() - validate_trigger callback for invensense
++ * MPU6050 device.
++ * @indio_dev: The IIO device
++ * @trig: The new trigger
++ *
++ * Returns: 0 if the 'trig' matches the trigger registered by the MPU6050
++ * device, -EINVAL otherwise.
++ */
++static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev,
++ struct iio_trigger *trig)
++{
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ if (st->trig != trig)
++ return -EINVAL;
++
++ return 0;
++}
++
++#define INV_MPU6050_CHAN(_type, _channel2, _index) \
++ { \
++ .type = _type, \
++ .modified = 1, \
++ .channel2 = _channel2, \
++ .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT \
++ | IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
++ .scan_index = _index, \
++ .scan_type = { \
++ .sign = 's', \
++ .realbits = 16, \
++ .storagebits = 16, \
++ .shift = 0 , \
++ .endianness = IIO_BE, \
++ }, \
++ }
++
++static const struct iio_chan_spec inv_mpu_channels[] = {
++ IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
++ /*
++ * Note that temperature should only be via polled reading only,
++ * not the final scan elements output.
++ */
++ {
++ .type = IIO_TEMP,
++ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT
++ | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT
++ | IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
++ .scan_index = -1,
++ },
++ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
++ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
++ INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
++
++ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X),
++ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y),
++ INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
++};
++
++/* constant IIO attribute */
++static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500");
++static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show,
++ inv_mpu6050_fifo_rate_store);
++static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL,
++ ATTR_GYRO_MATRIX);
++static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL,
++ ATTR_ACCL_MATRIX);
++
++static struct attribute *inv_attributes[] = {
++ &iio_dev_attr_in_gyro_matrix.dev_attr.attr,
++ &iio_dev_attr_in_accel_matrix.dev_attr.attr,
++ &iio_dev_attr_sampling_frequency.dev_attr.attr,
++ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
++ NULL,
++};
++
++static const struct attribute_group inv_attribute_group = {
++ .attrs = inv_attributes
++};
++
++static const struct iio_info mpu_info = {
++ .driver_module = THIS_MODULE,
++ .read_raw = &inv_mpu6050_read_raw,
++ .write_raw = &inv_mpu6050_write_raw,
++ .attrs = &inv_attribute_group,
++ .validate_trigger = inv_mpu6050_validate_trigger,
++};
++
++/**
++ * inv_check_and_setup_chip() - check and setup chip.
++ */
++static int inv_check_and_setup_chip(struct inv_mpu6050_state *st,
++ const struct i2c_device_id *id)
++{
++ int result;
++
++ st->chip_type = INV_MPU6050;
++ st->hw = &hw_info[st->chip_type];
++ st->reg = hw_info[st->chip_type].reg;
++
++ /* reset to make sure previous state are not there */
++ result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
++ INV_MPU6050_BIT_H_RESET);
++ if (result)
++ return result;
++ msleep(INV_MPU6050_POWER_UP_TIME);
++ /* toggle power state. After reset, the sleep bit could be on
++ or off depending on the OTP settings. Toggling power would
++ make it in a definite state as well as making the hardware
++ state align with the software state */
++ result = inv_mpu6050_set_power_itg(st, false);
++ if (result)
++ return result;
++ result = inv_mpu6050_set_power_itg(st, true);
++ if (result)
++ return result;
++
++ result = inv_mpu6050_switch_engine(st, false,
++ INV_MPU6050_BIT_PWR_ACCL_STBY);
++ if (result)
++ return result;
++ result = inv_mpu6050_switch_engine(st, false,
++ INV_MPU6050_BIT_PWR_GYRO_STBY);
++ if (result)
++ return result;
++
++ return 0;
++}
++
++/**
++ * inv_mpu_probe() - probe function.
++ * @client: i2c client.
++ * @id: i2c device id.
++ *
++ * Returns 0 on success, a negative error code otherwise.
++ */
++static int inv_mpu_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct inv_mpu6050_state *st;
++ struct iio_dev *indio_dev;
++ int result;
++
++ if (!i2c_check_functionality(client->adapter,
++ I2C_FUNC_SMBUS_READ_I2C_BLOCK |
++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
++ result = -ENOSYS;
++ goto out_no_free;
++ }
++ indio_dev = iio_device_alloc(sizeof(*st));
++ if (indio_dev == NULL) {
++ result = -ENOMEM;
++ goto out_no_free;
++ }
++ st = iio_priv(indio_dev);
++ st->client = client;
++ st->plat_data = *(struct inv_mpu6050_platform_data
++ *)dev_get_platdata(&client->dev);
++ /* power is turned on inside check chip type*/
++ result = inv_check_and_setup_chip(st, id);
++ if (result)
++ goto out_free;
++
++ result = inv_mpu6050_init_config(indio_dev);
++ if (result) {
++ dev_err(&client->dev,
++ "Could not initialize device.\n");
++ goto out_free;
++ }
++
++ i2c_set_clientdata(client, indio_dev);
++ indio_dev->dev.parent = &client->dev;
++ indio_dev->name = id->name;
++ indio_dev->channels = inv_mpu_channels;
++ indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
++
++ indio_dev->info = &mpu_info;
++ indio_dev->modes = INDIO_BUFFER_TRIGGERED;
++
++ result = iio_triggered_buffer_setup(indio_dev,
++ inv_mpu6050_irq_handler,
++ inv_mpu6050_read_fifo,
++ NULL);
++ if (result) {
++ dev_err(&st->client->dev, "configure buffer fail %d\n",
++ result);
++ goto out_free;
++ }
++ result = inv_mpu6050_probe_trigger(indio_dev);
++ if (result) {
++ dev_err(&st->client->dev, "trigger probe fail %d\n", result);
++ goto out_unreg_ring;
++ }
++
++ INIT_KFIFO(st->timestamps);
++ spin_lock_init(&st->time_stamp_lock);
++ result = iio_device_register(indio_dev);
++ if (result) {
++ dev_err(&st->client->dev, "IIO register fail %d\n", result);
++ goto out_remove_trigger;
++ }
++
++ return 0;
++
++out_remove_trigger:
++ inv_mpu6050_remove_trigger(st);
++out_unreg_ring:
++ iio_triggered_buffer_cleanup(indio_dev);
++out_free:
++ iio_device_free(indio_dev);
++out_no_free:
++
++ return result;
++}
++
++static int inv_mpu_remove(struct i2c_client *client)
++{
++ struct iio_dev *indio_dev = i2c_get_clientdata(client);
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ iio_device_unregister(indio_dev);
++ inv_mpu6050_remove_trigger(st);
++ iio_triggered_buffer_cleanup(indio_dev);
++ iio_device_free(indio_dev);
++
++ return 0;
++}
++#ifdef CONFIG_PM_SLEEP
++
++static int inv_mpu_resume(struct device *dev)
++{
++ return inv_mpu6050_set_power_itg(
++ iio_priv(i2c_get_clientdata(to_i2c_client(dev))), true);
++}
++
++static int inv_mpu_suspend(struct device *dev)
++{
++ return inv_mpu6050_set_power_itg(
++ iio_priv(i2c_get_clientdata(to_i2c_client(dev))), false);
++}
++static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
++
++#define INV_MPU6050_PMOPS (&inv_mpu_pmops)
++#else
++#define INV_MPU6050_PMOPS NULL
++#endif /* CONFIG_PM_SLEEP */
++
++/*
++ * device id table is used to identify what device can be
++ * supported by this driver
++ */
++static const struct i2c_device_id inv_mpu_id[] = {
++ {"mpu6050", INV_MPU6050},
++ {}
++};
++
++MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
++
++static struct i2c_driver inv_mpu_driver = {
++ .probe = inv_mpu_probe,
++ .remove = inv_mpu_remove,
++ .id_table = inv_mpu_id,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "inv-mpu6050",
++ .pm = INV_MPU6050_PMOPS,
++ },
++};
++
++module_i2c_driver(inv_mpu_driver);
++
++MODULE_AUTHOR("Invensense Corporation");
++MODULE_DESCRIPTION("Invensense device MPU6050 driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+new file mode 100644
+index 0000000..f383955
+--- /dev/null
++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+@@ -0,0 +1,246 @@
++/*
++* Copyright (C) 2012 Invensense, Inc.
++*
++* This software is licensed under the terms of the GNU General Public
++* License version 2, as published by the Free Software Foundation, and
++* may be copied, distributed, and modified under those terms.
++*
++* This program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*/
++#include <linux/i2c.h>
++#include <linux/kfifo.h>
++#include <linux/spinlock.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/sysfs.h>
++#include <linux/iio/kfifo_buf.h>
++#include <linux/iio/trigger.h>
++#include <linux/iio/triggered_buffer.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/platform_data/invensense_mpu6050.h>
++
++/**
++ * struct inv_mpu6050_reg_map - Notable registers.
++ * @sample_rate_div: Divider applied to gyro output rate.
++ * @lpf: Configures internal low pass filter.
++ * @user_ctrl: Enables/resets the FIFO.
++ * @fifo_en: Determines which data will appear in FIFO.
++ * @gyro_config: gyro config register.
++ * @accl_config: accel config register
++ * @fifo_count_h: Upper byte of FIFO count.
++ * @fifo_r_w: FIFO register.
++ * @raw_gyro: Address of first gyro register.
++ * @raw_accl: Address of first accel register.
++ * @temperature: temperature register
++ * @int_enable: Interrupt enable register.
++ * @pwr_mgmt_1: Controls chip's power state and clock source.
++ * @pwr_mgmt_2: Controls power state of individual sensors.
++ */
++struct inv_mpu6050_reg_map {
++ u8 sample_rate_div;
++ u8 lpf;
++ u8 user_ctrl;
++ u8 fifo_en;
++ u8 gyro_config;
++ u8 accl_config;
++ u8 fifo_count_h;
++ u8 fifo_r_w;
++ u8 raw_gyro;
++ u8 raw_accl;
++ u8 temperature;
++ u8 int_enable;
++ u8 pwr_mgmt_1;
++ u8 pwr_mgmt_2;
++};
++
++/*device enum */
++enum inv_devices {
++ INV_MPU6050,
++ INV_NUM_PARTS
++};
++
++/**
++ * struct inv_mpu6050_chip_config - Cached chip configuration data.
++ * @fsr: Full scale range.
++ * @lpf: Digital low pass filter frequency.
++ * @accl_fs: accel full scale range.
++ * @enable: master enable state.
++ * @accl_fifo_enable: enable accel data output
++ * @gyro_fifo_enable: enable gyro data output
++ * @fifo_rate: FIFO update rate.
++ */
++struct inv_mpu6050_chip_config {
++ unsigned int fsr:2;
++ unsigned int lpf:3;
++ unsigned int accl_fs:2;
++ unsigned int enable:1;
++ unsigned int accl_fifo_enable:1;
++ unsigned int gyro_fifo_enable:1;
++ u16 fifo_rate;
++};
++
++/**
++ * struct inv_mpu6050_hw - Other important hardware information.
++ * @num_reg: Number of registers on device.
++ * @name: name of the chip.
++ * @reg: register map of the chip.
++ * @config: configuration of the chip.
++ */
++struct inv_mpu6050_hw {
++ u8 num_reg;
++ u8 *name;
++ const struct inv_mpu6050_reg_map *reg;
++ const struct inv_mpu6050_chip_config *config;
++};
++
++/*
++ * struct inv_mpu6050_state - Driver state variables.
++ * @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
++ * @trig: IIO trigger.
++ * @chip_config: Cached attribute information.
++ * @reg: Map of important registers.
++ * @hw: Other hardware-specific information.
++ * @chip_type: chip type.
++ * @time_stamp_lock: spin lock to time stamp.
++ * @client: i2c client handle.
++ * @plat_data: platform data.
++ * @timestamps: kfifo queue to store time stamp.
++ */
++struct inv_mpu6050_state {
++#define TIMESTAMP_FIFO_SIZE 16
++ struct iio_trigger *trig;
++ struct inv_mpu6050_chip_config chip_config;
++ const struct inv_mpu6050_reg_map *reg;
++ const struct inv_mpu6050_hw *hw;
++ enum inv_devices chip_type;
++ spinlock_t time_stamp_lock;
++ struct i2c_client *client;
++ struct inv_mpu6050_platform_data plat_data;
++ DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
++};
++
++/*register and associated bit definition*/
++#define INV_MPU6050_REG_SAMPLE_RATE_DIV 0x19
++#define INV_MPU6050_REG_CONFIG 0x1A
++#define INV_MPU6050_REG_GYRO_CONFIG 0x1B
++#define INV_MPU6050_REG_ACCEL_CONFIG 0x1C
++
++#define INV_MPU6050_REG_FIFO_EN 0x23
++#define INV_MPU6050_BIT_ACCEL_OUT 0x08
++#define INV_MPU6050_BITS_GYRO_OUT 0x70
++
++#define INV_MPU6050_REG_INT_ENABLE 0x38
++#define INV_MPU6050_BIT_DATA_RDY_EN 0x01
++#define INV_MPU6050_BIT_DMP_INT_EN 0x02
++
++#define INV_MPU6050_REG_RAW_ACCEL 0x3B
++#define INV_MPU6050_REG_TEMPERATURE 0x41
++#define INV_MPU6050_REG_RAW_GYRO 0x43
++
++#define INV_MPU6050_REG_USER_CTRL 0x6A
++#define INV_MPU6050_BIT_FIFO_RST 0x04
++#define INV_MPU6050_BIT_DMP_RST 0x08
++#define INV_MPU6050_BIT_I2C_MST_EN 0x20
++#define INV_MPU6050_BIT_FIFO_EN 0x40
++#define INV_MPU6050_BIT_DMP_EN 0x80
++
++#define INV_MPU6050_REG_PWR_MGMT_1 0x6B
++#define INV_MPU6050_BIT_H_RESET 0x80
++#define INV_MPU6050_BIT_SLEEP 0x40
++#define INV_MPU6050_BIT_CLK_MASK 0x7
++
++#define INV_MPU6050_REG_PWR_MGMT_2 0x6C
++#define INV_MPU6050_BIT_PWR_ACCL_STBY 0x38
++#define INV_MPU6050_BIT_PWR_GYRO_STBY 0x07
++
++#define INV_MPU6050_REG_FIFO_COUNT_H 0x72
++#define INV_MPU6050_REG_FIFO_R_W 0x74
++
++#define INV_MPU6050_BYTES_PER_3AXIS_SENSOR 6
++#define INV_MPU6050_FIFO_COUNT_BYTE 2
++#define INV_MPU6050_FIFO_THRESHOLD 500
++#define INV_MPU6050_POWER_UP_TIME 100
++#define INV_MPU6050_TEMP_UP_TIME 100
++#define INV_MPU6050_SENSOR_UP_TIME 30
++#define INV_MPU6050_REG_UP_TIME 5
++
++#define INV_MPU6050_TEMP_OFFSET 12421
++#define INV_MPU6050_TEMP_SCALE 2941
++#define INV_MPU6050_MAX_GYRO_FS_PARAM 3
++#define INV_MPU6050_MAX_ACCL_FS_PARAM 3
++#define INV_MPU6050_THREE_AXIS 3
++#define INV_MPU6050_GYRO_CONFIG_FSR_SHIFT 3
++#define INV_MPU6050_ACCL_CONFIG_FSR_SHIFT 3
++
++/* 6 + 6 round up and plus 8 */
++#define INV_MPU6050_OUTPUT_DATA_SIZE 24
++
++/* init parameters */
++#define INV_MPU6050_INIT_FIFO_RATE 50
++#define INV_MPU6050_TIME_STAMP_TOR 5
++#define INV_MPU6050_MAX_FIFO_RATE 1000
++#define INV_MPU6050_MIN_FIFO_RATE 4
++#define INV_MPU6050_ONE_K_HZ 1000
++
++/* scan element definition */
++enum inv_mpu6050_scan {
++ INV_MPU6050_SCAN_ACCL_X,
++ INV_MPU6050_SCAN_ACCL_Y,
++ INV_MPU6050_SCAN_ACCL_Z,
++ INV_MPU6050_SCAN_GYRO_X,
++ INV_MPU6050_SCAN_GYRO_Y,
++ INV_MPU6050_SCAN_GYRO_Z,
++ INV_MPU6050_SCAN_TIMESTAMP,
++};
++
++enum inv_mpu6050_filter_e {
++ INV_MPU6050_FILTER_256HZ_NOLPF2 = 0,
++ INV_MPU6050_FILTER_188HZ,
++ INV_MPU6050_FILTER_98HZ,
++ INV_MPU6050_FILTER_42HZ,
++ INV_MPU6050_FILTER_20HZ,
++ INV_MPU6050_FILTER_10HZ,
++ INV_MPU6050_FILTER_5HZ,
++ INV_MPU6050_FILTER_2100HZ_NOLPF,
++ NUM_MPU6050_FILTER
++};
++
++/* IIO attribute address */
++enum INV_MPU6050_IIO_ATTR_ADDR {
++ ATTR_GYRO_MATRIX,
++ ATTR_ACCL_MATRIX,
++};
++
++enum inv_mpu6050_accl_fs_e {
++ INV_MPU6050_FS_02G = 0,
++ INV_MPU6050_FS_04G,
++ INV_MPU6050_FS_08G,
++ INV_MPU6050_FS_16G,
++ NUM_ACCL_FSR
++};
++
++enum inv_mpu6050_fsr_e {
++ INV_MPU6050_FSR_250DPS = 0,
++ INV_MPU6050_FSR_500DPS,
++ INV_MPU6050_FSR_1000DPS,
++ INV_MPU6050_FSR_2000DPS,
++ NUM_MPU6050_FSR
++};
++
++enum inv_mpu6050_clock_sel_e {
++ INV_CLK_INTERNAL = 0,
++ INV_CLK_PLL,
++ NUM_CLK
++};
++
++irqreturn_t inv_mpu6050_irq_handler(int irq, void *p);
++irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
++int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev);
++void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st);
++int inv_reset_fifo(struct iio_dev *indio_dev);
++int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask);
++int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
++int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
+diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+new file mode 100644
+index 0000000..331781f
+--- /dev/null
++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+@@ -0,0 +1,196 @@
++/*
++* Copyright (C) 2012 Invensense, Inc.
++*
++* This software is licensed under the terms of the GNU General Public
++* License version 2, as published by the Free Software Foundation, and
++* may be copied, distributed, and modified under those terms.
++*
++* This program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*/
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/delay.h>
++#include <linux/sysfs.h>
++#include <linux/jiffies.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/kfifo.h>
++#include <linux/poll.h>
++#include "inv_mpu_iio.h"
++
++int inv_reset_fifo(struct iio_dev *indio_dev)
++{
++ int result;
++ u8 d;
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ /* disable interrupt */
++ result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
++ if (result) {
++ dev_err(&st->client->dev, "int_enable failed %d\n", result);
++ return result;
++ }
++ /* disable the sensor output to FIFO */
++ result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
++ if (result)
++ goto reset_fifo_fail;
++ /* disable fifo reading */
++ result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
++ if (result)
++ goto reset_fifo_fail;
++
++ /* reset FIFO*/
++ result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
++ INV_MPU6050_BIT_FIFO_RST);
++ if (result)
++ goto reset_fifo_fail;
++ /* enable interrupt */
++ if (st->chip_config.accl_fifo_enable ||
++ st->chip_config.gyro_fifo_enable) {
++ result = inv_mpu6050_write_reg(st, st->reg->int_enable,
++ INV_MPU6050_BIT_DATA_RDY_EN);
++ if (result)
++ return result;
++ }
++ /* enable FIFO reading and I2C master interface*/
++ result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
++ INV_MPU6050_BIT_FIFO_EN);
++ if (result)
++ goto reset_fifo_fail;
++ /* enable sensor output to FIFO */
++ d = 0;
++ if (st->chip_config.gyro_fifo_enable)
++ d |= INV_MPU6050_BITS_GYRO_OUT;
++ if (st->chip_config.accl_fifo_enable)
++ d |= INV_MPU6050_BIT_ACCEL_OUT;
++ result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d);
++ if (result)
++ goto reset_fifo_fail;
++
++ return 0;
++
++reset_fifo_fail:
++ dev_err(&st->client->dev, "reset fifo failed %d\n", result);
++ result = inv_mpu6050_write_reg(st, st->reg->int_enable,
++ INV_MPU6050_BIT_DATA_RDY_EN);
++
++ return result;
++}
++
++static void inv_clear_kfifo(struct inv_mpu6050_state *st)
++{
++ unsigned long flags;
++
++ /* take the spin lock sem to avoid interrupt kick in */
++ spin_lock_irqsave(&st->time_stamp_lock, flags);
++ kfifo_reset(&st->timestamps);
++ spin_unlock_irqrestore(&st->time_stamp_lock, flags);
++}
++
++/**
++ * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
++ */
++irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
++{
++ struct iio_poll_func *pf = p;
++ struct iio_dev *indio_dev = pf->indio_dev;
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++ s64 timestamp;
++
++ timestamp = iio_get_time_ns();
++ spin_lock(&st->time_stamp_lock);
++ kfifo_in(&st->timestamps, &timestamp, 1);
++ spin_unlock(&st->time_stamp_lock);
++
++ return IRQ_WAKE_THREAD;
++}
++
++/**
++ * inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
++ */
++irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
++{
++ struct iio_poll_func *pf = p;
++ struct iio_dev *indio_dev = pf->indio_dev;
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++ size_t bytes_per_datum;
++ int result;
++ u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
++ u16 fifo_count;
++ s64 timestamp;
++ u64 *tmp;
++
++ mutex_lock(&indio_dev->mlock);
++ if (!(st->chip_config.accl_fifo_enable |
++ st->chip_config.gyro_fifo_enable))
++ goto end_session;
++ bytes_per_datum = 0;
++ if (st->chip_config.accl_fifo_enable)
++ bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
++
++ if (st->chip_config.gyro_fifo_enable)
++ bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
++
++ /*
++ * read fifo_count register to know how many bytes inside FIFO
++ * right now
++ */
++ result = i2c_smbus_read_i2c_block_data(st->client,
++ st->reg->fifo_count_h,
++ INV_MPU6050_FIFO_COUNT_BYTE, data);
++ if (result != INV_MPU6050_FIFO_COUNT_BYTE)
++ goto end_session;
++ fifo_count = be16_to_cpup((__be16 *)(&data[0]));
++ if (fifo_count < bytes_per_datum)
++ goto end_session;
++ /* fifo count can't be odd number, if it is odd, reset fifo*/
++ if (fifo_count & 1)
++ goto flush_fifo;
++ if (fifo_count > INV_MPU6050_FIFO_THRESHOLD)
++ goto flush_fifo;
++ /* Timestamp mismatch. */
++ if (kfifo_len(&st->timestamps) >
++ fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
++ goto flush_fifo;
++ while (fifo_count >= bytes_per_datum) {
++ result = i2c_smbus_read_i2c_block_data(st->client,
++ st->reg->fifo_r_w,
++ bytes_per_datum, data);
++ if (result != bytes_per_datum)
++ goto flush_fifo;
++
++ result = kfifo_out(&st->timestamps, &timestamp, 1);
++ /* when there is no timestamp, put timestamp as 0 */
++ if (0 == result)
++ timestamp = 0;
++
++ tmp = (u64 *)data;
++ tmp[DIV_ROUND_UP(bytes_per_datum, 8)] = timestamp;
++ result = iio_push_to_buffers(indio_dev, data);
++ if (result)
++ goto flush_fifo;
++ fifo_count -= bytes_per_datum;
++ }
++
++end_session:
++ mutex_unlock(&indio_dev->mlock);
++ iio_trigger_notify_done(indio_dev->trig);
++
++ return IRQ_HANDLED;
++
++flush_fifo:
++ /* Flush HW and SW FIFOs. */
++ inv_reset_fifo(indio_dev);
++ inv_clear_kfifo(st);
++ mutex_unlock(&indio_dev->mlock);
++ iio_trigger_notify_done(indio_dev->trig);
++
++ return IRQ_HANDLED;
++}
+diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+new file mode 100644
+index 0000000..e1d0869
+--- /dev/null
++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+@@ -0,0 +1,155 @@
++/*
++* Copyright (C) 2012 Invensense, Inc.
++*
++* This software is licensed under the terms of the GNU General Public
++* License version 2, as published by the Free Software Foundation, and
++* may be copied, distributed, and modified under those terms.
++*
++* This program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*/
++
++#include "inv_mpu_iio.h"
++
++static void inv_scan_query(struct iio_dev *indio_dev)
++{
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ st->chip_config.gyro_fifo_enable =
++ test_bit(INV_MPU6050_SCAN_GYRO_X,
++ indio_dev->active_scan_mask) ||
++ test_bit(INV_MPU6050_SCAN_GYRO_Y,
++ indio_dev->active_scan_mask) ||
++ test_bit(INV_MPU6050_SCAN_GYRO_Z,
++ indio_dev->active_scan_mask);
++
++ st->chip_config.accl_fifo_enable =
++ test_bit(INV_MPU6050_SCAN_ACCL_X,
++ indio_dev->active_scan_mask) ||
++ test_bit(INV_MPU6050_SCAN_ACCL_Y,
++ indio_dev->active_scan_mask) ||
++ test_bit(INV_MPU6050_SCAN_ACCL_Z,
++ indio_dev->active_scan_mask);
++}
++
++/**
++ * inv_mpu6050_set_enable() - enable chip functions.
++ * @indio_dev: Device driver instance.
++ * @enable: enable/disable
++ */
++static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
++{
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++ int result;
++
++ if (enable) {
++ result = inv_mpu6050_set_power_itg(st, true);
++ if (result)
++ return result;
++ inv_scan_query(indio_dev);
++ if (st->chip_config.gyro_fifo_enable) {
++ result = inv_mpu6050_switch_engine(st, true,
++ INV_MPU6050_BIT_PWR_GYRO_STBY);
++ if (result)
++ return result;
++ }
++ if (st->chip_config.accl_fifo_enable) {
++ result = inv_mpu6050_switch_engine(st, true,
++ INV_MPU6050_BIT_PWR_ACCL_STBY);
++ if (result)
++ return result;
++ }
++ result = inv_reset_fifo(indio_dev);
++ if (result)
++ return result;
++ } else {
++ result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
++ if (result)
++ return result;
++
++ result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
++ if (result)
++ return result;
++
++ result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
++ if (result)
++ return result;
++
++ result = inv_mpu6050_switch_engine(st, false,
++ INV_MPU6050_BIT_PWR_GYRO_STBY);
++ if (result)
++ return result;
++
++ result = inv_mpu6050_switch_engine(st, false,
++ INV_MPU6050_BIT_PWR_ACCL_STBY);
++ if (result)
++ return result;
++ result = inv_mpu6050_set_power_itg(st, false);
++ if (result)
++ return result;
++ }
++ st->chip_config.enable = enable;
++
++ return 0;
++}
++
++/**
++ * inv_mpu_data_rdy_trigger_set_state() - set data ready interrupt state
++ * @trig: Trigger instance
++ * @state: Desired trigger state
++ */
++static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
++ bool state)
++{
++ return inv_mpu6050_set_enable(trig->private_data, state);
++}
++
++static const struct iio_trigger_ops inv_mpu_trigger_ops = {
++ .owner = THIS_MODULE,
++ .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state,
++};
++
++int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
++{
++ int ret;
++ struct inv_mpu6050_state *st = iio_priv(indio_dev);
++
++ st->trig = iio_trigger_alloc("%s-dev%d",
++ indio_dev->name,
++ indio_dev->id);
++ if (st->trig == NULL) {
++ ret = -ENOMEM;
++ goto error_ret;
++ }
++ ret = request_irq(st->client->irq, &iio_trigger_generic_data_rdy_poll,
++ IRQF_TRIGGER_RISING,
++ "inv_mpu",
++ st->trig);
++ if (ret)
++ goto error_free_trig;
++ st->trig->dev.parent = &st->client->dev;
++ st->trig->private_data = indio_dev;
++ st->trig->ops = &inv_mpu_trigger_ops;
++ ret = iio_trigger_register(st->trig);
++ if (ret)
++ goto error_free_irq;
++ indio_dev->trig = st->trig;
++
++ return 0;
++
++error_free_irq:
++ free_irq(st->client->irq, st->trig);
++error_free_trig:
++ iio_trigger_free(st->trig);
++error_ret:
++ return ret;
++}
++
++void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st)
++{
++ iio_trigger_unregister(st->trig);
++ free_irq(st->client->irq, st->trig);
++ iio_trigger_free(st->trig);
++}
+diff --git a/include/linux/platform_data/invensense_mpu6050.h b/include/linux/platform_data/invensense_mpu6050.h
+new file mode 100644
+index 0000000..ad3aa7b
+--- /dev/null
++++ b/include/linux/platform_data/invensense_mpu6050.h
+@@ -0,0 +1,31 @@
++/*
++* Copyright (C) 2012 Invensense, Inc.
++*
++* This software is licensed under the terms of the GNU General Public
++* License version 2, as published by the Free Software Foundation, and
++* may be copied, distributed, and modified under those terms.
++*
++* This program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*/
++
++#ifndef __INV_MPU6050_PLATFORM_H_
++#define __INV_MPU6050_PLATFORM_H_
++
++/**
++ * struct inv_mpu6050_platform_data - Platform data for the mpu driver
++ * @orientation: Orientation matrix of the chip
++ *
++ * Contains platform specific information on how to configure the MPU6050 to
++ * work on this platform. The orientation matricies are 3x3 rotation matricies
++ * that are applied to the data to rotate from the mounting orientation to the
++ * platform orientation. The values must be one of 0, 1, or -1 and each row and
++ * column should have exactly 1 non-zero value.
++ */
++struct inv_mpu6050_platform_data {
++ __s8 orientation[9];
++};
++
++#endif
diff --git a/patches/linux-3.8.13/0463-iio-imu-inv_mpu6050-depends-on-IIO_BUFFER.patch b/patches/linux-3.8.13/0463-iio-imu-inv_mpu6050-depends-on-IIO_BUFFER.patch
new file mode 100644
index 0000000..8f9c50e
--- /dev/null
+++ b/patches/linux-3.8.13/0463-iio-imu-inv_mpu6050-depends-on-IIO_BUFFER.patch
@@ -0,0 +1,31 @@
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Fri, 1 Mar 2013 15:21:00 +0000
+Subject: [PATCH] iio/imu: inv_mpu6050 depends on IIO_BUFFER
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Fix:
+
+drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c: In function ‘inv_mpu6050_read_fifo’:
+drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c:176:3: error: implicit declaration of
+function ‘iio_push_to_buffers’ [-Werror=implicit-function-declaration]
+
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/imu/inv_mpu6050/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
+index b5cfa3a..361b232 100644
+--- a/drivers/iio/imu/inv_mpu6050/Kconfig
++++ b/drivers/iio/imu/inv_mpu6050/Kconfig
+@@ -5,6 +5,7 @@
+ config INV_MPU6050_IIO
+ tristate "Invensense MPU6050 devices"
+ depends on I2C && SYSFS
++ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ This driver supports the Invensense MPU6050 devices.
diff --git a/patches/linux-3.8.13/0464-using-kfifo_in_spinlocked-instead-of-separate-code.patch b/patches/linux-3.8.13/0464-using-kfifo_in_spinlocked-instead-of-separate-code.patch
new file mode 100644
index 0000000..c116043
--- /dev/null
+++ b/patches/linux-3.8.13/0464-using-kfifo_in_spinlocked-instead-of-separate-code.patch
@@ -0,0 +1,26 @@
+From: Ge Gao <ggao@invensense.com>
+Date: Mon, 4 Mar 2013 23:27:00 +0000
+Subject: [PATCH] using kfifo_in_spinlocked instead of separate code.
+
+Signed-off-by: Ge Gao <ggao@invensense.com>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+index 331781f..7da0832 100644
+--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+@@ -105,9 +105,8 @@ irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
+ s64 timestamp;
+
+ timestamp = iio_get_time_ns();
+- spin_lock(&st->time_stamp_lock);
+- kfifo_in(&st->timestamps, &timestamp, 1);
+- spin_unlock(&st->time_stamp_lock);
++ kfifo_in_spinlocked(&st->timestamps, &timestamp, 1,
++ &st->time_stamp_lock);
+
+ return IRQ_WAKE_THREAD;
+ }
diff --git a/patches/linux-3.8.13/0465-W1-w1-gpio-switch-to-using-dev_pm_ops.patch b/patches/linux-3.8.13/0465-W1-w1-gpio-switch-to-using-dev_pm_ops.patch
new file mode 100644
index 0000000..b6764be
--- /dev/null
+++ b/patches/linux-3.8.13/0465-W1-w1-gpio-switch-to-using-dev_pm_ops.patch
@@ -0,0 +1,66 @@
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Sun, 24 Feb 2013 22:59:34 -0800
+Subject: [PATCH] W1: w1-gpio - switch to using dev_pm_ops
+
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ drivers/w1/masters/w1-gpio.c | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index 012817a..c45b9ae 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -176,11 +176,10 @@ static int w1_gpio_remove(struct platform_device *pdev)
+ return 0;
+ }
+
+-#ifdef CONFIG_PM
+-
+-static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
++#ifdef CONFIG_PM_SLEEP
++static int w1_gpio_suspend(struct device *dev)
+ {
+- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
++ const struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
+
+ if (pdata->enable_external_pullup)
+ pdata->enable_external_pullup(0);
+@@ -188,31 +187,28 @@ static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
+ return 0;
+ }
+
+-static int w1_gpio_resume(struct platform_device *pdev)
++static int w1_gpio_resume(struct device *dev)
+ {
+- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
++ const struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
+
+ if (pdata->enable_external_pullup)
+ pdata->enable_external_pullup(1);
+
+ return 0;
+ }
+-
+-#else
+-#define w1_gpio_suspend NULL
+-#define w1_gpio_resume NULL
+ #endif
+
++static SIMPLE_DEV_PM_OPS(w1_gpio_pm_ops, w1_gpio_suspend, w1_gpio_resume);
++
+ static struct platform_driver w1_gpio_driver = {
+ .driver = {
+ .name = "w1-gpio",
+ .owner = THIS_MODULE,
++ .pm = &w1_gpio_pm_ops,
+ .of_match_table = of_match_ptr(w1_gpio_dt_ids),
+ },
+ .probe = w1_gpio_probe,
+- .remove = w1_gpio_remove,
+- .suspend = w1_gpio_suspend,
+- .resume = w1_gpio_resume,
++ .remove = w1_gpio_remove,
+ };
+
+ module_platform_driver(w1_gpio_driver);
diff --git a/patches/linux-3.8.13/0466-W1-w1-gpio-guard-DT-IDs-with-CONFIG_OF.patch b/patches/linux-3.8.13/0466-W1-w1-gpio-guard-DT-IDs-with-CONFIG_OF.patch
new file mode 100644
index 0000000..163b0f9
--- /dev/null
+++ b/patches/linux-3.8.13/0466-W1-w1-gpio-guard-DT-IDs-with-CONFIG_OF.patch
@@ -0,0 +1,49 @@
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Sun, 24 Feb 2013 22:59:35 -0800
+Subject: [PATCH] W1: w1-gpio - guard DT IDs with CONFIG_OF
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes the following warning:
+
+ CC drivers/w1/masters/w1-gpio.o
+drivers/w1/masters/w1-gpio.c:50:28: warning: ‘w1_gpio_dt_ids’ defined but not used [-Wunused-variable]
+
+Also provide stub for w1_gpio_probe_dt() if device tree support is
+disabled.
+
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ drivers/w1/masters/w1-gpio.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index c45b9ae..aa97a96 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -47,6 +47,8 @@ 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" },
+ {}
+@@ -72,6 +74,15 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
+ return 0;
+ }
+
++#else
++
++static inline int w1_gpio_probe_dt(struct platform_device *pdev)
++{
++ return -ENOSYS;
++}
++
++#endif
++
+ static int w1_gpio_probe(struct platform_device *pdev)
+ {
+ struct w1_bus_master *master;
diff --git a/patches/linux-3.8.13/0467-W1-w1-gpio-rework-handling-of-platform-data.patch b/patches/linux-3.8.13/0467-W1-w1-gpio-rework-handling-of-platform-data.patch
new file mode 100644
index 0000000..ae6a2bf
--- /dev/null
+++ b/patches/linux-3.8.13/0467-W1-w1-gpio-rework-handling-of-platform-data.patch
@@ -0,0 +1,122 @@
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Sun, 24 Feb 2013 22:59:36 -0800
+Subject: [PATCH] W1: w1-gpio - rework handling of platform data
+
+The platform data in the dveice structure does not belong to the driver
+and so it should not be trying to alter it, but instead use a local pointer
+and populate it with a local copy in case we are dealing with device tree
+setup.
+
+Also allow mixed setups where platform data coexists with device tree and
+prefer kernel-supplied data (it may be easier to fiddle in kernel structure
+before committing final result to device tree).
+
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ drivers/w1/masters/w1-gpio.c | 44 ++++++++++++++++++++++++------------------
+ 1 file changed, 25 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index aa97a96..465ce52 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -55,30 +55,34 @@ static struct of_device_id w1_gpio_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
+
+-static int w1_gpio_probe_dt(struct platform_device *pdev)
++static struct w1_gpio_platform_data *
++w1_gpio_probe_dt(struct platform_device *pdev)
+ {
+- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
++ struct w1_gpio_platform_data *pdata;
+ struct device_node *np = pdev->dev.of_node;
+
++ if (!np)
++ return ERR_PTR(-ENOENT);
++
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+- return -ENOMEM;
++ return ERR_PTR(-ENOMEM);
+
+ if (of_get_property(np, "linux,open-drain", NULL))
+ pdata->is_open_drain = 1;
+
+ pdata->pin = of_get_gpio(np, 0);
+ pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
+- pdev->dev.platform_data = pdata;
+
+- return 0;
++ return pdata;
+ }
+
+ #else
+
+-static inline int w1_gpio_probe_dt(struct platform_device *pdev)
++static inline struct w1_gpio_platform_data *
++w1_gpio_probe_dt(struct platform_device *pdev)
+ {
+- return -ENOSYS;
++ return NULL;
+ }
+
+ #endif
+@@ -94,19 +98,17 @@ static int w1_gpio_probe(struct platform_device *pdev)
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev, "unable to select pin group\n");
+
+- 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;
++ pdata = dev_get_platdata(&pdev->dev);
++ if (!pdata)
++ pdata = w1_gpio_probe_dt(pdev);
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "No configuration data\n");
+ return -ENXIO;
++ } else if (IS_ERR(pdata)) {
++ err = PTR_ERR(pdata);
++ dev_err(&pdev->dev, "Failed to parse DT\n");
++ return err;
+ }
+
+ master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
+@@ -172,7 +174,7 @@ static int w1_gpio_probe(struct platform_device *pdev)
+ static int w1_gpio_remove(struct platform_device *pdev)
+ {
+ struct w1_bus_master *master = platform_get_drvdata(pdev);
+- struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
++ const struct w1_gpio_platform_data *pdata = master->data;
+
+ if (pdata->enable_external_pullup)
+ pdata->enable_external_pullup(0);
+@@ -190,7 +192,9 @@ static int w1_gpio_remove(struct platform_device *pdev)
+ #ifdef CONFIG_PM_SLEEP
+ static int w1_gpio_suspend(struct device *dev)
+ {
+- const struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
++ struct platform_device *pdev = to_platform_device(dev);
++ struct w1_bus_master *master = platform_get_drvdata(pdev);
++ const struct w1_gpio_platform_data *pdata = master->data;
+
+ if (pdata->enable_external_pullup)
+ pdata->enable_external_pullup(0);
+@@ -200,7 +204,9 @@ static int w1_gpio_suspend(struct device *dev)
+
+ static int w1_gpio_resume(struct device *dev)
+ {
+- const struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
++ struct platform_device *pdev = to_platform_device(dev);
++ struct w1_bus_master *master = platform_get_drvdata(pdev);
++ const struct w1_gpio_platform_data *pdata = master->data;
+
+ if (pdata->enable_external_pullup)
+ pdata->enable_external_pullup(1);
diff --git a/patches/linux-3.8.13/0468-W1-w1-gpio-switch-to-using-managed-resources-devm.patch b/patches/linux-3.8.13/0468-W1-w1-gpio-switch-to-using-managed-resources-devm.patch
new file mode 100644
index 0000000..a1402e5
--- /dev/null
+++ b/patches/linux-3.8.13/0468-W1-w1-gpio-switch-to-using-managed-resources-devm.patch
@@ -0,0 +1,86 @@
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Sun, 24 Feb 2013 22:59:37 -0800
+Subject: [PATCH] W1: w1-gpio - switch to using managed resources (devm)
+
+This simplifies error unwinding and device teardown.
+
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+---
+ drivers/w1/masters/w1-gpio.c | 32 +++++++++++---------------------
+ 1 file changed, 11 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index 465ce52..464b1a8e 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -111,25 +111,27 @@ static int w1_gpio_probe(struct platform_device *pdev)
+ return err;
+ }
+
+- master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
++ master = devm_kzalloc(&pdev->dev,
++ sizeof(struct w1_bus_master), GFP_KERNEL);
+ if (!master) {
+ dev_err(&pdev->dev, "Out of memory\n");
+ return -ENOMEM;
+ }
+
+- err = gpio_request(pdata->pin, "w1");
++ err = devm_gpio_request(&pdev->dev, pdata->pin, "w1");
+ if (err) {
+ dev_err(&pdev->dev, "gpio_request (pin) failed\n");
+- goto free_master;
++ return err;
+ }
+
+ if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
+- err = gpio_request_one(pdata->ext_pullup_enable_pin,
+- GPIOF_INIT_LOW, "w1 pullup");
++ err = devm_gpio_request_one(&pdev->dev,
++ pdata->ext_pullup_enable_pin,
++ GPIOF_INIT_LOW, "w1 pullup");
+ if (err < 0) {
+- dev_err(&pdev->dev, "gpio_request_one "
+- "(ext_pullup_enable_pin) failed\n");
+- goto free_gpio;
++ dev_err(&pdev->dev,
++ "gpio_request_one (ext_pullup_enable_pin) failed\n");
++ return err;
+ }
+ }
+
+@@ -147,7 +149,7 @@ static int w1_gpio_probe(struct platform_device *pdev)
+ err = w1_add_master_device(master);
+ if (err) {
+ dev_err(&pdev->dev, "w1_add_master device failed\n");
+- goto free_gpio_ext_pu;
++ return err;
+ }
+
+ if (pdata->enable_external_pullup)
+@@ -159,16 +161,6 @@ static int w1_gpio_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, master);
+
+ return 0;
+-
+- free_gpio_ext_pu:
+- if (gpio_is_valid(pdata->ext_pullup_enable_pin))
+- gpio_free(pdata->ext_pullup_enable_pin);
+- free_gpio:
+- gpio_free(pdata->pin);
+- free_master:
+- kfree(master);
+-
+- return err;
+ }
+
+ static int w1_gpio_remove(struct platform_device *pdev)
+@@ -183,8 +175,6 @@ static int w1_gpio_remove(struct platform_device *pdev)
+ gpio_set_value(pdata->ext_pullup_enable_pin, 0);
+
+ w1_remove_master_device(master);
+- gpio_free(pdata->pin);
+- kfree(master);
+
+ return 0;
+ }
diff --git a/patches/linux-3.8.13/0469-ARM-OMAP-Clear-GPMC-bits-when-applying-new-setting.patch b/patches/linux-3.8.13/0469-ARM-OMAP-Clear-GPMC-bits-when-applying-new-setting.patch
new file mode 100644
index 0000000..787baed
--- /dev/null
+++ b/patches/linux-3.8.13/0469-ARM-OMAP-Clear-GPMC-bits-when-applying-new-setting.patch
@@ -0,0 +1,54 @@
+From: Mark Jackson <mpfj-list@mimc.co.uk>
+Date: Tue, 5 Mar 2013 10:13:40 +0000
+Subject: [PATCH] ARM: OMAP: Clear GPMC bits when applying new setting.
+
+When setting the GPMC device type, make sure any previous
+bits are cleared down, before applying the new setting.
+
+For OMAP4+ devices MUXADDDATA is a 2-bit field (bits 9:8)
+where as for OMAP2/3 devices it was only a one bit field
+(bit 9). For OMAP2/3 devices bit 8 is reserved and the
+OMAP documentation says to write a 0 to this bit. So
+clearing bit 8 on OMAP2/3 devices should not be a problem.
+Hence update the code to handle both bits 8 and 9 for all
+devices.
+
+Signed-off-by: Mark Jackson <mpfj@newflow.co.uk>
+[jon-hunter@ti.com: updated changelog]
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 4 ++++
+ arch/arm/mach-omap2/gpmc.h | 5 ++++-
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 8033cb7..f4219c1 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -606,6 +606,10 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
+
+ case GPMC_CONFIG_DEV_TYPE:
+ regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
++ /* clear 4 target bits */
++ regval &= ~(GPMC_CONFIG1_DEVICETYPE(3) |
++ GPMC_CONFIG1_MUXTYPE(3));
++ /* set the proper value */
+ regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+ if (wval == GPMC_DEVICETYPE_NOR)
+ regval |= GPMC_CONFIG1_MUXADDDATA;
+diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
+index fe0a844..f79cbde 100644
+--- a/arch/arm/mach-omap2/gpmc.h
++++ b/arch/arm/mach-omap2/gpmc.h
+@@ -58,7 +58,10 @@
+ #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1)
+ #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
+ #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
+-#define GPMC_CONFIG1_MUXADDDATA (1 << 9)
++#define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8)
++#define GPMC_CONFIG1_MUXNONMUX GPMC_CONFIG1_MUXTYPE(0)
++#define GPMC_CONFIG1_MUXAAD GPMC_CONFIG1_MUXTYPE(1)
++#define GPMC_CONFIG1_MUXADDDATA GPMC_CONFIG1_MUXTYPE(2)
+ #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
+ #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
+ #define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1))
diff --git a/patches/linux-3.8.13/0470-ARM-omap2-gpmc-Mark-local-scoped-functions-static.patch b/patches/linux-3.8.13/0470-ARM-omap2-gpmc-Mark-local-scoped-functions-static.patch
new file mode 100644
index 0000000..cc0edf7
--- /dev/null
+++ b/patches/linux-3.8.13/0470-ARM-omap2-gpmc-Mark-local-scoped-functions-static.patch
@@ -0,0 +1,107 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:17 -0300
+Subject: [PATCH] ARM: omap2: gpmc: Mark local scoped functions static
+
+This patch marks a bunch of functions that are local
+to gpmc.c file only as static.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 14 +++++++-------
+ arch/arm/mach-omap2/gpmc.h | 7 -------
+ 2 files changed, 7 insertions(+), 14 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index f4219c1..20de0f6 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -174,7 +174,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
+ __raw_writel(val, reg_addr);
+ }
+
+-u32 gpmc_cs_read_reg(int cs, int idx)
++static u32 gpmc_cs_read_reg(int cs, int idx)
+ {
+ void __iomem *reg_addr;
+
+@@ -183,7 +183,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
+ }
+
+ /* TODO: Add support for gpmc_fck to clock framework and use it */
+-unsigned long gpmc_get_fclk_period(void)
++static unsigned long gpmc_get_fclk_period(void)
+ {
+ unsigned long rate = clk_get_rate(gpmc_l3_clk);
+
+@@ -198,7 +198,7 @@ unsigned long gpmc_get_fclk_period(void)
+ return rate;
+ }
+
+-unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
++static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+ {
+ unsigned long tick_ps;
+
+@@ -208,7 +208,7 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+ return (time_ns * 1000 + tick_ps - 1) / tick_ps;
+ }
+
+-unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
++static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
+ {
+ unsigned long tick_ps;
+
+@@ -223,7 +223,7 @@ unsigned int gpmc_ticks_to_ns(unsigned int ticks)
+ return ticks * gpmc_get_fclk_period() / 1000;
+ }
+
+-unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
++static unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
+ {
+ unsigned long ticks = gpmc_ns_to_ticks(time_ns);
+
+@@ -441,7 +441,7 @@ static int gpmc_cs_mem_enabled(int cs)
+ return l & GPMC_CONFIG7_CSVALID;
+ }
+
+-int gpmc_cs_set_reserved(int cs, int reserved)
++static int gpmc_cs_set_reserved(int cs, int reserved)
+ {
+ if (cs > GPMC_CS_NUM)
+ return -ENODEV;
+@@ -452,7 +452,7 @@ int gpmc_cs_set_reserved(int cs, int reserved)
+ return 0;
+ }
+
+-int gpmc_cs_reserved(int cs)
++static int gpmc_cs_reserved(int cs)
+ {
+ if (cs > GPMC_CS_NUM)
+ return -ENODEV;
+diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
+index f79cbde..697ff42 100644
+--- a/arch/arm/mach-omap2/gpmc.h
++++ b/arch/arm/mach-omap2/gpmc.h
+@@ -198,20 +198,13 @@ extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+ extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+ extern int gpmc_get_client_irq(unsigned irq_config);
+
+-extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
+-extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
+ extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
+-extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
+-extern unsigned long gpmc_get_fclk_period(void);
+
+ extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
+-extern u32 gpmc_cs_read_reg(int cs, int idx);
+ extern int gpmc_calc_divider(unsigned int sync_clk);
+ extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
+ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+ extern void gpmc_cs_free(int cs);
+-extern int gpmc_cs_set_reserved(int cs, int reserved);
+-extern int gpmc_cs_reserved(int cs);
+ extern void omap3_gpmc_save_context(void);
+ extern void omap3_gpmc_restore_context(void);
+ extern int gpmc_cs_configure(int cs, int cmd, int wval);
diff --git a/patches/linux-3.8.13/0471-ARM-omap2-gpmc-Remove-unused-gpmc_round_ns_to_ticks-.patch b/patches/linux-3.8.13/0471-ARM-omap2-gpmc-Remove-unused-gpmc_round_ns_to_ticks-.patch
new file mode 100644
index 0000000..38442ce
--- /dev/null
+++ b/patches/linux-3.8.13/0471-ARM-omap2-gpmc-Remove-unused-gpmc_round_ns_to_ticks-.patch
@@ -0,0 +1,33 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:18 -0300
+Subject: [PATCH] ARM: omap2: gpmc: Remove unused gpmc_round_ns_to_ticks()
+ function
+
+This function is not used anywhere, so it's safe to remove it.
+This means less code to maintain.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 20de0f6..d7add37 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -223,13 +223,6 @@ unsigned int gpmc_ticks_to_ns(unsigned int ticks)
+ return ticks * gpmc_get_fclk_period() / 1000;
+ }
+
+-static unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
+-{
+- unsigned long ticks = gpmc_ns_to_ticks(time_ns);
+-
+- return ticks * gpmc_get_fclk_period() / 1000;
+-}
+-
+ static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
+ {
+ return ticks * gpmc_get_fclk_period();
diff --git a/patches/linux-3.8.13/0472-ARM-omap2-gpmc-Fix-gpmc_cs_reserved-return-value.patch b/patches/linux-3.8.13/0472-ARM-omap2-gpmc-Fix-gpmc_cs_reserved-return-value.patch
new file mode 100644
index 0000000..1f76f42
--- /dev/null
+++ b/patches/linux-3.8.13/0472-ARM-omap2-gpmc-Fix-gpmc_cs_reserved-return-value.patch
@@ -0,0 +1,37 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:19 -0300
+Subject: [PATCH] ARM: omap2: gpmc: Fix gpmc_cs_reserved() return value
+
+Currently gpmc_cs_reserved() return value is somewhat inconsistent,
+returning a negative value on an error condition, a positive value
+if the chip select is reserved and zero if it's available.
+
+Fix this by returning a boolean value as the function name suggests:
+ * true if the chip select is reserved,
+ * false if it's available
+
+Suggested-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index d7add37..83430a2 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -445,10 +445,10 @@ static int gpmc_cs_set_reserved(int cs, int reserved)
+ return 0;
+ }
+
+-static int gpmc_cs_reserved(int cs)
++static bool gpmc_cs_reserved(int cs)
+ {
+ if (cs > GPMC_CS_NUM)
+- return -ENODEV;
++ return true;
+
+ return gpmc_cs_map & (1 << cs);
+ }
diff --git a/patches/linux-3.8.13/0473-ARM-omap2-gpmc-nand-Print-something-useful-on-CS-req.patch b/patches/linux-3.8.13/0473-ARM-omap2-gpmc-nand-Print-something-useful-on-CS-req.patch
new file mode 100644
index 0000000..baf04bb
--- /dev/null
+++ b/patches/linux-3.8.13/0473-ARM-omap2-gpmc-nand-Print-something-useful-on-CS-req.patch
@@ -0,0 +1,29 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:20 -0300
+Subject: [PATCH] ARM: omap2: gpmc-nand: Print something useful on CS request
+ failure
+
+If CS request fails the current error message is rather unhelpful.
+Fix it by printing the failing chip select and the error code.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc-nand.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
+index db969a5..6027dd0 100644
+--- a/arch/arm/mach-omap2/gpmc-nand.c
++++ b/arch/arm/mach-omap2/gpmc-nand.c
+@@ -121,7 +121,8 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+ err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
+ (unsigned long *)&gpmc_nand_resource[0].start);
+ if (err < 0) {
+- dev_err(dev, "Cannot request GPMC CS\n");
++ dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
++ gpmc_nand_data->cs, err);
+ return err;
+ }
+
diff --git a/patches/linux-3.8.13/0474-ARM-omap2-gpmc-onenand-Print-something-useful-on-CS-.patch b/patches/linux-3.8.13/0474-ARM-omap2-gpmc-onenand-Print-something-useful-on-CS-.patch
new file mode 100644
index 0000000..8d3e9fd
--- /dev/null
+++ b/patches/linux-3.8.13/0474-ARM-omap2-gpmc-onenand-Print-something-useful-on-CS-.patch
@@ -0,0 +1,29 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:21 -0300
+Subject: [PATCH] ARM: omap2: gpmc-onenand: Print something useful on CS
+ request failure
+
+If CS request fails the current error message is rather unhelpful.
+Fix it by printing the failing chip select and the error code.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index 94a349e..80d756b 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -379,7 +379,8 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+ err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
+ (unsigned long *)&gpmc_onenand_resource.start);
+ if (err < 0) {
+- pr_err("%s: Cannot request GPMC CS\n", __func__);
++ pr_err("%s: Cannot request GPMC CS %d, error %d\n",
++ __func__, gpmc_onenand_data->cs, err);
+ return;
+ }
+
diff --git a/patches/linux-3.8.13/0475-ARM-omap2-gpmc-onenand-Replace-pr_err-with-dev_err.patch b/patches/linux-3.8.13/0475-ARM-omap2-gpmc-onenand-Replace-pr_err-with-dev_err.patch
new file mode 100644
index 0000000..16d53c4
--- /dev/null
+++ b/patches/linux-3.8.13/0475-ARM-omap2-gpmc-onenand-Replace-pr_err-with-dev_err.patch
@@ -0,0 +1,46 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:22 -0300
+Subject: [PATCH] ARM: omap2: gpmc-onenand: Replace pr_err() with dev_err()
+
+Do this becasue dev_err() is preferred over pr_err() and because
+it will match gpmc-nand, thus the code shows looks more consistent.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index 80d756b..e1daf94 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -359,6 +359,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
+ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+ {
+ int err;
++ struct device *dev = &gpmc_onenand_device.dev;
+
+ gpmc_onenand_data = _onenand_data;
+ gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
+@@ -379,8 +380,8 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+ err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
+ (unsigned long *)&gpmc_onenand_resource.start);
+ if (err < 0) {
+- pr_err("%s: Cannot request GPMC CS %d, error %d\n",
+- __func__, gpmc_onenand_data->cs, err);
++ dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
++ gpmc_onenand_data->cs, err);
+ return;
+ }
+
+@@ -388,7 +389,7 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+ ONENAND_IO_SIZE - 1;
+
+ if (platform_device_register(&gpmc_onenand_device) < 0) {
+- pr_err("%s: Unable to register OneNAND device\n", __func__);
++ dev_err(dev, "Unable to register OneNAND device\n");
+ gpmc_cs_free(gpmc_onenand_data->cs);
+ return;
+ }
diff --git a/patches/linux-3.8.13/0476-ARM-omap2-gpmc-onenand-Replace-printk-KERN_ERR-with-.patch b/patches/linux-3.8.13/0476-ARM-omap2-gpmc-onenand-Replace-printk-KERN_ERR-with-.patch
new file mode 100644
index 0000000..e84991e
--- /dev/null
+++ b/patches/linux-3.8.13/0476-ARM-omap2-gpmc-onenand-Replace-printk-KERN_ERR-with-.patch
@@ -0,0 +1,28 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:23 -0300
+Subject: [PATCH] ARM: omap2: gpmc-onenand: Replace printk KERN_ERR with
+ dev_warn()
+
+Since the condition is not an error but a warning, replace
+printk KERN_ERR with dev_warn.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index e1daf94..428cb19 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -367,7 +367,7 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+
+ if (cpu_is_omap24xx() &&
+ (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
+- printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
++ dev_warn(dev, "OneNAND using only SYNC_READ on 24xx\n");
+ gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
+ gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
+ }
diff --git a/patches/linux-3.8.13/0477-ARM-omap2-gpmc-Remove-redundant-chip-select-out-of-r.patch b/patches/linux-3.8.13/0477-ARM-omap2-gpmc-Remove-redundant-chip-select-out-of-r.patch
new file mode 100644
index 0000000..bc5d614
--- /dev/null
+++ b/patches/linux-3.8.13/0477-ARM-omap2-gpmc-Remove-redundant-chip-select-out-of-r.patch
@@ -0,0 +1,44 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 12 Feb 2013 16:22:24 -0300
+Subject: [PATCH] ARM: omap2: gpmc: Remove redundant chip select out of range
+ check
+
+This check is done before the call to gpmc_cs_reserved() and
+gpmc_cs_set_reserved() and it's redundant to do it again in each
+function. This simplifies the code a bit.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 83430a2..901dacd 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -434,22 +434,14 @@ static int gpmc_cs_mem_enabled(int cs)
+ return l & GPMC_CONFIG7_CSVALID;
+ }
+
+-static int gpmc_cs_set_reserved(int cs, int reserved)
++static void gpmc_cs_set_reserved(int cs, int reserved)
+ {
+- if (cs > GPMC_CS_NUM)
+- return -ENODEV;
+-
+ gpmc_cs_map &= ~(1 << cs);
+ gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+-
+- return 0;
+ }
+
+ static bool gpmc_cs_reserved(int cs)
+ {
+- if (cs > GPMC_CS_NUM)
+- return true;
+-
+ return gpmc_cs_map & (1 << cs);
+ }
+
diff --git a/patches/linux-3.8.13/0478-ARM-OMAP2-Simplify-code-configuring-ONENAND-devices.patch b/patches/linux-3.8.13/0478-ARM-OMAP2-Simplify-code-configuring-ONENAND-devices.patch
new file mode 100644
index 0000000..433338a
--- /dev/null
+++ b/patches/linux-3.8.13/0478-ARM-OMAP2-Simplify-code-configuring-ONENAND-devices.patch
@@ -0,0 +1,103 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 15:20:53 -0600
+Subject: [PATCH] ARM: OMAP2+: Simplify code configuring ONENAND devices
+
+The OMAP2+ code that configures the GPMC for ONENAND devices is copying
+structures between functions unnecessarily. Avoid this by passing
+pointers instead and simplify the code.
+
+A pointer to structure "omap_onenand_platform_data" is passed to the
+function omap2_onenand_calc_sync_timings(), but only the flags member
+of the structure is used. Simplify the code by only passing the flags
+member and not the entire structure.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 26 ++++++++++----------------
+ 1 file changed, 10 insertions(+), 16 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index 428cb19..b7f73c5 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -47,10 +47,9 @@ static struct platform_device gpmc_onenand_device = {
+ .resource = &gpmc_onenand_resource,
+ };
+
+-static struct gpmc_timings omap2_onenand_calc_async_timings(void)
++static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
+ {
+ struct gpmc_device_timings dev_t;
+- struct gpmc_timings t;
+
+ const int t_cer = 15;
+ const int t_avdp = 12;
+@@ -76,9 +75,7 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
+ dev_t.t_wpl = t_wpl * 1000;
+ dev_t.t_wph = t_wph * 1000;
+
+- gpmc_calc_timings(&t, &dev_t);
+-
+- return t;
++ gpmc_calc_timings(t, &dev_t);
+ }
+
+ static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
+@@ -158,12 +155,11 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
+ return freq;
+ }
+
+-static struct gpmc_timings
+-omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
+- int freq)
++static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
++ unsigned int flags,
++ int freq)
+ {
+ struct gpmc_device_timings dev_t;
+- struct gpmc_timings t;
+ const int t_cer = 15;
+ const int t_avdp = 12;
+ const int t_cez = 20; /* max of t_cez, t_oez */
+@@ -172,9 +168,9 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
+ int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
+ int div, gpmc_clk_ns;
+
+- if (cfg->flags & ONENAND_SYNC_READ)
++ if (flags & ONENAND_SYNC_READ)
+ onenand_flags = ONENAND_FLAG_SYNCREAD;
+- else if (cfg->flags & ONENAND_SYNC_READWRITE)
++ else if (flags & ONENAND_SYNC_READWRITE)
+ onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
+
+ switch (freq) {
+@@ -265,9 +261,7 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
+ dev_t.cyc_aavdh_oe = 1;
+ dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
+
+- gpmc_calc_timings(&t, &dev_t);
+-
+- return t;
++ gpmc_calc_timings(t, &dev_t);
+ }
+
+ static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
+@@ -300,7 +294,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
+
+ omap2_onenand_set_async_mode(onenand_base);
+
+- t = omap2_onenand_calc_async_timings();
++ omap2_onenand_calc_async_timings(&t);
+
+ ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
+ if (IS_ERR_VALUE(ret))
+@@ -322,7 +316,7 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
+ set_onenand_cfg(onenand_base);
+ }
+
+- t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
++ omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
+
+ ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
+ if (IS_ERR_VALUE(ret))
diff --git a/patches/linux-3.8.13/0479-ARM-OMAP2-Add-variable-to-store-number-of-GPMC-waitp.patch b/patches/linux-3.8.13/0479-ARM-OMAP2-Add-variable-to-store-number-of-GPMC-waitp.patch
new file mode 100644
index 0000000..fe77f8c
--- /dev/null
+++ b/patches/linux-3.8.13/0479-ARM-OMAP2-Add-variable-to-store-number-of-GPMC-waitp.patch
@@ -0,0 +1,285 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Wed, 20 Feb 2013 15:53:38 -0600
+Subject: [PATCH] ARM: OMAP2+: Add variable to store number of GPMC waitpins
+
+The GPMC has wait-pin signals that can be assigned to a chip-select
+to monitor the ready signal of an external device. Add a variable to
+indicate the total number of wait-pins for a given device. This will
+allow us to detect if the wait-pin being selected is valid or not.
+
+When booting with device-tree read the number of wait-pins from the
+device-tree blob. When device-tree is not used set the number of
+wait-pins to 4 which is valid for OMAP2-5 devices. Newer devices
+that have less wait-pins (such as AM335x) only support booting with
+device-tree and so hard-coding the wait-pin number when not using
+device-tree is fine.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 231 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 230 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 901dacd..1346f3e 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -102,6 +102,8 @@
+ #define GPMC_HAS_WR_ACCESS 0x1
+ #define GPMC_HAS_WR_DATA_MUX_BUS 0x2
+
++#define GPMC_NR_WAITPINS 4
++
+ /* XXX: Only NAND irq has been considered,currently these are the only ones used
+ */
+ #define GPMC_NR_IRQ 2
+@@ -145,7 +147,9 @@ static unsigned gpmc_irq_start;
+ static struct resource gpmc_mem_root;
+ static struct resource gpmc_cs_mem[GPMC_CS_NUM];
+ static DEFINE_SPINLOCK(gpmc_mem_lock);
+-static unsigned int gpmc_cs_map; /* flag for cs which are initialized */
++/* Define chip-selects as reserved by default until probe completes */
++static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
++static unsigned int gpmc_nr_waitpins;
+ static struct device *gpmc_dev;
+ static int gpmc_irq;
+ static resource_size_t phys_base, mem_size;
+@@ -1110,6 +1114,217 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+ return 0;
+ }
+
++#ifdef CONFIG_OF
++static struct of_device_id gpmc_dt_ids[] = {
++ { .compatible = "ti,omap2420-gpmc" },
++ { .compatible = "ti,omap2430-gpmc" },
++ { .compatible = "ti,omap3430-gpmc" }, /* omap3430 & omap3630 */
++ { .compatible = "ti,omap4430-gpmc" }, /* omap4430 & omap4460 & omap543x */
++ { .compatible = "ti,am3352-gpmc" }, /* am335x devices */
++ { }
++};
++MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
++
++static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
++ struct gpmc_timings *gpmc_t)
++{
++ u32 val;
++
++ memset(gpmc_t, 0, sizeof(*gpmc_t));
++
++ /* minimum clock period for syncronous mode */
++ if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
++ gpmc_t->sync_clk = val;
++
++ /* chip select timtings */
++ if (!of_property_read_u32(np, "gpmc,cs-on", &val))
++ gpmc_t->cs_on = val;
++
++ if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
++ gpmc_t->cs_rd_off = val;
++
++ if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
++ gpmc_t->cs_wr_off = val;
++
++ /* ADV signal timings */
++ if (!of_property_read_u32(np, "gpmc,adv-on", &val))
++ gpmc_t->adv_on = val;
++
++ if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
++ gpmc_t->adv_rd_off = val;
++
++ if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
++ gpmc_t->adv_wr_off = val;
++
++ /* WE signal timings */
++ if (!of_property_read_u32(np, "gpmc,we-on", &val))
++ gpmc_t->we_on = val;
++
++ if (!of_property_read_u32(np, "gpmc,we-off", &val))
++ gpmc_t->we_off = val;
++
++ /* OE signal timings */
++ if (!of_property_read_u32(np, "gpmc,oe-on", &val))
++ gpmc_t->oe_on = val;
++
++ if (!of_property_read_u32(np, "gpmc,oe-off", &val))
++ gpmc_t->oe_off = val;
++
++ /* access and cycle timings */
++ if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
++ gpmc_t->page_burst_access = val;
++
++ if (!of_property_read_u32(np, "gpmc,access", &val))
++ gpmc_t->access = val;
++
++ if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
++ gpmc_t->rd_cycle = val;
++
++ if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
++ gpmc_t->wr_cycle = val;
++
++ /* only for OMAP3430 */
++ if (!of_property_read_u32(np, "gpmc,wr-access", &val))
++ gpmc_t->wr_access = val;
++
++ if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
++ gpmc_t->wr_data_mux_bus = val;
++}
++
++#ifdef CONFIG_MTD_NAND
++
++static const char * const nand_ecc_opts[] = {
++ [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
++ [OMAP_ECC_HAMMING_CODE_HW] = "hw",
++ [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode",
++ [OMAP_ECC_BCH4_CODE_HW] = "bch4",
++ [OMAP_ECC_BCH8_CODE_HW] = "bch8",
++};
++
++static int gpmc_probe_nand_child(struct platform_device *pdev,
++ struct device_node *child)
++{
++ u32 val;
++ const char *s;
++ struct gpmc_timings gpmc_t;
++ struct omap_nand_platform_data *gpmc_nand_data;
++
++ if (of_property_read_u32(child, "reg", &val) < 0) {
++ dev_err(&pdev->dev, "%s has no 'reg' property\n",
++ child->full_name);
++ return -ENODEV;
++ }
++
++ gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
++ GFP_KERNEL);
++ if (!gpmc_nand_data)
++ return -ENOMEM;
++
++ gpmc_nand_data->cs = val;
++ gpmc_nand_data->of_node = child;
++
++ if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
++ for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
++ if (!strcasecmp(s, nand_ecc_opts[val])) {
++ gpmc_nand_data->ecc_opt = val;
++ break;
++ }
++
++ val = of_get_nand_bus_width(child);
++ if (val == 16)
++ gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
++
++ gpmc_read_timings_dt(child, &gpmc_t);
++ gpmc_nand_init(gpmc_nand_data, &gpmc_t);
++
++ return 0;
++}
++#else
++static int gpmc_probe_nand_child(struct platform_device *pdev,
++ struct device_node *child)
++{
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_MTD_ONENAND
++static int gpmc_probe_onenand_child(struct platform_device *pdev,
++ struct device_node *child)
++{
++ u32 val;
++ struct omap_onenand_platform_data *gpmc_onenand_data;
++
++ if (of_property_read_u32(child, "reg", &val) < 0) {
++ dev_err(&pdev->dev, "%s has no 'reg' property\n",
++ child->full_name);
++ return -ENODEV;
++ }
++
++ gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data),
++ GFP_KERNEL);
++ if (!gpmc_onenand_data)
++ return -ENOMEM;
++
++ gpmc_onenand_data->cs = val;
++ gpmc_onenand_data->of_node = child;
++ gpmc_onenand_data->dma_channel = -1;
++
++ if (!of_property_read_u32(child, "dma-channel", &val))
++ gpmc_onenand_data->dma_channel = val;
++
++ gpmc_onenand_init(gpmc_onenand_data);
++
++ return 0;
++}
++#else
++static int gpmc_probe_onenand_child(struct platform_device *pdev,
++ struct device_node *child)
++{
++ return 0;
++}
++#endif
++
++static int gpmc_probe_dt(struct platform_device *pdev)
++{
++ int ret;
++ struct device_node *child;
++ const struct of_device_id *of_id =
++ of_match_device(gpmc_dt_ids, &pdev->dev);
++
++ if (!of_id)
++ return 0;
++
++ ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
++ &gpmc_nr_waitpins);
++ if (ret < 0) {
++ pr_err("%s: number of wait pins not found!\n", __func__);
++ return ret;
++ }
++
++ for_each_node_by_name(child, "nand") {
++ ret = gpmc_probe_nand_child(pdev, child);
++ if (ret < 0) {
++ of_node_put(child);
++ return ret;
++ }
++ }
++
++ for_each_node_by_name(child, "onenand") {
++ ret = gpmc_probe_onenand_child(pdev, child);
++ if (ret < 0) {
++ of_node_put(child);
++ return ret;
++ }
++ }
++ return 0;
++}
++#else
++static int gpmc_probe_dt(struct platform_device *pdev)
++{
++ return 0;
++}
++#endif
++
+ static int gpmc_probe(struct platform_device *pdev)
+ {
+ int rc;
+@@ -1163,6 +1378,20 @@ static int gpmc_probe(struct platform_device *pdev)
+ if (IS_ERR_VALUE(gpmc_setup_irq()))
+ dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
+
++ /* Now the GPMC is initialised, unreserve the chip-selects */
++ gpmc_cs_map = 0;
++
++ if (!pdev->dev.of_node)
++ gpmc_nr_waitpins = GPMC_NR_WAITPINS;
++
++ rc = gpmc_probe_dt(pdev);
++ if (rc < 0) {
++ clk_disable_unprepare(gpmc_l3_clk);
++ clk_put(gpmc_l3_clk);
++ dev_err(gpmc_dev, "failed to probe DT parameters\n");
++ return rc;
++ }
++
+ return 0;
+ }
+
diff --git a/patches/linux-3.8.13/0480-ARM-OMAP2-Add-structure-for-storing-GPMC-settings.patch b/patches/linux-3.8.13/0480-ARM-OMAP2-Add-structure-for-storing-GPMC-settings.patch
new file mode 100644
index 0000000..6158aab
--- /dev/null
+++ b/patches/linux-3.8.13/0480-ARM-OMAP2-Add-structure-for-storing-GPMC-settings.patch
@@ -0,0 +1,323 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 13:46:22 -0600
+Subject: [PATCH] ARM: OMAP2+: Add structure for storing GPMC settings
+
+The GPMC has various different configuration options such as bus-width,
+synchronous or asychronous mode selection, burst mode options etc.
+Currently, there is no central structure for storing all these options
+when configuring the GPMC for a given device. Some of the options are
+stored in the GPMC timing structure and some are directly programmed
+into the GPMC configuration register. Add a new structure to store
+these options and convert code to use this structure. Adding this
+structure will allow us to create a common function for configuring
+these options.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 18 ++++++++++-----
+ arch/arm/mach-omap2/gpmc-smc91x.c | 2 +-
+ arch/arm/mach-omap2/gpmc.c | 45 +++++++++++++++++++++---------------
+ arch/arm/mach-omap2/gpmc.h | 28 ++++++++++++++++------
+ arch/arm/mach-omap2/usb-tusb6010.c | 19 ++++++++-------
+ 5 files changed, 72 insertions(+), 40 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index b7f73c5..d2bf43e 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -47,6 +47,15 @@ static struct platform_device gpmc_onenand_device = {
+ .resource = &gpmc_onenand_resource,
+ };
+
++static struct gpmc_settings onenand_async = {
++ .mux_add_data = GPMC_MUX_AD,
++};
++
++static struct gpmc_settings onenand_sync = {
++ .burst_read = true,
++ .mux_add_data = GPMC_MUX_AD,
++};
++
+ static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
+ {
+ struct gpmc_device_timings dev_t;
+@@ -63,7 +72,6 @@ static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
+
+ memset(&dev_t, 0, sizeof(dev_t));
+
+- dev_t.mux = true;
+ dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
+ dev_t.t_avdp_w = dev_t.t_avdp_r;
+ dev_t.t_aavdh = t_aavdh * 1000;
+@@ -75,7 +83,7 @@ static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
+ dev_t.t_wpl = t_wpl * 1000;
+ dev_t.t_wph = t_wph * 1000;
+
+- gpmc_calc_timings(t, &dev_t);
++ gpmc_calc_timings(t, &onenand_async, &dev_t);
+ }
+
+ static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
+@@ -235,10 +243,8 @@ static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
+ /* Set synchronous read timings */
+ memset(&dev_t, 0, sizeof(dev_t));
+
+- dev_t.mux = true;
+- dev_t.sync_read = true;
+ if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
+- dev_t.sync_write = true;
++ onenand_sync.sync_write = true;
+ } else {
+ dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
+ dev_t.t_wpl = t_wpl * 1000;
+@@ -261,7 +267,7 @@ static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
+ dev_t.cyc_aavdh_oe = 1;
+ dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
+
+- gpmc_calc_timings(t, &dev_t);
++ gpmc_calc_timings(t, &onenand_sync, &dev_t);
+ }
+
+ static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
+diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
+index 11d0b75..4b78338 100644
+--- a/arch/arm/mach-omap2/gpmc-smc91x.c
++++ b/arch/arm/mach-omap2/gpmc-smc91x.c
+@@ -104,7 +104,7 @@ static int smc91c96_gpmc_retime(void)
+ dev_t.t_cez_w = t4_w * 1000;
+ dev_t.t_wr_cycle = (t20 - t3) * 1000;
+
+- gpmc_calc_timings(&t, &dev_t);
++ gpmc_calc_timings(&t, NULL, &dev_t);
+
+ return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
+ }
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 1346f3e..888c4b4 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -814,9 +814,9 @@ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
+
+ /* XXX: can the cycles be avoided ? */
+ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
+- struct gpmc_device_timings *dev_t)
++ struct gpmc_device_timings *dev_t,
++ bool mux)
+ {
+- bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_rd_off */
+@@ -869,9 +869,9 @@ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
+ }
+
+ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
+- struct gpmc_device_timings *dev_t)
++ struct gpmc_device_timings *dev_t,
++ bool mux)
+ {
+- bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_wr_off */
+@@ -931,9 +931,9 @@ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
+ }
+
+ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
+- struct gpmc_device_timings *dev_t)
++ struct gpmc_device_timings *dev_t,
++ bool mux)
+ {
+- bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_rd_off */
+@@ -971,9 +971,9 @@ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
+ }
+
+ static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
+- struct gpmc_device_timings *dev_t)
++ struct gpmc_device_timings *dev_t,
++ bool mux)
+ {
+- bool mux = dev_t->mux;
+ u32 temp;
+
+ /* adv_wr_off */
+@@ -1043,7 +1043,8 @@ static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
+ }
+
+ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
+- struct gpmc_device_timings *dev_t)
++ struct gpmc_device_timings *dev_t,
++ bool sync)
+ {
+ u32 temp;
+
+@@ -1057,7 +1058,7 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
+ gpmc_t->cs_on + dev_t->t_ce_avd);
+ gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
+
+- if (dev_t->sync_write || dev_t->sync_read)
++ if (sync)
+ gpmc_calc_sync_common_timings(gpmc_t, dev_t);
+
+ return 0;
+@@ -1092,21 +1093,29 @@ static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
+ }
+
+ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+- struct gpmc_device_timings *dev_t)
++ struct gpmc_settings *gpmc_s,
++ struct gpmc_device_timings *dev_t)
+ {
++ bool mux = false, sync = false;
++
++ if (gpmc_s) {
++ mux = gpmc_s->mux_add_data ? true : false;
++ sync = (gpmc_s->sync_read || gpmc_s->sync_write);
++ }
++
+ memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+- gpmc_calc_common_timings(gpmc_t, dev_t);
++ gpmc_calc_common_timings(gpmc_t, dev_t, sync);
+
+- if (dev_t->sync_read)
+- gpmc_calc_sync_read_timings(gpmc_t, dev_t);
++ if (gpmc_s && gpmc_s->sync_read)
++ gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux);
+ else
+- gpmc_calc_async_read_timings(gpmc_t, dev_t);
++ gpmc_calc_async_read_timings(gpmc_t, dev_t, mux);
+
+- if (dev_t->sync_write)
+- gpmc_calc_sync_write_timings(gpmc_t, dev_t);
++ if (gpmc_s && gpmc_s->sync_write)
++ gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux);
+ else
+- gpmc_calc_async_write_timings(gpmc_t, dev_t);
++ gpmc_calc_async_write_timings(gpmc_t, dev_t, mux);
+
+ /* TODO: remove, see function definition */
+ gpmc_convert_ps_to_ns(gpmc_t);
+diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
+index 697ff42..39e4e04 100644
+--- a/arch/arm/mach-omap2/gpmc.h
++++ b/arch/arm/mach-omap2/gpmc.h
+@@ -60,8 +60,8 @@
+ #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
+ #define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8)
+ #define GPMC_CONFIG1_MUXNONMUX GPMC_CONFIG1_MUXTYPE(0)
+-#define GPMC_CONFIG1_MUXAAD GPMC_CONFIG1_MUXTYPE(1)
+-#define GPMC_CONFIG1_MUXADDDATA GPMC_CONFIG1_MUXTYPE(2)
++#define GPMC_CONFIG1_MUXAAD GPMC_CONFIG1_MUXTYPE(GPMC_MUX_AAD)
++#define GPMC_CONFIG1_MUXADDDATA GPMC_CONFIG1_MUXTYPE(GPMC_MUX_AD)
+ #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
+ #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
+ #define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1))
+@@ -76,6 +76,8 @@
+ #define GPMC_IRQ_FIFOEVENTENABLE 0x01
+ #define GPMC_IRQ_COUNT_EVENT 0x02
+
++#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
++#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
+
+ /* bool type time settings */
+ struct gpmc_bool_timings {
+@@ -181,10 +183,6 @@ struct gpmc_device_timings {
+ u8 cyc_wpl; /* write deassertion time in cycles */
+ u32 cyc_iaa; /* initial access time in cycles */
+
+- bool mux; /* address & data muxed */
+- bool sync_write;/* synchronous write */
+- bool sync_read; /* synchronous read */
+-
+ /* extra delays */
+ bool ce_xdelay;
+ bool avd_xdelay;
+@@ -192,8 +190,24 @@ struct gpmc_device_timings {
+ bool we_xdelay;
+ };
+
++struct gpmc_settings {
++ bool burst_wrap; /* enables wrap bursting */
++ bool burst_read; /* enables read page/burst mode */
++ bool burst_write; /* enables write page/burst mode */
++ bool device_nand; /* device is NAND */
++ bool sync_read; /* enables synchronous reads */
++ bool sync_write; /* enables synchronous writes */
++ bool wait_on_read; /* monitor wait on reads */
++ bool wait_on_write; /* monitor wait on writes */
++ u32 burst_len; /* page/burst length */
++ u32 device_width; /* device bus width (8 or 16 bit) */
++ u32 mux_add_data; /* multiplex address & data */
++ u32 wait_pin; /* wait-pin to be used */
++};
++
+ extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+- struct gpmc_device_timings *dev_t);
++ struct gpmc_settings *gpmc_s,
++ struct gpmc_device_timings *dev_t);
+
+ extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+ extern int gpmc_get_client_irq(unsigned irq_config);
+diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
+index c5a3c6f..faaf96d 100644
+--- a/arch/arm/mach-omap2/usb-tusb6010.c
++++ b/arch/arm/mach-omap2/usb-tusb6010.c
+@@ -26,6 +26,15 @@
+ static u8 async_cs, sync_cs;
+ static unsigned refclk_psec;
+
++static struct gpmc_settings tusb_async = {
++ .mux_add_data = GPMC_MUX_AD,
++};
++
++static struct gpmc_settings tusb_sync = {
++ .sync_read = true,
++ .sync_write = true,
++ .mux_add_data = GPMC_MUX_AD,
++};
+
+ /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
+
+@@ -37,8 +46,6 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
+
+ memset(&dev_t, 0, sizeof(dev_t));
+
+- dev_t.mux = true;
+-
+ dev_t.t_ceasu = 8 * 1000;
+ dev_t.t_avdasu = t_acsnh_advnh - 7000;
+ dev_t.t_ce_avd = 1000;
+@@ -52,7 +59,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
+ dev_t.t_wpl = 300;
+ dev_t.cyc_aavdh_we = 1;
+
+- gpmc_calc_timings(&t, &dev_t);
++ gpmc_calc_timings(&t, &tusb_async, &dev_t);
+
+ return gpmc_cs_set_timings(async_cs, &t);
+ }
+@@ -65,10 +72,6 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
+
+ memset(&dev_t, 0, sizeof(dev_t));
+
+- dev_t.mux = true;
+- dev_t.sync_read = true;
+- dev_t.sync_write = true;
+-
+ dev_t.clk = 11100;
+ dev_t.t_bacc = 1000;
+ dev_t.t_ces = 1000;
+@@ -84,7 +87,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
+ dev_t.cyc_wpl = 6;
+ dev_t.t_ce_rdyz = 7000;
+
+- gpmc_calc_timings(&t, &dev_t);
++ gpmc_calc_timings(&t, &tusb_sync, &dev_t);
+
+ return gpmc_cs_set_timings(sync_cs, &t);
+ }
diff --git a/patches/linux-3.8.13/0481-ARM-OMAP2-Add-function-for-configuring-GPMC-settings.patch b/patches/linux-3.8.13/0481-ARM-OMAP2-Add-function-for-configuring-GPMC-settings.patch
new file mode 100644
index 0000000..f27137e
--- /dev/null
+++ b/patches/linux-3.8.13/0481-ARM-OMAP2-Add-function-for-configuring-GPMC-settings.patch
@@ -0,0 +1,176 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 15:25:23 -0600
+Subject: [PATCH] ARM: OMAP2+: Add function for configuring GPMC settings
+
+The GPMC has various different configuration options such as bus-width,
+synchronous or asychronous mode selection, burst mode options etc.
+Currently, there is no common function for configuring these options and
+various devices set these options by either programming the GPMC CONFIG1
+register directly or by calling gpmc_cs_configure() to set some of the
+options.
+
+Add a new function for configuring all of the GPMC options. Having a common
+function for configuring this options will simplify code and ease the
+migration to device-tree.
+
+Also add a new capability flag to detect devices that support the
+address-address-data multiplexing mode.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 100 ++++++++++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-omap2/gpmc.h | 6 +++
+ 2 files changed, 106 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 888c4b4..0302a03 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -101,6 +101,7 @@
+
+ #define GPMC_HAS_WR_ACCESS 0x1
+ #define GPMC_HAS_WR_DATA_MUX_BUS 0x2
++#define GPMC_HAS_MUX_AAD 0x4
+
+ #define GPMC_NR_WAITPINS 4
+
+@@ -1123,6 +1124,90 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+ return 0;
+ }
+
++/**
++ * gpmc_cs_program_settings - programs non-timing related settings
++ * @cs: GPMC chip-select to program
++ * @p: pointer to GPMC settings structure
++ *
++ * Programs non-timing related settings for a GPMC chip-select, such as
++ * bus-width, burst configuration, etc. Function should be called once
++ * for each chip-select that is being used and must be called before
++ * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
++ * register will be initialised to zero by this function. Returns 0 on
++ * success and appropriate negative error code on failure.
++ */
++int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
++{
++ u32 config1;
++
++ if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) {
++ pr_err("%s: invalid width %d!", __func__, p->device_width);
++ return -EINVAL;
++ }
++
++ /* Address-data multiplexing not supported for NAND devices */
++ if (p->device_nand && p->mux_add_data) {
++ pr_err("%s: invalid configuration!\n", __func__);
++ return -EINVAL;
++ }
++
++ if ((p->mux_add_data > GPMC_MUX_AD) ||
++ ((p->mux_add_data == GPMC_MUX_AAD) &&
++ !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
++ pr_err("%s: invalid multiplex configuration!\n", __func__);
++ return -EINVAL;
++ }
++
++ /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
++ if (p->burst_read || p->burst_write) {
++ switch (p->burst_len) {
++ case GPMC_BURST_4:
++ case GPMC_BURST_8:
++ case GPMC_BURST_16:
++ break;
++ default:
++ pr_err("%s: invalid page/burst-length (%d)\n",
++ __func__, p->burst_len);
++ return -EINVAL;
++ }
++ }
++
++ if ((p->wait_on_read || p->wait_on_write) &&
++ (p->wait_pin > gpmc_nr_waitpins)) {
++ pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
++ return -EINVAL;
++ }
++
++ config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
++
++ if (p->sync_read)
++ config1 |= GPMC_CONFIG1_READTYPE_SYNC;
++ if (p->sync_write)
++ config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
++ if (p->wait_on_read)
++ config1 |= GPMC_CONFIG1_WAIT_READ_MON;
++ if (p->wait_on_write)
++ config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
++ if (p->wait_on_read || p->wait_on_write)
++ config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
++ if (p->device_nand)
++ config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
++ if (p->mux_add_data)
++ config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
++ if (p->burst_read)
++ config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
++ if (p->burst_write)
++ config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
++ if (p->burst_read || p->burst_write) {
++ config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
++ config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
++ }
++
++ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
++
++ return 0;
++}
++
+ #ifdef CONFIG_OF
+ static struct of_device_id gpmc_dt_ids[] = {
+ { .compatible = "ti,omap2420-gpmc" },
+@@ -1371,8 +1456,23 @@ static int gpmc_probe(struct platform_device *pdev)
+ gpmc_dev = &pdev->dev;
+
+ l = gpmc_read_reg(GPMC_REVISION);
++
++ /*
++ * FIXME: Once device-tree migration is complete the below flags
++ * should be populated based upon the device-tree compatible
++ * string. For now just use the IP revision. OMAP3+ devices have
++ * the wr_access and wr_data_mux_bus register fields. OMAP4+
++ * devices support the addr-addr-data multiplex protocol.
++ *
++ * GPMC IP revisions:
++ * - OMAP24xx = 2.0
++ * - OMAP3xxx = 5.0
++ * - OMAP44xx/54xx/AM335x = 6.0
++ */
+ if (GPMC_REVISION_MAJOR(l) > 0x4)
+ gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
++ if (GPMC_REVISION_MAJOR(l) > 0x5)
++ gpmc_capability |= GPMC_HAS_MUX_AAD;
+ dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
+ GPMC_REVISION_MINOR(l));
+
+diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
+index 39e4e04..ce6ae21 100644
+--- a/arch/arm/mach-omap2/gpmc.h
++++ b/arch/arm/mach-omap2/gpmc.h
+@@ -76,6 +76,11 @@
+ #define GPMC_IRQ_FIFOEVENTENABLE 0x01
+ #define GPMC_IRQ_COUNT_EVENT 0x02
+
++#define GPMC_BURST_4 4 /* 4 word burst */
++#define GPMC_BURST_8 8 /* 8 word burst */
++#define GPMC_BURST_16 16 /* 16 word burst */
++#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */
++#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */
+ #define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
+ #define GPMC_MUX_AD 2 /* Addr-Data multiplex */
+
+@@ -217,6 +222,7 @@ extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
+ extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
+ extern int gpmc_calc_divider(unsigned int sync_clk);
+ extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
++extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p);
+ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+ extern void gpmc_cs_free(int cs);
+ extern void omap3_gpmc_save_context(void);
diff --git a/patches/linux-3.8.13/0482-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch b/patches/linux-3.8.13/0482-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch
new file mode 100644
index 0000000..91cbb30
--- /dev/null
+++ b/patches/linux-3.8.13/0482-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch
@@ -0,0 +1,133 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 12:42:22 -0600
+Subject: [PATCH] ARM: OMAP2+: Convert ONENAND to use
+ gpmc_cs_program_settings()
+
+Convert the OMAP2+ ONENAND code to use the gpmc_cs_program_settings()
+function for configuring the various GPMC options instead of directly
+programming the CONFIG1 register.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 57 +++++++++++++++---------------------
+ 1 file changed, 23 insertions(+), 34 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index d2bf43e..dae6e05 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -48,18 +48,22 @@ static struct platform_device gpmc_onenand_device = {
+ };
+
+ static struct gpmc_settings onenand_async = {
++ .device_width = GPMC_DEVWIDTH_16BIT,
+ .mux_add_data = GPMC_MUX_AD,
+ };
+
+ static struct gpmc_settings onenand_sync = {
+ .burst_read = true,
++ .burst_wrap = true,
++ .burst_len = GPMC_BURST_16,
++ .device_width = GPMC_DEVWIDTH_16BIT,
+ .mux_add_data = GPMC_MUX_AD,
++ .wait_pin = 0,
+ };
+
+ static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
+ {
+ struct gpmc_device_timings dev_t;
+-
+ const int t_cer = 15;
+ const int t_avdp = 12;
+ const int t_aavdh = 7;
+@@ -86,16 +90,6 @@ static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
+ gpmc_calc_timings(t, &onenand_async, &dev_t);
+ }
+
+-static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
+-{
+- /* Configure GPMC for asynchronous read */
+- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+- GPMC_CONFIG1_DEVICESIZE_16 |
+- GPMC_CONFIG1_MUXADDDATA);
+-
+- return gpmc_cs_set_timings(cs, t);
+-}
+-
+ static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
+ {
+ u32 reg;
+@@ -243,8 +237,11 @@ static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
+ /* Set synchronous read timings */
+ memset(&dev_t, 0, sizeof(dev_t));
+
++ if (onenand_flags & ONENAND_FLAG_SYNCREAD)
++ onenand_sync.sync_read = true;
+ if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
+ onenand_sync.sync_write = true;
++ onenand_sync.burst_write = true;
+ } else {
+ dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
+ dev_t.t_wpl = t_wpl * 1000;
+@@ -270,29 +267,6 @@ static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
+ gpmc_calc_timings(t, &onenand_sync, &dev_t);
+ }
+
+-static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
+-{
+- unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD;
+- unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE;
+-
+- /* Configure GPMC for synchronous read */
+- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+- GPMC_CONFIG1_WRAPBURST_SUPP |
+- GPMC_CONFIG1_READMULTIPLE_SUPP |
+- (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
+- (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
+- (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
+- GPMC_CONFIG1_PAGE_LEN(2) |
+- (cpu_is_omap34xx() ? 0 :
+- (GPMC_CONFIG1_WAIT_READ_MON |
+- GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
+- GPMC_CONFIG1_DEVICESIZE_16 |
+- GPMC_CONFIG1_DEVICETYPE_NOR |
+- GPMC_CONFIG1_MUXADDDATA);
+-
+- return gpmc_cs_set_timings(cs, t);
+-}
+-
+ static int omap2_onenand_setup_async(void __iomem *onenand_base)
+ {
+ struct gpmc_timings t;
+@@ -302,6 +276,10 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
+
+ omap2_onenand_calc_async_timings(&t);
+
++ ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
++ if (ret < 0)
++ return ret;
++
+ ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+@@ -322,8 +300,19 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
+ set_onenand_cfg(onenand_base);
+ }
+
++ /*
++ * FIXME: Appears to be legacy code from initial ONENAND commit.
++ * Unclear what boards this is for and if this can be removed.
++ */
++ if (!cpu_is_omap34xx())
++ onenand_sync.wait_on_read = true;
++
+ omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
+
++ ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_sync);
++ if (ret < 0)
++ return ret;
++
+ ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
+ if (IS_ERR_VALUE(ret))
+ return ret;
diff --git a/patches/linux-3.8.13/0483-ARM-OMAP2-Convert-NAND-to-use-gpmc_cs_program_settin.patch b/patches/linux-3.8.13/0483-ARM-OMAP2-Convert-NAND-to-use-gpmc_cs_program_settin.patch
new file mode 100644
index 0000000..74b4cf8
--- /dev/null
+++ b/patches/linux-3.8.13/0483-ARM-OMAP2-Convert-NAND-to-use-gpmc_cs_program_settin.patch
@@ -0,0 +1,84 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 15:43:08 -0600
+Subject: [PATCH] ARM: OMAP2+: Convert NAND to use gpmc_cs_program_settings()
+
+Convert the OMAP2+ NAND code to use the gpmc_cs_program_settings()
+function for configuring the various GPMC options instead of directly
+programming the CONFIG1 register.
+
+This moves the configuration of some GPMC options outside the
+nand_gpmc_retime() because these options should only need to be set once
+regardless of whether the gpmc timing is changing dynamically at runtime.
+The programming of where the wait-pin is also moved slightly, but this
+will not have any impact to existing devices as no boards are currently
+setting the dev_ready variable.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc-nand.c | 35 +++++++++++++++++++++++------------
+ 1 file changed, 23 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
+index 6027dd0..d8ad997 100644
+--- a/arch/arm/mach-omap2/gpmc-nand.c
++++ b/arch/arm/mach-omap2/gpmc-nand.c
+@@ -74,14 +74,6 @@ static int omap2_nand_gpmc_retime(
+ t.cs_wr_off = gpmc_t->cs_wr_off;
+ t.wr_cycle = gpmc_t->wr_cycle;
+
+- /* Configure GPMC */
+- if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+- gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
+- else
+- gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
+- gpmc_cs_configure(gpmc_nand_data->cs,
+- GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
+- gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
+ err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
+ if (err)
+ return err;
+@@ -114,8 +106,11 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+ struct gpmc_timings *gpmc_t)
+ {
+ int err = 0;
++ struct gpmc_settings s;
+ struct device *dev = &gpmc_nand_device.dev;
+
++ memset(&s, 0, sizeof(struct gpmc_settings));
++
+ gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+
+ err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
+@@ -140,11 +135,27 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+ dev_err(dev, "Unable to set gpmc timings: %d\n", err);
+ return err;
+ }
+- }
+
+- /* Enable RD PIN Monitoring Reg */
+- if (gpmc_nand_data->dev_ready) {
+- gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
++ s.device_nand = true;
++
++ /* Enable RD PIN Monitoring Reg */
++ if (gpmc_nand_data->dev_ready) {
++ s.wait_on_read = true;
++ s.wait_on_write = true;
++ }
++
++ if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
++ s.device_width = GPMC_DEVWIDTH_16BIT;
++ else
++ s.device_width = GPMC_DEVWIDTH_8BIT;
++
++ err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
++ if (err < 0)
++ goto out_free_cs;
++
++ err = gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
++ if (err < 0)
++ goto out_free_cs;
+ }
+
+ gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
diff --git a/patches/linux-3.8.13/0484-ARM-OMAP2-Convert-SMC91x-to-use-gpmc_cs_program_sett.patch b/patches/linux-3.8.13/0484-ARM-OMAP2-Convert-SMC91x-to-use-gpmc_cs_program_sett.patch
new file mode 100644
index 0000000..08043f1
--- /dev/null
+++ b/patches/linux-3.8.13/0484-ARM-OMAP2-Convert-SMC91x-to-use-gpmc_cs_program_sett.patch
@@ -0,0 +1,81 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 13:01:37 -0600
+Subject: [PATCH] ARM: OMAP2+: Convert SMC91x to use
+ gpmc_cs_program_settings()
+
+Convert the OMAP2+ SMC91x code to use the gpmc_cs_program_settings()
+function for configuring the various GPMC options instead of directly
+programming the CONFIG1 register.
+
+Move configuration of the GPMC settings outside retime function and
+this does not need to be done if the timings are changed dynamically
+at runtime.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc-smc91x.c | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
+index 4b78338..61a0635 100644
+--- a/arch/arm/mach-omap2/gpmc-smc91x.c
++++ b/arch/arm/mach-omap2/gpmc-smc91x.c
+@@ -49,6 +49,10 @@ static struct platform_device gpmc_smc91x_device = {
+ .resource = gpmc_smc91x_resources,
+ };
+
++static struct gpmc_settings smc91x_settings = {
++ .device_width = GPMC_DEVWIDTH_16BIT,
++};
++
+ /*
+ * Set the gpmc timings for smc91c96. The timings are taken
+ * from the data sheet available at:
+@@ -67,18 +71,6 @@ static int smc91c96_gpmc_retime(void)
+ const int t7 = 5; /* Figure 12.4 write */
+ const int t8 = 5; /* Figure 12.4 write */
+ const int t20 = 185; /* Figure 12.2 read and 12.4 write */
+- u32 l;
+-
+- l = GPMC_CONFIG1_DEVICESIZE_16;
+- if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
+- l |= GPMC_CONFIG1_MUXADDDATA;
+- if (gpmc_cfg->flags & GPMC_READ_MON)
+- l |= GPMC_CONFIG1_WAIT_READ_MON;
+- if (gpmc_cfg->flags & GPMC_WRITE_MON)
+- l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+- if (gpmc_cfg->wait_pin)
+- l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
+- gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
+
+ /*
+ * FIXME: Calculate the address and data bus muxed timings.
+@@ -104,7 +96,7 @@ static int smc91c96_gpmc_retime(void)
+ dev_t.t_cez_w = t4_w * 1000;
+ dev_t.t_wr_cycle = (t20 - t3) * 1000;
+
+- gpmc_calc_timings(&t, NULL, &dev_t);
++ gpmc_calc_timings(&t, &smc91x_settings, &dev_t);
+
+ return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
+ }
+@@ -133,6 +125,18 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
+ gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
+ gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+
++ if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
++ smc91x_settings.mux_add_data = GPMC_MUX_AD;
++ if (gpmc_cfg->flags & GPMC_READ_MON)
++ smc91x_settings.wait_on_read = true;
++ if (gpmc_cfg->flags & GPMC_WRITE_MON)
++ smc91x_settings.wait_on_write = true;
++ if (gpmc_cfg->wait_pin)
++ smc91x_settings.wait_pin = gpmc_cfg->wait_pin;
++ ret = gpmc_cs_program_settings(gpmc_cfg->cs, &smc91x_settings);
++ if (ret < 0)
++ goto free1;
++
+ if (gpmc_cfg->retime) {
+ ret = gpmc_cfg->retime();
+ if (ret != 0)
diff --git a/patches/linux-3.8.13/0485-ARM-OMAP2-Convert-TUSB-to-use-gpmc_cs_program_settin.patch b/patches/linux-3.8.13/0485-ARM-OMAP2-Convert-TUSB-to-use-gpmc_cs_program_settin.patch
new file mode 100644
index 0000000..715042d
--- /dev/null
+++ b/patches/linux-3.8.13/0485-ARM-OMAP2-Convert-TUSB-to-use-gpmc_cs_program_settin.patch
@@ -0,0 +1,98 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 13:01:47 -0600
+Subject: [PATCH] ARM: OMAP2+: Convert TUSB to use gpmc_cs_program_settings()
+
+Convert the OMAP2+ TUSB code to use the gpmc_cs_program_settings()
+function for configuring the various GPMC options instead of directly
+programming the CONFIG1 register.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/usb-tusb6010.c | 43 ++++++++++++++++--------------------
+ 1 file changed, 19 insertions(+), 24 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
+index faaf96d..e832bc7 100644
+--- a/arch/arm/mach-omap2/usb-tusb6010.c
++++ b/arch/arm/mach-omap2/usb-tusb6010.c
+@@ -8,6 +8,7 @@
+ * published by the Free Software Foundation.
+ */
+
++#include <linux/err.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/errno.h>
+@@ -27,12 +28,21 @@ static u8 async_cs, sync_cs;
+ static unsigned refclk_psec;
+
+ static struct gpmc_settings tusb_async = {
++ .wait_on_read = true,
++ .wait_on_write = true,
++ .device_width = GPMC_DEVWIDTH_16BIT,
+ .mux_add_data = GPMC_MUX_AD,
+ };
+
+ static struct gpmc_settings tusb_sync = {
++ .burst_read = true,
++ .burst_write = true,
+ .sync_read = true,
+ .sync_write = true,
++ .wait_on_read = true,
++ .wait_on_write = true,
++ .burst_len = GPMC_BURST_16,
++ .device_width = GPMC_DEVWIDTH_16BIT,
+ .mux_add_data = GPMC_MUX_AD,
+ };
+
+@@ -168,18 +178,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
+ return status;
+ }
+ tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
++ tusb_async.wait_pin = waitpin;
+ async_cs = async;
+- gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
+- GPMC_CONFIG1_PAGE_LEN(2)
+- | GPMC_CONFIG1_WAIT_READ_MON
+- | GPMC_CONFIG1_WAIT_WRITE_MON
+- | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
+- | GPMC_CONFIG1_READTYPE_ASYNC
+- | GPMC_CONFIG1_WRITETYPE_ASYNC
+- | GPMC_CONFIG1_DEVICESIZE_16
+- | GPMC_CONFIG1_DEVICETYPE_NOR
+- | GPMC_CONFIG1_MUXADDDATA);
+
++ status = gpmc_cs_program_settings(async_cs, &tusb_async);
++ if (status < 0)
++ return status;
+
+ /* SYNC region, primarily for DMA */
+ status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
+@@ -189,21 +193,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
+ return status;
+ }
+ tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
++ tusb_sync.wait_pin = waitpin;
+ sync_cs = sync;
+- gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
+- GPMC_CONFIG1_READMULTIPLE_SUPP
+- | GPMC_CONFIG1_READTYPE_SYNC
+- | GPMC_CONFIG1_WRITEMULTIPLE_SUPP
+- | GPMC_CONFIG1_WRITETYPE_SYNC
+- | GPMC_CONFIG1_PAGE_LEN(2)
+- | GPMC_CONFIG1_WAIT_READ_MON
+- | GPMC_CONFIG1_WAIT_WRITE_MON
+- | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
+- | GPMC_CONFIG1_DEVICESIZE_16
+- | GPMC_CONFIG1_DEVICETYPE_NOR
+- | GPMC_CONFIG1_MUXADDDATA
+- /* fclk divider gets set later */
+- );
++
++ status = gpmc_cs_program_settings(sync_cs, &tusb_sync);
++ if (status < 0)
++ return status;
+
+ /* IRQ */
+ status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
diff --git a/patches/linux-3.8.13/0486-ARM-OMAP2-Don-t-configure-of-chip-select-options-in-.patch b/patches/linux-3.8.13/0486-ARM-OMAP2-Don-t-configure-of-chip-select-options-in-.patch
new file mode 100644
index 0000000..770cde4
--- /dev/null
+++ b/patches/linux-3.8.13/0486-ARM-OMAP2-Don-t-configure-of-chip-select-options-in-.patch
@@ -0,0 +1,129 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 13:00:21 -0600
+Subject: [PATCH] ARM: OMAP2+: Don't configure of chip-select options in
+ gpmc_cs_configure()
+
+With the addition of the gpmc_cs_program_settings(), we no longer need
+or use gpmc_cs_configure() to configure some of the GPMC chip-select
+options. So rename the function to gpmc_configure() and remove code that
+modifies options in the CONFIG1 register.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc-nand.c | 2 +-
+ arch/arm/mach-omap2/gpmc.c | 49 ++++++---------------------------------
+ arch/arm/mach-omap2/gpmc.h | 5 +---
+ 3 files changed, 9 insertions(+), 47 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
+index d8ad997..7c70752 100644
+--- a/arch/arm/mach-omap2/gpmc-nand.c
++++ b/arch/arm/mach-omap2/gpmc-nand.c
+@@ -153,7 +153,7 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+ if (err < 0)
+ goto out_free_cs;
+
+- err = gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
++ err = gpmc_configure(GPMC_CONFIG_WP, 0);
+ if (err < 0)
+ goto out_free_cs;
+ }
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 0302a03..de8be1e 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -544,16 +544,14 @@ void gpmc_cs_free(int cs)
+ EXPORT_SYMBOL(gpmc_cs_free);
+
+ /**
+- * gpmc_cs_configure - write request to configure gpmc
+- * @cs: chip select number
++ * gpmc_configure - write request to configure gpmc
+ * @cmd: command type
+ * @wval: value to write
+ * @return status of the operation
+ */
+-int gpmc_cs_configure(int cs, int cmd, int wval)
++int gpmc_configure(int cmd, int wval)
+ {
+- int err = 0;
+- u32 regval = 0;
++ u32 regval;
+
+ switch (cmd) {
+ case GPMC_ENABLE_IRQ:
+@@ -573,47 +571,14 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
+ gpmc_write_reg(GPMC_CONFIG, regval);
+ break;
+
+- case GPMC_CONFIG_RDY_BSY:
+- regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+- if (wval)
+- regval |= WR_RD_PIN_MONITORING;
+- else
+- regval &= ~WR_RD_PIN_MONITORING;
+- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+- break;
+-
+- case GPMC_CONFIG_DEV_SIZE:
+- regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+-
+- /* clear 2 target bits */
+- regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
+-
+- /* set the proper value */
+- regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+-
+- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+- break;
+-
+- case GPMC_CONFIG_DEV_TYPE:
+- regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+- /* clear 4 target bits */
+- regval &= ~(GPMC_CONFIG1_DEVICETYPE(3) |
+- GPMC_CONFIG1_MUXTYPE(3));
+- /* set the proper value */
+- regval |= GPMC_CONFIG1_DEVICETYPE(wval);
+- if (wval == GPMC_DEVICETYPE_NOR)
+- regval |= GPMC_CONFIG1_MUXADDDATA;
+- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
+- break;
+-
+ default:
+- printk(KERN_ERR "gpmc_configure_cs: Not supported\n");
+- err = -EINVAL;
++ pr_err("%s: command not supported\n", __func__);
++ return -EINVAL;
+ }
+
+- return err;
++ return 0;
+ }
+-EXPORT_SYMBOL(gpmc_cs_configure);
++EXPORT_SYMBOL(gpmc_configure);
+
+ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
+ {
+diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
+index ce6ae21..87d2a22 100644
+--- a/arch/arm/mach-omap2/gpmc.h
++++ b/arch/arm/mach-omap2/gpmc.h
+@@ -59,9 +59,6 @@
+ #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10)
+ #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0)
+ #define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8)
+-#define GPMC_CONFIG1_MUXNONMUX GPMC_CONFIG1_MUXTYPE(0)
+-#define GPMC_CONFIG1_MUXAAD GPMC_CONFIG1_MUXTYPE(GPMC_MUX_AAD)
+-#define GPMC_CONFIG1_MUXADDDATA GPMC_CONFIG1_MUXTYPE(GPMC_MUX_AD)
+ #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4)
+ #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3)
+ #define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1))
+@@ -227,6 +224,6 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+ extern void gpmc_cs_free(int cs);
+ extern void omap3_gpmc_save_context(void);
+ extern void omap3_gpmc_restore_context(void);
+-extern int gpmc_cs_configure(int cs, int cmd, int wval);
++extern int gpmc_configure(int cmd, int wval);
+
+ #endif
diff --git a/patches/linux-3.8.13/0487-ARM-OMAP2-Add-function-to-read-GPMC-settings-from-de.patch b/patches/linux-3.8.13/0487-ARM-OMAP2-Add-function-to-read-GPMC-settings-from-de.patch
new file mode 100644
index 0000000..5c03a1a
--- /dev/null
+++ b/patches/linux-3.8.13/0487-ARM-OMAP2-Add-function-to-read-GPMC-settings-from-de.patch
@@ -0,0 +1,196 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Wed, 20 Feb 2013 15:53:12 -0600
+Subject: [PATCH] ARM: OMAP2+: Add function to read GPMC settings from
+ device-tree
+
+Adds a function to read the various GPMC chip-select settings from
+device-tree and store them in the gpmc_settings structure.
+
+Update the GPMC device-tree binding documentation to describe these
+options.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ Documentation/devicetree/bindings/bus/ti-gpmc.txt | 107 +++++++++++++++++++++
+ arch/arm/mach-omap2/gpmc.c | 40 ++++++++
+ arch/arm/mach-omap2/gpmc.h | 2 +
+ 3 files changed, 149 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
+new file mode 100644
+index 0000000..6fde1cf
+--- /dev/null
++++ b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
+@@ -0,0 +1,107 @@
++Device tree bindings for OMAP general purpose memory controllers (GPMC)
++
++The actual devices are instantiated from the child nodes of a GPMC node.
++
++Required properties:
++
++ - compatible: Should be set to one of the following:
++
++ ti,omap2420-gpmc (omap2420)
++ ti,omap2430-gpmc (omap2430)
++ ti,omap3430-gpmc (omap3430 & omap3630)
++ ti,omap4430-gpmc (omap4430 & omap4460 & omap543x)
++ ti,am3352-gpmc (am335x devices)
++
++ - reg: A resource specifier for the register space
++ (see the example below)
++ - ti,hwmods: Should be set to "ti,gpmc" until the DT transition is
++ completed.
++ - #address-cells: Must be set to 2 to allow memory address translation
++ - #size-cells: Must be set to 1 to allow CS address passing
++ - gpmc,num-cs: The maximum number of chip-select lines that controller
++ can support.
++ - gpmc,num-waitpins: The maximum number of wait pins that controller can
++ support.
++ - ranges: Must be set up to reflect the memory layout with four
++ integer values for each chip-select line in use:
++
++ <cs-number> 0 <physical address of mapping> <size>
++
++ Currently, calculated values derived from the contents
++ of the per-CS register GPMC_CONFIG7 (as set up by the
++ bootloader) are used for the physical address decoding.
++ As this will change in the future, filling correct
++ values here is a requirement.
++
++Timing properties for child nodes. All are optional and default to 0.
++
++ - gpmc,sync-clk: Minimum clock period for synchronous mode, in picoseconds
++
++ Chip-select signal timings corresponding to GPMC_CONFIG2:
++ - gpmc,cs-on: Assertion time
++ - gpmc,cs-rd-off: Read deassertion time
++ - gpmc,cs-wr-off: Write deassertion time
++
++ ADV signal timings corresponding to GPMC_CONFIG3:
++ - gpmc,adv-on: Assertion time
++ - gpmc,adv-rd-off: Read deassertion time
++ - gpmc,adv-wr-off: Write deassertion time
++
++ WE signals timings corresponding to GPMC_CONFIG4:
++ - gpmc,we-on: Assertion time
++ - gpmc,we-off: Deassertion time
++
++ OE signals timings corresponding to GPMC_CONFIG4:
++ - gpmc,oe-on: Assertion time
++ - gpmc,oe-off: Deassertion time
++
++ Access time and cycle time timings corresponding to GPMC_CONFIG5:
++ - gpmc,page-burst-access: Multiple access word delay
++ - gpmc,access: Start-cycle to first data valid delay
++ - gpmc,rd-cycle: Total read cycle time
++ - gpmc,wr-cycle: Total write cycle time
++
++The following are only applicable to OMAP3+ and AM335x:
++ - gpmc,wr-access
++ - gpmc,wr-data-mux-bus
++
++GPMC chip-select settings properties for child nodes. All are optional.
++
++- gpmc,burst-length Page/burst length. Must be 4, 8 or 16.
++- gpmc,burst-wrap Enables wrap bursting
++- gpmc,burst-read Enables read page/burst mode
++- gpmc,burst-write Enables write page/burst mode
++- gpmc,device-nand Device is NAND
++- gpmc,device-width Total width of device(s) connected to a GPMC
++ chip-select in bytes. The GPMC supports 8-bit
++ and 16-bit devices and so this property must be
++ 1 or 2.
++- gpmc,mux-add-data Address and data multiplexing configuration.
++ Valid values are 1 for address-address-data
++ multiplexing mode and 2 for address-data
++ multiplexing mode.
++- gpmc,sync-read Enables synchronous read. Defaults to asynchronous
++ is this is not set.
++- gpmc,sync-write Enables synchronous writes. Defaults to asynchronous
++ is this is not set.
++- gpmc,wait-pin Wait-pin used by client. Must be less than
++ "gpmc,num-waitpins".
++- gpmc,wait-on-read Enables wait monitoring on reads.
++- gpmc,wait-on-write Enables wait monitoring on writes.
++
++Example for an AM33xx board:
++
++ gpmc: gpmc@50000000 {
++ compatible = "ti,am3352-gpmc";
++ ti,hwmods = "gpmc";
++ reg = <0x50000000 0x2000>;
++ interrupts = <100>;
++
++ gpmc,num-cs = <8>;
++ gpmc,num-waitpins = <2>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++ ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
++
++ /* child nodes go here */
++ };
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index de8be1e..dd2c72c 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -1184,6 +1184,46 @@ static struct of_device_id gpmc_dt_ids[] = {
+ };
+ MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
+
++/**
++ * gpmc_read_settings_dt - read gpmc settings from device-tree
++ * @np: pointer to device-tree node for a gpmc child device
++ * @p: pointer to gpmc settings structure
++ *
++ * Reads the GPMC settings for a GPMC child device from device-tree and
++ * stores them in the GPMC settings structure passed. The GPMC settings
++ * structure is initialised to zero by this function and so any
++ * previously stored settings will be cleared.
++ */
++void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
++{
++ memset(p, 0, sizeof(struct gpmc_settings));
++
++ p->sync_read = of_property_read_bool(np, "gpmc,sync-read");
++ p->sync_write = of_property_read_bool(np, "gpmc,sync-write");
++ p->device_nand = of_property_read_bool(np, "gpmc,device-nand");
++ of_property_read_u32(np, "gpmc,device-width", &p->device_width);
++ of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
++
++ if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
++ p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap");
++ p->burst_read = of_property_read_bool(np, "gpmc,burst-read");
++ p->burst_write = of_property_read_bool(np, "gpmc,burst-write");
++ if (!p->burst_read && !p->burst_write)
++ pr_warn("%s: page/burst-length set but not used!\n",
++ __func__);
++ }
++
++ if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
++ p->wait_on_read = of_property_read_bool(np,
++ "gpmc,wait-on-read");
++ p->wait_on_write = of_property_read_bool(np,
++ "gpmc,wait-on-write");
++ if (!p->wait_on_read && !p->wait_on_write)
++ pr_warn("%s: read/write wait monitoring not enabled!\n",
++ __func__);
++ }
++}
++
+ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
+ struct gpmc_timings *gpmc_t)
+ {
+diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
+index 87d2a22..707f6d5 100644
+--- a/arch/arm/mach-omap2/gpmc.h
++++ b/arch/arm/mach-omap2/gpmc.h
+@@ -225,5 +225,7 @@ extern void gpmc_cs_free(int cs);
+ extern void omap3_gpmc_save_context(void);
+ extern void omap3_gpmc_restore_context(void);
+ extern int gpmc_configure(int cmd, int wval);
++extern void gpmc_read_settings_dt(struct device_node *np,
++ struct gpmc_settings *p);
+
+ #endif
diff --git a/patches/linux-3.8.13/0488-ARM-OMAP2-Add-additional-GPMC-timing-parameters.patch b/patches/linux-3.8.13/0488-ARM-OMAP2-Add-additional-GPMC-timing-parameters.patch
new file mode 100644
index 0000000..6a9d313
--- /dev/null
+++ b/patches/linux-3.8.13/0488-ARM-OMAP2-Add-additional-GPMC-timing-parameters.patch
@@ -0,0 +1,238 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 18:51:27 -0600
+Subject: [PATCH] ARM: OMAP2+: Add additional GPMC timing parameters
+
+Some of the GPMC timings parameters are currently missing from the GPMC
+device-tree binding. Add these parameters to the binding documentation
+as well as code to read them. Also add either "-ps" or "-ns" suffix to
+the GPMC timing properties to indicate whether the timing is in
+picoseconds or nanoseconds.
+
+The existing code in gpmc_read_timings_dt() is checking the value of
+of_property_read_u32() and only is successful storing the value read
+in the gpmc_timings structure. Checking the return value in this case
+is not necessary and we can simply read the value, if present, and
+store directly in the gpmc_timings structure. Therefore, simplify the
+code by removing these checks.
+
+The comment in the gpmc_read_timings_dt() function, "only for OMAP3430"
+is also incorrect as it is applicable to all OMAP3+ devices. So correct
+this too.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ Documentation/devicetree/bindings/bus/ti-gpmc.txt | 78 +++++++++++------
+ arch/arm/mach-omap2/gpmc.c | 94 ++++++++++-----------
+ 2 files changed, 98 insertions(+), 74 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
+index 6fde1cf..4b87ea1 100644
+--- a/Documentation/devicetree/bindings/bus/ti-gpmc.txt
++++ b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
+@@ -35,35 +35,59 @@ Required properties:
+
+ Timing properties for child nodes. All are optional and default to 0.
+
+- - gpmc,sync-clk: Minimum clock period for synchronous mode, in picoseconds
+-
+- Chip-select signal timings corresponding to GPMC_CONFIG2:
+- - gpmc,cs-on: Assertion time
+- - gpmc,cs-rd-off: Read deassertion time
+- - gpmc,cs-wr-off: Write deassertion time
+-
+- ADV signal timings corresponding to GPMC_CONFIG3:
+- - gpmc,adv-on: Assertion time
+- - gpmc,adv-rd-off: Read deassertion time
+- - gpmc,adv-wr-off: Write deassertion time
+-
+- WE signals timings corresponding to GPMC_CONFIG4:
+- - gpmc,we-on: Assertion time
+- - gpmc,we-off: Deassertion time
+-
+- OE signals timings corresponding to GPMC_CONFIG4:
+- - gpmc,oe-on: Assertion time
+- - gpmc,oe-off: Deassertion time
+-
+- Access time and cycle time timings corresponding to GPMC_CONFIG5:
+- - gpmc,page-burst-access: Multiple access word delay
+- - gpmc,access: Start-cycle to first data valid delay
+- - gpmc,rd-cycle: Total read cycle time
+- - gpmc,wr-cycle: Total write cycle time
++ - gpmc,sync-clk-ps: Minimum clock period for synchronous mode, in picoseconds
++
++ Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
++ - gpmc,cs-on-ns: Assertion time
++ - gpmc,cs-rd-off-ns: Read deassertion time
++ - gpmc,cs-wr-off-ns: Write deassertion time
++
++ ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
++ - gpmc,adv-on-ns: Assertion time
++ - gpmc,adv-rd-off-ns: Read deassertion time
++ - gpmc,adv-wr-off-ns: Write deassertion time
++
++ WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
++ - gpmc,we-on-ns Assertion time
++ - gpmc,we-off-ns: Deassertion time
++
++ OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
++ - gpmc,oe-on-ns: Assertion time
++ - gpmc,oe-off-ns: Deassertion time
++
++ Access time and cycle time timings (in nanoseconds) corresponding to
++ GPMC_CONFIG5:
++ - gpmc,page-burst-access-ns: Multiple access word delay
++ - gpmc,access-ns: Start-cycle to first data valid delay
++ - gpmc,rd-cycle-ns: Total read cycle time
++ - gpmc,wr-cycle-ns: Total write cycle time
++ - gpmc,bus-turnaround-ns: Turn-around time between successive accesses
++ - gpmc,cycle2cycle-delay-ns: Delay between chip-select pulses
++ - gpmc,clk-activation-ns: GPMC clock activation time
++ - gpmc,wait-monitoring-ns: Start of wait monitoring with regard to valid
++ data
++
++Boolean timing parameters. If property is present parameter enabled and
++disabled if omitted:
++ - gpmc,adv-extra-delay: ADV signal is delayed by half GPMC clock
++ - gpmc,cs-extra-delay: CS signal is delayed by half GPMC clock
++ - gpmc,cycle2cycle-diffcsen: Add "cycle2cycle-delay" between successive
++ accesses to a different CS
++ - gpmc,cycle2cycle-samecsen: Add "cycle2cycle-delay" between successive
++ accesses to the same CS
++ - gpmc,oe-extra-delay: OE signal is delayed by half GPMC clock
++ - gpmc,we-extra-delay: WE signal is delayed by half GPMC clock
++ - gpmc,time-para-granularity: Multiply all access times by 2
+
+ The following are only applicable to OMAP3+ and AM335x:
+- - gpmc,wr-access
+- - gpmc,wr-data-mux-bus
++ - gpmc,wr-access-ns: In synchronous write mode, for single or
++ burst accesses, defines the number of
++ GPMC_FCLK cycles from start access time
++ to the GPMC_CLK rising edge used by the
++ memory device for the first data capture.
++ - gpmc,wr-data-mux-bus-ns: In address-data multiplex mode, specifies
++ the time when the first data is driven on
++ the address-data bus.
+
+ GPMC chip-select settings properties for child nodes. All are optional.
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index dd2c72c..c127e75 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -1227,67 +1227,67 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
+ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
+ struct gpmc_timings *gpmc_t)
+ {
+- u32 val;
++ struct gpmc_bool_timings *p;
++
++ if (!np || !gpmc_t)
++ return;
+
+ memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+ /* minimum clock period for syncronous mode */
+- if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
+- gpmc_t->sync_clk = val;
++ of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk);
+
+ /* chip select timtings */
+- if (!of_property_read_u32(np, "gpmc,cs-on", &val))
+- gpmc_t->cs_on = val;
+-
+- if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
+- gpmc_t->cs_rd_off = val;
+-
+- if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
+- gpmc_t->cs_wr_off = val;
++ of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on);
++ of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off);
++ of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off);
+
+ /* ADV signal timings */
+- if (!of_property_read_u32(np, "gpmc,adv-on", &val))
+- gpmc_t->adv_on = val;
+-
+- if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
+- gpmc_t->adv_rd_off = val;
+-
+- if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
+- gpmc_t->adv_wr_off = val;
++ of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on);
++ of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off);
++ of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off);
+
+ /* WE signal timings */
+- if (!of_property_read_u32(np, "gpmc,we-on", &val))
+- gpmc_t->we_on = val;
+-
+- if (!of_property_read_u32(np, "gpmc,we-off", &val))
+- gpmc_t->we_off = val;
++ of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on);
++ of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off);
+
+ /* OE signal timings */
+- if (!of_property_read_u32(np, "gpmc,oe-on", &val))
+- gpmc_t->oe_on = val;
+-
+- if (!of_property_read_u32(np, "gpmc,oe-off", &val))
+- gpmc_t->oe_off = val;
++ of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on);
++ of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off);
+
+ /* access and cycle timings */
+- if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
+- gpmc_t->page_burst_access = val;
+-
+- if (!of_property_read_u32(np, "gpmc,access", &val))
+- gpmc_t->access = val;
+-
+- if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
+- gpmc_t->rd_cycle = val;
+-
+- if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
+- gpmc_t->wr_cycle = val;
+-
+- /* only for OMAP3430 */
+- if (!of_property_read_u32(np, "gpmc,wr-access", &val))
+- gpmc_t->wr_access = val;
+-
+- if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
+- gpmc_t->wr_data_mux_bus = val;
++ of_property_read_u32(np, "gpmc,page-burst-access-ns",
++ &gpmc_t->page_burst_access);
++ of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access);
++ of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle);
++ of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle);
++ of_property_read_u32(np, "gpmc,bus-turnaround-ns",
++ &gpmc_t->bus_turnaround);
++ of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns",
++ &gpmc_t->cycle2cycle_delay);
++ of_property_read_u32(np, "gpmc,wait-monitoring-ns",
++ &gpmc_t->wait_monitoring);
++ of_property_read_u32(np, "gpmc,clk-activation-ns",
++ &gpmc_t->clk_activation);
++
++ /* only applicable to OMAP3+ */
++ of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access);
++ of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns",
++ &gpmc_t->wr_data_mux_bus);
++
++ /* bool timing parameters */
++ p = &gpmc_t->bool_timings;
++
++ p->cycle2cyclediffcsen =
++ of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen");
++ p->cycle2cyclesamecsen =
++ of_property_read_bool(np, "gpmc,cycle2cycle-samecsen");
++ p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay");
++ p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay");
++ p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay");
++ p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay");
++ p->time_para_granularity =
++ of_property_read_bool(np, "gpmc,time-para-granularity");
+ }
+
+ #ifdef CONFIG_MTD_NAND
diff --git a/patches/linux-3.8.13/0489-ARM-OMAP2-Add-device-tree-support-for-NOR-flash.patch b/patches/linux-3.8.13/0489-ARM-OMAP2-Add-device-tree-support-for-NOR-flash.patch
new file mode 100644
index 0000000..22fa14b
--- /dev/null
+++ b/patches/linux-3.8.13/0489-ARM-OMAP2-Add-device-tree-support-for-NOR-flash.patch
@@ -0,0 +1,273 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Fri, 8 Feb 2013 16:46:13 -0600
+Subject: [PATCH] ARM: OMAP2+: Add device-tree support for NOR flash
+
+NOR flash is not currently supported when booting with device-tree
+on OMAP2+ devices. Add support to detect and configure NOR devices
+when booting with device-tree.
+
+Add documentation for the TI GPMC NOR binding.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ Documentation/devicetree/bindings/mtd/gpmc-nor.txt | 98 ++++++++++++++++
+ arch/arm/mach-omap2/gpmc.c | 119 ++++++++++++++++++++
+ 2 files changed, 217 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/mtd/gpmc-nor.txt
+
+diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
+new file mode 100644
+index 0000000..420b3ab
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
+@@ -0,0 +1,98 @@
++Device tree bindings for NOR flash connect to TI GPMC
++
++NOR flash connected to the TI GPMC (found on OMAP boards) are represented as
++child nodes of the GPMC controller with a name of "nor".
++
++All timing relevant properties as well as generic GPMC child properties are
++explained in a separate documents. Please refer to
++Documentation/devicetree/bindings/bus/ti-gpmc.txt
++
++Required properties:
++- bank-width: Width of NOR flash in bytes. GPMC supports 8-bit and
++ 16-bit devices and so must be either 1 or 2 bytes.
++- compatible: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
++- gpmc,cs-on-ns: Chip-select assertion time
++- gpmc,cs-rd-off-ns: Chip-select de-assertion time for reads
++- gpmc,cs-wr-off-ns: Chip-select de-assertion time for writes
++- gpmc,oe-on-ns: Output-enable assertion time
++- gpmc,oe-off-ns: Output-enable de-assertion time
++- gpmc,we-on-ns Write-enable assertion time
++- gpmc,we-off-ns: Write-enable de-assertion time
++- gpmc,access-ns: Start cycle to first data capture (read access)
++- gpmc,rd-cycle-ns: Total read cycle time
++- gpmc,wr-cycle-ns: Total write cycle time
++- linux,mtd-name: Documentation/devicetree/bindings/mtd/mtd-physmap.txt
++- reg: Chip-select, base address (relative to chip-select)
++ and size of NOR flash. Note that base address will be
++ typically 0 as this is the start of the chip-select.
++
++Optional properties:
++- gpmc,XXX Additional GPMC timings and settings parameters. See
++ Documentation/devicetree/bindings/bus/ti-gpmc.txt
++
++Optional properties for partiton table parsing:
++- #address-cells: should be set to 1
++- #size-cells: should be set to 1
++
++Example:
++
++gpmc: gpmc@6e000000 {
++ compatible = "ti,omap3430-gpmc", "simple-bus";
++ ti,hwmods = "gpmc";
++ reg = <0x6e000000 0x1000>;
++ interrupts = <20>;
++ gpmc,num-cs = <8>;
++ gpmc,num-waitpins = <4>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++
++ ranges = <0 0 0x10000000 0x08000000>;
++
++ nor@0,0 {
++ compatible = "cfi-flash";
++ linux,mtd-name= "intel,pf48f6000m0y1be";
++ #address-cells = <1>;
++ #size-cells = <1>;
++ reg = <0 0 0x08000000>;
++ bank-width = <2>;
++
++ gpmc,mux-add-data;
++ gpmc,cs-on-ns = <0>;
++ gpmc,cs-rd-off-ns = <186>;
++ gpmc,cs-wr-off-ns = <186>;
++ gpmc,adv-on-ns = <12>;
++ gpmc,adv-rd-off-ns = <48>;
++ gpmc,adv-wr-off-ns = <48>;
++ gpmc,oe-on-ns = <54>;
++ gpmc,oe-off-ns = <168>;
++ gpmc,we-on-ns = <54>;
++ gpmc,we-off-ns = <168>;
++ gpmc,rd-cycle-ns = <186>;
++ gpmc,wr-cycle-ns = <186>;
++ gpmc,access-ns = <114>;
++ gpmc,page-burst-access-ns = <6>;
++ gpmc,bus-turnaround-ns = <12>;
++ gpmc,cycle2cycle-delay-ns = <18>;
++ gpmc,wr-data-mux-bus-ns = <90>;
++ gpmc,wr-access-ns = <186>;
++ gpmc,cycle2cycle-samecsen;
++ gpmc,cycle2cycle-diffcsen;
++
++ partition@0 {
++ label = "bootloader-nor";
++ reg = <0 0x40000>;
++ };
++ partition@0x40000 {
++ label = "params-nor";
++ reg = <0x40000 0x40000>;
++ };
++ partition@0x80000 {
++ label = "kernel-nor";
++ reg = <0x80000 0x200000>;
++ };
++ partition@0x280000 {
++ label = "filesystem-nor";
++ reg = <0x240000 0x7d80000>;
++ };
++ };
++};
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index c127e75..80dd023 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -25,6 +25,11 @@
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/of_mtd.h>
++#include <linux/of_device.h>
++#include <linux/mtd/nand.h>
+
+ #include <linux/platform_data/mtd-nand-omap2.h>
+
+@@ -493,6 +498,37 @@ static int gpmc_cs_delete_mem(int cs)
+ return r;
+ }
+
++/**
++ * gpmc_cs_remap - remaps a chip-select physical base address
++ * @cs: chip-select to remap
++ * @base: physical base address to re-map chip-select to
++ *
++ * Re-maps a chip-select to a new physical base address specified by
++ * "base". Returns 0 on success and appropriate negative error code
++ * on failure.
++ */
++static int gpmc_cs_remap(int cs, u32 base)
++{
++ int ret;
++ u32 old_base, size;
++
++ if (cs > GPMC_CS_NUM)
++ return -ENODEV;
++ gpmc_cs_get_memconf(cs, &old_base, &size);
++ if (base == old_base)
++ return 0;
++ gpmc_cs_disable_mem(cs);
++ ret = gpmc_cs_delete_mem(cs);
++ if (ret < 0)
++ return ret;
++ ret = gpmc_cs_insert_mem(cs, base, size);
++ if (ret < 0)
++ return ret;
++ gpmc_cs_enable_mem(cs, base, size);
++
++ return 0;
++}
++
+ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
+ {
+ struct resource *res = &gpmc_cs_mem[cs];
+@@ -1383,6 +1419,80 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
+ }
+ #endif
+
++/**
++ * gpmc_probe_nor_child - configures the gpmc for a nor device
++ * @pdev: pointer to gpmc platform device
++ * @child: pointer to device-tree node for nor device
++ *
++ * Allocates and configures a GPMC chip-select for a NOR flash device.
++ * Returns 0 on success and appropriate negative error code on failure.
++ */
++static int gpmc_probe_nor_child(struct platform_device *pdev,
++ struct device_node *child)
++{
++ struct gpmc_settings gpmc_s;
++ struct gpmc_timings gpmc_t;
++ struct resource res;
++ unsigned long base;
++ int ret, cs;
++
++ if (of_property_read_u32(child, "reg", &cs) < 0) {
++ dev_err(&pdev->dev, "%s has no 'reg' property\n",
++ child->full_name);
++ return -ENODEV;
++ }
++
++ if (of_address_to_resource(child, 0, &res) < 0) {
++ dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
++ child->full_name);
++ return -ENODEV;
++ }
++
++ ret = gpmc_cs_request(cs, resource_size(&res), &base);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
++ return ret;
++ }
++
++ /*
++ * FIXME: gpmc_cs_request() will map the CS to an arbitary
++ * location in the gpmc address space. When booting with
++ * device-tree we want the NOR flash to be mapped to the
++ * location specified in the device-tree blob. So remap the
++ * CS to this location. Once DT migration is complete should
++ * just make gpmc_cs_request() map a specific address.
++ */
++ ret = gpmc_cs_remap(cs, res.start);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
++ cs, res.start);
++ goto err;
++ }
++
++ gpmc_read_settings_dt(child, &gpmc_s);
++
++ ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
++ if (ret < 0)
++ goto err;
++
++ ret = gpmc_cs_program_settings(cs, &gpmc_s);
++ if (ret < 0)
++ goto err;
++
++ gpmc_read_timings_dt(child, &gpmc_t);
++ gpmc_cs_set_timings(cs, &gpmc_t);
++
++ if (of_platform_device_create(child, NULL, &pdev->dev))
++ return 0;
++
++ dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
++
++err:
++ gpmc_cs_free(cs);
++
++ return ret;
++}
++
+ static int gpmc_probe_dt(struct platform_device *pdev)
+ {
+ int ret;
+@@ -1415,6 +1525,15 @@ static int gpmc_probe_dt(struct platform_device *pdev)
+ return ret;
+ }
+ }
++
++ for_each_node_by_name(child, "nor") {
++ ret = gpmc_probe_nor_child(pdev, child);
++ if (ret < 0) {
++ of_node_put(child);
++ return ret;
++ }
++ }
++
+ return 0;
+ }
+ #else
diff --git a/patches/linux-3.8.13/0490-ARM-OMAP2-Convert-NAND-to-retrieve-GPMC-settings-fro.patch b/patches/linux-3.8.13/0490-ARM-OMAP2-Convert-NAND-to-retrieve-GPMC-settings-fro.patch
new file mode 100644
index 0000000..20fabba
--- /dev/null
+++ b/patches/linux-3.8.13/0490-ARM-OMAP2-Convert-NAND-to-retrieve-GPMC-settings-fro.patch
@@ -0,0 +1,42 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Mon, 25 Feb 2013 11:36:47 -0600
+Subject: [PATCH] ARM: OMAP2+: Convert NAND to retrieve GPMC settings from DT
+
+When booting with device-tree, retrieve GPMC settings for NAND from
+the device-tree blob. This will allow us to remove all static settings
+stored in the gpmc-nand.c in the future once the migration to
+device-tree is complete.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc-nand.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
+index 7c70752..026785c 100644
+--- a/arch/arm/mach-omap2/gpmc-nand.c
++++ b/arch/arm/mach-omap2/gpmc-nand.c
+@@ -136,12 +136,16 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+ return err;
+ }
+
+- s.device_nand = true;
+-
+- /* Enable RD PIN Monitoring Reg */
+- if (gpmc_nand_data->dev_ready) {
+- s.wait_on_read = true;
+- s.wait_on_write = true;
++ if (gpmc_nand_data->of_node) {
++ gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
++ } else {
++ s.device_nand = true;
++
++ /* Enable RD PIN Monitoring Reg */
++ if (gpmc_nand_data->dev_ready) {
++ s.wait_on_read = true;
++ s.wait_on_write = true;
++ }
+ }
+
+ if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
diff --git a/patches/linux-3.8.13/0491-ARM-OMAP2-Convert-ONENAND-to-retrieve-GPMC-settings-.patch b/patches/linux-3.8.13/0491-ARM-OMAP2-Convert-ONENAND-to-retrieve-GPMC-settings-.patch
new file mode 100644
index 0000000..e94826a
--- /dev/null
+++ b/patches/linux-3.8.13/0491-ARM-OMAP2-Convert-ONENAND-to-retrieve-GPMC-settings-.patch
@@ -0,0 +1,122 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Mon, 25 Feb 2013 11:37:58 -0600
+Subject: [PATCH] ARM: OMAP2+: Convert ONENAND to retrieve GPMC settings from
+ DT
+
+When booting with device-tree, retrieve GPMC settings for ONENAND from
+the device-tree blob. This will allow us to remove all static settings
+stored in the gpmc-nand.c in the future once the migration to
+device-tree is complete.
+
+The user must now specify the ONENAND device width in the device-tree
+binding so that the GPMC can be programmed correctly. Therefore, update
+the device-tree binding documentation for ONENAND devices connected to
+the GPMC to reflect this.
+
+Please note that this does not include GPMC timings for ONENAND. The
+timings are being calculated at runtime.
+
+There is some legacy code that only enables read wait monitoring for
+non-OMAP3 devices. There are no known OMAP3 device issues that prevent
+this feature being enabled and so when booting with device-tree use the
+wait-monitoring settings described in the device-tree blob.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ .../devicetree/bindings/mtd/gpmc-onenand.txt | 46 ++++++++++++++++++++
+ arch/arm/mach-omap2/gpmc-onenand.c | 21 ++++++---
+ 2 files changed, 61 insertions(+), 6 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
+
+diff --git a/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt b/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
+new file mode 100644
+index 0000000..b752942
+--- /dev/null
++++ b/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
+@@ -0,0 +1,46 @@
++Device tree bindings for GPMC connected OneNANDs
++
++GPMC connected OneNAND (found on OMAP boards) are represented as child nodes of
++the GPMC controller with a name of "onenand".
++
++All timing relevant properties as well as generic gpmc child properties are
++explained in a separate documents - please refer to
++Documentation/devicetree/bindings/bus/ti-gpmc.txt
++
++Required properties:
++
++ - reg: The CS line the peripheral is connected to
++ - gpmc,device-width Width of the ONENAND device connected to the GPMC
++ in bytes. Must be 1 or 2.
++
++Optional properties:
++
++ - dma-channel: DMA Channel index
++
++For inline partiton table parsing (optional):
++
++ - #address-cells: should be set to 1
++ - #size-cells: should be set to 1
++
++Example for an OMAP3430 board:
++
++ gpmc: gpmc@6e000000 {
++ compatible = "ti,omap3430-gpmc";
++ ti,hwmods = "gpmc";
++ reg = <0x6e000000 0x1000000>;
++ interrupts = <20>;
++ gpmc,num-cs = <8>;
++ gpmc,num-waitpins = <4>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++
++ onenand@0 {
++ reg = <0 0 0>; /* CS0, offset 0 */
++ gpmc,device-width = <2>;
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ /* partitions go here */
++ };
++ };
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index dae6e05..1a2b84e 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -272,6 +272,10 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
+ struct gpmc_timings t;
+ int ret;
+
++ if (gpmc_onenand_data->of_node)
++ gpmc_read_settings_dt(gpmc_onenand_data->of_node,
++ &onenand_async);
++
+ omap2_onenand_set_async_mode(onenand_base);
+
+ omap2_onenand_calc_async_timings(&t);
+@@ -300,12 +304,17 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
+ set_onenand_cfg(onenand_base);
+ }
+
+- /*
+- * FIXME: Appears to be legacy code from initial ONENAND commit.
+- * Unclear what boards this is for and if this can be removed.
+- */
+- if (!cpu_is_omap34xx())
+- onenand_sync.wait_on_read = true;
++ if (gpmc_onenand_data->of_node) {
++ gpmc_read_settings_dt(gpmc_onenand_data->of_node,
++ &onenand_sync);
++ } else {
++ /*
++ * FIXME: Appears to be legacy code from initial ONENAND commit.
++ * Unclear what boards this is for and if this can be removed.
++ */
++ if (!cpu_is_omap34xx())
++ onenand_sync.wait_on_read = true;
++ }
+
+ omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
+
diff --git a/patches/linux-3.8.13/0492-ARM-OMAP2-Detect-incorrectly-aligned-GPMC-base-addre.patch b/patches/linux-3.8.13/0492-ARM-OMAP2-Detect-incorrectly-aligned-GPMC-base-addre.patch
new file mode 100644
index 0000000..9ffb942
--- /dev/null
+++ b/patches/linux-3.8.13/0492-ARM-OMAP2-Detect-incorrectly-aligned-GPMC-base-addre.patch
@@ -0,0 +1,76 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Wed, 6 Mar 2013 12:00:10 -0600
+Subject: [PATCH] ARM: OMAP2+: Detect incorrectly aligned GPMC base address
+
+Each GPMC chip-select can be configured to map 16MB, 32MB, 64MB or 128MB
+of address space. The physical base address where a chip-select starts
+is also configurable and must be aligned on a boundary that is equal to
+or greater than the size of the address space mapped bt the chip-select.
+When enabling a GPMC chip-select, ensure that the base address is aligned
+to the appropriate boundary.
+
+Reported-by: Mark Jackson <mpfj-list@mimc.co.uk>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 22 +++++++++++++++++++---
+ 1 file changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 80dd023..9fed934 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -401,11 +401,18 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
+ return 0;
+ }
+
+-static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
++static int gpmc_cs_enable_mem(int cs, u32 base, u32 size)
+ {
+ u32 l;
+ u32 mask;
+
++ /*
++ * Ensure that base address is aligned on a
++ * boundary equal to or greater than size.
++ */
++ if (base & (size - 1))
++ return -EINVAL;
++
+ mask = (1 << GPMC_SECTION_SHIFT) - size;
+ l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+ l &= ~0x3f;
+@@ -414,6 +421,8 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
+ l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
+ l |= GPMC_CONFIG7_CSVALID;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
++
++ return 0;
+ }
+
+ static void gpmc_cs_disable_mem(int cs)
+@@ -524,7 +533,9 @@ static int gpmc_cs_remap(int cs, u32 base)
+ ret = gpmc_cs_insert_mem(cs, base, size);
+ if (ret < 0)
+ return ret;
+- gpmc_cs_enable_mem(cs, base, size);
++ ret = gpmc_cs_enable_mem(cs, base, size);
++ if (ret < 0)
++ return ret;
+
+ return 0;
+ }
+@@ -554,7 +565,12 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
+ if (r < 0)
+ goto out;
+
+- gpmc_cs_enable_mem(cs, res->start, resource_size(res));
++ r = gpmc_cs_enable_mem(cs, res->start, resource_size(res));
++ if (r < 0) {
++ release_resource(res);
++ goto out;
++ }
++
+ *base = res->start;
+ gpmc_cs_set_reserved(cs, 1);
+ out:
diff --git a/patches/linux-3.8.13/0493-ARM-OMAP2-Remove-unnecesssary-GPMC-definitions-and-v.patch b/patches/linux-3.8.13/0493-ARM-OMAP2-Remove-unnecesssary-GPMC-definitions-and-v.patch
new file mode 100644
index 0000000..586d677
--- /dev/null
+++ b/patches/linux-3.8.13/0493-ARM-OMAP2-Remove-unnecesssary-GPMC-definitions-and-v.patch
@@ -0,0 +1,52 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Wed, 6 Mar 2013 14:12:59 -0600
+Subject: [PATCH] ARM: OMAP2+: Remove unnecesssary GPMC definitions and
+ variable
+
+With commit 21cc2bd (ARM: OMAP2+: Remove apollon board support) the
+variable "boot_rom_space" is now not needed and the code surrounding
+this variable can be cleaned up and simplified. Remove unnecessary
+definitions and clean-up the comment as well.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 9fed934..3f87752 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -90,9 +90,7 @@
+ #define GPMC_CS_SIZE 0x30
+ #define GPMC_BCH_SIZE 0x10
+
+-#define GPMC_MEM_START 0x00000000
+ #define GPMC_MEM_END 0x3FFFFFFF
+-#define BOOT_ROM_SPACE 0x100000 /* 1MB */
+
+ #define GPMC_CHUNK_SHIFT 24 /* 16 MB */
+ #define GPMC_SECTION_SHIFT 28 /* 128 MB */
+@@ -788,16 +786,13 @@ static void gpmc_mem_exit(void)
+ static int gpmc_mem_init(void)
+ {
+ int cs, rc;
+- unsigned long boot_rom_space = 0;
+
+- /* never allocate the first page, to facilitate bug detection;
+- * even if we didn't boot from ROM.
++ /*
++ * The first 1MB of GPMC address space is typically mapped to
++ * the internal ROM. Never allocate the first page, to
++ * facilitate bug detection; even if we didn't boot from ROM.
+ */
+- boot_rom_space = BOOT_ROM_SPACE;
+- /* In apollon the CS0 is mapped as 0x0000 0000 */
+- if (machine_is_omap_apollon())
+- boot_rom_space = 0;
+- gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
++ gpmc_mem_root.start = SZ_1M;
+ gpmc_mem_root.end = GPMC_MEM_END;
+
+ /* Reserve all regions that has been set up by bootloader */
diff --git a/patches/linux-3.8.13/0494-ARM-OMAP2-Allow-GPMC-probe-to-complete-even-if-CS-ma.patch b/patches/linux-3.8.13/0494-ARM-OMAP2-Allow-GPMC-probe-to-complete-even-if-CS-ma.patch
new file mode 100644
index 0000000..709459c
--- /dev/null
+++ b/patches/linux-3.8.13/0494-ARM-OMAP2-Allow-GPMC-probe-to-complete-even-if-CS-ma.patch
@@ -0,0 +1,79 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Wed, 6 Mar 2013 14:36:47 -0600
+Subject: [PATCH] ARM: OMAP2+: Allow GPMC probe to complete even if CS mapping
+ fails
+
+When the GPMC driver is probed, we call gpmc_mem_init() to see which
+chip-selects have already been configured and enabled by the boot-loader
+and allocate space for them. If we fail to allocate space for one
+chip-select, then we return failure from the probe and the GPMC driver
+will not be available.
+
+Rather than render the GPMC useless for all GPMC devices, if we fail to
+allocate space for one chip-select print a warning and disable the
+chip-select. This way other GPMC clients can still be used.
+
+There is no downside to this approach, because all GPMC clients need to
+request a chip-select before they can use the GPMC and on requesting a
+chip-select, if memory has not already been reserved for the chip-select
+then it will be.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 25 ++++++++-----------------
+ 1 file changed, 8 insertions(+), 17 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 3f87752..5482d23 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -783,9 +783,9 @@ static void gpmc_mem_exit(void)
+
+ }
+
+-static int gpmc_mem_init(void)
++static void gpmc_mem_init(void)
+ {
+- int cs, rc;
++ int cs;
+
+ /*
+ * The first 1MB of GPMC address space is typically mapped to
+@@ -802,16 +802,13 @@ static int gpmc_mem_init(void)
+ if (!gpmc_cs_mem_enabled(cs))
+ continue;
+ gpmc_cs_get_memconf(cs, &base, &size);
+- rc = gpmc_cs_insert_mem(cs, base, size);
+- if (IS_ERR_VALUE(rc)) {
+- while (--cs >= 0)
+- if (gpmc_cs_mem_enabled(cs))
+- gpmc_cs_delete_mem(cs);
+- return rc;
++
++ if (gpmc_cs_insert_mem(cs, base, size)) {
++ pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n",
++ __func__, cs, base, base + size);
++ gpmc_cs_disable_mem(cs);
+ }
+ }
+-
+- return 0;
+ }
+
+ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
+@@ -1611,13 +1608,7 @@ static int gpmc_probe(struct platform_device *pdev)
+ dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
+ GPMC_REVISION_MINOR(l));
+
+- rc = gpmc_mem_init();
+- if (IS_ERR_VALUE(rc)) {
+- clk_disable_unprepare(gpmc_l3_clk);
+- clk_put(gpmc_l3_clk);
+- dev_err(gpmc_dev, "failed to reserve memory\n");
+- return rc;
+- }
++ gpmc_mem_init();
+
+ if (IS_ERR_VALUE(gpmc_setup_irq()))
+ dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
diff --git a/patches/linux-3.8.13/0495-ARM-OMAP2-return-ENODEV-if-GPMC-child-device-creatio.patch b/patches/linux-3.8.13/0495-ARM-OMAP2-return-ENODEV-if-GPMC-child-device-creatio.patch
new file mode 100644
index 0000000..8258f69
--- /dev/null
+++ b/patches/linux-3.8.13/0495-ARM-OMAP2-return-ENODEV-if-GPMC-child-device-creatio.patch
@@ -0,0 +1,34 @@
+From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+Date: Thu, 14 Mar 2013 16:09:20 +0100
+Subject: [PATCH] ARM: OMAP2+: return -ENODEV if GPMC child device creation
+ fails
+
+gpmc_probe_nor_child() calls of_platform_device_create() to create a
+platform device for the NOR child. If this function fails the value
+of ret is returned to the caller but this value is zero since it was
+assigned the return of a previous call to gpmc_cs_program_settings()
+that had to succeed or otherwise gpmc_probe_nor_child() would have
+returned before.
+
+This means that if of_platform_device_create() fails, 0 will be returned
+to the caller instead of an appropriate error code.
+
+Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 5482d23..e20c6d0 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -1494,6 +1494,7 @@ static int gpmc_probe_nor_child(struct platform_device *pdev,
+ return 0;
+
+ dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
++ ret = -ENODEV;
+
+ err:
+ gpmc_cs_free(cs);
diff --git a/patches/linux-3.8.13/0496-ARM-OMAP2-rename-gpmc_probe_nor_child-to-gpmc_probe_.patch b/patches/linux-3.8.13/0496-ARM-OMAP2-rename-gpmc_probe_nor_child-to-gpmc_probe_.patch
new file mode 100644
index 0000000..554a372
--- /dev/null
+++ b/patches/linux-3.8.13/0496-ARM-OMAP2-rename-gpmc_probe_nor_child-to-gpmc_probe_.patch
@@ -0,0 +1,52 @@
+From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+Date: Thu, 14 Mar 2013 16:09:21 +0100
+Subject: [PATCH] ARM: OMAP2+: rename gpmc_probe_nor_child() to
+ gpmc_probe_generic_child()
+
+The gpmc_probe_nor_child() function is used in the GPMC driver to
+configure the GPMC for a NOR child device node.
+
+But this function is quite generic and all the NOR specific configuration
+is made by the driver of the actual NOR flash memory used.
+
+Other Pseudo-SRAM devices such as ethernet controllers need a similar
+setup so by making this function generic it can be used for those too.
+
+Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index e20c6d0..780cb12 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -1428,14 +1428,14 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
+ #endif
+
+ /**
+- * gpmc_probe_nor_child - configures the gpmc for a nor device
++ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev: pointer to gpmc platform device
+- * @child: pointer to device-tree node for nor device
++ * @child: pointer to device-tree node for child device
+ *
+- * Allocates and configures a GPMC chip-select for a NOR flash device.
++ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+-static int gpmc_probe_nor_child(struct platform_device *pdev,
++static int gpmc_probe_generic_child(struct platform_device *pdev,
+ struct device_node *child)
+ {
+ struct gpmc_settings gpmc_s;
+@@ -1536,7 +1536,7 @@ static int gpmc_probe_dt(struct platform_device *pdev)
+ }
+
+ for_each_node_by_name(child, "nor") {
+- ret = gpmc_probe_nor_child(pdev, child);
++ ret = gpmc_probe_generic_child(pdev, child);
+ if (ret < 0) {
+ of_node_put(child);
+ return ret;
diff --git a/patches/linux-3.8.13/0497-ARM-OMAP2-Add-GPMC-DT-support-for-Ethernet-child-nod.patch b/patches/linux-3.8.13/0497-ARM-OMAP2-Add-GPMC-DT-support-for-Ethernet-child-nod.patch
new file mode 100644
index 0000000..a2ef1af
--- /dev/null
+++ b/patches/linux-3.8.13/0497-ARM-OMAP2-Add-GPMC-DT-support-for-Ethernet-child-nod.patch
@@ -0,0 +1,142 @@
+From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+Date: Thu, 14 Mar 2013 22:54:11 +0100
+Subject: [PATCH] ARM: OMAP2+: Add GPMC DT support for Ethernet child nodes
+
+Besides being used to interface with external memory devices,
+the General-Purpose Memory Controller can be used to connect
+Pseudo-SRAM devices such as ethernet controllers to OMAP2+
+processors using the TI GPMC as a data bus.
+
+This patch allows an ethernet chip to be defined as an GPMC
+child device node.
+
+Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+---
+ Documentation/devicetree/bindings/net/gpmc-eth.txt | 97 ++++++++++++++++++++
+ arch/arm/mach-omap2/gpmc.c | 8 ++
+ 2 files changed, 105 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/gpmc-eth.txt
+
+diff --git a/Documentation/devicetree/bindings/net/gpmc-eth.txt b/Documentation/devicetree/bindings/net/gpmc-eth.txt
+new file mode 100644
+index 0000000..24cb4e4
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/gpmc-eth.txt
+@@ -0,0 +1,97 @@
++Device tree bindings for Ethernet chip connected to TI GPMC
++
++Besides being used to interface with external memory devices, the
++General-Purpose Memory Controller can be used to connect Pseudo-SRAM devices
++such as ethernet controllers to processors using the TI GPMC as a data bus.
++
++Ethernet controllers connected to TI GPMC are represented as child nodes of
++the GPMC controller with an "ethernet" name.
++
++All timing relevant properties as well as generic GPMC child properties are
++explained in a separate documents. Please refer to
++Documentation/devicetree/bindings/bus/ti-gpmc.txt
++
++For the properties relevant to the ethernet controller connected to the GPMC
++refer to the binding documentation of the device. For example, the documentation
++for the SMSC 911x is Documentation/devicetree/bindings/net/smsc911x.txt
++
++Child nodes need to specify the GPMC bus address width using the "bank-width"
++property but is possible that an ethernet controller also has a property to
++specify the I/O registers address width. Even when the GPMC has a maximum 16-bit
++address width, it supports devices with 32-bit word registers.
++For example with an SMSC LAN911x/912x controller connected to the TI GPMC on an
++OMAP2+ board, "bank-width = <2>;" and "reg-io-width = <4>;".
++
++Required properties:
++- bank-width: Address width of the device in bytes. GPMC supports 8-bit
++ and 16-bit devices and so must be either 1 or 2 bytes.
++- compatible: Compatible string property for the ethernet child device.
++- gpmc,cs-on: Chip-select assertion time
++- gpmc,cs-rd-off: Chip-select de-assertion time for reads
++- gpmc,cs-wr-off: Chip-select de-assertion time for writes
++- gpmc,oe-on: Output-enable assertion time
++- gpmc,oe-off Output-enable de-assertion time
++- gpmc,we-on: Write-enable assertion time
++- gpmc,we-off: Write-enable de-assertion time
++- gpmc,access: Start cycle to first data capture (read access)
++- gpmc,rd-cycle: Total read cycle time
++- gpmc,wr-cycle: Total write cycle time
++- reg: Chip-select, base address (relative to chip-select)
++ and size of the memory mapped for the device.
++ Note that base address will be typically 0 as this
++ is the start of the chip-select.
++
++Optional properties:
++- gpmc,XXX Additional GPMC timings and settings parameters. See
++ Documentation/devicetree/bindings/bus/ti-gpmc.txt
++
++Example:
++
++gpmc: gpmc@6e000000 {
++ compatible = "ti,omap3430-gpmc";
++ ti,hwmods = "gpmc";
++ reg = <0x6e000000 0x1000>;
++ interrupts = <20>;
++ gpmc,num-cs = <8>;
++ gpmc,num-waitpins = <4>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++
++ ranges = <5 0 0x2c000000 0x1000000>;
++
++ ethernet@5,0 {
++ compatible = "smsc,lan9221", "smsc,lan9115";
++ reg = <5 0 0xff>;
++ bank-width = <2>;
++
++ gpmc,mux-add-data;
++ gpmc,cs-on = <0>;
++ gpmc,cs-rd-off = <186>;
++ gpmc,cs-wr-off = <186>;
++ gpmc,adv-on = <12>;
++ gpmc,adv-rd-off = <48>;
++ gpmc,adv-wr-off = <48>;
++ gpmc,oe-on = <54>;
++ gpmc,oe-off = <168>;
++ gpmc,we-on = <54>;
++ gpmc,we-off = <168>;
++ gpmc,rd-cycle = <186>;
++ gpmc,wr-cycle = <186>;
++ gpmc,access = <114>;
++ gpmc,page-burst-access = <6>;
++ gpmc,bus-turnaround = <12>;
++ gpmc,cycle2cycle-delay = <18>;
++ gpmc,wr-data-mux-bus = <90>;
++ gpmc,wr-access = <186>;
++ gpmc,cycle2cycle-samecsen;
++ gpmc,cycle2cycle-diffcsen;
++
++ interrupt-parent = <&gpio6>;
++ interrupts = <16>;
++ vmmc-supply = <&vddvario>;
++ vmmc_aux-supply = <&vdd33a>;
++ reg-io-width = <4>;
++
++ smsc,save-mac-address;
++ };
++};
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 780cb12..52c32c9 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -1543,6 +1543,14 @@ static int gpmc_probe_dt(struct platform_device *pdev)
+ }
+ }
+
++ for_each_node_by_name(child, "ethernet") {
++ ret = gpmc_probe_generic_child(pdev, child);
++ if (ret < 0) {
++ of_node_put(child);
++ return ret;
++ }
++ }
++
+ return 0;
+ }
+ #else
diff --git a/patches/linux-3.8.13/0498-mtd-omap-nand-pass-device_node-in-platform-data.patch b/patches/linux-3.8.13/0498-mtd-omap-nand-pass-device_node-in-platform-data.patch
new file mode 100644
index 0000000..42030b9
--- /dev/null
+++ b/patches/linux-3.8.13/0498-mtd-omap-nand-pass-device_node-in-platform-data.patch
@@ -0,0 +1,56 @@
+From: Daniel Mack <zonque@gmail.com>
+Date: Fri, 14 Dec 2012 11:36:41 +0100
+Subject: [PATCH] mtd: omap-nand: pass device_node in platform data
+
+Pass an optional device_node pointer in the platform data, which in turn
+will be put into a mtd_part_parser_data. This way, code that sets up the
+platform devices can pass along the node from DT so that the partitions
+can be parsed.
+
+For non-DT boards, this change has no effect.
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Acked-by: Artem Bityutskiy <dedekind1@gmail.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+ drivers/mtd/nand/omap2.c | 4 +++-
+ include/linux/platform_data/mtd-nand-omap2.h | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
+index 0002d5e..1d333497c 100644
+--- a/drivers/mtd/nand/omap2.c
++++ b/drivers/mtd/nand/omap2.c
+@@ -1332,6 +1332,7 @@ static int omap_nand_probe(struct platform_device *pdev)
+ dma_cap_mask_t mask;
+ unsigned sig;
+ struct resource *res;
++ struct mtd_part_parser_data ppdata = {};
+
+ pdata = pdev->dev.platform_data;
+ if (pdata == NULL) {
+@@ -1557,7 +1558,8 @@ static int omap_nand_probe(struct platform_device *pdev)
+ goto out_release_mem_region;
+ }
+
+- mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts,
++ ppdata.of_node = pdata->of_node;
++ mtd_device_parse_register(&info->mtd, NULL, &ppdata, pdata->parts,
+ pdata->nr_parts);
+
+ platform_set_drvdata(pdev, &info->mtd);
+diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
+index 24d32ca..6bf9ef4 100644
+--- a/include/linux/platform_data/mtd-nand-omap2.h
++++ b/include/linux/platform_data/mtd-nand-omap2.h
+@@ -60,6 +60,8 @@ struct omap_nand_platform_data {
+ int devsize;
+ enum omap_ecc ecc_opt;
+ struct gpmc_nand_regs reg;
+-};
+
++ /* for passing the partitions */
++ struct device_node *of_node;
++};
+ #endif
diff --git a/patches/linux-3.8.13/0499-ARM-OMAP-gpmc-nand-drop-__init-annotation.patch b/patches/linux-3.8.13/0499-ARM-OMAP-gpmc-nand-drop-__init-annotation.patch
new file mode 100644
index 0000000..9fd276d
--- /dev/null
+++ b/patches/linux-3.8.13/0499-ARM-OMAP-gpmc-nand-drop-__init-annotation.patch
@@ -0,0 +1,39 @@
+From: Daniel Mack <zonque@gmail.com>
+Date: Fri, 14 Dec 2012 11:36:42 +0100
+Subject: [PATCH] ARM: OMAP: gpmc-nand: drop __init annotation
+
+gpmc_nand_init() will be called from another driver's probe() function,
+so the easiest way to prevent section mismatches is to drop the
+annotation here.
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/gpmc-nand.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
+index 026785c..b966784 100644
+--- a/arch/arm/mach-omap2/gpmc-nand.c
++++ b/arch/arm/mach-omap2/gpmc-nand.c
+@@ -81,7 +81,7 @@ static int omap2_nand_gpmc_retime(
+ return 0;
+ }
+
+-static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
++static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
+ {
+ /* support only OMAP3 class */
+ if (!cpu_is_omap34xx()) {
+@@ -102,8 +102,8 @@ static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
+ return 1;
+ }
+
+-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+- struct gpmc_timings *gpmc_t)
++int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
++ struct gpmc_timings *gpmc_t)
+ {
+ int err = 0;
+ struct gpmc_settings s;
diff --git a/patches/linux-3.8.13/0500-ARM-OMAP-gpmc-enable-hwecc-for-AM33xx-SoCs.patch b/patches/linux-3.8.13/0500-ARM-OMAP-gpmc-enable-hwecc-for-AM33xx-SoCs.patch
new file mode 100644
index 0000000..39b082a
--- /dev/null
+++ b/patches/linux-3.8.13/0500-ARM-OMAP-gpmc-enable-hwecc-for-AM33xx-SoCs.patch
@@ -0,0 +1,41 @@
+From: Daniel Mack <zonque@gmail.com>
+Date: Fri, 14 Dec 2012 11:36:43 +0100
+Subject: [PATCH] ARM: OMAP: gpmc: enable hwecc for AM33xx SoCs
+
+The am33xx is capable of handling bch error correction modes, so
+enable that feature in the driver.
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/gpmc-nand.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
+index b966784..d9c2719 100644
+--- a/arch/arm/mach-omap2/gpmc-nand.c
++++ b/arch/arm/mach-omap2/gpmc-nand.c
+@@ -84,17 +84,18 @@ static int omap2_nand_gpmc_retime(
+ static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
+ {
+ /* support only OMAP3 class */
+- if (!cpu_is_omap34xx()) {
++ if (!cpu_is_omap34xx() && !soc_is_am33xx()) {
+ pr_err("BCH ecc is not supported on this CPU\n");
+ return 0;
+ }
+
+ /*
+- * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1.
+- * Other chips may be added if confirmed to work.
++ * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1
++ * and AM33xx derivates. Other chips may be added if confirmed to work.
+ */
+ if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) &&
+- (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) {
++ (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0)) &&
++ (!soc_is_am33xx())) {
+ pr_err("BCH 4-bit mode is not supported on this CPU\n");
+ return 0;
+ }
diff --git a/patches/linux-3.8.13/0501-ARM-OMAP-gpmc-don-t-create-devices-from-initcall-on-.patch b/patches/linux-3.8.13/0501-ARM-OMAP-gpmc-don-t-create-devices-from-initcall-on-.patch
new file mode 100644
index 0000000..57af696
--- /dev/null
+++ b/patches/linux-3.8.13/0501-ARM-OMAP-gpmc-don-t-create-devices-from-initcall-on-.patch
@@ -0,0 +1,32 @@
+From: Daniel Mack <zonque@gmail.com>
+Date: Fri, 14 Dec 2012 11:36:40 +0100
+Subject: [PATCH] ARM: OMAP: gpmc: don't create devices from initcall on DT
+
+On DT driven boards, the gpmc node will match the driver. Hence, there's
+no need to do that unconditionally from the initcall.
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 52c32c9..de43b61 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -1676,6 +1676,13 @@ static int __init omap_gpmc_init(void)
+ struct platform_device *pdev;
+ char *oh_name = "gpmc";
+
++ /*
++ * if the board boots up with a populated DT, do not
++ * manually add the device from this initcall
++ */
++ if (of_have_populated_dt())
++ return -ENODEV;
++
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh) {
+ pr_err("Could not look up %s\n", oh_name);
diff --git a/patches/linux-3.8.13/0502-ARM-OMAP2-gpmc-onenand-drop-__init-annotation.patch b/patches/linux-3.8.13/0502-ARM-OMAP2-gpmc-onenand-drop-__init-annotation.patch
new file mode 100644
index 0000000..c54bfd9
--- /dev/null
+++ b/patches/linux-3.8.13/0502-ARM-OMAP2-gpmc-onenand-drop-__init-annotation.patch
@@ -0,0 +1,26 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Fri, 25 Jan 2013 09:23:10 -0300
+Subject: [PATCH] ARM: OMAP2+: gpmc-onenand: drop __init annotation
+
+gpmc_onenand_init() will be called from another driver's probe() function,
+so drop the __init annotation, in order to prevent section mismatches.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index 1a2b84e..3df9230 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -354,7 +354,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
+ return ret;
+ }
+
+-void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
++void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+ {
+ int err;
+ struct device *dev = &gpmc_onenand_device.dev;
diff --git a/patches/linux-3.8.13/0503-gpmc-Add-missing-gpmc-includes.patch b/patches/linux-3.8.13/0503-gpmc-Add-missing-gpmc-includes.patch
new file mode 100644
index 0000000..e205028
--- /dev/null
+++ b/patches/linux-3.8.13/0503-gpmc-Add-missing-gpmc-includes.patch
@@ -0,0 +1,22 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 23 Apr 2013 20:14:46 +0300
+Subject: [PATCH] gpmc: Add missing gpmc includes.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index de43b61..6f9fb7a 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -39,6 +39,8 @@
+ #include "common.h"
+ #include "omap_device.h"
+ #include "gpmc.h"
++#include "gpmc-nand.h"
++#include "gpmc-onenand.h"
+
+ #define DEVICE_NAME "omap-gpmc"
+
diff --git a/patches/linux-3.8.13/0504-mtd-omap-onenand-pass-device_node-in-platform-data.patch b/patches/linux-3.8.13/0504-mtd-omap-onenand-pass-device_node-in-platform-data.patch
new file mode 100644
index 0000000..a6f1782
--- /dev/null
+++ b/patches/linux-3.8.13/0504-mtd-omap-onenand-pass-device_node-in-platform-data.patch
@@ -0,0 +1,54 @@
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Fri, 25 Jan 2013 09:23:09 -0300
+Subject: [PATCH] mtd: omap-onenand: pass device_node in platform data
+
+Pass an optional device_node pointer in the platform data,
+which in turn will be put into a mtd_part_parser_data.
+This way, code that sets up the platform devices can pass
+along the node from DT so that the partitions can be parsed.
+
+For non-DT boards, this change has no effect.
+
+Acked-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+---
+ drivers/mtd/onenand/omap2.c | 4 +++-
+ include/linux/platform_data/mtd-onenand-omap2.h | 3 +++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
+index 065f3fe..eec2aed 100644
+--- a/drivers/mtd/onenand/omap2.c
++++ b/drivers/mtd/onenand/omap2.c
+@@ -637,6 +637,7 @@ static int omap2_onenand_probe(struct platform_device *pdev)
+ struct onenand_chip *this;
+ int r;
+ struct resource *res;
++ struct mtd_part_parser_data ppdata = {};
+
+ pdata = pdev->dev.platform_data;
+ if (pdata == NULL) {
+@@ -767,7 +768,8 @@ static int omap2_onenand_probe(struct platform_device *pdev)
+ if ((r = onenand_scan(&c->mtd, 1)) < 0)
+ goto err_release_regulator;
+
+- r = mtd_device_parse_register(&c->mtd, NULL, NULL,
++ ppdata.of_node = pdata->of_node;
++ r = mtd_device_parse_register(&c->mtd, NULL, &ppdata,
+ pdata ? pdata->parts : NULL,
+ pdata ? pdata->nr_parts : 0);
+ if (r)
+diff --git a/include/linux/platform_data/mtd-onenand-omap2.h b/include/linux/platform_data/mtd-onenand-omap2.h
+index 685af7e..e9a9fb1 100644
+--- a/include/linux/platform_data/mtd-onenand-omap2.h
++++ b/include/linux/platform_data/mtd-onenand-omap2.h
+@@ -29,5 +29,8 @@ struct omap_onenand_platform_data {
+ u8 flags;
+ u8 regulator_can_sleep;
+ u8 skip_initial_unlocking;
++
++ /* for passing the partitions */
++ struct device_node *of_node;
+ };
+ #endif
diff --git a/patches/linux-3.8.13/0505-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch b/patches/linux-3.8.13/0505-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch
new file mode 100644
index 0000000..0d3179f
--- /dev/null
+++ b/patches/linux-3.8.13/0505-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch
@@ -0,0 +1,44 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Thu, 21 Feb 2013 12:42:22 -0600
+Subject: [PATCH] ARM: OMAP2+: Convert ONENAND to use
+ gpmc_cs_program_settings()
+
+Convert the OMAP2+ ONENAND code to use the gpmc_cs_program_settings()
+function for configuring the various GPMC options instead of directly
+programming the CONFIG1 register.
+
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+
+Conflicts:
+ arch/arm/mach-omap2/gpmc-onenand.c
+---
+ arch/arm/mach-omap2/gpmc-onenand.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
+index 3df9230..64b5a83 100644
+--- a/arch/arm/mach-omap2/gpmc-onenand.c
++++ b/arch/arm/mach-omap2/gpmc-onenand.c
+@@ -284,8 +284,8 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
+ if (ret < 0)
+ return ret;
+
+- ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
+- if (IS_ERR_VALUE(ret))
++ ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
++ if (ret < 0)
+ return ret;
+
+ omap2_onenand_set_async_mode(onenand_base);
+@@ -322,8 +322,8 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
+ if (ret < 0)
+ return ret;
+
+- ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
+- if (IS_ERR_VALUE(ret))
++ ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
++ if (ret < 0)
+ return ret;
+
+ set_onenand_cfg(onenand_base);
diff --git a/patches/linux-3.8.13/0506-omap-gpmc-Various-driver-fixes.patch b/patches/linux-3.8.13/0506-omap-gpmc-Various-driver-fixes.patch
new file mode 100644
index 0000000..e862db3
--- /dev/null
+++ b/patches/linux-3.8.13/0506-omap-gpmc-Various-driver-fixes.patch
@@ -0,0 +1,203 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 26 Apr 2013 01:21:49 +0300
+Subject: [PATCH] omap: gpmc: Various driver fixes
+
+Various fixes:
+
+* clk_activation option added
+* pinctrl support add
+* Add camera device
+* Fix child node handling
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/gpmc.c | 94 +++++++++++++++++++++++---------------------
+ arch/arm/mach-omap2/gpmc.h | 1 +
+ 2 files changed, 51 insertions(+), 44 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
+index 6f9fb7a..993cb5e 100644
+--- a/arch/arm/mach-omap2/gpmc.c
++++ b/arch/arm/mach-omap2/gpmc.c
+@@ -30,6 +30,7 @@
+ #include <linux/of_mtd.h>
+ #include <linux/of_device.h>
+ #include <linux/mtd/nand.h>
++#include <linux/pinctrl/consumer.h>
+
+ #include <linux/platform_data/mtd-nand-omap2.h>
+
+@@ -1213,6 +1214,8 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
+ config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+ config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+ }
++ if (p->clk_activation)
++ config1 |= GPMC_CONFIG1_CLKACTIVATIONTIME(p->clk_activation);
+
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
+
+@@ -1249,6 +1252,7 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
+ p->device_nand = of_property_read_bool(np, "gpmc,device-nand");
+ of_property_read_u32(np, "gpmc,device-width", &p->device_width);
+ of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
++ of_property_read_u32(np, "gpmc,clk-activation", &p->clk_activation);
+
+ if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
+ p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap");
+@@ -1464,30 +1468,40 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
+ return ret;
+ }
+
+- /*
+- * FIXME: gpmc_cs_request() will map the CS to an arbitary
+- * location in the gpmc address space. When booting with
+- * device-tree we want the NOR flash to be mapped to the
+- * location specified in the device-tree blob. So remap the
+- * CS to this location. Once DT migration is complete should
+- * just make gpmc_cs_request() map a specific address.
+- */
+- ret = gpmc_cs_remap(cs, res.start);
+- if (ret < 0) {
+- dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
+- cs, res.start);
+- goto err;
++ if (!of_property_read_bool(child, "gpmc,no-remap")) {
++ /*
++ * FIXME: gpmc_cs_request() will map the CS to an arbitary
++ * location in the gpmc address space. When booting with
++ * device-tree we want the NOR flash to be mapped to the
++ * location specified in the device-tree blob. So remap the
++ * CS to this location. Once DT migration is complete should
++ * just make gpmc_cs_request() map a specific address.
++ */
++ ret = gpmc_cs_remap(cs, res.start);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
++ cs, res.start);
++ goto err;
++ }
++
++ dev_info(&pdev->dev, "GPMC%d: res.start=0x%x\n", cs, (unsigned int)res.start);
+ }
+
+ gpmc_read_settings_dt(child, &gpmc_s);
+
+ ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+- if (ret < 0)
++ if (ret < 0) {
++ dev_err(&pdev->dev, "%s has no 'bank-width' property\n",
++ child->full_name);
+ goto err;
++ }
+
+ ret = gpmc_cs_program_settings(cs, &gpmc_s);
+- if (ret < 0)
++ if (ret < 0) {
++ dev_err(&pdev->dev, "%s failed to program settings\n",
++ child->full_name);
+ goto err;
++ }
+
+ gpmc_read_timings_dt(child, &gpmc_t);
+ gpmc_cs_set_timings(cs, &gpmc_t);
+@@ -1507,46 +1521,31 @@ err:
+ static int gpmc_probe_dt(struct platform_device *pdev)
+ {
+ int ret;
++ struct device_node *node = pdev->dev.of_node;
+ struct device_node *child;
+- const struct of_device_id *of_id =
+- of_match_device(gpmc_dt_ids, &pdev->dev);
+-
+- if (!of_id)
+- return 0;
+
+- ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
++ ret = of_property_read_u32(node, "gpmc,num-waitpins",
+ &gpmc_nr_waitpins);
+ if (ret < 0) {
+ pr_err("%s: number of wait pins not found!\n", __func__);
+ return ret;
+ }
+
+- for_each_node_by_name(child, "nand") {
+- ret = gpmc_probe_nand_child(pdev, child);
+- if (ret < 0) {
+- of_node_put(child);
+- return ret;
+- }
+- }
++ for_each_available_child_of_node(node, child) {
+
+- for_each_node_by_name(child, "onenand") {
+- ret = gpmc_probe_onenand_child(pdev, child);
+- if (ret < 0) {
+- of_node_put(child);
+- return ret;
+- }
+- }
++ if (!child->name)
++ continue;
+
+- for_each_node_by_name(child, "nor") {
+- ret = gpmc_probe_generic_child(pdev, child);
+- if (ret < 0) {
+- of_node_put(child);
+- return ret;
+- }
+- }
++ ret = 0;
++ if (of_node_cmp(child->name, "nand") == 0)
++ ret = gpmc_probe_nand_child(pdev, child);
++ else if (of_node_cmp(child->name, "onenand") == 0)
++ ret = gpmc_probe_onenand_child(pdev, child);
++ else if (of_node_cmp(child->name, "nor") == 0 ||
++ of_node_cmp(child->name, "ethernet") == 0 ||
++ of_node_cmp(child->name, "camera") == 0)
++ ret = gpmc_probe_generic_child(pdev, child);
+
+- for_each_node_by_name(child, "ethernet") {
+- ret = gpmc_probe_generic_child(pdev, child);
+ if (ret < 0) {
+ of_node_put(child);
+ return ret;
+@@ -1567,6 +1566,11 @@ static int gpmc_probe(struct platform_device *pdev)
+ int rc;
+ u32 l;
+ struct resource *res;
++ struct pinctrl *pinctrl;
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+@@ -1637,6 +1641,7 @@ static int gpmc_probe(struct platform_device *pdev)
+ dev_err(gpmc_dev, "failed to probe DT parameters\n");
+ return rc;
+ }
++ dev_info(gpmc_dev, "loaded OK\n");
+
+ return 0;
+ }
+@@ -1655,6 +1660,7 @@ static struct platform_driver gpmc_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(gpmc_dt_ids),
+ },
+ };
+
+diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
+index 707f6d5..b329bb8 100644
+--- a/arch/arm/mach-omap2/gpmc.h
++++ b/arch/arm/mach-omap2/gpmc.h
+@@ -205,6 +205,7 @@ struct gpmc_settings {
+ u32 device_width; /* device bus width (8 or 16 bit) */
+ u32 mux_add_data; /* multiplex address & data */
+ u32 wait_pin; /* wait-pin to be used */
++ u32 clk_activation; /* clock activation time */
+ };
+
+ extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
diff --git a/patches/linux-3.8.13/0507-gpmc-Add-DT-node-for-gpmc-on-am33xx.patch b/patches/linux-3.8.13/0507-gpmc-Add-DT-node-for-gpmc-on-am33xx.patch
new file mode 100644
index 0000000..76f7476
--- /dev/null
+++ b/patches/linux-3.8.13/0507-gpmc-Add-DT-node-for-gpmc-on-am33xx.patch
@@ -0,0 +1,35 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 18:38:25 +0300
+Subject: [PATCH] gpmc: Add DT node for gpmc on am33xx
+
+Add am33xx gpmc device.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 6c24c9b..76fa03b 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -399,6 +399,19 @@
+
+ };
+
++ gpmc: gpmc@50000000 {
++ compatible = "ti,am3352-gpmc";
++ ti,hwmods = "gpmc";
++ reg = <0x50000000 0x01000000>;
++ interrupts = <100>;
++ gpmc,num-cs = <7>;
++ gpmc,num-waitpins = <2>;
++ #address-cells = <2>;
++ #size-cells = <1>;
++
++ status = "disabled";
++ };
++
+ nop-phy@0 {
+ compatible = "nop-xceiv-usb";
+ };
diff --git a/patches/linux-3.8.13/0508-CHROMIUM-Input-atmel_mxt_ts-refactor-i2c-error-handl.patch b/patches/linux-3.8.13/0508-CHROMIUM-Input-atmel_mxt_ts-refactor-i2c-error-handl.patch
new file mode 100644
index 0000000..24d0ae0
--- /dev/null
+++ b/patches/linux-3.8.13/0508-CHROMIUM-Input-atmel_mxt_ts-refactor-i2c-error-handl.patch
@@ -0,0 +1,163 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Wed, 19 Dec 2012 17:22:16 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - refactor i2c error handling
+
+A recent patch refactored i2c error handling in the register read/write
+path. This adds similar handling to the other i2c paths used in fw_update
+and bootloader state detection.
+
+The generic i2c layer can return values indicating a partial transaction.
+From the atmel_mxt driver's perspective, this is an IO error, so we use
+some helper functions to convert these partial transfers to -EIO in a
+uniform way. Other error codes might still be useful, though, so we pass
+them up unmodified.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+Change-Id: I59eabbb80dea610a89c01a3be06f0d165f4b4431
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 92 ++++++++++++++++++------------
+ 1 file changed, 54 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index d04f810..a222bd8 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -324,16 +324,62 @@ static void mxt_dump_message(struct device *dev,
+ message->reportid, 7, message->message);
+ }
+
++static int mxt_i2c_recv(struct i2c_client *client, u8 *buf, size_t count)
++{
++ int ret;
++
++ ret = i2c_master_recv(client, buf, count);
++ if (ret == count) {
++ ret = 0;
++ } else if (ret != count) {
++ ret = (ret < 0) ? ret : -EIO;
++ dev_err(&client->dev, "i2c recv failed (%d)\n", ret);
++ }
++
++ return ret;
++}
++
++static int mxt_i2c_send(struct i2c_client *client, const u8 *buf, size_t count)
++{
++ int ret;
++
++ ret = i2c_master_send(client, buf, count);
++ if (ret == count) {
++ ret = 0;
++ } else if (ret != count) {
++ ret = (ret < 0) ? ret : -EIO;
++ dev_err(&client->dev, "i2c send failed (%d)\n", ret);
++ }
++
++ return ret;
++}
++
++static int mxt_i2c_transfer(struct i2c_client *client, struct i2c_msg *msgs,
++ size_t count)
++{
++ int ret;
++
++ ret = i2c_transfer(client->adapter, msgs, count);
++ if (ret == count) {
++ ret = 0;
++ } else {
++ ret = (ret < 0) ? ret : -EIO;
++ dev_err(&client->dev, "i2c transfer failed (%d)\n", ret);
++ }
++
++ return ret;
++}
++
+ static int mxt_check_bootloader(struct i2c_client *client,
+ unsigned int state)
+ {
+ u8 val;
++ int ret;
+
+ recheck:
+- if (i2c_master_recv(client, &val, 1) != 1) {
+- dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
+- return -EIO;
+- }
++ ret = mxt_i2c_recv(client, &val, 1);
++ if (ret)
++ return ret;
+
+ switch (state) {
+ case MXT_WAITING_BOOTLOAD_CMD:
+@@ -363,23 +409,13 @@ static int mxt_unlock_bootloader(struct i2c_client *client)
+ buf[0] = MXT_UNLOCK_CMD_LSB;
+ buf[1] = MXT_UNLOCK_CMD_MSB;
+
+- if (i2c_master_send(client, buf, 2) != 2) {
+- dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+- return -EIO;
+- }
+-
+- return 0;
++ return mxt_i2c_send(client, buf, 2);
+ }
+
+ static int mxt_fw_write(struct i2c_client *client,
+ const u8 *data, unsigned int frame_size)
+ {
+- if (i2c_master_send(client, data, frame_size) != frame_size) {
+- dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+- return -EIO;
+- }
+-
+- return 0;
++ return mxt_i2c_send(client, data, frame_size);
+ }
+
+ static int __mxt_read_reg(struct i2c_client *client,
+@@ -387,7 +423,6 @@ static int __mxt_read_reg(struct i2c_client *client,
+ {
+ struct i2c_msg xfer[2];
+ u8 buf[2];
+- int ret;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+@@ -404,17 +439,7 @@ static int __mxt_read_reg(struct i2c_client *client,
+ xfer[1].len = len;
+ xfer[1].buf = val;
+
+- ret = i2c_transfer(client->adapter, xfer, 2);
+- if (ret == 2) {
+- ret = 0;
+- } else {
+- if (ret >= 0)
+- ret = -EIO;
+- dev_err(&client->dev, "%s: i2c transfer failed (%d)\n",
+- __func__, ret);
+- }
+-
+- return ret;
++ return mxt_i2c_transfer(client, xfer, 2);
+ }
+
+ static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
+@@ -438,16 +463,7 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
+ buf[1] = (reg >> 8) & 0xff;
+ memcpy(&buf[2], val, len);
+
+- ret = i2c_master_send(client, buf, count);
+- if (ret == count) {
+- ret = 0;
+- } else {
+- if (ret >= 0)
+- ret = -EIO;
+- dev_err(&client->dev, "%s: i2c send failed (%d)\n",
+- __func__, ret);
+- }
+-
++ ret = mxt_i2c_send(client, buf, count);
+ kfree(buf);
+ return ret;
+ }
diff --git a/patches/linux-3.8.13/0509-CHROMIUM-Input-atmel_mxt_ts-register-input-device-be.patch b/patches/linux-3.8.13/0509-CHROMIUM-Input-atmel_mxt_ts-register-input-device-be.patch
new file mode 100644
index 0000000..5a0fd3d
--- /dev/null
+++ b/patches/linux-3.8.13/0509-CHROMIUM-Input-atmel_mxt_ts-register-input-device-be.patch
@@ -0,0 +1,109 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Fri, 27 Apr 2012 22:08:52 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - register input device before
+ request_irq
+
+As soon as the irq is request, input event interrupts could occur that
+the isr should handle. Similarly, if there are input events queued up
+in the device output buffer, it will send them immediately when we
+drain the message buffer with mxt_handle_messages.
+
+Therefore, register the input device before enabling the irq (or handling
+messages).
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=cat /sys/bus/i2c/drivers/atmel_mxt_ts/2-004b/object
+
+Change-Id: I16172901d963cd2e60533e12e455012cb62cdfe5
+Reviewed-on: https://gerrit.chromium.org/gerrit/21061
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+[djkurtz: v3.8 rebase]
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 32 +++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index a222bd8..84f0408 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1124,8 +1124,13 @@ static int mxt_probe(struct i2c_client *client,
+ return -EINVAL;
+
+ data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
++ if (!data) {
++ dev_err(&client->dev, "Failed to allocate memory\n");
++ return -ENOMEM;
++ }
++
+ input_dev = input_allocate_device();
+- if (!data || !input_dev) {
++ if (!input_dev) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ error = -ENOMEM;
+ goto err_free_mem;
+@@ -1167,8 +1172,11 @@ static int mxt_probe(struct i2c_client *client,
+ /* For multi touch */
+ num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
+ error = input_mt_init_slots(input_dev, num_mt_slots, 0);
+- if (error)
++ if (error) {
++ input_free_device(input_dev);
+ goto err_free_object;
++ }
++
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, MXT_MAX_AREA, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+@@ -1181,37 +1189,37 @@ static int mxt_probe(struct i2c_client *client,
+ input_set_drvdata(input_dev, data);
+ i2c_set_clientdata(client, data);
+
++ error = input_register_device(input_dev);
++ if (error) {
++ input_free_device(input_dev);
++ goto err_free_object;
++ }
++
+ error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+ pdata->irqflags | IRQF_ONESHOT,
+ client->name, data);
+ if (error) {
+ dev_err(&client->dev, "Failed to register interrupt\n");
+- goto err_free_object;
++ goto err_unregister_device;
+ }
+
+ error = mxt_make_highchg(data);
+ if (error)
+ goto err_free_irq;
+
+- error = input_register_device(input_dev);
+- if (error)
+- goto err_free_irq;
+-
+ error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
+ if (error)
+- goto err_unregister_device;
++ goto err_free_irq;
+
+ return 0;
+
+-err_unregister_device:
+- input_unregister_device(input_dev);
+- input_dev = NULL;
+ err_free_irq:
+ free_irq(client->irq, data);
++err_unregister_device:
++ input_unregister_device(data->input_dev);
+ err_free_object:
+ kfree(data->object_table);
+ err_free_mem:
+- input_free_device(input_dev);
+ kfree(data);
+ return error;
+ }
diff --git a/patches/linux-3.8.13/0510-CHROMIUM-Input-atmel_mxt_ts-refactor-input-device-cr.patch b/patches/linux-3.8.13/0510-CHROMIUM-Input-atmel_mxt_ts-refactor-input-device-cr.patch
new file mode 100644
index 0000000..d5548bd
--- /dev/null
+++ b/patches/linux-3.8.13/0510-CHROMIUM-Input-atmel_mxt_ts-refactor-input-device-cr.patch
@@ -0,0 +1,157 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Fri, 27 Apr 2012 22:15:16 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - refactor input device
+ creation
+
+Move input device initialization to its own helper function.
+This is in preparation of a future patch that makes input device
+conditional on the device not being in its bootloader.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=builds clean; input device created as before.
+
+Change-Id: Ife128dc63a4c23c162ed116c21cc0dd3d076a559
+Reviewed-on: https://gerrit.chromium.org/gerrit/20844
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+[djkurtz: v3.8-rc3 rebase]
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 91 ++++++++++++++++--------------
+ 1 file changed, 50 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 84f0408..9afc26e 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1111,52 +1111,23 @@ static void mxt_input_close(struct input_dev *dev)
+ mxt_stop(data);
+ }
+
+-static int mxt_probe(struct i2c_client *client,
+- const struct i2c_device_id *id)
++static int mxt_input_dev_create(struct mxt_data *data)
+ {
+- const struct mxt_platform_data *pdata = client->dev.platform_data;
+- struct mxt_data *data;
+ struct input_dev *input_dev;
+ int error;
+ unsigned int num_mt_slots;
+
+- if (!pdata)
+- return -EINVAL;
+-
+- data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+- if (!data) {
+- dev_err(&client->dev, "Failed to allocate memory\n");
++ data->input_dev = input_dev = input_allocate_device();
++ if (!input_dev)
+ return -ENOMEM;
+- }
+-
+- input_dev = input_allocate_device();
+- if (!input_dev) {
+- dev_err(&client->dev, "Failed to allocate memory\n");
+- error = -ENOMEM;
+- goto err_free_mem;
+- }
+
+ input_dev->name = "Atmel maXTouch Touchscreen";
+- snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
+- client->adapter->nr, client->addr);
+ input_dev->phys = data->phys;
+-
+ input_dev->id.bustype = BUS_I2C;
+- input_dev->dev.parent = &client->dev;
++ input_dev->dev.parent = &data->client->dev;
+ input_dev->open = mxt_input_open;
+ input_dev->close = mxt_input_close;
+
+- data->client = client;
+- data->input_dev = input_dev;
+- data->pdata = pdata;
+- data->irq = client->irq;
+-
+- mxt_calc_resolution(data);
+-
+- error = mxt_initialize(data);
+- if (error)
+- goto err_free_mem;
+-
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+@@ -1172,10 +1143,8 @@ static int mxt_probe(struct i2c_client *client,
+ /* For multi touch */
+ num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
+ error = input_mt_init_slots(input_dev, num_mt_slots, 0);
+- if (error) {
+- input_free_device(input_dev);
+- goto err_free_object;
+- }
++ if (error)
++ goto err_free_device;
+
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, MXT_MAX_AREA, 0, 0);
+@@ -1187,14 +1156,54 @@ static int mxt_probe(struct i2c_client *client,
+ 0, 255, 0, 0);
+
+ input_set_drvdata(input_dev, data);
+- i2c_set_clientdata(client, data);
+
+ error = input_register_device(input_dev);
+- if (error) {
+- input_free_device(input_dev);
+- goto err_free_object;
++ if (error)
++ goto err_free_device;
++
++ return 0;
++
++err_free_device:
++ input_free_device(data->input_dev);
++ data->input_dev = NULL;
++ return error;
++}
++
++static int __devinit mxt_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ const struct mxt_platform_data *pdata = client->dev.platform_data;
++ struct mxt_data *data;
++ int error;
++
++ if (!pdata)
++ return -EINVAL;
++
++ data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
++ if (!data) {
++ dev_err(&client->dev, "Failed to allocate memory\n");
++ return -ENOMEM;
+ }
+
++ snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
++ client->adapter->nr, client->addr);
++
++ data->client = client;
++ i2c_set_clientdata(client, data);
++
++ data->pdata = pdata;
++ data->irq = client->irq;
++
++ mxt_calc_resolution(data);
++
++ error = mxt_initialize(data);
++ if (error)
++ goto err_free_mem;
++
++ error = mxt_input_dev_create(data);
++ if (error)
++ goto err_free_object;
++
+ error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+ pdata->irqflags | IRQF_ONESHOT,
+ client->name, data);
diff --git a/patches/linux-3.8.13/0511-CHROMIUM-Input-atmel_mxt_ts-handle-bootloader-mode-a.patch b/patches/linux-3.8.13/0511-CHROMIUM-Input-atmel_mxt_ts-handle-bootloader-mode-a.patch
new file mode 100644
index 0000000..d623a68
--- /dev/null
+++ b/patches/linux-3.8.13/0511-CHROMIUM-Input-atmel_mxt_ts-handle-bootloader-mode-a.patch
@@ -0,0 +1,180 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Fri, 21 Dec 2012 09:26:54 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - handle bootloader mode at
+ probe
+
+In some cases it is possible for a device to be in its bootloader at
+driver probe time. This is detected by the driver when probe() is called
+with an i2c_client which has one of the Atmel Bootloader i2c addresses.
+
+In this case, we should load enough driver functionality to still loading
+new firmware using:
+ echo 1 > update_fw
+
+However, we must be very careful not to follow any code paths that would try
+to access the as-yet uninitialized object table or input device.
+In particular:
+ 1) mxt_remove calls input_unregister_device on input_dev.
+ 2) mxt_suspend/resume reads and writes from the object table.
+ 3) Spurious or bootloader induced interrupts
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:8733, chrome-os-partner:16507
+TEST=Interrupt a firmware update. Boot the system. Ensure
+ that the atmel_mxt_ts driver brings up the device using one of
+ the two MXT_BOOT i2c addresses. From there, it should be possible
+ to echo 1 > update_fw and recover.
+TEST=First, get the touch device into a bad state by doing the following:
+ 1. Modify chromeos/config/base.config and set CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+ 2. Build, boot this kernel, and make sure that the touch device works.
+ 3. /opt/google/touch/firmware/chromeos-touch-firmwareupdate.sh \
+ -d atmel_mxt_ts -n maxtouch-ts.fw -f
+ 4. Before it can finish, CTRL-C to interrupt the firmware update.
+ This will ensure that the touch device is stuck in bootloader mode.
+TEST=No crash on mxt_remove:
+ 1. rmmod atmel_mxt_ts
+ 2. check that the system does not reboot.
+ 3. modprobe chromeos_mxt_ts
+TEST=No crash on suspend/resume:
+ 1. Close the lid to suspend the system.
+ 2. Open the lid to suspend the system.
+ 3. Check that the system did not reboot.
+
+Original-Change-Id: If86e6f0065bb24a5da340ac69adca4ac61d675c9
+Reviewed-on: https://gerrit.chromium.org/gerrit/19637
+Original-Change-Id: I83e517d21738cb75d0c2b0ab8bf16398044e52f3
+Reviewed-on: https://gerrit.chromium.org/gerrit/39022
+Reviewed-by: Yufeng Shen <miletus@chromium.org>
+Commit-Ready: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+Change-Id: I2b65ec6cc3c9506372499785f4f8599faf4aa353
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 51 +++++++++++++++++++++++-------
+ 1 file changed, 40 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 9afc26e..6c2c712 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -324,6 +324,12 @@ static void mxt_dump_message(struct device *dev,
+ message->reportid, 7, message->message);
+ }
+
++static bool mxt_in_bootloader(struct mxt_data *data)
++{
++ struct i2c_client *client = data->client;
++ return (client->addr == MXT_BOOT_LOW || client->addr == MXT_BOOT_HIGH);
++}
++
+ static int mxt_i2c_recv(struct i2c_client *client, u8 *buf, size_t count)
+ {
+ int ret;
+@@ -584,6 +590,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+ u8 reportid;
+ bool update_input = false;
+
++ if (mxt_in_bootloader(data))
++ goto end;
++
+ do {
+ if (mxt_read_message(data, &message)) {
+ dev_err(dev, "Failed to read message\n");
+@@ -975,6 +984,9 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ return ret;
+ }
+
++ if (mxt_in_bootloader(data))
++ goto bootloader_ready;
++
+ /* Change to the bootloader mode */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+@@ -986,6 +998,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ else
+ client->addr = MXT_BOOT_HIGH;
+
++bootloader_ready:
+ ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
+ if (ret)
+ goto out;
+@@ -1196,25 +1209,34 @@ static int __devinit mxt_probe(struct i2c_client *client,
+
+ mxt_calc_resolution(data);
+
+- error = mxt_initialize(data);
+- if (error)
+- goto err_free_mem;
++ if (mxt_in_bootloader(data)) {
++ dev_info(&client->dev, "Device in bootloader at probe\n");
++ } else {
++ error = mxt_initialize(data);
++ if (error)
++ goto err_free_mem;
+
+- error = mxt_input_dev_create(data);
+- if (error)
+- goto err_free_object;
++ error = mxt_input_dev_create(data);
++ if (error)
++ goto err_free_object;
++ }
+
+ error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+ pdata->irqflags | IRQF_ONESHOT,
+ client->name, data);
+ if (error) {
+ dev_err(&client->dev, "Failed to register interrupt\n");
+- goto err_unregister_device;
++ if (mxt_in_bootloader(data))
++ goto err_free_mem;
++ else
++ goto err_unregister_device;
+ }
+
+- error = mxt_make_highchg(data);
+- if (error)
+- goto err_free_irq;
++ if (!mxt_in_bootloader(data)) {
++ error = mxt_make_highchg(data);
++ if (error)
++ goto err_free_irq;
++ }
+
+ error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
+ if (error)
+@@ -1239,7 +1261,8 @@ static int mxt_remove(struct i2c_client *client)
+
+ sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+ free_irq(data->irq, data);
+- input_unregister_device(data->input_dev);
++ if (data->input_dev)
++ input_unregister_device(data->input_dev);
+ kfree(data->object_table);
+ kfree(data);
+
+@@ -1253,6 +1276,9 @@ static int mxt_suspend(struct device *dev)
+ struct mxt_data *data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = data->input_dev;
+
++ if (mxt_in_bootloader(data))
++ return 0;
++
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users)
+@@ -1269,6 +1295,9 @@ static int mxt_resume(struct device *dev)
+ struct mxt_data *data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = data->input_dev;
+
++ if (mxt_in_bootloader(data))
++ return 0;
++
+ /* Soft reset */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_RESET, 1);
diff --git a/patches/linux-3.8.13/0512-CHROMIUM-Input-atmel_mxt_ts-handle-errors-during-fw-.patch b/patches/linux-3.8.13/0512-CHROMIUM-Input-atmel_mxt_ts-handle-errors-during-fw-.patch
new file mode 100644
index 0000000..2efb4bd
--- /dev/null
+++ b/patches/linux-3.8.13/0512-CHROMIUM-Input-atmel_mxt_ts-handle-errors-during-fw-.patch
@@ -0,0 +1,74 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Thu, 20 Dec 2012 23:16:35 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - handle errors during fw
+ update
+
+If there are any (i2c) errors during fw update, abort the update, but
+leave the i2c address assigned to the bootloader address.
+
+Note that an error when trying to reset the device into the bootloader
+will leave the i2c address assigned to the application address.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+Change-Id: I2933505115dd55aa4dcf07e333f0e1d56e9e246e
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 6c2c712..76a25d3 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -988,8 +988,10 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ goto bootloader_ready;
+
+ /* Change to the bootloader mode */
+- mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_RESET, MXT_BOOT_VALUE);
++ if (ret)
++ goto out;
+ msleep(MXT_RESET_TIME);
+
+ /* Change to slave address of bootloader */
+@@ -1004,7 +1006,9 @@ bootloader_ready:
+ goto out;
+
+ /* Unlock bootloader */
+- mxt_unlock_bootloader(client);
++ ret = mxt_unlock_bootloader(client);
++ if (ret)
++ goto out;
+
+ while (pos < fw->size) {
+ ret = mxt_check_bootloader(client,
+@@ -1020,7 +1024,9 @@ bootloader_ready:
+ frame_size += 2;
+
+ /* Write one frame to device */
+- mxt_fw_write(client, fw->data + pos, frame_size);
++ ret = mxt_fw_write(client, fw->data + pos, frame_size);
++ if (ret)
++ goto out;
+
+ ret = mxt_check_bootloader(client,
+ MXT_FRAME_CRC_PASS);
+@@ -1032,14 +1038,13 @@ bootloader_ready:
+ dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+ }
+
+-out:
+- release_firmware(fw);
+-
+ /* Change to slave address of application */
+ if (client->addr == MXT_BOOT_LOW)
+ client->addr = MXT_APP_LOW;
+ else
+ client->addr = MXT_APP_HIGH;
++out:
++ release_firmware(fw);
+
+ return ret;
+ }
diff --git a/patches/linux-3.8.13/0513-CHROMIUM-Input-atmel_mxt_ts-destroy-state-before-fw-.patch b/patches/linux-3.8.13/0513-CHROMIUM-Input-atmel_mxt_ts-destroy-state-before-fw-.patch
new file mode 100644
index 0000000..7589f11
--- /dev/null
+++ b/patches/linux-3.8.13/0513-CHROMIUM-Input-atmel_mxt_ts-destroy-state-before-fw-.patch
@@ -0,0 +1,51 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Thu, 20 Dec 2012 23:38:08 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - destroy state before fw
+ update and restore after
+
+After firmware update, the device may have a completely different object
+table which corresponds to an input device with different properties.
+So, destroy the old state before firmware update, and completely
+reinitialize the driver afterward.
+
+Two benefits of this:
+ 1) Since there is no input device during fw update, no need to worry
+about device open/close events.
+ 2) If firmware update fails, the device and driver will still be in
+bootloader mode and an improperly configured input device will not exist.
+
+Change-Id: I42e6b946e2206b4957c313be00b9b45b9dd02b60
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 76a25d3..c74f5a5 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1001,6 +1001,13 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ client->addr = MXT_BOOT_HIGH;
+
+ bootloader_ready:
++ /* Free any driver state. It will get reinitialized after fw update. */
++ mxt_free_object_table(data);
++ if (data->input_dev) {
++ input_unregister_device(data->input_dev);
++ data->input_dev = NULL;
++ }
++
+ ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
+ if (ret)
+ goto out;
+@@ -1068,9 +1075,8 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ /* Wait for reset */
+ msleep(MXT_FWRESET_TIME);
+
+- mxt_free_object_table(data);
+-
+ mxt_initialize(data);
++ mxt_input_dev_create(data);
+ }
+
+ enable_irq(data->irq);
diff --git a/patches/linux-3.8.13/0514-CHROMIUM-Input-atmel_mxt_ts-refactor-bootloader-entr.patch b/patches/linux-3.8.13/0514-CHROMIUM-Input-atmel_mxt_ts-refactor-bootloader-entr.patch
new file mode 100644
index 0000000..7efd8ac
--- /dev/null
+++ b/patches/linux-3.8.13/0514-CHROMIUM-Input-atmel_mxt_ts-refactor-bootloader-entr.patch
@@ -0,0 +1,239 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Thu, 3 May 2012 13:57:46 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - refactor bootloader
+ entry/exit
+
+Refactor bootloading into a three parts:
+ 1) bl enter that only happens when device is not yet in bl.
+ bl enter frees old driver state and switches to BL i2c addr.
+ 2) the actual fw_update
+ 3) bl exit that only happens if fw update is successful.
+ bl exit switches to APP i2c addr and reloads object table and creates
+ a new input device.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:8716,chrome-os-partner:9103,chrome-os-partner:10688
+TEST=Place an firmware file at /lib/firmware/maxtouch.fw
+echo 1 > update_fw
+Ensure that a normal firmware update works.
+TEST=update the firmware and then check that the input device
+ is still working, by using evtest/xinput.
+TEST=The following instructions will write the wrong firmware to the
+touchpad device.
+1. cd /sys/bus/i2c/devices/1-004b
+2. echo maxtouch-ts.fw > fw_file
+3. echo 1 > update_fw
+4. dmesg | tail
+This will result in a failed touchpad update. Check that dmesg shows:
+[ 158.495164] atmel_mxt_ts 1-004b: bootloader version: 32
+[ 170.563491] atmel_mxt_ts 1-004b: mxt_read_reg: i2c read failed
+[ 170.563513] atmel_mxt_ts 1-004b: Failed to initialize on exit bl. error = -6
+Check that the system does not panic in this situation.
+
+To recover from this state, simply shut the machine down completely using
+sudo shutdown -P now
+
+Original-Change-Id: I49bf582be90ffc8c4dd2696413ceff060fd8926e
+Reviewed-on: https://gerrit.chromium.org/gerrit/21831
+Original-Change-Id: I2ec8b4c96954151495238c450301eddd48085e18
+Reviewed-on: https://gerrit.chromium.org/gerrit/23256
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Original-Change-Id: Ib773efd8b76aced9f5faab0b51745db7192e78f9
+Reviewed-on: https://gerrit.chromium.org/gerrit/37860
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 128 ++++++++++++++++++++----------
+ 1 file changed, 87 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index c74f5a5..be96be3 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -253,6 +253,11 @@ struct mxt_data {
+ u8 T9_reportid_max;
+ };
+
++static void mxt_free_object_table(struct mxt_data *data);
++static int mxt_initialize(struct mxt_data *data);
++static int mxt_input_dev_create(struct mxt_data *data);
++static int mxt_make_highchg(struct mxt_data *data);
++
+ static bool mxt_object_readable(unsigned int type)
+ {
+ switch (type) {
+@@ -402,6 +407,8 @@ recheck:
+
+ if (val != state) {
+ dev_err(&client->dev, "Unvalid bootloader mode state\n");
++ dev_err(&client->dev, "Invalid bootloader mode state %d, %d\n",
++ val, state);
+ return -EINVAL;
+ }
+
+@@ -581,6 +588,81 @@ static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
+ return (id >= data->T9_reportid_min && id <= data->T9_reportid_max);
+ }
+
++static int mxt_enter_bl(struct mxt_data *data)
++{
++ struct i2c_client *client = data->client;
++ int ret;
++
++ if (mxt_in_bootloader(data))
++ return 0;
++
++ disable_irq(data->irq);
++
++ /* Change to the bootloader mode */
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_RESET, MXT_BOOT_VALUE);
++ if (ret) {
++ enable_irq(data->irq);
++ return ret;
++ }
++
++ /* Change to slave address of bootloader */
++ if (client->addr == MXT_APP_LOW)
++ client->addr = MXT_BOOT_LOW;
++ else
++ client->addr = MXT_BOOT_HIGH;
++
++ /* Free any driver state. It will get reinitialized after fw update. */
++ mxt_free_object_table(data);
++ if (data->input_dev) {
++ input_unregister_device(data->input_dev);
++ data->input_dev = NULL;
++ }
++
++ enable_irq(data->irq);
++ msleep(MXT_RESET_TIME);
++ return 0;
++}
++
++static void mxt_exit_bl(struct mxt_data *data)
++{
++ struct i2c_client *client = data->client;
++ struct device *dev = &client->dev;
++ int error;
++
++ if (!mxt_in_bootloader(data))
++ return;
++
++ disable_irq(data->irq);
++ /* Wait for reset */
++ msleep(MXT_FWRESET_TIME);
++
++ if (client->addr == MXT_BOOT_LOW)
++ client->addr = MXT_APP_LOW;
++ else
++ client->addr = MXT_APP_HIGH;
++
++ error = mxt_initialize(data);
++ if (error) {
++ dev_err(dev, "Failed to initialize on exit bl. error = %d\n",
++ error);
++ return;
++ }
++
++ error = mxt_input_dev_create(data);
++ if (error) {
++ dev_err(dev, "Create input dev failed after init. error = %d\n",
++ error);
++ return;
++ }
++
++ error = mxt_make_highchg(data);
++ if (error)
++ dev_err(dev, "Failed to clear CHG after init. error = %d\n",
++ error);
++ enable_irq(data->irq);
++}
++
+ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+ {
+ struct mxt_data *data = dev_id;
+@@ -984,28 +1066,10 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ return ret;
+ }
+
+- if (mxt_in_bootloader(data))
+- goto bootloader_ready;
+-
+- /* Change to the bootloader mode */
+- ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+- MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+- if (ret)
++ ret = mxt_enter_bl(data);
++ if (ret) {
++ dev_err(dev, "Failed to reset to bootloader.\n");
+ goto out;
+- msleep(MXT_RESET_TIME);
+-
+- /* Change to slave address of bootloader */
+- if (client->addr == MXT_APP_LOW)
+- client->addr = MXT_BOOT_LOW;
+- else
+- client->addr = MXT_BOOT_HIGH;
+-
+-bootloader_ready:
+- /* Free any driver state. It will get reinitialized after fw update. */
+- mxt_free_object_table(data);
+- if (data->input_dev) {
+- input_unregister_device(data->input_dev);
+- data->input_dev = NULL;
+ }
+
+ ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
+@@ -1045,11 +1109,8 @@ bootloader_ready:
+ dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+ }
+
+- /* Change to slave address of application */
+- if (client->addr == MXT_BOOT_LOW)
+- client->addr = MXT_APP_LOW;
+- else
+- client->addr = MXT_APP_HIGH;
++ /* Device exits bl mode to app mode only if successful */
++ mxt_exit_bl(data);
+ out:
+ release_firmware(fw);
+
+@@ -1060,31 +1121,16 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- struct mxt_data *data = dev_get_drvdata(dev);
+ int error;
+
+- disable_irq(data->irq);
+-
+ error = mxt_load_fw(dev, MXT_FW_NAME);
+ if (error) {
+ dev_err(dev, "The firmware update failed(%d)\n", error);
+ count = error;
+ } else {
+ dev_dbg(dev, "The firmware update succeeded\n");
+-
+- /* Wait for reset */
+- msleep(MXT_FWRESET_TIME);
+-
+- mxt_initialize(data);
+- mxt_input_dev_create(data);
+ }
+
+- enable_irq(data->irq);
+-
+- error = mxt_make_highchg(data);
+- if (error)
+- return error;
+-
+ return count;
+ }
+
diff --git a/patches/linux-3.8.13/0515-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-assert-in-m.patch b/patches/linux-3.8.13/0515-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-assert-in-m.patch
new file mode 100644
index 0000000..6548fba
--- /dev/null
+++ b/patches/linux-3.8.13/0515-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-assert-in-m.patch
@@ -0,0 +1,170 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Wed, 25 Apr 2012 23:08:12 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - wait for CHG assert in
+ mxt_check_bootloader
+
+The driver should not immediately read bootloader status when
+in Application Update Mode. The CHG line will assert when the device
+has made a state transition and is ready to report a new status
+via i2c.
+
+This change adds a wait for completion in mxt_check_bootloader,
+and changes the mxt_interrupt handler to signal the completion.
+
+This will allow this commit in the intel_i2c driver to be reverted,
+as the time is no longer spent waiting for i2c read:
+3414f39 CHROMIUM: drm/i915/intel_i2c: Increase bitbang fallback timeout for atmel_mx
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:8730
+TEST=(a) Verify when device not in BL (normal case), no functional change.
+TEST=(b) Verify fw update works, and device is initialized properly
+ after.
+
+Change-Id: I5d20a9d63361fb91cb59aa7351e581f55422b924
+Reviewed-on: https://gerrit.chromium.org/gerrit/21173
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 63 ++++++++++++++++++++++++++----
+ 1 file changed, 55 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index be96be3..d0f91ff 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -13,6 +13,7 @@
+
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/completion.h>
+ #include <linux/delay.h>
+ #include <linux/firmware.h>
+ #include <linux/i2c.h>
+@@ -251,6 +252,9 @@ struct mxt_data {
+ u8 T6_reportid;
+ u8 T9_reportid_min;
+ u8 T9_reportid_max;
++
++ /* for fw update in bootloader */
++ struct completion bl_completion;
+ };
+
+ static void mxt_free_object_table(struct mxt_data *data);
+@@ -381,19 +385,58 @@ static int mxt_i2c_transfer(struct i2c_client *client, struct i2c_msg *msgs,
+ return ret;
+ }
+
+-static int mxt_check_bootloader(struct i2c_client *client,
+- unsigned int state)
++static int mxt_wait_for_chg(struct mxt_data *data, unsigned int timeout_ms)
+ {
++ struct device *dev = &data->client->dev;
++ struct completion *comp = &data->bl_completion;
++ unsigned long timeout = msecs_to_jiffies(timeout_ms);
++ long ret;
++
++ ret = wait_for_completion_interruptible_timeout(comp, timeout);
++ if (ret < 0) {
++ dev_err(dev, "Wait for completion interrupted.\n");
++ /*
++ * TODO: handle -EINTR better by terminating fw update process
++ * before returning to userspace by writing length 0x000 to
++ * device (iff we are in WAITING_FRAME_DATA state).
++ */
++ return -EINTR;
++ } else if (ret == 0) {
++ dev_err(dev, "Wait for completion timed out.\n");
++ return -ETIMEDOUT;
++ }
++ return 0;
++}
++
++static int mxt_check_bootloader(struct mxt_data *data, unsigned int state)
++{
++ struct i2c_client *client = data->client;
+ u8 val;
+ int ret;
+
+ recheck:
++ if (state != MXT_WAITING_BOOTLOAD_CMD) {
++ /*
++ * In application update mode, the interrupt
++ * line signals state transitions. We must wait for the
++ * CHG assertion before reading the status byte.
++ * Once the status byte has been read, the line is deasserted.
++ */
++ int ret = mxt_wait_for_chg(data, 300);
++ if (ret) {
++ dev_err(&client->dev, "Update wait error %d\n", ret);
++ return ret;
++ }
++ }
++
+ ret = mxt_i2c_recv(client, &val, 1);
+ if (ret)
+ return ret;
+
+ switch (state) {
+ case MXT_WAITING_BOOTLOAD_CMD:
++ dev_info(&client->dev, "bootloader version: %d\n",
++ val & MXT_BOOT_STATUS_MASK);
+ case MXT_WAITING_FRAME_DATA:
+ val &= ~MXT_BOOT_STATUS_MASK;
+ break;
+@@ -672,8 +715,11 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+ u8 reportid;
+ bool update_input = false;
+
+- if (mxt_in_bootloader(data))
++ if (mxt_in_bootloader(data)) {
++ /* bootloader state transition completion */
++ complete(&data->bl_completion);
+ goto end;
++ }
+
+ do {
+ if (mxt_read_message(data, &message)) {
+@@ -1072,18 +1118,18 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ goto out;
+ }
+
+- ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
++ ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD);
+ if (ret)
+ goto out;
+
++ INIT_COMPLETION(data->bl_completion);
+ /* Unlock bootloader */
+ ret = mxt_unlock_bootloader(client);
+ if (ret)
+ goto out;
+
+ while (pos < fw->size) {
+- ret = mxt_check_bootloader(client,
+- MXT_WAITING_FRAME_DATA);
++ ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA);
+ if (ret)
+ goto out;
+
+@@ -1099,8 +1145,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ if (ret)
+ goto out;
+
+- ret = mxt_check_bootloader(client,
+- MXT_FRAME_CRC_PASS);
++ ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS);
+ if (ret)
+ goto out;
+
+@@ -1264,6 +1309,8 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ data->pdata = pdata;
+ data->irq = client->irq;
+
++ init_completion(&data->bl_completion);
++
+ mxt_calc_resolution(data);
+
+ if (mxt_in_bootloader(data)) {
diff --git a/patches/linux-3.8.13/0516-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-after-bootl.patch b/patches/linux-3.8.13/0516-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-after-bootl.patch
new file mode 100644
index 0000000..d90dd56
--- /dev/null
+++ b/patches/linux-3.8.13/0516-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-after-bootl.patch
@@ -0,0 +1,84 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Wed, 2 May 2012 20:21:12 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - wait for CHG after
+ bootloader resets
+
+Rather than msleep for MXT_RESET_TIME and MXT_FWRESET_TIME
+during the transition to bootloader mode and the transition
+back from app, wait for the CHG assert to indicate that the
+transition is done.
+
+This change replaces the msleep with a wait for completion that
+the mxt_interrupt handler signals.
+
+This improves firmware update time at 300ms as we no longer
+wait longer than necessary for each reset.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:8716,chrome-os-partner:8732
+TEST=Verify fw update works, and device is initialized properly after.
+
+Change-Id: Id8982144d3966ccd8227da2a2ea47f9e73115d8e
+Reviewed-on: https://gerrit.chromium.org/gerrit/21832
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index d0f91ff..ef867d3 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -634,6 +634,7 @@ static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
+ static int mxt_enter_bl(struct mxt_data *data)
+ {
+ struct i2c_client *client = data->client;
++ struct device *dev = &client->dev;
+ int ret;
+
+ if (mxt_in_bootloader(data))
+@@ -662,8 +663,19 @@ static int mxt_enter_bl(struct mxt_data *data)
+ data->input_dev = NULL;
+ }
+
++ INIT_COMPLETION(data->bl_completion);
+ enable_irq(data->irq);
+- msleep(MXT_RESET_TIME);
++
++ /* Wait for CHG assert to indicate successful reset into bootloader */
++ ret = mxt_wait_for_chg(data, MXT_RESET_TIME);
++ if (ret) {
++ dev_err(dev, "Failed waiting for reset to bootloader.\n");
++ if (client->addr == MXT_BOOT_LOW)
++ client->addr = MXT_APP_LOW;
++ else
++ client->addr = MXT_APP_HIGH;
++ return ret;
++ }
+ return 0;
+ }
+
+@@ -676,10 +688,10 @@ static void mxt_exit_bl(struct mxt_data *data)
+ if (!mxt_in_bootloader(data))
+ return;
+
+- disable_irq(data->irq);
+ /* Wait for reset */
+- msleep(MXT_FWRESET_TIME);
++ mxt_wait_for_chg(data, MXT_FWRESET_TIME);
+
++ disable_irq(data->irq);
+ if (client->addr == MXT_BOOT_LOW)
+ client->addr = MXT_APP_LOW;
+ else
+@@ -1122,7 +1134,6 @@ static int mxt_load_fw(struct device *dev, const char *fn)
+ if (ret)
+ goto out;
+
+- INIT_COMPLETION(data->bl_completion);
+ /* Unlock bootloader */
+ ret = mxt_unlock_bootloader(client);
+ if (ret)
diff --git a/patches/linux-3.8.13/0517-CHROMIUM-Input-atmel_mxt_ts-change-MXT_BOOT_LOW-to-0.patch b/patches/linux-3.8.13/0517-CHROMIUM-Input-atmel_mxt_ts-change-MXT_BOOT_LOW-to-0.patch
new file mode 100644
index 0000000..4aa3da8
--- /dev/null
+++ b/patches/linux-3.8.13/0517-CHROMIUM-Input-atmel_mxt_ts-change-MXT_BOOT_LOW-to-0.patch
@@ -0,0 +1,37 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Wed, 4 Apr 2012 17:26:47 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - change MXT_BOOT_LOW to 0x26
+
+Changed to support address on new part. This is contrary to
+Atmel documentation, and we are still working with them
+to clear up this inconsistency. In the meantime,
+change it for now to allow existing systems to update.
+
+BUG=chrome-os-partner:8734
+TEST=Firmware update works.
+
+Change-Id: Ib2db2a066126df291c7a85208743c80c5357d55d
+Signed-off-by: Benson Leung <bleung@chromium.org>
+Reviewed-on: https://gerrit.chromium.org/gerrit/19639
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index ef867d3..0aae3fb 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -30,7 +30,11 @@
+ /* Slave addresses */
+ #define MXT_APP_LOW 0x4a
+ #define MXT_APP_HIGH 0x4b
+-#define MXT_BOOT_LOW 0x24
++/*
++ * MXT_BOOT_LOW disagrees with Atmel documentation, but has been
++ * updated to support new touch hardware that pairs 0x26 boot with 0x4a app.
++ */
++#define MXT_BOOT_LOW 0x26
+ #define MXT_BOOT_HIGH 0x25
+
+ /* Firmware */
diff --git a/patches/linux-3.8.13/0518-CHROMIUM-Input-atmel_mxt_ts-Increase-FWRESET_TIME.patch b/patches/linux-3.8.13/0518-CHROMIUM-Input-atmel_mxt_ts-Increase-FWRESET_TIME.patch
new file mode 100644
index 0000000..6852cf9
--- /dev/null
+++ b/patches/linux-3.8.13/0518-CHROMIUM-Input-atmel_mxt_ts-Increase-FWRESET_TIME.patch
@@ -0,0 +1,31 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Wed, 4 Apr 2012 19:34:52 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Increase FWRESET_TIME
+
+175ms is not enough time to update the firmware. Set to
+500ms.
+
+BUG=chrome-os-partner:8731
+TEST=firmware update. ensure that transitions back to app mode at the end.
+
+Change-Id: Idaec72cb4f326a10d3513ffb82bf4b144c68b30c
+Signed-off-by: Benson Leung <bleung@chromium.org>
+Reviewed-on: https://gerrit.chromium.org/gerrit/19640
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 0aae3fb..b9b9b3f 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -184,7 +184,7 @@
+ #define MXT_BACKUP_TIME 25 /* msec */
+ #define MXT_RESET_TIME 65 /* msec */
+
+-#define MXT_FWRESET_TIME 175 /* msec */
++#define MXT_FWRESET_TIME 500 /* msec */
+
+ /* Command to unlock bootloader */
+ #define MXT_UNLOCK_CMD_MSB 0xaa
diff --git a/patches/linux-3.8.13/0519-CHROMIUM-Input-atmel_mxt_ts-add-calibrate-sysfs-entr.patch b/patches/linux-3.8.13/0519-CHROMIUM-Input-atmel_mxt_ts-add-calibrate-sysfs-entr.patch
new file mode 100644
index 0000000..807fc6e
--- /dev/null
+++ b/patches/linux-3.8.13/0519-CHROMIUM-Input-atmel_mxt_ts-add-calibrate-sysfs-entr.patch
@@ -0,0 +1,80 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Sun, 22 Apr 2012 23:29:25 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add calibrate sysfs entry
+
+In some situations, a touch surface may get out of calibration.
+It is useful to provide a means for userspace to trigger a recal, so add a
+calibrate sysfs entry.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:9148
+TEST=echo 1 > /sys/bus/i2c/drivers/atmel_mxt_ts/<dev>/calibrate
+
+Change-Id: Idbdd7bf4f412f03e36604a2a1fae162f059234d3
+Reviewed-on: https://gerrit.chromium.org/gerrit/20812
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index b9b9b3f..00968a1 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -183,6 +183,7 @@
+ #define MXT_BACKUP_VALUE 0x55
+ #define MXT_BACKUP_TIME 25 /* msec */
+ #define MXT_RESET_TIME 65 /* msec */
++#define MXT_CAL_TIME 25 /* msec */
+
+ #define MXT_FWRESET_TIME 500 /* msec */
+
+@@ -1033,6 +1034,27 @@ static void mxt_calc_resolution(struct mxt_data *data)
+ }
+ }
+
++static ssize_t mxt_calibrate_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ int ret;
++
++ disable_irq(data->irq);
++
++ /* Perform touch surface recalibration */
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_CALIBRATE, 1);
++ if (ret)
++ goto out;
++ msleep(MXT_CAL_TIME);
++
++out:
++ enable_irq(data->irq);
++ return ret ?: count;
++}
++
+ /* Firmware Version is returned as Major.Minor.Build */
+ static ssize_t mxt_fw_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+@@ -1194,12 +1216,14 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ return count;
+ }
+
++static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
+ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+ static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+ static struct attribute *mxt_attrs[] = {
++ &dev_attr_calibrate.attr,
+ &dev_attr_fw_version.attr,
+ &dev_attr_hw_version.attr,
+ &dev_attr_object.attr,
diff --git a/patches/linux-3.8.13/0520-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch b/patches/linux-3.8.13/0520-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch
new file mode 100644
index 0000000..9f811f9
--- /dev/null
+++ b/patches/linux-3.8.13/0520-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch
@@ -0,0 +1,82 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 23 Apr 2012 12:33:12 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add sysfs entry to read
+ config checksum
+
+Config checksum is returned in the T6 message at every boot, and when
+the config changes. Cache its value and add sysfs entry for userspace to
+read it.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=cat /sys/bus/i2c/drivers/atmel_mxt_ts/2-004b/config_csum
+
+Change-Id: Ic546d1671e9f6a3da598f06a31f76a6ca96ce235
+Reviewed-on: https://gerrit.chromium.org/gerrit/20597
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 00968a1..a03a0c4 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -253,6 +253,8 @@ struct mxt_data {
+ unsigned int max_x;
+ unsigned int max_y;
+
++ u32 config_csum;
++
+ /* Cached parameters from object table */
+ u8 T6_reportid;
+ u8 T9_reportid_min;
+@@ -748,9 +750,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+
+ if (reportid == data->T6_reportid) {
+ u8 status = payload[0];
+- unsigned csum = mxt_extract_T6_csum(&payload[1]);
++ data->config_csum = mxt_extract_T6_csum(&payload[1]);
+ dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
+- status, csum);
++ status, data->config_csum);
+ } else if (mxt_is_T9_message(data, &message)) {
+ int id = reportid - data->T9_reportid_min;
+ mxt_input_touchevent(data, &message, id);
+@@ -1055,6 +1057,13 @@ out:
+ return ret ?: count;
+ }
+
++static ssize_t mxt_config_csum_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_csum);
++}
++
+ /* Firmware Version is returned as Major.Minor.Build */
+ static ssize_t mxt_fw_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+@@ -1217,6 +1226,7 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ }
+
+ static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
++static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
+ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+ static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
+@@ -1224,6 +1234,7 @@ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+ static struct attribute *mxt_attrs[] = {
+ &dev_attr_calibrate.attr,
++ &dev_attr_config_csum.attr,
+ &dev_attr_fw_version.attr,
+ &dev_attr_hw_version.attr,
+ &dev_attr_object.attr,
diff --git a/patches/linux-3.8.13/0521-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch b/patches/linux-3.8.13/0521-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch
new file mode 100644
index 0000000..9f0c2cb
--- /dev/null
+++ b/patches/linux-3.8.13/0521-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch
@@ -0,0 +1,103 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Fri, 27 Apr 2012 21:44:58 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add sysfs entry to read info
+ checksum
+
+The device stores the Information Block Checksum in the 3 bytes
+immediately following the Information Block.
+
+Read these three bytes, cache the value, and add a sysfs entry so
+userspace can read it.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=cat /sys/bus/i2c/drivers/atmel_mxt_ts/2-004b/info_csum
+
+Change-Id: I27512c624bad15674bc7c50c15717913595affe4
+Reviewed-on: https://gerrit.chromium.org/gerrit/20599
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index a03a0c4..e6a5422 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -253,6 +253,7 @@ struct mxt_data {
+ unsigned int max_x;
+ unsigned int max_y;
+
++ u32 info_csum;
+ u32 config_csum;
+
+ /* Cached parameters from object table */
+@@ -894,10 +895,12 @@ static int mxt_get_info(struct mxt_data *data)
+ static int mxt_get_object_table(struct mxt_data *data)
+ {
+ struct i2c_client *client = data->client;
++ struct device *dev = &data->client->dev;
+ size_t table_size;
+ int error;
+ int i;
+ u8 reportid;
++ u8 csum[3];
+
+ table_size = data->info.object_num * sizeof(struct mxt_object);
+ error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
+@@ -905,6 +908,18 @@ static int mxt_get_object_table(struct mxt_data *data)
+ if (error)
+ return error;
+
++ /*
++ * Read Information Block checksum from 3 bytes immediately following
++ * info block
++ */
++ error = __mxt_read_reg(client, MXT_OBJECT_START + table_size,
++ sizeof(csum), csum);
++ if (error)
++ return error;
++
++ data->info_csum = csum[0] | (csum[1] << 8) | (csum[2] << 16);
++ dev_info(dev, "Information Block Checksum = %06x\n", data->info_csum);
++
+ /* Valid Report IDs start counting from 1 */
+ reportid = 1;
+ for (i = 0; i < data->info.object_num; i++) {
+@@ -1084,6 +1099,13 @@ static ssize_t mxt_hw_version_show(struct device *dev,
+ info->family_id, info->variant_id);
+ }
+
++static ssize_t mxt_info_csum_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%06x\n", data->info_csum);
++}
++
+ static ssize_t mxt_show_instance(char *buf, int count,
+ struct mxt_object *object, int instance,
+ const u8 *val)
+@@ -1229,6 +1251,7 @@ static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
+ static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
+ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
++static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
+ static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+@@ -1237,6 +1260,7 @@ static struct attribute *mxt_attrs[] = {
+ &dev_attr_config_csum.attr,
+ &dev_attr_fw_version.attr,
+ &dev_attr_hw_version.attr,
++ &dev_attr_info_csum.attr,
+ &dev_attr_object.attr,
+ &dev_attr_update_fw.attr,
+ NULL
diff --git a/patches/linux-3.8.13/0522-CHROMIUM-Input-atmel_mxt_ts-verify-info-block-checks.patch b/patches/linux-3.8.13/0522-CHROMIUM-Input-atmel_mxt_ts-verify-info-block-checks.patch
new file mode 100644
index 0000000..e3483bb
--- /dev/null
+++ b/patches/linux-3.8.13/0522-CHROMIUM-Input-atmel_mxt_ts-verify-info-block-checks.patch
@@ -0,0 +1,111 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Thu, 26 Apr 2012 00:57:41 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - verify info block checksum
+
+Compute 24 bit CRC over entire Information Block (ID info plus Object
+Table), and verify that it matches checksum read from the device.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=Verify atmel device is discovered and operates as before.
+
+Change-Id: Ic20f585abf6726e7ff5e2cc4afd7ae805180b81d
+Reviewed-on: https://gerrit.chromium.org/gerrit/20600
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 69 ++++++++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index e6a5422..9210a8a 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -878,6 +878,71 @@ static void mxt_handle_pdata(struct mxt_data *data)
+ }
+ }
+
++/* Update 24-bit CRC with two new bytes of data */
++static u32 crc24_step(u32 crc, u8 byte1, u8 byte2)
++{
++ const u32 crcpoly = 0x80001b;
++ u16 data = byte1 | (byte2 << 8);
++ u32 result = data ^ (crc << 1);
++
++ /* XOR result with crcpoly if bit 25 is set (overflow occurred) */
++ if (result & 0x01000000)
++ result ^= crcpoly;
++
++ return result & 0x00ffffff;
++}
++
++static u32 crc24(u32 crc, const u8 *data, size_t len)
++{
++ size_t i;
++
++ for (i = 0; i < len - 1; i += 2)
++ crc = crc24_step(crc, data[i], data[i + 1]);
++
++ /* If there were an odd number of bytes pad with 0 */
++ if (i < len)
++ crc = crc24_step(crc, data[i], 0);
++
++ return crc;
++}
++
++static int mxt_verify_info_block_csum(struct mxt_data *data)
++{
++ struct i2c_client *client = data->client;
++ struct device *dev = &client->dev;
++ size_t object_table_size, info_block_size;
++ u32 crc = 0;
++ u8 *info_block;
++ int ret = 0;
++
++ object_table_size = data->info.object_num * MXT_OBJECT_SIZE;
++ info_block_size = sizeof(data->info) + object_table_size;
++ info_block = kmalloc(info_block_size, GFP_KERNEL);
++ if (!info_block)
++ return -ENOMEM;
++
++ /*
++ * Information Block CRC is computed over both ID info and Object Table
++ * So concat them in a temporary buffer, before computing CRC.
++ * TODO: refactor how the info block is read from the device such
++ * that it ends up in a single buffer and this copy is not needed.
++ */
++ memcpy(info_block, &data->info, sizeof(data->info));
++ memcpy(&info_block[sizeof(data->info)], data->object_table,
++ object_table_size);
++
++ crc = crc24(crc, info_block, info_block_size);
++
++ if (crc != data->info_csum) {
++ dev_err(dev, "Information Block CRC mismatch: %06x != %06x\n",
++ data->info_csum, crc);
++ ret = -EINVAL;
++ }
++
++ kfree(info_block);
++ return ret;
++}
++
+ static int mxt_get_info(struct mxt_data *data)
+ {
+ struct i2c_client *client = data->client;
+@@ -920,6 +985,10 @@ static int mxt_get_object_table(struct mxt_data *data)
+ data->info_csum = csum[0] | (csum[1] << 8) | (csum[2] << 16);
+ dev_info(dev, "Information Block Checksum = %06x\n", data->info_csum);
+
++ error = mxt_verify_info_block_csum(data);
++ if (error)
++ return error;
++
+ /* Valid Report IDs start counting from 1 */
+ reportid = 1;
+ for (i = 0; i < data->info.object_num; i++) {
diff --git a/patches/linux-3.8.13/0523-CHROMIUM-Input-atmel_mxt_tx-add-matrix_size-sysfs-en.patch b/patches/linux-3.8.13/0523-CHROMIUM-Input-atmel_mxt_tx-add-matrix_size-sysfs-en.patch
new file mode 100644
index 0000000..41175c1
--- /dev/null
+++ b/patches/linux-3.8.13/0523-CHROMIUM-Input-atmel_mxt_tx-add-matrix_size-sysfs-en.patch
@@ -0,0 +1,63 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 30 Apr 2012 13:30:31 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_tx - add matrix_size sysfs entry
+
+Returns the number of X and Y sense lines.
+
+This entry will be used by userspace for determining the dimensions of
+the T37 arrays that will be returned by deltas and refs debugfs entries.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:29899
+TEST=cat /sys/bus/i2c/drivers/atmel_mxt_ts/<dev>/matrix_size
+
+Change-Id: I3f6414a1eaa09f51d345256e7f1bb90bdbbc528f
+Reviewed-on: https://gerrit.chromium.org/gerrit/21458
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 9210a8a..b9a0de2 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1175,6 +1175,16 @@ static ssize_t mxt_info_csum_show(struct device *dev,
+ return scnprintf(buf, PAGE_SIZE, "%06x\n", data->info_csum);
+ }
+
++/* Matrix Size is <MatrixSizeX> <MatrixSizeY> */
++static ssize_t mxt_matrix_size_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ struct mxt_info *info = &data->info;
++ return scnprintf(buf, PAGE_SIZE, "%u %u\n",
++ info->matrix_xsize, info->matrix_ysize);
++}
++
+ static ssize_t mxt_show_instance(char *buf, int count,
+ struct mxt_object *object, int instance,
+ const u8 *val)
+@@ -1321,6 +1331,7 @@ static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
+ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+ static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
++static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL);
+ static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+@@ -1330,6 +1341,7 @@ static struct attribute *mxt_attrs[] = {
+ &dev_attr_fw_version.attr,
+ &dev_attr_hw_version.attr,
+ &dev_attr_info_csum.attr,
++ &dev_attr_matrix_size.attr,
+ &dev_attr_object.attr,
+ &dev_attr_update_fw.attr,
+ NULL
diff --git a/patches/linux-3.8.13/0524-CHROMIUM-Input-atmel_mxt_ts-define-helper-functions-.patch b/patches/linux-3.8.13/0524-CHROMIUM-Input-atmel_mxt_ts-define-helper-functions-.patch
new file mode 100644
index 0000000..2800b7c
--- /dev/null
+++ b/patches/linux-3.8.13/0524-CHROMIUM-Input-atmel_mxt_ts-define-helper-functions-.patch
@@ -0,0 +1,117 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 17 Dec 2012 17:22:02 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - define helper functions for
+ size and instances
+
+These two object table entry fields are reported 1 less than their value.
+When used, however, we always want the actual size and instances.
+
+To keep the object size and instances 1-byte fields, and thus preserve
+the object-table struct's 6-byte packed alignment, add some convenient
+accessor functions that do the +1 every time these fields are accessed.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=Confirm object table is read correctly:
+ cat /sys/bus/i2c/devices/<dev>/object
+
+Change-Id: If303428b09e8ad5516bae8f2eccb3fd1c386192d
+Reviewed-on: https://gerrit.chromium.org/gerrit/17946
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 31 ++++++++++++++++++++----------
+ 1 file changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index b9a0de2..b53e839 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -270,6 +270,16 @@ static int mxt_initialize(struct mxt_data *data);
+ static int mxt_input_dev_create(struct mxt_data *data);
+ static int mxt_make_highchg(struct mxt_data *data);
+
++static inline size_t mxt_obj_size(const struct mxt_object *obj)
++{
++ return obj->size + 1;
++}
++
++static inline size_t mxt_obj_instances(const struct mxt_object *obj)
++{
++ return obj->instances + 1;
++}
++
+ static bool mxt_object_readable(unsigned int type)
+ {
+ switch (type) {
+@@ -575,7 +585,7 @@ static int mxt_write_object(struct mxt_data *data,
+ u16 reg;
+
+ object = mxt_get_object(data, type);
+- if (!object || offset >= object->size + 1)
++ if (!object || offset >= mxt_obj_size(object))
+ return -EINVAL;
+
+ reg = object->start_address;
+@@ -792,7 +802,7 @@ static int mxt_check_reg_init(struct mxt_data *data)
+ if (!mxt_object_writable(object->type))
+ continue;
+
+- size = (object->size + 1) * (object->instances + 1);
++ size = mxt_obj_size(object) * mxt_obj_instances(object);
+ if (index + size > pdata->config_length) {
+ dev_err(dev, "Not enough config data!\n");
+ return -EINVAL;
+@@ -1000,7 +1010,7 @@ static int mxt_get_object_table(struct mxt_data *data)
+ if (object->num_report_ids) {
+ min_id = reportid;
+ reportid += object->num_report_ids *
+- (object->instances + 1);
++ mxt_obj_instances(object);
+ max_id = reportid - 1;
+ } else {
+ min_id = 0;
+@@ -1008,9 +1018,10 @@ static int mxt_get_object_table(struct mxt_data *data)
+ }
+
+ dev_dbg(&data->client->dev,
+- "Type %2d Start %3d Size %3d Instances %2d ReportIDs %3u : %3u\n",
+- object->type, object->start_address, object->size + 1,
+- object->instances + 1, min_id, max_id);
++ "Type %2d Start %3d Size %3zu Instances %2zu ReportIDs %3u : %3u\n",
++ object->type, object->start_address,
++ mxt_obj_size(object), mxt_obj_instances(object),
++ min_id, max_id);
+
+ switch (object->type) {
+ case MXT_GEN_COMMAND_T6:
+@@ -1191,11 +1202,11 @@ static ssize_t mxt_show_instance(char *buf, int count,
+ {
+ int i;
+
+- if (object->instances > 0)
++ if (mxt_obj_instances(object) > 1)
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "Instance %u\n", instance);
+
+- for (i = 0; i < object->size + 1; i++)
++ for (i = 0; i < mxt_obj_size(object); i++)
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "\t[%2u]: %02x (%d)\n", i, val[i], val[i]);
+ count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+@@ -1228,8 +1239,8 @@ static ssize_t mxt_object_show(struct device *dev,
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "T%u:\n", object->type);
+
+- for (j = 0; j < object->instances + 1; j++) {
+- u16 size = object->size + 1;
++ for (j = 0; j < mxt_obj_instances(object); j++) {
++ u16 size = mxt_obj_size(object);
+ u16 addr = object->start_address + j * size;
+
+ error = __mxt_read_reg(data->client, addr, size, obuf);
diff --git a/patches/linux-3.8.13/0525-CHROMIUM-Input-atmel_mxt_ts-add-debugfs-infrastructu.patch b/patches/linux-3.8.13/0525-CHROMIUM-Input-atmel_mxt_ts-add-debugfs-infrastructu.patch
new file mode 100644
index 0000000..aa3d35c
--- /dev/null
+++ b/patches/linux-3.8.13/0525-CHROMIUM-Input-atmel_mxt_ts-add-debugfs-infrastructu.patch
@@ -0,0 +1,127 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Wed, 9 May 2012 02:18:14 +0000
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add debugfs infrastructure
+
+This patch just creates a per-device debugfs root directory.
+Actual debugfs entries will be added in subsequent patches.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+BUG=chromium-os:29899
+TEST=ls /sys/kernel/debug/atmel_mxt_ts
+ => Should show directories for each atmel_mxt_ts device on the system
+
+Change-Id: I82e5470f5d1658dae03ad8d66bf348cc4fb2edb2
+Reviewed-on: https://gerrit.chromium.org/gerrit/21051
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 55 +++++++++++++++++++++++++++++-
+ 1 file changed, 54 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index b53e839..311959d 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -14,6 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/completion.h>
++#include <linux/debugfs.h>
+ #include <linux/delay.h>
+ #include <linux/firmware.h>
+ #include <linux/i2c.h>
+@@ -263,8 +264,14 @@ struct mxt_data {
+
+ /* for fw update in bootloader */
+ struct completion bl_completion;
++
++ /* per-instance debugfs root */
++ struct dentry *dentry_dev;
+ };
+
++/* global root node of the atmel_mxt_ts debugfs directory. */
++static struct dentry *mxt_debugfs_root;
++
+ static void mxt_free_object_table(struct mxt_data *data);
+ static int mxt_initialize(struct mxt_data *data);
+ static int mxt_input_dev_create(struct mxt_data *data);
+@@ -1362,6 +1369,27 @@ static const struct attribute_group mxt_attr_group = {
+ .attrs = mxt_attrs,
+ };
+
++/*
++ **************************************************************
++ * debugfs interface
++ **************************************************************
++*/
++static int mxt_debugfs_init(struct mxt_data *mxt)
++{
++ struct device *dev = &mxt->client->dev;
++
++ if (!mxt_debugfs_root)
++ return -ENODEV;
++
++ mxt->dentry_dev = debugfs_create_dir(kobject_name(&dev->kobj),
++ mxt_debugfs_root);
++
++ if (!mxt->dentry_dev)
++ return -ENODEV;
++
++ return 0;
++}
++
+ static void mxt_start(struct mxt_data *data)
+ {
+ /* Touch enable */
+@@ -1512,6 +1540,10 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ if (error)
+ goto err_free_irq;
+
++ error = mxt_debugfs_init(data);
++ if (error)
++ dev_warn(&client->dev, "error creating debugfs entries.\n");
++
+ return 0;
+
+ err_free_irq:
+@@ -1529,6 +1561,8 @@ static int mxt_remove(struct i2c_client *client)
+ {
+ struct mxt_data *data = i2c_get_clientdata(client);
+
++ if (data->dentry_dev)
++ debugfs_remove_recursive(data->dentry_dev);
+ sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+ free_irq(data->irq, data);
+ if (data->input_dev)
+@@ -1606,7 +1640,26 @@ static struct i2c_driver mxt_driver = {
+ .id_table = mxt_id,
+ };
+
+-module_i2c_driver(mxt_driver);
++static int __init mxt_init(void)
++{
++ /* Create a global debugfs root for all atmel_mxt_ts devices */
++ mxt_debugfs_root = debugfs_create_dir(mxt_driver.driver.name, NULL);
++ if (mxt_debugfs_root == ERR_PTR(-ENODEV))
++ mxt_debugfs_root = NULL;
++
++ return i2c_add_driver(&mxt_driver);
++}
++
++static void __exit mxt_exit(void)
++{
++ if (mxt_debugfs_root)
++ debugfs_remove_recursive(mxt_debugfs_root);
++
++ i2c_del_driver(&mxt_driver);
++}
++
++module_init(mxt_init);
++module_exit(mxt_exit);
+
+ /* Module information */
+ MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
diff --git a/patches/linux-3.8.13/0526-CHROMIUM-Input-atmel_mxt_ts-add-deltas-and-refs-debu.patch b/patches/linux-3.8.13/0526-CHROMIUM-Input-atmel_mxt_ts-add-deltas-and-refs-debu.patch
new file mode 100644
index 0000000..4f4bb2d
--- /dev/null
+++ b/patches/linux-3.8.13/0526-CHROMIUM-Input-atmel_mxt_ts-add-deltas-and-refs-debu.patch
@@ -0,0 +1,338 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 17 Dec 2012 17:32:59 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add deltas and refs debugfs
+ entries
+
+Reading these two debugfs entries returns a binary blob containing the
+contents of all pages of the T37 object when the DELTAS and REFERENCES
+commands are requested, respectively.
+The values are written to the file as they are arranged in the device's
+T37 object, that is, as a 2D array with matrix_ysize columns and
+matrix_xsize rows of 2-byte (little endian) values.
+
+It is left to userspace to parse the 2-byte values.
+ * Deltas are signed 2's complement 2-byte little-endian values.
+ s32 delta = (b[0] + (b[1] << 8));
+
+ * Refs are signed 'offset binary' 2-byte little-endian values,
+ with offset 16384 (0x4000):
+ s32 ref = (b[0] + (b[1] << 8)) - 16384;
+
+Userspace should use the 'matrix_size' sysfs entry to determine the
+dimensions of the returned arrays.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:29899
+TEST=hexdump -e '52/2 "%6d" "\n"' /sys/kernel/debug/atmel_mxt_ts/<dev>/deltas
+ => dumps 'delta' values in a 52-column wide grid
+TEST=hexdump -e '12/2 "%6d" "\n"' /sys/kernel/debug/atmel_mxt_ts/<dev>/deltas
+ => dumps the 'ref' values in a 12-column wide grid
+
+Change-Id: I9deb64074dd9947739961aa4323573f4544e9dc1
+Reviewed-on: https://gerrit.chromium.org/gerrit/21052
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 241 +++++++++++++++++++++++++++++-
+ 1 file changed, 240 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 311959d..9a8cfd2 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -22,6 +22,7 @@
+ #include <linux/input/mt.h>
+ #include <linux/interrupt.h>
+ #include <linux/slab.h>
++#include <linux/uaccess.h>
+
+ /* Version */
+ #define MXT_VER_20 20
+@@ -90,6 +91,13 @@
+ #define MXT_COMMAND_REPORTALL 3
+ #define MXT_COMMAND_DIAGNOSTIC 5
+
++#define MXT_T6_CMD_PAGE_UP 0x01
++#define MXT_T6_CMD_PAGE_DOWN 0x02
++#define MXT_T6_CMD_DELTAS 0x10
++#define MXT_T6_CMD_REFS 0x11
++#define MXT_T6_CMD_DEVICE_ID 0x80
++#define MXT_T6_CMD_TOUCH_THRESH 0xF4
++
+ /* MXT_GEN_POWER_T7 field */
+ #define MXT_POWER_IDLEACQINT 0
+ #define MXT_POWER_ACTVACQINT 1
+@@ -267,6 +275,13 @@ struct mxt_data {
+
+ /* per-instance debugfs root */
+ struct dentry *dentry_dev;
++ struct dentry *dentry_deltas;
++ struct dentry *dentry_refs;
++
++ /* Protect access to the T37 object buffer, used by debugfs */
++ struct mutex T37_buf_mutex;
++ u8 *T37_buf;
++ size_t T37_buf_size;
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -1138,6 +1153,133 @@ static void mxt_calc_resolution(struct mxt_data *data)
+ }
+ }
+
++/*
++ * Helper function for performing a T6 diagnostic command
++ */
++static int mxt_T6_diag_cmd(struct mxt_data *data, struct mxt_object *T6,
++ u8 cmd)
++{
++ int ret;
++ u16 addr = T6->start_address + MXT_COMMAND_DIAGNOSTIC;
++
++ ret = mxt_write_reg(data->client, addr, cmd);
++ if (ret)
++ return ret;
++
++ /*
++ * Poll T6.diag until it returns 0x00, which indicates command has
++ * completed.
++ */
++ while (cmd != 0) {
++ ret = __mxt_read_reg(data->client, addr, 1, &cmd);
++ if (ret)
++ return ret;
++ }
++ return 0;
++}
++
++/*
++ * SysFS Helper function for reading DELTAS and REFERENCE values for T37 object
++ *
++ * For both modes, a T37_buf is allocated to stores matrix_xsize * matrix_ysize
++ * 2-byte (little-endian) values, which are returned to userspace unmodified.
++ *
++ * It is left to userspace to parse the 2-byte values.
++ * - deltas are signed 2's complement 2-byte little-endian values.
++ * s32 delta = (b[0] + (b[1] << 8));
++ * - refs are signed 'offset binary' 2-byte little-endian values, with offset
++ * value 0x4000:
++ * s32 ref = (b[0] + (b[1] << 8)) - 0x4000;
++ */
++static ssize_t mxt_T37_fetch(struct mxt_data *data, u8 mode)
++{
++ struct mxt_object *T6, *T37;
++ u8 *obuf;
++ ssize_t ret = 0;
++ size_t i;
++ size_t T37_buf_size, num_pages;
++ size_t pos;
++
++ if (!data || !data->object_table)
++ return -ENODEV;
++
++ T6 = mxt_get_object(data, MXT_GEN_COMMAND_T6);
++ T37 = mxt_get_object(data, MXT_DEBUG_DIAGNOSTIC_T37);
++ if (!T6 || mxt_obj_size(T6) < 6 || !T37 || mxt_obj_size(T37) < 3) {
++ dev_err(&data->client->dev, "Invalid T6 or T37 object\n");
++ return -ENODEV;
++ }
++
++ /* Something has gone wrong if T37_buf is already allocated */
++ if (data->T37_buf)
++ return -EINVAL;
++
++ T37_buf_size = data->info.matrix_xsize * data->info.matrix_ysize *
++ sizeof(__le16);
++ data->T37_buf_size = T37_buf_size;
++ data->T37_buf = kmalloc(data->T37_buf_size, GFP_KERNEL);
++ if (!data->T37_buf)
++ return -ENOMEM;
++
++ /* Temporary buffer used to fetch one T37 page */
++ obuf = kmalloc(mxt_obj_size(T37), GFP_KERNEL);
++ if (!obuf)
++ return -ENOMEM;
++
++ disable_irq(data->irq);
++ num_pages = DIV_ROUND_UP(T37_buf_size, mxt_obj_size(T37) - 2);
++ pos = 0;
++ for (i = 0; i < num_pages; i++) {
++ u8 cmd;
++ size_t chunk_len;
++
++ /* For first page, send mode as cmd, otherwise PageUp */
++ cmd = (i == 0) ? mode : MXT_T6_CMD_PAGE_UP;
++ ret = mxt_T6_diag_cmd(data, T6, cmd);
++ if (ret)
++ goto err_free_T37_buf;
++
++ ret = __mxt_read_reg(data->client, T37->start_address,
++ mxt_obj_size(T37), obuf);
++ if (ret)
++ goto err_free_T37_buf;
++
++ /* Verify first two bytes are current mode and page # */
++ if (obuf[0] != mode) {
++ dev_err(&data->client->dev,
++ "Unexpected mode (%u != %u)\n", obuf[0], mode);
++ ret = -EIO;
++ goto err_free_T37_buf;
++ }
++
++ if (obuf[1] != i) {
++ dev_err(&data->client->dev,
++ "Unexpected page (%u != %zu)\n", obuf[1], i);
++ ret = -EIO;
++ goto err_free_T37_buf;
++ }
++
++ /*
++ * Copy the data portion of the page, or however many bytes are
++ * left, whichever is less.
++ */
++ chunk_len = min(mxt_obj_size(T37) - 2, T37_buf_size - pos);
++ memcpy(&data->T37_buf[pos], &obuf[2], chunk_len);
++ pos += chunk_len;
++ }
++
++ goto out;
++
++err_free_T37_buf:
++ kfree(data->T37_buf);
++ data->T37_buf = NULL;
++ data->T37_buf_size = 0;
++out:
++ kfree(obuf);
++ enable_irq(data->irq);
++ return ret ?: 0;
++}
++
+ static ssize_t mxt_calibrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+@@ -1374,6 +1516,92 @@ static const struct attribute_group mxt_attr_group = {
+ * debugfs interface
+ **************************************************************
+ */
++static int mxt_debugfs_T37_open(struct inode *inode, struct file *file)
++{
++ struct mxt_data *mxt = inode->i_private;
++ int ret;
++ u8 cmd;
++
++ if (file->f_dentry == mxt->dentry_deltas)
++ cmd = MXT_T6_CMD_DELTAS;
++ else if (file->f_dentry == mxt->dentry_refs)
++ cmd = MXT_T6_CMD_REFS;
++ else
++ return -EINVAL;
++
++ /* Only allow one T37 debugfs file to be opened at a time */
++ ret = mutex_lock_interruptible(&mxt->T37_buf_mutex);
++ if (ret)
++ return ret;
++
++ if (!i2c_use_client(mxt->client)) {
++ ret = -ENODEV;
++ goto err_unlock;
++ }
++
++ /* Fetch all T37 pages into mxt->T37_buf */
++ ret = mxt_T37_fetch(mxt, cmd);
++ if (ret)
++ goto err_release;
++
++ file->private_data = mxt;
++
++ return 0;
++
++err_release:
++ i2c_release_client(mxt->client);
++err_unlock:
++ mutex_unlock(&mxt->T37_buf_mutex);
++ return ret;
++}
++
++static int mxt_debugfs_T37_release(struct inode *inode, struct file *file)
++{
++ struct mxt_data *mxt = file->private_data;
++
++ file->private_data = NULL;
++
++ kfree(mxt->T37_buf);
++ mxt->T37_buf = NULL;
++ mxt->T37_buf_size = 0;
++
++ i2c_release_client(mxt->client);
++ mutex_unlock(&mxt->T37_buf_mutex);
++
++ return 0;
++}
++
++
++/* Return some bytes from the buffered T37 object, starting from *ppos */
++static ssize_t mxt_debugfs_T37_read(struct file *file, char __user *buffer,
++ size_t count, loff_t *ppos)
++{
++ struct mxt_data *mxt = file->private_data;
++
++ if (!mxt->T37_buf)
++ return -ENODEV;
++
++ if (*ppos >= mxt->T37_buf_size)
++ return 0;
++
++ if (count + *ppos > mxt->T37_buf_size)
++ count = mxt->T37_buf_size - *ppos;
++
++ if (copy_to_user(buffer, &mxt->T37_buf[*ppos], count))
++ return -EFAULT;
++
++ *ppos += count;
++
++ return count;
++}
++
++static const struct file_operations mxt_debugfs_T37_fops = {
++ .owner = THIS_MODULE,
++ .open = mxt_debugfs_T37_open,
++ .release = mxt_debugfs_T37_release,
++ .read = mxt_debugfs_T37_read
++};
++
+ static int mxt_debugfs_init(struct mxt_data *mxt)
+ {
+ struct device *dev = &mxt->client->dev;
+@@ -1387,6 +1615,14 @@ static int mxt_debugfs_init(struct mxt_data *mxt)
+ if (!mxt->dentry_dev)
+ return -ENODEV;
+
++ mutex_init(&mxt->T37_buf_mutex);
++
++ mxt->dentry_deltas = debugfs_create_file("deltas", S_IRUSR,
++ mxt->dentry_dev, mxt,
++ &mxt_debugfs_T37_fops);
++ mxt->dentry_refs = debugfs_create_file("refs", S_IRUSR,
++ mxt->dentry_dev, mxt,
++ &mxt_debugfs_T37_fops);
+ return 0;
+ }
+
+@@ -1561,8 +1797,11 @@ static int mxt_remove(struct i2c_client *client)
+ {
+ struct mxt_data *data = i2c_get_clientdata(client);
+
+- if (data->dentry_dev)
++ if (data->dentry_dev) {
+ debugfs_remove_recursive(data->dentry_dev);
++ mutex_destroy(&data->T37_buf_mutex);
++ kfree(data->T37_buf);
++ }
+ sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+ free_irq(data->irq, data);
+ if (data->input_dev)
diff --git a/patches/linux-3.8.13/0527-CHROMIUM-Input-atmel_mxt_ts-add-device-id-for-touchp.patch b/patches/linux-3.8.13/0527-CHROMIUM-Input-atmel_mxt_ts-add-device-id-for-touchp.patch
new file mode 100644
index 0000000..26075cd
--- /dev/null
+++ b/patches/linux-3.8.13/0527-CHROMIUM-Input-atmel_mxt_ts-add-device-id-for-touchp.patch
@@ -0,0 +1,180 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Wed, 12 Dec 2012 15:33:18 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add device id for touchpad
+ variant
+
+This same driver can be used by atmel based touchscreens and touchpads
+(buttonpads) by instantiating the i2c device as a "atmel_mxt_tp".
+
+This will cause the driver to perform some touchpad specific
+initializations, such as:
+ * register input device name "Atmel maXTouch Touchpad" instead of
+ Touchscreen.
+ * register BTN_LEFT & BTN_TOOL_* event types.
+ * register axis resolution (as a fixed constant, for now)
+ * register BUTTONPAD property
+ * process GPIO buttons using reportid T19
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27714
+TEST=builds clean; atmel tp works using ddc lines and cmt
+
+Change-Id: Ifb5cff5667156ca48c1ca90e5e8eea0c434480df
+Reviewed-on: https://gerrit.chromium.org/gerrit/17959
+Commit-Ready: Benson Leung <bleung@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 51 +++++++++++++++++++++++++++++-
+ 1 file changed, 50 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 9a8cfd2..3b9007c 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -196,6 +196,12 @@
+
+ #define MXT_FWRESET_TIME 500 /* msec */
+
++/* MXT_SPT_GPIOPWM_T19 field */
++#define MXT_GPIO0_MASK 0x04
++#define MXT_GPIO1_MASK 0x08
++#define MXT_GPIO2_MASK 0x10
++#define MXT_GPIO3_MASK 0x20
++
+ /* Command to unlock bootloader */
+ #define MXT_UNLOCK_CMD_MSB 0xaa
+ #define MXT_UNLOCK_CMD_LSB 0xdc
+@@ -227,6 +233,9 @@
+ /* Touchscreen absolute values */
+ #define MXT_MAX_AREA 0xff
+
++/* For CMT (must match XRANGE/YRANGE as defined in board config */
++#define MXT_PIXELS_PER_MM 20
++
+ struct mxt_info {
+ u8 family_id;
+ u8 variant_id;
+@@ -258,6 +267,8 @@ struct mxt_data {
+ const struct mxt_platform_data *pdata;
+ struct mxt_object *object_table;
+ struct mxt_info info;
++ bool is_tp;
++
+ unsigned int irq;
+ unsigned int max_x;
+ unsigned int max_y;
+@@ -269,6 +280,7 @@ struct mxt_data {
+ u8 T6_reportid;
+ u8 T9_reportid_min;
+ u8 T9_reportid_max;
++ u8 T19_reportid;
+
+ /* for fw update in bootloader */
+ struct completion bl_completion;
+@@ -614,6 +626,18 @@ static int mxt_write_object(struct mxt_data *data,
+ return mxt_write_reg(data->client, reg + offset, val);
+ }
+
++static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
++{
++ struct device *dev = &data->client->dev;
++ struct input_dev *input = data->input_dev;
++ bool button;
++
++ /* Active-low switch */
++ button = !(message->message[0] & MXT_GPIO3_MASK);
++ input_report_key(input, BTN_LEFT, button);
++ dev_dbg(dev, "Button state: %d\n", button);
++}
++
+ static void mxt_input_touchevent(struct mxt_data *data,
+ struct mxt_message *message, int id)
+ {
+@@ -790,6 +814,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+ int id = reportid - data->T9_reportid_min;
+ mxt_input_touchevent(data, &message, id);
+ update_input = true;
++ } else if (message.reportid == data->T19_reportid) {
++ mxt_input_button(data, &message);
++ update_input = true;
+ } else {
+ mxt_dump_message(dev, &message);
+ }
+@@ -1053,6 +1080,9 @@ static int mxt_get_object_table(struct mxt_data *data)
+ data->T9_reportid_min = min_id;
+ data->T9_reportid_max = max_id;
+ break;
++ case MXT_SPT_GPIOPWM_T19:
++ data->T19_reportid = min_id;
++ break;
+ }
+ }
+
+@@ -1666,7 +1696,8 @@ static int mxt_input_dev_create(struct mxt_data *data)
+ if (!input_dev)
+ return -ENOMEM;
+
+- input_dev->name = "Atmel maXTouch Touchscreen";
++ input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" :
++ "Atmel maXTouch Touchscreen";
+ input_dev->phys = data->phys;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = &data->client->dev;
+@@ -1677,6 +1708,18 @@ static int mxt_input_dev_create(struct mxt_data *data)
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+
++ if (data->is_tp) {
++ __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
++ __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
++
++ __set_bit(BTN_LEFT, input_dev->keybit);
++ __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
++ __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
++ __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
++ __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
++ __set_bit(BTN_TOOL_QUINTTAP, input_dev->keybit);
++ }
++
+ /* For single touch */
+ input_set_abs_params(input_dev, ABS_X,
+ 0, data->max_x, 0, 0);
+@@ -1684,6 +1727,8 @@ static int mxt_input_dev_create(struct mxt_data *data)
+ 0, data->max_y, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE,
+ 0, 255, 0, 0);
++ input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
++ input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
+
+ /* For multi touch */
+ num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
+@@ -1699,6 +1744,8 @@ static int mxt_input_dev_create(struct mxt_data *data)
+ 0, data->max_y, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+ 0, 255, 0, 0);
++ input_abs_set_res(input_dev, ABS_MT_POSITION_X, MXT_PIXELS_PER_MM);
++ input_abs_set_res(input_dev, ABS_MT_POSITION_Y, MXT_PIXELS_PER_MM);
+
+ input_set_drvdata(input_dev, data);
+
+@@ -1730,6 +1777,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ return -ENOMEM;
+ }
+
++ data->is_tp = !strcmp(id->name, "atmel_mxt_tp");
+ snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
+ client->adapter->nr, client->addr);
+
+@@ -1863,6 +1911,7 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
+ static const struct i2c_device_id mxt_id[] = {
+ { "qt602240_ts", 0 },
+ { "atmel_mxt_ts", 0 },
++ { "atmel_mxt_tp", 0 },
+ { "mXT224", 0 },
+ { }
+ };
diff --git a/patches/linux-3.8.13/0528-CHROMIUM-Input-atmel_mxt_ts-Read-resolution-from-dev.patch b/patches/linux-3.8.13/0528-CHROMIUM-Input-atmel_mxt_ts-Read-resolution-from-dev.patch
new file mode 100644
index 0000000..878c608
--- /dev/null
+++ b/patches/linux-3.8.13/0528-CHROMIUM-Input-atmel_mxt_ts-Read-resolution-from-dev.patch
@@ -0,0 +1,130 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Tue, 1 May 2012 16:58:46 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Read resolution from device
+ memory
+
+Currently mxt_calc_resolution() computes device resolution from
+provided platform data. Since we are going to support loading
+configuration data from file instead of platform data, we rework
+mxt_calc_resolution() so it reads the actual resolution from the
+configured device memory.
+
+And also move mxt_calc_resolution() into mxt_initialize() after
+the device is configured.
+
+BUG=chrome-os-partner:9103
+TEST=Use evtest to check that the range of ABS_X/Y and
+ ABS_MT_POSITION_X/Y are correct.
+
+Change-Id: Ibf66af4c656b138b52ce5608d7357bf15ee423ac
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+Reviewed-on: https://gerrit.chromium.org/gerrit/21544
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 51 +++++++++++++++++++++++-------
+ 1 file changed, 40 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 3b9007c..95abf18 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -299,6 +299,7 @@ struct mxt_data {
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+ static struct dentry *mxt_debugfs_root;
+
++static int mxt_calc_resolution(struct mxt_data *data);
+ static void mxt_free_object_table(struct mxt_data *data);
+ static int mxt_initialize(struct mxt_data *data);
+ static int mxt_input_dev_create(struct mxt_data *data);
+@@ -1131,14 +1132,17 @@ static int mxt_initialize(struct mxt_data *data)
+ mxt_handle_pdata(data);
+
+ /* Backup to memory */
+- mxt_write_object(data, MXT_GEN_COMMAND_T6,
+- MXT_COMMAND_BACKUPNV,
+- MXT_BACKUP_VALUE);
++ error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
++ if (error)
++ return error;
+ msleep(MXT_BACKUP_TIME);
+
+ /* Soft reset */
+- mxt_write_object(data, MXT_GEN_COMMAND_T6,
+- MXT_COMMAND_RESET, 1);
++ error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_RESET, 1);
++ if (error)
++ return error;
+ msleep(MXT_RESET_TIME);
+
+ /* Update matrix size at info struct */
+@@ -1162,6 +1166,10 @@ static int mxt_initialize(struct mxt_data *data)
+ info->matrix_xsize, info->matrix_ysize,
+ info->object_num);
+
++ error = mxt_calc_resolution(data);
++ if (error)
++ return error;
++
+ return 0;
+
+ err_free_object_table:
+@@ -1169,18 +1177,41 @@ err_free_object_table:
+ return error;
+ }
+
+-static void mxt_calc_resolution(struct mxt_data *data)
++static int mxt_calc_resolution(struct mxt_data *data)
+ {
+- unsigned int max_x = data->pdata->x_size - 1;
+- unsigned int max_y = data->pdata->y_size - 1;
++ struct i2c_client *client = data->client;
++ u8 orient;
++ __le16 xyrange[2];
++ unsigned int max_x, max_y;
++ int ret;
+
+- if (data->pdata->orient & MXT_XY_SWITCH) {
++ struct mxt_object *T9 = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
++ if (T9 == NULL)
++ return -EINVAL;
++
++ /* Get touchscreen resolution */
++ ret = __mxt_read_reg(client, T9->start_address + MXT_TOUCH_XRANGE_LSB,
++ 4, xyrange);
++ if (ret)
++ return ret;
++
++ ret = __mxt_read_reg(client, T9->start_address + MXT_TOUCH_ORIENT,
++ 1, &orient);
++ if (ret)
++ return ret;
++
++ max_x = le16_to_cpu(xyrange[0]);
++ max_y = le16_to_cpu(xyrange[1]);
++
++ if (orient & MXT_XY_SWITCH) {
+ data->max_x = max_y;
+ data->max_y = max_x;
+ } else {
+ data->max_x = max_x;
+ data->max_y = max_y;
+ }
++
++ return 0;
+ }
+
+ /*
+@@ -1789,8 +1820,6 @@ static int __devinit mxt_probe(struct i2c_client *client,
+
+ init_completion(&data->bl_completion);
+
+- mxt_calc_resolution(data);
+-
+ if (mxt_in_bootloader(data)) {
+ dev_info(&client->dev, "Device in bootloader at probe\n");
+ } else {
diff --git a/patches/linux-3.8.13/0529-CHROMIUM-Input-atmel_mxt_ts-Report-TOUCH-MAJOR-in-te.patch b/patches/linux-3.8.13/0529-CHROMIUM-Input-atmel_mxt_ts-Report-TOUCH-MAJOR-in-te.patch
new file mode 100644
index 0000000..7fce353
--- /dev/null
+++ b/patches/linux-3.8.13/0529-CHROMIUM-Input-atmel_mxt_ts-Report-TOUCH-MAJOR-in-te.patch
@@ -0,0 +1,147 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Fri, 25 May 2012 13:55:26 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Report TOUCH MAJOR in terms
+ of pixels
+
+The TCHAREA field reported from the device is in terms of channels
+covered by the touch, while ABS_MT_TOUCH_MAJOR is expected to be in
+the units the same as the configured device resolution. So we
+approximate the touch contact as a circle, convert the touch area
+from channel numbers to pixel numbers, and compute the diameter of
+the circle touch as the value of ABS_MT_TOUCH_MAJOR.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:9968
+TEST=using evtest to check the range of ABS_MT_TOUCH_MAJOR is now
+ somewhat between 50 ~ 100, instead of 1 ~ 10 while making
+ normal touching.
+
+Change-Id: I9972a4989a18b9fbe4fdf1edd70330a4e9df3f85
+Reviewed-on: https://gerrit.chromium.org/gerrit/24530
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Reviewed-by: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 40 ++++++++++++++++++++++++++++--
+ 1 file changed, 38 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 95abf18..66b6f70 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -273,6 +273,10 @@ struct mxt_data {
+ unsigned int max_x;
+ unsigned int max_y;
+
++ /* max touchscreen area in terms of pixels and channels */
++ unsigned int max_area_pixels;
++ unsigned int max_area_channels;
++
+ u32 info_csum;
+ u32 config_csum;
+
+@@ -639,6 +643,23 @@ static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
+ dev_dbg(dev, "Button state: %d\n", button);
+ }
+
++/*
++ * Assume a circle touch contact and use the diameter as the touch major.
++ * touch_pixels = touch_channels * (max_area_pixels / max_area_channels)
++ * touch_pixels = pi * (touch_major / 2) ^ 2;
++ */
++static int get_touch_major_pixels(struct mxt_data *data, int touch_channels)
++{
++ int touch_pixels;
++
++ if (data->max_area_channels == 0)
++ return 0;
++
++ touch_pixels = DIV_ROUND_CLOSEST(touch_channels * data->max_area_pixels,
++ data->max_area_channels);
++ return int_sqrt(DIV_ROUND_CLOSEST(touch_pixels * 100, 314)) * 2;
++}
++
+ static void mxt_input_touchevent(struct mxt_data *data,
+ struct mxt_message *message, int id)
+ {
+@@ -649,6 +670,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ int y;
+ int area;
+ int pressure;
++ int touch_major;
+
+ x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
+ y = (message->message[2] << 4) | ((message->message[3] & 0xf));
+@@ -658,6 +680,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ y = y >> 2;
+
+ area = message->message[4];
++ touch_major = get_touch_major_pixels(data, area);
+ pressure = message->message[5];
+
+ dev_dbg(dev,
+@@ -681,7 +704,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
+- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area);
++ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch_major);
+ }
+ }
+
+@@ -1183,6 +1206,7 @@ static int mxt_calc_resolution(struct mxt_data *data)
+ u8 orient;
+ __le16 xyrange[2];
+ unsigned int max_x, max_y;
++ u8 xylines[2];
+ int ret;
+
+ struct mxt_object *T9 = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
+@@ -1200,6 +1224,11 @@ static int mxt_calc_resolution(struct mxt_data *data)
+ if (ret)
+ return ret;
+
++ ret = __mxt_read_reg(client, T9->start_address + MXT_TOUCH_XSIZE,
++ 2, xylines);
++ if (ret)
++ return ret;
++
+ max_x = le16_to_cpu(xyrange[0]);
+ max_y = le16_to_cpu(xyrange[1]);
+
+@@ -1211,6 +1240,9 @@ static int mxt_calc_resolution(struct mxt_data *data)
+ data->max_y = max_y;
+ }
+
++ data->max_area_pixels = max_x * max_y;
++ data->max_area_channels = xylines[0] * xylines[1];
++
+ return 0;
+ }
+
+@@ -1722,6 +1754,8 @@ static int mxt_input_dev_create(struct mxt_data *data)
+ struct input_dev *input_dev;
+ int error;
+ unsigned int num_mt_slots;
++ int max_area_channels;
++ int max_touch_major;
+
+ data->input_dev = input_dev = input_allocate_device();
+ if (!input_dev)
+@@ -1767,8 +1801,10 @@ static int mxt_input_dev_create(struct mxt_data *data)
+ if (error)
+ goto err_free_device;
+
++ max_area_channels = min(255U, data->max_area_channels);
++ max_touch_major = get_touch_major_pixels(data, max_area_channels);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+- 0, MXT_MAX_AREA, 0, 0);
++ 0, max_touch_major, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, data->max_x, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
diff --git a/patches/linux-3.8.13/0530-CHROMIUM-Input-atmel_mxt_ts-add-new-object-types.patch b/patches/linux-3.8.13/0530-CHROMIUM-Input-atmel_mxt_ts-add-new-object-types.patch
new file mode 100644
index 0000000..cb1823a
--- /dev/null
+++ b/patches/linux-3.8.13/0530-CHROMIUM-Input-atmel_mxt_ts-add-new-object-types.patch
@@ -0,0 +1,78 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Wed, 4 Apr 2012 17:19:55 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add new object types
+
+Add new object types to support newer mxt devices.
+
+BUG=chrome-os-partner:8732
+TEST=None yet.
+
+Change-Id: I5b7c8987ec4d98fc678a939154b7a057338037bd
+Signed-off-by: Benson Leung <bleung@chromium.org>
+Reviewed-on: https://gerrit.chromium.org/gerrit/19638
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 66b6f70..4d67eeb 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -75,6 +75,10 @@
+ #define MXT_PROCI_TOUCHSUPPRESSION_T42 42
+ #define MXT_PROCI_STYLUS_T47 47
+ #define MXT_PROCG_NOISESUPPRESSION_T48 48
++#define MXT_PROCI_ADAPTIVETHRESHOLD_T55 55
++#define MXT_PROCI_SHIELDLESS_T56 56
++#define MXT_PROCI_EXTRATOUCHSCREENDATA_T57 57
++#define MXT_PROCG_NOISESUPPRESSION_T62 62
+ #define MXT_SPT_COMMSCONFIG_T18 18
+ #define MXT_SPT_GPIOPWM_T19 19
+ #define MXT_SPT_SELFTEST_T25 25
+@@ -83,6 +87,7 @@
+ #define MXT_SPT_DIGITIZER_T43 43
+ #define MXT_SPT_MESSAGECOUNT_T44 44
+ #define MXT_SPT_CTECONFIG_T46 46
++#define MXT_SPT_TIMER_T61 61
+
+ /* MXT_GEN_COMMAND_T6 field */
+ #define MXT_COMMAND_RESET 0
+@@ -339,6 +344,10 @@ static bool mxt_object_readable(unsigned int type)
+ case MXT_PROCI_TOUCHSUPPRESSION_T42:
+ case MXT_PROCI_STYLUS_T47:
+ case MXT_PROCG_NOISESUPPRESSION_T48:
++ case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
++ case MXT_PROCI_SHIELDLESS_T56:
++ case MXT_PROCI_EXTRATOUCHSCREENDATA_T57:
++ case MXT_PROCG_NOISESUPPRESSION_T62:
+ case MXT_SPT_COMMSCONFIG_T18:
+ case MXT_SPT_GPIOPWM_T19:
+ case MXT_SPT_SELFTEST_T25:
+@@ -346,6 +355,7 @@ static bool mxt_object_readable(unsigned int type)
+ case MXT_SPT_USERDATA_T38:
+ case MXT_SPT_DIGITIZER_T43:
+ case MXT_SPT_CTECONFIG_T46:
++ case MXT_SPT_TIMER_T61:
+ return true;
+ default:
+ return false;
+@@ -371,12 +381,17 @@ static bool mxt_object_writable(unsigned int type)
+ case MXT_PROCI_TOUCHSUPPRESSION_T42:
+ case MXT_PROCI_STYLUS_T47:
+ case MXT_PROCG_NOISESUPPRESSION_T48:
++ case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
++ case MXT_PROCI_SHIELDLESS_T56:
++ case MXT_PROCI_EXTRATOUCHSCREENDATA_T57:
++ case MXT_PROCG_NOISESUPPRESSION_T62:
+ case MXT_SPT_COMMSCONFIG_T18:
+ case MXT_SPT_GPIOPWM_T19:
+ case MXT_SPT_SELFTEST_T25:
+ case MXT_SPT_CTECONFIG_T28:
+ case MXT_SPT_DIGITIZER_T43:
+ case MXT_SPT_CTECONFIG_T46:
++ case MXT_SPT_TIMER_T61:
+ return true;
+ default:
+ return false;
diff --git a/patches/linux-3.8.13/0531-CHROMIUM-INPUT-atmel_mxt_ts-Increase-the-wait-times-.patch b/patches/linux-3.8.13/0531-CHROMIUM-INPUT-atmel_mxt_ts-Increase-the-wait-times-.patch
new file mode 100644
index 0000000..ca2e2b0
--- /dev/null
+++ b/patches/linux-3.8.13/0531-CHROMIUM-INPUT-atmel_mxt_ts-Increase-the-wait-times-.patch
@@ -0,0 +1,48 @@
+From: Iiro Valkonen <iiro.valkonen@atmel.com>
+Date: Fri, 29 Apr 2011 09:37:45 -0400
+Subject: [PATCH] CHROMIUM: INPUT: atmel_mxt_ts - Increase the wait times for
+ backup and reset
+
+Increase the sleep times after backup and reset, so that we can be sure they have been completed even when the mXT cycle time is set to maximum value (254ms).
+
+Signed-off-by: Iiro Valkonen <iiro.valkonen@atmel.com>
+Patch is in progress of being submitted at http://www.spinics.net/lists/linux-input/msg14593.html
+Signed-off-by: Jon Kliegman <kliegs@chromium.org>
+
+R=olofj@chromium.org, msb@chromium.org
+BUG=chromium-os:13514
+TEST=Built kernel
+ Validated kernel boots fine
+ Validated in conjunction with other CLs in bug that the driver works
+
+Cherrypicking forward to 3.0 branch from 2.6.38
+(cherry picked from commit 1ebffd5d7df2202b20eee3c906096ff7f1d6c56a)
+
+Cherrypicking forward to 2.6.38 branch from http://codereview.chromium.org/6711073
+(cherry picked from commit 4dc5fe662e1352e12181ba4cfeb0f8333486c882)
+
+Review URL: http://codereview.chromium.org/6893098
+Patch from Iiro Valkonen <iiro.valkonen@atmel.com>.
+
+Change-Id: I487c75fd05d5eb7b6223b5a3b79d34076d096726
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+Reviewed-on: http://gerrit.chromium.org/gerrit/8773
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 4d67eeb..2f22ae1 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -195,8 +195,8 @@
+ /* Define for MXT_GEN_COMMAND_T6 */
+ #define MXT_BOOT_VALUE 0xa5
+ #define MXT_BACKUP_VALUE 0x55
+-#define MXT_BACKUP_TIME 25 /* msec */
+-#define MXT_RESET_TIME 65 /* msec */
++#define MXT_BACKUP_TIME 270 /* msec */
++#define MXT_RESET_TIME 350 /* msec */
+ #define MXT_CAL_TIME 25 /* msec */
+
+ #define MXT_FWRESET_TIME 500 /* msec */
diff --git a/patches/linux-3.8.13/0532-CHROMIUM-Input-atmel_mxt_ts-dump-mxt_read-write_reg.patch b/patches/linux-3.8.13/0532-CHROMIUM-Input-atmel_mxt_ts-dump-mxt_read-write_reg.patch
new file mode 100644
index 0000000..ba3816a
--- /dev/null
+++ b/patches/linux-3.8.13/0532-CHROMIUM-Input-atmel_mxt_ts-dump-mxt_read-write_reg.patch
@@ -0,0 +1,91 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Wed, 15 Feb 2012 16:32:02 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - dump mxt_read/write_reg
+
+For verbose on-the-wire debugging.
+Prints DUMP_LEN bytes (in hex) per line.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=builds clean w/ & w/out DEBUG defined.
+ If DEBUG defined, bytes read & written over i2c by atmel_mxt_ts should
+ appear in /var/log/messages
+
+Change-Id: Ib1b8301a25bb915fea47e4dd62ff261ae5284c3c
+Reviewed-on: https://gerrit.chromium.org/gerrit/17943
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 35 +++++++++++++++++++++++++++++-
+ 1 file changed, 34 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 2f22ae1..50fe84a 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -546,11 +546,39 @@ static int mxt_fw_write(struct i2c_client *client,
+ return mxt_i2c_send(client, data, frame_size);
+ }
+
++#ifdef DEBUG
++#define DUMP_LEN 16
++static void mxt_dump_xfer(struct device *dev, const char *func, u16 reg,
++ u16 len, const u8 *val)
++{
++ /* Rough guess for string size */
++ char str[DUMP_LEN * 3 + 2];
++ int i;
++ size_t n;
++
++ for (i = 0, n = 0; i < len; i++) {
++ n += snprintf(&str[n], sizeof(str) - n, "%02x ", val[i]);
++ if ((i + 1) % DUMP_LEN == 0 || (i + 1) == len) {
++ dev_dbg(dev,
++ "%s(reg: %d len: %d offset: 0x%02x): %s\n",
++ func, reg, len, (i / DUMP_LEN) * DUMP_LEN,
++ str);
++ n = 0;
++ }
++ }
++}
++#undef DUMP_LEN
++#else
++static void mxt_dump_xfer(struct device *dev, const char *func, u16 reg,
++ u16 len, const u8 *val) { }
++#endif
++
+ static int __mxt_read_reg(struct i2c_client *client,
+ u16 reg, u16 len, void *val)
+ {
+ struct i2c_msg xfer[2];
+ u8 buf[2];
++ int ret;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+@@ -567,7 +595,11 @@ static int __mxt_read_reg(struct i2c_client *client,
+ xfer[1].len = len;
+ xfer[1].buf = val;
+
+- return mxt_i2c_transfer(client, xfer, 2);
++ ret = mxt_i2c_transfer(client, xfer, 2);
++ if (ret == 0)
++ mxt_dump_xfer(&client->dev, __func__, reg, len, val);
++
++ return ret;
+ }
+
+ static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
+@@ -591,6 +623,7 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
+ buf[1] = (reg >> 8) & 0xff;
+ memcpy(&buf[2], val, len);
+
++ mxt_dump_xfer(&client->dev, __func__, reg, len, val);
+ ret = mxt_i2c_send(client, buf, count);
+ kfree(buf);
+ return ret;
diff --git a/patches/linux-3.8.13/0533-CHROMIUM-Input-atmel_mxt_ts-take-an-instance-for-mxt.patch b/patches/linux-3.8.13/0533-CHROMIUM-Input-atmel_mxt_ts-take-an-instance-for-mxt.patch
new file mode 100644
index 0000000..1a93854
--- /dev/null
+++ b/patches/linux-3.8.13/0533-CHROMIUM-Input-atmel_mxt_ts-take-an-instance-for-mxt.patch
@@ -0,0 +1,59 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Wed, 12 Dec 2012 15:27:51 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - take an instance for
+ mxt_write_object
+
+Objects in the object table can have multiple instances.
+Force writes to specify a particular instance.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=build clean; atmel touch device configured and enabled correctly.
+
+Change-Id: Ic7208b2b994b490528cce7b2d780bf5497e0d1db
+Reviewed-on: https://gerrit.chromium.org/gerrit/18432
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 50fe84a..d07732d 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -665,18 +665,24 @@ static int mxt_read_message(struct mxt_data *data,
+ sizeof(struct mxt_message), message);
+ }
+
+-static int mxt_write_object(struct mxt_data *data,
+- u8 type, u8 offset, u8 val)
++static int mxt_write_obj_instance(struct mxt_data *data, u8 type, u8 instance,
++ u8 offset, u8 val)
+ {
+ struct mxt_object *object;
+ u16 reg;
+
+ object = mxt_get_object(data, type);
+- if (!object || offset >= mxt_obj_size(object))
++ if (!object || offset >= mxt_obj_size(object) ||
++ instance >= mxt_obj_instances(object))
+ return -EINVAL;
+
+- reg = object->start_address;
+- return mxt_write_reg(data->client, reg + offset, val);
++ reg = object->start_address + instance * mxt_obj_size(object) + offset;
++ return mxt_write_reg(data->client, reg, val);
++}
++
++static int mxt_write_object(struct mxt_data *data, u8 type, u8 offset, u8 val)
++{
++ return mxt_write_obj_instance(data, type, 0, offset, val);
+ }
+
+ static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
diff --git a/patches/linux-3.8.13/0534-CHROMIUM-Input-atmel_mxt_ts-allow-writing-to-object-.patch b/patches/linux-3.8.13/0534-CHROMIUM-Input-atmel_mxt_ts-allow-writing-to-object-.patch
new file mode 100644
index 0000000..6558816
--- /dev/null
+++ b/patches/linux-3.8.13/0534-CHROMIUM-Input-atmel_mxt_ts-allow-writing-to-object-.patch
@@ -0,0 +1,108 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 19 Mar 2012 09:39:12 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - allow writing to object
+ sysfs entry
+
+Userspace can write a 32-bit value (encoded as a 8 character hex string)
+to the 'object' sysfs entry to modify a single byte of the object table.
+The hex string encodes 4 bytes, in the following format:
+
+ TTIIFFVV
+
+Where:
+ TT = object type (atmel 'T' number)
+ II = object instance (0-indexes, so 0 is the first instance)
+ FF = object offset
+ VV = byte value
+
+The object table is modified in device ram, which means the change is
+volatile, and will be overwritten on the next device reset. To make
+changes permanent, the new settings should be persisted in the device's
+Non-Voltatile Memory using the updatenv sysfs entry.
+
+Also, since the device driver initializes itself by reading some values
+from the object table, the entire driver may need to be unloaded and
+reloaded after writing the values for the driver to stay in sync. Whether
+this is required depends on exactly which values were updated.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=ls -l /sys/.../object
+ --wr--r--r 1 root root 4096 Feb 14 20:54 update_fw
+
+ (0) confirm current number of fingers (look for (Type 9, Offset 14)):
+ $ cat /sys/.../object
+ (1) Change number of reported fingers (Type: 0x09, Offset: 0x0e) to 7:
+ $ echo -n "090e07" > /sys/.../object
+ (2) confirm current number of fingers (look for (Type 9, Offset 14)):
+ $ cat /sys/.../object
+ (3) using mtplot, notice that there now up to 7 fingers are reported.
+ (4) reboot, and verify that the old number of fingers is restored.
+TEST=Trying to write to a non-existant instance, or past the length of
+ an object, should fail. For example:
+ echo -n "070005ab" > /sys/bus/i2c/devices/<dev>/object
+ => -bash: echo: write error: Invalid argument
+
+Change-Id: I8149770f762a84ef457c7bf4aefdb310d07c52c5
+Reviewed-on: https://gerrit.chromium.org/gerrit/17944
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 32 +++++++++++++++++++++++++++++-
+ 1 file changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index d07732d..120d766 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1552,6 +1552,35 @@ done:
+ return error ?: count;
+ }
+
++static ssize_t mxt_object_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ int ret;
++ u32 param;
++ u8 type, instance, offset, val;
++
++ ret = kstrtou32(buf, 16, &param);
++ if (ret < 0)
++ return -EINVAL;
++
++ /*
++ * Byte Write Command is encoded in 32-bit word: TTIIOOVV:
++ * <Type> <Instance> <Offset> <Value>
++ */
++ type = (param & 0xff000000) >> 24;
++ instance = (param & 0x00ff0000) >> 16;
++ offset = (param & 0x0000ff00) >> 8;
++ val = param & 0x000000ff;
++
++ ret = mxt_write_obj_instance(data, type, instance, offset, val);
++ if (ret)
++ return ret;
++
++ return count;
++}
++
+ static int mxt_load_fw(struct device *dev, const char *fn)
+ {
+ struct mxt_data *data = dev_get_drvdata(dev);
+@@ -1639,7 +1668,8 @@ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+ static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
+ static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL);
+-static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
++static DEVICE_ATTR(object, S_IRUGO | S_IWUSR, mxt_object_show,
++ mxt_object_store);
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+ static struct attribute *mxt_attrs[] = {
diff --git a/patches/linux-3.8.13/0535-CHROMIUM-Input-atmel_mxt_ts-add-backupnv-sysfs-entry.patch b/patches/linux-3.8.13/0535-CHROMIUM-Input-atmel_mxt_ts-add-backupnv-sysfs-entry.patch
new file mode 100644
index 0000000..e34db9d
--- /dev/null
+++ b/patches/linux-3.8.13/0535-CHROMIUM-Input-atmel_mxt_ts-add-backupnv-sysfs-entry.patch
@@ -0,0 +1,72 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 19 Mar 2012 10:09:41 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add backupnv sysfs entry
+
+Writing to the object sysfs entry permits individual object table entries
+to be modified in the device RAM at runtime. To permanently save
+the settings, they must be written to Non-Volatile memory (NVM).
+This patch adds a write-only sysfs entry to allow userspace to save
+current settings to NVM, but restricts access to root.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=ls -al /sys/.../backupnv
+ -> --w------- 1 root root 4096 Feb 14 20:54 backupnv
+
+Change-Id: Id767e0b7ef7f882d6a45ebfe7e96e02800ef2cb8
+Reviewed-on: https://gerrit.chromium.org/gerrit/17945
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 120d766..c2891f2 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1427,6 +1427,23 @@ out:
+ return ret ?: 0;
+ }
+
++static ssize_t mxt_backupnv_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ int ret;
++
++ /* Backup non-volatile memory */
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
++ if (ret)
++ return ret;
++ msleep(MXT_BACKUP_TIME);
++
++ return count;
++}
++
+ static ssize_t mxt_calibrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+@@ -1662,6 +1679,7 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ return count;
+ }
+
++static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store);
+ static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
+ static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
+ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+@@ -1673,6 +1691,7 @@ static DEVICE_ATTR(object, S_IRUGO | S_IWUSR, mxt_object_show,
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+ static struct attribute *mxt_attrs[] = {
++ &dev_attr_backupnv.attr,
+ &dev_attr_calibrate.attr,
+ &dev_attr_config_csum.attr,
+ &dev_attr_fw_version.attr,
diff --git a/patches/linux-3.8.13/0536-CHROMIUM-Input-atmel_mxt_ts-read-num-messages-then-a.patch b/patches/linux-3.8.13/0536-CHROMIUM-Input-atmel_mxt_ts-read-num-messages-then-a.patch
new file mode 100644
index 0000000..e1c36fc
--- /dev/null
+++ b/patches/linux-3.8.13/0536-CHROMIUM-Input-atmel_mxt_ts-read-num-messages-then-a.patch
@@ -0,0 +1,237 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 19 Mar 2012 09:42:09 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - read num messages, then all
+ messages
+
+Implement the MXT DMA method of reading messages.
+On an interrupt, the T44 report always contains the number of messages
+pending to be read. So, read 1 byte from T44 in 1 i2c transaction, then
+read the N pending messages in a second transaction.
+
+The end result is a much much faster read time for all pending messages.
+Using 400kHz i2c, it is possible to read 10 pending messages (e.g. for 10
+moving contatcts) in less than 2.8ms, which is well less than the typical
+10-15ms update rate.
+
+Note: There is a possible optimization here. The T44 byte is guaranteed
+to always be right before the T5 address. Thus, it should be possible
+to always fetch the T44 message count and the first message in a single
+transaction. This would eliminate the overhead of a second complete read
+transaction for the case where there is only a single pending message.
+(This is actually the most common case, for instance with just 1-contact
+on the device touch surface). This optimization, however, is not done in
+this patch.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=builds clean; all pending messages are processed for each interrupt.
+
+Change-Id: I9aa4627d2afdc6da14b7495e78c429d1c4ded7ae
+Reviewed-on: https://gerrit.chromium.org/gerrit/17956
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 138 +++++++++++++++++++-----------
+ 1 file changed, 90 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index c2891f2..8c29fb3 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -286,10 +286,12 @@ struct mxt_data {
+ u32 config_csum;
+
+ /* Cached parameters from object table */
++ u16 T5_address;
+ u8 T6_reportid;
+ u8 T9_reportid_min;
+ u8 T9_reportid_max;
+ u8 T19_reportid;
++ u16 T44_address;
+
+ /* for fw update in bootloader */
+ struct completion bl_completion;
+@@ -650,19 +652,23 @@ mxt_get_object(struct mxt_data *data, u8 type)
+ return NULL;
+ }
+
+-static int mxt_read_message(struct mxt_data *data,
+- struct mxt_message *message)
++static int mxt_read_num_messages(struct mxt_data *data, u8 *count)
+ {
+- struct mxt_object *object;
+- u16 reg;
++ /* TODO: Optimization: read first message along with message count */
++ return __mxt_read_reg(data->client, data->T44_address, 1, count);
++}
+
+- object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
+- if (!object)
+- return -EINVAL;
++static int mxt_read_messages(struct mxt_data *data, u8 count,
++ struct mxt_message *messages)
++{
++ return __mxt_read_reg(data->client, data->T5_address,
++ sizeof(struct mxt_message) * count, messages);
++}
+
+- reg = object->start_address;
+- return __mxt_read_reg(data->client, reg,
+- sizeof(struct mxt_message), message);
++static int mxt_read_message(struct mxt_data *data,
++ struct mxt_message *message)
++{
++ return mxt_read_messages(data, 1, message);
+ }
+
+ static int mxt_write_obj_instance(struct mxt_data *data, u8 type, u8 instance,
+@@ -773,6 +779,72 @@ static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
+ return (id >= data->T9_reportid_min && id <= data->T9_reportid_max);
+ }
+
++static int mxt_proc_messages(struct mxt_data *data, u8 count)
++{
++ struct device *dev = &data->client->dev;
++ u8 reportid;
++ bool update_input = false;
++ struct mxt_message *messages, *msg;
++ int ret;
++
++ messages = kcalloc(count, sizeof(*messages), GFP_KERNEL);
++ if (!messages)
++ return -ENOMEM;
++
++ ret = mxt_read_messages(data, count, messages);
++ if (ret) {
++ dev_err(dev, "Failed to read %u messages (%d).\n", count, ret);
++ goto out;
++ }
++
++ for (msg = messages; msg < &messages[count]; msg++) {
++ mxt_dump_message(dev, msg);
++ reportid = msg->reportid;
++
++ if (reportid == data->T6_reportid) {
++ const u8 *payload = &msg->message[0];
++ u8 status = payload[0];
++ data->config_csum = mxt_extract_T6_csum(&payload[1]);
++ dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
++ status, data->config_csum);
++ } else if (mxt_is_T9_message(data, msg)) {
++ int id = reportid - data->T9_reportid_min;
++ mxt_input_touchevent(data, msg, id);
++ update_input = true;
++ } else if (msg->reportid == data->T19_reportid) {
++ mxt_input_button(data, msg);
++ update_input = true;
++ }
++ }
++
++ if (update_input) {
++ input_mt_report_pointer_emulation(data->input_dev, false);
++ input_sync(data->input_dev);
++ }
++
++out:
++ kfree(messages);
++ return ret;
++}
++
++static int mxt_handle_messages(struct mxt_data *data)
++{
++ struct device *dev = &data->client->dev;
++ int ret;
++ u8 count;
++
++ ret = mxt_read_num_messages(data, &count);
++ if (ret) {
++ dev_err(dev, "Failed to read message count (%d).\n", ret);
++ return ret;
++ }
++
++ if (count > 0)
++ ret = mxt_proc_messages(data, count);
++
++ return ret;
++}
++
+ static int mxt_enter_bl(struct mxt_data *data)
+ {
+ struct i2c_client *client = data->client;
+@@ -863,49 +935,13 @@ static void mxt_exit_bl(struct mxt_data *data)
+ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+ {
+ struct mxt_data *data = dev_id;
+- struct mxt_message message;
+- const u8 *payload = &message.message[0];
+- struct device *dev = &data->client->dev;
+- u8 reportid;
+- bool update_input = false;
+
+ if (mxt_in_bootloader(data)) {
+ /* bootloader state transition completion */
+ complete(&data->bl_completion);
+- goto end;
+- }
+-
+- do {
+- if (mxt_read_message(data, &message)) {
+- dev_err(dev, "Failed to read message\n");
+- goto end;
+- }
+-
+- reportid = message.reportid;
+-
+- if (reportid == data->T6_reportid) {
+- u8 status = payload[0];
+- data->config_csum = mxt_extract_T6_csum(&payload[1]);
+- dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
+- status, data->config_csum);
+- } else if (mxt_is_T9_message(data, &message)) {
+- int id = reportid - data->T9_reportid_min;
+- mxt_input_touchevent(data, &message, id);
+- update_input = true;
+- } else if (message.reportid == data->T19_reportid) {
+- mxt_input_button(data, &message);
+- update_input = true;
+- } else {
+- mxt_dump_message(dev, &message);
+- }
+- } while (reportid != 0xff);
+-
+- if (update_input) {
+- input_mt_report_pointer_emulation(data->input_dev, false);
+- input_sync(data->input_dev);
++ } else {
++ mxt_handle_messages(data);
+ }
+-
+-end:
+ return IRQ_HANDLED;
+ }
+
+@@ -1151,6 +1187,9 @@ static int mxt_get_object_table(struct mxt_data *data)
+ min_id, max_id);
+
+ switch (object->type) {
++ case MXT_GEN_MESSAGE_T5:
++ data->T5_address = object->start_address;
++ break;
+ case MXT_GEN_COMMAND_T6:
+ data->T6_reportid = min_id;
+ break;
+@@ -1161,6 +1200,9 @@ static int mxt_get_object_table(struct mxt_data *data)
+ case MXT_SPT_GPIOPWM_T19:
+ data->T19_reportid = min_id;
+ break;
++ case MXT_SPT_MESSAGECOUNT_T44:
++ data->T44_address = object->start_address;
++ break;
+ }
+ }
+
diff --git a/patches/linux-3.8.13/0537-CHROMIUM-Input-atmel_mxt_ts-remove-mxt_make_highchg.patch b/patches/linux-3.8.13/0537-CHROMIUM-Input-atmel_mxt_ts-remove-mxt_make_highchg.patch
new file mode 100644
index 0000000..63c45ff
--- /dev/null
+++ b/patches/linux-3.8.13/0537-CHROMIUM-Input-atmel_mxt_ts-remove-mxt_make_highchg.patch
@@ -0,0 +1,104 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Wed, 19 Dec 2012 17:48:36 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - remove mxt_make_highchg
+
+This function attempts to make the CHG pin high by reading a messages
+until the device queue is empty.
+
+Instead of throwing away the message contents, let's actually process them.
+Also, instead of stopping after a fixed (10) number of messages, keep
+reading until the device reports that it has no more valid messages - at
+that point, the CHG line should truly be high.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=builds clean; messages after boot are processed;
+ Config Checksum displayed in dmesg:
+ $ grep "Config Checksum" /var/log/messages
+
+Change-Id: I3d1e266d1ac53f5640e65c5acc3fe6672a0c1451
+Reviewed-on: https://gerrit.chromium.org/gerrit/17957
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 33 ++----------------------------
+ 1 file changed, 2 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 8c29fb3..8dfdba9 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -314,7 +314,6 @@ static int mxt_calc_resolution(struct mxt_data *data);
+ static void mxt_free_object_table(struct mxt_data *data);
+ static int mxt_initialize(struct mxt_data *data);
+ static int mxt_input_dev_create(struct mxt_data *data);
+-static int mxt_make_highchg(struct mxt_data *data);
+
+ static inline size_t mxt_obj_size(const struct mxt_object *obj)
+ {
+@@ -665,12 +664,6 @@ static int mxt_read_messages(struct mxt_data *data, u8 count,
+ sizeof(struct mxt_message) * count, messages);
+ }
+
+-static int mxt_read_message(struct mxt_data *data,
+- struct mxt_message *message)
+-{
+- return mxt_read_messages(data, 1, message);
+-}
+-
+ static int mxt_write_obj_instance(struct mxt_data *data, u8 type, u8 instance,
+ u8 offset, u8 val)
+ {
+@@ -925,7 +918,7 @@ static void mxt_exit_bl(struct mxt_data *data)
+ return;
+ }
+
+- error = mxt_make_highchg(data);
++ error = mxt_handle_messages(data);
+ if (error)
+ dev_err(dev, "Failed to clear CHG after init. error = %d\n",
+ error);
+@@ -981,28 +974,6 @@ static int mxt_check_reg_init(struct mxt_data *data)
+ return 0;
+ }
+
+-static int mxt_make_highchg(struct mxt_data *data)
+-{
+- struct device *dev = &data->client->dev;
+- struct mxt_message message;
+- int count = 10;
+- int error;
+-
+- /* Read dummy message to make high CHG pin */
+- do {
+- error = mxt_read_message(data, &message);
+- if (error)
+- return error;
+- } while (message.reportid != 0xff && --count);
+-
+- if (!count) {
+- dev_err(dev, "CHG pin isn't cleared\n");
+- return -EBUSY;
+- }
+-
+- return 0;
+-}
+-
+ static void mxt_handle_pdata(struct mxt_data *data)
+ {
+ const struct mxt_platform_data *pdata = data->pdata;
+@@ -2025,7 +1996,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ }
+
+ if (!mxt_in_bootloader(data)) {
+- error = mxt_make_highchg(data);
++ error = mxt_handle_messages(data);
+ if (error)
+ goto err_free_irq;
+ }
diff --git a/patches/linux-3.8.13/0538-CHROMIUM-Input-atmel_mxt_ts-Remove-matrix-size-updat.patch b/patches/linux-3.8.13/0538-CHROMIUM-Input-atmel_mxt_ts-Remove-matrix-size-updat.patch
new file mode 100644
index 0000000..c1cdfc7
--- /dev/null
+++ b/patches/linux-3.8.13/0538-CHROMIUM-Input-atmel_mxt_ts-Remove-matrix-size-updat.patch
@@ -0,0 +1,64 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Tue, 1 May 2012 17:31:04 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Remove matrix size update
+
+The matrix x/y size in the Info Block represents the max x/y lines
+availble on the device and it will only be updated by the firmware
+but not the platform data configuration, which sets the x/y lines
+in T9 object.
+
+BUG=None
+TEST=None
+
+Change-Id: I18e4f9855fe2018c2b55256ce25821a6197b9f81
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+Reviewed-on: https://gerrit.chromium.org/gerrit/21547
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 17 -----------------
+ 1 file changed, 17 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 8dfdba9..71a5317 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -603,11 +603,6 @@ static int __mxt_read_reg(struct i2c_client *client,
+ return ret;
+ }
+
+-static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
+-{
+- return __mxt_read_reg(client, reg, 1, val);
+-}
+-
+ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
+ const void *val)
+ {
+@@ -1195,7 +1190,6 @@ static int mxt_initialize(struct mxt_data *data)
+ struct i2c_client *client = data->client;
+ struct mxt_info *info = &data->info;
+ int error;
+- u8 val;
+
+ error = mxt_get_info(data);
+ if (error)
+@@ -1235,17 +1229,6 @@ static int mxt_initialize(struct mxt_data *data)
+ return error;
+ msleep(MXT_RESET_TIME);
+
+- /* Update matrix size at info struct */
+- error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
+- if (error)
+- goto err_free_object_table;
+- info->matrix_xsize = val;
+-
+- error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
+- if (error)
+- goto err_free_object_table;
+- info->matrix_ysize = val;
+-
+ dev_info(&client->dev,
+ "Family ID: %u Variant ID: %u Major.Minor.Build: %u.%u.%02X\n",
+ info->family_id, info->variant_id, info->version >> 4,
diff --git a/patches/linux-3.8.13/0539-CHROMIUM-Input-atmel_mxt_ts-parse-vector-field-of-da.patch b/patches/linux-3.8.13/0539-CHROMIUM-Input-atmel_mxt_ts-parse-vector-field-of-da.patch
new file mode 100644
index 0000000..53f60b1
--- /dev/null
+++ b/patches/linux-3.8.13/0539-CHROMIUM-Input-atmel_mxt_ts-parse-vector-field-of-da.patch
@@ -0,0 +1,69 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Mon, 20 Feb 2012 23:35:06 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - parse vector field of data
+ packets
+
+The atmel_mxt_ts T9 data contains information orientation in its 'vector'
+field. Parse and debug print its contents, although its value isn't
+actually used yet.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chromium-os:27713
+TEST=builds clean; vector values are reported when DEBUG is defined.
+
+Change-Id: Ida4d9aa167e5134c76d044599240a6c7e329a62c
+Reviewed-on: https://gerrit.chromium.org/gerrit/17951
+Commit-Ready: Daniel Kurtz <djkurtz@chromium.org>
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Tested-by: Daniel Kurtz <djkurtz@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 71a5317..1882e14 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -719,6 +719,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ int area;
+ int pressure;
+ int touch_major;
++ int vector1, vector2;
+
+ x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
+ y = (message->message[2] << 4) | ((message->message[3] & 0xf));
+@@ -731,8 +732,12 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ touch_major = get_touch_major_pixels(data, area);
+ pressure = message->message[5];
+
++ /* The two vector components are 4-bit signed ints (2s complement) */
++ vector1 = (signed)((signed char)message->message[6]) >> 4;
++ vector2 = (signed)((signed char)(message->message[6] << 4)) >> 4;
++
+ dev_dbg(dev,
+- "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n",
++ "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u vector: [%d,%d]\n",
+ id,
+ (status & MXT_DETECT) ? 'D' : '.',
+ (status & MXT_PRESS) ? 'P' : '.',
+@@ -742,7 +747,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ (status & MXT_AMP) ? 'A' : '.',
+ (status & MXT_SUPPRESS) ? 'S' : '.',
+ (status & MXT_UNGRIP) ? 'U' : '.',
+- x, y, area, pressure);
++ x, y, area, pressure, vector1, vector2);
+
+ input_mt_slot(input_dev, id);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+@@ -753,6 +758,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
+ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch_major);
++ /* TODO: Use vector to report ORIENTATION & TOUCH_MINOR */
+ }
+ }
+
diff --git a/patches/linux-3.8.13/0540-CHROMIUM-Input-atmel_mxt_ts-Add-IDLE-DEEP-SLEEP-mode.patch b/patches/linux-3.8.13/0540-CHROMIUM-Input-atmel_mxt_ts-Add-IDLE-DEEP-SLEEP-mode.patch
new file mode 100644
index 0000000..639a5de
--- /dev/null
+++ b/patches/linux-3.8.13/0540-CHROMIUM-Input-atmel_mxt_ts-Add-IDLE-DEEP-SLEEP-mode.patch
@@ -0,0 +1,226 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Fri, 4 May 2012 20:47:32 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Add IDLE/DEEP-SLEEP modes
+ when suspend
+
+Currently when system enters/leaves sleep mode, the driver dis/enables
+T9 object. It has the limitation that 1) it does not allow the device
+to wakeup the system 2) the device is not in it's best power saving mode
+when the system is sleeping.
+
+This patch adds the support to put the device into 1) Idle mode, when the
+need of wakeup from sleep is needed 2) Deepsleep mode when wakeup from
+sleep is not needed.
+
+To achieve this, when the system enters sleep mode, the current T7 Power
+Config value is first saved and then it is re-configured to be Idle mode
+(with largest Idle Acquisition Interval and largest Active Acquisition
+Interval) or Deepsleep mode. Also if wakeup from sleep is needed, the
+current T9 Ctrl field is saved and a resonable value 0x03 is used to
+enable T9 so that we can be sure touch contact will generate IRQ to wake
+the system up.
+
+When resume, before-suspend T7 and T9 values are restored accordingly.
+
+BUG=chrome-os-partner:9413
+TEST=On system with atmel trackpad
+ cd /sys/bus/i2c/drivers/atmel_mxt_ts/2-004b/power
+ echo "enabled" > wakeup
+ powerd_suspend
+ touch trackpad should wakeup the system
+ echo "disabled" > wakeup
+ powerd_suspend
+ touch trackpad should not wakeup the system
+
+Change-Id: I85896691ddd69d854a923f548edf8b7d6caa9f8e
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+Reviewed-on: https://gerrit.chromium.org/gerrit/21919
+Reviewed-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 134 ++++++++++++++++++++++++++++--
+ 1 file changed, 127 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 1882e14..0804795 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -305,6 +305,20 @@ struct mxt_data {
+ struct mutex T37_buf_mutex;
+ u8 *T37_buf;
+ size_t T37_buf_size;
++
++ /* Saved T7 configuration
++ * [0] = IDLEACQINT
++ * [1] = ACTVACQINT
++ * [2] = ACTV2IDLETO
++ */
++ u8 T7_config[3];
++ bool T7_config_valid;
++
++ /* Saved T9 Ctrl field */
++ u8 T9_ctrl;
++ bool T9_ctrl_valid;
++
++ bool irq_wake; /* irq wake is enabled */
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -1824,6 +1838,44 @@ static int mxt_debugfs_init(struct mxt_data *mxt)
+ return 0;
+ }
+
++static int mxt_save_regs(struct mxt_data *data, u8 type, u8 instance,
++ u8 offset, u8 *val, u16 size)
++{
++ struct mxt_object *object;
++ u16 addr;
++ int ret;
++
++ object = mxt_get_object(data, type);
++ if (!object)
++ return -EINVAL;
++
++ addr = object->start_address + instance * mxt_obj_size(object) + offset;
++ ret = __mxt_read_reg(data->client, addr, size, val);
++ if (ret)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int mxt_set_regs(struct mxt_data *data, u8 type, u8 instance,
++ u8 offset, const u8 *val, u16 size)
++{
++ struct mxt_object *object;
++ u16 addr;
++ int ret;
++
++ object = mxt_get_object(data, type);
++ if (!object)
++ return -EINVAL;
++
++ addr = object->start_address + instance * mxt_obj_size(object) + offset;
++ ret = __mxt_write_reg(data->client, addr, size, val);
++ if (ret)
++ return -EINVAL;
++
++ return 0;
++}
++
+ static void mxt_start(struct mxt_data *data)
+ {
+ /* Touch enable */
+@@ -2036,14 +2088,62 @@ static int mxt_suspend(struct device *dev)
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mxt_data *data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = data->input_dev;
++ static const u8 T7_config_idle[3] = { 0xfe, 0xfe, 0x00 };
++ static const u8 T7_config_deepsleep[3] = { 0x00, 0x00, 0x00 };
++ const u8 *power_config;
++ u8 T9_ctrl = 0x03;
++ int ret;
+
+ if (mxt_in_bootloader(data))
+ return 0;
+
+ mutex_lock(&input_dev->mutex);
+
+- if (input_dev->users)
++ /* Save 3 bytes T7 Power config */
++ ret = mxt_save_regs(data, MXT_GEN_POWER_T7, 0, 0,
++ data->T7_config, 3);
++ if (ret)
++ dev_err(dev, "Save T7 Power config failed, %d\n", ret);
++ data->T7_config_valid = (ret == 0);
++
++ /*
++ * Set T7 to idle mode if we allow wakeup from touch, otherwise
++ * put it into deepsleep mode.
++ */
++ power_config = device_may_wakeup(dev) ? T7_config_idle
++ : T7_config_deepsleep;
++
++ ret = mxt_set_regs(data, MXT_GEN_POWER_T7, 0, 0,
++ power_config, 3);
++ if (ret)
++ dev_err(dev, "Set T7 Power config failed, %d\n", ret);
++
++ if (device_may_wakeup(dev)) {
++ /*
++ * If we allow wakeup from touch, we have to enable T9 so
++ * that IRQ can be generated from touch
++ */
++
++ /* Save 1 byte T9 Ctrl config */
++ ret = mxt_save_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
++ &data->T9_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
++ data->T9_ctrl_valid = (ret == 0);
++
++ /* Enable T9 object */
++ ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
++ &T9_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Set T9 ctrl config failed, %d\n", ret);
++
++ /* Enable wake from IRQ */
++ data->irq_wake = (enable_irq_wake(data->irq) == 0);
++ } else if (input_dev->users) {
+ mxt_stop(data);
++ }
++
++ disable_irq(data->irq);
+
+ mutex_unlock(&input_dev->mutex);
+
+@@ -2055,20 +2155,40 @@ static int mxt_resume(struct device *dev)
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mxt_data *data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = data->input_dev;
++ int ret;
+
+ if (mxt_in_bootloader(data))
+ return 0;
+
+- /* Soft reset */
+- mxt_write_object(data, MXT_GEN_COMMAND_T6,
+- MXT_COMMAND_RESET, 1);
+-
+- msleep(MXT_RESET_TIME);
++ /* Process any pending message so that CHG line can be de-asserted */
++ ret = mxt_handle_messages(data);
++ if (ret)
++ dev_err(dev, "Handling message fails upon resume, %d\n", ret);
+
+ mutex_lock(&input_dev->mutex);
+
+- if (input_dev->users)
++ enable_irq(data->irq);
++
++ if (device_may_wakeup(dev) && data->irq_wake)
++ disable_irq_wake(data->irq);
++
++ /* Restore the T9 Ctrl config to before-suspend value */
++ if (device_may_wakeup(dev) && data->T9_ctrl_valid) {
++ ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
++ &data->T9_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Set T9 ctrl config failed, %d\n", ret);
++ } else if (input_dev->users) {
+ mxt_start(data);
++ }
++
++ /* Restore the T7 Power config to before-suspend value */
++ if (data->T7_config_valid) {
++ ret = mxt_set_regs(data, MXT_GEN_POWER_T7, 0, 0,
++ data->T7_config, 3);
++ if (ret)
++ dev_err(dev, "Set T7 power config failed, %d\n", ret);
++ }
+
+ mutex_unlock(&input_dev->mutex);
+
diff --git a/patches/linux-3.8.13/0541-CHROMIUM-Input-atmel_mxt_ts-Move-object-from-sysfs-t.patch b/patches/linux-3.8.13/0541-CHROMIUM-Input-atmel_mxt_ts-Move-object-from-sysfs-t.patch
new file mode 100644
index 0000000..bbb1d34
--- /dev/null
+++ b/patches/linux-3.8.13/0541-CHROMIUM-Input-atmel_mxt_ts-Move-object-from-sysfs-t.patch
@@ -0,0 +1,372 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Thu, 10 May 2012 16:19:04 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Move object from sysfs to
+ debugfs
+
+The object sysfs entry is used to read the current register value
+of all the objects. Each read on the sysfs entry can only return
+up to PAGE_SIZE (usually 4k) bytes, which is not enough for showing
+all the object values for some atmel chips. This CL moves the sysfs
+entry to debugfs which does not have this PAGE_SIZE limit on read.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:9253
+TEST=cd /sys/kernel/debug/atmel_mxt_ts/*DEVICE-I2C-ADDR*/
+ cat object
+ it should show the register value for all the objects
+
+Change-Id: Ic2f0df0c17655b5208ef5746f602fdb8af1c3467
+Reviewed-on: https://gerrit.chromium.org/gerrit/21812
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Reviewed-by: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 279 +++++++++++++++++++++++-------
+ 1 file changed, 212 insertions(+), 67 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 0804795..3ea35d1 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -300,6 +300,7 @@ struct mxt_data {
+ struct dentry *dentry_dev;
+ struct dentry *dentry_deltas;
+ struct dentry *dentry_refs;
++ struct dentry *dentry_object;
+
+ /* Protect access to the T37 object buffer, used by debugfs */
+ struct mutex T37_buf_mutex;
+@@ -319,6 +320,11 @@ struct mxt_data {
+ bool T9_ctrl_valid;
+
+ bool irq_wake; /* irq wake is enabled */
++
++ /* Protect access to the object register buffer */
++ struct mutex object_str_mutex;
++ char *object_str;
++ size_t object_str_size;
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -1525,66 +1531,6 @@ static ssize_t mxt_matrix_size_show(struct device *dev,
+ info->matrix_xsize, info->matrix_ysize);
+ }
+
+-static ssize_t mxt_show_instance(char *buf, int count,
+- struct mxt_object *object, int instance,
+- const u8 *val)
+-{
+- int i;
+-
+- if (mxt_obj_instances(object) > 1)
+- count += scnprintf(buf + count, PAGE_SIZE - count,
+- "Instance %u\n", instance);
+-
+- for (i = 0; i < mxt_obj_size(object); i++)
+- count += scnprintf(buf + count, PAGE_SIZE - count,
+- "\t[%2u]: %02x (%d)\n", i, val[i], val[i]);
+- count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+-
+- return count;
+-}
+-
+-static ssize_t mxt_object_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct mxt_data *data = dev_get_drvdata(dev);
+- struct mxt_object *object;
+- int count = 0;
+- int i, j;
+- int error;
+- u8 *obuf;
+-
+- /* Pre-allocate buffer large enough to hold max sized object. */
+- obuf = kmalloc(256, GFP_KERNEL);
+- if (!obuf)
+- return -ENOMEM;
+-
+- error = 0;
+- for (i = 0; i < data->info.object_num; i++) {
+- object = data->object_table + i;
+-
+- if (!mxt_object_readable(object->type))
+- continue;
+-
+- count += scnprintf(buf + count, PAGE_SIZE - count,
+- "T%u:\n", object->type);
+-
+- for (j = 0; j < mxt_obj_instances(object); j++) {
+- u16 size = mxt_obj_size(object);
+- u16 addr = object->start_address + j * size;
+-
+- error = __mxt_read_reg(data->client, addr, size, obuf);
+- if (error)
+- goto done;
+-
+- count = mxt_show_instance(buf, count, object, j, obuf);
+- }
+- }
+-
+-done:
+- kfree(obuf);
+- return error ?: count;
+-}
+-
+ static ssize_t mxt_object_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+@@ -1702,8 +1648,7 @@ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+ static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
+ static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL);
+-static DEVICE_ATTR(object, S_IRUGO | S_IWUSR, mxt_object_show,
+- mxt_object_store);
++static DEVICE_ATTR(object, S_IWUSR, NULL, mxt_object_store);
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+ static struct attribute *mxt_attrs[] = {
+@@ -1725,6 +1670,122 @@ static const struct attribute_group mxt_attr_group = {
+
+ /*
+ **************************************************************
++ * debugfs helper functions
++ **************************************************************
++*/
++
++/*
++ * Print the formatted string into the end of string |*str| which has size
++ * |*str_size|. Extra space will be allocated to hold the formatted string
++ * and |*str_size| will be updated accordingly.
++ */
++static int mxt_asprintf(char **str, size_t *str_size, const char *fmt, ...)
++{
++ unsigned int len;
++ va_list ap, aq;
++ int ret;
++ char *str_tmp;
++
++ va_start(ap, fmt);
++ va_copy(aq, ap);
++ len = vsnprintf(NULL, 0, fmt, aq);
++ va_end(aq);
++
++ str_tmp = krealloc(*str, *str_size + len + 1, GFP_KERNEL);
++ if (str_tmp == NULL)
++ return -ENOMEM;
++
++ *str = str_tmp;
++
++ ret = vsnprintf(*str + *str_size, len + 1, fmt, ap);
++ va_end(ap);
++
++ if (ret != len)
++ return -EINVAL;
++
++ *str_size += len;
++
++ return 0;
++}
++
++static int mxt_instance_fetch(char **str, size_t *count,
++ struct mxt_object *object, int instance, const u8 *val)
++{
++ int i;
++ int ret;
++
++ if (mxt_obj_instances(object) > 1) {
++ ret = mxt_asprintf(str, count, "Instance: %zu\n", instance);
++ if (ret)
++ return ret;
++ }
++
++ for (i = 0; i < mxt_obj_size(object); i++) {
++ ret = mxt_asprintf(str, count,
++ "\t[%2zu]: %02x (%d)\n", i, val[i], val[i]);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
++static int mxt_object_fetch(struct mxt_data *data)
++{
++ struct mxt_object *object;
++ size_t count = 0;
++ size_t i, j;
++ int ret = 0;
++ char *str = NULL;
++ u8 *obuf;
++
++ if (data->object_str)
++ return -EINVAL;
++
++ /* Pre-allocate buffer large enough to hold max sized object. */
++ obuf = kmalloc(256, GFP_KERNEL);
++ if (!obuf)
++ return -ENOMEM;
++
++ for (i = 0; i < data->info.object_num; i++) {
++ object = data->object_table + i;
++
++ if (!mxt_object_readable(object->type))
++ continue;
++
++ ret = mxt_asprintf(&str, &count, "\nT%u\n", object->type);
++ if (ret)
++ goto err;
++
++ for (j = 0; j < mxt_obj_instances(object); j++) {
++ u16 size = mxt_obj_size(object);
++ u16 addr = object->start_address + j * size;
++
++ ret = __mxt_read_reg(data->client, addr, size, obuf);
++ if (ret)
++ goto done;
++
++ ret = mxt_instance_fetch(&str, &count, object, j, obuf);
++ if (ret)
++ goto err;
++ }
++ }
++
++ goto done;
++
++err:
++ kfree(str);
++ str = NULL;
++ count = 0;
++done:
++ data->object_str = str;
++ data->object_str_size = count;
++ kfree(obuf);
++ return ret;
++}
++
++/*
++ **************************************************************
+ * debugfs interface
+ **************************************************************
+ */
+@@ -1814,6 +1875,78 @@ static const struct file_operations mxt_debugfs_T37_fops = {
+ .read = mxt_debugfs_T37_read
+ };
+
++static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
++{
++ struct mxt_data *mxt = inode->i_private;
++ int ret;
++
++ /* Only allow one object debugfs file to be opened at a time */
++ ret = mutex_lock_interruptible(&mxt->object_str_mutex);
++ if (ret)
++ return ret;
++
++ if (!i2c_use_client(mxt->client)) {
++ ret = -ENODEV;
++ goto err_object_unlock;
++ }
++
++ ret = mxt_object_fetch(mxt);
++ if (ret)
++ goto err_object_i2c_release;
++ file->private_data = mxt;
++
++ return 0;
++
++err_object_i2c_release:
++ i2c_release_client(mxt->client);
++err_object_unlock:
++ mutex_unlock(&mxt->object_str_mutex);
++ return ret;
++}
++
++static int mxt_debugfs_object_release(struct inode *inode, struct file *file)
++{
++ struct mxt_data *mxt = file->private_data;
++ file->private_data = NULL;
++
++ kfree(mxt->object_str);
++ mxt->object_str = NULL;
++ mxt->object_str_size = 0;
++
++ i2c_release_client(mxt->client);
++ mutex_unlock(&mxt->object_str_mutex);
++
++ return 0;
++}
++
++static ssize_t mxt_debugfs_object_read(struct file *file, char __user* buffer,
++ size_t count, loff_t *ppos)
++{
++ struct mxt_data *mxt = file->private_data;
++ if (!mxt->object_str)
++ return -ENODEV;
++
++ if (*ppos >= mxt->object_str_size)
++ return 0;
++
++ if (count + *ppos > mxt->object_str_size)
++ count = mxt->object_str_size - *ppos;
++
++ if (copy_to_user(buffer, &mxt->object_str[*ppos], count))
++ return -EFAULT;
++
++ *ppos += count;
++
++ return count;
++}
++
++static const struct file_operations mxt_debugfs_object_fops = {
++ .owner = THIS_MODULE,
++ .open = mxt_debugfs_object_open,
++ .release = mxt_debugfs_object_release,
++ .read = mxt_debugfs_object_read,
++};
++
+ static int mxt_debugfs_init(struct mxt_data *mxt)
+ {
+ struct device *dev = &mxt->client->dev;
+@@ -1835,9 +1968,25 @@ static int mxt_debugfs_init(struct mxt_data *mxt)
+ mxt->dentry_refs = debugfs_create_file("refs", S_IRUSR,
+ mxt->dentry_dev, mxt,
+ &mxt_debugfs_T37_fops);
++ mutex_init(&mxt->object_str_mutex);
++
++ mxt->dentry_object = debugfs_create_file("object", S_IRUGO,
++ mxt->dentry_dev, mxt,
++ &mxt_debugfs_object_fops);
+ return 0;
+ }
+
++static void mxt_debugfs_remove(struct mxt_data *mxt)
++{
++ if (mxt->dentry_dev) {
++ debugfs_remove_recursive(mxt->dentry_dev);
++ mutex_destroy(&mxt->object_str_mutex);
++ kfree(mxt->object_str);
++ mutex_destroy(&mxt->T37_buf_mutex);
++ kfree(mxt->T37_buf);
++ }
++}
++
+ static int mxt_save_regs(struct mxt_data *data, u8 type, u8 instance,
+ u8 offset, u8 *val, u16 size)
+ {
+@@ -2067,11 +2216,7 @@ static int mxt_remove(struct i2c_client *client)
+ {
+ struct mxt_data *data = i2c_get_clientdata(client);
+
+- if (data->dentry_dev) {
+- debugfs_remove_recursive(data->dentry_dev);
+- mutex_destroy(&data->T37_buf_mutex);
+- kfree(data->T37_buf);
+- }
++ mxt_debugfs_remove(data);
+ sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+ free_irq(data->irq, data);
+ if (data->input_dev)
diff --git a/patches/linux-3.8.13/0542-CHROMIUM-Input-atmel_mxt_ts-Set-default-irqflags-whe.patch b/patches/linux-3.8.13/0542-CHROMIUM-Input-atmel_mxt_ts-Set-default-irqflags-whe.patch
new file mode 100644
index 0000000..7bb730e
--- /dev/null
+++ b/patches/linux-3.8.13/0542-CHROMIUM-Input-atmel_mxt_ts-Set-default-irqflags-whe.patch
@@ -0,0 +1,55 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Mon, 14 May 2012 12:06:29 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Set default irqflags when
+ there is no pdata
+
+This is the preparation for supporting the code path when there is
+platform data provided and still boot the device into a sane state
+with backup NVRAM config.
+
+This CL makes the irqflags default to be IRQF_TRIGGER_FALLING if no
+platform data is provided.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=The code path for no pdata is not supported yet, so no test can
+ be done at this point. And no funtional change along the normal
+ code path with platform data provided.
+
+Change-Id: Icea0fff544c77b38eb380851d7e7d8f857b76745
+Reviewed-on: https://gerrit.chromium.org/gerrit/22417
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 3ea35d1..ec1077b 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2139,6 +2139,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ {
+ const struct mxt_platform_data *pdata = client->dev.platform_data;
+ struct mxt_data *data;
++ unsigned long irqflags;
+ int error;
+
+ if (!pdata)
+@@ -2174,8 +2175,10 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ goto err_free_object;
+ }
+
++ /* Default to falling edge if no platform data provided */
++ irqflags = pdata ? pdata->irqflags : IRQF_TRIGGER_FALLING;
+ error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+- pdata->irqflags | IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ client->name, data);
+ if (error) {
+ dev_err(&client->dev, "Failed to register interrupt\n");
diff --git a/patches/linux-3.8.13/0543-CHROMIUM-Input-atmel_mxt_ts-Support-the-case-with-no.patch b/patches/linux-3.8.13/0543-CHROMIUM-Input-atmel_mxt_ts-Support-the-case-with-no.patch
new file mode 100644
index 0000000..9fc8d2d
--- /dev/null
+++ b/patches/linux-3.8.13/0543-CHROMIUM-Input-atmel_mxt_ts-Support-the-case-with-no.patch
@@ -0,0 +1,110 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Mon, 14 May 2012 12:29:52 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Support the case with no
+ platform data
+
+Add the support that the device finishes initialization even when no
+platform data is provided. Most of the time the device needs configured
+only once and later on it can just use backed up config from NVRAM.
+So the code path with no platform saves on device initialization time.
+
+Rename mxt_check_reg_init() to be mxt_apply_pdata_config() and move it
+into mxt_handle_pdata() so that all the platform data processing is in
+one fucntion.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=Rebuild the kernel with no platform data provided, boot the device
+ with a previously working atmel chip, and make sure the atmel chip
+ still works.
+
+Change-Id: I2440c58ab9b9baa1160406827ba9d08aee52a554
+Reviewed-on: https://gerrit.chromium.org/gerrit/22587
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Reviewed-by: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index ec1077b..3dbaa3c 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -959,7 +959,7 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-static int mxt_check_reg_init(struct mxt_data *data)
++static int mxt_apply_pdata_config(struct mxt_data *data)
+ {
+ const struct mxt_platform_data *pdata = data->pdata;
+ struct mxt_object *object;
+@@ -969,7 +969,7 @@ static int mxt_check_reg_init(struct mxt_data *data)
+ int ret;
+
+ if (!pdata->config) {
+- dev_dbg(dev, "No cfg data defined, skipping reg init\n");
++ dev_info(dev, "No cfg data defined, skipping reg init\n");
+ return 0;
+ }
+
+@@ -995,10 +995,21 @@ static int mxt_check_reg_init(struct mxt_data *data)
+ return 0;
+ }
+
+-static void mxt_handle_pdata(struct mxt_data *data)
++static int mxt_handle_pdata(struct mxt_data *data)
+ {
+ const struct mxt_platform_data *pdata = data->pdata;
++ struct device *dev = &data->client->dev;
+ u8 voltage;
++ int ret;
++
++ if (!pdata) {
++ dev_info(dev, "No platform data provided\n");
++ return 0;
++ }
++
++ ret = mxt_apply_pdata_config(data);
++ if (ret)
++ return ret;
+
+ /* Set touchscreen lines */
+ mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE,
+@@ -1041,6 +1052,8 @@ static void mxt_handle_pdata(struct mxt_data *data)
+ mxt_write_object(data, MXT_SPT_CTECONFIG_T28,
+ MXT_CTE_VOLTAGE, voltage);
+ }
++
++ return 0;
+ }
+
+ /* Update 24-bit CRC with two new bytes of data */
+@@ -1234,13 +1247,11 @@ static int mxt_initialize(struct mxt_data *data)
+ if (error)
+ goto err_free_object_table;
+
+- /* Check register init values */
+- error = mxt_check_reg_init(data);
++ /* Apply config from platform data */
++ error = mxt_handle_pdata(data);
+ if (error)
+ goto err_free_object_table;
+
+- mxt_handle_pdata(data);
+-
+ /* Backup to memory */
+ error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+@@ -2142,9 +2153,6 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ unsigned long irqflags;
+ int error;
+
+- if (!pdata)
+- return -EINVAL;
+-
+ data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&client->dev, "Failed to allocate memory\n");
diff --git a/patches/linux-3.8.13/0544-CHROMIUM-Input-atmel_mxt_ts-Wait-on-auto-calibration.patch b/patches/linux-3.8.13/0544-CHROMIUM-Input-atmel_mxt_ts-Wait-on-auto-calibration.patch
new file mode 100644
index 0000000..5620224
--- /dev/null
+++ b/patches/linux-3.8.13/0544-CHROMIUM-Input-atmel_mxt_ts-Wait-on-auto-calibration.patch
@@ -0,0 +1,117 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Wed, 16 May 2012 14:52:02 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Wait on auto calibration msg
+ in suspend
+
+If the atmel chip enters suspend mode and wants to be able to
+wakeup from suspend, T9 object has to be enabled during suspend.
+If T9 is enalbed from a disabled state, the chip will perform an
+auto calibration and send back the status of the calibration.
+We have to wait for these messages to be read before entering
+suspend, otherwise these message will wakeup the system automatically.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:8722
+TEST=run powerd_suspend to put system into sleep and make sure it
+ does not wakeup automatically. And touch the TS/TP to wake the
+ system up
+
+Change-Id: Iaf8175c8e6d523edfd152172e1966303ac8fd65f
+Reviewed-on: https://gerrit.chromium.org/gerrit/22842
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 39 +++++++++++++++++++++++++-----
+ 1 file changed, 33 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 3dbaa3c..bac30d1f 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -325,6 +325,9 @@ struct mxt_data {
+ struct mutex object_str_mutex;
+ char *object_str;
+ size_t object_str_size;
++
++ /* for auto-calibration in suspend */
++ struct completion auto_cal_completion;
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -821,6 +824,8 @@ static int mxt_proc_messages(struct mxt_data *data, u8 count)
+ data->config_csum = mxt_extract_T6_csum(&payload[1]);
+ dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
+ status, data->config_csum);
++ if (status == 0x00)
++ complete(&data->auto_cal_completion);
+ } else if (mxt_is_T9_message(data, msg)) {
+ int id = reportid - data->T9_reportid_min;
+ mxt_input_touchevent(data, msg, id);
+@@ -2170,6 +2175,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ data->irq = client->irq;
+
+ init_completion(&data->bl_completion);
++ init_completion(&data->auto_cal_completion);
+
+ if (mxt_in_bootloader(data)) {
+ dev_info(&client->dev, "Device in bootloader at probe\n");
+@@ -2239,6 +2245,30 @@ static int mxt_remove(struct i2c_client *client)
+ }
+
+ #ifdef CONFIG_PM_SLEEP
++
++static void mxt_suspend_enable_T9(struct mxt_data *data)
++{
++ struct device *dev = &data->client->dev;
++ u8 T9_ctrl = 0x03;
++ int ret;
++ unsigned long timeout = msecs_to_jiffies(350);
++
++ INIT_COMPLETION(data->auto_cal_completion);
++
++ /* Enable T9 object */
++ ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
++ &T9_ctrl, 1);
++ if (ret) {
++ dev_err(dev, "Set T9 ctrl config failed, %d\n", ret);
++ return;
++ }
++
++ ret = wait_for_completion_interruptible_timeout(
++ &data->auto_cal_completion, timeout);
++ if (ret <= 0)
++ dev_err(dev, "Wait for auto cal completion failed.\n");
++}
++
+ static int mxt_suspend(struct device *dev)
+ {
+ struct i2c_client *client = to_i2c_client(dev);
+@@ -2247,7 +2277,6 @@ static int mxt_suspend(struct device *dev)
+ static const u8 T7_config_idle[3] = { 0xfe, 0xfe, 0x00 };
+ static const u8 T7_config_deepsleep[3] = { 0x00, 0x00, 0x00 };
+ const u8 *power_config;
+- u8 T9_ctrl = 0x03;
+ int ret;
+
+ if (mxt_in_bootloader(data))
+@@ -2287,11 +2316,9 @@ static int mxt_suspend(struct device *dev)
+ dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
+ data->T9_ctrl_valid = (ret == 0);
+
+- /* Enable T9 object */
+- ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+- &T9_ctrl, 1);
+- if (ret)
+- dev_err(dev, "Set T9 ctrl config failed, %d\n", ret);
++ /* Enable T9 only if it is not currently enabled */
++ if (data->T9_ctrl_valid && !(data->T9_ctrl & 0x01))
++ mxt_suspend_enable_T9(data);
+
+ /* Enable wake from IRQ */
+ data->irq_wake = (enable_irq_wake(data->irq) == 0);
diff --git a/patches/linux-3.8.13/0545-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch b/patches/linux-3.8.13/0545-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch
new file mode 100644
index 0000000..9e354b2
--- /dev/null
+++ b/patches/linux-3.8.13/0545-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch
@@ -0,0 +1,182 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Thu, 13 Dec 2012 11:36:59 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Add sysfs entry for r/w fw
+ file name
+
+On system with more than 1 Atmel chip, a fixed firmware file name
+"maxtouch.fw" does not work since different chips need different
+firmware files. This CL adds the sysfs entry that make it possible
+for userspace to specify the file name of the firmware to be loaded.
+If no file name is specified, the default "maxtouch.fw" is used for
+compatibility with existing code.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=cat path-to-atmel-sysfs/fw_file
+ and make sure "maxtouch.fw" is returned
+ echo XXX > path-to-atmel-sysfs/fw_file
+ cat path-to-atmel-sysfs/fw_file
+ and make sure XXX is returned
+ echo 1 > path-to-atmel-sysfs/update_fw
+ and make sure the driver tries to load XXX
+ if XXX exists in /lib/firmware, check that
+ firmware update succeeds
+ if XXX does not exist in /lib/firmware, check
+ that firmware update fails
+
+Change-Id: Icdff2851866b36de08c6fd75c29947a8d27f7dfe
+Reviewed-on: https://gerrit.chromium.org/gerrit/22867
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 69 +++++++++++++++++++++++++++++-
+ 1 file changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index bac30d1f..1659d91 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -328,6 +328,9 @@ struct mxt_data {
+
+ /* for auto-calibration in suspend */
+ struct completion auto_cal_completion;
++
++ /* firmware file name */
++ char *fw_file;
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -1465,6 +1468,35 @@ out:
+ return ret ?: 0;
+ }
+
++static int mxt_update_file_name(struct device *dev, char** file_name,
++ const char *buf, size_t count)
++{
++ char *file_name_tmp;
++
++ /* Simple sanity check */
++ if (count > 64) {
++ dev_warn(dev, "File name too long\n");
++ return -EINVAL;
++ }
++
++ file_name_tmp = krealloc(*file_name, count + 1, GFP_KERNEL);
++ if (!file_name_tmp) {
++ dev_warn(dev, "no memory\n");
++ return -ENOMEM;
++ }
++
++ *file_name = file_name_tmp;
++ memcpy(*file_name, buf, count);
++
++ /* Echo into the sysfs entry may append newline at the end of buf */
++ if (buf[count - 1] == '\n')
++ (*file_name)[count - 1] = '\0';
++ else
++ (*file_name)[count] = '\0';
++
++ return 0;
++}
++
+ static ssize_t mxt_backupnv_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+@@ -1510,6 +1542,27 @@ static ssize_t mxt_config_csum_show(struct device *dev,
+ return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_csum);
+ }
+
++static ssize_t mxt_fw_file_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", data->fw_file);
++}
++
++static ssize_t mxt_fw_file_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ int ret;
++
++ ret = mxt_update_file_name(dev, &data->fw_file, buf, count);
++ if (ret)
++ return ret;
++
++ return count;
++}
++
+ /* Firmware Version is returned as Major.Minor.Build */
+ static ssize_t mxt_fw_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+@@ -1644,9 +1697,10 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
++ struct mxt_data *data = dev_get_drvdata(dev);
+ int error;
+
+- error = mxt_load_fw(dev, MXT_FW_NAME);
++ error = mxt_load_fw(dev, data->fw_file);
+ if (error) {
+ dev_err(dev, "The firmware update failed(%d)\n", error);
+ count = error;
+@@ -1660,6 +1714,8 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store);
+ static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
+ static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
++static DEVICE_ATTR(fw_file, S_IRUGO | S_IWUSR, mxt_fw_file_show,
++ mxt_fw_file_store);
+ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+ static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
+@@ -1671,6 +1727,7 @@ static struct attribute *mxt_attrs[] = {
+ &dev_attr_backupnv.attr,
+ &dev_attr_calibrate.attr,
+ &dev_attr_config_csum.attr,
++ &dev_attr_fw_file.attr,
+ &dev_attr_fw_version.attr,
+ &dev_attr_hw_version.attr,
+ &dev_attr_info_csum.attr,
+@@ -2177,12 +2234,17 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ init_completion(&data->bl_completion);
+ init_completion(&data->auto_cal_completion);
+
++ error = mxt_update_file_name(&client->dev, &data->fw_file, MXT_FW_NAME,
++ strlen(MXT_FW_NAME));
++ if (error)
++ goto err_free_mem;
++
+ if (mxt_in_bootloader(data)) {
+ dev_info(&client->dev, "Device in bootloader at probe\n");
+ } else {
+ error = mxt_initialize(data);
+ if (error)
+- goto err_free_mem;
++ goto err_free_fw_file;
+
+ error = mxt_input_dev_create(data);
+ if (error)
+@@ -2224,6 +2286,8 @@ err_unregister_device:
+ input_unregister_device(data->input_dev);
+ err_free_object:
+ kfree(data->object_table);
++err_free_fw_file:
++ kfree(data->fw_file);
+ err_free_mem:
+ kfree(data);
+ return error;
+@@ -2239,6 +2303,7 @@ static int mxt_remove(struct i2c_client *client)
+ if (data->input_dev)
+ input_unregister_device(data->input_dev);
+ kfree(data->object_table);
++ kfree(data->fw_file);
+ kfree(data);
+
+ return 0;
diff --git a/patches/linux-3.8.13/0546-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch b/patches/linux-3.8.13/0546-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch
new file mode 100644
index 0000000..51411ec
--- /dev/null
+++ b/patches/linux-3.8.13/0546-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch
@@ -0,0 +1,137 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Wed, 16 May 2012 18:38:14 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Add sysfs entry for r/w
+ config file name
+
+In the preparation for adding support of loading atmel config data
+from file, this CL adds the sysfs entry config_file so that which
+config file to be used is configurable from userspace. The config
+file under /lib/firmware/ will be loaded through request_firmware()
+call. The default config file is "maxtouch.cfg".
+
+This support is necessary on system with more than 1 atmel chip and
+each needs a different configuration file.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:9103
+TEST=cat path-to-atmel-sysfs/config_file
+ and make sure "maxtouch.cfg" is returned
+ echo XXX > path-to-atmel-sysfs/config_file
+ cat path-to-atmel-sysfs/config_file
+ and make sure XXX is returned
+
+Change-Id: If87a4956c46b4a27e40f689be6304691b79cbf00
+Reviewed-on: https://gerrit.chromium.org/gerrit/21663
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 37 +++++++++++++++++++++++++++++-
+ 1 file changed, 36 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 1659d91..dbabc89 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -42,6 +42,9 @@
+ /* Firmware */
+ #define MXT_FW_NAME "maxtouch.fw"
+
++/* Config file */
++#define MXT_CONFIG_NAME "maxtouch.cfg"
++
+ /* Registers */
+ #define MXT_INFO 0x00
+ #define MXT_FAMILY_ID 0x00
+@@ -331,6 +334,9 @@ struct mxt_data {
+
+ /* firmware file name */
+ char *fw_file;
++
++ /* config file name */
++ char *config_file;
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -1542,6 +1548,24 @@ static ssize_t mxt_config_csum_show(struct device *dev,
+ return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_csum);
+ }
+
++static ssize_t mxt_config_file_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ return scnprintf(buf, PAGE_SIZE, "%s\n", data->config_file);
++}
++
++static ssize_t mxt_config_file_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ int ret;
++
++ ret = mxt_update_file_name(dev, &data->config_file, buf, count);
++ return ret ? ret : count;
++}
++
+ static ssize_t mxt_fw_file_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -1714,6 +1738,8 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store);
+ static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
+ static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
++static DEVICE_ATTR(config_file, S_IRUGO | S_IWUSR, mxt_config_file_show,
++ mxt_config_file_store);
+ static DEVICE_ATTR(fw_file, S_IRUGO | S_IWUSR, mxt_fw_file_show,
+ mxt_fw_file_store);
+ static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+@@ -1727,6 +1753,7 @@ static struct attribute *mxt_attrs[] = {
+ &dev_attr_backupnv.attr,
+ &dev_attr_calibrate.attr,
+ &dev_attr_config_csum.attr,
++ &dev_attr_config_file.attr,
+ &dev_attr_fw_file.attr,
+ &dev_attr_fw_version.attr,
+ &dev_attr_hw_version.attr,
+@@ -2239,12 +2266,17 @@ static int __devinit mxt_probe(struct i2c_client *client,
+ if (error)
+ goto err_free_mem;
+
++ error = mxt_update_file_name(&client->dev, &data->config_file,
++ MXT_CONFIG_NAME, strlen(MXT_CONFIG_NAME));
++ if (error)
++ goto err_free_fw_file;
++
+ if (mxt_in_bootloader(data)) {
+ dev_info(&client->dev, "Device in bootloader at probe\n");
+ } else {
+ error = mxt_initialize(data);
+ if (error)
+- goto err_free_fw_file;
++ goto err_free_cfg_file;
+
+ error = mxt_input_dev_create(data);
+ if (error)
+@@ -2286,6 +2318,8 @@ err_unregister_device:
+ input_unregister_device(data->input_dev);
+ err_free_object:
+ kfree(data->object_table);
++err_free_cfg_file:
++ kfree(data->config_file);
+ err_free_fw_file:
+ kfree(data->fw_file);
+ err_free_mem:
+@@ -2304,6 +2338,7 @@ static int mxt_remove(struct i2c_client *client)
+ input_unregister_device(data->input_dev);
+ kfree(data->object_table);
+ kfree(data->fw_file);
++ kfree(data->config_file);
+ kfree(data);
+
+ return 0;
diff --git a/patches/linux-3.8.13/0547-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-for-writ.patch b/patches/linux-3.8.13/0547-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-for-writ.patch
new file mode 100644
index 0000000..f14fd89
--- /dev/null
+++ b/patches/linux-3.8.13/0547-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-for-writ.patch
@@ -0,0 +1,408 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Fri, 18 May 2012 16:04:06 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - add sysfs entry for writing
+ a config file
+
+Adding a sysfs entry for loading .raw Atmel config file and write it to
+the device memory.
+
+The format spec of .raw Atmel config file can be found at
+E-9078 Object-Based Chip Config File Format
+
+The input device is unregistered while the configuration data is written
+to ensure there are no open/close calls to the driver which may write
+extraneous values to the T9 control register.
+The input device is recreated once the device has been reset following
+the configuration update.
+
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:9103,chromium-os:33981
+
+TEST=Provide no platform to the atmel device
+ cd path-to-atmel-sysfs
+ 1. cat config_file
+ make sure maxtouch.cfg is returned.
+ echo 1 > update_config
+ and check the error msg in dmesg for
+ "Unable to open config file"
+ 2. copy maxtouch.cfg over to /lib/firmware/
+ echo 1 > update_config
+ check dmesg to see the device is reconfigured.
+
+Original-Change-Id: I439d86fcc0bf05b7922619e55af56ef79c1892ab
+Reviewed-on: https://gerrit.chromium.org/gerrit/24532
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+Change-Id: If8f7ea2953f1a825cbcad4a548cf563345518c7d
+Reviewed-on: https://gerrit.chromium.org/gerrit/31638
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 315 ++++++++++++++++++++++++++++++
+ 1 file changed, 315 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index dbabc89..8f1a33f 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -45,6 +45,9 @@
+ /* Config file */
+ #define MXT_CONFIG_NAME "maxtouch.cfg"
+
++/* Configuration Data */
++#define MXT_CONFIG_VERSION "OBP_RAW V1"
++
+ /* Registers */
+ #define MXT_INFO 0x00
+ #define MXT_FAMILY_ID 0x00
+@@ -244,6 +247,19 @@
+ /* For CMT (must match XRANGE/YRANGE as defined in board config */
+ #define MXT_PIXELS_PER_MM 20
+
++struct mxt_cfg_file_hdr {
++ bool valid;
++ u32 info_crc;
++ u32 cfg_crc;
++};
++
++struct mxt_cfg_file_line {
++ struct list_head list;
++ u16 addr;
++ u8 size;
++ u8 *content;
++};
++
+ struct mxt_info {
+ u8 family_id;
+ u8 variant_id;
+@@ -1348,6 +1364,287 @@ static int mxt_calc_resolution(struct mxt_data *data)
+ }
+
+ /*
++ * Atmel Raw Config File Format
++ *
++ * The first four lines of the raw config file contain:
++ * 1) Version
++ * 2) Chip ID Information (first 7 bytes of device memory)
++ * 3) Chip Information Block 24-bit CRC Checksum
++ * 4) Chip Configuration 24-bit CRC Checksum
++ *
++ * The rest of the file consists of one line per object instance:
++ * <TYPE> <INSTANCE> <SIZE> <CONTENTS>
++ *
++ * <TYPE> - 2-byte object type as hex
++ * <INSTANCE> - 2-byte object instance number as hex
++ * <SIZE> - 2-byte object size as hex
++ * <CONTENTS> - array of <SIZE> 1-byte hex values
++ */
++static int mxt_cfg_verify_hdr(struct mxt_data *data, char **config)
++{
++ struct i2c_client *client = data->client;
++ struct device *dev = &client->dev;
++ struct mxt_info info;
++ char *token;
++ int ret = 0;
++ u32 crc;
++
++ /* Process the first four lines of the file*/
++ /* 1) Version */
++ token = strsep(config, "\n");
++ dev_info(dev, "Config File: Version = %s\n", token ?: "<null>");
++ if (!token ||
++ strncmp(token, MXT_CONFIG_VERSION, strlen(MXT_CONFIG_VERSION))) {
++ dev_err(dev, "Invalid config file: Bad Version\n");
++ return -EINVAL;
++ }
++
++ /* 2) Chip ID */
++ token = strsep(config, "\n");
++ if (!token) {
++ dev_err(dev, "Invalid config file: No Chip ID\n");
++ return -EINVAL;
++ }
++ ret = sscanf(token, "%hhx %hhx %hhx %hhx %hhx %hhx %hhx",
++ &info.family_id, &info.variant_id,
++ &info.version, &info.build, &info.matrix_xsize,
++ &info.matrix_ysize, &info.object_num);
++ dev_info(dev, "Config File: Chip ID = %02x %02x %02x %02x %02x %02x %02x\n",
++ info.family_id, info.variant_id, info.version, info.build,
++ info.matrix_xsize, info.matrix_ysize, info.object_num);
++ if (ret != 7 ||
++ info.family_id != data->info.family_id ||
++ info.variant_id != data->info.variant_id ||
++ info.version != data->info.version ||
++ info.build != data->info.build ||
++ info.matrix_xsize != data->info.matrix_xsize ||
++ info.matrix_ysize != data->info.matrix_ysize ||
++ info.object_num != data->info.object_num) {
++ dev_err(dev, "Invalid config file: Chip ID info mismatch\n");
++ dev_err(dev, "Chip Info: %02x %02x %02x %02x %02x %02x %02x\n",
++ data->info.family_id, data->info.variant_id,
++ data->info.version, data->info.build,
++ data->info.matrix_xsize, data->info.matrix_ysize,
++ data->info.object_num);
++ return -EINVAL;
++ }
++
++ /* 3) Info Block CRC */
++ token = strsep(config, "\n");
++ if (!token) {
++ dev_err(dev, "Invalid config file: No Info Block CRC\n");
++ return -EINVAL;
++ }
++ ret = sscanf(token, "%x", &crc);
++ dev_info(dev, "Config File: Info Block CRC = %06x\n", crc);
++ if (ret != 1 || crc != data->info_csum) {
++ dev_err(dev, "Invalid config file: Bad Info Block CRC\n");
++ return -EINVAL;
++ }
++
++ /* 4) Config CRC */
++ /*
++ * Parse but don't verify against current config;
++ * TODO: Verify against CRC of rest of file?
++ */
++ token = strsep(config, "\n");
++ if (!token) {
++ dev_err(dev, "Invalid config file: No Config CRC\n");
++ return -EINVAL;
++ }
++ ret = sscanf(token, "%x", &crc);
++ dev_info(dev, "Config File: Config CRC = %06x\n", crc);
++ if (ret != 1) {
++ dev_err(dev, "Invalid config file: Bad Config CRC\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int mxt_cfg_proc_line(struct mxt_data *data, const char *line,
++ struct list_head *cfg_list)
++{
++ int ret;
++ u16 type, instance, size;
++ int len;
++ struct mxt_cfg_file_line *cfg_line;
++ struct mxt_object *object;
++ u8 *content;
++ size_t i;
++
++ ret = sscanf(line, "%hx %hx %hx%n", &type, &instance, &size, &len);
++ /* Skip unparseable lines */
++ if (ret < 3)
++ return 0;
++ /* Only support 1-byte types */
++ if (type > 0xff)
++ return -EINVAL;
++
++ /* Supplied object MUST be a valid instance and match object size */
++ object = mxt_get_object(data, type);
++ if (!object || instance > object->instances || size != object->size)
++ return -EINVAL;
++
++ content = kmalloc(size, GFP_KERNEL);
++ if (!content)
++ return -ENOMEM;
++
++ for (i = 0; i < size; i++) {
++ line += len;
++ ret = sscanf(line, "%hhx%n", &content[i], &len);
++ if (ret < 1) {
++ ret = -EINVAL;
++ goto free_content;
++ }
++ }
++
++ cfg_line = kzalloc(sizeof(*cfg_line), GFP_KERNEL);
++ if (!cfg_line) {
++ ret = -ENOMEM;
++ goto free_content;
++ }
++ INIT_LIST_HEAD(&cfg_line->list);
++ cfg_line->addr = object->start_address + instance * object->size;
++ cfg_line->size = object->size;
++ cfg_line->content = content;
++ list_add_tail(&cfg_line->list, cfg_list);
++
++ return 0;
++
++free_content:
++ kfree(content);
++ return ret;
++}
++
++static int mxt_cfg_proc_data(struct mxt_data *data, char **config)
++{
++ struct i2c_client *client = data->client;
++ struct device *dev = &client->dev;
++ char *line;
++ int ret = 0;
++ struct list_head cfg_lines;
++ struct mxt_cfg_file_line *cfg_line, *cfg_line_tmp;
++
++ INIT_LIST_HEAD(&cfg_lines);
++
++ while ((line = strsep(config, "\n"))) {
++ ret = mxt_cfg_proc_line(data, line, &cfg_lines);
++ if (ret < 0)
++ goto free_objects;
++ }
++
++ list_for_each_entry(cfg_line, &cfg_lines, list) {
++ dev_dbg(dev, "Addr = %u Size = %u\n",
++ cfg_line->addr, cfg_line->size);
++ print_hex_dump(KERN_DEBUG, "atmel_mxt_ts: ", DUMP_PREFIX_OFFSET,
++ 16, 1, cfg_line->content, cfg_line->size, false);
++
++ ret = __mxt_write_reg(client, cfg_line->addr, cfg_line->size,
++ cfg_line->content);
++ if (ret)
++ break;
++ }
++
++free_objects:
++ list_for_each_entry_safe(cfg_line, cfg_line_tmp, &cfg_lines, list) {
++ list_del(&cfg_line->list);
++ kfree(cfg_line->content);
++ kfree(cfg_line);
++ }
++ return ret;
++}
++
++static int mxt_load_config(struct mxt_data *data, const char *fn)
++{
++ struct i2c_client *client = data->client;
++ struct device *dev = &client->dev;
++ const struct firmware *fw = NULL;
++ int ret, ret2;
++ char *cfg_copy = NULL;
++ char *running;
++
++ ret = request_firmware(&fw, fn, dev);
++ if (ret) {
++ dev_err(dev, "Unable to open config file %s\n", fn);
++ return ret;
++ }
++
++ dev_info(dev, "Using config file %s (size = %zu)\n", fn, fw->size);
++
++ /* Make a mutable, '\0'-terminated copy of the config file */
++ cfg_copy = kmalloc(fw->size + 1, GFP_KERNEL);
++ if (!cfg_copy) {
++ ret = -ENOMEM;
++ goto err_alloc_copy;
++ }
++ memcpy(cfg_copy, fw->data, fw->size);
++ cfg_copy[fw->size] = '\0';
++
++ /* Verify config file header (after which running points to data) */
++ running = cfg_copy;
++ ret = mxt_cfg_verify_hdr(data, &running);
++ if (ret) {
++ dev_err(dev, "Error verifying config header (%d)\n", ret);
++ goto free_cfg_copy;
++ }
++
++ disable_irq(data->irq);
++
++ if (data->input_dev) {
++ input_unregister_device(data->input_dev);
++ data->input_dev = NULL;
++ }
++
++ /* Write configuration */
++ ret = mxt_cfg_proc_data(data, &running);
++ if (ret) {
++ dev_err(dev, "Error writing config file (%d)\n", ret);
++ goto register_input_dev;
++ }
++
++ /* Backup nvram */
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_BACKUPNV,
++ MXT_BACKUP_VALUE);
++ if (ret) {
++ dev_err(dev, "Error backup to nvram (%d)\n", ret);
++ goto register_input_dev;
++ }
++ msleep(MXT_BACKUP_TIME);
++
++ /* Reset device */
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_RESET, 1);
++ if (ret) {
++ dev_err(dev, "Error resetting device (%d)\n", ret);
++ goto register_input_dev;
++ }
++ msleep(MXT_RESET_TIME);
++
++register_input_dev:
++ ret2 = mxt_input_dev_create(data);
++ if (ret2) {
++ dev_err(dev, "Error creating input_dev (%d)\n", ret2);
++ ret = ret2;
++ }
++
++ /* Clear message buffer */
++ ret2 = mxt_handle_messages(data);
++ if (ret2) {
++ dev_err(dev, "Error clearing msg buffer (%d)\n", ret2);
++ ret = ret2;
++ }
++
++ enable_irq(data->irq);
++free_cfg_copy:
++ kfree(cfg_copy);
++err_alloc_copy:
++ release_firmware(fw);
++ return ret;
++}
++
++/*
+ * Helper function for performing a T6 diagnostic command
+ */
+ static int mxt_T6_diag_cmd(struct mxt_data *data, struct mxt_object *T6,
+@@ -1653,6 +1950,22 @@ static ssize_t mxt_object_store(struct device *dev,
+ return count;
+ }
+
++static ssize_t mxt_update_config_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ ssize_t ret;
++
++ ret = mxt_load_config(data, data->config_file);
++ if (ret)
++ dev_err(dev, "The config update failed (%zd)\n", ret);
++ else
++ dev_dbg(dev, "The config update succeeded\n");
++
++ return ret ?: count;
++}
++
+ static int mxt_load_fw(struct device *dev, const char *fn)
+ {
+ struct mxt_data *data = dev_get_drvdata(dev);
+@@ -1747,6 +2060,7 @@ static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+ static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
+ static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL);
+ static DEVICE_ATTR(object, S_IWUSR, NULL, mxt_object_store);
++static DEVICE_ATTR(update_config, S_IWUSR, NULL, mxt_update_config_store);
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+
+ static struct attribute *mxt_attrs[] = {
+@@ -1760,6 +2074,7 @@ static struct attribute *mxt_attrs[] = {
+ &dev_attr_info_csum.attr,
+ &dev_attr_matrix_size.attr,
+ &dev_attr_object.attr,
++ &dev_attr_update_config.attr,
+ &dev_attr_update_fw.attr,
+ NULL
+ };
diff --git a/patches/linux-3.8.13/0548-CHROMIUM-Input-atmel_mxt_ts-make-mxt_initialize-asyn.patch b/patches/linux-3.8.13/0548-CHROMIUM-Input-atmel_mxt_ts-make-mxt_initialize-asyn.patch
new file mode 100644
index 0000000..edbd0db
--- /dev/null
+++ b/patches/linux-3.8.13/0548-CHROMIUM-Input-atmel_mxt_ts-make-mxt_initialize-asyn.patch
@@ -0,0 +1,223 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Tue, 30 Oct 2012 16:06:51 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - make mxt_initialize async
+
+mxt_probe() calles mxt_initialize() to initialize the device, which includes
+a soft reset and then msleep for the reset to finish. This has big impact on
+the system boot time. This patch makes the mxt_initizlize() call async to
+reduce the system boot time.
+
+BUG=chrome-os-partner:15743
+TEST=Boot the device and check the kernel timestamp in dmesg to see that
+ the device initialization is parallelized.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+Original-Change-Id: If106af37a52a0fa874cdc8255c91fdde36776e1f
+Reviewed-on: https://gerrit.chromium.org/gerrit/36964
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Tested-by: Simon Que <sque@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+[sonnyrao: removed __devinit for 3.8 rebase]
+
+Change-Id: I81785546c6a0ff87486e7ee92cb8bab8aefe2594
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 123 ++++++++++++++++++------------
+ 1 file changed, 74 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 8f1a33f..315dcb9 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -13,6 +13,7 @@
+
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/async.h>
+ #include <linux/completion.h>
+ #include <linux/debugfs.h>
+ #include <linux/delay.h>
+@@ -1286,14 +1287,14 @@ static int mxt_initialize(struct mxt_data *data)
+ error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+ if (error)
+- return error;
++ goto err_free_object_table;
+ msleep(MXT_BACKUP_TIME);
+
+ /* Soft reset */
+ error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_RESET, 1);
+ if (error)
+- return error;
++ goto err_free_object_table;
+ msleep(MXT_RESET_TIME);
+
+ dev_info(&client->dev,
+@@ -2549,92 +2550,116 @@ err_free_device:
+ return error;
+ }
+
+-static int __devinit mxt_probe(struct i2c_client *client,
+- const struct i2c_device_id *id)
++static void mxt_initialize_async(void *closure, async_cookie_t cookie)
+ {
+- const struct mxt_platform_data *pdata = client->dev.platform_data;
+- struct mxt_data *data;
++ struct mxt_data *data = closure;
++ struct i2c_client *client = data->client;
+ unsigned long irqflags;
+ int error;
+
+- data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+- if (!data) {
+- dev_err(&client->dev, "Failed to allocate memory\n");
+- return -ENOMEM;
+- }
+-
+- data->is_tp = !strcmp(id->name, "atmel_mxt_tp");
+- snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
+- client->adapter->nr, client->addr);
+-
+- data->client = client;
+- i2c_set_clientdata(client, data);
+-
+- data->pdata = pdata;
+- data->irq = client->irq;
+-
+- init_completion(&data->bl_completion);
+- init_completion(&data->auto_cal_completion);
+-
+- error = mxt_update_file_name(&client->dev, &data->fw_file, MXT_FW_NAME,
+- strlen(MXT_FW_NAME));
+- if (error)
+- goto err_free_mem;
+-
+- error = mxt_update_file_name(&client->dev, &data->config_file,
+- MXT_CONFIG_NAME, strlen(MXT_CONFIG_NAME));
+- if (error)
+- goto err_free_fw_file;
+-
+ if (mxt_in_bootloader(data)) {
+- dev_info(&client->dev, "Device in bootloader at probe\n");
++ dev_info(&client->dev, "device in bootloader at probe\n");
+ } else {
+ error = mxt_initialize(data);
+ if (error)
+- goto err_free_cfg_file;
++ goto error_free_mem;
+
+ error = mxt_input_dev_create(data);
+ if (error)
+- goto err_free_object;
++ goto error_free_object;
+ }
+
+ /* Default to falling edge if no platform data provided */
+- irqflags = pdata ? pdata->irqflags : IRQF_TRIGGER_FALLING;
++ irqflags = data->pdata ? data->pdata->irqflags : IRQF_TRIGGER_FALLING;
+ error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+ irqflags | IRQF_ONESHOT,
+ client->name, data);
+ if (error) {
+ dev_err(&client->dev, "Failed to register interrupt\n");
+ if (mxt_in_bootloader(data))
+- goto err_free_mem;
++ goto error_free_mem;
+ else
+- goto err_unregister_device;
++ goto error_unregister_device;
+ }
+
+ if (!mxt_in_bootloader(data)) {
+ error = mxt_handle_messages(data);
+ if (error)
+- goto err_free_irq;
++ goto error_free_irq;
+ }
+
+- error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
++ /* Force the device to report back status so we can cache the device
++ * config checksum
++ */
++ error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_REPORTALL, 1);
+ if (error)
+- goto err_free_irq;
++ dev_warn(&client->dev, "error making device report status.\n");
++
++ error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
++ if (error) {
++ dev_err(&client->dev, "error creating sysfs entries.\n");
++ goto error_free_irq;
++ }
+
+ error = mxt_debugfs_init(data);
+ if (error)
+ dev_warn(&client->dev, "error creating debugfs entries.\n");
+
+- return 0;
++ return;
+
+-err_free_irq:
++error_free_irq:
+ free_irq(client->irq, data);
+-err_unregister_device:
++error_unregister_device:
+ input_unregister_device(data->input_dev);
+-err_free_object:
++error_free_object:
+ kfree(data->object_table);
+-err_free_cfg_file:
++error_free_mem:
++ kfree(data->fw_file);
+ kfree(data->config_file);
++ kfree(data);
++}
++
++static int mxt_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ const struct mxt_platform_data *pdata = client->dev.platform_data;
++ struct mxt_data *data;
++ int error;
++
++ data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
++ if (!data) {
++ dev_err(&client->dev, "Failed to allocate memory\n");
++ return -ENOMEM;
++ }
++
++ data->is_tp = !strcmp(id->name, "atmel_mxt_tp");
++ snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
++ client->adapter->nr, client->addr);
++
++ data->client = client;
++ i2c_set_clientdata(client, data);
++
++ data->pdata = pdata;
++ data->irq = client->irq;
++
++ init_completion(&data->bl_completion);
++ init_completion(&data->auto_cal_completion);
++
++ error = mxt_update_file_name(&client->dev, &data->fw_file, MXT_FW_NAME,
++ strlen(MXT_FW_NAME));
++ if (error)
++ goto err_free_mem;
++
++ error = mxt_update_file_name(&client->dev, &data->config_file,
++ MXT_CONFIG_NAME, strlen(MXT_CONFIG_NAME));
++ if (error)
++ goto err_free_fw_file;
++
++ async_schedule(mxt_initialize_async, data);
++
++ return 0;
++
+ err_free_fw_file:
+ kfree(data->fw_file);
+ err_free_mem:
diff --git a/patches/linux-3.8.13/0549-CHROMIUM-Input-atmel_mxt_ts-move-backup_nv-to-handle.patch b/patches/linux-3.8.13/0549-CHROMIUM-Input-atmel_mxt_ts-move-backup_nv-to-handle.patch
new file mode 100644
index 0000000..2608fe1
--- /dev/null
+++ b/patches/linux-3.8.13/0549-CHROMIUM-Input-atmel_mxt_ts-move-backup_nv-to-handle.patch
@@ -0,0 +1,62 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Tue, 7 Aug 2012 19:48:12 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - move backup_nv to
+ handle_pdata
+
+Now that we conditionally load configs from pdata only if pdata exists,
+we no longer need to backup_nv in mxt_initialize.
+Backup nv should only be done if config data
+was provided as a part of platform data. This will save 270ms for
+backup to nv wait.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chromium-os:33370
+TEST=Boot on a system with a touch device instantiated without
+pdata. Ensure that device is still functional, but that
+270ms has been saved until the input device is created.
+
+Change-Id: I44ecf9237db2f866787c72e03e8962ca285db865
+Reviewed-on: https://gerrit.chromium.org/gerrit/29571
+Commit-Ready: Benson Leung <bleung@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 315dcb9..bdbcc60 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -1084,6 +1084,13 @@ static int mxt_handle_pdata(struct mxt_data *data)
+ MXT_CTE_VOLTAGE, voltage);
+ }
+
++ /* Backup to memory */
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
++ if (ret)
++ return ret;
++ msleep(MXT_BACKUP_TIME);
++
+ return 0;
+ }
+
+@@ -1283,13 +1290,6 @@ static int mxt_initialize(struct mxt_data *data)
+ if (error)
+ goto err_free_object_table;
+
+- /* Backup to memory */
+- error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+- MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+- if (error)
+- goto err_free_object_table;
+- msleep(MXT_BACKUP_TIME);
+-
+ /* Soft reset */
+ error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_RESET, 1);
diff --git a/patches/linux-3.8.13/0550-CHROMIUM-Input-atmel_mxt_ts-Add-defines-for-T9-Touch.patch b/patches/linux-3.8.13/0550-CHROMIUM-Input-atmel_mxt_ts-Add-defines-for-T9-Touch.patch
new file mode 100644
index 0000000..045aa55
--- /dev/null
+++ b/patches/linux-3.8.13/0550-CHROMIUM-Input-atmel_mxt_ts-Add-defines-for-T9-Touch.patch
@@ -0,0 +1,81 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Tue, 7 Aug 2012 16:20:18 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Add defines for T9 Touch
+ Control
+
+Fix the use of magic numbers (such as 0x83) to write to
+T9 Touch Control.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chromium-os:33368
+TEST=Builds clean.
+
+Change-Id: I28d650becaa103490541cd88b600fdb535b4196c
+Reviewed-on: https://gerrit.chromium.org/gerrit/29558
+Commit-Ready: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index bdbcc60..f13ef67 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -154,6 +154,21 @@
+ #define MXT_TOUCH_YEDGEDIST 29
+ #define MXT_TOUCH_JUMPLIMIT 30
+
++/* MXT_TOUCH_CTRL bits */
++#define MXT_TOUCH_CTRL_ENABLE (1 << 0)
++#define MXT_TOUCH_CTRL_RPTEN (1 << 1)
++#define MXT_TOUCH_CTRL_DISAMP (1 << 2)
++#define MXT_TOUCH_CTRL_DISVECT (1 << 3)
++#define MXT_TOUCH_CTRL_DISMOVE (1 << 4)
++#define MXT_TOUCH_CTRL_DISREL (1 << 5)
++#define MXT_TOUCH_CTRL_DISPRESS (1 << 6)
++#define MXT_TOUCH_CTRL_SCANEN (1 << 7)
++#define MXT_TOUCH_CTRL_OPERATIONAL (MXT_TOUCH_CTRL_ENABLE | \
++ MXT_TOUCH_CTRL_SCANEN | \
++ MXT_TOUCH_CTRL_RPTEN)
++#define MXT_TOUCH_CTRL_SCANNING (MXT_TOUCH_CTRL_ENABLE | \
++ MXT_TOUCH_CTRL_SCANEN)
++
+ /* MXT_PROCI_GRIPFACE_T20 field */
+ #define MXT_GRIPFACE_CTRL 0
+ #define MXT_GRIPFACE_XLOGRIP 1
+@@ -2444,8 +2459,8 @@ static int mxt_set_regs(struct mxt_data *data, u8 type, u8 instance,
+ static void mxt_start(struct mxt_data *data)
+ {
+ /* Touch enable */
+- mxt_write_object(data,
+- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83);
++ mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
++ MXT_TOUCH_CTRL_OPERATIONAL);
+ }
+
+ static void mxt_stop(struct mxt_data *data)
+@@ -2689,7 +2704,7 @@ static int mxt_remove(struct i2c_client *client)
+ static void mxt_suspend_enable_T9(struct mxt_data *data)
+ {
+ struct device *dev = &data->client->dev;
+- u8 T9_ctrl = 0x03;
++ u8 T9_ctrl = MXT_TOUCH_CTRL_ENABLE | MXT_TOUCH_CTRL_RPTEN;
+ int ret;
+ unsigned long timeout = msecs_to_jiffies(350);
+
+@@ -2757,7 +2772,8 @@ static int mxt_suspend(struct device *dev)
+ data->T9_ctrl_valid = (ret == 0);
+
+ /* Enable T9 only if it is not currently enabled */
+- if (data->T9_ctrl_valid && !(data->T9_ctrl & 0x01))
++ if (data->T9_ctrl_valid &&
++ !(data->T9_ctrl & MXT_TOUCH_CTRL_ENABLE))
+ mxt_suspend_enable_T9(data);
+
+ /* Enable wake from IRQ */
diff --git a/patches/linux-3.8.13/0551-CHROMIUM-Input-atmel_mxt_ts-disable-reporting-on-sto.patch b/patches/linux-3.8.13/0551-CHROMIUM-Input-atmel_mxt_ts-disable-reporting-on-sto.patch
new file mode 100644
index 0000000..ca1c752
--- /dev/null
+++ b/patches/linux-3.8.13/0551-CHROMIUM-Input-atmel_mxt_ts-disable-reporting-on-sto.patch
@@ -0,0 +1,48 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Fri, 10 Aug 2012 18:43:52 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - disable reporting on stop
+
+Leave the touch device scanning and enabled, but disable reporting
+on mxt_stop. This will prevent a needless recalibration due to the T9_ctrl
+register being set to 0 (disabling the object) and then set back to 0x83.
+
+BUG=chrome-os-partner:12042,chrome-os-partner:9717
+TEST=Log in to guest mode. Test the touch screen.
+Log out. Verify that in the next session (after X has restarted)
+touch performance is still good.
+
+Change-Id: If5556325d69390a329d1ed406b5bba9f0d494896
+Signed-off-by: Benson Leung <bleung@chromium.org>
+Reviewed-on: https://gerrit.chromium.org/gerrit/29951
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index f13ef67..33b564b 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2458,16 +2458,16 @@ static int mxt_set_regs(struct mxt_data *data, u8 type, u8 instance,
+
+ static void mxt_start(struct mxt_data *data)
+ {
+- /* Touch enable */
++ /* Enable touch reporting */
+ mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
+ MXT_TOUCH_CTRL_OPERATIONAL);
+ }
+
+ static void mxt_stop(struct mxt_data *data)
+ {
+- /* Touch disable */
+- mxt_write_object(data,
+- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
++ /* Disable touch reporting */
++ mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
++ MXT_TOUCH_CTRL_SCANNING);
+ }
+
+ static int mxt_input_open(struct input_dev *dev)
diff --git a/patches/linux-3.8.13/0552-CHROMIUM-Input-atmel_mxt_ts-Suppress-handle-messages.patch b/patches/linux-3.8.13/0552-CHROMIUM-Input-atmel_mxt_ts-Suppress-handle-messages.patch
new file mode 100644
index 0000000..25fb51d
--- /dev/null
+++ b/patches/linux-3.8.13/0552-CHROMIUM-Input-atmel_mxt_ts-Suppress-handle-messages.patch
@@ -0,0 +1,112 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Mon, 13 Aug 2012 18:10:29 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Suppress handle messages
+ used for resume
+
+The position information at resume time while the system is in a
+low power state may be garbage, so do not actually report this
+information up to the input layer. Just perform the reads to clear
+out the status on the device side.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:12318
+TEST=Suspend/resume using lid close. Check that on resume,
+the touch device doesn't show a bunch of garbage data
+from when the lid was just being opened.
+
+Change-Id: I4e60ab672d6191b9141e08e9b0bfdbf42649a95e
+Reviewed-on: https://gerrit.chromium.org/gerrit/31194
+Reviewed-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 33b564b..af92d8d 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -837,7 +837,7 @@ static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
+ return (id >= data->T9_reportid_min && id <= data->T9_reportid_max);
+ }
+
+-static int mxt_proc_messages(struct mxt_data *data, u8 count)
++static int mxt_proc_messages(struct mxt_data *data, u8 count, bool report)
+ {
+ struct device *dev = &data->client->dev;
+ u8 reportid;
+@@ -854,6 +854,8 @@ static int mxt_proc_messages(struct mxt_data *data, u8 count)
+ dev_err(dev, "Failed to read %u messages (%d).\n", count, ret);
+ goto out;
+ }
++ if (!report)
++ goto out;
+
+ for (msg = messages; msg < &messages[count]; msg++) {
+ mxt_dump_message(dev, msg);
+@@ -887,7 +889,7 @@ out:
+ return ret;
+ }
+
+-static int mxt_handle_messages(struct mxt_data *data)
++static int mxt_handle_messages(struct mxt_data *data, bool report)
+ {
+ struct device *dev = &data->client->dev;
+ int ret;
+@@ -900,7 +902,7 @@ static int mxt_handle_messages(struct mxt_data *data)
+ }
+
+ if (count > 0)
+- ret = mxt_proc_messages(data, count);
++ ret = mxt_proc_messages(data, count, report);
+
+ return ret;
+ }
+@@ -985,7 +987,7 @@ static void mxt_exit_bl(struct mxt_data *data)
+ return;
+ }
+
+- error = mxt_handle_messages(data);
++ error = mxt_handle_messages(data, false);
+ if (error)
+ dev_err(dev, "Failed to clear CHG after init. error = %d\n",
+ error);
+@@ -1000,7 +1002,7 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+ /* bootloader state transition completion */
+ complete(&data->bl_completion);
+ } else {
+- mxt_handle_messages(data);
++ mxt_handle_messages(data, true);
+ }
+ return IRQ_HANDLED;
+ }
+@@ -1646,7 +1648,7 @@ register_input_dev:
+ }
+
+ /* Clear message buffer */
+- ret2 = mxt_handle_messages(data);
++ ret2 = mxt_handle_messages(data, true);
+ if (ret2) {
+ dev_err(dev, "Error clearing msg buffer (%d)\n", ret2);
+ ret = ret2;
+@@ -2598,7 +2600,7 @@ static void mxt_initialize_async(void *closure, async_cookie_t cookie)
+ }
+
+ if (!mxt_in_bootloader(data)) {
+- error = mxt_handle_messages(data);
++ error = mxt_handle_messages(data, true);
+ if (error)
+ goto error_free_irq;
+ }
+@@ -2800,7 +2802,7 @@ static int mxt_resume(struct device *dev)
+ return 0;
+
+ /* Process any pending message so that CHG line can be de-asserted */
+- ret = mxt_handle_messages(data);
++ ret = mxt_handle_messages(data, false);
+ if (ret)
+ dev_err(dev, "Handling message fails upon resume, %d\n", ret);
+
diff --git a/patches/linux-3.8.13/0553-CHROMIUM-Input-atmel_mxt_ts-save-and-restore-t9_ctrl.patch b/patches/linux-3.8.13/0553-CHROMIUM-Input-atmel_mxt_ts-save-and-restore-t9_ctrl.patch
new file mode 100644
index 0000000..d8b216e
--- /dev/null
+++ b/patches/linux-3.8.13/0553-CHROMIUM-Input-atmel_mxt_ts-save-and-restore-t9_ctrl.patch
@@ -0,0 +1,70 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Thu, 23 Aug 2012 15:43:55 -0700
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - save and restore t9_ctrl on
+ wakeup disabled
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:12318
+TEST=Close and open the lid to suspend and resume the system.
+Make sure that the touchscreen does not generate a lot of
+stray events on resume.
+
+Change-Id: I57b34aab52149cc78cd55a79640b496239bbfa5e
+Reviewed-on: https://gerrit.chromium.org/gerrit/31270
+Reviewed-by: Yufeng Shen <miletus@chromium.org>
+Commit-Ready: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index af92d8d..ae8a6f3 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2760,19 +2760,19 @@ static int mxt_suspend(struct device *dev)
+ if (ret)
+ dev_err(dev, "Set T7 Power config failed, %d\n", ret);
+
++ /* Save 1 byte T9 Ctrl config */
++ ret = mxt_save_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
++ &data->T9_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
++ data->T9_ctrl_valid = (ret == 0);
++
+ if (device_may_wakeup(dev)) {
+ /*
+ * If we allow wakeup from touch, we have to enable T9 so
+ * that IRQ can be generated from touch
+ */
+
+- /* Save 1 byte T9 Ctrl config */
+- ret = mxt_save_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+- &data->T9_ctrl, 1);
+- if (ret)
+- dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
+- data->T9_ctrl_valid = (ret == 0);
+-
+ /* Enable T9 only if it is not currently enabled */
+ if (data->T9_ctrl_valid &&
+ !(data->T9_ctrl & MXT_TOUCH_CTRL_ENABLE))
+@@ -2814,13 +2814,11 @@ static int mxt_resume(struct device *dev)
+ disable_irq_wake(data->irq);
+
+ /* Restore the T9 Ctrl config to before-suspend value */
+- if (device_may_wakeup(dev) && data->T9_ctrl_valid) {
++ if (data->T9_ctrl_valid) {
+ ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+ &data->T9_ctrl, 1);
+ if (ret)
+ dev_err(dev, "Set T9 ctrl config failed, %d\n", ret);
+- } else if (input_dev->users) {
+- mxt_start(data);
+ }
+
+ /* Restore the T7 Power config to before-suspend value */
diff --git a/patches/linux-3.8.13/0554-CHROMIUM-Input-atmel_mxt_ts-enable-RPTEN-if-can-wake.patch b/patches/linux-3.8.13/0554-CHROMIUM-Input-atmel_mxt_ts-enable-RPTEN-if-can-wake.patch
new file mode 100644
index 0000000..aad2a97
--- /dev/null
+++ b/patches/linux-3.8.13/0554-CHROMIUM-Input-atmel_mxt_ts-enable-RPTEN-if-can-wake.patch
@@ -0,0 +1,95 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Wed, 12 Sep 2012 12:42:16 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - enable RPTEN if can wakeup
+ from suspend
+
+Currently when going into suspend and if wakeup is enabled,
+the driver will check whether the T9_ctrl ENABLE bit is set and
+if not, it will toggle the bit so that T9 object is enabled
+to make wakeup possible during suspend.
+
+With recent change to T9_ctrl's default value to be 0x81, it
+is enabled (ENABLE bit set) but not reporting (RPTEN bit not
+set) which prevents touches reported back during suspend.
+
+To fix this, this patches adds checking that whether both ENABLE
+and RPTEN bits are set, and if not, set both of them.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:9192
+TEST=Use powerd_suspend to supend the device and then make sure
+ touching the touch device wakes up the system.
+
+Change-Id: I234531ae91627f7e1cccbef5810a18a5af6cbae9
+Reviewed-on: https://gerrit.chromium.org/gerrit/33088
+Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 35 ++++++++++++++++++++++--------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index ae8a6f3..d7cd1a5 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2709,10 +2709,26 @@ static void mxt_suspend_enable_T9(struct mxt_data *data)
+ u8 T9_ctrl = MXT_TOUCH_CTRL_ENABLE | MXT_TOUCH_CTRL_RPTEN;
+ int ret;
+ unsigned long timeout = msecs_to_jiffies(350);
++ bool need_enable = false;
++ bool need_report = false;
+
+- INIT_COMPLETION(data->auto_cal_completion);
++ dev_dbg(dev, "Current T9_Ctrl is %x\n", data->T9_ctrl);
+
+- /* Enable T9 object */
++ need_enable = !(data->T9_ctrl & MXT_TOUCH_CTRL_ENABLE);
++ need_report = !(data->T9_ctrl & MXT_TOUCH_CTRL_RPTEN);
++
++ /* If already enabled and reporting, do nothing */
++ if (!need_enable && !need_report)
++ return;
++
++ /* If the ENABLE bit is toggled, there will be auto-calibration msg.
++ * We will have to clear this msg before going into suspend otherwise
++ * it will wake up the device immediately
++ */
++ if (need_enable)
++ INIT_COMPLETION(data->auto_cal_completion);
++
++ /* Enable T9 object (ENABLE and REPORT) */
+ ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+ &T9_ctrl, 1);
+ if (ret) {
+@@ -2720,10 +2736,12 @@ static void mxt_suspend_enable_T9(struct mxt_data *data)
+ return;
+ }
+
+- ret = wait_for_completion_interruptible_timeout(
+- &data->auto_cal_completion, timeout);
+- if (ret <= 0)
+- dev_err(dev, "Wait for auto cal completion failed.\n");
++ if (need_enable) {
++ ret = wait_for_completion_interruptible_timeout(
++ &data->auto_cal_completion, timeout);
++ if (ret <= 0)
++ dev_err(dev, "Wait for auto cal completion failed.\n");
++ }
+ }
+
+ static int mxt_suspend(struct device *dev)
+@@ -2773,9 +2791,8 @@ static int mxt_suspend(struct device *dev)
+ * that IRQ can be generated from touch
+ */
+
+- /* Enable T9 only if it is not currently enabled */
+- if (data->T9_ctrl_valid &&
+- !(data->T9_ctrl & MXT_TOUCH_CTRL_ENABLE))
++ /* Set proper T9 ENABLE & REPTN bits */
++ if (data->T9_ctrl_valid)
+ mxt_suspend_enable_T9(data);
+
+ /* Enable wake from IRQ */
diff --git a/patches/linux-3.8.13/0555-CHROMIUM-Input-atmel_mxt_ts-release-all-fingers-on-r.patch b/patches/linux-3.8.13/0555-CHROMIUM-Input-atmel_mxt_ts-release-all-fingers-on-r.patch
new file mode 100644
index 0000000..e8fa618
--- /dev/null
+++ b/patches/linux-3.8.13/0555-CHROMIUM-Input-atmel_mxt_ts-release-all-fingers-on-r.patch
@@ -0,0 +1,126 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Tue, 9 Oct 2012 16:51:52 -0400
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - release all fingers on
+ resume
+
+Currently lid close/open can generate noise touch events on system
+suspend and resume. One case is that touch down is generated before
+suspend, and touch liftoff is processed on resume. The driver will
+discard any pending messages on resume which might make the system
+enter ghost finger state (touch down without ever liftoff).
+
+To workaround the ghost finger case, this patch forces release of
+all possible fingers on resume. And to avoid the unwanted click
+resulted from the forced release, move these fingers first to (0,0)
+and assign them with maximal PRESSURE and TOUCH_MAJOR value so to
+make them look like palms.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chromium:154383
+TEST=use evtest to monitor the touch device; put fingers on the
+ touch device; close the lid; remove fingers after making
+ sure the system enters suspend; Open the lid;
+ Make sure to see finger move events with pressue and
+ touch_major = 255 and the release events.
+
+Change-Id: Ic9f0659a2e731c2db03255eb2107be88b333541a
+Reviewed-on: https://gerrit.chromium.org/gerrit/35046
+Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 49 ++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index d7cd1a5..b964430 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -260,6 +260,8 @@
+ /* Touchscreen absolute values */
+ #define MXT_MAX_AREA 0xff
+
++#define MXT_MAX_FINGER 10
++
+ /* For CMT (must match XRANGE/YRANGE as defined in board config */
+ #define MXT_PIXELS_PER_MM 20
+
+@@ -369,6 +371,9 @@ struct mxt_data {
+
+ /* config file name */
+ char *config_file;
++
++ /* map for the tracking id currently being used */
++ bool current_id[MXT_MAX_FINGER];
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -470,6 +475,47 @@ static void mxt_dump_message(struct device *dev,
+ message->reportid, 7, message->message);
+ }
+
++/*
++ * Release all the fingers that are being tracked. To avoid unwanted gestures,
++ * move all the fingers to (0,0) with largest PRESSURE and TOUCH_MAJOR.
++ * Userspace apps can use these info to filter out these events and/or cancel
++ * existing gestures.
++ */
++static void mxt_release_all_fingers(struct mxt_data *data)
++{
++ struct device *dev = &data->client->dev;
++ struct input_dev *input_dev = data->input_dev;
++ int id;
++ bool need_update = false;
++ for (id = 0; id < MXT_MAX_FINGER; id++) {
++ if (data->current_id[id]) {
++ dev_warn(dev, "Move touch %d to (0,0)\n", id);
++ input_mt_slot(input_dev, id);
++ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
++ true);
++ input_report_abs(input_dev, ABS_MT_POSITION_X, 0);
++ input_report_abs(input_dev, ABS_MT_POSITION_Y, 0);
++ input_report_abs(input_dev, ABS_MT_PRESSURE, 255);
++ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 255);
++ need_update = true;
++ }
++ }
++ if (need_update)
++ input_sync(data->input_dev);
++
++ for (id = 0; id < MXT_MAX_FINGER; id++) {
++ if (data->current_id[id]) {
++ dev_warn(dev, "Release touch contact %d\n", id);
++ input_mt_slot(input_dev, id);
++ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
++ false);
++ data->current_id[id] = false;
++ }
++ }
++ if (need_update)
++ input_sync(data->input_dev);
++}
++
+ static bool mxt_in_bootloader(struct mxt_data *data)
+ {
+ struct i2c_client *client = data->client;
+@@ -816,6 +862,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
+ input_mt_slot(input_dev, id);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+ status & MXT_DETECT);
++ data->current_id[id] = status & MXT_DETECT;
+
+ if (status & MXT_DETECT) {
+ input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+@@ -2823,6 +2870,8 @@ static int mxt_resume(struct device *dev)
+ if (ret)
+ dev_err(dev, "Handling message fails upon resume, %d\n", ret);
+
++ mxt_release_all_fingers(data);
++
+ mutex_lock(&input_dev->mutex);
+
+ enable_irq(data->irq);
diff --git a/patches/linux-3.8.13/0556-CHROMIUM-Input-atmel_mxt_ts-make-suspend-power-acqui.patch b/patches/linux-3.8.13/0556-CHROMIUM-Input-atmel_mxt_ts-make-suspend-power-acqui.patch
new file mode 100644
index 0000000..6c4fa6e
--- /dev/null
+++ b/patches/linux-3.8.13/0556-CHROMIUM-Input-atmel_mxt_ts-make-suspend-power-acqui.patch
@@ -0,0 +1,167 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Mon, 12 Nov 2012 14:21:10 -0500
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - make suspend power
+ acquisition interval configurable
+
+Create sysfs for T7 IDLE/ACTV-ACQINT settings to have a configurable power
+acquisition setting during system suspend.
+
+Also change the default T7 IDLE/ACTV-ACQINT values during system suspend to be
+32ms to have a sensitive wakeup-from-touch response.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+
+BUG=chrome-os-partner:15968
+TEST=1. go to touch device sysfs directory
+ echo 254 > power/suspend_acq_interval_ms
+ Try powerd_suspend and use very quick, gentle touch to wake up the system
+ and notice that sometimes the system does not wake up from touch.
+ 2. go to touch device sysfs directory
+ echo 32 > power/suspend_acq_interval_ms
+ Try powerd_suspend and use very quick, gentle touch to wake up the system
+ and make sure the system always wakes up.
+
+Change-Id: Ib7ad7a6b81699b71bcb165df06f275e55a68e7c6
+Reviewed-on: https://gerrit.chromium.org/gerrit/37836
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 64 +++++++++++++++++++++++++++++-
+ 1 file changed, 63 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index b964430..8ca5288 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -223,6 +223,9 @@
+
+ #define MXT_FWRESET_TIME 500 /* msec */
+
++/* Default value for acquisition interval when in suspend mode*/
++#define MXT_SUSPEND_ACQINT_VALUE 32 /* msec */
++
+ /* MXT_SPT_GPIOPWM_T19 field */
+ #define MXT_GPIO0_MASK 0x04
+ #define MXT_GPIO1_MASK 0x08
+@@ -352,6 +355,9 @@ struct mxt_data {
+ u8 T7_config[3];
+ bool T7_config_valid;
+
++ /* T7 IDLEACQINT & ACTVACQINT setting when in suspend mode*/
++ u8 suspend_acq_interval;
++
+ /* Saved T9 Ctrl field */
+ u8 T9_ctrl;
+ bool T9_ctrl_valid;
+@@ -2113,6 +2119,39 @@ static ssize_t mxt_update_fw_store(struct device *dev,
+ return count;
+ }
+
++static ssize_t mxt_suspend_acq_interval_ms_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ u8 interval_reg = data->suspend_acq_interval;
++ u8 interval_ms = (interval_reg == 255) ? 0 : interval_reg;
++ return scnprintf(buf, PAGE_SIZE, "%u\n", interval_ms);
++}
++
++static ssize_t mxt_suspend_acq_interval_ms_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mxt_data *data = dev_get_drvdata(dev);
++ int ret;
++ u32 param;
++
++ ret = kstrtou32(buf, 10, &param);
++ if (ret < 0)
++ return -EINVAL;
++
++ /* 0 ms inteval means "free run" */
++ if (param == 0)
++ param = 255;
++ /* 254 ms is the largest interval */
++ else if (param > 254)
++ param = 254;
++
++ data->suspend_acq_interval = param;
++ return count;
++}
++
+ static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store);
+ static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
+ static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
+@@ -2127,6 +2166,9 @@ static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL);
+ static DEVICE_ATTR(object, S_IWUSR, NULL, mxt_object_store);
+ static DEVICE_ATTR(update_config, S_IWUSR, NULL, mxt_update_config_store);
+ static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
++static DEVICE_ATTR(suspend_acq_interval_ms, S_IRUGO | S_IWUSR,
++ mxt_suspend_acq_interval_ms_show,
++ mxt_suspend_acq_interval_ms_store);
+
+ static struct attribute *mxt_attrs[] = {
+ &dev_attr_backupnv.attr,
+@@ -2148,6 +2190,16 @@ static const struct attribute_group mxt_attr_group = {
+ .attrs = mxt_attrs,
+ };
+
++static struct attribute *mxt_power_attrs[] = {
++ &dev_attr_suspend_acq_interval_ms.attr,
++ NULL
++};
++
++static const struct attribute_group mxt_power_attr_group = {
++ .name = power_group_name,
++ .attrs = mxt_power_attrs,
++};
++
+ /*
+ **************************************************************
+ * debugfs helper functions
+@@ -2666,6 +2718,10 @@ static void mxt_initialize_async(void *closure, async_cookie_t cookie)
+ goto error_free_irq;
+ }
+
++ error = sysfs_merge_group(&client->dev.kobj, &mxt_power_attr_group);
++ if (error)
++ dev_warn(&client->dev, "error merging power sysfs entries.\n");
++
+ error = mxt_debugfs_init(data);
+ if (error)
+ dev_warn(&client->dev, "error creating debugfs entries.\n");
+@@ -2710,6 +2766,8 @@ static int mxt_probe(struct i2c_client *client,
+ init_completion(&data->bl_completion);
+ init_completion(&data->auto_cal_completion);
+
++ data->suspend_acq_interval = MXT_SUSPEND_ACQINT_VALUE;
++
+ error = mxt_update_file_name(&client->dev, &data->fw_file, MXT_FW_NAME,
+ strlen(MXT_FW_NAME));
+ if (error)
+@@ -2736,6 +2794,7 @@ static int mxt_remove(struct i2c_client *client)
+ struct mxt_data *data = i2c_get_clientdata(client);
+
+ mxt_debugfs_remove(data);
++ sysfs_unmerge_group(&client->dev.kobj, &mxt_power_attr_group);
+ sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+ free_irq(data->irq, data);
+ if (data->input_dev)
+@@ -2796,7 +2855,10 @@ static int mxt_suspend(struct device *dev)
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mxt_data *data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = data->input_dev;
+- static const u8 T7_config_idle[3] = { 0xfe, 0xfe, 0x00 };
++ const u8 T7_config_idle[3] = {
++ data->suspend_acq_interval,
++ data->suspend_acq_interval,
++ 0x00 };
+ static const u8 T7_config_deepsleep[3] = { 0x00, 0x00, 0x00 };
+ const u8 *power_config;
+ int ret;
diff --git a/patches/linux-3.8.13/0557-CHROMIUM-Input-atmel_mxt_ts-recalibrate-on-system-re.patch b/patches/linux-3.8.13/0557-CHROMIUM-Input-atmel_mxt_ts-recalibrate-on-system-re.patch
new file mode 100644
index 0000000..9d473e4
--- /dev/null
+++ b/patches/linux-3.8.13/0557-CHROMIUM-Input-atmel_mxt_ts-recalibrate-on-system-re.patch
@@ -0,0 +1,80 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Wed, 14 Nov 2012 16:13:59 -0500
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - recalibrate on system resume
+
+In the suspend path, if we don't allow device wakeup, we put the
+chip into deepsleep mode and the chip stops scanning during suspen.
+On resume if the environment changes, the calibrated baseline before
+suspend will no longer be valid.
+
+In this patch we force a recalibration on resume if device wakeup is
+disabled during suspend to handle the environment change.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:16171
+TEST=I don't have a controlled environment to test this. So I only test
+ normal suspend/resume to make sure no noise touches happen on resume
+ and touch devices work as expected.
+ 1. With lid open, using powerd_suspend to suspend the system. Wakeup
+ the system and make sure the touch device still works.
+ Run "demsg | grep atmel" to make sure no calibration message reported.
+ 2. Use lid close to suspend the system. Wakeup the system and make
+ sure touch device still works.
+ Run "demsg | grep atmel" to make sure calibration message are reported.
+ 3. Also notice the case of lid open caused system resume, if something is
+ on the touch surface (like opening the lid and quickly put the palm on the
+ touch surface for a while), the system will get calibrated into a wrong
+ baseline and touch device then won't work.
+
+Change-Id: I62cb47fa1c97917a2c0f968e41ee4cd13f12187c
+Reviewed-on: https://gerrit.chromium.org/gerrit/38051
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Commit-Ready: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+
+v3.7 rebase:
+Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 8ca5288..9196e94 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2936,11 +2936,6 @@ static int mxt_resume(struct device *dev)
+
+ mutex_lock(&input_dev->mutex);
+
+- enable_irq(data->irq);
+-
+- if (device_may_wakeup(dev) && data->irq_wake)
+- disable_irq_wake(data->irq);
+-
+ /* Restore the T9 Ctrl config to before-suspend value */
+ if (data->T9_ctrl_valid) {
+ ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+@@ -2957,8 +2952,22 @@ static int mxt_resume(struct device *dev)
+ dev_err(dev, "Set T7 power config failed, %d\n", ret);
+ }
+
++ if (!device_may_wakeup(dev)) {
++ /* Recalibration in case of environment change */
++ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
++ MXT_COMMAND_CALIBRATE, 1);
++ if (ret)
++ dev_err(dev, "Resume recalibration failed %d\n", ret);
++ msleep(MXT_CAL_TIME);
++ }
++
+ mutex_unlock(&input_dev->mutex);
+
++ enable_irq(data->irq);
++
++ if (device_may_wakeup(dev) && data->irq_wake)
++ disable_irq_wake(data->irq);
++
+ return 0;
+ }
+ #endif
diff --git a/patches/linux-3.8.13/0558-CHROMIUM-Input-atmel_mxt_ts-Use-correct-max-touch_ma.patch b/patches/linux-3.8.13/0558-CHROMIUM-Input-atmel_mxt_ts-Use-correct-max-touch_ma.patch
new file mode 100644
index 0000000..6877389
--- /dev/null
+++ b/patches/linux-3.8.13/0558-CHROMIUM-Input-atmel_mxt_ts-Use-correct-max-touch_ma.patch
@@ -0,0 +1,59 @@
+From: Yufeng Shen <miletus@chromium.org>
+Date: Thu, 10 Jan 2013 15:00:42 -0500
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts: Use correct max touch_major
+ in mxt_release_all_fingers()
+
+We hard-coded the maximal touch_major value to be 255 in mxt_release_all_fingers().
+Fixing this by using the queried actual maximal touch_major value.
+
+Signed-off-by: Yufeng Shen <miletus@chromium.org>
+
+BUG=chrome-os-partner:17176
+TEST=1. Run evtest on the touch device
+ 2. Keep touching the device while closing the lid.
+ 3. Release the touch after the system suspends.
+ 4. Open the lid to resume the system
+ 5. Check evtest result and see that there is release events with correct
+ touch major value.
+
+Change-Id: I4c3bbb37c25c0df67c752a8b6943f6c127f01aa7
+Reviewed-on: https://gerrit.chromium.org/gerrit/41031
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Commit-Queue: Yufeng Shen <miletus@chromium.org>
+Tested-by: Yufeng Shen <miletus@chromium.org>
+(cherry picked from commit 0a962d62165755547e4802da837ca9004f5d246b)
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 9196e94..893d59d 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -389,6 +389,7 @@ static int mxt_calc_resolution(struct mxt_data *data);
+ static void mxt_free_object_table(struct mxt_data *data);
+ static int mxt_initialize(struct mxt_data *data);
+ static int mxt_input_dev_create(struct mxt_data *data);
++static int get_touch_major_pixels(struct mxt_data *data, int touch_channels);
+
+ static inline size_t mxt_obj_size(const struct mxt_object *obj)
+ {
+@@ -492,6 +493,8 @@ static void mxt_release_all_fingers(struct mxt_data *data)
+ struct device *dev = &data->client->dev;
+ struct input_dev *input_dev = data->input_dev;
+ int id;
++ int max_area_channels = min(255U, data->max_area_channels);
++ int max_touch_major = get_touch_major_pixels(data, max_area_channels);
+ bool need_update = false;
+ for (id = 0; id < MXT_MAX_FINGER; id++) {
+ if (data->current_id[id]) {
+@@ -502,7 +505,8 @@ static void mxt_release_all_fingers(struct mxt_data *data)
+ input_report_abs(input_dev, ABS_MT_POSITION_X, 0);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, 0);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, 255);
+- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 255);
++ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
++ max_touch_major);
+ need_update = true;
+ }
+ }
diff --git a/patches/linux-3.8.13/0559-CHROMIUM-Input-atmel_mxt_ts-Add-support-for-T65-Lens.patch b/patches/linux-3.8.13/0559-CHROMIUM-Input-atmel_mxt_ts-Add-support-for-T65-Lens.patch
new file mode 100644
index 0000000..d8df62f
--- /dev/null
+++ b/patches/linux-3.8.13/0559-CHROMIUM-Input-atmel_mxt_ts-Add-support-for-T65-Lens.patch
@@ -0,0 +1,70 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Wed, 9 Jan 2013 17:30:44 -0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Add support for T65,
+ Lensbending Correction
+
+Add T65 object to list of supported objects, and mark it readable
+and writable.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:17253
+TEST=cat /sys/kernel/debug/atmel_mxt_ts/2-004a/object
+Check that the following object appears:
+Type: 65
+ [ 0]: 00 (0)
+ [ 1]: 00 (0)
+ [ 2]: 00 (0)
+ [ 3]: 00 (0)
+ [ 4]: 00 (0)
+ [ 5]: 00 (0)
+ [ 6]: 00 (0)
+ [ 7]: 00 (0)
+ [ 8]: 00 (0)
+ [ 9]: 00 (0)
+ [10]: 00 (0)
+ [11]: 00 (0)
+ [12]: 00 (0)
+ [13]: 00 (0)
+ [14]: 00 (0)
+ [15]: 00 (0)
+ [16]: 00 (0)
+
+Change-Id: I8400bd53d619ff0e4af4c4d5ae7f54bb5dc6e9b8
+Reviewed-on: https://gerrit.chromium.org/gerrit/41310
+Reviewed-by: Yufeng Shen <miletus@chromium.org>
+Commit-Queue: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+(cherry picked from commit 5fd7e4778bd22252de5611a894d061a3bb64c4a2)
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 893d59d..fdf61b8 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -86,6 +86,7 @@
+ #define MXT_PROCI_SHIELDLESS_T56 56
+ #define MXT_PROCI_EXTRATOUCHSCREENDATA_T57 57
+ #define MXT_PROCG_NOISESUPPRESSION_T62 62
++#define MXT_PROCI_LENSBENDING_T65 65
+ #define MXT_SPT_COMMSCONFIG_T18 18
+ #define MXT_SPT_GPIOPWM_T19 19
+ #define MXT_SPT_SELFTEST_T25 25
+@@ -425,6 +426,7 @@ static bool mxt_object_readable(unsigned int type)
+ case MXT_PROCI_SHIELDLESS_T56:
+ case MXT_PROCI_EXTRATOUCHSCREENDATA_T57:
+ case MXT_PROCG_NOISESUPPRESSION_T62:
++ case MXT_PROCI_LENSBENDING_T65:
+ case MXT_SPT_COMMSCONFIG_T18:
+ case MXT_SPT_GPIOPWM_T19:
+ case MXT_SPT_SELFTEST_T25:
+@@ -462,6 +464,7 @@ static bool mxt_object_writable(unsigned int type)
+ case MXT_PROCI_SHIELDLESS_T56:
+ case MXT_PROCI_EXTRATOUCHSCREENDATA_T57:
+ case MXT_PROCG_NOISESUPPRESSION_T62:
++ case MXT_PROCI_LENSBENDING_T65:
+ case MXT_SPT_COMMSCONFIG_T18:
+ case MXT_SPT_GPIOPWM_T19:
+ case MXT_SPT_SELFTEST_T25:
diff --git a/patches/linux-3.8.13/0560-CHROMIUM-Input-atmel_mxt_ts-On-Tpads-enable-T42-disa.patch b/patches/linux-3.8.13/0560-CHROMIUM-Input-atmel_mxt_ts-On-Tpads-enable-T42-disa.patch
new file mode 100644
index 0000000..d40b812
--- /dev/null
+++ b/patches/linux-3.8.13/0560-CHROMIUM-Input-atmel_mxt_ts-On-Tpads-enable-T42-disa.patch
@@ -0,0 +1,118 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Fri, 18 Jan 2013 17:35:19 -0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts : On Tpads, enable T42,
+ disable T19 on suspend
+
+To work around an issue where an idle-suspended system may wake
+unnecessarily when the lid is closed because the B panel comes close to
+the trackpad, enable touch suppression (t42) when suspending. Also
+disable T19, for the button, to allow the button to be pressed if
+the case is flexed without the system waking.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:17336
+TEST=1. Suspend the system with powerd_suspend with lid open.
+2. Touch the touchpad. Make sure the system still wakes.
+3. Suspend again with powerd_suspend
+4. Close the lid. Ensure the system does not wake by observing the system
+status light.
+
+Change-Id: I858af27e65ce491c8eb99f5b8db13ea91f789f3e
+Reviewed-on: https://gerrit.chromium.org/gerrit/41678
+Reviewed-by: Puneet Kumar <puneetster@chromium.org>
+Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
+Commit-Queue: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+(cherry picked from commit 6988c8d813d863007df2ba3f418172d07b63ece6)
+[djkurtz: v3.6: merge]
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 61 ++++++++++++++++++++++++++++++
+ 1 file changed, 61 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index fdf61b8..8077000 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -364,6 +364,13 @@ struct mxt_data {
+ bool T9_ctrl_valid;
+
+ bool irq_wake; /* irq wake is enabled */
++ /* Saved T42 Touch Suppression field */
++ u8 T42_ctrl;
++ bool T42_ctrl_valid;
++
++ /* Saved T19 GPIO config */
++ u8 T19_ctrl;
++ bool T19_ctrl_valid;
+
+ /* Protect access to the object register buffer */
+ struct mutex object_str_mutex;
+@@ -2901,6 +2908,44 @@ static int mxt_suspend(struct device *dev)
+ dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
+ data->T9_ctrl_valid = (ret == 0);
+
++ /*
++ * For tpads, save T42 and T19 ctrl registers if may wakeup,
++ * enable large object suppression, and disable button wake.
++ * This will prevent a lid close from acting as a wake source.
++ */
++ if (data->is_tp && device_may_wakeup(dev)) {
++ u8 T42_sleep = 0x01;
++ u8 T19_sleep = 0x00;
++
++ ret = mxt_save_regs(data, MXT_PROCI_TOUCHSUPPRESSION_T42, 0, 0,
++ &data->T42_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Save T42 ctrl config failed, %d\n", ret);
++ data->T42_ctrl_valid = (ret == 0);
++
++ ret = mxt_save_regs(data, MXT_SPT_GPIOPWM_T19, 0, 0,
++ &data->T19_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Save T19 ctrl config failed, %d\n", ret);
++ data->T19_ctrl_valid = (ret == 0);
++
++
++ /* Enable Large Object Suppression */
++ ret = mxt_set_regs(data, MXT_PROCI_TOUCHSUPPRESSION_T42, 0, 0,
++ &T42_sleep, 1);
++ if (ret)
++ dev_err(dev, "Set T42 ctrl failed, %d\n", ret);
++
++ /* Disable Touchpad Button via GPIO */
++ ret = mxt_set_regs(data, MXT_SPT_GPIOPWM_T19, 0, 0,
++ &T19_sleep, 1);
++ if (ret)
++ dev_err(dev, "Set T19 ctrl failed, %d\n", ret);
++
++ } else {
++ data->T42_ctrl_valid = data->T19_ctrl_valid = false;
++ }
++
+ if (device_may_wakeup(dev)) {
+ /*
+ * If we allow wakeup from touch, we have to enable T9 so
+@@ -2959,6 +3004,22 @@ static int mxt_resume(struct device *dev)
+ dev_err(dev, "Set T7 power config failed, %d\n", ret);
+ }
+
++ /* Restore the T42 ctrl to before-suspend value */
++ if (data->T42_ctrl_valid) {
++ ret = mxt_set_regs(data, MXT_PROCI_TOUCHSUPPRESSION_T42, 0, 0,
++ &data->T42_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Set T42 ctrl failed, %d\n", ret);
++ }
++
++ /* Restore the T19 ctrl to before-suspend value */
++ if (data->T19_ctrl_valid) {
++ ret = mxt_set_regs(data, MXT_SPT_GPIOPWM_T19, 0, 0,
++ &data->T19_ctrl, 1);
++ if (ret)
++ dev_err(dev, "Set T19 ctrl failed, %d\n", ret);
++ }
++
+ if (!device_may_wakeup(dev)) {
+ /* Recalibration in case of environment change */
+ ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
diff --git a/patches/linux-3.8.13/0561-CHROMIUM-Input-atmel_mxt_ts-Set-power-wakeup-to-disa.patch b/patches/linux-3.8.13/0561-CHROMIUM-Input-atmel_mxt_ts-Set-power-wakeup-to-disa.patch
new file mode 100644
index 0000000..33b6996
--- /dev/null
+++ b/patches/linux-3.8.13/0561-CHROMIUM-Input-atmel_mxt_ts-Set-power-wakeup-to-disa.patch
@@ -0,0 +1,39 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Fri, 18 Jan 2013 17:35:52 -0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts : Set power/wakeup to disabled
+ by default.
+
+Userspace will change it to enabled if needed.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:17336
+TEST=cat /sys/bus/i2c/devices/2-004a/power/wakeup
+Check that it returns "disabled"
+Suspend the system using powerd_suspend.
+Check that the touch device 2-004a does not wake the system.
+
+Change-Id: If5ac3b30c137d16e5592d4a2ee555fd2533b0caa
+Reviewed-on: https://gerrit.chromium.org/gerrit/41679
+Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
+Reviewed-by: Puneet Kumar <puneetster@chromium.org>
+Commit-Queue: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+(cherry picked from commit 6625e780bacf270b6da346751819d2825f09c20a)
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 8077000..3f14d3b 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2792,6 +2792,8 @@ static int mxt_probe(struct i2c_client *client,
+ if (error)
+ goto err_free_fw_file;
+
++ device_set_wakeup_enable(&client->dev, false);
++
+ async_schedule(mxt_initialize_async, data);
+
+ return 0;
diff --git a/patches/linux-3.8.13/0562-CHROMIUM-Input-atmel_mxt_ts-mxt_stop-on-lid-close.patch b/patches/linux-3.8.13/0562-CHROMIUM-Input-atmel_mxt_ts-mxt_stop-on-lid-close.patch
new file mode 100644
index 0000000..c71b1f3
--- /dev/null
+++ b/patches/linux-3.8.13/0562-CHROMIUM-Input-atmel_mxt_ts-mxt_stop-on-lid-close.patch
@@ -0,0 +1,121 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Fri, 25 Jan 2013 17:45:56 -0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - mxt_stop on lid close
+
+This is an x86 specific change for the short term.
+When the lid is closed, issue an mxt_stop to turn off scanning
+to prevent the lid from affecting the touch device and causing
+stray touches.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:17465
+TEST=From test mode, run evtest, and watch the atmel_mxt device.
+Close and open the lid. Make sure there are no touch data comes
+from the atmel driver when the lid is being closed.
+
+Change-Id: I2163384fc7cbd45c63d05983c50d2a869975a3c9
+Reviewed-on: https://gerrit.chromium.org/gerrit/42080
+Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
+Commit-Queue: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+(cherry picked from commit 5391ebafb8f9b72475795445ca71b02815a2a229)
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 49 ++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 3f14d3b..cd900ee 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -25,6 +25,11 @@
+ #include <linux/slab.h>
+ #include <linux/uaccess.h>
+
++#if defined(CONFIG_ACPI_BUTTON)
++#include <acpi/button.h>
++#endif
++
++
+ /* Version */
+ #define MXT_VER_20 20
+ #define MXT_VER_21 21
+@@ -388,6 +393,11 @@ struct mxt_data {
+
+ /* map for the tracking id currently being used */
+ bool current_id[MXT_MAX_FINGER];
++
++#if defined(CONFIG_ACPI_BUTTON)
++ /* notifier block for acpi_lid_notifier */
++ struct notifier_block lid_notifier;
++#endif
+ };
+
+ /* global root node of the atmel_mxt_ts debugfs directory. */
+@@ -2601,6 +2611,24 @@ static void mxt_input_close(struct input_dev *dev)
+ mxt_stop(data);
+ }
+
++#if defined(CONFIG_ACPI_BUTTON)
++static int mxt_lid_notify(struct notifier_block *nb, unsigned long val,
++ void *unused)
++{
++ struct mxt_data *data = container_of(nb, struct mxt_data, lid_notifier);
++
++ if (mxt_in_bootloader(data))
++ return NOTIFY_OK;
++
++ if (val == 0)
++ mxt_stop(data);
++ else
++ mxt_start(data);
++
++ return NOTIFY_OK;
++}
++#endif
++
+ static int mxt_input_dev_create(struct mxt_data *data)
+ {
+ struct input_dev *input_dev;
+@@ -2796,6 +2824,14 @@ static int mxt_probe(struct i2c_client *client,
+
+ async_schedule(mxt_initialize_async, data);
+
++#if defined(CONFIG_ACPI_BUTTON)
++ data->lid_notifier.notifier_call = mxt_lid_notify;
++ if (acpi_lid_notifier_register(&data->lid_notifier)) {
++ pr_info("lid notifier registration failed\n");
++ data->lid_notifier.notifier_call = NULL;
++ }
++#endif
++
+ return 0;
+
+ err_free_fw_file:
+@@ -2815,6 +2851,10 @@ static int mxt_remove(struct i2c_client *client)
+ free_irq(data->irq, data);
+ if (data->input_dev)
+ input_unregister_device(data->input_dev);
++#if defined(CONFIG_ACPI_BUTTON)
++ if (data->lid_notifier.notifier_call)
++ acpi_lid_notifier_unregister(&data->lid_notifier);
++#endif
+ kfree(data->object_table);
+ kfree(data->fw_file);
+ kfree(data->config_file);
+@@ -2910,6 +2950,15 @@ static int mxt_suspend(struct device *dev)
+ dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
+ data->T9_ctrl_valid = (ret == 0);
+
++#if defined(CONFIG_ACPI_BUTTON)
++ ret = acpi_lid_open();
++ if (ret == 0) {
++ /* lid is closed. set T9_ctrl to operational on resume */
++ data->T9_ctrl = MXT_TOUCH_CTRL_OPERATIONAL;
++ data->T9_ctrl_valid = true;
++ }
++#endif
++
+ /*
+ * For tpads, save T42 and T19 ctrl registers if may wakeup,
+ * enable large object suppression, and disable button wake.
diff --git a/patches/linux-3.8.13/0563-CHROMIUM-Input-atmel_mxt_ts-Disable-T9-on-mxt_stop.patch b/patches/linux-3.8.13/0563-CHROMIUM-Input-atmel_mxt_ts-Disable-T9-on-mxt_stop.patch
new file mode 100644
index 0000000..df01c74
--- /dev/null
+++ b/patches/linux-3.8.13/0563-CHROMIUM-Input-atmel_mxt_ts-Disable-T9-on-mxt_stop.patch
@@ -0,0 +1,49 @@
+From: Daniel Kurtz <djkurtz@chromium.org>
+Date: Thu, 31 Jan 2013 17:43:07 +0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Disable T9 on mxt_stop
+
+Instead of using 0x81 to keep the object enabled,
+disable T9 on mxt_stop by writing 0x00 to it.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:17465
+TEST=stop powerd (on R25 also stop powerm)
+close the lid, or use a magnet to trigger the lid sensor.
+cat /sys/kernel/debug/atmel_mxt_ts/2-004a/object
+Look for Type: 9, byte 0. Check that this is 0x00
+when lid is closed. When opened, this should return
+to 0x83.
+
+Change-Id: If794e121d1b61186fee9e5b9f97b922549d7beb8
+Reviewed-on: https://gerrit.chromium.org/gerrit/42183
+Reviewed-by: Puneet Kumar <puneetster@chromium.org>
+Commit-Queue: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+(cherry picked from commit 65caaf9e0697899cd5e21eb643e018298adc781a)
+[djkurtz: v3.6 merge]
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index cd900ee..0865842 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -174,6 +174,7 @@
+ MXT_TOUCH_CTRL_RPTEN)
+ #define MXT_TOUCH_CTRL_SCANNING (MXT_TOUCH_CTRL_ENABLE | \
+ MXT_TOUCH_CTRL_SCANEN)
++#define MXT_TOUCH_CTRL_OFF 0x0
+
+ /* MXT_PROCI_GRIPFACE_T20 field */
+ #define MXT_GRIPFACE_CTRL 0
+@@ -2592,7 +2593,7 @@ static void mxt_stop(struct mxt_data *data)
+ {
+ /* Disable touch reporting */
+ mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
+- MXT_TOUCH_CTRL_SCANNING);
++ MXT_TOUCH_CTRL_OFF);
+ }
+
+ static int mxt_input_open(struct input_dev *dev)
diff --git a/patches/linux-3.8.13/0564-CHROMIUM-Input-atmel_mxt_ts-Set-T9-in-mxt_resume-bas.patch b/patches/linux-3.8.13/0564-CHROMIUM-Input-atmel_mxt_ts-Set-T9-in-mxt_resume-bas.patch
new file mode 100644
index 0000000..c8f70cf
--- /dev/null
+++ b/patches/linux-3.8.13/0564-CHROMIUM-Input-atmel_mxt_ts-Set-T9-in-mxt_resume-bas.patch
@@ -0,0 +1,73 @@
+From: Benson Leung <bleung@chromium.org>
+Date: Mon, 28 Jan 2013 15:26:25 -0800
+Subject: [PATCH] CHROMIUM: Input: atmel_mxt_ts - Set T9 in mxt_resume based
+ on lid state
+
+This is an x86 specific change for the short term.
+When the lid is closed on resume, make sure T9 is disabled.
+to prevent the lid from affecting the touch device and causing
+stray touches. If lid is open, restore operational settings for T9.
+
+Signed-off-by: Benson Leung <bleung@chromium.org>
+
+BUG=chrome-os-partner:17465
+TEST=Close the lid to suspend in guest mode.
+Open the lid slowly, until you see the lights indicating resuming.
+Close the lid immediately upon seeing the system resume from
+the status light.
+The system should stay in S0. Check via ssh:
+cat /sys/kernel/debug/atmel_mxt_ts/2-004a/object
+Check that T9 is 0x00.
+On a normal suspend/resume, where the lid is opened,
+check that touch device is functional.
+
+Change-Id: Ibce1c8c000e4bd2a8f360bea2b116051eee35be7
+Reviewed-on: https://gerrit.chromium.org/gerrit/42184
+Reviewed-by: Puneet Kumar <puneetster@chromium.org>
+Commit-Queue: Benson Leung <bleung@chromium.org>
+Tested-by: Benson Leung <bleung@chromium.org>
+(cherry picked from commit 4201ff9f7a9e114c453932662d49e34047dee59c)
+---
+ drivers/input/touchscreen/atmel_mxt_ts.c | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
+index 0865842..ca94635 100644
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2951,15 +2951,6 @@ static int mxt_suspend(struct device *dev)
+ dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
+ data->T9_ctrl_valid = (ret == 0);
+
+-#if defined(CONFIG_ACPI_BUTTON)
+- ret = acpi_lid_open();
+- if (ret == 0) {
+- /* lid is closed. set T9_ctrl to operational on resume */
+- data->T9_ctrl = MXT_TOUCH_CTRL_OPERATIONAL;
+- data->T9_ctrl_valid = true;
+- }
+-#endif
+-
+ /*
+ * For tpads, save T42 and T19 ctrl registers if may wakeup,
+ * enable large object suppression, and disable button wake.
+@@ -3040,6 +3031,19 @@ static int mxt_resume(struct device *dev)
+
+ mutex_lock(&input_dev->mutex);
+
++#if defined(CONFIG_ACPI_BUTTON)
++ ret = acpi_lid_open();
++ if (ret == 0) {
++ /* lid is closed. set T9_ctrl to non operational resume */
++ data->T9_ctrl = MXT_TOUCH_CTRL_OFF;
++ data->T9_ctrl_valid = true;
++ } else if (ret == 1) {
++ /* lid is open. Set to operational */
++ data->T9_ctrl = MXT_TOUCH_CTRL_OPERATIONAL;
++ data->T9_ctrl_valid = true;
++ }
++#endif
++
+ /* Restore the T9 Ctrl config to before-suspend value */
+ if (data->T9_ctrl_valid) {
+ ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
diff --git a/patches/linux-3.8.13/0565-video-ssd1307fb-Add-support-for-SSD1306-OLED-control.patch b/patches/linux-3.8.13/0565-video-ssd1307fb-Add-support-for-SSD1306-OLED-control.patch
new file mode 100644
index 0000000..ef175ab
--- /dev/null
+++ b/patches/linux-3.8.13/0565-video-ssd1307fb-Add-support-for-SSD1306-OLED-control.patch
@@ -0,0 +1,431 @@
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Fri, 7 Dec 2012 17:20:04 +0100
+Subject: [PATCH] video: ssd1307fb: Add support for SSD1306 OLED controller
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ .../devicetree/bindings/video/ssd1307fb.txt | 10 +-
+ drivers/video/ssd1307fb.c | 267 ++++++++++++++------
+ 2 files changed, 203 insertions(+), 74 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
+index 3d0060c..7a12542 100644
+--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
++++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
+@@ -1,13 +1,17 @@
+ * Solomon SSD1307 Framebuffer Driver
+
+ Required properties:
+- - compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for
+- now is i2c.
++ - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
++ now is i2c, and the supported chips are ssd1306 and ssd1307.
+ - reg: Should contain address of the controller on the I2C bus. Most likely
+ 0x3c or 0x3d
+ - pwm: Should contain the pwm to use according to the OF device tree PWM
+- specification [0]
++ specification [0]. Only required for the ssd1307.
+ - reset-gpios: Should contain the GPIO used to reset the OLED display
++ - solomon,height: Height in pixel of the screen driven by the controller
++ - solomon,width: Width in pixel of the screen driven by the controller
++ - solomon,page-offset: Offset of pages (band of 8 pixels) that the screen is
++ mapped to.
+
+ Optional properties:
+ - reset-active-low: Is the reset gpio is active on physical low?
+diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
+index 395cb6a..95f76e2 100644
+--- a/drivers/video/ssd1307fb.c
++++ b/drivers/video/ssd1307fb.c
+@@ -16,24 +16,39 @@
+ #include <linux/pwm.h>
+ #include <linux/delay.h>
+
+-#define SSD1307FB_WIDTH 96
+-#define SSD1307FB_HEIGHT 16
+-
+ #define SSD1307FB_DATA 0x40
+ #define SSD1307FB_COMMAND 0x80
+
+ #define SSD1307FB_CONTRAST 0x81
++#define SSD1307FB_CHARGE_PUMP 0x8d
+ #define SSD1307FB_SEG_REMAP_ON 0xa1
+ #define SSD1307FB_DISPLAY_OFF 0xae
++#define SSD1307FB_SET_MULTIPLEX_RATIO 0xa8
+ #define SSD1307FB_DISPLAY_ON 0xaf
+ #define SSD1307FB_START_PAGE_ADDRESS 0xb0
++#define SSD1307FB_SET_DISPLAY_OFFSET 0xd3
++#define SSD1307FB_SET_CLOCK_FREQ 0xd5
++#define SSD1307FB_SET_PRECHARGE_PERIOD 0xd9
++#define SSD1307FB_SET_COM_PINS_CONFIG 0xda
++#define SSD1307FB_SET_VCOMH 0xdb
++
++struct ssd1307fb_par;
++
++struct ssd1307fb_ops {
++ int (*init)(struct ssd1307fb_par *);
++ int (*remove)(struct ssd1307fb_par *);
++};
+
+ struct ssd1307fb_par {
+ struct i2c_client *client;
++ u32 height;
+ struct fb_info *info;
++ struct ssd1307fb_ops *ops;
++ u32 page_offset;
+ struct pwm_device *pwm;
+ u32 pwm_period;
+ int reset;
++ u32 width;
+ };
+
+ static struct fb_fix_screeninfo ssd1307fb_fix = {
+@@ -43,15 +58,10 @@ static struct fb_fix_screeninfo ssd1307fb_fix = {
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
+- .line_length = SSD1307FB_WIDTH / 8,
+ .accel = FB_ACCEL_NONE,
+ };
+
+ static struct fb_var_screeninfo ssd1307fb_var = {
+- .xres = SSD1307FB_WIDTH,
+- .yres = SSD1307FB_HEIGHT,
+- .xres_virtual = SSD1307FB_WIDTH,
+- .yres_virtual = SSD1307FB_HEIGHT,
+ .bits_per_pixel = 1,
+ };
+
+@@ -134,16 +144,16 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+ * (5) A4 B4 C4 D4 E4 F4 G4 H4
+ */
+
+- for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) {
+- ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1));
++ for (i = 0; i < (par->height / 8); i++) {
++ ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + i + par->page_offset);
+ ssd1307fb_write_cmd(par->client, 0x00);
+ ssd1307fb_write_cmd(par->client, 0x10);
+
+- for (j = 0; j < SSD1307FB_WIDTH; j++) {
++ for (j = 0; j < par->width; j++) {
+ u8 buf = 0;
+ for (k = 0; k < 8; k++) {
+- u32 page_length = SSD1307FB_WIDTH * i;
+- u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
++ u32 page_length = par->width * i;
++ u32 index = page_length + (par->width * k + j) / 8;
+ u8 byte = *(vmem + index);
+ u8 bit = byte & (1 << (j % 8));
+ bit = bit >> (j % 8);
+@@ -227,16 +237,137 @@ static struct fb_deferred_io ssd1307fb_defio = {
+ .deferred_io = ssd1307fb_deferred_io,
+ };
+
++static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par) {
++ int ret;
++
++ par->pwm = pwm_get(&par->client->dev, NULL);
++ if (IS_ERR(par->pwm)) {
++ dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
++ return PTR_ERR(par->pwm);
++ }
++
++ par->pwm_period = pwm_get_period(par->pwm);
++ /* Enable the PWM */
++ pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
++ pwm_enable(par->pwm);
++
++ dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
++
++ /* Map column 127 of the OLED to segment 0 */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
++ if (ret < 0)
++ return ret;
++
++ /* Turn on the display */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par) {
++ pwm_disable(par->pwm);
++ pwm_put(par->pwm);
++ return 0;
++}
++
++static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
++ .init = ssd1307fb_ssd1307_init,
++ .remove = ssd1307fb_ssd1307_remove,
++};
++
++static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par) {
++ int ret;
++
++ /* Set initial contrast */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0x7f);
++ if (ret < 0)
++ return ret;
++
++ /* Set COM direction */
++ ret = ssd1307fb_write_cmd(par->client, 0xc8);
++ if (ret < 0)
++ return ret;
++
++ /* Set segment re-map */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
++ if (ret < 0)
++ return ret;
++
++ /* Set multiplex ratio value */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO);
++ ret = ret & ssd1307fb_write_cmd(par->client, par->height - 1);
++ if (ret < 0)
++ return ret;
++
++ /* set display offset value */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET);
++ ret = ssd1307fb_write_cmd(par->client, 0x20);
++ if (ret < 0)
++ return ret;
++
++ /* Set clock frequency */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0xf0);
++ if (ret < 0)
++ return ret;
++
++ /* Set precharge period in number of ticks from the internal clock */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
++ if (ret < 0)
++ return ret;
++
++ /* Set COM pins configuration */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
++ if (ret < 0)
++ return ret;
++
++ /* Set VCOMH */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0x49);
++ if (ret < 0)
++ return ret;
++
++ /* Turn on the DC-DC Charge Pump */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0x14);
++ if (ret < 0)
++ return ret;
++
++ /* Turn on the display */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
++ .init = ssd1307fb_ssd1306_init,
++};
++
++static const struct of_device_id ssd1307fb_of_match[] = {
++ { .compatible = "solomon,ssd1306fb-i2c", .data = (void*)&ssd1307fb_ssd1306_ops },
++ { .compatible = "solomon,ssd1307fb-i2c", .data = (void*)&ssd1307fb_ssd1307_ops },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
++
+ static int ssd1307fb_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+ {
+ struct fb_info *info;
+- u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
++ struct device_node *node = client->dev.of_node;
++ u32 vmem_size;
+ struct ssd1307fb_par *par;
+ u8 *vmem;
+ int ret;
+
+- if (!client->dev.of_node) {
++ if (!node) {
+ dev_err(&client->dev, "No device tree data found!\n");
+ return -EINVAL;
+ }
+@@ -247,6 +378,36 @@ static int ssd1307fb_probe(struct i2c_client *client,
+ return -ENOMEM;
+ }
+
++ par = info->par;
++ par->info = info;
++ par->client = client;
++
++ par->ops = (struct ssd1307fb_ops*)of_match_device(ssd1307fb_of_match, &client->dev)->data;
++
++ par->reset = of_get_named_gpio(client->dev.of_node,
++ "reset-gpios", 0);
++ if (!gpio_is_valid(par->reset)) {
++ ret = -EINVAL;
++ goto fb_alloc_error;
++ }
++
++ if (of_property_read_u32(node, "solomon,width", &par->width))
++ par->width = 96;
++
++ printk("Width\t%u\n", par->width);
++
++ if (of_property_read_u32(node, "solomon,height", &par->height))
++ par->width = 16;
++
++ printk("Height\t%u\n", par->height);
++
++ if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
++ par->page_offset = 1;
++
++ printk("Offset\t%u\n", par->page_offset);
++
++ vmem_size = par->width * par->height / 8;
++
+ vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+ if (!vmem) {
+ dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
+@@ -256,9 +417,15 @@ static int ssd1307fb_probe(struct i2c_client *client,
+
+ info->fbops = &ssd1307fb_ops;
+ info->fix = ssd1307fb_fix;
++ info->fix.line_length = par->width / 8;
+ info->fbdefio = &ssd1307fb_defio;
+
+ info->var = ssd1307fb_var;
++ info->var.xres = par->width;
++ info->var.xres_virtual = par->width;
++ info->var.yres = par->height;
++ info->var.yres_virtual = par->height;
++
+ info->var.red.length = 1;
+ info->var.red.offset = 0;
+ info->var.green.length = 1;
+@@ -272,17 +439,6 @@ static int ssd1307fb_probe(struct i2c_client *client,
+
+ fb_deferred_io_init(info);
+
+- par = info->par;
+- par->info = info;
+- par->client = client;
+-
+- par->reset = of_get_named_gpio(client->dev.of_node,
+- "reset-gpios", 0);
+- if (!gpio_is_valid(par->reset)) {
+- ret = -EINVAL;
+- goto reset_oled_error;
+- }
+-
+ ret = devm_gpio_request_one(&client->dev, par->reset,
+ GPIOF_OUT_INIT_HIGH,
+ "oled-reset");
+@@ -293,23 +449,6 @@ static int ssd1307fb_probe(struct i2c_client *client,
+ goto reset_oled_error;
+ }
+
+- par->pwm = pwm_get(&client->dev, NULL);
+- if (IS_ERR(par->pwm)) {
+- dev_err(&client->dev, "Could not get PWM from device tree!\n");
+- ret = PTR_ERR(par->pwm);
+- goto pwm_error;
+- }
+-
+- par->pwm_period = pwm_get_period(par->pwm);
+-
+- dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
+-
+- ret = register_framebuffer(info);
+- if (ret) {
+- dev_err(&client->dev, "Couldn't register the framebuffer\n");
+- goto fbreg_error;
+- }
+-
+ i2c_set_clientdata(client, info);
+
+ /* Reset the screen */
+@@ -318,34 +457,25 @@ static int ssd1307fb_probe(struct i2c_client *client,
+ gpio_set_value(par->reset, 1);
+ udelay(4);
+
+- /* Enable the PWM */
+- pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+- pwm_enable(par->pwm);
+-
+- /* Map column 127 of the OLED to segment 0 */
+- ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON);
+- if (ret < 0) {
+- dev_err(&client->dev, "Couldn't remap the screen.\n");
+- goto remap_error;
++ if (par->ops->init) {
++ ret = par->ops->init(par);
++ if (ret)
++ goto reset_oled_error;
+ }
+
+- /* Turn on the display */
+- ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON);
+- if (ret < 0) {
+- dev_err(&client->dev, "Couldn't turn the display on.\n");
+- goto remap_error;
++ ret = register_framebuffer(info);
++ if (ret) {
++ dev_err(&client->dev, "Couldn't register the framebuffer\n");
++ goto panel_init_error;
+ }
+
+ dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
+
+ return 0;
+
+-remap_error:
+- unregister_framebuffer(info);
+- pwm_disable(par->pwm);
+-fbreg_error:
+- pwm_put(par->pwm);
+-pwm_error:
++panel_init_error:
++ if (par->ops->remove)
++ par->ops->remove(par);
+ reset_oled_error:
+ fb_deferred_io_cleanup(info);
+ fb_alloc_error:
+@@ -359,8 +489,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
+ struct ssd1307fb_par *par = info->par;
+
+ unregister_framebuffer(info);
+- pwm_disable(par->pwm);
+- pwm_put(par->pwm);
++ if (par->ops->remove)
++ par->ops->remove(par);
+ fb_deferred_io_cleanup(info);
+ framebuffer_release(info);
+
+@@ -368,17 +498,12 @@ static int ssd1307fb_remove(struct i2c_client *client)
+ }
+
+ static const struct i2c_device_id ssd1307fb_i2c_id[] = {
++ { "ssd1306fb", 0 },
+ { "ssd1307fb", 0 },
+ { }
+ };
+ MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
+
+-static const struct of_device_id ssd1307fb_of_match[] = {
+- { .compatible = "solomon,ssd1307fb-i2c" },
+- {},
+-};
+-MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
+-
+ static struct i2c_driver ssd1307fb_driver = {
+ .probe = ssd1307fb_probe,
+ .remove = ssd1307fb_remove,
diff --git a/patches/linux-3.8.13/0566-ssd1307fb-Rework-the-communication-functions.patch b/patches/linux-3.8.13/0566-ssd1307fb-Rework-the-communication-functions.patch
new file mode 100644
index 0000000..b963a37
--- /dev/null
+++ b/patches/linux-3.8.13/0566-ssd1307fb-Rework-the-communication-functions.patch
@@ -0,0 +1,111 @@
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Tue, 26 Feb 2013 11:39:52 +0100
+Subject: [PATCH] ssd1307fb: Rework the communication functions
+
+To efficiently send a whole page to the display, we need to be able to
+manipulate more easily the data arrays that has to be sent to the OLED
+controller. As such, this patch introduces a ssd1307fb_array structure
+that handles both the small header to be sent over i2c, which contains
+the type of information sent, and the raw bytes after that.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ drivers/video/ssd1307fb.c | 62 +++++++++++++++++++++++++--------------------
+ 1 file changed, 35 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
+index 95f76e2..85e0860 100644
+--- a/drivers/video/ssd1307fb.c
++++ b/drivers/video/ssd1307fb.c
+@@ -51,6 +51,11 @@ struct ssd1307fb_par {
+ u32 width;
+ };
+
++struct ssd1307fb_array {
++ u8 type;
++ u8 data[0];
++};
++
+ static struct fb_fix_screeninfo ssd1307fb_fix = {
+ .id = "Solomon SSD1307",
+ .type = FB_TYPE_PACKED_PIXELS,
+@@ -65,49 +70,52 @@ static struct fb_var_screeninfo ssd1307fb_var = {
+ .bits_per_pixel = 1,
+ };
+
+-static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8 *cmd, u32 len)
++static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
+ {
+- u8 *buf;
+- int ret = 0;
++ struct ssd1307fb_array *array = kzalloc(sizeof(struct ssd1307fb_array) + len, GFP_KERNEL);
++ if (!array)
++ return NULL;
+
+- buf = kzalloc(len + 1, GFP_KERNEL);
+- if (!buf) {
+- dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
+- return -ENOMEM;
+- }
++ array->type = type;
+
+- buf[0] = type;
+- memcpy(buf + 1, cmd, len);
++ return array;
++}
+
+- ret = i2c_master_send(client, buf, len + 1);
+- if (ret != len + 1) {
++static int ssd1307fb_write_array(struct i2c_client *client, struct ssd1307fb_array *array, u32 len)
++{
++ int ret;
++
++ len += sizeof(struct ssd1307fb_array);
++
++ ret = i2c_master_send(client, (u8*)array, len);
++ if (ret != len) {
+ dev_err(&client->dev, "Couldn't send I2C command.\n");
+- goto error;
++ return ret;
+ }
+
+-error:
+- kfree(buf);
+- return ret;
+-}
+-
+-static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8 *cmd, u32 len)
+-{
+- return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len);
++ return 0;
+ }
+
+ static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
+ {
+- return ssd1307fb_write_cmd_array(client, &cmd, 1);
+-}
++ struct ssd1307fb_array *array = ssd1307fb_alloc_array(1, SSD1307FB_COMMAND);
++ if (!array)
++ return -ENOMEM;
+
+-static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len)
+-{
+- return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
++ array->data[0] = cmd;
++
++ return ssd1307fb_write_array(client, array, 1);
+ }
+
+ static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
+ {
+- return ssd1307fb_write_data_array(client, &data, 1);
++ struct ssd1307fb_array *array = ssd1307fb_alloc_array(1, SSD1307FB_DATA);
++ if (!array)
++ return -ENOMEM;
++
++ array->data[0] = data;
++
++ return ssd1307fb_write_array(client, array, 1);
+ }
+
+ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
diff --git a/patches/linux-3.8.13/0567-ssd1307fb-Speed-up-the-communication-with-the-contro.patch b/patches/linux-3.8.13/0567-ssd1307fb-Speed-up-the-communication-with-the-contro.patch
new file mode 100644
index 0000000..ab176ad
--- /dev/null
+++ b/patches/linux-3.8.13/0567-ssd1307fb-Speed-up-the-communication-with-the-contro.patch
@@ -0,0 +1,53 @@
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Tue, 26 Feb 2013 11:46:40 +0100
+Subject: [PATCH] ssd1307fb: Speed up the communication with the controller
+
+The code until now was sending only 1pixel-wide page segment at once,
+and started a new transfer every time. It has proven very inefficient,
+because for one byte to display on the screen, we had to actually send 3
+bytes over I2C: the address, the type of data that was going to the
+controller, and then the actual data.
+
+This patches changes that by sending a whole page at once, avoiding most
+of this expensive overhead.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ drivers/video/ssd1307fb.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
+index 85e0860..676241b 100644
+--- a/drivers/video/ssd1307fb.c
++++ b/drivers/video/ssd1307fb.c
+@@ -153,22 +153,27 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+ */
+
+ for (i = 0; i < (par->height / 8); i++) {
++ struct ssd1307fb_array *array;
++
+ ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + i + par->page_offset);
+ ssd1307fb_write_cmd(par->client, 0x00);
+ ssd1307fb_write_cmd(par->client, 0x10);
+
++ array = ssd1307fb_alloc_array(par->width, SSD1307FB_DATA);
++
+ for (j = 0; j < par->width; j++) {
+- u8 buf = 0;
++ array->data[j] = 0;
+ for (k = 0; k < 8; k++) {
+ u32 page_length = par->width * i;
+ u32 index = page_length + (par->width * k + j) / 8;
+ u8 byte = *(vmem + index);
+ u8 bit = byte & (1 << (j % 8));
+ bit = bit >> (j % 8);
+- buf |= bit << k;
++ array->data[j] |= bit << k;
+ }
+- ssd1307fb_write_data(par->client, buf);
+ }
++
++ ssd1307fb_write_array(par->client, array, par->width);
+ }
+ }
+
diff --git a/patches/linux-3.8.13/0568-ssd1307fb-Make-use-of-horizontal-addressing-mode.patch b/patches/linux-3.8.13/0568-ssd1307fb-Make-use-of-horizontal-addressing-mode.patch
new file mode 100644
index 0000000..484cff5
--- /dev/null
+++ b/patches/linux-3.8.13/0568-ssd1307fb-Make-use-of-horizontal-addressing-mode.patch
@@ -0,0 +1,105 @@
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Fri, 13 Jul 2012 15:16:12 +0200
+Subject: [PATCH] ssd1307fb: Make use of horizontal addressing mode
+
+By default, the ssd1307 controller uses an addressing mode called page
+addressing. This mode only increments the column cursor in memory when
+writing data but will not increments the page cursor when we are at the
+end of the page.
+
+However, the controller supports another addressing mode, called
+horizontal addressing, that will maintain both the page and column
+cursors when writing data to the controller.
+
+That means that we can just remove the code that increments the current
+page address and reset the column cursor when reaching the end of the
+line, allowing to have a lower data overhead, and a simpler driver.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ drivers/video/ssd1307fb.c | 41 +++++++++++++++++++++++++++++------------
+ 1 file changed, 29 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
+index 676241b..6594458 100644
+--- a/drivers/video/ssd1307fb.c
++++ b/drivers/video/ssd1307fb.c
+@@ -19,6 +19,12 @@
+ #define SSD1307FB_DATA 0x40
+ #define SSD1307FB_COMMAND 0x80
+
++#define SSD1307FB_SET_ADDRESS_MODE 0x20
++#define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL (0x00)
++#define SSD1307FB_SET_ADDRESS_MODE_VERTICAL (0x01)
++#define SSD1307FB_SET_ADDRESS_MODE_PAGE (0x02)
++#define SSD1307FB_SET_COL_RANGE 0x21
++#define SSD1307FB_SET_PAGE_RANGE 0x22
+ #define SSD1307FB_CONTRAST 0x81
+ #define SSD1307FB_CHARGE_PUMP 0x8d
+ #define SSD1307FB_SEG_REMAP_ON 0xa1
+@@ -120,6 +126,7 @@ static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
+
+ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+ {
++ struct ssd1307fb_array *array = ssd1307fb_alloc_array(par->width * par->height / 8, SSD1307FB_DATA);
+ u8 *vmem = par->info->screen_base;
+ int i, j, k;
+
+@@ -153,28 +160,20 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+ */
+
+ for (i = 0; i < (par->height / 8); i++) {
+- struct ssd1307fb_array *array;
+-
+- ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + i + par->page_offset);
+- ssd1307fb_write_cmd(par->client, 0x00);
+- ssd1307fb_write_cmd(par->client, 0x10);
+-
+- array = ssd1307fb_alloc_array(par->width, SSD1307FB_DATA);
+-
+ for (j = 0; j < par->width; j++) {
+- array->data[j] = 0;
++ u32 array_idx = i * par->width + j;
++ array->data[array_idx] = 0;
+ for (k = 0; k < 8; k++) {
+ u32 page_length = par->width * i;
+ u32 index = page_length + (par->width * k + j) / 8;
+ u8 byte = *(vmem + index);
+ u8 bit = byte & (1 << (j % 8));
+ bit = bit >> (j % 8);
+- array->data[j] |= bit << k;
++ array->data[array_idx] |= bit << k;
+ }
+ }
+-
+- ssd1307fb_write_array(par->client, array, par->width);
+ }
++ ssd1307fb_write_array(par->client, array, par->width * par->height / 8);
+ }
+
+
+@@ -351,6 +350,24 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par) {
+ if (ret < 0)
+ return ret;
+
++ /* Switch to horizontal addressing mode */
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
++ ret = ret & ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
++ if (ret < 0)
++ return ret;
++
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
++ ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1);
++ if (ret < 0)
++ return ret;
++
++ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
++ ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
++ ret = ret & ssd1307fb_write_cmd(par->client, par->page_offset + (par->height / 8) - 1);
++ if (ret < 0)
++ return ret;
++
+ /* Turn on the display */
+ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+ if (ret < 0)
diff --git a/patches/linux-3.8.13/0569-SSD1307fb-1Hz-8Hz-defio-updates.patch b/patches/linux-3.8.13/0569-SSD1307fb-1Hz-8Hz-defio-updates.patch
new file mode 100644
index 0000000..88c4f56
--- /dev/null
+++ b/patches/linux-3.8.13/0569-SSD1307fb-1Hz-8Hz-defio-updates.patch
@@ -0,0 +1,22 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Sat, 13 Apr 2013 20:10:05 +0200
+Subject: [PATCH] SSD1307fb: 1Hz -> 8Hz defio updates
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/video/ssd1307fb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
+index 6594458..f47b59b 100644
+--- a/drivers/video/ssd1307fb.c
++++ b/drivers/video/ssd1307fb.c
+@@ -245,7 +245,7 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
+ }
+
+ static struct fb_deferred_io ssd1307fb_defio = {
+- .delay = HZ,
++ .delay = HZ/8,
+ .deferred_io = ssd1307fb_deferred_io,
+ };
+
diff --git a/patches/linux-3.8.13/0570-ARM-force-march-armv7a-for-thumb2-builds-http-lists..patch b/patches/linux-3.8.13/0570-ARM-force-march-armv7a-for-thumb2-builds-http-lists..patch
new file mode 100644
index 0000000..21032a1
--- /dev/null
+++ b/patches/linux-3.8.13/0570-ARM-force-march-armv7a-for-thumb2-builds-http-lists..patch
@@ -0,0 +1,23 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 3 Apr 2013 09:36:21 +0200
+Subject: [PATCH] ARM: force -march=armv7a for thumb2 builds -
+ http://lists.linaro.org/pipermail/linaro-dev/2011-August/006752.html
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/compressed/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
+index 5cad8a6..12edc8c 100644
+--- a/arch/arm/boot/compressed/Makefile
++++ b/arch/arm/boot/compressed/Makefile
+@@ -121,7 +121,7 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
+ endif
+
+ ccflags-y := -fpic -fno-builtin -I$(obj)
+-asflags-y := -Wa,-march=all -DZIMAGE
++asflags-y := -Wa,-march=armv7a -DZIMAGE
+
+ # Supply kernel BSS size to the decompressor via a linker symbol.
+ KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \
diff --git a/patches/linux-3.8.13/0571-headers_install-Fix-build-failures-on-deep-directory.patch b/patches/linux-3.8.13/0571-headers_install-Fix-build-failures-on-deep-directory.patch
new file mode 100644
index 0000000..790519d
--- /dev/null
+++ b/patches/linux-3.8.13/0571-headers_install-Fix-build-failures-on-deep-directory.patch
@@ -0,0 +1,56 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 8 Apr 2013 19:45:48 +0000
+Subject: [PATCH] headers_install: Fix build failures on deep directory
+ hierarchy
+
+Make headers_install croaks when we're on a deep directory hierarchy
+Fix using intermediate file lists in /tmp + xargs (but crud is left in /tmp)
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ scripts/Makefile.headersinst | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
+index e253917..c399133 100644
+--- a/scripts/Makefile.headersinst
++++ b/scripts/Makefile.headersinst
+@@ -60,6 +60,13 @@ input-files := $(foreach hdr, $(header-y), \
+ $(error Missing generated UAPI file $(gendir)/$(hdr)) \
+ ))
+
++# these will leave a file in /tmp - but they work...
++input-files-temp := $(shell mktemp)
++$(foreach f, $(input-files), $(shell echo "$(f)" >> $(input-files-temp)))
++
++all-files-temp := $(shell mktemp)
++$(foreach f, $(all-files), $(shell echo "$(installdir)/$(f)" >> $(all-files-temp)))
++
+ # Work out what needs to be removed
+ oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h))
+ unwanted := $(filter-out $(all-files),$(oldheaders))
+@@ -72,7 +79,7 @@ printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
+ quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
+ file$(if $(word 2, $(all-files)),s))
+ cmd_install = \
+- $(PERL) $< $(installdir) $(SRCARCH) $(input-files); \
++ cat $(input-files-temp) | xargs -d '\n' | $(PERL) $< $(installdir) $(SRCARCH); \
+ for F in $(wrapper-files); do \
+ echo "\#include <asm-generic/$$F>" > $(installdir)/$$F; \
+ done; \
+@@ -84,11 +91,10 @@ quiet_cmd_remove = REMOVE $(unwanted)
+ quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files)
+ # Headers list can be pretty long, xargs helps to avoid
+ # the "Argument list too long" error.
+- cmd_check = for f in $(all-files); do \
+- echo "$(installdir)/$${f}"; done \
+- | xargs \
+- $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
+- touch $@
++ cmd_check = \
++ cat $(all-files-temp) | xargs -d '\n' | \
++ $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
++ touch $@
+
+ PHONY += __headersinst __headerscheck
+
diff --git a/patches/linux-3.8.13/0572-libtraceevent-Remove-hard-coded-include-to-usr-local.patch b/patches/linux-3.8.13/0572-libtraceevent-Remove-hard-coded-include-to-usr-local.patch
new file mode 100644
index 0000000..86036de
--- /dev/null
+++ b/patches/linux-3.8.13/0572-libtraceevent-Remove-hard-coded-include-to-usr-local.patch
@@ -0,0 +1,33 @@
+From: Jack Mitchell <jack.mitchell@dbbroadcast.co.uk>
+Date: Fri, 8 Mar 2013 11:21:52 +0000
+Subject: [PATCH] libtraceevent: Remove hard coded include to
+ /usr/local/include in Makefile
+
+having /usr/local/include hardcoded into the makefile is not necessary
+as this is automatically included by GCC. It also infects cross-compile
+builds with the host systems includes.
+
+Signed-off-by: Jack Mitchell <jack.mitchell@dbbroadcast.co.uk>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Link: http://lkml.kernel.org/r/1362741712-21308-1-git-send-email-ml@communistcode.co.uk
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+---
+ tools/lib/traceevent/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
+index a20e320..0b0a907 100644
+--- a/tools/lib/traceevent/Makefile
++++ b/tools/lib/traceevent/Makefile
+@@ -122,7 +122,7 @@ export Q VERBOSE
+
+ EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
+
+-INCLUDES = -I. -I/usr/local/include $(CONFIG_INCLUDES)
++INCLUDES = -I. $(CONFIG_INCLUDES)
+
+ # Set compile option CFLAGS if not set elsewhere
+ CFLAGS ?= -g -Wall
diff --git a/patches/linux-3.8.13/0573-Make-single-.dtb-targets-also-with-DTC_FLAGS.patch b/patches/linux-3.8.13/0573-Make-single-.dtb-targets-also-with-DTC_FLAGS.patch
new file mode 100644
index 0000000..f233308
--- /dev/null
+++ b/patches/linux-3.8.13/0573-Make-single-.dtb-targets-also-with-DTC_FLAGS.patch
@@ -0,0 +1,21 @@
+From: Phil Eichinger <phil@zankapfel.net>
+Date: Wed, 5 Jun 2013 15:32:04 +0200
+Subject: [PATCH] Make single .dtb targets also with DTC_FLAGS
+
+---
+ arch/arm/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index e9729a4..d5935c0 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -299,7 +299,7 @@ uImage-dtb.%: scripts
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+ %.dtb: scripts
+- $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
++ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) DTC_FLAGS=$(DTC_FLAGS) $(boot)/dts/$@
+
+ dtbs: scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) DTC_FLAGS=$(DTC_FLAGS) dtbs
diff --git a/patches/linux-3.8.13/0574-video-Add-generic-HDMI-infoframe-helpers.patch b/patches/linux-3.8.13/0574-video-Add-generic-HDMI-infoframe-helpers.patch
new file mode 100644
index 0000000..05ccb04
--- /dev/null
+++ b/patches/linux-3.8.13/0574-video-Add-generic-HDMI-infoframe-helpers.patch
@@ -0,0 +1,593 @@
+From: Thierry Reding <thierry.reding@avionic-design.de>
+Date: Fri, 22 Feb 2013 07:03:26 +0000
+Subject: [PATCH] video: Add generic HDMI infoframe helpers
+
+Add generic helpers to pack HDMI infoframes into binary buffers.
+
+Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
+---
+ drivers/video/Kconfig | 3 +
+ drivers/video/Makefile | 1 +
+ drivers/video/hdmi.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/hdmi.h | 231 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 543 insertions(+)
+ create mode 100644 drivers/video/hdmi.c
+ create mode 100644 include/linux/hdmi.h
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index f8f0a41..a0c757a 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -54,6 +54,9 @@ config OF_VIDEOMODE
+ help
+ helper to get videomodes from the devicetree
+
++config HDMI
++ bool
++
+ menuconfig FB
+ tristate "Support for frame buffer devices"
+ ---help---
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index a3ab28c..28bfbca 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -5,6 +5,7 @@
+ # Each configuration option enables a list of files.
+
+ obj-$(CONFIG_VGASTATE) += vgastate.o
++obj-$(CONFIG_HDMI) += hdmi.o
+ obj-y += fb_notify.o
+ obj-$(CONFIG_FB) += fb.o
+ fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
+diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
+new file mode 100644
+index 0000000..ab23c9b
+--- /dev/null
++++ b/drivers/video/hdmi.c
+@@ -0,0 +1,308 @@
++/*
++ * Copyright (C) 2012 Avionic Design GmbH
++ *
++ * 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/bitops.h>
++#include <linux/errno.h>
++#include <linux/export.h>
++#include <linux/hdmi.h>
++#include <linux/string.h>
++
++static void hdmi_infoframe_checksum(void *buffer, size_t size)
++{
++ u8 *ptr = buffer;
++ u8 csum = 0;
++ size_t i;
++
++ /* compute checksum */
++ for (i = 0; i < size; i++)
++ csum += ptr[i];
++
++ ptr[3] = 256 - csum;
++}
++
++/**
++ * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
++ * @frame: HDMI AVI infoframe
++ *
++ * Returns 0 on success or a negative error code on failure.
++ */
++int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
++{
++ memset(frame, 0, sizeof(*frame));
++
++ frame->type = HDMI_INFOFRAME_TYPE_AVI;
++ frame->version = 2;
++ frame->length = 13;
++
++ return 0;
++}
++EXPORT_SYMBOL(hdmi_avi_infoframe_init);
++
++/**
++ * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
++ * @frame: HDMI AVI infoframe
++ * @buffer: destination buffer
++ * @size: size of buffer
++ *
++ * Packs the information contained in the @frame structure into a binary
++ * representation that can be written into the corresponding controller
++ * registers. Also computes the checksum as required by section 5.3.5 of
++ * the HDMI 1.4 specification.
++ *
++ * Returns the number of bytes packed into the binary buffer or a negative
++ * error code on failure.
++ */
++ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
++ size_t size)
++{
++ u8 *ptr = buffer;
++ size_t length;
++
++ length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
++
++ if (size < length)
++ return -ENOSPC;
++
++ memset(buffer, 0, length);
++
++ ptr[0] = frame->type;
++ ptr[1] = frame->version;
++ ptr[2] = frame->length;
++ ptr[3] = 0; /* checksum */
++
++ /* start infoframe payload */
++ ptr += HDMI_INFOFRAME_HEADER_SIZE;
++
++ ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
++
++ if (frame->active_info_valid)
++ ptr[0] |= BIT(4);
++
++ if (frame->horizontal_bar_valid)
++ ptr[0] |= BIT(3);
++
++ if (frame->vertical_bar_valid)
++ ptr[0] |= BIT(2);
++
++ ptr[1] = ((frame->colorimetry & 0x3) << 6) |
++ ((frame->picture_aspect & 0x3) << 4) |
++ (frame->active_aspect & 0xf);
++
++ ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
++ ((frame->quantization_range & 0x3) << 2) |
++ (frame->nups & 0x3);
++
++ if (frame->itc)
++ ptr[2] |= BIT(7);
++
++ ptr[3] = frame->video_code & 0x7f;
++
++ ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
++ ((frame->content_type & 0x3) << 4) |
++ (frame->pixel_repeat & 0xf);
++
++ ptr[5] = frame->top_bar & 0xff;
++ ptr[6] = (frame->top_bar >> 8) & 0xff;
++ ptr[7] = frame->bottom_bar & 0xff;
++ ptr[8] = (frame->bottom_bar >> 8) & 0xff;
++ ptr[9] = frame->left_bar & 0xff;
++ ptr[10] = (frame->left_bar >> 8) & 0xff;
++ ptr[11] = frame->right_bar & 0xff;
++ ptr[12] = (frame->right_bar >> 8) & 0xff;
++
++ hdmi_infoframe_checksum(buffer, length);
++
++ return length;
++}
++EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
++
++/**
++ * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
++ * @frame: HDMI SPD infoframe
++ * @vendor: vendor string
++ * @product: product string
++ *
++ * Returns 0 on success or a negative error code on failure.
++ */
++int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
++ const char *vendor, const char *product)
++{
++ memset(frame, 0, sizeof(*frame));
++
++ frame->type = HDMI_INFOFRAME_TYPE_SPD;
++ frame->version = 1;
++ frame->length = 25;
++
++ strncpy(frame->vendor, vendor, sizeof(frame->vendor));
++ strncpy(frame->product, product, sizeof(frame->product));
++
++ return 0;
++}
++EXPORT_SYMBOL(hdmi_spd_infoframe_init);
++
++/**
++ * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
++ * @frame: HDMI SPD infoframe
++ * @buffer: destination buffer
++ * @size: size of buffer
++ *
++ * Packs the information contained in the @frame structure into a binary
++ * representation that can be written into the corresponding controller
++ * registers. Also computes the checksum as required by section 5.3.5 of
++ * the HDMI 1.4 specification.
++ *
++ * Returns the number of bytes packed into the binary buffer or a negative
++ * error code on failure.
++ */
++ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
++ size_t size)
++{
++ u8 *ptr = buffer;
++ size_t length;
++
++ length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
++
++ if (size < length)
++ return -ENOSPC;
++
++ memset(buffer, 0, length);
++
++ ptr[0] = frame->type;
++ ptr[1] = frame->version;
++ ptr[2] = frame->length;
++ ptr[3] = 0; /* checksum */
++
++ /* start infoframe payload */
++ ptr += HDMI_INFOFRAME_HEADER_SIZE;
++
++ memcpy(ptr, frame->vendor, sizeof(frame->vendor));
++ memcpy(ptr + 8, frame->product, sizeof(frame->product));
++
++ ptr[24] = frame->sdi;
++
++ hdmi_infoframe_checksum(buffer, length);
++
++ return length;
++}
++EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
++
++/**
++ * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
++ * @frame: HDMI audio infoframe
++ *
++ * Returns 0 on success or a negative error code on failure.
++ */
++int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
++{
++ memset(frame, 0, sizeof(*frame));
++
++ frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
++ frame->version = 1;
++ frame->length = 10;
++
++ return 0;
++}
++EXPORT_SYMBOL(hdmi_audio_infoframe_init);
++
++/**
++ * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
++ * @frame: HDMI audio infoframe
++ * @buffer: destination buffer
++ * @size: size of buffer
++ *
++ * Packs the information contained in the @frame structure into a binary
++ * representation that can be written into the corresponding controller
++ * registers. Also computes the checksum as required by section 5.3.5 of
++ * the HDMI 1.4 specification.
++ *
++ * Returns the number of bytes packed into the binary buffer or a negative
++ * error code on failure.
++ */
++ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
++ void *buffer, size_t size)
++{
++ unsigned char channels;
++ u8 *ptr = buffer;
++ size_t length;
++
++ length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
++
++ if (size < length)
++ return -ENOSPC;
++
++ memset(buffer, 0, length);
++
++ if (frame->channels >= 2)
++ channels = frame->channels - 1;
++ else
++ channels = 0;
++
++ ptr[0] = frame->type;
++ ptr[1] = frame->version;
++ ptr[2] = frame->length;
++ ptr[3] = 0; /* checksum */
++
++ /* start infoframe payload */
++ ptr += HDMI_INFOFRAME_HEADER_SIZE;
++
++ ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
++ ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
++ (frame->sample_size & 0x3);
++ ptr[2] = frame->coding_type_ext & 0x1f;
++ ptr[3] = frame->channel_allocation;
++ ptr[4] = (frame->level_shift_value & 0xf) << 3;
++
++ if (frame->downmix_inhibit)
++ ptr[4] |= BIT(7);
++
++ hdmi_infoframe_checksum(buffer, length);
++
++ return length;
++}
++EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
++
++/**
++ * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary
++ * buffer
++ * @frame: HDMI vendor infoframe
++ * @buffer: destination buffer
++ * @size: size of buffer
++ *
++ * Packs the information contained in the @frame structure into a binary
++ * representation that can be written into the corresponding controller
++ * registers. Also computes the checksum as required by section 5.3.5 of
++ * the HDMI 1.4 specification.
++ *
++ * Returns the number of bytes packed into the binary buffer or a negative
++ * error code on failure.
++ */
++ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
++ void *buffer, size_t size)
++{
++ u8 *ptr = buffer;
++ size_t length;
++
++ length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
++
++ if (size < length)
++ return -ENOSPC;
++
++ memset(buffer, 0, length);
++
++ ptr[0] = frame->type;
++ ptr[1] = frame->version;
++ ptr[2] = frame->length;
++ ptr[3] = 0; /* checksum */
++
++ memcpy(&ptr[HDMI_INFOFRAME_HEADER_SIZE], frame->data, frame->length);
++
++ hdmi_infoframe_checksum(buffer, length);
++
++ return length;
++}
++EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
+diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
+new file mode 100644
+index 0000000..3b58944
+--- /dev/null
++++ b/include/linux/hdmi.h
+@@ -0,0 +1,231 @@
++/*
++ * Copyright (C) 2012 Avionic Design GmbH
++ *
++ * 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_HDMI_H_
++#define __LINUX_HDMI_H_
++
++#include <linux/types.h>
++
++enum hdmi_infoframe_type {
++ HDMI_INFOFRAME_TYPE_VENDOR = 0x81,
++ HDMI_INFOFRAME_TYPE_AVI = 0x82,
++ HDMI_INFOFRAME_TYPE_SPD = 0x83,
++ HDMI_INFOFRAME_TYPE_AUDIO = 0x84,
++};
++
++#define HDMI_INFOFRAME_HEADER_SIZE 4
++#define HDMI_AVI_INFOFRAME_SIZE 13
++#define HDMI_SPD_INFOFRAME_SIZE 25
++#define HDMI_AUDIO_INFOFRAME_SIZE 10
++
++enum hdmi_colorspace {
++ HDMI_COLORSPACE_RGB,
++ HDMI_COLORSPACE_YUV422,
++ HDMI_COLORSPACE_YUV444,
++};
++
++enum hdmi_scan_mode {
++ HDMI_SCAN_MODE_NONE,
++ HDMI_SCAN_MODE_OVERSCAN,
++ HDMI_SCAN_MODE_UNDERSCAN,
++};
++
++enum hdmi_colorimetry {
++ HDMI_COLORIMETRY_NONE,
++ HDMI_COLORIMETRY_ITU_601,
++ HDMI_COLORIMETRY_ITU_709,
++ HDMI_COLORIMETRY_EXTENDED,
++};
++
++enum hdmi_picture_aspect {
++ HDMI_PICTURE_ASPECT_NONE,
++ HDMI_PICTURE_ASPECT_4_3,
++ HDMI_PICTURE_ASPECT_16_9,
++};
++
++enum hdmi_active_aspect {
++ HDMI_ACTIVE_ASPECT_16_9_TOP = 2,
++ HDMI_ACTIVE_ASPECT_14_9_TOP = 3,
++ HDMI_ACTIVE_ASPECT_16_9_CENTER = 4,
++ HDMI_ACTIVE_ASPECT_PICTURE = 8,
++ HDMI_ACTIVE_ASPECT_4_3 = 9,
++ HDMI_ACTIVE_ASPECT_16_9 = 10,
++ HDMI_ACTIVE_ASPECT_14_9 = 11,
++ HDMI_ACTIVE_ASPECT_4_3_SP_14_9 = 13,
++ HDMI_ACTIVE_ASPECT_16_9_SP_14_9 = 14,
++ HDMI_ACTIVE_ASPECT_16_9_SP_4_3 = 15,
++};
++
++enum hdmi_extended_colorimetry {
++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601,
++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_709,
++ HDMI_EXTENDED_COLORIMETRY_S_YCC_601,
++ HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601,
++ HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB,
++};
++
++enum hdmi_quantization_range {
++ HDMI_QUANTIZATION_RANGE_DEFAULT,
++ HDMI_QUANTIZATION_RANGE_LIMITED,
++ HDMI_QUANTIZATION_RANGE_FULL,
++};
++
++/* non-uniform picture scaling */
++enum hdmi_nups {
++ HDMI_NUPS_UNKNOWN,
++ HDMI_NUPS_HORIZONTAL,
++ HDMI_NUPS_VERTICAL,
++ HDMI_NUPS_BOTH,
++};
++
++enum hdmi_ycc_quantization_range {
++ HDMI_YCC_QUANTIZATION_RANGE_LIMITED,
++ HDMI_YCC_QUANTIZATION_RANGE_FULL,
++};
++
++enum hdmi_content_type {
++ HDMI_CONTENT_TYPE_NONE,
++ HDMI_CONTENT_TYPE_PHOTO,
++ HDMI_CONTENT_TYPE_CINEMA,
++ HDMI_CONTENT_TYPE_GAME,
++};
++
++struct hdmi_avi_infoframe {
++ enum hdmi_infoframe_type type;
++ unsigned char version;
++ unsigned char length;
++ enum hdmi_colorspace colorspace;
++ bool active_info_valid;
++ bool horizontal_bar_valid;
++ bool vertical_bar_valid;
++ enum hdmi_scan_mode scan_mode;
++ enum hdmi_colorimetry colorimetry;
++ enum hdmi_picture_aspect picture_aspect;
++ enum hdmi_active_aspect active_aspect;
++ bool itc;
++ enum hdmi_extended_colorimetry extended_colorimetry;
++ enum hdmi_quantization_range quantization_range;
++ enum hdmi_nups nups;
++ unsigned char video_code;
++ enum hdmi_ycc_quantization_range ycc_quantization_range;
++ enum hdmi_content_type content_type;
++ unsigned char pixel_repeat;
++ unsigned short top_bar;
++ unsigned short bottom_bar;
++ unsigned short left_bar;
++ unsigned short right_bar;
++};
++
++int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
++ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
++ size_t size);
++
++enum hdmi_spd_sdi {
++ HDMI_SPD_SDI_UNKNOWN,
++ HDMI_SPD_SDI_DSTB,
++ HDMI_SPD_SDI_DVDP,
++ HDMI_SPD_SDI_DVHS,
++ HDMI_SPD_SDI_HDDVR,
++ HDMI_SPD_SDI_DVC,
++ HDMI_SPD_SDI_DSC,
++ HDMI_SPD_SDI_VCD,
++ HDMI_SPD_SDI_GAME,
++ HDMI_SPD_SDI_PC,
++ HDMI_SPD_SDI_BD,
++ HDMI_SPD_SDI_SACD,
++ HDMI_SPD_SDI_HDDVD,
++ HDMI_SPD_SDI_PMP,
++};
++
++struct hdmi_spd_infoframe {
++ enum hdmi_infoframe_type type;
++ unsigned char version;
++ unsigned char length;
++ char vendor[8];
++ char product[16];
++ enum hdmi_spd_sdi sdi;
++};
++
++int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
++ const char *vendor, const char *product);
++ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
++ size_t size);
++
++enum hdmi_audio_coding_type {
++ HDMI_AUDIO_CODING_TYPE_STREAM,
++ HDMI_AUDIO_CODING_TYPE_PCM,
++ HDMI_AUDIO_CODING_TYPE_AC3,
++ HDMI_AUDIO_CODING_TYPE_MPEG1,
++ HDMI_AUDIO_CODING_TYPE_MP3,
++ HDMI_AUDIO_CODING_TYPE_MPEG2,
++ HDMI_AUDIO_CODING_TYPE_AAC_LC,
++ HDMI_AUDIO_CODING_TYPE_DTS,
++ HDMI_AUDIO_CODING_TYPE_ATRAC,
++ HDMI_AUDIO_CODING_TYPE_DSD,
++ HDMI_AUDIO_CODING_TYPE_EAC3,
++ HDMI_AUDIO_CODING_TYPE_DTS_HD,
++ HDMI_AUDIO_CODING_TYPE_MLP,
++ HDMI_AUDIO_CODING_TYPE_DST,
++ HDMI_AUDIO_CODING_TYPE_WMA_PRO,
++};
++
++enum hdmi_audio_sample_size {
++ HDMI_AUDIO_SAMPLE_SIZE_STREAM,
++ HDMI_AUDIO_SAMPLE_SIZE_16,
++ HDMI_AUDIO_SAMPLE_SIZE_20,
++ HDMI_AUDIO_SAMPLE_SIZE_24,
++};
++
++enum hdmi_audio_sample_frequency {
++ HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM,
++ HDMI_AUDIO_SAMPLE_FREQUENCY_32000,
++ HDMI_AUDIO_SAMPLE_FREQUENCY_44100,
++ HDMI_AUDIO_SAMPLE_FREQUENCY_48000,
++ HDMI_AUDIO_SAMPLE_FREQUENCY_88200,
++ HDMI_AUDIO_SAMPLE_FREQUENCY_96000,
++ HDMI_AUDIO_SAMPLE_FREQUENCY_176400,
++ HDMI_AUDIO_SAMPLE_FREQUENCY_192000,
++};
++
++enum hdmi_audio_coding_type_ext {
++ HDMI_AUDIO_CODING_TYPE_EXT_STREAM,
++ HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC,
++ HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2,
++ HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND,
++};
++
++struct hdmi_audio_infoframe {
++ enum hdmi_infoframe_type type;
++ unsigned char version;
++ unsigned char length;
++ unsigned char channels;
++ enum hdmi_audio_coding_type coding_type;
++ enum hdmi_audio_sample_size sample_size;
++ enum hdmi_audio_sample_frequency sample_frequency;
++ enum hdmi_audio_coding_type_ext coding_type_ext;
++ unsigned char channel_allocation;
++ unsigned char level_shift_value;
++ bool downmix_inhibit;
++
++};
++
++int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
++ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
++ void *buffer, size_t size);
++
++struct hdmi_vendor_infoframe {
++ enum hdmi_infoframe_type type;
++ unsigned char version;
++ unsigned char length;
++ u8 data[27];
++};
++
++ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
++ void *buffer, size_t size);
++
++#endif /* _DRM_HDMI_H */
diff --git a/patches/linux-3.8.13/0575-BeagleBone-Black-TDA998x-Initial-HDMI-Audio-support.patch b/patches/linux-3.8.13/0575-BeagleBone-Black-TDA998x-Initial-HDMI-Audio-support.patch
new file mode 100644
index 0000000..9eddf81
--- /dev/null
+++ b/patches/linux-3.8.13/0575-BeagleBone-Black-TDA998x-Initial-HDMI-Audio-support.patch
@@ -0,0 +1,784 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Fri, 19 Apr 2013 12:37:37 -0500
+Subject: [PATCH] BeagleBone Black TDA998x Initial HDMI Audio support
+
+commit 5e166deffcfe438f57ec334e288e068e42fb05bb
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Fri Apr 19 11:34:44 2013 -0500
+
+ tda998x - select the correct i2s format for BBB
+
+commit 27ce11f74e084c2d49bd9d50db7eaf8fe3386bf9
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Thu Apr 18 15:42:57 2013 -0500
+
+ TDA998x initial attempt at adding HDMI/audio
+ This now supports HDMI with correct CEA timings and Audio output (fixed at 48KHz)
+
+commit a25d22ec97a60611ba8f3579a015fa05ee4f96fa
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 17:06:40 2013 -0500
+
+ TILCDC enable pulling in HDMI infoframe helper functions
+
+commit 90cd4a836a4d60232d70f84f56a854c794917422
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 14:11:59 2013 -0500
+
+ Adding new audio driver-combined with DRM driver for NXP TDA 998x
+
+commit df7d51d3aebcb2222be60acfd3408e67d83d9383
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 13:52:29 2013 -0500
+
+ Remove debug, changing codec name to dedicated NXP
+
+commit 566687c6bb1c80a1d8e8cb66b469152bf69ae67b
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 12:14:08 2013 -0500
+
+ Remove NXP supplied driver from the build
+ Replace with custom DRM driver.
+
+commit c150fef5971088705fc155163a3a5a4f805b321e
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 12:07:25 2013 -0500
+
+ AM335x audio back to original setup, with new NXP hdmi driver moved to DRM
+
+commit 19c2249b7e4ad600f28bfdb67106abe0c8509701
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 11:55:50 2013 -0500
+
+ Reverting file back to original form and replacing with custom NXP driver
+ that will be part of the DRM driver.
+
+commit da88657d82d52ad212f34429b7b349dbea093bc0
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 11:50:02 2013 -0500
+
+ Cleaning up for NXP codec support on BeagleBone Black
+
+commit bda7bcce6f54c8108bd8dc9efb5e0f4c375f112d
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 11:48:44 2013 -0500
+
+ Added a new build target for NXP audio driver
+
+commit 38b5a020fa895a6da2b495a5b46b7f5e4cb5a0a4
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 11:47:40 2013 -0500
+
+ Changing to put the NXP into HDMI mode by default
+ Much more work is needed to make this into a real driver
+ with audio support.
+
+commit 0bdff4a28649d1c17bff1d74ca41bf9ce28f7743
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Wed Apr 17 11:46:15 2013 -0500
+
+ Initial version of dummy codec driver for NXP HDMI encoder
+
+commit e15d0879137b6cb15c1ff57d9f32d60f4ba9e232
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Fri Apr 12 16:45:43 2013 -0500
+
+ Fixing typo in Bone Cape DTS file
+
+commit 8a2693c254cc56227f9b8ae180df64963ec944dd
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Fri Apr 5 16:15:45 2013 -0500
+
+ Fixing the default audio format from the mcasp for nxp hdmi driver.
+
+commit 1e66174fbe31672e3fb8776fe6146d4445916021
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Fri Apr 5 13:09:24 2013 -0500
+
+ Create an hdmi device and fix setting in mcasp
+ this is very much a temporary commit and needs to be cleaned up and
+ done the right way before it is rolled out further.
+
+commit e48b28929abdfa635d69fca38009bea1422745e7
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Fri Apr 5 13:07:51 2013 -0500
+
+ Set the right format for HDMI Codec
+
+commit 465924ca1fd1a27c252f47fe6f501444f624319d
+Author: Darren Etheridge <detheridge@ti.com>
+Date: Fri Apr 5 10:44:03 2013 -0500
+
+ Add the necessary device tree nodes to enable HDMI audio. Add code to enable the McASP clock
+ that is enabled by setting gpio1_27 high. Create a new machine in Davinci audio driver for
+ BeagleBone Black.
+---
+ drivers/gpu/drm/i2c/Kconfig | 1 +
+ drivers/gpu/drm/i2c/Makefile | 2 +-
+ drivers/gpu/drm/i2c/tda998x_audio_drv.c | 76 ++++++++++
+ drivers/gpu/drm/i2c/tda998x_drv.c | 205 ++++++++++++++++++++++++++-
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 52 +++++++
+ sound/soc/davinci/davinci-evm.c | 50 ++++++-
+ sound/soc/davinci/davinci-mcasp.c | 15 +-
+ 7 files changed, 385 insertions(+), 16 deletions(-)
+ create mode 100644 drivers/gpu/drm/i2c/tda998x_audio_drv.c
+
+diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
+index 4d341db..2342005 100644
+--- a/drivers/gpu/drm/i2c/Kconfig
++++ b/drivers/gpu/drm/i2c/Kconfig
+@@ -22,6 +22,7 @@ config DRM_I2C_SIL164
+ config DRM_I2C_NXP_TDA998X
+ tristate "NXP Semiconductors TDA998X HDMI encoder"
+ default m if DRM_TILCDC
++ select HDMI
+ help
+ Support for NXP Semiconductors TDA998X HDMI encoders.
+
+diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
+index 43aa33b..0ba6bd3 100644
+--- a/drivers/gpu/drm/i2c/Makefile
++++ b/drivers/gpu/drm/i2c/Makefile
+@@ -6,5 +6,5 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
+ sil164-y := sil164_drv.o
+ obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
+
+-tda998x-y := tda998x_drv.o
++tda998x-y := tda998x_drv.o tda998x_audio_drv.o
+ obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
+diff --git a/drivers/gpu/drm/i2c/tda998x_audio_drv.c b/drivers/gpu/drm/i2c/tda998x_audio_drv.c
+new file mode 100644
+index 0000000..c13e25b
+--- /dev/null
++++ b/drivers/gpu/drm/i2c/tda998x_audio_drv.c
+@@ -0,0 +1,76 @@
++/*
++ * ALSA SoC codec driver for HDMI audio on NXP TDA998x series.
++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
++ * Author: Darren Etheridge <detheridge@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.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ *
++ */
++#include <linux/module.h>
++#include <sound/soc.h>
++#include <linux/of_device.h>
++
++#define DRV_NAME "nxp-hdmi-audio-codec"
++
++static struct snd_soc_codec_driver nxp_hdmi_codec;
++
++static struct snd_soc_dai_driver nxp_hdmi_codec_dai = {
++ .name = "nxp-hdmi-hifi",
++ .playback = {
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_48000,
++ .formats = SNDRV_PCM_FMTBIT_S32_LE,
++ },
++};
++
++#ifdef CONFIG_OF
++static const struct of_device_id nxptda_dt_ids[] = {
++ { .compatible = "nxp,nxptda", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, nxptda_dt_ids);
++#endif
++
++
++static int nxp_hdmi_codec_probe(struct platform_device *pdev)
++{
++ return snd_soc_register_codec(&pdev->dev, &nxp_hdmi_codec,
++ &nxp_hdmi_codec_dai, 1);
++}
++
++static int nxp_hdmi_codec_remove(struct platform_device *pdev)
++{
++ snd_soc_unregister_codec(&pdev->dev);
++ return 0;
++}
++
++static struct platform_driver nxp_hdmi_codec_driver = {
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(nxptda_dt_ids)
++ },
++
++ .probe = nxp_hdmi_codec_probe,
++ .remove = nxp_hdmi_codec_remove,
++};
++
++module_platform_driver(nxp_hdmi_codec_driver);
++
++MODULE_AUTHOR("Darren Etheridge <detheridge@ti.com>");
++MODULE_DESCRIPTION("ASoC NXP Dummy HDMI codec driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:" DRV_NAME);
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index e68b58a..e3e9101 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -23,7 +23,7 @@
+ #include <drm/drm_crtc_helper.h>
+ #include <drm/drm_encoder_slave.h>
+ #include <drm/drm_edid.h>
+-
++#include <linux/hdmi.h>
+
+ #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+@@ -110,6 +110,9 @@ struct tda998x_priv {
+ #define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
+ # define VIP_CNTRL_5_CKCASE (1 << 0)
+ # define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
++
++#define REG_MUX_AP REG(0x00, 0x26)
++# define MUX_AP_SELECT_I2S (0x64)
+ #define REG_MAT_CONTRL REG(0x00, 0x80) /* write */
+ # define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0)
+ # define MAT_CONTRL_MAT_BP (1 << 2)
+@@ -171,7 +174,10 @@ struct tda998x_priv {
+ # define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4)
+ # define HVF_CNTRL_1_SEMI_PLANAR (1 << 6)
+ #define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */
++#define REG_I2S_FORMAT REG(0x00, 0xfc)
+
++#define REG_AIP_CLKSEL REG(0x00, 0xfd)
++# define SEL_AIP_I2S (1 << 3) /* I2S Clk */
+
+ /* Page 02h: PLL settings */
+ #define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */
+@@ -212,7 +218,8 @@ struct tda998x_priv {
+
+
+ /* Page 10h: information frames and packets */
+-
++#define REG_AVI_IF REG(0x10, 0x40) /* AVI Infoframe packet */
++#define REG_AUDIO_IF REG(0x10, 0x80) /* AVI Infoframe packet */
+
+ /* Page 11h: audio settings and content info packets */
+ #define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */
+@@ -221,11 +228,28 @@ struct tda998x_priv {
+ # define AIP_CNTRL_0_LAYOUT (1 << 2)
+ # define AIP_CNTRL_0_ACR_MAN (1 << 5)
+ # define AIP_CNTRL_0_RST_CTS (1 << 6)
++#define REG_ACR_CTS_0 REG(0x11, 0x05)
++#define REG_ACR_CTS_1 REG(0x11, 0x06)
++#define REG_ACR_CTS_2 REG(0x11, 0x07)
++#define REG_ACR_N_0 REG(0x11, 0x08)
++#define REG_ACR_N_1 REG(0x11, 0x09)
++#define REG_ACR_N_2 REG(0x11, 0x0a)
++#define REG_GC_AVMUTE REG(0x11, 0x0b)
++# define GC_AVMUTE_CLRMUTE (1 << 0)
++# define GC_AVMUTE_SETMUTE (1 << 1)
++#define REG_CTS_N REG(0x11, 0x0c)
+ #define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */
+ # define ENC_CNTRL_RST_ENC (1 << 0)
+ # define ENC_CNTRL_RST_SEL (1 << 1)
+ # define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2)
+-
++#define REG_DIP_FLAGS REG(0x11, 0x0e)
++# define DIP_FLAGS_ACR (1 << 0)
++#define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */
++#define DIP_IF_FLAGS_IF1 (1 << 1)
++#define DIP_IF_FLAGS_IF2 (1 << 2)
++#define DIP_IF_FLAGS_IF3 (1 << 3)
++#define DIP_IF_FLAGS_IF4 (1 << 4)
++#define DIP_IF_FLAGS_IF5 (1 << 5)
+
+ /* Page 12h: HDCP and OTP */
+ #define REG_TX3 REG(0x12, 0x9a) /* read/write */
+@@ -262,6 +286,9 @@ struct tda998x_priv {
+ #define TDA19989N2 0x0202
+ #define TDA19988 0x0301
+
++static uint8_t *
++do_get_edid(struct drm_encoder *encoder);
++
+ static void
+ cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
+ {
+@@ -338,6 +365,35 @@ fail:
+ return ret;
+ }
+
++static int
++reg_write_range(struct drm_encoder *encoder, uint16_t reg, char *buf, int cnt)
++{
++ struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
++ int ret = 0;
++ uint8_t *i2cpacket;
++
++ i2cpacket = (uint8_t *)kmalloc(cnt + 1, GFP_KERNEL);
++ if(!i2cpacket) {
++ goto fail;
++ }
++ i2cpacket[0] = REG2ADDR(reg);
++ memcpy(&i2cpacket[1], buf, cnt);
++
++ set_page(encoder, reg);
++
++ ret = i2c_master_send(client, i2cpacket, cnt+1);
++ kfree(i2cpacket);
++ if (ret < 0)
++ goto fail;
++
++ return ret;
++
++fail:
++ dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
++ return ret;
++}
++
++
+ static uint8_t
+ reg_read(struct drm_encoder *encoder, uint16_t reg)
+ {
+@@ -437,7 +493,7 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+ switch (mode) {
+ case DRM_MODE_DPMS_ON:
+ /* enable audio and video ports */
+- reg_write(encoder, REG_ENA_AP, 0xff);
++ reg_write(encoder, REG_ENA_AP, 0x03);
+ reg_write(encoder, REG_ENA_VP_0, 0xff);
+ reg_write(encoder, REG_ENA_VP_1, 0xff);
+ reg_write(encoder, REG_ENA_VP_2, 0xff);
+@@ -488,6 +544,87 @@ tda998x_encoder_mode_valid(struct drm_encoder *encoder,
+ return MODE_OK;
+ }
+
++
++static void
++tda998x_audio_infoframe_enable(struct drm_encoder *encoder)
++{
++ uint8_t buffer[20];
++ struct hdmi_audio_infoframe audio_frame;
++ size_t len;
++
++ hdmi_audio_infoframe_init(&audio_frame);
++
++ /* NXP audio is fixed at these values for the time being */
++ audio_frame.channels = 2;
++ audio_frame.coding_type = HDMI_AUDIO_CODING_TYPE_PCM;
++ audio_frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_24;
++ audio_frame.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
++
++ len = hdmi_audio_infoframe_pack(&audio_frame, buffer, sizeof(buffer));
++ WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
++
++ reg_write_range(encoder, REG_AUDIO_IF, buffer, len);
++
++ /* enable Audio Infoframe output in DIP_IF Register */
++ reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
++ udelay(5);
++ reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
++}
++
++static void
++tda998x_avi_infoframe_enable(struct drm_encoder *encoder,
++ struct drm_display_mode *mode)
++{
++ uint8_t buffer[20];
++ struct hdmi_avi_infoframe avi_frame;
++ size_t len;
++
++ hdmi_avi_infoframe_init(&avi_frame);
++ avi_frame.video_code = drm_match_cea_mode(mode);
++ avi_frame.picture_aspect = HDMI_PICTURE_ASPECT_NONE;
++ avi_frame.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
++ len = hdmi_avi_infoframe_pack(&avi_frame, buffer, sizeof(buffer));
++ WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
++
++ reg_write_range(encoder, REG_AVI_IF, buffer, len);
++
++ /*
++ * enable AVI Infoframe output in DIP_IF Register, but toggle it
++ * so that the hardware acknowledges that the packet data might have
++ * changed
++ */
++ reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF3);
++ udelay(5);
++ reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF3);
++}
++
++/* loopup table for CEA values to VIDFORMAT values taken from NXP datasheet */
++static char cea_to_nxp_mode[32] = {-1, 0, 1, 1, 2, 3, 4, 4, 5, 5, -1, -1,
++ -1, -1, -1, -1, 6, 7, 7, 8, 9, 10, 10,
++ 11, 11, -1, -1, -1, -1, -1, -1, 12};
++
++static char tda998x_cea_to_vidformat(unsigned char cea_mode)
++{
++ if(cea_mode > 31) {
++ return -1;
++ }
++ return cea_to_nxp_mode[cea_mode];
++}
++
++static char tda998x_is_monitor_hdmi(struct drm_encoder *encoder)
++{
++ struct edid *edid = (struct edid *)do_get_edid(encoder);
++ char hdmi = 0;
++ if(edid) {
++ hdmi = drm_detect_hdmi_monitor(edid);
++ kfree(edid);
++ } else {
++ return -1;
++ }
++ return hdmi;
++}
++
++
+ static void
+ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+@@ -534,7 +671,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ /* mute the audio FIFO: */
+ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+
+- /* set HDMI HDCP mode off: */
++ /* HDMI/HDCP mode off... for now...: */
+ reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+ reg_clear(encoder, REG_TX33, TX33_HDMI);
+
+@@ -605,14 +742,69 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ reg = TBG_CNTRL_1_VHX_EXT_DE |
+ TBG_CNTRL_1_VHX_EXT_HS |
+ TBG_CNTRL_1_VHX_EXT_VS |
+- TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
++ TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
+ TBG_CNTRL_1_VH_TGL_2;
+ if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC))
+ reg |= TBG_CNTRL_1_VH_TGL_0;
+ reg_set(encoder, REG_TBG_CNTRL_1, reg);
+
++
++
++
++ if(tda998x_is_monitor_hdmi(encoder) == 1) {
++ char vidformat;
++ vidformat = tda998x_cea_to_vidformat(drm_match_cea_mode(mode));
++ if(vidformat == (char)-1) {
++ dev_err(encoder->dev->dev, "Not sure which CEA mode to set, leaving as DVI");
++ goto out;
++ }
++ dev_info(encoder->dev->dev, "Connected to an HDMI monitor with cea mode %d", vidformat);
++
++ /* this is an HDMI monitor, so set things up a bit differently */
++ reg_write(encoder, REG_TBG_CNTRL_1, 0);
++ reg_write(encoder, REG_VIDFORMAT, vidformat);
++ /* get the infoframes pumping */
++ tda998x_avi_infoframe_enable(encoder, mode);
++ tda998x_audio_infoframe_enable(encoder);
++ reg_set(encoder, REG_TX33, TX33_HDMI);
++
++ /* set up audio registers */
++ reg_write(encoder, REG_ACR_CTS_0, 0x0);
++ reg_write(encoder, REG_ACR_CTS_1, 0x0);
++ reg_write(encoder, REG_ACR_CTS_2, 0x0);
++
++ reg_write(encoder, REG_ACR_N_0, 0x0);
++ reg_write(encoder, REG_ACR_N_1, 0x18);
++ reg_write(encoder, REG_ACR_N_2, 0x0);
++
++ reg_set(encoder, REG_DIP_FLAGS, DIP_FLAGS_ACR);
++
++ reg_write(encoder, REG_ENC_CNTRL, 0x04);
++ reg_write(encoder, REG_CTS_N, 0x33);
++ /* Set 2 channel I2S mode */
++ reg_write(encoder, REG_ENA_AP, 0x3);
++
++ /* set audio divider in pll settings */
++ reg_write(encoder, REG_AUDIO_DIV, 0x2);
++
++ /* select the audio input port clock */
++ reg_write(encoder, REG_AIP_CLKSEL, SEL_AIP_I2S);
++ reg_write(encoder, REG_MUX_AP, MUX_AP_SELECT_I2S);
++
++ /* select I2S format, and datasize */
++ reg_write(encoder, REG_I2S_FORMAT, 0x0a);
++
++ /* enable the audio FIFO: */
++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
++
++ /* mute and then unmute, to get audio going */
++ reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_SETMUTE);
++ reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_CLRMUTE);
++ }
++out:
+ /* must be last register set: */
+ reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
++
+ }
+
+ static enum drm_connector_status
+@@ -904,3 +1096,4 @@ MODULE_LICENSE("GPL");
+
+ module_init(tda998x_init);
+ module_exit(tda998x_exit);
++
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index ee36d0e..e5f714a 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -46,6 +46,16 @@
+ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+ >;
+ };
++
++ mcasp0_pins: mcasp0_pins {
++ pinctrl-single,pins = <
++ 0x1ac 0x30 /* mcasp0_ahclkx, MODE0 | INPUT */
++ 0x19c 0x02 /* mcasp0_ahclkr, */
++ 0x194 0x10 /* mcasp0_fsx, MODE0 | OUTPUT */
++ 0x190 0x00 /* mcasp0_aclkr.mcasp0_aclkx, MODE0 | OUTPUT_PULLDOWN */
++ 0x1a8 0x1f /* mcasp0_axr1 GPIO1_27 | OUTPUT | PULLUP */
++ >;
++ };
+ };
+ };
+
+@@ -57,6 +67,11 @@
+ #address-cells = <1>;
+ #size-cells = <1>;
+
++ nxptda: nxptda@0 {
++ compatible = "nxp,nxptda";
++ status = "okay";
++ };
++
+ hdmi {
+ compatible = "tilcdc,slave";
+ i2c = <&i2c0>;
+@@ -77,4 +92,41 @@
+ };
+ };
+
++ fragment@3 {
++ target = <&mcasp0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&mcasp0_pins>;
++
++ status = "okay";
++
++ op-mode = <0>; /* MCASP_IIS_MODE */
++ tdm-slots = <2>;
++ num-serializer = <16>;
++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
++ 0 0 1 0
++ 0 0 0 0
++ 0 0 0 0
++ 0 0 0 0
++ >;
++ tx-num-evt = <1>;
++ rx-num-evt = <1>;
++ };
++ };
++
++ fragment@4 {
++ target = <&ocp>;
++ __overlay__ {
++ sound {
++ compatible = "ti,am33xx-beaglebone-black";
++ ti,model = "TI BeagleBone Black";
++ ti,audio-codec = <&nxptda>;
++ ti,mcasp-controller = <&mcasp0>;
++ ti,codec-clock-rate = <2457600>;
++ mcasp_clock_enable = <&gpio2 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
++ };
++ };
++
++ };
++
+ };
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+index 349db80..7a7fc47 100644
+--- a/sound/soc/davinci/davinci-evm.c
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -30,6 +30,9 @@
+ #include "davinci-i2s.h"
+ #include "davinci-mcasp.h"
+
++#include <linux/of_gpio.h>
++
++
+ #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
+ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
+ static int evm_hw_params(struct snd_pcm_substream *substream,
+@@ -311,11 +314,13 @@ static struct snd_soc_card da850_snd_soc_card = {
+ .num_links = 1,
+ };
+
++
+ #if defined(CONFIG_OF)
+
+ enum {
+ MACHINE_VERSION_1 = 0, /* DM365 with Voice Codec */
+ MACHINE_VERSION_2, /* DM365/DA8xx/OMAPL1x/AM33xx */
++ MACHINE_VERSION_3, /* AM33xx BeagleBone Black */
+ };
+
+ static const struct of_device_id davinci_evm_dt_ids[] = {
+@@ -327,6 +332,10 @@ static const struct of_device_id davinci_evm_dt_ids[] = {
+ .compatible = "ti,da830-evm-audio",
+ .data = (void *)MACHINE_VERSION_2,
+ },
++ {
++ .compatible = "ti,am33xx-beaglebone-black",
++ .data = (void *)MACHINE_VERSION_3,
++ },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, davinci_mcasp_dt_ids);
+@@ -353,7 +362,7 @@ static int davinci_evm_probe(struct platform_device *pdev)
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match =
+ of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
+- u32 machine_ver;
++ u32 machine_ver, clk_gpio;
+ int ret = 0;
+
+ machine_ver = (u32)match->data;
+@@ -363,12 +372,37 @@ static int davinci_evm_probe(struct platform_device *pdev)
+ evm_dai.stream_name = "CQ93";
+ evm_dai.codec_dai_name = "cq93vc-hifi";
+ break;
+-
+ case MACHINE_VERSION_2:
+ evm_dai.ops = &evm_ops;
+ evm_dai.init = evm_aic3x_init;
+ break;
++ case MACHINE_VERSION_3:
++ evm_dai.name = "NXP TDA HDMI Chip";
++ evm_dai.stream_name = "HDMI";
++ evm_dai.codec_dai_name = "nxp-hdmi-hifi";
++
++ /*
++ * Move GPIO handling out of the probe, if probe gets
++ * deferred, the gpio will have been claimed on previous
++ * probe and will fail on the second and susequent probes
++ */
++ clk_gpio = of_get_named_gpio(np, "mcasp_clock_enable", 0);
++ if (clk_gpio < 0) {
++ dev_err(&pdev->dev, "failed to find mcasp_clock enable GPIO!\n");
++ return -EINVAL;
++ }
++ ret = gpio_request_one(clk_gpio, GPIOF_OUT_INIT_HIGH,
++ "McASP Clock Enable Pin");
++ if (ret < 0) {
++ dev_err(&pdev->dev, "Failed to claim McASP Clock Enable pin\n");
++ return -EINVAL;
++ }
++ gpio_set_value(clk_gpio, 1);
++ evm_dai.dai_fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF;
++ break;
++
+ }
++
+
+ evm_dai.codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
+ if (!evm_dai.codec_of_node)
+@@ -387,9 +421,9 @@ static int davinci_evm_probe(struct platform_device *pdev)
+ return ret;
+
+ ret = snd_soc_register_card(&evm_soc_card);
+- if (ret)
++ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+-
++ }
+ return ret;
+ }
+
+@@ -426,8 +460,9 @@ static int __init evm_init(void)
+ * If dtb is there, the devices will be created dynamically.
+ * Only register platfrom driver structure.
+ */
+- if (of_have_populated_dt())
+- return platform_driver_register(&davinci_evm_driver);
++ if (of_have_populated_dt()) {
++ return platform_driver_register(&davinci_evm_driver);
++ }
+ #endif
+
+ if (machine_is_davinci_evm()) {
+@@ -448,8 +483,9 @@ static int __init evm_init(void)
+ } else if (machine_is_davinci_da850_evm()) {
+ evm_snd_dev_data = &da850_snd_soc_card;
+ index = 0;
+- } else
++ } else {
+ return -EINVAL;
++ }
+
+ evm_snd_device = platform_device_alloc("soc-audio", index);
+ if (!evm_snd_device)
+diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
+index ea292f6..4c700df 100644
+--- a/sound/soc/davinci/davinci-mcasp.c
++++ b/sound/soc/davinci/davinci-mcasp.c
+@@ -497,16 +497,22 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+- /* codec is clock and frame slave */
+- mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
++ /* codec is clock and frame slave */
++ printk("SND_SOC_DAIFMT_CBS_CFS entered\n");
++ mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | ACLKXDIV(7));
++ mcasp_set_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(0));
++ mcasp_clr_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+ mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+
+ mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+ mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+
+ mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
++ mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
++ printk("SND_SOC_DAIFMT_CBM_CFS entered\n");
++
+ /* codec is clock master and frame slave */
+ mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+ mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+@@ -520,6 +526,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ AFSX | AFSR);
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
++ printk("SND_SOC_DAIFMT_CBM_CFM entered\n");
+ /* codec is clock and frame master */
+ mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+ mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+@@ -746,6 +753,8 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* bit stream is MSB first with no delay */
+ /* DSP_B mode */
++ printk("davinci hw_params _ PLAYBACK modified\n");
++ mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+ mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
+ mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
+
+@@ -755,6 +764,8 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
+ else
+ printk(KERN_ERR "playback tdm slot %d not supported\n",
+ dev->tdm_slots);
++ mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
++ mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+ } else {
+ /* bit stream is MSB first with no delay */
+ /* DSP_B mode */
diff --git a/patches/linux-3.8.13/0576-Clean-up-some-formating-and-debug-in-Davinci-MCASP-d.patch b/patches/linux-3.8.13/0576-Clean-up-some-formating-and-debug-in-Davinci-MCASP-d.patch
new file mode 100644
index 0000000..3dda5bc
--- /dev/null
+++ b/patches/linux-3.8.13/0576-Clean-up-some-formating-and-debug-in-Davinci-MCASP-d.patch
@@ -0,0 +1,55 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Fri, 19 Apr 2013 13:18:14 -0500
+Subject: [PATCH] Clean up some formating and debug in Davinci MCASP driver
+
+---
+ sound/soc/davinci/davinci-mcasp.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
+index 4c700df..bef4e72 100644
+--- a/sound/soc/davinci/davinci-mcasp.c
++++ b/sound/soc/davinci/davinci-mcasp.c
+@@ -497,11 +497,10 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+- /* codec is clock and frame slave */
+- printk("SND_SOC_DAIFMT_CBS_CFS entered\n");
+- mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | ACLKXDIV(7));
+- mcasp_set_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(0));
+- mcasp_clr_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
++ /* codec is clock and frame slave */
++ mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | ACLKXDIV(7));
++ mcasp_set_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(0));
++ mcasp_clr_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+ mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+
+ mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+@@ -511,8 +510,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+- printk("SND_SOC_DAIFMT_CBM_CFS entered\n");
+-
+ /* codec is clock master and frame slave */
+ mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+ mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+@@ -526,7 +523,6 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ AFSX | AFSR);
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+- printk("SND_SOC_DAIFMT_CBM_CFM entered\n");
+ /* codec is clock and frame master */
+ mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+ mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+@@ -753,8 +749,7 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* bit stream is MSB first with no delay */
+ /* DSP_B mode */
+- printk("davinci hw_params _ PLAYBACK modified\n");
+- mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
++ mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+ mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
+ mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
+
diff --git a/patches/linux-3.8.13/0577-tilcdc-Prune-modes-that-can-t-support-audio.patch b/patches/linux-3.8.13/0577-tilcdc-Prune-modes-that-can-t-support-audio.patch
new file mode 100644
index 0000000..339d422
--- /dev/null
+++ b/patches/linux-3.8.13/0577-tilcdc-Prune-modes-that-can-t-support-audio.patch
@@ -0,0 +1,240 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 3 May 2013 16:11:53 +0300
+Subject: [PATCH] tilcdc: Prune modes that can't support audio.
+
+If the connector supports audio, prune all the display modes that
+don't support it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 73 +++++++++++++++++++-------------
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 9 +++-
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 3 +-
+ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 2 +-
+ drivers/gpu/drm/tilcdc/tilcdc_slave.c | 6 ++-
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 2 +-
+ 6 files changed, 59 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 69675e6..afbaa6f 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -241,7 +241,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
+ int ret;
+
+- ret = tilcdc_crtc_mode_valid(crtc, mode, 0);
++ ret = tilcdc_crtc_mode_valid(crtc, mode, 0, 0, NULL);
+ if (WARN_ON(ret))
+ return ret;
+
+@@ -430,11 +430,12 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc)
+ }
+
+ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+- int rb_check)
++ int rb_check, int audio, struct edid *edid)
+ {
+ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+ unsigned int bandwidth;
+ uint32_t hbp, hfp, hsw, vbp, vfp, vsw;
++ int has_audio, is_cea_mode;
+
+ int rb;
+
+@@ -450,10 +451,22 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ if (mode->vdisplay > 2048)
+ return MODE_VIRTUAL_Y;
+
++ /* set if there's audio capability */
++ has_audio = edid && drm_detect_monitor_audio(edid);
+
+- DBG("Processing mode %dx%d@%d with pixel clock %d",
+- mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), mode->clock);
++ /* set if it's a cea mode */
++ is_cea_mode = drm_match_cea_mode(mode) > 0;
+
++ DBG("mode %dx%d@%d pixel-clock %d audio %s cea %s",
++ mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
++ mode->clock,
++ has_audio ? "true" : "false",
++ is_cea_mode ? "true" : "false");
++
++ if (audio && has_audio && !is_cea_mode) {
++ DBG("Pruning mode : Does not support audio\n");
++ return MODE_BAD;
++ }
+
+ hbp = mode->htotal - mode->hsync_end;
+ hfp = mode->hsync_start - mode->hdisplay;
+@@ -462,56 +475,56 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ vfp = mode->vsync_start - mode->vdisplay;
+ vsw = mode->vsync_end - mode->vsync_start;
+
+- if(hbp & ~0x3ff) {
+- DBG("Pruning mode : Horizontal Back Porch out of range\n");
+- return MODE_BAD;
++ if (hbp & ~0x3ff) {
++ DBG("Pruning mode : Horizontal Back Porch out of range\n");
++ return MODE_BAD;
+ }
+
+- if(hfp & ~0x3ff) {
+- DBG("Pruning mode : Horizontal Front Porch out of range\n");
+- return MODE_BAD;
++ if (hfp & ~0x3ff) {
++ DBG("Pruning mode : Horizontal Front Porch out of range\n");
++ return MODE_BAD;
+ }
+
+- if(hsw & ~0x3ff) {
+- DBG("Pruning mode : Horizontal Sync Width out of range\n");
+- return MODE_BAD;
++ if (hsw & ~0x3ff) {
++ DBG("Pruning mode : Horizontal Sync Width out of range\n");
++ return MODE_BAD;
+ }
+
+- if(vbp & ~0xff) {
+- DBG("Pruning mode : Vertical Back Porch out of range\n");
+- return MODE_BAD;
++ if (vbp & ~0xff) {
++ DBG("Pruning mode : Vertical Back Porch out of range\n");
++ return MODE_BAD;
+ }
+
+- if(vfp & ~0xff) {
+- DBG("Pruning mode : Vertical Front Porch out of range\n");
+- return MODE_BAD;
++ if (vfp & ~0xff) {
++ DBG("Pruning mode : Vertical Front Porch out of range\n");
++ return MODE_BAD;
+ }
+
+- if(vsw & ~0x3f) {
+- DBG("Pruning mode : Vertical Sync Width out of range\n");
+- return MODE_BAD;
++ if (vsw & ~0x3f) {
++ DBG("Pruning mode : Vertical Sync Width out of range\n");
++ return MODE_BAD;
+ }
+
+ /* some devices have a maximum allowed pixel clock */
+ /* configured from the DT */
+- if(mode->clock > priv->max_pixelclock) {
+- DBG("Pruning mode, pixel clock too high");
+- return MODE_BAD;
++ if (mode->clock > priv->max_pixelclock) {
++ DBG("Pruning mode, pixel clock too high");
++ return MODE_BAD;
+ }
+
+ /* some devices further limit the max horizontal resolution */
+ /* configured from the DT */
+- if(mode->hdisplay > priv->max_width) {
+- DBG("Pruning mode, above max width of %d supported by device", priv->max_width);
+- return MODE_BAD;
++ if (mode->hdisplay > priv->max_width) {
++ DBG("Pruning mode, above max width of %d supported by device", priv->max_width);
++ return MODE_BAD;
+ }
+
+ /* filter out modes that would require too much memory bandwidth: */
+ /* configured from the DT */
+ bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode);
+ if (bandwidth > priv->max_bandwidth) {
+- DBG("Pruning mode, exceeds defined bandwidth limit");
+- return MODE_BAD;
++ DBG("Pruning mode, exceeds defined bandwidth limit");
++ return MODE_BAD;
+ }
+
+ if (rb_check) {
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index fca4f16..31e039e 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -250,12 +250,17 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+
+ DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
+
+-
+ priv->allow_non_rblank = of_property_read_bool(node,
+ "ti,allow-non-reduced-blanking-modes");
+
++ DBG("Allowing Standard Monitor Modes: %s",
++ priv->allow_non_rblank ? "true" : "false");
++
++ priv->allow_non_audio = of_property_read_bool(node,
++ "ti,allow-non-audio-modes");
+
+- DBG("Allowing Standard Monitor Modes: %s", priv->allow_non_rblank?"true":"false");
++ DBG("Allowing Non Audio Monitor Modes: %s",
++ priv->allow_non_audio ? "true" : "false");
+
+ pm_runtime_enable(dev->dev);
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index 48d744c..db3c468 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -58,6 +58,7 @@ struct tilcdc_drm_private {
+ uint32_t max_width;
+
+ int allow_non_rblank; /* ATM we don't support non reduced blank modes */
++ int allow_non_audio; /* allow modes that don't have working audio */
+
+ /* register contents saved across suspend/resume: */
+ u32 saved_register[12];
+@@ -160,7 +161,7 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
+ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
+ const struct tilcdc_panel_info *info);
+ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+- int rb_check);
++ int rb_check, int audio, struct edid *edid);
+ int tilcdc_crtc_max_width(struct drm_crtc *crtc);
+
+ #endif /* __TILCDC_DRV_H__ */
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+index 361c569..90bc0e3 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+@@ -199,7 +199,7 @@ static int panel_connector_mode_valid(struct drm_connector *connector,
+ {
+ struct tilcdc_drm_private *priv = connector->dev->dev_private;
+ /* our only constraints are what the crtc can generate: */
+- return tilcdc_crtc_mode_valid(priv->crtc, mode, 0);
++ return tilcdc_crtc_mode_valid(priv->crtc, mode, 0, 0, NULL);
+ }
+
+ static struct drm_encoder *panel_connector_best_encoder(
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+index 17252ef..e454874 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+@@ -170,7 +170,11 @@ static int slave_connector_mode_valid(struct drm_connector *connector,
+ int ret;
+
+ ret = tilcdc_crtc_mode_valid(priv->crtc, mode,
+- priv->allow_non_rblank ? 0 : 1);
++ priv->allow_non_rblank ? 0 : 1,
++ priv->allow_non_audio ? 0 : 1,
++ connector->edid_blob_ptr ?
++ (struct edid *)connector->edid_blob_ptr->data :
++ NULL);
+ if (ret != MODE_OK)
+ return ret;
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+index 9d9796f..c71f955 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+@@ -216,7 +216,7 @@ static int tfp410_connector_mode_valid(struct drm_connector *connector,
+ struct tilcdc_drm_private *priv = connector->dev->dev_private;
+ /* our only constraints are what the crtc can generate: */
+ return tilcdc_crtc_mode_valid(priv->crtc, mode,
+- priv->allow_non_rblank ? 0 : 1);
++ priv->allow_non_rblank ? 0 : 1, 0, NULL);
+ }
+
+ static struct drm_encoder *tfp410_connector_best_encoder(
diff --git a/patches/linux-3.8.13/0578-Enable-output-of-correct-AVI-Infoframe-type-hdmi.patch b/patches/linux-3.8.13/0578-Enable-output-of-correct-AVI-Infoframe-type-hdmi.patch
new file mode 100644
index 0000000..af9c935
--- /dev/null
+++ b/patches/linux-3.8.13/0578-Enable-output-of-correct-AVI-Infoframe-type-hdmi.patch
@@ -0,0 +1,24 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Tue, 7 May 2013 21:22:27 -0500
+Subject: [PATCH] Enable output of correct AVI Infoframe type hdmi
+
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index e3e9101..7c64696 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -593,9 +593,9 @@ tda998x_avi_infoframe_enable(struct drm_encoder *encoder,
+ * so that the hardware acknowledges that the packet data might have
+ * changed
+ */
+- reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF3);
++ reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
+ udelay(5);
+- reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF3);
++ reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
+ }
+
+ /* loopup table for CEA values to VIDFORMAT values taken from NXP datasheet */
diff --git a/patches/linux-3.8.13/0579-drm-am335x-add-support-for-2048-lines-vertical.patch b/patches/linux-3.8.13/0579-drm-am335x-add-support-for-2048-lines-vertical.patch
new file mode 100644
index 0000000..d5003a0
--- /dev/null
+++ b/patches/linux-3.8.13/0579-drm-am335x-add-support-for-2048-lines-vertical.patch
@@ -0,0 +1,86 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Wed, 8 May 2013 16:15:40 -0500
+Subject: [PATCH] drm: am335x: add support for 2048 lines vertical
+
+Add extra mode that enables 1920x1080@24, this now works
+with 2048 lines vertical support and EMIF setting of
+INT_CONFIG optimized.
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 15 ++++++++++++---
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 10 +++++++---
+ drivers/gpu/drm/tilcdc/tilcdc_regs.h | 1 +
+ 3 files changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index afbaa6f..1dbd927 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -308,6 +308,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ (((hsw-1) & 0x3f) << 10);
+ if (priv->rev == 2)
+ reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
++
+ tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
+
+ /* only the vertical sync width maps 0 as 1 so only subtract 1 from vsw */
+@@ -317,6 +318,14 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ (((vsw-1) & 0x3f) << 10);
+ tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
+
++ if (priv->rev == 2) {
++ if((mode->vdisplay - 1) & 0x400) {
++ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
++ } else {
++ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
++ }
++ }
++
+ /* Configure display type: */
+ reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
+ ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
+@@ -530,9 +539,9 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ if (rb_check) {
+ /* we only support reduced blanking modes */
+ rb = (mode->htotal - mode->hdisplay == 160) &&
+- (mode->hsync_end - mode->hdisplay == 80) &&
+- (mode->hsync_end - mode->hsync_start == 32) &&
+- (mode->vsync_start - mode->vdisplay == 3);
++ (mode->hsync_end - mode->hdisplay == 80) &&
++ (mode->hsync_end - mode->hsync_start == 32) &&
++ (mode->vsync_start - mode->vdisplay == 3);
+ if (!rb) {
+ DBG("Pruning mode, only support reduced blanking modes");
+ return MODE_BAD;
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index db3c468..6b2c7ea 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -37,9 +37,13 @@
+ /* Defaulting to pixel clock defined on AM335x */
+ #define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000
+ /* Defaulting to max width as defined on AM335x */
+-#define TILCDC_DEFAULT_MAX_WIDTH 1366
+-/* This may need some tweaking, but want to allow at least 1280x1024@60 */
+-#define TILCDC_DEFAULT_MAX_BANDWIDTH (1366*1024*60)
++#define TILCDC_DEFAULT_MAX_WIDTH 2048
++/*
++ * This may need some tweaking, but want to allow at least 1280x1024@60
++ * with optimized DDR & EMIF settings tweaked 1920x1080@24 appears to
++ * be supportable
++ */
++#define TILCDC_DEFAULT_MAX_BANDWIDTH (1920*1080*25)
+
+ struct tilcdc_drm_private {
+ void __iomem *mmio;
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
+index 17fd1b4..1bf5e25 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
+@@ -80,6 +80,7 @@
+ #define LCDC_INVERT_PIXEL_CLOCK BIT(22)
+ #define LCDC_INVERT_HSYNC BIT(21)
+ #define LCDC_INVERT_VSYNC BIT(20)
++#define LCDC_LPP_B10 BIT(26)
+
+ /* LCDC Block */
+ #define LCDC_PID_REG 0x0
diff --git a/patches/linux-3.8.13/0580-drm-tda998x-Adding-extra-CEA-mode-for-1920x1080-24.patch b/patches/linux-3.8.13/0580-drm-tda998x-Adding-extra-CEA-mode-for-1920x1080-24.patch
new file mode 100644
index 0000000..492c2f1
--- /dev/null
+++ b/patches/linux-3.8.13/0580-drm-tda998x-Adding-extra-CEA-mode-for-1920x1080-24.patch
@@ -0,0 +1,31 @@
+From: Darren Etheridge <detheridge@ti.com>
+Date: Wed, 8 May 2013 16:39:28 -0500
+Subject: [PATCH] drm: tda998x Adding extra CEA mode for 1920x1080@24
+
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index 7c64696..412ba4f 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -598,14 +598,14 @@ tda998x_avi_infoframe_enable(struct drm_encoder *encoder,
+ reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
+ }
+
+-/* loopup table for CEA values to VIDFORMAT values taken from NXP datasheet */
+-static char cea_to_nxp_mode[32] = {-1, 0, 1, 1, 2, 3, 4, 4, 5, 5, -1, -1,
++/* lookup table for CEA values to VIDFORMAT values taken from NXP datasheet */
++static char cea_to_nxp_mode[34] = {-1, 0, 1, 1, 2, 3, 4, 4, 5, 5, -1, -1,
+ -1, -1, -1, -1, 6, 7, 7, 8, 9, 10, 10,
+- 11, 11, -1, -1, -1, -1, -1, -1, 12};
++ 11, 11, -1, -1, -1, -1, -1, -1, 12, 13};
+
+ static char tda998x_cea_to_vidformat(unsigned char cea_mode)
+ {
+- if(cea_mode > 31) {
++ if(cea_mode > (sizeof(cea_to_nxp_mode) -1) ) {
+ return -1;
+ }
+ return cea_to_nxp_mode[cea_mode];
diff --git a/patches/linux-3.8.13/0581-tilcdc-Remove-superfluous-newlines-from-DBG-messages.patch b/patches/linux-3.8.13/0581-tilcdc-Remove-superfluous-newlines-from-DBG-messages.patch
new file mode 100644
index 0000000..e889122
--- /dev/null
+++ b/patches/linux-3.8.13/0581-tilcdc-Remove-superfluous-newlines-from-DBG-messages.patch
@@ -0,0 +1,63 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 20 May 2013 13:54:21 +0300
+Subject: [PATCH] tilcdc: Remove superfluous newlines from DBG messages
+
+DBGs supply their own newlines, don't add them.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 1dbd927..c39503b 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -473,7 +473,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ is_cea_mode ? "true" : "false");
+
+ if (audio && has_audio && !is_cea_mode) {
+- DBG("Pruning mode : Does not support audio\n");
++ DBG("Pruning mode : Does not support audio");
+ return MODE_BAD;
+ }
+
+@@ -485,32 +485,32 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ vsw = mode->vsync_end - mode->vsync_start;
+
+ if (hbp & ~0x3ff) {
+- DBG("Pruning mode : Horizontal Back Porch out of range\n");
++ DBG("Pruning mode : Horizontal Back Porch out of range");
+ return MODE_BAD;
+ }
+
+ if (hfp & ~0x3ff) {
+- DBG("Pruning mode : Horizontal Front Porch out of range\n");
++ DBG("Pruning mode : Horizontal Front Porch out of range");
+ return MODE_BAD;
+ }
+
+ if (hsw & ~0x3ff) {
+- DBG("Pruning mode : Horizontal Sync Width out of range\n");
++ DBG("Pruning mode : Horizontal Sync Width out of range");
+ return MODE_BAD;
+ }
+
+ if (vbp & ~0xff) {
+- DBG("Pruning mode : Vertical Back Porch out of range\n");
++ DBG("Pruning mode : Vertical Back Porch out of range");
+ return MODE_BAD;
+ }
+
+ if (vfp & ~0xff) {
+- DBG("Pruning mode : Vertical Front Porch out of range\n");
++ DBG("Pruning mode : Vertical Front Porch out of range");
+ return MODE_BAD;
+ }
+
+ if (vsw & ~0x3f) {
+- DBG("Pruning mode : Vertical Sync Width out of range\n");
++ DBG("Pruning mode : Vertical Sync Width out of range");
+ return MODE_BAD;
+ }
+
diff --git a/patches/linux-3.8.13/0582-tilcdc-1280x1024x60-bw-1920x1080x24-bw.patch b/patches/linux-3.8.13/0582-tilcdc-1280x1024x60-bw-1920x1080x24-bw.patch
new file mode 100644
index 0000000..f236e24
--- /dev/null
+++ b/patches/linux-3.8.13/0582-tilcdc-1280x1024x60-bw-1920x1080x24-bw.patch
@@ -0,0 +1,43 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 20 May 2013 15:16:55 +0300
+Subject: [PATCH] tilcdc: 1280x1024x60 bw > 1920x1080x24 bw
+
+The lower resolution modes do infact need more bandwidth.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 +-
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 5 +++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index c39503b..7ba2048 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -472,7 +472,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ has_audio ? "true" : "false",
+ is_cea_mode ? "true" : "false");
+
+- if (audio && has_audio && !is_cea_mode) {
++ if (edid && audio && has_audio && !is_cea_mode) {
+ DBG("Pruning mode : Does not support audio");
+ return MODE_BAD;
+ }
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index 6b2c7ea..f3861e4 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -40,10 +40,11 @@
+ #define TILCDC_DEFAULT_MAX_WIDTH 2048
+ /*
+ * This may need some tweaking, but want to allow at least 1280x1024@60
+- * with optimized DDR & EMIF settings tweaked 1920x1080@24 appears to
++ * with optimized DDR & EMIF settings tweaked 1920x1080@25 appears to
+ * be supportable
++ * Note: 1920x1080x25=49766400 < 1280x1024x60=78643200
+ */
+-#define TILCDC_DEFAULT_MAX_BANDWIDTH (1920*1080*25)
++#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60)
+
+ struct tilcdc_drm_private {
+ void __iomem *mmio;
diff --git a/patches/linux-3.8.13/0583-tilcdc-Only-support-Audio-on-50-60-Hz-modes.patch b/patches/linux-3.8.13/0583-tilcdc-Only-support-Audio-on-50-60-Hz-modes.patch
new file mode 100644
index 0000000..d2c42a9
--- /dev/null
+++ b/patches/linux-3.8.13/0583-tilcdc-Only-support-Audio-on-50-60-Hz-modes.patch
@@ -0,0 +1,62 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 20 May 2013 16:01:07 +0300
+Subject: [PATCH] tilcdc: Only support Audio on 50 & 60 Hz modes
+
+Apparently anything other fails to work (at least for me).
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 7ba2048..14cee74 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -310,7 +310,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
+
+ tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
+-
++
+ /* only the vertical sync width maps 0 as 1 so only subtract 1 from vsw */
+ reg = ((mode->vdisplay - 1) & 0x3ff) |
+ ((vbp & 0xff) << 24) |
+@@ -444,7 +444,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+ unsigned int bandwidth;
+ uint32_t hbp, hfp, hsw, vbp, vfp, vsw;
+- int has_audio, is_cea_mode;
++ int has_audio, is_cea_mode, can_output_audio, refresh;
+
+ int rb;
+
+@@ -463,16 +463,24 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ /* set if there's audio capability */
+ has_audio = edid && drm_detect_monitor_audio(edid);
+
++ /* only 50 & 60Hz modes reliably support audio */
++ refresh = drm_mode_vrefresh(mode);
++
+ /* set if it's a cea mode */
+ is_cea_mode = drm_match_cea_mode(mode) > 0;
+
+- DBG("mode %dx%d@%d pixel-clock %d audio %s cea %s",
+- mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
++ /* set if we can output audio */
++ can_output_audio = edid && has_audio && is_cea_mode &&
++ (refresh == 50 || refresh == 60);
++
++ DBG("mode %dx%d@%d pixel-clock %d audio %s cea %s can_output %s",
++ mode->hdisplay, mode->vdisplay,refresh,
+ mode->clock,
+ has_audio ? "true" : "false",
+- is_cea_mode ? "true" : "false");
++ is_cea_mode ? "true" : "false",
++ can_output_audio ? "true" : "false" );
+
+- if (edid && audio && has_audio && !is_cea_mode) {
++ if (edid && has_audio && !can_output_audio) {
+ DBG("Pruning mode : Does not support audio");
+ return MODE_BAD;
+ }
diff --git a/patches/linux-3.8.13/0584-drm-i2c-nxp-tda998x-fix-EDID-reading-on-TDA19988-dev.patch b/patches/linux-3.8.13/0584-drm-i2c-nxp-tda998x-fix-EDID-reading-on-TDA19988-dev.patch
new file mode 100644
index 0000000..1976f1e
--- /dev/null
+++ b/patches/linux-3.8.13/0584-drm-i2c-nxp-tda998x-fix-EDID-reading-on-TDA19988-dev.patch
@@ -0,0 +1,68 @@
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Thu, 16 May 2013 19:25:58 +0000
+Subject: [PATCH] drm/i2c: nxp-tda998x: fix EDID reading on TDA19988 devices
+
+TDA19988 devices need their RAM enabled in order to read EDID
+information. Add support for this.
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index 412ba4f..9ac4ed9 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -253,6 +253,8 @@ struct tda998x_priv {
+
+ /* Page 12h: HDCP and OTP */
+ #define REG_TX3 REG(0x12, 0x9a) /* read/write */
++#define REG_TX4 REG(0x12, 0x9b) /* read/write */
++# define TX4_PD_RAM (1 << 1)
+ #define REG_TX33 REG(0x12, 0xb8) /* read/write */
+ # define TX33_HDMI (1 << 1)
+
+@@ -865,6 +867,7 @@ read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
+ static uint8_t *
+ do_get_edid(struct drm_encoder *encoder)
+ {
++ struct tda998x_priv *priv = to_tda998x_priv(encoder);
+ int j = 0, valid_extensions = 0;
+ uint8_t *block, *new;
+ bool print_bad_edid = drm_debug & DRM_UT_KMS;
+@@ -872,6 +875,9 @@ do_get_edid(struct drm_encoder *encoder)
+ if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
+ return NULL;
+
++ if (priv->rev == TDA19988)
++ reg_clear(encoder, REG_TX4, TX4_PD_RAM);
++
+ /* base block fetch */
+ if (read_edid_block(encoder, block, 0))
+ goto fail;
+@@ -881,7 +887,7 @@ do_get_edid(struct drm_encoder *encoder)
+
+ /* if there's no extensions, we're done */
+ if (block[0x7e] == 0)
+- return block;
++ goto done;
+
+ new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
+ if (!new)
+@@ -908,9 +914,15 @@ do_get_edid(struct drm_encoder *encoder)
+ block = new;
+ }
+
++done:
++ if (priv->rev == TDA19988)
++ reg_set(encoder, REG_TX4, TX4_PD_RAM);
++
+ return block;
+
+ fail:
++ if (priv->rev == TDA19988)
++ reg_set(encoder, REG_TX4, TX4_PD_RAM);
+ dev_warn(encoder->dev->dev, "failed to read EDID\n");
+ kfree(block);
+ return NULL;
diff --git a/patches/linux-3.8.13/0585-tilcdc-Allow-non-audio-modes-when-we-don-t-support-t.patch b/patches/linux-3.8.13/0585-tilcdc-Allow-non-audio-modes-when-we-don-t-support-t.patch
new file mode 100644
index 0000000..6c902a6
--- /dev/null
+++ b/patches/linux-3.8.13/0585-tilcdc-Allow-non-audio-modes-when-we-don-t-support-t.patch
@@ -0,0 +1,26 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 4 Jun 2013 17:53:07 +0300
+Subject: [PATCH] tilcdc: Allow non-audio modes when we don't support them.
+
+Allow non-audio modes on an audio capable monitor if we explicitly
+disable audio.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 14cee74..5f5f464 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -480,7 +480,8 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ is_cea_mode ? "true" : "false",
+ can_output_audio ? "true" : "false" );
+
+- if (edid && has_audio && !can_output_audio) {
++ /* we only prune the mode if we ask for it */
++ if (audio && edid && has_audio && !can_output_audio) {
+ DBG("Pruning mode : Does not support audio");
+ return MODE_BAD;
+ }
diff --git a/patches/linux-3.8.13/0586-drm-i2c-nxp-tda998x-ensure-VIP-output-mux-is-properl.patch b/patches/linux-3.8.13/0586-drm-i2c-nxp-tda998x-ensure-VIP-output-mux-is-properl.patch
new file mode 100644
index 0000000..8c79a03
--- /dev/null
+++ b/patches/linux-3.8.13/0586-drm-i2c-nxp-tda998x-ensure-VIP-output-mux-is-properl.patch
@@ -0,0 +1,39 @@
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Thu, 16 May 2013 19:26:18 +0000
+Subject: [PATCH] drm/i2c: nxp-tda998x: ensure VIP output mux is properly set
+
+When switching between various drivers for this device, it's possible
+that some critical registers are left containing values which affect
+the device operation. One such case encountered is the VIP output
+mux register. This defaults to 0x24 on powerup, but other drivers may
+set this to 0x12. This results in incorrect colours.
+
+Fix this by ensuring that the register is always set to the power on
+default setting.
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index 9ac4ed9..37094fd 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -110,6 +110,7 @@ struct tda998x_priv {
+ #define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
+ # define VIP_CNTRL_5_CKCASE (1 << 0)
+ # define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
++#define REG_MUX_VP_VIP_OUT REG(0x00, 0x27) /* read/write */
+
+ #define REG_MUX_AP REG(0x00, 0x26)
+ # define MUX_AP_SELECT_I2S (0x64)
+@@ -494,6 +495,8 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+
+ switch (mode) {
+ case DRM_MODE_DPMS_ON:
++ /* Write the default value MUX register */
++ reg_write(encoder, REG_MUX_VP_VIP_OUT, 0x24);
+ /* enable audio and video ports */
+ reg_write(encoder, REG_ENA_AP, 0x03);
+ reg_write(encoder, REG_ENA_VP_0, 0xff);
diff --git a/patches/linux-3.8.13/0587-drm-i2c-nxp-tda998x-fix-npix-nline-programming.patch b/patches/linux-3.8.13/0587-drm-i2c-nxp-tda998x-fix-npix-nline-programming.patch
new file mode 100644
index 0000000..a547cd5
--- /dev/null
+++ b/patches/linux-3.8.13/0587-drm-i2c-nxp-tda998x-fix-npix-nline-programming.patch
@@ -0,0 +1,28 @@
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Thu, 16 May 2013 19:26:38 +0000
+Subject: [PATCH] drm/i2c: nxp-tda998x: fix npix/nline programming
+
+The npix/nline registers are supposed to be programmed with the total
+number of pixels/lines, not the displayed pixels/lines, and not minus
+one either.
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index 37094fd..17db51b 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -723,8 +723,8 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
+
+ reg_write(encoder, REG_VIDFORMAT, 0x00);
+- reg_write16(encoder, REG_NPIX_MSB, mode->hdisplay - 1);
+- reg_write16(encoder, REG_NLINE_MSB, mode->vdisplay - 1);
++ reg_write16(encoder, REG_NPIX_MSB, mode->htotal);
++ reg_write16(encoder, REG_NLINE_MSB, mode->vtotal);
+ reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, line_start);
+ reg_write16(encoder, REG_VS_LINE_END_1_MSB, line_end);
+ reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, hs_start);
diff --git a/patches/linux-3.8.13/0588-drm-tilcdc-Clear-bits-of-register-we-re-going-to-set.patch b/patches/linux-3.8.13/0588-drm-tilcdc-Clear-bits-of-register-we-re-going-to-set.patch
new file mode 100644
index 0000000..66d60ae
--- /dev/null
+++ b/patches/linux-3.8.13/0588-drm-tilcdc-Clear-bits-of-register-we-re-going-to-set.patch
@@ -0,0 +1,63 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 5 Jun 2013 19:48:59 +0300
+Subject: [PATCH] drm: tilcdc: Clear bits of register we're going to set.
+
+Bits weren't cleared so resolution changes didn't work.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 5f5f464..8ce18ca 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -286,15 +286,18 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);
+
+ /* Configure the AC Bias Period and Number of Transitions per Interrupt: */
+- reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
++ reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG);
++ reg &= ~0x000fff00;
+ reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
+ LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
+
+ /* subtract one from hfp, hbp, hsw because the hardware uses a value of 0 as 1 */
+ if (priv->rev == 2) {
+- reg |= ((hfp-1) & 0x300) >> 8;
+- reg |= ((hbp-1) & 0x300) >> 4;
+- reg |= ((hsw-1) & 0x3c0) << 21;
++ /* clear bits we're going to set */
++ reg &= ~0x78000033;
++ reg |= ((hfp-1) & 0x300) >> 8;
++ reg |= ((hbp-1) & 0x300) >> 4;
++ reg |= ((hsw-1) & 0x3c0) << 21;
+ }
+ tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
+
+@@ -307,7 +310,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ (((hfp-1) & 0xff) << 16) |
+ (((hsw-1) & 0x3f) << 10);
+ if (priv->rev == 2)
+- reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
++ reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
+
+ tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
+
+@@ -319,11 +322,10 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
+ tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
+
+ if (priv->rev == 2) {
+- if((mode->vdisplay - 1) & 0x400) {
+- tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
+- } else {
+- tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
+- }
++ if ((mode->vdisplay - 1) & 0x400)
++ tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
++ else
++ tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
+ }
+
+ /* Configure display type: */
diff --git a/patches/linux-3.8.13/0589-DRM-tda998x-add-missing-include.patch b/patches/linux-3.8.13/0589-DRM-tda998x-add-missing-include.patch
new file mode 100644
index 0000000..0de2566
--- /dev/null
+++ b/patches/linux-3.8.13/0589-DRM-tda998x-add-missing-include.patch
@@ -0,0 +1,42 @@
+From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+Date: Sat, 18 May 2013 17:12:19 +0000
+Subject: [PATCH] DRM: tda998x: add missing include
+
+The RFC sent by Russell King was missing an include for tda998x. This
+is just a compatible clone to remember Russell to add that later.
+
+Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ include/drm/i2c/tda998x.h | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+ create mode 100644 include/drm/i2c/tda998x.h
+
+diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
+new file mode 100644
+index 0000000..41f799f
+--- /dev/null
++++ b/include/drm/i2c/tda998x.h
+@@ -0,0 +1,23 @@
++#ifndef __TDA998X_H__
++#define __TDA998X_H__
++
++enum tda998x_audio_format {
++ AFMT_I2S,
++ AFMT_SPDIF,
++};
++
++struct tda998x_encoder_params {
++ int audio_cfg;
++ int audio_clk_cfg;
++ enum tda998x_audio_format audio_format;
++ int audio_sample_rate;
++ char audio_frame[6];
++ int swap_a, mirr_a;
++ int swap_b, mirr_b;
++ int swap_c, mirr_c;
++ int swap_d, mirr_d;
++ int swap_e, mirr_e;
++ int swap_f, mirr_f;
++};
++
++#endif
diff --git a/patches/linux-3.8.13/0590-drm-i2c-nxp-tda998x-prepare-for-video-input-configur.patch b/patches/linux-3.8.13/0590-drm-i2c-nxp-tda998x-prepare-for-video-input-configur.patch
new file mode 100644
index 0000000..f3a45fa
--- /dev/null
+++ b/patches/linux-3.8.13/0590-drm-i2c-nxp-tda998x-prepare-for-video-input-configur.patch
@@ -0,0 +1,50 @@
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Thu, 16 May 2013 19:26:58 +0000
+Subject: [PATCH] drm/i2c: nxp-tda998x: prepare for video input configuration
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index 17db51b..49e5d98 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -32,6 +32,9 @@ struct tda998x_priv {
+ uint16_t rev;
+ uint8_t current_page;
+ int dpms;
++ u8 vip_cntrl_0;
++ u8 vip_cntrl_1;
++ u8 vip_cntrl_2;
+ };
+
+ #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
+@@ -503,12 +506,9 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+ reg_write(encoder, REG_ENA_VP_1, 0xff);
+ reg_write(encoder, REG_ENA_VP_2, 0xff);
+ /* set muxing after enabling ports: */
+- reg_write(encoder, REG_VIP_CNTRL_0,
+- VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3));
+- reg_write(encoder, REG_VIP_CNTRL_1,
+- VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1));
+- reg_write(encoder, REG_VIP_CNTRL_2,
+- VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5));
++ reg_write(encoder, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
++ reg_write(encoder, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
++ reg_write(encoder, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
+ break;
+ case DRM_MODE_DPMS_OFF:
+ /* disable audio and video ports */
+@@ -1014,6 +1014,10 @@ tda998x_encoder_init(struct i2c_client *client,
+ if (!priv)
+ return -ENOMEM;
+
++ priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
++ priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
++ priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
++
+ priv->current_page = 0;
+ priv->cec = i2c_new_dummy(client->adapter, 0x34);
+ priv->dpms = DRM_MODE_DPMS_OFF;
diff --git a/patches/linux-3.8.13/0591-WIP-of-new-tda998x-patches.patch b/patches/linux-3.8.13/0591-WIP-of-new-tda998x-patches.patch
new file mode 100644
index 0000000..990f0b0
--- /dev/null
+++ b/patches/linux-3.8.13/0591-WIP-of-new-tda998x-patches.patch
@@ -0,0 +1,808 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 5 Jun 2013 19:52:25 +0300
+Subject: [PATCH] WIP of new tda998x patches.
+
+Video works, but no audio. RMK uses SPDIF so I2S is missing various bits.
+With the tilcdc driver the some non CEC modes are shifted too.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 574 ++++++++++++++++++++++++++-----------
+ include/drm/i2c/tda998x.h | 21 +-
+ 2 files changed, 419 insertions(+), 176 deletions(-)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index 49e5d98..2049898 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -25,6 +25,8 @@
+ #include <drm/drm_edid.h>
+ #include <linux/hdmi.h>
+
++#include <drm/i2c/tda998x.h>
++
+ #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+ struct tda998x_priv {
+@@ -32,9 +34,11 @@ struct tda998x_priv {
+ uint16_t rev;
+ uint8_t current_page;
+ int dpms;
++ bool is_hdmi_sink;
+ u8 vip_cntrl_0;
+ u8 vip_cntrl_1;
+ u8 vip_cntrl_2;
++ struct tda998x_encoder_params params;
+ };
+
+ #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
+@@ -71,10 +75,13 @@ struct tda998x_priv {
+ # define I2C_MASTER_DIS_MM (1 << 0)
+ # define I2C_MASTER_DIS_FILT (1 << 1)
+ # define I2C_MASTER_APP_STRT_LAT (1 << 2)
++#define REG_FEAT_POWERDOWN REG(0x00, 0x0e) /* read/write */
++# define FEAT_POWERDOWN_SPDIF (1 << 3)
+ #define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */
+ #define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */
+ #define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */
+ # define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
++#define REG_ENA_ACLK REG(0x00, 0x16) /* read/write */
+ #define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */
+ #define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */
+ #define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */
+@@ -113,10 +120,8 @@ struct tda998x_priv {
+ #define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
+ # define VIP_CNTRL_5_CKCASE (1 << 0)
+ # define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
++#define REG_MUX_AP REG(0x00, 0x26) /* read/write */
+ #define REG_MUX_VP_VIP_OUT REG(0x00, 0x27) /* read/write */
+-
+-#define REG_MUX_AP REG(0x00, 0x26)
+-# define MUX_AP_SELECT_I2S (0x64)
+ #define REG_MAT_CONTRL REG(0x00, 0x80) /* write */
+ # define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0)
+ # define MAT_CONTRL_MAT_BP (1 << 2)
+@@ -178,10 +183,13 @@ struct tda998x_priv {
+ # define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4)
+ # define HVF_CNTRL_1_SEMI_PLANAR (1 << 6)
+ #define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */
+-#define REG_I2S_FORMAT REG(0x00, 0xfc)
++#define REG_I2S_FORMAT REG(0x00, 0xfc) /* read/write */
++# define I2S_FORMAT(x) (((x) & 3) << 0)
++#define REG_AIP_CLKSEL REG(0x00, 0xfd) /* write */
++# define AIP_CLKSEL_FS(x) (((x) & 3) << 0)
++# define AIP_CLKSEL_CLK_POL(x) (((x) & 1) << 2)
++# define AIP_CLKSEL_AIP(x) (((x) & 7) << 3)
+
+-#define REG_AIP_CLKSEL REG(0x00, 0xfd)
+-# define SEL_AIP_I2S (1 << 3) /* I2S Clk */
+
+ /* Page 02h: PLL settings */
+ #define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */
+@@ -222,8 +230,12 @@ struct tda998x_priv {
+
+
+ /* Page 10h: information frames and packets */
+-#define REG_AVI_IF REG(0x10, 0x40) /* AVI Infoframe packet */
+-#define REG_AUDIO_IF REG(0x10, 0x80) /* AVI Infoframe packet */
++#define REG_IF1_HB0 REG(0x10, 0x20) /* read/write */
++#define REG_IF2_HB0 REG(0x10, 0x40) /* read/write */
++#define REG_IF3_HB0 REG(0x10, 0x60) /* read/write */
++#define REG_IF4_HB0 REG(0x10, 0x80) /* read/write */
++#define REG_IF5_HB0 REG(0x10, 0xa0) /* read/write */
++
+
+ /* Page 11h: audio settings and content info packets */
+ #define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */
+@@ -232,28 +244,34 @@ struct tda998x_priv {
+ # define AIP_CNTRL_0_LAYOUT (1 << 2)
+ # define AIP_CNTRL_0_ACR_MAN (1 << 5)
+ # define AIP_CNTRL_0_RST_CTS (1 << 6)
+-#define REG_ACR_CTS_0 REG(0x11, 0x05)
+-#define REG_ACR_CTS_1 REG(0x11, 0x06)
+-#define REG_ACR_CTS_2 REG(0x11, 0x07)
+-#define REG_ACR_N_0 REG(0x11, 0x08)
+-#define REG_ACR_N_1 REG(0x11, 0x09)
+-#define REG_ACR_N_2 REG(0x11, 0x0a)
+-#define REG_GC_AVMUTE REG(0x11, 0x0b)
+-# define GC_AVMUTE_CLRMUTE (1 << 0)
+-# define GC_AVMUTE_SETMUTE (1 << 1)
+-#define REG_CTS_N REG(0x11, 0x0c)
++#define REG_CA_I2S REG(0x11, 0x01) /* read/write */
++# define CA_I2S_CA_I2S(x) (((x) & 31) << 0)
++# define CA_I2S_HBR_CHSTAT (1 << 6)
++#define REG_LATENCY_RD REG(0x11, 0x04) /* read/write */
++#define REG_ACR_CTS_0 REG(0x11, 0x05) /* read/write */
++#define REG_ACR_CTS_1 REG(0x11, 0x06) /* read/write */
++#define REG_ACR_CTS_2 REG(0x11, 0x07) /* read/write */
++#define REG_ACR_N_0 REG(0x11, 0x08) /* read/write */
++#define REG_ACR_N_1 REG(0x11, 0x09) /* read/write */
++#define REG_ACR_N_2 REG(0x11, 0x0a) /* read/write */
++#define REG_CTS_N REG(0x11, 0x0c) /* read/write */
++# define CTS_N_K(x) (((x) & 7) << 0)
++# define CTS_N_M(x) (((x) & 3) << 4)
+ #define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */
+ # define ENC_CNTRL_RST_ENC (1 << 0)
+ # define ENC_CNTRL_RST_SEL (1 << 1)
+ # define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2)
+-#define REG_DIP_FLAGS REG(0x11, 0x0e)
++#define REG_DIP_FLAGS REG(0x11, 0x0e) /* read/write */
+ # define DIP_FLAGS_ACR (1 << 0)
++# define DIP_FLAGS_GC (1 << 1)
+ #define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */
+-#define DIP_IF_FLAGS_IF1 (1 << 1)
+-#define DIP_IF_FLAGS_IF2 (1 << 2)
+-#define DIP_IF_FLAGS_IF3 (1 << 3)
+-#define DIP_IF_FLAGS_IF4 (1 << 4)
+-#define DIP_IF_FLAGS_IF5 (1 << 5)
++# define DIP_IF_FLAGS_IF1 (1 << 1)
++# define DIP_IF_FLAGS_IF2 (1 << 2)
++# define DIP_IF_FLAGS_IF3 (1 << 3)
++# define DIP_IF_FLAGS_IF4 (1 << 4)
++# define DIP_IF_FLAGS_IF5 (1 << 5)
++#define REG_CH_STAT_B(x) REG(0x11, 0x14 + (x)) /* read/write */
++
+
+ /* Page 12h: HDCP and OTP */
+ #define REG_TX3 REG(0x12, 0x9a) /* read/write */
+@@ -292,9 +310,6 @@ struct tda998x_priv {
+ #define TDA19989N2 0x0202
+ #define TDA19988 0x0301
+
+-static uint8_t *
+-do_get_edid(struct drm_encoder *encoder);
+-
+ static void
+ cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
+ {
+@@ -477,11 +492,257 @@ tda998x_reset(struct drm_encoder *encoder)
+ reg_write(encoder, REG_PLL_SCG2, 0x10);
+ }
+
++static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes)
++{
++ uint8_t sum = 0;
++
++ while (bytes--)
++ sum += *buf++;
++ return (255 - sum) + 1;
++}
++
++#define HB(x) (x)
++#define PB(x) (HB(2) + 1 + (x))
++
++static void
++tda998x_write_if(struct drm_encoder *encoder, uint8_t bit, uint16_t addr,
++ uint8_t *buf, size_t size)
++{
++ buf[PB(0)] = tda998x_cksum(buf, size);
++
++ reg_clear(encoder, REG_DIP_IF_FLAGS, bit);
++ reg_write_range(encoder, addr, buf, size);
++ reg_set(encoder, REG_DIP_IF_FLAGS, bit);
++}
++
++static void
++tda998x_write_aif(struct drm_encoder *encoder, struct tda998x_encoder_params *p)
++{
++ uint8_t buf[PB(5) + 1];
++
++ buf[HB(0)] = 0x84;
++ buf[HB(1)] = 0x01;
++ buf[HB(2)] = 10;
++ buf[PB(0)] = 0;
++ buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */
++ buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */
++ buf[PB(4)] = p->audio_frame[4];
++ buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */
++
++ tda998x_write_if(encoder, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf,
++ sizeof(buf));
++}
++
++static void
++tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode)
++{
++ uint8_t buf[PB(13) + 1];
++
++ memset(buf, 0, sizeof(buf));
++ buf[HB(0)] = 0x82;
++ buf[HB(1)] = 0x02;
++ buf[HB(2)] = 13;
++ buf[PB(4)] = drm_match_cea_mode(mode);
++
++ tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
++ sizeof(buf));
++}
++
++static void tda998x_audio_mute(struct drm_encoder *encoder, bool on)
++{
++ if (on) {
++ reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO);
++ reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO);
++ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
++ } else {
++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
++ }
++}
++
++static void
++tda998x_configure_audio(struct drm_encoder *encoder, struct tda998x_encoder_params *p)
++{
++ uint8_t buf[6], clksel_aip = 0, clksel_fs = 0, ca_i2s, cts_n;
++ uint32_t n;
++
++ /* SetAudioPortConfig */
++ reg_write(encoder, REG_ENA_AP, p->audio_cfg);
++ /* SetAudioClockPortConfig */
++ reg_write(encoder, REG_ENA_ACLK, p->audio_clk_cfg);
++
++ /*
++ * layout = channelAllocation ? 1 : 0;
++ * AudioInSetConfig(format, i2sFormat, channelAllocation,
++ * HDMITX_CHAN_NO_CHANGE, HDMITX_CLKPOLDSD_NO_CHANGE,
++ * HDMITX_SWAPDSD_NO_CHANGE, layout, HDMITX_LATENCY_CURRENT,
++ * dstRate)
++ */
++ switch (p->audio_format) {
++ case AFMT_SPDIF:
++ reg_write(encoder, REG_MUX_AP, 0x40);
++ clksel_aip = AIP_CLKSEL_AIP(0);
++ /* FS64SPDIF */
++ clksel_fs = AIP_CLKSEL_FS(2);
++ cts_n = CTS_N_M(3) | CTS_N_K(3);
++ ca_i2s = 0;
++ break;
++
++ case AFMT_I2S:
++ reg_write(encoder, REG_MUX_AP, 0x64);
++ clksel_aip = AIP_CLKSEL_AIP(1);
++ /* ACLK */
++ clksel_fs = AIP_CLKSEL_FS(0);
++ cts_n = CTS_N_M(3) | CTS_N_K(3);
++ ca_i2s = CA_I2S_CA_I2S(0 /* channel allocation */);
++ break;
++ }
++
++ reg_write(encoder, REG_AIP_CLKSEL, clksel_aip);
++ if (p->audio_format == AFMT_I2S) {
++ reg_write(encoder, REG_CA_I2S, ca_i2s);
++ reg_write(encoder, REG_I2S_FORMAT, p->i2s_fmt);
++ }
++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT);
++ /* latency? */
++
++ /* get video format */
++
++ /*
++ * ctsRef = HDMITX_CTSREF_FS64SPDIF, uCtsX = HDMITX_CTSX_64
++ * AudioInSetCts(ctsRef, rate, VidFmt, vOutFreq,
++ * HDMITX_CTS_AUTO, uCtsX, HDMITX_CTSK_USE_CTSX,
++ * HDMITX_CTSMTS_USE_CTSX, dstRate)
++ */
++ /* Auto CTS */
++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_ACR_MAN);
++ reg_write(encoder, REG_CTS_N, cts_n);
++ // reg_write(encoder, REG_AUDIO_DIV, 3);
++ reg_write(encoder, REG_AUDIO_DIV, 2);
++
++ /*
++ * This is the approximate value of N, which happens to be
++ * the recommended values for non-coherent clocks.
++ */
++ n = 128 * p->audio_sample_rate / 1000;
++
++ /* Write the CTS and N values */
++ buf[0] = 0x44;
++ buf[1] = 0x42;
++ buf[2] = 0x01;
++ buf[3] = n;
++ buf[4] = n >> 8;
++ buf[5] = n >> 16;
++ reg_write_range(encoder, REG_ACR_CTS_0, buf, 6);
++
++ /* Set CTS clock reference */
++ reg_write(encoder, REG_AIP_CLKSEL, clksel_aip | clksel_fs);
++
++ /* Reset CTS generator */
++ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
++
++ /* Write the channel status */
++ buf[0] = 0x04;
++ buf[1] = 0x00;
++ buf[2] = 0x00;
++ buf[3] = 0xf1;
++ reg_write_range(encoder, REG_CH_STAT_B(0), buf, 4);
++
++ tda998x_audio_mute(encoder, true);
++ mdelay(20);
++ tda998x_audio_mute(encoder, false);
++
++ /* Write the audio information packet */
++ tda998x_write_aif(encoder, p);
++}
++
++#if 0
++static struct tda998x_encoder_params default_params = {
++#if 0
++ /* This is with a post mux value of 0x12, which is what the nxp driver uses
++ VIP_MUX_G_B | VIP_MUX_B_R | VIP_MUX_R_G = 0x00 | 0x02 | 0x10
++ LCD out Pins VIP Int VP
++ R:7:0 VPC7:0 23:16 7:0[R]
++ G:15:8 VPB7:0 15:8 23:16[G]
++ B:23:16 VPA7:0 7:0 15:8[B]
++ */
++ .swap_a = 0,
++ .swap_b = 1,
++ .swap_c = 2,
++ .swap_d = 3,
++ .swap_e = 4,
++ .swap_f = 5,
++#else
++ /* With 0x24, there is no translation between vp_out and int_vp
++ FB LCD out Pins VIP Int Vp
++ R:23:16 R:7:0 VPC7:0 7:0 7:0[R]
++ G:15:8 G:15:8 VPB7:0 23:16 23:16[G]
++ B:7:0 B:23:16 VPA7:0 15:8 15:8[B]
++ */
++ .swap_a = 2,
++ .swap_b = 3,
++ .swap_c = 4,
++ .swap_d = 5,
++ .swap_e = 0,
++ .swap_f = 1,
++#endif
++ .audio_cfg = BIT(2),
++ .audio_frame[1] = 1,
++ .audio_format = AFMT_SPDIF,
++ .audio_sample_rate = 44100,
++};
++#else
++static struct tda998x_encoder_params default_params = {
++ .swap_a = 2,
++ .mirr_a = 0,
++ .swap_b = 3,
++ .mirr_b = 0,
++ .swap_c = 0,
++ .mirr_c = 0,
++ .swap_d = 1,
++ .mirr_d = 0,
++ .swap_e = 4,
++ .mirr_e = 0,
++ .swap_f = 5,
++ .mirr_f = 0,
++
++ .audio_cfg = 3, /* 2 channels i2s mode */
++ .audio_frame[1] = 1,
++ .audio_format = AFMT_I2S,
++ .audio_sample_rate = 44100,
++ .i2s_fmt = 0x0a,
++};
++#endif
++
+ /* DRM encoder functions */
+
+ static void
+ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
+ {
++ struct tda998x_priv *priv = to_tda998x_priv(encoder);
++ struct tda998x_encoder_params *p = params;
++
++ dev_info(encoder->dev->dev, "%s\n", __func__);
++
++ p = &default_params;
++
++ priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
++ (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
++ VIP_CNTRL_0_SWAP_B(p->swap_b) |
++ (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
++ priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
++ (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
++ VIP_CNTRL_1_SWAP_D(p->swap_d) |
++ (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
++ priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
++ (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
++ VIP_CNTRL_2_SWAP_F(p->swap_f) |
++ (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
++
++ priv->params = *p;
++
++ if (p->audio_cfg)
++ tda998x_configure_audio(encoder, p);
+ }
+
+ static void
+@@ -501,7 +762,8 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+ /* Write the default value MUX register */
+ reg_write(encoder, REG_MUX_VP_VIP_OUT, 0x24);
+ /* enable audio and video ports */
+- reg_write(encoder, REG_ENA_AP, 0x03);
++// reg_write(encoder, REG_ENA_AP, priv->ena_ap);
++// reg_write(encoder, REG_ENA_ACLK, priv->ena_aclk);
+ reg_write(encoder, REG_ENA_VP_0, 0xff);
+ reg_write(encoder, REG_ENA_VP_1, 0xff);
+ reg_write(encoder, REG_ENA_VP_2, 0xff);
+@@ -512,7 +774,7 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+ break;
+ case DRM_MODE_DPMS_OFF:
+ /* disable audio and video ports */
+- reg_write(encoder, REG_ENA_AP, 0x00);
++// reg_write(encoder, REG_ENA_AP, 0x00);
+ reg_write(encoder, REG_ENA_VP_0, 0x00);
+ reg_write(encoder, REG_ENA_VP_1, 0x00);
+ reg_write(encoder, REG_ENA_VP_2, 0x00);
+@@ -537,99 +799,36 @@ tda998x_encoder_restore(struct drm_encoder *encoder)
+ static bool
+ tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+- struct drm_display_mode *adjusted_mode)
+-{
+- return true;
+-}
+-
+-static int
+-tda998x_encoder_mode_valid(struct drm_encoder *encoder,
+- struct drm_display_mode *mode)
+-{
+- return MODE_OK;
+-}
+-
+-
+-static void
+-tda998x_audio_infoframe_enable(struct drm_encoder *encoder)
++ struct drm_display_mode *adjusted)
+ {
+- uint8_t buffer[20];
+- struct hdmi_audio_infoframe audio_frame;
+- size_t len;
+-
+- hdmi_audio_infoframe_init(&audio_frame);
+-
+- /* NXP audio is fixed at these values for the time being */
+- audio_frame.channels = 2;
+- audio_frame.coding_type = HDMI_AUDIO_CODING_TYPE_PCM;
+- audio_frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_24;
+- audio_frame.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
++ DBG("");
+
+- len = hdmi_audio_infoframe_pack(&audio_frame, buffer, sizeof(buffer));
+- WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
++ adjusted->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
++ DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC |
++ DRM_MODE_FLAG_PCSYNC | DRM_MODE_FLAG_NCSYNC);
+
+- reg_write_range(encoder, REG_AUDIO_IF, buffer, len);
++ /* The TDA19988 always requires negative VSYNC? */
++ adjusted->flags |= DRM_MODE_FLAG_NVSYNC;
+
+- /* enable Audio Infoframe output in DIP_IF Register */
+- reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
+- udelay(5);
+- reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
+-}
++ /* The TDA19988 requires positive HSYNC on 1080p or 720p */
++ if ((adjusted->hdisplay == 1920 && adjusted->vdisplay == 1080) ||
++ (adjusted->hdisplay == 1280 && adjusted->vdisplay == 720))
++ adjusted->flags |= DRM_MODE_FLAG_PHSYNC;
++ else
++ adjusted->flags |= DRM_MODE_FLAG_NHSYNC;
+
+-static void
+-tda998x_avi_infoframe_enable(struct drm_encoder *encoder,
+- struct drm_display_mode *mode)
+-{
+- uint8_t buffer[20];
+- struct hdmi_avi_infoframe avi_frame;
+- size_t len;
+-
+- hdmi_avi_infoframe_init(&avi_frame);
+- avi_frame.video_code = drm_match_cea_mode(mode);
+- avi_frame.picture_aspect = HDMI_PICTURE_ASPECT_NONE;
+- avi_frame.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
+- len = hdmi_avi_infoframe_pack(&avi_frame, buffer, sizeof(buffer));
+- WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
+-
+- reg_write_range(encoder, REG_AVI_IF, buffer, len);
+-
+- /*
+- * enable AVI Infoframe output in DIP_IF Register, but toggle it
+- * so that the hardware acknowledges that the packet data might have
+- * changed
+- */
+- reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
+- udelay(5);
+- reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
++ return true;
+ }
+
+-/* lookup table for CEA values to VIDFORMAT values taken from NXP datasheet */
+-static char cea_to_nxp_mode[34] = {-1, 0, 1, 1, 2, 3, 4, 4, 5, 5, -1, -1,
+- -1, -1, -1, -1, 6, 7, 7, 8, 9, 10, 10,
+- 11, 11, -1, -1, -1, -1, -1, -1, 12, 13};
+-
+-static char tda998x_cea_to_vidformat(unsigned char cea_mode)
++static int
++tda998x_encoder_mode_valid(struct drm_encoder *encoder,
++ struct drm_display_mode *mode)
+ {
+- if(cea_mode > (sizeof(cea_to_nxp_mode) -1) ) {
+- return -1;
+- }
+- return cea_to_nxp_mode[cea_mode];
+-}
++ DBG("");
+
+-static char tda998x_is_monitor_hdmi(struct drm_encoder *encoder)
+-{
+- struct edid *edid = (struct edid *)do_get_edid(encoder);
+- char hdmi = 0;
+- if(edid) {
+- hdmi = drm_detect_hdmi_monitor(edid);
+- kfree(edid);
+- } else {
+- return -1;
+- }
+- return hdmi;
++ return MODE_OK;
+ }
+
+-
+ static void
+ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+@@ -676,7 +875,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ /* mute the audio FIFO: */
+ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+
+- /* HDMI/HDCP mode off... for now...: */
++ /* set HDMI HDCP mode off: */
+ reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+ reg_clear(encoder, REG_TX33, TX33_HDMI);
+
+@@ -744,69 +943,29 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ reg_write16(encoder, REG_REFPIX_MSB, ref_pix);
+ reg_write16(encoder, REG_REFLINE_MSB, ref_line);
+
+- reg = TBG_CNTRL_1_VHX_EXT_DE |
+- TBG_CNTRL_1_VHX_EXT_HS |
+- TBG_CNTRL_1_VHX_EXT_VS |
+- TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
++ reg = TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
+ TBG_CNTRL_1_VH_TGL_2;
++ /*
++ * It is questionable whether this is correct - the nxp driver
++ * does not set VH_TGL_2 and the below for all display modes.
++ */
+ if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC))
+ reg |= TBG_CNTRL_1_VH_TGL_0;
+ reg_set(encoder, REG_TBG_CNTRL_1, reg);
+
+-
+-
+-
+- if(tda998x_is_monitor_hdmi(encoder) == 1) {
+- char vidformat;
+- vidformat = tda998x_cea_to_vidformat(drm_match_cea_mode(mode));
+- if(vidformat == (char)-1) {
+- dev_err(encoder->dev->dev, "Not sure which CEA mode to set, leaving as DVI");
+- goto out;
+- }
+- dev_info(encoder->dev->dev, "Connected to an HDMI monitor with cea mode %d", vidformat);
+-
+- /* this is an HDMI monitor, so set things up a bit differently */
+- reg_write(encoder, REG_TBG_CNTRL_1, 0);
+- reg_write(encoder, REG_VIDFORMAT, vidformat);
+- /* get the infoframes pumping */
+- tda998x_avi_infoframe_enable(encoder, mode);
+- tda998x_audio_infoframe_enable(encoder);
++ /* Only setup the info frames if the sink is HDMI */
++ if (priv->is_hdmi_sink) {
++ /* We need to turn HDMI HDCP stuff on to get audio through */
++ reg_clear(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
++ reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
+ reg_set(encoder, REG_TX33, TX33_HDMI);
+
+- /* set up audio registers */
+- reg_write(encoder, REG_ACR_CTS_0, 0x0);
+- reg_write(encoder, REG_ACR_CTS_1, 0x0);
+- reg_write(encoder, REG_ACR_CTS_2, 0x0);
+-
+- reg_write(encoder, REG_ACR_N_0, 0x0);
+- reg_write(encoder, REG_ACR_N_1, 0x18);
+- reg_write(encoder, REG_ACR_N_2, 0x0);
++ tda998x_write_avi(encoder, adjusted_mode);
+
+- reg_set(encoder, REG_DIP_FLAGS, DIP_FLAGS_ACR);
+-
+- reg_write(encoder, REG_ENC_CNTRL, 0x04);
+- reg_write(encoder, REG_CTS_N, 0x33);
+- /* Set 2 channel I2S mode */
+- reg_write(encoder, REG_ENA_AP, 0x3);
+-
+- /* set audio divider in pll settings */
+- reg_write(encoder, REG_AUDIO_DIV, 0x2);
+-
+- /* select the audio input port clock */
+- reg_write(encoder, REG_AIP_CLKSEL, SEL_AIP_I2S);
+- reg_write(encoder, REG_MUX_AP, MUX_AP_SELECT_I2S);
+-
+- /* select I2S format, and datasize */
+- reg_write(encoder, REG_I2S_FORMAT, 0x0a);
+-
+- /* enable the audio FIFO: */
+- reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+-
+- /* mute and then unmute, to get audio going */
+- reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_SETMUTE);
+- reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_CLRMUTE);
++ if (priv->params.audio_cfg)
++ tda998x_configure_audio(encoder, &priv->params);
+ }
+-out:
++
+ /* must be last register set: */
+ reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
+
+@@ -935,12 +1094,14 @@ static int
+ tda998x_encoder_get_modes(struct drm_encoder *encoder,
+ struct drm_connector *connector)
+ {
++ struct tda998x_priv *priv = to_tda998x_priv(encoder);
+ struct edid *edid = (struct edid *)do_get_edid(encoder);
+ int n = 0;
+
+ if (edid) {
+ drm_mode_connector_update_edid_property(connector, edid);
+ n = drm_add_edid_modes(connector, edid);
++ priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
+ kfree(edid);
+ }
+
+@@ -1002,6 +1163,59 @@ tda998x_remove(struct i2c_client *client)
+ return 0;
+ }
+
++static ssize_t i2c_read_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct drm_encoder *encoder = dev_get_drvdata(dev);
++ unsigned int page, addr;
++ unsigned char val;
++
++ sscanf(buf, "%x %x", &page, &addr);
++
++ val = reg_read(encoder, REG(page, addr));
++
++ printk("i2c read %02x @ page:%02x address:%02x\n", val, page, addr);
++ return size;
++}
++
++static ssize_t i2c_write_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct drm_encoder *encoder = dev_get_drvdata(dev);
++ unsigned int page, addr, mask, val;
++ unsigned char rval;
++
++ sscanf(buf, "%x %x %x %x", &page, &addr, &mask, &val);
++
++ rval = reg_read(encoder, REG(page, addr));
++ rval &= ~mask;
++ rval |= val & mask;
++ reg_write(encoder, REG(page, addr), rval);
++
++ printk("i2c write %02x @ page:%02x address:%02x\n", rval, page, addr);
++ return size;
++}
++
++static ssize_t i2c_dump_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct drm_encoder *encoder = dev_get_drvdata(dev);
++ unsigned int page;
++ char prefix[16];
++ uint8_t tmp[255];
++
++ sscanf(buf, "%x", &page);
++
++ reg_read_range(encoder, REG(page, 0), tmp, 254);
++
++ snprintf(prefix, sizeof(prefix) - 1, "PG-%02x ", page);
++
++ print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 16, 1, tmp, 254, false);
++
++ return size;
++}
++
++static DEVICE_ATTR(i2c_read, S_IWUSR, NULL, i2c_read_store);
++static DEVICE_ATTR(i2c_write, S_IWUSR, NULL, i2c_write_store);
++static DEVICE_ATTR(i2c_dump, S_IWUSR, NULL, i2c_dump_store);
++
+ static int
+ tda998x_encoder_init(struct i2c_client *client,
+ struct drm_device *dev,
+@@ -1009,14 +1223,41 @@ tda998x_encoder_init(struct i2c_client *client,
+ {
+ struct drm_encoder *encoder = &encoder_slave->base;
+ struct tda998x_priv *priv;
++ struct tda998x_encoder_params *p;
++
++/* debug */
++ device_create_file(&client->dev, &dev_attr_i2c_read);
++ device_create_file(&client->dev, &dev_attr_i2c_write);
++ device_create_file(&client->dev, &dev_attr_i2c_dump);
++ dev_set_drvdata(&client->dev, encoder);
++/* debug end */
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
++ p = &priv->params;
++#if 0
+ priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
+ priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
+ priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
++#else
++
++ *p = default_params;
++
++ priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
++ (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
++ VIP_CNTRL_0_SWAP_B(p->swap_b) |
++ (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
++ priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
++ (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
++ VIP_CNTRL_1_SWAP_D(p->swap_d) |
++ (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
++ priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
++ (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
++ VIP_CNTRL_2_SWAP_F(p->swap_f) |
++ (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
++#endif
+
+ priv->current_page = 0;
+ priv->cec = i2c_new_dummy(client->adapter, 0x34);
+@@ -1115,4 +1356,3 @@ MODULE_LICENSE("GPL");
+
+ module_init(tda998x_init);
+ module_exit(tda998x_exit);
+-
+diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
+index 41f799f..23736f1 100644
+--- a/include/drm/i2c/tda998x.h
++++ b/include/drm/i2c/tda998x.h
+@@ -1,23 +1,26 @@
+ #ifndef __TDA998X_H__
+ #define __TDA998X_H__
+
++#include <linux/types.h>
++
+ enum tda998x_audio_format {
+ AFMT_I2S,
+ AFMT_SPDIF,
+ };
+
+ struct tda998x_encoder_params {
+- int audio_cfg;
+- int audio_clk_cfg;
++ uint8_t audio_cfg;
++ uint8_t audio_clk_cfg;
+ enum tda998x_audio_format audio_format;
+ int audio_sample_rate;
+- char audio_frame[6];
+- int swap_a, mirr_a;
+- int swap_b, mirr_b;
+- int swap_c, mirr_c;
+- int swap_d, mirr_d;
+- int swap_e, mirr_e;
+- int swap_f, mirr_f;
++ uint8_t audio_frame[6];
++ uint8_t swap_a, mirr_a;
++ uint8_t swap_b, mirr_b;
++ uint8_t swap_c, mirr_c;
++ uint8_t swap_d, mirr_d;
++ uint8_t swap_e, mirr_e;
++ uint8_t swap_f, mirr_f;
++ uint8_t i2s_fmt;
+ };
+
+ #endif
diff --git a/patches/linux-3.8.13/0592-tilcdc-Slave-panel-settings-read-from-DT-now.patch b/patches/linux-3.8.13/0592-tilcdc-Slave-panel-settings-read-from-DT-now.patch
new file mode 100644
index 0000000..75110ff
--- /dev/null
+++ b/patches/linux-3.8.13/0592-tilcdc-Slave-panel-settings-read-from-DT-now.patch
@@ -0,0 +1,221 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 6 Jun 2013 11:45:28 +0300
+Subject: [PATCH] tilcdc: Slave panel settings read from DT now
+
+Turns out that we really need those panel settings.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 56 +++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 3 ++
+ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 49 +----------------------------
+ drivers/gpu/drm/tilcdc/tilcdc_slave.c | 25 +++++++--------
+ 4 files changed, 71 insertions(+), 62 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 8ce18ca..023092f 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -721,3 +721,59 @@ fail:
+ tilcdc_crtc_destroy(crtc);
+ return NULL;
+ }
++
++struct tilcdc_panel_info *tilcdc_of_get_panel_info(struct device_node *np)
++{
++ struct device_node *info_np;
++ struct tilcdc_panel_info *info;
++ int ret = 0;
++
++ if (!np)
++ return NULL;
++
++ info_np = of_get_child_by_name(np, "panel-info");
++ if (!info_np) {
++ pr_err("%s: could not find panel-info node\n",
++ of_node_full_name(np));
++ return NULL;
++ }
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (!info) {
++ pr_err("%s: allocation failed\n",
++ of_node_full_name(np));
++ goto err_no_mem;
++ }
++
++ ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias);
++ ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt);
++ ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz);
++ ret |= of_property_read_u32(info_np, "bpp", &info->bpp);
++ ret |= of_property_read_u32(info_np, "fdd", &info->fdd);
++ ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge);
++ ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl);
++ ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order);
++ ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th);
++
++ /* optional: */
++ info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode");
++ info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk");
++
++ if (ret) {
++ pr_err("%s: error reading panel-info properties\n",
++ of_node_full_name(info_np));
++ goto err_bad_prop;
++ }
++
++ /* release ref */
++ of_node_put(info_np);
++
++ return info;
++
++err_bad_prop:
++ kfree(info);
++err_no_mem:
++ of_node_put(info_np);
++ return NULL;
++}
++
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index f3861e4..40ff5d4 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -169,4 +169,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ int rb_check, int audio, struct edid *edid);
+ int tilcdc_crtc_max_width(struct drm_crtc *crtc);
+
++/* OF helper for reading panel info */
++struct tilcdc_panel_info *tilcdc_of_get_panel_info(struct device_node *np);
++
+ #endif /* __TILCDC_DRV_H__ */
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+index 90bc0e3..2aa4a2e 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+@@ -308,53 +308,6 @@ static const struct tilcdc_module_ops panel_module_ops = {
+ * Device:
+ */
+
+-/* maybe move this somewhere common if it is needed by other outputs? */
+-static struct tilcdc_panel_info * of_get_panel_info(struct device_node *np)
+-{
+- struct device_node *info_np;
+- struct tilcdc_panel_info *info;
+- int ret = 0;
+-
+- if (!np) {
+- pr_err("%s: no devicenode given\n", __func__);
+- return NULL;
+- }
+-
+- info_np = of_get_child_by_name(np, "panel-info");
+- if (!info_np) {
+- pr_err("%s: could not find panel-info node\n", __func__);
+- return NULL;
+- }
+-
+- info = kzalloc(sizeof(*info), GFP_KERNEL);
+- if (!info) {
+- pr_err("%s: allocation failed\n", __func__);
+- return NULL;
+- }
+-
+- ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias);
+- ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt);
+- ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz);
+- ret |= of_property_read_u32(info_np, "bpp", &info->bpp);
+- ret |= of_property_read_u32(info_np, "fdd", &info->fdd);
+- ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge);
+- ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl);
+- ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order);
+- ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th);
+-
+- /* optional: */
+- info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode");
+- info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk");
+-
+- if (ret) {
+- pr_err("%s: error reading panel-info properties\n", __func__);
+- kfree(info);
+- return NULL;
+- }
+-
+- return info;
+-}
+-
+ static struct of_device_id panel_of_match[];
+
+ static ssize_t pinmux_show_state(struct device *dev,
+@@ -495,7 +448,7 @@ static int panel_probe(struct platform_device *pdev)
+ goto fail;
+ }
+
+- panel_mod->info = of_get_panel_info(node);
++ panel_mod->info = tilcdc_of_get_panel_info(node);
+ if (!panel_mod->info) {
+ dev_err(&pdev->dev, "could not get panel info\n");
+ goto fail;
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+index e454874..440de4e 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+@@ -25,25 +25,13 @@
+
+ struct slave_module {
+ struct tilcdc_module base;
++ struct tilcdc_panel_info *info;
+ struct i2c_adapter *i2c;
+ struct pinctrl *pinctrl;
+ char *selected_state_name;
+ };
+ #define to_slave_module(x) container_of(x, struct slave_module, base)
+
+-static const struct tilcdc_panel_info slave_info = {
+- .bpp = 16,
+- .ac_bias = 255,
+- .ac_bias_intrpt = 0,
+- .dma_burst_sz = 16,
+- .fdd = 0x80,
+- .tft_alt_mode = 0,
+- .sync_edge = 0,
+- .sync_ctrl = 1,
+- .raster_order = 0,
+-};
+-
+-
+ /*
+ * Encoder:
+ */
+@@ -71,8 +59,10 @@ static void slave_encoder_destroy(struct drm_encoder *encoder)
+
+ static void slave_encoder_prepare(struct drm_encoder *encoder)
+ {
++ struct slave_encoder *slave_encoder = to_slave_encoder(encoder);
++
+ drm_i2c_encoder_prepare(encoder);
+- tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info);
++ tilcdc_crtc_set_panel_info(encoder->crtc, slave_encoder->mod->info);
+ }
+
+ static const struct drm_encoder_funcs slave_encoder_funcs = {
+@@ -283,6 +273,7 @@ static void slave_destroy(struct tilcdc_module *mod)
+ struct slave_module *slave_mod = to_slave_module(mod);
+
+ tilcdc_module_cleanup(mod);
++ kfree(slave_mod->info);
+ kfree(slave_mod);
+ }
+
+@@ -446,6 +437,12 @@ static int slave_probe(struct platform_device *pdev)
+ goto fail;
+ }
+
++ slave_mod->info = tilcdc_of_get_panel_info(node);
++ if (!slave_mod->info) {
++ dev_err(&pdev->dev, "could not get panel info\n");
++ goto fail;
++ }
++
+ of_node_put(i2c_node);
+
+ return 0;
diff --git a/patches/linux-3.8.13/0593-drm-tda998x-Revert-WIP-to-previous-state.patch b/patches/linux-3.8.13/0593-drm-tda998x-Revert-WIP-to-previous-state.patch
new file mode 100644
index 0000000..e6d7285
--- /dev/null
+++ b/patches/linux-3.8.13/0593-drm-tda998x-Revert-WIP-to-previous-state.patch
@@ -0,0 +1,838 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 6 Jun 2013 22:25:45 +0300
+Subject: [PATCH] drm: tda998x: Revert WIP to previous state
+
+Revert all the changes of the WIP so that audio continues to work.
+We do it with an explicit patch so that we can revisit at a later
+time when things settled down.
+---
+ drivers/gpu/drm/i2c/tda998x_drv.c | 611 +++++++++++--------------------------
+ 1 file changed, 176 insertions(+), 435 deletions(-)
+
+diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
+index 2049898..412ba4f 100644
+--- a/drivers/gpu/drm/i2c/tda998x_drv.c
++++ b/drivers/gpu/drm/i2c/tda998x_drv.c
+@@ -25,8 +25,6 @@
+ #include <drm/drm_edid.h>
+ #include <linux/hdmi.h>
+
+-#include <drm/i2c/tda998x.h>
+-
+ #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+ struct tda998x_priv {
+@@ -34,11 +32,6 @@ struct tda998x_priv {
+ uint16_t rev;
+ uint8_t current_page;
+ int dpms;
+- bool is_hdmi_sink;
+- u8 vip_cntrl_0;
+- u8 vip_cntrl_1;
+- u8 vip_cntrl_2;
+- struct tda998x_encoder_params params;
+ };
+
+ #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
+@@ -75,13 +68,10 @@ struct tda998x_priv {
+ # define I2C_MASTER_DIS_MM (1 << 0)
+ # define I2C_MASTER_DIS_FILT (1 << 1)
+ # define I2C_MASTER_APP_STRT_LAT (1 << 2)
+-#define REG_FEAT_POWERDOWN REG(0x00, 0x0e) /* read/write */
+-# define FEAT_POWERDOWN_SPDIF (1 << 3)
+ #define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */
+ #define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */
+ #define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */
+ # define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
+-#define REG_ENA_ACLK REG(0x00, 0x16) /* read/write */
+ #define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */
+ #define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */
+ #define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */
+@@ -120,8 +110,9 @@ struct tda998x_priv {
+ #define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
+ # define VIP_CNTRL_5_CKCASE (1 << 0)
+ # define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
+-#define REG_MUX_AP REG(0x00, 0x26) /* read/write */
+-#define REG_MUX_VP_VIP_OUT REG(0x00, 0x27) /* read/write */
++
++#define REG_MUX_AP REG(0x00, 0x26)
++# define MUX_AP_SELECT_I2S (0x64)
+ #define REG_MAT_CONTRL REG(0x00, 0x80) /* write */
+ # define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0)
+ # define MAT_CONTRL_MAT_BP (1 << 2)
+@@ -183,13 +174,10 @@ struct tda998x_priv {
+ # define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4)
+ # define HVF_CNTRL_1_SEMI_PLANAR (1 << 6)
+ #define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */
+-#define REG_I2S_FORMAT REG(0x00, 0xfc) /* read/write */
+-# define I2S_FORMAT(x) (((x) & 3) << 0)
+-#define REG_AIP_CLKSEL REG(0x00, 0xfd) /* write */
+-# define AIP_CLKSEL_FS(x) (((x) & 3) << 0)
+-# define AIP_CLKSEL_CLK_POL(x) (((x) & 1) << 2)
+-# define AIP_CLKSEL_AIP(x) (((x) & 7) << 3)
++#define REG_I2S_FORMAT REG(0x00, 0xfc)
+
++#define REG_AIP_CLKSEL REG(0x00, 0xfd)
++# define SEL_AIP_I2S (1 << 3) /* I2S Clk */
+
+ /* Page 02h: PLL settings */
+ #define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */
+@@ -230,12 +218,8 @@ struct tda998x_priv {
+
+
+ /* Page 10h: information frames and packets */
+-#define REG_IF1_HB0 REG(0x10, 0x20) /* read/write */
+-#define REG_IF2_HB0 REG(0x10, 0x40) /* read/write */
+-#define REG_IF3_HB0 REG(0x10, 0x60) /* read/write */
+-#define REG_IF4_HB0 REG(0x10, 0x80) /* read/write */
+-#define REG_IF5_HB0 REG(0x10, 0xa0) /* read/write */
+-
++#define REG_AVI_IF REG(0x10, 0x40) /* AVI Infoframe packet */
++#define REG_AUDIO_IF REG(0x10, 0x80) /* AVI Infoframe packet */
+
+ /* Page 11h: audio settings and content info packets */
+ #define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */
+@@ -244,39 +228,31 @@ struct tda998x_priv {
+ # define AIP_CNTRL_0_LAYOUT (1 << 2)
+ # define AIP_CNTRL_0_ACR_MAN (1 << 5)
+ # define AIP_CNTRL_0_RST_CTS (1 << 6)
+-#define REG_CA_I2S REG(0x11, 0x01) /* read/write */
+-# define CA_I2S_CA_I2S(x) (((x) & 31) << 0)
+-# define CA_I2S_HBR_CHSTAT (1 << 6)
+-#define REG_LATENCY_RD REG(0x11, 0x04) /* read/write */
+-#define REG_ACR_CTS_0 REG(0x11, 0x05) /* read/write */
+-#define REG_ACR_CTS_1 REG(0x11, 0x06) /* read/write */
+-#define REG_ACR_CTS_2 REG(0x11, 0x07) /* read/write */
+-#define REG_ACR_N_0 REG(0x11, 0x08) /* read/write */
+-#define REG_ACR_N_1 REG(0x11, 0x09) /* read/write */
+-#define REG_ACR_N_2 REG(0x11, 0x0a) /* read/write */
+-#define REG_CTS_N REG(0x11, 0x0c) /* read/write */
+-# define CTS_N_K(x) (((x) & 7) << 0)
+-# define CTS_N_M(x) (((x) & 3) << 4)
++#define REG_ACR_CTS_0 REG(0x11, 0x05)
++#define REG_ACR_CTS_1 REG(0x11, 0x06)
++#define REG_ACR_CTS_2 REG(0x11, 0x07)
++#define REG_ACR_N_0 REG(0x11, 0x08)
++#define REG_ACR_N_1 REG(0x11, 0x09)
++#define REG_ACR_N_2 REG(0x11, 0x0a)
++#define REG_GC_AVMUTE REG(0x11, 0x0b)
++# define GC_AVMUTE_CLRMUTE (1 << 0)
++# define GC_AVMUTE_SETMUTE (1 << 1)
++#define REG_CTS_N REG(0x11, 0x0c)
+ #define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */
+ # define ENC_CNTRL_RST_ENC (1 << 0)
+ # define ENC_CNTRL_RST_SEL (1 << 1)
+ # define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2)
+-#define REG_DIP_FLAGS REG(0x11, 0x0e) /* read/write */
++#define REG_DIP_FLAGS REG(0x11, 0x0e)
+ # define DIP_FLAGS_ACR (1 << 0)
+-# define DIP_FLAGS_GC (1 << 1)
+ #define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */
+-# define DIP_IF_FLAGS_IF1 (1 << 1)
+-# define DIP_IF_FLAGS_IF2 (1 << 2)
+-# define DIP_IF_FLAGS_IF3 (1 << 3)
+-# define DIP_IF_FLAGS_IF4 (1 << 4)
+-# define DIP_IF_FLAGS_IF5 (1 << 5)
+-#define REG_CH_STAT_B(x) REG(0x11, 0x14 + (x)) /* read/write */
+-
++#define DIP_IF_FLAGS_IF1 (1 << 1)
++#define DIP_IF_FLAGS_IF2 (1 << 2)
++#define DIP_IF_FLAGS_IF3 (1 << 3)
++#define DIP_IF_FLAGS_IF4 (1 << 4)
++#define DIP_IF_FLAGS_IF5 (1 << 5)
+
+ /* Page 12h: HDCP and OTP */
+ #define REG_TX3 REG(0x12, 0x9a) /* read/write */
+-#define REG_TX4 REG(0x12, 0x9b) /* read/write */
+-# define TX4_PD_RAM (1 << 1)
+ #define REG_TX33 REG(0x12, 0xb8) /* read/write */
+ # define TX33_HDMI (1 << 1)
+
+@@ -310,6 +286,9 @@ struct tda998x_priv {
+ #define TDA19989N2 0x0202
+ #define TDA19988 0x0301
+
++static uint8_t *
++do_get_edid(struct drm_encoder *encoder);
++
+ static void
+ cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
+ {
+@@ -492,257 +471,11 @@ tda998x_reset(struct drm_encoder *encoder)
+ reg_write(encoder, REG_PLL_SCG2, 0x10);
+ }
+
+-static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes)
+-{
+- uint8_t sum = 0;
+-
+- while (bytes--)
+- sum += *buf++;
+- return (255 - sum) + 1;
+-}
+-
+-#define HB(x) (x)
+-#define PB(x) (HB(2) + 1 + (x))
+-
+-static void
+-tda998x_write_if(struct drm_encoder *encoder, uint8_t bit, uint16_t addr,
+- uint8_t *buf, size_t size)
+-{
+- buf[PB(0)] = tda998x_cksum(buf, size);
+-
+- reg_clear(encoder, REG_DIP_IF_FLAGS, bit);
+- reg_write_range(encoder, addr, buf, size);
+- reg_set(encoder, REG_DIP_IF_FLAGS, bit);
+-}
+-
+-static void
+-tda998x_write_aif(struct drm_encoder *encoder, struct tda998x_encoder_params *p)
+-{
+- uint8_t buf[PB(5) + 1];
+-
+- buf[HB(0)] = 0x84;
+- buf[HB(1)] = 0x01;
+- buf[HB(2)] = 10;
+- buf[PB(0)] = 0;
+- buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */
+- buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */
+- buf[PB(4)] = p->audio_frame[4];
+- buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */
+-
+- tda998x_write_if(encoder, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf,
+- sizeof(buf));
+-}
+-
+-static void
+-tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode)
+-{
+- uint8_t buf[PB(13) + 1];
+-
+- memset(buf, 0, sizeof(buf));
+- buf[HB(0)] = 0x82;
+- buf[HB(1)] = 0x02;
+- buf[HB(2)] = 13;
+- buf[PB(4)] = drm_match_cea_mode(mode);
+-
+- tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
+- sizeof(buf));
+-}
+-
+-static void tda998x_audio_mute(struct drm_encoder *encoder, bool on)
+-{
+- if (on) {
+- reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO);
+- reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO);
+- reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+- } else {
+- reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+- }
+-}
+-
+-static void
+-tda998x_configure_audio(struct drm_encoder *encoder, struct tda998x_encoder_params *p)
+-{
+- uint8_t buf[6], clksel_aip = 0, clksel_fs = 0, ca_i2s, cts_n;
+- uint32_t n;
+-
+- /* SetAudioPortConfig */
+- reg_write(encoder, REG_ENA_AP, p->audio_cfg);
+- /* SetAudioClockPortConfig */
+- reg_write(encoder, REG_ENA_ACLK, p->audio_clk_cfg);
+-
+- /*
+- * layout = channelAllocation ? 1 : 0;
+- * AudioInSetConfig(format, i2sFormat, channelAllocation,
+- * HDMITX_CHAN_NO_CHANGE, HDMITX_CLKPOLDSD_NO_CHANGE,
+- * HDMITX_SWAPDSD_NO_CHANGE, layout, HDMITX_LATENCY_CURRENT,
+- * dstRate)
+- */
+- switch (p->audio_format) {
+- case AFMT_SPDIF:
+- reg_write(encoder, REG_MUX_AP, 0x40);
+- clksel_aip = AIP_CLKSEL_AIP(0);
+- /* FS64SPDIF */
+- clksel_fs = AIP_CLKSEL_FS(2);
+- cts_n = CTS_N_M(3) | CTS_N_K(3);
+- ca_i2s = 0;
+- break;
+-
+- case AFMT_I2S:
+- reg_write(encoder, REG_MUX_AP, 0x64);
+- clksel_aip = AIP_CLKSEL_AIP(1);
+- /* ACLK */
+- clksel_fs = AIP_CLKSEL_FS(0);
+- cts_n = CTS_N_M(3) | CTS_N_K(3);
+- ca_i2s = CA_I2S_CA_I2S(0 /* channel allocation */);
+- break;
+- }
+-
+- reg_write(encoder, REG_AIP_CLKSEL, clksel_aip);
+- if (p->audio_format == AFMT_I2S) {
+- reg_write(encoder, REG_CA_I2S, ca_i2s);
+- reg_write(encoder, REG_I2S_FORMAT, p->i2s_fmt);
+- }
+- reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT);
+- /* latency? */
+-
+- /* get video format */
+-
+- /*
+- * ctsRef = HDMITX_CTSREF_FS64SPDIF, uCtsX = HDMITX_CTSX_64
+- * AudioInSetCts(ctsRef, rate, VidFmt, vOutFreq,
+- * HDMITX_CTS_AUTO, uCtsX, HDMITX_CTSK_USE_CTSX,
+- * HDMITX_CTSMTS_USE_CTSX, dstRate)
+- */
+- /* Auto CTS */
+- reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_ACR_MAN);
+- reg_write(encoder, REG_CTS_N, cts_n);
+- // reg_write(encoder, REG_AUDIO_DIV, 3);
+- reg_write(encoder, REG_AUDIO_DIV, 2);
+-
+- /*
+- * This is the approximate value of N, which happens to be
+- * the recommended values for non-coherent clocks.
+- */
+- n = 128 * p->audio_sample_rate / 1000;
+-
+- /* Write the CTS and N values */
+- buf[0] = 0x44;
+- buf[1] = 0x42;
+- buf[2] = 0x01;
+- buf[3] = n;
+- buf[4] = n >> 8;
+- buf[5] = n >> 16;
+- reg_write_range(encoder, REG_ACR_CTS_0, buf, 6);
+-
+- /* Set CTS clock reference */
+- reg_write(encoder, REG_AIP_CLKSEL, clksel_aip | clksel_fs);
+-
+- /* Reset CTS generator */
+- reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
+- reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
+-
+- /* Write the channel status */
+- buf[0] = 0x04;
+- buf[1] = 0x00;
+- buf[2] = 0x00;
+- buf[3] = 0xf1;
+- reg_write_range(encoder, REG_CH_STAT_B(0), buf, 4);
+-
+- tda998x_audio_mute(encoder, true);
+- mdelay(20);
+- tda998x_audio_mute(encoder, false);
+-
+- /* Write the audio information packet */
+- tda998x_write_aif(encoder, p);
+-}
+-
+-#if 0
+-static struct tda998x_encoder_params default_params = {
+-#if 0
+- /* This is with a post mux value of 0x12, which is what the nxp driver uses
+- VIP_MUX_G_B | VIP_MUX_B_R | VIP_MUX_R_G = 0x00 | 0x02 | 0x10
+- LCD out Pins VIP Int VP
+- R:7:0 VPC7:0 23:16 7:0[R]
+- G:15:8 VPB7:0 15:8 23:16[G]
+- B:23:16 VPA7:0 7:0 15:8[B]
+- */
+- .swap_a = 0,
+- .swap_b = 1,
+- .swap_c = 2,
+- .swap_d = 3,
+- .swap_e = 4,
+- .swap_f = 5,
+-#else
+- /* With 0x24, there is no translation between vp_out and int_vp
+- FB LCD out Pins VIP Int Vp
+- R:23:16 R:7:0 VPC7:0 7:0 7:0[R]
+- G:15:8 G:15:8 VPB7:0 23:16 23:16[G]
+- B:7:0 B:23:16 VPA7:0 15:8 15:8[B]
+- */
+- .swap_a = 2,
+- .swap_b = 3,
+- .swap_c = 4,
+- .swap_d = 5,
+- .swap_e = 0,
+- .swap_f = 1,
+-#endif
+- .audio_cfg = BIT(2),
+- .audio_frame[1] = 1,
+- .audio_format = AFMT_SPDIF,
+- .audio_sample_rate = 44100,
+-};
+-#else
+-static struct tda998x_encoder_params default_params = {
+- .swap_a = 2,
+- .mirr_a = 0,
+- .swap_b = 3,
+- .mirr_b = 0,
+- .swap_c = 0,
+- .mirr_c = 0,
+- .swap_d = 1,
+- .mirr_d = 0,
+- .swap_e = 4,
+- .mirr_e = 0,
+- .swap_f = 5,
+- .mirr_f = 0,
+-
+- .audio_cfg = 3, /* 2 channels i2s mode */
+- .audio_frame[1] = 1,
+- .audio_format = AFMT_I2S,
+- .audio_sample_rate = 44100,
+- .i2s_fmt = 0x0a,
+-};
+-#endif
+-
+ /* DRM encoder functions */
+
+ static void
+ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
+ {
+- struct tda998x_priv *priv = to_tda998x_priv(encoder);
+- struct tda998x_encoder_params *p = params;
+-
+- dev_info(encoder->dev->dev, "%s\n", __func__);
+-
+- p = &default_params;
+-
+- priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
+- (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
+- VIP_CNTRL_0_SWAP_B(p->swap_b) |
+- (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
+- priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
+- (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
+- VIP_CNTRL_1_SWAP_D(p->swap_d) |
+- (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
+- priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
+- (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
+- VIP_CNTRL_2_SWAP_F(p->swap_f) |
+- (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
+-
+- priv->params = *p;
+-
+- if (p->audio_cfg)
+- tda998x_configure_audio(encoder, p);
+ }
+
+ static void
+@@ -759,22 +492,22 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+
+ switch (mode) {
+ case DRM_MODE_DPMS_ON:
+- /* Write the default value MUX register */
+- reg_write(encoder, REG_MUX_VP_VIP_OUT, 0x24);
+ /* enable audio and video ports */
+-// reg_write(encoder, REG_ENA_AP, priv->ena_ap);
+-// reg_write(encoder, REG_ENA_ACLK, priv->ena_aclk);
++ reg_write(encoder, REG_ENA_AP, 0x03);
+ reg_write(encoder, REG_ENA_VP_0, 0xff);
+ reg_write(encoder, REG_ENA_VP_1, 0xff);
+ reg_write(encoder, REG_ENA_VP_2, 0xff);
+ /* set muxing after enabling ports: */
+- reg_write(encoder, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
+- reg_write(encoder, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
+- reg_write(encoder, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
++ reg_write(encoder, REG_VIP_CNTRL_0,
++ VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3));
++ reg_write(encoder, REG_VIP_CNTRL_1,
++ VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1));
++ reg_write(encoder, REG_VIP_CNTRL_2,
++ VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5));
+ break;
+ case DRM_MODE_DPMS_OFF:
+ /* disable audio and video ports */
+-// reg_write(encoder, REG_ENA_AP, 0x00);
++ reg_write(encoder, REG_ENA_AP, 0x00);
+ reg_write(encoder, REG_ENA_VP_0, 0x00);
+ reg_write(encoder, REG_ENA_VP_1, 0x00);
+ reg_write(encoder, REG_ENA_VP_2, 0x00);
+@@ -799,24 +532,8 @@ tda998x_encoder_restore(struct drm_encoder *encoder)
+ static bool
+ tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+- struct drm_display_mode *adjusted)
++ struct drm_display_mode *adjusted_mode)
+ {
+- DBG("");
+-
+- adjusted->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
+- DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC |
+- DRM_MODE_FLAG_PCSYNC | DRM_MODE_FLAG_NCSYNC);
+-
+- /* The TDA19988 always requires negative VSYNC? */
+- adjusted->flags |= DRM_MODE_FLAG_NVSYNC;
+-
+- /* The TDA19988 requires positive HSYNC on 1080p or 720p */
+- if ((adjusted->hdisplay == 1920 && adjusted->vdisplay == 1080) ||
+- (adjusted->hdisplay == 1280 && adjusted->vdisplay == 720))
+- adjusted->flags |= DRM_MODE_FLAG_PHSYNC;
+- else
+- adjusted->flags |= DRM_MODE_FLAG_NHSYNC;
+-
+ return true;
+ }
+
+@@ -824,11 +541,90 @@ static int
+ tda998x_encoder_mode_valid(struct drm_encoder *encoder,
+ struct drm_display_mode *mode)
+ {
+- DBG("");
+-
+ return MODE_OK;
+ }
+
++
++static void
++tda998x_audio_infoframe_enable(struct drm_encoder *encoder)
++{
++ uint8_t buffer[20];
++ struct hdmi_audio_infoframe audio_frame;
++ size_t len;
++
++ hdmi_audio_infoframe_init(&audio_frame);
++
++ /* NXP audio is fixed at these values for the time being */
++ audio_frame.channels = 2;
++ audio_frame.coding_type = HDMI_AUDIO_CODING_TYPE_PCM;
++ audio_frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_24;
++ audio_frame.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
++
++ len = hdmi_audio_infoframe_pack(&audio_frame, buffer, sizeof(buffer));
++ WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
++
++ reg_write_range(encoder, REG_AUDIO_IF, buffer, len);
++
++ /* enable Audio Infoframe output in DIP_IF Register */
++ reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
++ udelay(5);
++ reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
++}
++
++static void
++tda998x_avi_infoframe_enable(struct drm_encoder *encoder,
++ struct drm_display_mode *mode)
++{
++ uint8_t buffer[20];
++ struct hdmi_avi_infoframe avi_frame;
++ size_t len;
++
++ hdmi_avi_infoframe_init(&avi_frame);
++ avi_frame.video_code = drm_match_cea_mode(mode);
++ avi_frame.picture_aspect = HDMI_PICTURE_ASPECT_NONE;
++ avi_frame.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
++ len = hdmi_avi_infoframe_pack(&avi_frame, buffer, sizeof(buffer));
++ WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
++
++ reg_write_range(encoder, REG_AVI_IF, buffer, len);
++
++ /*
++ * enable AVI Infoframe output in DIP_IF Register, but toggle it
++ * so that the hardware acknowledges that the packet data might have
++ * changed
++ */
++ reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
++ udelay(5);
++ reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
++}
++
++/* lookup table for CEA values to VIDFORMAT values taken from NXP datasheet */
++static char cea_to_nxp_mode[34] = {-1, 0, 1, 1, 2, 3, 4, 4, 5, 5, -1, -1,
++ -1, -1, -1, -1, 6, 7, 7, 8, 9, 10, 10,
++ 11, 11, -1, -1, -1, -1, -1, -1, 12, 13};
++
++static char tda998x_cea_to_vidformat(unsigned char cea_mode)
++{
++ if(cea_mode > (sizeof(cea_to_nxp_mode) -1) ) {
++ return -1;
++ }
++ return cea_to_nxp_mode[cea_mode];
++}
++
++static char tda998x_is_monitor_hdmi(struct drm_encoder *encoder)
++{
++ struct edid *edid = (struct edid *)do_get_edid(encoder);
++ char hdmi = 0;
++ if(edid) {
++ hdmi = drm_detect_hdmi_monitor(edid);
++ kfree(edid);
++ } else {
++ return -1;
++ }
++ return hdmi;
++}
++
++
+ static void
+ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+@@ -875,7 +671,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ /* mute the audio FIFO: */
+ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+
+- /* set HDMI HDCP mode off: */
++ /* HDMI/HDCP mode off... for now...: */
+ reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+ reg_clear(encoder, REG_TX33, TX33_HDMI);
+
+@@ -922,8 +718,8 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
+
+ reg_write(encoder, REG_VIDFORMAT, 0x00);
+- reg_write16(encoder, REG_NPIX_MSB, mode->htotal);
+- reg_write16(encoder, REG_NLINE_MSB, mode->vtotal);
++ reg_write16(encoder, REG_NPIX_MSB, mode->hdisplay - 1);
++ reg_write16(encoder, REG_NLINE_MSB, mode->vdisplay - 1);
+ reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, line_start);
+ reg_write16(encoder, REG_VS_LINE_END_1_MSB, line_end);
+ reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, hs_start);
+@@ -943,29 +739,69 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
+ reg_write16(encoder, REG_REFPIX_MSB, ref_pix);
+ reg_write16(encoder, REG_REFLINE_MSB, ref_line);
+
+- reg = TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
++ reg = TBG_CNTRL_1_VHX_EXT_DE |
++ TBG_CNTRL_1_VHX_EXT_HS |
++ TBG_CNTRL_1_VHX_EXT_VS |
++ TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
+ TBG_CNTRL_1_VH_TGL_2;
+- /*
+- * It is questionable whether this is correct - the nxp driver
+- * does not set VH_TGL_2 and the below for all display modes.
+- */
+ if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC))
+ reg |= TBG_CNTRL_1_VH_TGL_0;
+ reg_set(encoder, REG_TBG_CNTRL_1, reg);
+
+- /* Only setup the info frames if the sink is HDMI */
+- if (priv->is_hdmi_sink) {
+- /* We need to turn HDMI HDCP stuff on to get audio through */
+- reg_clear(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+- reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
++
++
++
++ if(tda998x_is_monitor_hdmi(encoder) == 1) {
++ char vidformat;
++ vidformat = tda998x_cea_to_vidformat(drm_match_cea_mode(mode));
++ if(vidformat == (char)-1) {
++ dev_err(encoder->dev->dev, "Not sure which CEA mode to set, leaving as DVI");
++ goto out;
++ }
++ dev_info(encoder->dev->dev, "Connected to an HDMI monitor with cea mode %d", vidformat);
++
++ /* this is an HDMI monitor, so set things up a bit differently */
++ reg_write(encoder, REG_TBG_CNTRL_1, 0);
++ reg_write(encoder, REG_VIDFORMAT, vidformat);
++ /* get the infoframes pumping */
++ tda998x_avi_infoframe_enable(encoder, mode);
++ tda998x_audio_infoframe_enable(encoder);
+ reg_set(encoder, REG_TX33, TX33_HDMI);
+
+- tda998x_write_avi(encoder, adjusted_mode);
++ /* set up audio registers */
++ reg_write(encoder, REG_ACR_CTS_0, 0x0);
++ reg_write(encoder, REG_ACR_CTS_1, 0x0);
++ reg_write(encoder, REG_ACR_CTS_2, 0x0);
+
+- if (priv->params.audio_cfg)
+- tda998x_configure_audio(encoder, &priv->params);
+- }
++ reg_write(encoder, REG_ACR_N_0, 0x0);
++ reg_write(encoder, REG_ACR_N_1, 0x18);
++ reg_write(encoder, REG_ACR_N_2, 0x0);
++
++ reg_set(encoder, REG_DIP_FLAGS, DIP_FLAGS_ACR);
++
++ reg_write(encoder, REG_ENC_CNTRL, 0x04);
++ reg_write(encoder, REG_CTS_N, 0x33);
++ /* Set 2 channel I2S mode */
++ reg_write(encoder, REG_ENA_AP, 0x3);
++
++ /* set audio divider in pll settings */
++ reg_write(encoder, REG_AUDIO_DIV, 0x2);
+
++ /* select the audio input port clock */
++ reg_write(encoder, REG_AIP_CLKSEL, SEL_AIP_I2S);
++ reg_write(encoder, REG_MUX_AP, MUX_AP_SELECT_I2S);
++
++ /* select I2S format, and datasize */
++ reg_write(encoder, REG_I2S_FORMAT, 0x0a);
++
++ /* enable the audio FIFO: */
++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
++
++ /* mute and then unmute, to get audio going */
++ reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_SETMUTE);
++ reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_CLRMUTE);
++ }
++out:
+ /* must be last register set: */
+ reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
+
+@@ -1029,7 +865,6 @@ read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
+ static uint8_t *
+ do_get_edid(struct drm_encoder *encoder)
+ {
+- struct tda998x_priv *priv = to_tda998x_priv(encoder);
+ int j = 0, valid_extensions = 0;
+ uint8_t *block, *new;
+ bool print_bad_edid = drm_debug & DRM_UT_KMS;
+@@ -1037,9 +872,6 @@ do_get_edid(struct drm_encoder *encoder)
+ if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
+ return NULL;
+
+- if (priv->rev == TDA19988)
+- reg_clear(encoder, REG_TX4, TX4_PD_RAM);
+-
+ /* base block fetch */
+ if (read_edid_block(encoder, block, 0))
+ goto fail;
+@@ -1049,7 +881,7 @@ do_get_edid(struct drm_encoder *encoder)
+
+ /* if there's no extensions, we're done */
+ if (block[0x7e] == 0)
+- goto done;
++ return block;
+
+ new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
+ if (!new)
+@@ -1076,15 +908,9 @@ do_get_edid(struct drm_encoder *encoder)
+ block = new;
+ }
+
+-done:
+- if (priv->rev == TDA19988)
+- reg_set(encoder, REG_TX4, TX4_PD_RAM);
+-
+ return block;
+
+ fail:
+- if (priv->rev == TDA19988)
+- reg_set(encoder, REG_TX4, TX4_PD_RAM);
+ dev_warn(encoder->dev->dev, "failed to read EDID\n");
+ kfree(block);
+ return NULL;
+@@ -1094,14 +920,12 @@ static int
+ tda998x_encoder_get_modes(struct drm_encoder *encoder,
+ struct drm_connector *connector)
+ {
+- struct tda998x_priv *priv = to_tda998x_priv(encoder);
+ struct edid *edid = (struct edid *)do_get_edid(encoder);
+ int n = 0;
+
+ if (edid) {
+ drm_mode_connector_update_edid_property(connector, edid);
+ n = drm_add_edid_modes(connector, edid);
+- priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
+ kfree(edid);
+ }
+
+@@ -1163,59 +987,6 @@ tda998x_remove(struct i2c_client *client)
+ return 0;
+ }
+
+-static ssize_t i2c_read_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+-{
+- struct drm_encoder *encoder = dev_get_drvdata(dev);
+- unsigned int page, addr;
+- unsigned char val;
+-
+- sscanf(buf, "%x %x", &page, &addr);
+-
+- val = reg_read(encoder, REG(page, addr));
+-
+- printk("i2c read %02x @ page:%02x address:%02x\n", val, page, addr);
+- return size;
+-}
+-
+-static ssize_t i2c_write_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+-{
+- struct drm_encoder *encoder = dev_get_drvdata(dev);
+- unsigned int page, addr, mask, val;
+- unsigned char rval;
+-
+- sscanf(buf, "%x %x %x %x", &page, &addr, &mask, &val);
+-
+- rval = reg_read(encoder, REG(page, addr));
+- rval &= ~mask;
+- rval |= val & mask;
+- reg_write(encoder, REG(page, addr), rval);
+-
+- printk("i2c write %02x @ page:%02x address:%02x\n", rval, page, addr);
+- return size;
+-}
+-
+-static ssize_t i2c_dump_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+-{
+- struct drm_encoder *encoder = dev_get_drvdata(dev);
+- unsigned int page;
+- char prefix[16];
+- uint8_t tmp[255];
+-
+- sscanf(buf, "%x", &page);
+-
+- reg_read_range(encoder, REG(page, 0), tmp, 254);
+-
+- snprintf(prefix, sizeof(prefix) - 1, "PG-%02x ", page);
+-
+- print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 16, 1, tmp, 254, false);
+-
+- return size;
+-}
+-
+-static DEVICE_ATTR(i2c_read, S_IWUSR, NULL, i2c_read_store);
+-static DEVICE_ATTR(i2c_write, S_IWUSR, NULL, i2c_write_store);
+-static DEVICE_ATTR(i2c_dump, S_IWUSR, NULL, i2c_dump_store);
+-
+ static int
+ tda998x_encoder_init(struct i2c_client *client,
+ struct drm_device *dev,
+@@ -1223,42 +994,11 @@ tda998x_encoder_init(struct i2c_client *client,
+ {
+ struct drm_encoder *encoder = &encoder_slave->base;
+ struct tda998x_priv *priv;
+- struct tda998x_encoder_params *p;
+-
+-/* debug */
+- device_create_file(&client->dev, &dev_attr_i2c_read);
+- device_create_file(&client->dev, &dev_attr_i2c_write);
+- device_create_file(&client->dev, &dev_attr_i2c_dump);
+- dev_set_drvdata(&client->dev, encoder);
+-/* debug end */
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+- p = &priv->params;
+-#if 0
+- priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
+- priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
+- priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
+-#else
+-
+- *p = default_params;
+-
+- priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
+- (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
+- VIP_CNTRL_0_SWAP_B(p->swap_b) |
+- (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
+- priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
+- (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
+- VIP_CNTRL_1_SWAP_D(p->swap_d) |
+- (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
+- priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
+- (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
+- VIP_CNTRL_2_SWAP_F(p->swap_f) |
+- (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
+-#endif
+-
+ priv->current_page = 0;
+ priv->cec = i2c_new_dummy(client->adapter, 0x34);
+ priv->dpms = DRM_MODE_DPMS_OFF;
+@@ -1356,3 +1096,4 @@ MODULE_LICENSE("GPL");
+
+ module_init(tda998x_init);
+ module_exit(tda998x_exit);
++
diff --git a/patches/linux-3.8.13/0594-tilcdc-More-refined-audio-mode-compatibility-check.patch b/patches/linux-3.8.13/0594-tilcdc-More-refined-audio-mode-compatibility-check.patch
new file mode 100644
index 0000000..0987fc7
--- /dev/null
+++ b/patches/linux-3.8.13/0594-tilcdc-More-refined-audio-mode-compatibility-check.patch
@@ -0,0 +1,69 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 6 Jun 2013 22:55:04 +0300
+Subject: [PATCH] tilcdc: More refined audio mode compatibility check.
+
+Allow audio modes more selectively. This should end up in DT instead
+but it will do for release.
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 30 ++++++++++++++++++++++++++----
+ 1 file changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+index 023092f..375986e 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -440,6 +440,25 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc)
+ return max_width;
+ }
+
++/* this should find it's way to DT */
++static int audio_mode_check(int hdisplay, int vdisplay, int refresh,
++ int cea_mode)
++{
++ /* only cea modes can handle audio */
++ if (cea_mode <= 0)
++ return 0;
++
++ /* hardcoded mode that supports audio (at 24Hz) */
++ if (hdisplay == 1920 && vdisplay == 1080 && refresh == 24)
++ return 1;
++
++ /* from the rest, only those modes that refresh at 50/60 */
++ if (refresh != 50 && refresh != 60)
++ return 0;
++
++ return 1;
++}
++
+ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ int rb_check, int audio, struct edid *edid)
+ {
+@@ -447,6 +466,7 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ unsigned int bandwidth;
+ uint32_t hbp, hfp, hsw, vbp, vfp, vsw;
+ int has_audio, is_cea_mode, can_output_audio, refresh;
++ uint8_t cea_mode;
+
+ int rb;
+
+@@ -469,14 +489,16 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ refresh = drm_mode_vrefresh(mode);
+
+ /* set if it's a cea mode */
+- is_cea_mode = drm_match_cea_mode(mode) > 0;
++ cea_mode = drm_match_cea_mode(mode);
++ is_cea_mode = cea_mode > 0;
+
+ /* set if we can output audio */
+- can_output_audio = edid && has_audio && is_cea_mode &&
+- (refresh == 50 || refresh == 60);
++ can_output_audio = edid && has_audio &&
++ audio_mode_check(mode->hdisplay, mode->vdisplay,
++ refresh, cea_mode);
+
+ DBG("mode %dx%d@%d pixel-clock %d audio %s cea %s can_output %s",
+- mode->hdisplay, mode->vdisplay,refresh,
++ mode->hdisplay, mode->vdisplay, refresh,
+ mode->clock,
+ has_audio ? "true" : "false",
+ is_cea_mode ? "true" : "false",
diff --git a/patches/linux-3.8.13/0595-drm-tilcdc-Implement-whitelist-blacklist-mode-suppor.patch b/patches/linux-3.8.13/0595-drm-tilcdc-Implement-whitelist-blacklist-mode-suppor.patch
new file mode 100644
index 0000000..03c60f1
--- /dev/null
+++ b/patches/linux-3.8.13/0595-drm-tilcdc-Implement-whitelist-blacklist-mode-suppor.patch
@@ -0,0 +1,435 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 12 Jun 2013 11:11:12 +0300
+Subject: [PATCH] drm: tilcdc: Implement whitelist & blacklist mode support
+
+Some modes just don't work; so we need a way to control which ones
+we select. Implement a DT based whitelist & blacklist.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 +-
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 2 +-
+ drivers/gpu/drm/tilcdc/tilcdc_panel.c | 4 +-
+ drivers/gpu/drm/tilcdc/tilcdc_slave.c | 249 +++++++++++++++++++++++++++++++-
+ drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 4 +-
+ 5 files changed, 250 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+index 31e039e..85f972f 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -140,15 +140,15 @@ static int tilcdc_unload(struct drm_device *dev)
+ flush_workqueue(priv->wq);
+ destroy_workqueue(priv->wq);
+
+- dev->dev_private = NULL;
+-
+ pm_runtime_disable(dev->dev);
+
+ list_for_each_entry_safe(mod, cur, &module_list, list) {
+ DBG("destroying module: %s", mod->name);
+- mod->funcs->destroy(mod);
++ mod->funcs->destroy(mod, dev);
+ }
+
++ dev->dev_private = NULL;
++
+ kfree(priv);
+
+ return 0;
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+index 40ff5d4..d869519 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -97,7 +97,7 @@ struct tilcdc_module;
+ struct tilcdc_module_ops {
+ /* create appropriate encoders/connectors: */
+ int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev);
+- void (*destroy)(struct tilcdc_module *mod);
++ void (*destroy)(struct tilcdc_module *mod, struct drm_device *dev);
+ #ifdef CONFIG_DEBUG_FS
+ /* create debugfs nodes (can be NULL): */
+ int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor);
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+index 2aa4a2e..f690583 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+@@ -285,7 +285,7 @@ static int panel_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
+ return 0;
+ }
+
+-static void panel_destroy(struct tilcdc_module *mod)
++static void panel_destroy(struct tilcdc_module *mod, struct drm_device *dev)
+ {
+ struct panel_module *panel_mod = to_panel_module(mod);
+
+@@ -482,7 +482,7 @@ static int panel_probe(struct platform_device *pdev)
+ return 0;
+
+ fail:
+- panel_destroy(mod);
++ panel_destroy(mod, NULL);
+ return ret;
+ }
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+index 440de4e..641aeee 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+@@ -23,12 +23,25 @@
+
+ #include "tilcdc_drv.h"
+
++/* keep a list of text modestrings */
++struct slave_modelist {
++ struct list_head node;
++ const char *modestr; /* the text mode string i.e. 1280x720@50 */
++ struct drm_cmdline_mode clmode; /* the command line mode */
++ struct drm_display_mode *mode; /* the display mode (as seen by the device) */
++ unsigned int parsed : 1; /* parsed (whether good or bad) */
++ unsigned int good : 1; /* it's ok to use it */
++};
++
+ struct slave_module {
+ struct tilcdc_module base;
+ struct tilcdc_panel_info *info;
+ struct i2c_adapter *i2c;
+ struct pinctrl *pinctrl;
+ char *selected_state_name;
++
++ struct list_head whitelist;
++ struct list_head blacklist;
+ };
+ #define to_slave_module(x) container_of(x, struct slave_module, base)
+
+@@ -152,13 +165,152 @@ static int slave_connector_get_modes(struct drm_connector *connector)
+ return get_slave_funcs(encoder)->get_modes(encoder, connector);
+ }
+
++static int slave_modelist_match(struct drm_connector *connector,
++ struct slave_modelist *sml, struct drm_display_mode *mode)
++{
++ struct drm_cmdline_mode *clmode = &sml->clmode;
++
++ if (sml->mode == NULL || !sml->good)
++ return 0;
++
++ /* xres, yres valid */
++ if (clmode->specified &&
++ (drm_mode_width(mode) != clmode->xres ||
++ drm_mode_height(mode) != clmode->yres))
++ return 0;
++
++ /* refresh mode specified */
++ if (clmode->refresh_specified &&
++ drm_mode_vrefresh(mode) != clmode->refresh)
++ return 0;
++
++ /* interlace */
++ if (clmode->interlace && (mode->flags & DRM_MODE_FLAG_INTERLACE) == 0)
++ return 0;
++
++ /* match */
++ return 1;
++}
++
++/* returns 0 if mode is listed, -ENOENT otherwise */
++static int slave_connector_mode_match(struct drm_connector *connector,
++ struct drm_display_mode *mode,
++ struct list_head *lh)
++{
++ struct drm_device *dev = connector->dev;
++ struct slave_modelist *sml;
++ bool parse;
++
++ /* ok, we have to find a match */
++ list_for_each_entry(sml, lh, node) {
++
++ /* if the mode is not parsed, do it now */
++ if (!sml->parsed) {
++
++ /* whether good or bad, we're trying only once */
++ sml->parsed = 1;
++ sml->good = 0;
++
++ parse = drm_mode_parse_command_line_for_connector(
++ sml->modestr, connector, &sml->clmode);
++
++ /* report in case something's off */
++ if (!parse) {
++ dev_err(dev->dev, "Failed to parse mode %s\n",
++ sml->modestr);
++ continue;
++ }
++
++ /* need to hold the mutex */
++ mutex_lock(&dev->mode_config.mutex);
++ sml->mode = drm_mode_create_from_cmdline_mode(dev,
++ &sml->clmode);
++ mutex_unlock(&dev->mode_config.mutex);
++
++ if (sml->mode == NULL) {
++ dev_err(dev->dev, "Failed to create mode %s\n",
++ sml->modestr);
++ continue;
++ }
++ sml->good = 1;
++ }
++
++ /* bad mode is skipped */
++ if (!sml->good)
++ continue;
++
++ /* we can't use drm_mode_equal, we use own own comparison */
++ if (slave_modelist_match(connector, sml, mode)) {
++ return 1;
++ }
++
++ }
++
++ return 0;
++}
++
++static int slave_connector_mode_whitelisted(struct drm_connector *connector,
++ struct drm_display_mode *mode)
++{
++ struct slave_connector *slave_connector = to_slave_connector(connector);
++ struct slave_module *slave_mod = slave_connector->mod;
++ int ret;
++
++ /* if the list is empty, everything is whitelisted */
++ if (list_empty(&slave_mod->whitelist))
++ return 1;
++
++ ret = slave_connector_mode_match(connector, mode, &slave_mod->whitelist);
++ if (ret != 0)
++ return 1;
++
++ /* not found */
++ return 0;
++}
++
++static int slave_connector_mode_blacklisted(struct drm_connector *connector,
++ struct drm_display_mode *mode)
++{
++ struct slave_connector *slave_connector = to_slave_connector(connector);
++ struct slave_module *slave_mod = slave_connector->mod;
++ int ret;
++
++ /* if the list is empty, nothing is blacklisted */
++ if (list_empty(&slave_mod->blacklist))
++ return 0;
++
++ ret = slave_connector_mode_match(connector, mode, &slave_mod->blacklist);
++ if (ret != 0)
++ return 1;
++
++ /* not found; all is OK */
++ return 0;
++}
++
+ static int slave_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+ {
+ struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
+- struct tilcdc_drm_private *priv = connector->dev->dev_private;
++ struct drm_device *dev = connector->dev;
++ struct tilcdc_drm_private *priv = dev->dev_private;
+ int ret;
+
++ /* if there's a whitelist, we must be in it */
++ if (!slave_connector_mode_whitelisted(connector, mode)) {
++ dev_info(dev->dev, "mode %dx%d@%d is not whitelisted\n",
++ drm_mode_width(mode), drm_mode_height(mode),
++ drm_mode_vrefresh(mode));
++ return MODE_BAD;
++ }
++
++ /* if there's a blacklist, we shouldn't be in it */
++ if (slave_connector_mode_blacklisted(connector, mode)) {
++ dev_info(dev->dev, "mode %dx%d@%d is blacklisted\n",
++ drm_mode_width(mode), drm_mode_height(mode),
++ drm_mode_vrefresh(mode));
++ return MODE_BAD;
++ }
++
+ ret = tilcdc_crtc_mode_valid(priv->crtc, mode,
+ priv->allow_non_rblank ? 0 : 1,
+ priv->allow_non_audio ? 0 : 1,
+@@ -254,6 +406,12 @@ static int slave_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+
++ if (priv->num_encoders >= ARRAY_SIZE(priv->encoders))
++ return -ENOENT;
++
++ if (priv->num_connectors >= ARRAY_SIZE(priv->connectors))
++ return -ENOENT;
++
+ encoder = slave_encoder_create(dev, slave_mod);
+ if (!encoder)
+ return -ENOMEM;
+@@ -268,18 +426,33 @@ static int slave_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
+ return 0;
+ }
+
+-static void slave_destroy(struct tilcdc_module *mod)
++static void slave_destroy(struct tilcdc_module *mod, struct drm_device *dev)
+ {
+ struct slave_module *slave_mod = to_slave_module(mod);
++ struct slave_modelist *sml;
+
+ tilcdc_module_cleanup(mod);
++
++ if (dev != NULL) {
++ /* no need to free sml, it's res tracked */
++ list_for_each_entry(sml, &slave_mod->whitelist, node) {
++ if (sml->mode != NULL)
++ drm_mode_destroy(dev, sml->mode);
++ }
++
++ list_for_each_entry(sml, &slave_mod->whitelist, node) {
++ if (sml->mode != NULL)
++ drm_mode_destroy(dev, sml->mode);
++ }
++ }
++
+ kfree(slave_mod->info);
+ kfree(slave_mod);
+ }
+
+ static const struct tilcdc_module_ops slave_module_ops = {
+- .modeset_init = slave_modeset_init,
+- .destroy = slave_destroy,
++ .modeset_init = slave_modeset_init,
++ .destroy = slave_destroy,
+ };
+
+ /*
+@@ -355,10 +528,54 @@ static const struct attribute_group pinmux_attr_group = {
+ .attrs = pinmux_attributes,
+ };
+
++/* fill in the mode list via the string list property */
++static int slave_mode_of_mode_list(struct platform_device *pdev,
++ const char *propname, struct list_head *lh)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *node = dev->of_node;
++ struct slave_modelist *sml;
++ int ret, i, count;
++
++ /* count the string list property */
++ count = of_property_count_strings(node, propname);
++
++ /* negative or zero, means no mode list */
++ if (count <= 0)
++ return 0;
++
++ for (i = 0; i < count; i++) {
++
++ sml = devm_kzalloc(dev, sizeof(*sml), GFP_KERNEL);
++ if (sml == NULL) {
++ dev_err(dev, "Failed to allocate mode list for %s\n",
++ propname);
++ return -ENOMEM;
++ }
++
++ ret = of_property_read_string_index(node, propname, i,
++ &sml->modestr);
++ if (ret != 0) {
++ dev_err(dev, "Failed to read string #%d for %s \n",
++ i, propname);
++ return ret;
++ }
++
++ /* add it to the tail */
++ list_add_tail(&sml->node, lh);
++
++ dev_info(dev, "%s #%d -> %s\n",
++ propname, i, sml->modestr);
++
++ }
++
++ return 0;
++}
++
+ static int slave_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+- struct device_node *node = pdev->dev.of_node;
++ struct device_node *node = dev->of_node;
+ struct device_node *i2c_node;
+ struct slave_module *slave_mod;
+ struct tilcdc_module *mod;
+@@ -379,6 +596,9 @@ static int slave_probe(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, slave_mod);
+
++ INIT_LIST_HEAD(&slave_mod->whitelist);
++ INIT_LIST_HEAD(&slave_mod->blacklist);
++
+ mod = &slave_mod->base;
+
+ tilcdc_module_init(mod, "slave", &slave_module_ops);
+@@ -395,8 +615,9 @@ static int slave_probe(struct platform_device *pdev)
+
+ slave_mod->pinctrl = devm_pinctrl_get(dev);
+ if (IS_ERR(slave_mod->pinctrl)) {
+- dev_err(dev, "Failed to get pinctrl\n");
+ ret = PTR_RET(slave_mod->pinctrl);
++ if (ret != -EPROBE_DEFER)
++ dev_err(dev, "Failed to get pinctrl\n");
+ goto fail;
+ }
+
+@@ -443,12 +664,26 @@ static int slave_probe(struct platform_device *pdev)
+ goto fail;
+ }
+
++ ret = slave_mode_of_mode_list(pdev, "modes-blacklisted",
++ &slave_mod->blacklist);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Invalid modes-blacklisted property\n");
++ goto fail;
++ }
++
++ ret = slave_mode_of_mode_list(pdev, "modes-whitelisted",
++ &slave_mod->whitelist);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Invalid modes-whitelisted property\n");
++ goto fail;
++ }
++
+ of_node_put(i2c_node);
+
+ return 0;
+
+ fail:
+- slave_destroy(mod);
++ slave_destroy(mod, NULL);
+ return ret;
+ }
+
+diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+index c71f955..86fcd1c 100644
+--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+@@ -305,7 +305,7 @@ static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev
+ return 0;
+ }
+
+-static void tfp410_destroy(struct tilcdc_module *mod)
++static void tfp410_destroy(struct tilcdc_module *mod, struct drm_device *dev)
+ {
+ struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
+
+@@ -507,7 +507,7 @@ static int tfp410_probe(struct platform_device *pdev)
+ return 0;
+
+ fail:
+- tfp410_destroy(mod);
++ tfp410_destroy(mod, NULL); /* meh */
+ return ret;
+ }
+
diff --git a/patches/linux-3.8.13/0596-boneblack-Remove-default-pinmuxing-for-MMC1.patch b/patches/linux-3.8.13/0596-boneblack-Remove-default-pinmuxing-for-MMC1.patch
new file mode 100644
index 0000000..d61fdc6
--- /dev/null
+++ b/patches/linux-3.8.13/0596-boneblack-Remove-default-pinmuxing-for-MMC1.patch
@@ -0,0 +1,43 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 18 Apr 2013 12:34:45 +0300
+Subject: [PATCH] boneblack: Remove default pinmuxing for MMC1
+
+The MMC driver already has the right pinmuxing options, remove it
+from here.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-boneblack.dts | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index 1abf267..a35a106 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -11,21 +11,6 @@
+
+ /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} */
+- >;
+-};
+-
+ &ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+@@ -58,4 +43,3 @@
+ 300000 969000
+ >;
+ };
+-
diff --git a/patches/linux-3.8.13/0597-capemgr-Implement-cape-priorities.patch b/patches/linux-3.8.13/0597-capemgr-Implement-cape-priorities.patch
new file mode 100644
index 0000000..1576a13
--- /dev/null
+++ b/patches/linux-3.8.13/0597-capemgr-Implement-cape-priorities.patch
@@ -0,0 +1,276 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 22 Apr 2013 17:11:17 +0300
+Subject: [PATCH] capemgr: Implement cape priorities
+
+Allow capes to define priorities, this is important when you need
+to load built-in capes last, only after all the add-on capes have
+loaded.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 139 +++++++++++++++++++++++++++-----
+ 1 file changed, 119 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 5d87088..820852d 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -43,6 +43,7 @@
+ #include <linux/i2c.h>
+ #include <linux/i2c/eeprom.h>
+ #include <linux/kthread.h>
++#include <linux/wait.h>
+
+ /* extra command line overrides */
+ static char *extra_override = NULL;
+@@ -109,6 +110,9 @@ struct bone_cape_slot {
+
+ /* loader thread */
+ struct task_struct *loader_thread;
++
++ /* load priority */
++ int priority;
+ };
+
+ struct bone_capemap {
+@@ -154,6 +158,9 @@ struct bone_capemgr_info {
+
+ /* baseboard EEPROM data */
+ struct bone_baseboard baseboard;
++
++ /* wait queue for keeping the priorities straight */
++ wait_queue_head_t load_wq;
+ };
+
+ static int bone_slot_fill_override(struct bone_cape_slot *slot,
+@@ -162,6 +169,7 @@ static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ static struct bone_cape_slot *bone_capemgr_add_slot(
+ struct bone_capemgr_info *info, struct device_node *node,
+ const char *part_number, const char *version);
++static int bone_capemgr_remove_slot_no_lock(struct bone_cape_slot *slot);
+ static int bone_capemgr_remove_slot(struct bone_cape_slot *slot);
+ static int bone_capemgr_load(struct bone_cape_slot *slot);
+ static int bone_capemgr_unload(struct bone_cape_slot *slot);
+@@ -1014,7 +1022,7 @@ static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
+ mutex_unlock(&info->slots_list_mutex);
+ return -ENODEV;
+ found:
+- ret = bone_capemgr_remove_slot(slot);
++ ret = bone_capemgr_remove_slot_no_lock(slot);
+ mutex_unlock(&info->slots_list_mutex);
+
+ if (ret == 0)
+@@ -1100,6 +1108,9 @@ found:
+
+ ret = bone_capemgr_load(slot);
+
++ if (ret != 0)
++ bone_capemgr_remove_slot(slot);
++
+ return ret == 0 ? strlen(buf) : ret;
+ err_fail:
+ of_node_put(node);
+@@ -1307,6 +1318,7 @@ err_fail:
+ slot->fw = NULL;
+
+ err_fail_no_fw:
++ slot->loading = 0;
+ return err;
+ }
+
+@@ -1327,7 +1339,7 @@ static int bone_capemgr_unload(struct bone_cape_slot *slot)
+ }
+
+ /* slots_list_mutex must be taken */
+-static int bone_capemgr_remove_slot(struct bone_cape_slot *slot)
++static int bone_capemgr_remove_slot_no_lock(struct bone_cape_slot *slot)
+ {
+ struct bone_capemgr_info *info = slot->info;
+ struct device *dev = &info->pdev->dev;
+@@ -1336,11 +1348,13 @@ static int bone_capemgr_remove_slot(struct bone_cape_slot *slot)
+ if (slot == NULL)
+ return 0;
+
+- /* unload just in case */
+- ret = bone_capemgr_unload(slot);
+- if (ret != 0) {
+- dev_err(dev, "Unable to unload slot #%d\n", slot->slotno);
+- return ret;
++ if (slot->loaded && slot->ovinfo) {
++ /* unload just in case */
++ ret = bone_capemgr_unload(slot);
++ if (ret != 0) {
++ dev_err(dev, "Unable to unload slot #%d\n", slot->slotno);
++ return ret;
++ }
+ }
+
+ /* if probed OK, remove the sysfs nodes */
+@@ -1355,6 +1369,18 @@ static int bone_capemgr_remove_slot(struct bone_cape_slot *slot)
+ return 0;
+ }
+
++static int bone_capemgr_remove_slot(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ int ret;
++
++ mutex_lock(&info->slots_list_mutex);
++ ret = bone_capemgr_remove_slot_no_lock(slot);
++ mutex_unlock(&info->slots_list_mutex);
++
++ return ret;
++}
++
+ static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ struct device_node *node,
+ const char *part_number, const char *version)
+@@ -1362,6 +1388,7 @@ static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ const struct ee_field *sig_field;
+ struct property *prop;
+ int i, len, has_part_number;
++ u32 val;
+ char *p;
+
+ slot->probe_failed = 0;
+@@ -1413,6 +1440,10 @@ static int bone_slot_fill_override(struct bone_cape_slot *slot,
+ if (i == CAPE_EE_FIELD_PART_NUMBER && len > 0)
+ has_part_number = 1;
+ }
++
++ if (of_property_read_u32(node, "priority", &val) != 0)
++ val = 0;
++ slot->priority = val;
+ }
+
+ /* if a part_number is supplied use it */
+@@ -1579,11 +1610,72 @@ err_no_mem:
+ return ERR_PTR(ret);
+ }
+
++static int lowest_loading_cape(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ int my_prio = slot->priority;
++ struct device *dev = &info->pdev->dev;
++ int ret;
++
++ dev_info(dev, "loader: check slot-%d %s:%s (prio %d)\n", slot->slotno,
++ slot->part_number, slot->version, slot->priority);
++
++ mutex_lock(&info->slots_list_mutex);
++ ret = 1;
++ list_for_each_entry(slot, &info->slot_list, node) {
++ /* if any slot is loading with lowest priority */
++ if (!slot->loading)
++ continue;
++ if (slot->priority < my_prio) {
++ ret = 0;
++ break;
++ }
++ }
++ mutex_unlock(&info->slots_list_mutex);
++ return ret;
++}
++
+ static int bone_capemgr_loader(void *data)
+ {
+ struct bone_cape_slot *slot = data;
++ struct bone_capemgr_info *info = slot->info;
++ struct device *dev = &info->pdev->dev;
++ int ret;
++
++ dev_info(dev, "loader: before slot-%d %s:%s (prio %d)\n", slot->slotno,
++ slot->part_number, slot->version, slot->priority);
++
++ /*
++ * We have a basic priority based arbitration system
++ * Slots have priorities, so the lower priority ones
++ * should start loading first. So each time we end up
++ * here.
++ */
++ ret = wait_event_interruptible(info->load_wq,
++ lowest_loading_cape(slot));
++ if (ret < 0) {
++ dev_info(dev, "loader, Signal pending\n");
++ return ret;
++ }
++
++ dev_info(dev, "loader: after slot-%d %s:%s (prio %d)\n", slot->slotno,
++ slot->part_number, slot->version, slot->priority);
++
++ ret = bone_capemgr_load(slot);
++
++ slot->loading = 0;
++
++ dev_info(dev, "loader: done slot-%d %s:%s (prio %d)\n", slot->slotno,
++ slot->part_number, slot->version, slot->priority);
++
++ /* we're done, wake up all */
++ wake_up_interruptible_all(&info->load_wq);
+
+- return bone_capemgr_load(slot);
++ /* not loaded? remove */
++ if (ret != 0)
++ bone_capemgr_remove_slot(slot);
++
++ return ret;
+ }
+
+ static int
+@@ -1623,6 +1715,8 @@ bone_capemgr_probe(struct platform_device *pdev)
+ INIT_LIST_HEAD(&info->capemap_list);
+ mutex_init(&info->capemap_mutex);
+
++ init_waitqueue_head(&info->load_wq);
++
+ baseboardmaps_node = NULL;
+ capemaps_node = NULL;
+
+@@ -1803,21 +1897,26 @@ bone_capemgr_probe(struct platform_device *pdev)
+ continue;
+ }
+
+- if (!slot->probe_failed && !slot->loaded) {
++ if (!slot->probe_failed && !slot->loaded)
+ slot->loading = 1;
+- slot->loader_thread = kthread_run(bone_capemgr_loader,
+- slot, "capemgr-loader-%d",
+- slot->slotno);
+- if (IS_ERR(slot->loader_thread)) {
+- dev_warn(&pdev->dev, "slot #%d: Failed to "
+- "start loader\n", slot->slotno);
+- slot->loader_thread = NULL;
+- }
+- }
+ }
+
+- mutex_unlock(&info->slots_list_mutex);
++ /* now start the loader thread(s) (all at once) */
++ list_for_each_entry(slot, &info->slot_list, node) {
++
++ if (!slot->loading)
++ continue;
+
++ slot->loader_thread = kthread_run(bone_capemgr_loader,
++ slot, "capemgr-loader-%d",
++ slot->slotno);
++ if (IS_ERR(slot->loader_thread)) {
++ dev_warn(&pdev->dev, "slot #%d: Failed to "
++ "start loader\n", slot->slotno);
++ slot->loader_thread = NULL;
++ }
++ }
++ mutex_unlock(&info->slots_list_mutex);
+
+ dev_info(&pdev->dev, "initialized OK.\n");
+
+@@ -1840,7 +1939,7 @@ static int bone_capemgr_remove(struct platform_device *pdev)
+
+ mutex_lock(&info->slots_list_mutex);
+ list_for_each_entry_safe(slot, slotn, &info->slot_list, node)
+- bone_capemgr_remove_slot(slot);
++ bone_capemgr_remove_slot_no_lock(slot);
+ mutex_unlock(&info->slots_list_mutex);
+
+ bone_capemgr_info_sysfs_unregister(info);
diff --git a/patches/linux-3.8.13/0598-rstctl-Reset-control-subsystem.patch b/patches/linux-3.8.13/0598-rstctl-Reset-control-subsystem.patch
new file mode 100644
index 0000000..93be6b9
--- /dev/null
+++ b/patches/linux-3.8.13/0598-rstctl-Reset-control-subsystem.patch
@@ -0,0 +1,1049 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Apr 2013 18:14:52 +0300
+Subject: [PATCH] rstctl: Reset control subsystem
+
+A reset control subsystem. Similar to pinctrl but for handling
+reset conditions.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/Kconfig | 2 +
+ drivers/Makefile | 2 +
+ drivers/rstctl/Kconfig | 30 +++
+ drivers/rstctl/Makefile | 8 +
+ drivers/rstctl/core.c | 368 +++++++++++++++++++++++++++++++++
+ drivers/rstctl/rstctl-gpio.c | 259 +++++++++++++++++++++++
+ drivers/rstctl/rstctl-test-consumer.c | 82 ++++++++
+ drivers/rstctl/rstctl-test.c | 138 +++++++++++++
+ include/linux/rstctl.h | 71 +++++++
+ 9 files changed, 960 insertions(+)
+ create mode 100644 drivers/rstctl/Kconfig
+ create mode 100644 drivers/rstctl/Makefile
+ create mode 100644 drivers/rstctl/core.c
+ create mode 100644 drivers/rstctl/rstctl-gpio.c
+ create mode 100644 drivers/rstctl/rstctl-test-consumer.c
+ create mode 100644 drivers/rstctl/rstctl-test.c
+ create mode 100644 include/linux/rstctl.h
+
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index f5fb072..0e8852a 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -158,4 +158,6 @@ source "drivers/irqchip/Kconfig"
+
+ source "drivers/ipack/Kconfig"
+
++source "drivers/rstctl/Kconfig"
++
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index 7863b9f..8c50114 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -11,6 +11,8 @@ obj-y += bus/
+ # GPIO must come after pinctrl as gpios may need to mux pins etc
+ obj-y += pinctrl/
+ obj-y += gpio/
++# similarly rstctl must come very early
++obj-y += rstctl/
+ obj-y += pwm/
+ obj-$(CONFIG_PCI) += pci/
+ obj-$(CONFIG_PARISC) += parisc/
+diff --git a/drivers/rstctl/Kconfig b/drivers/rstctl/Kconfig
+new file mode 100644
+index 0000000..b943253
+--- /dev/null
++++ b/drivers/rstctl/Kconfig
+@@ -0,0 +1,30 @@
++#
++# RSTCTL infrastructure and drivers
++#
++
++menuconfig RSTCTL
++ bool "Reset control subsystem"
++ help
++ Select this to enable the reset control subsystem
++
++if RSTCTL
++
++config RSTCTL_GPIO
++ tristate "GPIO reset driver"
++ depends on RSTCTL
++ help
++ This selects the GPIO based reset driver
++
++config RSTCTL_TEST
++ tristate "Test reset driver"
++ depends on RSTCTL
++ help
++ This selects the test reset driver
++
++config RSTCTL_TEST_CONSUMER
++ tristate "Test reset consumer driver"
++ depends on RSTCTL
++ help
++ This select the test reset consumer driver
++
++endif
+diff --git a/drivers/rstctl/Makefile b/drivers/rstctl/Makefile
+new file mode 100644
+index 0000000..26dfcf6
+--- /dev/null
++++ b/drivers/rstctl/Makefile
+@@ -0,0 +1,8 @@
++# rstctl support
++
++ccflags-$(CONFIG_DEBUG_RSTCTL) += -DDEBUG
++
++obj-$(CONFIG_RSTCTL) += core.o
++obj-$(CONFIG_RSTCTL_TEST) += rstctl-test.o
++obj-$(CONFIG_RSTCTL_TEST_CONSUMER) += rstctl-test-consumer.o
++obj-$(CONFIG_RSTCTL_GPIO) += rstctl-gpio.o
+diff --git a/drivers/rstctl/core.c b/drivers/rstctl/core.c
+new file mode 100644
+index 0000000..a3f02c2
+--- /dev/null
++++ b/drivers/rstctl/core.c
+@@ -0,0 +1,368 @@
++/*
++ * Core driver for the reset control subsystem
++ *
++ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Based on bits of rstctl, regulator core, gpio core and clk core
++ *
++ * License terms: GNU General Public License (GPL) version 2
++ */
++#define pr_fmt(fmt) "rstctl core: " fmt
++
++#include <linux/kernel.h>
++#include <linux/export.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/list.h>
++#include <linux/sysfs.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++
++#include <linux/rstctl.h>
++
++static inline int reset_request(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ /* no request op? */
++ if (rdev->rdesc->ops->request == NULL)
++ return 0;
++
++ return rdev->rdesc->ops->request(rdev, line);
++}
++
++static inline int reset_release(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ /* no release op? */
++ if (rdev->rdesc->ops->release == NULL)
++ return 0;
++
++ return rdev->rdesc->ops->release(rdev, line);
++}
++
++static inline int reset_assert(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ return rdev->rdesc->ops->assert(rdev, line);
++}
++
++static inline int reset_deassert(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ return rdev->rdesc->ops->deassert(rdev, line);
++}
++
++static inline int reset_pulse(struct rstctl_dev *rdev,
++ const struct rstctl_line *line,
++ unsigned long hold_ns)
++{
++ return rdev->rdesc->ops->pulse(rdev, line, hold_ns);
++}
++
++int rstctl_assert(struct rstctl *rctrl)
++{
++ if (IS_ERR_OR_NULL(rctrl))
++ return -EINVAL;
++ return reset_assert(rctrl->rdev, rctrl->line);
++}
++EXPORT_SYMBOL(rstctl_assert);
++
++int rstctl_deassert(struct rstctl *rctrl)
++{
++ if (IS_ERR_OR_NULL(rctrl))
++ return -EINVAL;
++ return reset_deassert(rctrl->rdev, rctrl->line);
++}
++EXPORT_SYMBOL(rstctl_deassert);
++
++int rstctl_pulse(struct rstctl *rctrl, unsigned long hold_ns)
++{
++ if (IS_ERR_OR_NULL(rctrl))
++ return -EINVAL;
++ return reset_pulse(rctrl->rdev, rctrl->line, hold_ns);
++}
++EXPORT_SYMBOL(rstctl_pulse);
++
++/* Mutex taken by all entry points */
++static DEFINE_MUTEX(rstctl_lock);
++
++/* Global list of reset control devices (struct rstctl_dev) */
++static LIST_HEAD(rstctl_dev_list);
++
++static struct rstctl *rstctl_request_line(struct rstctl_dev *rdev,
++ struct device *dev, const struct rstctl_line *line)
++{
++ struct rstctl *rctrl;
++ int index, err;
++
++ index = line - rdev->rdesc->lines;
++
++ /* find if it's already requested */
++ list_for_each_entry(rctrl, &rdev->handles, node) {
++ /* retreive index from the point */
++ if (rctrl->line == line) {
++ dev_err(dev, "Reset %s:%d already requested\n",
++ rdev->rdesc->name, index);
++ return ERR_PTR(-EEXIST);
++ }
++ }
++
++ /* request from the driver */
++ err = reset_request(rdev, line);
++ if (err != 0) {
++ dev_err(dev, "reset_request on %s:%d failed\n",
++ rdev->rdesc->name, index);
++ return ERR_PTR(err);
++ }
++
++ /* allocate */
++ rctrl = kzalloc(sizeof(*rctrl), GFP_KERNEL);
++ if (rctrl == NULL) {
++ dev_err(dev, "Out of memory on %s:%d request\n",
++ rdev->rdesc->name, index);
++ reset_release(rdev, line);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ INIT_LIST_HEAD(&rctrl->node);
++ rctrl->rdev = rdev;
++ rctrl->dev = dev;
++ rctrl->line = line;
++
++ /* add it to the handle list */
++ list_add_tail(&rctrl->node, &rdev->handles);
++
++ return rctrl;
++}
++
++#ifdef CONFIG_OF
++
++static struct rstctl_dev *of_node_to_rstctl_dev(struct device_node *np)
++{
++ struct rstctl_dev *rdev;
++
++ list_for_each_entry(rdev, &rstctl_dev_list, node) {
++ if (rdev->dev && rdev->dev->of_node == np)
++ return rdev;
++ }
++
++ return ERR_PTR(-EPROBE_DEFER);
++}
++
++static struct rstctl *of_rstctl_get(struct device *dev, const char *id)
++{
++ struct device_node *np;
++ struct rstctl *rctrl;
++ struct rstctl_dev *rdev;
++ const struct rstctl_line *line;
++ struct of_phandle_args args;
++ int index, lineidx, err;
++
++ /* sanity check */
++ if (dev == NULL || dev->of_node == NULL)
++ return NULL;
++ np = dev->of_node;
++
++ index = 0;
++ if (id != NULL) {
++ err = of_property_match_string(np, "reset-names", id);
++ if (err < 0) {
++ dev_err(dev, "of_property_match of 'reset-names' failed\n");
++ rctrl = ERR_PTR(err);
++ goto out;
++ }
++ index = err;
++ }
++
++ err = of_parse_phandle_with_args(np, "reset", "#reset-cells", index,
++ &args);
++ if (err != 0) {
++ dev_err(dev, "of_parse_phandle_with_args of 'reset' failed\n");
++ rctrl = ERR_PTR(err);
++ goto out;
++ }
++
++ mutex_lock(&rstctl_lock);
++
++ rdev = of_node_to_rstctl_dev(args.np);
++ if (IS_ERR_OR_NULL(rdev)) {
++ dev_err(dev, "rstctl node not found\n");
++ rctrl = rdev == NULL ? ERR_PTR(-EINVAL) : (void *)rdev;
++ goto out_unlock;
++ }
++
++ if (args.args_count != 2) {
++ dev_err(dev, "#reset-cells not %d\n", 2);
++ rctrl = ERR_PTR(-EINVAL);
++ goto out_unlock;
++ }
++
++ lineidx = args.args[0];
++ /* make sure it's one we handle */
++ if (lineidx < 0 || lineidx >= rdev->rdesc->nlines) {
++ dev_err(dev, "Illegal reset #%d\n", lineidx);
++ rctrl = ERR_PTR(-EINVAL);
++ goto out_unlock;
++ }
++ line = &rdev->rdesc->lines[lineidx];
++
++ rctrl = rstctl_request_line(rdev, dev, line);
++ if (IS_ERR(rctrl)) {
++ dev_err(dev, "rstctl_request_line failed\n");
++ goto out_unlock;
++ }
++
++ /* put the label in */
++ err = of_property_read_string_index(np, "reset-names", index,
++ &rctrl->label);
++ if (err != 0)
++ rctrl->label = np->name;
++
++out_unlock:
++ mutex_unlock(&rstctl_lock);
++out:
++ return rctrl;
++}
++#else
++static inline struct rstctl *of_rstctl_get(struct device *dev,
++ const char *id)
++{
++ return NULL;
++}
++#endif
++
++struct rstctl *rstctl_get(struct device *dev, const char *id)
++{
++ struct rstctl_dev *rdev;
++ struct rstctl *rctrl;
++ const struct rstctl_line *line;
++ int i;
++
++ /* DT case goes through here */
++ if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
++ return of_rstctl_get(dev, id);
++
++ /* non DT case does not support id == NULL */
++ if (id == NULL) {
++ dev_err(dev, "No reset ID supplied\n");
++ return ERR_PTR(-EINVAL);
++ }
++
++ /*
++ * We search all the rstctl devices for a match
++ * with the given label id
++ */
++ mutex_lock(&rstctl_lock);
++ list_for_each_entry(rdev, &rstctl_dev_list, node) {
++ for (i = 0; i < rdev->rdesc->nlines; i++) {
++ line = &rdev->rdesc->lines[i];
++ if (strcmp(line->name, id) == 0) {
++ rctrl = rstctl_request_line(rdev, dev, line);
++ goto out;
++ }
++ }
++ }
++ rctrl = ERR_PTR(-ENODEV);
++out:
++ mutex_unlock(&rstctl_lock);
++
++ return rctrl;
++}
++EXPORT_SYMBOL(rstctl_get);
++
++void rstctl_put(struct rstctl *rctrl)
++{
++ struct rstctl_dev *rdev;
++ struct rstctl *rctrlt;
++
++ /* safe */
++ if (IS_ERR_OR_NULL(rctrl))
++ return;
++ rdev = rctrl->rdev;
++
++ mutex_lock(&rstctl_lock);
++ list_for_each_entry(rctrlt, &rdev->handles, node) {
++ if (rctrlt == rctrl)
++ goto found;
++ }
++ goto out;
++found:
++ /* release the reset */
++ reset_release(rctrl->rdev, rctrl->line);
++ list_del(&rctrl->node);
++ kfree(rctrl);
++out:
++ mutex_unlock(&rstctl_lock);
++}
++EXPORT_SYMBOL(rstctl_put);
++
++struct rstctl_dev *rstctl_register(struct device *dev,
++ const struct rstctl_desc *rdesc)
++{
++ struct rstctl_dev *rdev;
++
++ /* sanity check */
++ if (dev == NULL || rdesc == NULL || rdesc->ops == NULL)
++ return ERR_PTR(-EINVAL);
++
++ /* those three must be defined */
++ if (rdesc->ops->assert == NULL || rdesc->ops->deassert == NULL
++ || rdesc->ops->pulse == NULL)
++ return ERR_PTR(-EINVAL);
++
++ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
++ if (rdev == NULL) {
++ dev_err(dev, "failed to alloc struct rstctl_dev\n");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ INIT_LIST_HEAD(&rdev->node);
++ rdev->dev = dev;
++ rdev->rdesc = rdesc;
++ INIT_LIST_HEAD(&rdev->handles);
++
++ mutex_lock(&rstctl_lock);
++ list_add_tail(&rdev->node, &rstctl_dev_list);
++ mutex_unlock(&rstctl_lock);
++
++ return rdev;
++}
++
++int rstctl_unregister(struct rstctl_dev *rdev)
++{
++ int err;
++
++ /* guard */
++ if (IS_ERR_OR_NULL(rdev))
++ return -EINVAL;
++
++ err = 0;
++
++ mutex_lock(&rstctl_lock);
++
++ if (!list_empty(&rdev->handles)) {
++ dev_err(rdev->dev, "%s still busy\n", rdev->rdesc->name);
++ err = -EBUSY;
++ goto out;
++ }
++ list_del(&rdev->node);
++
++ /* free */
++ kfree(rdev);
++
++ mutex_unlock(&rstctl_lock);
++
++out:
++ mutex_unlock(&rstctl_lock);
++ return err;
++}
++
++static int __init rstctl_init(void)
++{
++ pr_info("initialized rstctl subsystem\n");
++ return 0;
++}
++
++/* init early, resetting is needed pretty early */
++core_initcall(rstctl_init);
+diff --git a/drivers/rstctl/rstctl-gpio.c b/drivers/rstctl/rstctl-gpio.c
+new file mode 100644
+index 0000000..4f3b5c1
+--- /dev/null
++++ b/drivers/rstctl/rstctl-gpio.c
+@@ -0,0 +1,259 @@
++/*
++ * Test driver for rstctl
++ *
++ * Author: Pantelis Antoniou <panto@antoniou-consulting.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/rstctl.h>
++#include <linux/of.h>
++#include <linux/of_gpio.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/delay.h>
++#include <linux/pinctrl/consumer.h>
++
++struct gpio_data {
++ int gpio;
++ enum of_gpio_flags flags;
++ int hold_ns;
++};
++
++struct gpio_rctrl_info {
++ struct rstctl_dev *rdev;
++ struct rstctl_desc desc;
++ struct gpio_data *gpio_data;
++};
++
++int gpio_rctrl_request(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ struct device *dev = rdev->dev;
++ const struct gpio_data *gd = line->data;
++ unsigned long flags;
++ int err;
++
++ dev_info(dev, "%s %s\n", __func__, line->name);
++
++ flags = GPIOF_DIR_OUT;
++ if (gd->flags & OF_GPIO_ACTIVE_LOW)
++ flags |= GPIOF_INIT_LOW;
++ else
++ flags |= GPIOF_INIT_HIGH;
++ /* XXX more flags ? */
++
++ err = devm_gpio_request_one(dev, gd->gpio, flags, line->name);
++ if (err != 0) {
++ dev_err(dev, "Failed to gpio_request\n");
++ return err;
++ }
++ return 0;
++}
++
++int gpio_rctrl_release(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ struct device *dev = rdev->dev;
++ const struct gpio_data *gd = line->data;
++
++ dev_info(dev, "%s %s\n", __func__, line->name);
++ devm_gpio_free(dev, gd->gpio);
++ return 0;
++}
++
++int gpio_rctrl_assert(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ struct device *dev = rdev->dev;
++ const struct gpio_data *gd = line->data;
++
++ dev_info(dev, "%s %s\n", __func__, line->name);
++ gpio_set_value(gd->gpio,
++ (gd->flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1);
++ return 0;
++}
++
++int gpio_rctrl_deassert(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ struct device *dev = rdev->dev;
++ const struct gpio_data *gd = line->data;
++
++ dev_info(dev, "%s %s\n", __func__, line->name);
++ gpio_set_value(gd->gpio,
++ (gd->flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0);
++ return 0;
++}
++
++int gpio_rctrl_pulse(struct rstctl_dev *rdev,
++ const struct rstctl_line *line,
++ unsigned long hold_ns)
++{
++ struct device *dev = rdev->dev;
++ const struct gpio_data *gd = line->data;
++
++ dev_info(dev, "%s %s\n", __func__, line->name);
++
++ gpio_set_value(gd->gpio,
++ (gd->flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1);
++
++ if (hold_ns == 0)
++ hold_ns = gd->hold_ns;
++
++ if (hold_ns < 1000000)
++ ndelay(hold_ns);
++ else
++ mdelay(hold_ns / 1000000);
++
++ gpio_set_value(gd->gpio,
++ (gd->flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0);
++ return 0;
++}
++
++static const struct rstctl_ops gpio_rctrl_ops = {
++ .request = gpio_rctrl_request,
++ .release = gpio_rctrl_release,
++ .assert = gpio_rctrl_assert,
++ .deassert = gpio_rctrl_deassert,
++ .pulse = gpio_rctrl_pulse,
++};
++
++static int gpio_rctrl_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct gpio_rctrl_info *info;
++ struct rstctl_line *line, *lines;
++ struct gpio_data *gdata, *gd;
++ struct pinctrl *pinctrl;
++ int count, i, err;
++
++ /* we require OF */
++ if (!IS_ENABLED(CONFIG_OF) || np == NULL) {
++ dev_err(dev, "GPIO rstctl requires DT\n");
++ return -ENODEV;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(dev, "Unable to select pin group\n");
++
++ count = of_gpio_named_count(np, "gpios");
++ if (count == 0) {
++ dev_err(dev, "GPIO rstctl found no GPIO resources\n");
++ return -ENODEV;
++ }
++
++ if (of_property_count_strings(np, "gpio-names") != count) {
++ dev_err(dev, "GPIO rstctl gpio-names property is invalid\n");
++ return -ENODEV;
++ }
++
++ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
++ if (!info) {
++ dev_err(dev, "GPIO rstctl kzalloc failed\n");
++ return -ENOMEM;
++ }
++ lines = devm_kzalloc(dev, sizeof(*line) * count, GFP_KERNEL);
++ if (!lines) {
++ dev_err(dev, "GPIO rstctl kzalloc failed\n");
++ return -ENOMEM;
++ }
++ gdata = devm_kzalloc(dev, sizeof(*gdata) * count, GFP_KERNEL);
++ if (!gdata) {
++ dev_err(dev, "GPIO rstctl kzalloc failed\n");
++ return -ENOMEM;
++ }
++
++ info->desc.name = "gpio";
++ info->desc.ops = &gpio_rctrl_ops;
++ info->desc.nlines = count;
++ info->desc.lines = lines;
++ info->gpio_data = gdata;
++
++ for (i = 0; i < count; i++) {
++ line = &lines[i];
++ err = of_property_read_string_index(np, "gpio-names",
++ i, &line->name);
++ if (err != 0) {
++ dev_err(dev, "Failed to get string property\n");
++ return err;
++ }
++
++ gd = &gdata[i];
++ err = of_get_named_gpio_flags(np, "gpios", i, &gd->flags);
++ if (IS_ERR_VALUE(err)) {
++ dev_err(dev, "Failed to get named gpio\n");
++ return err;
++ }
++ gd->gpio = err;
++ gd->hold_ns = 1000; /* 1us reset */
++ line->data = gd;
++ }
++
++ info->rdev = rstctl_register(&pdev->dev, &info->desc);
++ if (IS_ERR(info->rdev)) {
++ dev_err(&pdev->dev, "failed to register\n");
++ return PTR_ERR(info->rdev);
++ }
++ platform_set_drvdata(pdev, info);
++
++ dev_info(&pdev->dev, "loaded OK\n");
++
++ return 0;
++}
++
++static int gpio_rctrl_remove(struct platform_device *pdev)
++{
++ struct gpio_rctrl_info *info = platform_get_drvdata(pdev);
++ int err;
++
++ err = rstctl_unregister(info->rdev);
++ if (err == 0)
++ dev_info(&pdev->dev, "removed OK\n");
++
++ return err;
++}
++
++#ifdef CONFIG_OF
++static struct of_device_id gpio_rctrl_of_match[] = {
++ { .compatible = "gpio-rctrl" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, gpio_rctrl_of_match);
++#endif
++
++static struct platform_driver gpio_rctrl_driver = {
++ .driver = {
++ .name = "gpio-rctrl",
++ .of_match_table = of_match_ptr(gpio_rctrl_of_match),
++ },
++ .probe = gpio_rctrl_probe,
++ .remove = gpio_rctrl_remove,
++};
++
++/*
++ * The reset control driver must be done very early.
++ */
++static int __init gpio_rctrl_drv_reg(void)
++{
++ return platform_driver_register(&gpio_rctrl_driver);
++}
++postcore_initcall(gpio_rctrl_drv_reg);
++
++MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
++MODULE_DESCRIPTION("rstctl GPIO driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/rstctl/rstctl-test-consumer.c b/drivers/rstctl/rstctl-test-consumer.c
+new file mode 100644
+index 0000000..dd26ca1
+--- /dev/null
++++ b/drivers/rstctl/rstctl-test-consumer.c
+@@ -0,0 +1,82 @@
++/*
++ * Test consumer driver for rstctl
++ *
++ * Author: Pantelis Antoniou <panto@antoniou-consulting.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/rstctl.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++
++static int test_consumer_rctrl_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct rstctl *rctrl;
++
++ dev_info(dev, "Trying to get NULL (OF case only)\n");
++ rctrl = rstctl_get(dev, NULL);
++ if (IS_ERR(rctrl)) {
++ dev_info(dev, "Failed to get it\n");
++ return PTR_ERR(rctrl);
++ }
++
++ dev_info(dev, "Got it (%s:#%d name %s) label:%s\n",
++ rctrl->rdev->rdesc->name,
++ rctrl->line - rctrl->rdev->rdesc->lines,
++ rctrl->line->name, rctrl->label);
++
++ /* for now always assert */
++ rstctl_assert(rctrl);
++ platform_set_drvdata(pdev, rctrl);
++
++ dev_info(&pdev->dev, "loaded OK\n");
++ return 0;
++}
++
++static int test_consumer_rctrl_remove(struct platform_device *pdev)
++{
++ struct rstctl *rctrl = platform_get_drvdata(pdev);
++
++ rstctl_deassert(rctrl);
++ rstctl_put(rctrl);
++
++ dev_info(&pdev->dev, "unloaded OK\n");
++ return 0;
++}
++
++#ifdef CONFIG_OF
++static struct of_device_id test_consumer_rctrl_of_match[] = {
++ { .compatible = "test-consumer-rctrl" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, test_consumer_rctrl_of_match);
++#endif
++
++static struct platform_driver test_consumer_rctrl_driver = {
++ .driver = {
++ .name = "test-consumer-rctrl",
++ .of_match_table = of_match_ptr(test_consumer_rctrl_of_match),
++ },
++ .probe = test_consumer_rctrl_probe,
++ .remove = test_consumer_rctrl_remove,
++};
++module_platform_driver(test_consumer_rctrl_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
++MODULE_DESCRIPTION("rstctl test consumer driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/rstctl/rstctl-test.c b/drivers/rstctl/rstctl-test.c
+new file mode 100644
+index 0000000..144c048
+--- /dev/null
++++ b/drivers/rstctl/rstctl-test.c
+@@ -0,0 +1,138 @@
++/*
++ * Test driver for rstctl
++ *
++ * Author: Pantelis Antoniou <panto@antoniou-consulting.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.
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/rstctl.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++
++struct test_rctrl_info {
++ struct rstctl_dev *rdev;
++};
++
++int test_rctrl_request(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ dev_info(rdev->dev, "%s %s\n", __func__, line->name);
++ return 0;
++}
++
++int test_rctrl_release(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ dev_info(rdev->dev, "%s %s\n", __func__, line->name);
++ return 0;
++}
++
++int test_rctrl_assert(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ dev_info(rdev->dev, "%s %s\n", __func__, line->name);
++ return 0;
++}
++
++int test_rctrl_deassert(struct rstctl_dev *rdev,
++ const struct rstctl_line *line)
++{
++ dev_info(rdev->dev, "%s %s\n", __func__, line->name);
++ return 0;
++}
++
++int test_rctrl_pulse(struct rstctl_dev *rdev,
++ const struct rstctl_line *line,
++ unsigned long hold_ns)
++{
++ dev_info(rdev->dev, "%s %s\n", __func__, line->name);
++ return 0;
++}
++
++static const struct rstctl_ops test_rctrl_ops = {
++ .request = test_rctrl_request,
++ .release = test_rctrl_release,
++ .assert = test_rctrl_assert,
++ .deassert = test_rctrl_deassert,
++ .pulse = test_rctrl_pulse,
++};
++
++static const struct rstctl_line test_rctrl_lines[] = {
++ { .name = "RESET1", },
++ { .name = "RESET2", },
++};
++
++static const struct rstctl_desc test_rctrl_desc = {
++ .name = "test",
++ .ops = &test_rctrl_ops,
++ .nlines = ARRAY_SIZE(test_rctrl_lines),
++ .lines = test_rctrl_lines,
++};
++
++static int test_rctrl_probe(struct platform_device *pdev)
++{
++ struct test_rctrl_info *info;
++
++ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ info->rdev = rstctl_register(&pdev->dev, &test_rctrl_desc);
++ if (IS_ERR(info->rdev)) {
++ dev_err(&pdev->dev, "failed to register\n");
++ return PTR_ERR(info->rdev);
++ }
++ platform_set_drvdata(pdev, info);
++
++ dev_info(&pdev->dev, "loaded OK\n");
++
++ return 0;
++}
++
++static int test_rctrl_remove(struct platform_device *pdev)
++{
++ struct test_rctrl_info *info = platform_get_drvdata(pdev);
++ int err;
++
++ err = rstctl_unregister(info->rdev);
++ if (err == 0)
++ dev_info(&pdev->dev, "removed OK\n");
++
++ return err;
++}
++
++#ifdef CONFIG_OF
++static struct of_device_id test_rctrl_of_match[] = {
++ { .compatible = "test-rctrl" },
++ { },
++};
++MODULE_DEVICE_TABLE(of, test_rctrl_of_match);
++#endif
++
++static struct platform_driver test_rctrl_driver = {
++ .driver = {
++ .name = "test-rctrl",
++ .of_match_table = of_match_ptr(test_rctrl_of_match),
++ },
++ .probe = test_rctrl_probe,
++ .remove = test_rctrl_remove,
++};
++module_platform_driver(test_rctrl_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
++MODULE_DESCRIPTION("rstctl test driver");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/rstctl.h b/include/linux/rstctl.h
+new file mode 100644
+index 0000000..b2e674a
+--- /dev/null
++++ b/include/linux/rstctl.h
+@@ -0,0 +1,71 @@
++/*
++ * Reset control subsystem
++ *
++ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
++ *
++ * License terms: GNU General Public License (GPL) version 2
++ */
++#ifndef __LINUX_RSTCTL_H
++#define __LINUX_RSTCTL_H
++
++#include <linux/of.h>
++#include <linux/list.h>
++
++struct rstctl_dev;
++
++struct rstctl_line {
++ const char *name;
++ void *data;
++};
++
++struct rstctl_ops {
++ int (*request)(struct rstctl_dev *rdev,
++ const struct rstctl_line *line);
++ int (*release)(struct rstctl_dev *rdev,
++ const struct rstctl_line *line);
++ int (*assert)(struct rstctl_dev *rdev,
++ const struct rstctl_line *line);
++ int (*deassert)(struct rstctl_dev *rdev,
++ const struct rstctl_line *line);
++ int (*pulse)(struct rstctl_dev *rdev,
++ const struct rstctl_line *line,
++ unsigned long hold_ns);
++ struct module *owner;
++};
++
++struct rstctl_desc {
++ const char *name;
++ const struct rstctl_ops *ops;
++ int nlines;
++ const struct rstctl_line *lines;
++};
++
++struct rstctl_dev {
++ struct list_head node;
++ struct device *dev;
++ const struct rstctl_desc *rdesc;
++ struct list_head handles;
++};
++
++struct rstctl {
++ struct list_head node; /* linked all in */
++ struct device *dev; /* the user */
++ struct rstctl_dev *rdev; /* the controler */
++ const struct rstctl_line *line;
++ const char *label;
++};
++
++/* driver API */
++struct rstctl_dev *rstctl_register(struct device *dev,
++ const struct rstctl_desc *rdesc);
++int rstctl_unregister(struct rstctl_dev *rdev);
++
++/* consumer API */
++struct rstctl *rstctl_get(struct device *dev, const char *id);
++void rstctl_put(struct rstctl *rctrl);
++
++int rstctl_assert(struct rstctl *rctrl);
++int rstctl_deassert(struct rstctl *rctrl);
++int rstctl_pulse(struct rstctl *rctrl, unsigned long hold_ns);
++
++#endif
diff --git a/patches/linux-3.8.13/0599-omap_hsmmc-Enable-rstctl-bindings.patch b/patches/linux-3.8.13/0599-omap_hsmmc-Enable-rstctl-bindings.patch
new file mode 100644
index 0000000..8e278f4
--- /dev/null
+++ b/patches/linux-3.8.13/0599-omap_hsmmc-Enable-rstctl-bindings.patch
@@ -0,0 +1,82 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 22 Apr 2013 20:32:40 +0300
+Subject: [PATCH] omap_hsmmc: Enable rstctl bindings.
+
+Use the rstctl resource if that's available. If not, don't
+probe the device.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 7a35c8e..f6f5875 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -44,6 +44,7 @@
+ #include <linux/err.h>
+ #include <mach/hardware.h>
+ #include <plat/cpu.h>
++#include <linux/rstctl.h>
+
+ /* OMAP HSMMC Host Controller Registers */
+ #define OMAP_HSMMC_SYSSTATUS 0x0014
+@@ -187,6 +188,8 @@ struct omap_hsmmc_host {
+ struct omap_hsmmc_next next_data;
+
+ struct omap_mmc_platform_data *pdata;
++
++ struct rstctl *rstctl;
+ };
+
+ static int omap_hsmmc_card_detect(struct device *dev, int slot)
+@@ -1810,6 +1813,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ unsigned tx_req, rx_req;
+ struct dmaengine_chan_caps *dma_chan_caps;
+ struct pinctrl *pinctrl;
++ struct rstctl *rctrl;
+
+ match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
+ if (match) {
+@@ -1830,6 +1834,24 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ return -ENXIO;
+ }
+
++ /* request reset control (bail if deffering) */
++ rctrl = rstctl_get(&pdev->dev, NULL);
++ if (IS_ERR(rctrl)) {
++ if (PTR_ERR(rctrl) == -EPROBE_DEFER) {
++ dev_info(&pdev->dev, "Loading deferred\n");
++ return -EPROBE_DEFER;
++ }
++ dev_info(&pdev->dev, "Failed to get rstctl\n");
++ rctrl = NULL;
++ } else {
++ dev_info(&pdev->dev, "Got rstctl (%s:#%d name %s) label:%s\n",
++ rctrl->rdev->rdesc->name,
++ rctrl->line - rctrl->rdev->rdesc->lines,
++ rctrl->line->name, rctrl->label);
++
++ rstctl_deassert(rctrl);
++ }
++
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev, "unable to select pin group\n");
+@@ -1865,6 +1887,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ host->base = ioremap(host->mapbase, SZ_4K);
+ host->power_mode = MMC_POWER_OFF;
+ host->next_data.cookie = 1;
++ host->rstctl = rctrl;
+
+ platform_set_drvdata(pdev, host);
+
+@@ -2130,6 +2153,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
+
+ omap_hsmmc_gpio_free(host->pdata);
+ iounmap(host->base);
++ rstctl_put(host->rstctl);
+ mmc_free_host(host->mmc);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/patches/linux-3.8.13/0600-bone-Add-rstctl-DT-binding-for-beaglebone.patch b/patches/linux-3.8.13/0600-bone-Add-rstctl-DT-binding-for-beaglebone.patch
new file mode 100644
index 0000000..ca8f3d8
--- /dev/null
+++ b/patches/linux-3.8.13/0600-bone-Add-rstctl-DT-binding-for-beaglebone.patch
@@ -0,0 +1,77 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 22 Apr 2013 20:36:35 +0300
+Subject: [PATCH] bone: Add rstctl DT binding for beaglebone
+
+Add a reset control resource for the eMMC's reset GPIO.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 6 ++++++
+ arch/arm/boot/dts/am335x-boneblack.dts | 24 ++++++++++++++++++++++++
+ 2 files changed, 30 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 89ec6f2..e341a08 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -50,6 +50,12 @@
+ };
+
+ ocp: ocp {
++
++ /* reset controller comes first (even if disabled) */
++ rstctl: rstctl@0 {
++ status = "disabled";
++ };
++
+ uart1: serial@44e09000 {
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index a35a106..1545cca 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -11,12 +11,33 @@
+
+ /include/ "am335x-bone-common.dtsi"
+
++&am33xx_pinmux {
++ rstctl_pins: pinmux_rstctl_pins {
++ pinctrl-single,pins = <
++ /* eMMC_RSTn */
++ 0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */
++ >;
++ };
++};
++
+ &ldo3_reg {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
++&rstctl {
++ status = "okay";
++ compatible = "gpio-rctrl";
++ pinctrl-names = "default";
++ pinctrl-0 = <&rstctl_pins>;
++
++ #reset-cells = <2>;
++
++ gpios = <&gpio2 20 0x00>;
++ gpio-names = "eMMC_RSTn";
++};
++
+ &mmc1 {
+ vmmc-supply = <&vmmcsd_fixed>;
+ };
+@@ -26,6 +47,9 @@
+ bus-width = <8>;
+ ti,non-removable;
+ status = "okay";
++
++ reset = <&rstctl 0 0>;
++ reset-names = "eMMC_RSTn-CONSUMER";
+ };
+
+
diff --git a/patches/linux-3.8.13/0601-bone-eMMC-Add-rstctl-rstctl-DT-bindings.patch b/patches/linux-3.8.13/0601-bone-eMMC-Add-rstctl-rstctl-DT-bindings.patch
new file mode 100644
index 0000000..5ec01ec
--- /dev/null
+++ b/patches/linux-3.8.13/0601-bone-eMMC-Add-rstctl-rstctl-DT-bindings.patch
@@ -0,0 +1,64 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 22 Apr 2013 20:38:11 +0300
+Subject: [PATCH] bone-eMMC: Add rstctl rstctl DT bindings
+
+Add the references to the reset controller for the eMMC capes.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/BB-BONE-eMMC1-01-00A0.dts | 7 +++----
+ firmware/capes/cape-bone-2g-emmc1.dts | 7 +++----
+ 2 files changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+index ebac267..0776bee 100644
+--- a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
++++ b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+@@ -30,9 +30,6 @@
+ 0x14 0x31 /* gpmc_ad5.mmc1_dat5, INPUT_PULLUP | MODE1 */
+ 0x18 0x31 /* gpmc_ad6.mmc1_dat6, INPUT_PULLUP | MODE1 */
+ 0x1c 0x31 /* gpmc_ad7.mmc1_dat7, INPUT_PULLUP | MODE1 */
+-
+- /* the reset */
+- 0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */
+ >;
+ };
+ };
+@@ -46,8 +43,10 @@
+ bus-width = <8>;
+ ti,non-removable;
+ status = "okay";
+- reset-gpios = <&gpio2 20 1>; /* active low */
+ ti,vcc-aux-disable-is-sleep;
++
++ reset = <&rstctl 0 0>;
++ reset-names = "eMMC_RSTn";
+ };
+ };
+ };
+diff --git a/firmware/capes/cape-bone-2g-emmc1.dts b/firmware/capes/cape-bone-2g-emmc1.dts
+index 69bb684..bf26ae1 100644
+--- a/firmware/capes/cape-bone-2g-emmc1.dts
++++ b/firmware/capes/cape-bone-2g-emmc1.dts
+@@ -31,9 +31,6 @@
+ 0x14 0x31 /* gpmc_ad5.mmc1_dat5, INPUT_PULLUP | MODE1 */
+ 0x18 0x31 /* gpmc_ad6.mmc1_dat6, INPUT_PULLUP | MODE1 */
+ 0x1c 0x31 /* gpmc_ad7.mmc1_dat7, INPUT_PULLUP | MODE1 */
+-
+- /* the reset */
+- 0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */
+ >;
+ };
+ };
+@@ -47,8 +44,10 @@
+ bus-width = <8>;
+ ti,non-removable;
+ status = "okay";
+- reset-gpios = <&gpio2 20 1>; /* active low */
+ ti,vcc-aux-disable-is-sleep;
++
++ reset = <&rstctl 0 0>;
++ reset-names = "eMMC_RSTn";
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0602-capes-Add-testing-capes-for-rstctl.patch b/patches/linux-3.8.13/0602-capes-Add-testing-capes-for-rstctl.patch
new file mode 100644
index 0000000..72ae35a
--- /dev/null
+++ b/patches/linux-3.8.13/0602-capes-Add-testing-capes-for-rstctl.patch
@@ -0,0 +1,115 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 22 Apr 2013 20:40:07 +0300
+Subject: [PATCH] capes: Add testing capes for rstctl
+
+Add a couple of reset control capes for testing rstctl
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/BB-BONE-RST-00A0.dts | 62 ++++++++++++++++++++++++++++++++++
+ firmware/capes/BB-BONE-RST2-00A0.dts | 27 +++++++++++++++
+ 2 files changed, 89 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-RST-00A0.dts
+ create mode 100644 firmware/capes/BB-BONE-RST2-00A0.dts
+
+diff --git a/firmware/capes/BB-BONE-RST-00A0.dts b/firmware/capes/BB-BONE-RST-00A0.dts
+new file mode 100644
+index 0000000..acdcda4
+--- /dev/null
++++ b/firmware/capes/BB-BONE-RST-00A0.dts
+@@ -0,0 +1,62 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-RST";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&ocp>;
++ __overlay__ {
++ test_rctrl: test_reset {
++ compatible = "test-rctrl";
++ #reset-cells = <2>;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ test_consumer_rctrl: test_consumer_reset {
++ compatible = "test-consumer-rctrl";
++
++ reset = <&test_rctrl 0 0>;
++ reset-names = "RESET_1";
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++ gpio_rctrl: gpio_reset {
++ compatible = "gpio-rctrl";
++ #reset-cells = <2>;
++
++ gpios = <&gpio2 28 0x1>, <&gpio2 29 0x0>;
++ gpio-names = "HDMI-reset", "eMMC-reset";
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&ocp>;
++ __overlay__ {
++ gpio_consumer_rctrl:gpio_consumer_reset {
++ compatible = "test-consumer-rctrl";
++
++ reset = <&gpio_rctrl 0 0>, <&gpio_rctrl 1 0>;
++ reset-names = "RESET_1", "RESET_2";
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/BB-BONE-RST2-00A0.dts b/firmware/capes/BB-BONE-RST2-00A0.dts
+new file mode 100644
+index 0000000..6904cc5
+--- /dev/null
++++ b/firmware/capes/BB-BONE-RST2-00A0.dts
+@@ -0,0 +1,27 @@
++/*
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-RST2";
++ version = "00A0";
++
++ fragment@0 {
++ target = <&ocp>;
++ __overlay__ {
++ emmc_reset_consumer_rctrl: emmc_reset_consumer {
++ compatible = "test-consumer-rctrl";
++
++ reset = <&rstctl 0 0>;
++ reset-names = "eMMC_RSTn-CONSUMER";
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0603-omap_hsmmc-Bail-out-when-rstctl-error-is-unrecoverab.patch b/patches/linux-3.8.13/0603-omap_hsmmc-Bail-out-when-rstctl-error-is-unrecoverab.patch
new file mode 100644
index 0000000..25dffb5
--- /dev/null
+++ b/patches/linux-3.8.13/0603-omap_hsmmc-Bail-out-when-rstctl-error-is-unrecoverab.patch
@@ -0,0 +1,35 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 22 Apr 2013 17:05:53 +0300
+Subject: [PATCH] omap_hsmmc: Bail out when rstctl error is unrecoverable
+
+Make sure that when a rstctl resource is requested, but unavailable
+to fail the device probe.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index f6f5875..e2b97df 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1837,11 +1837,15 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ /* request reset control (bail if deffering) */
+ rctrl = rstctl_get(&pdev->dev, NULL);
+ if (IS_ERR(rctrl)) {
+- if (PTR_ERR(rctrl) == -EPROBE_DEFER) {
+- dev_info(&pdev->dev, "Loading deferred\n");
++ ret = PTR_ERR(rctrl);
++ if (ret == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
++
++ if (ret != -ENODEV && ret != -ENOENT) {
++ dev_err(&pdev->dev, "Unrecoverable rstctl error\n");
++ return PTR_ERR(rctrl);
+ }
+- dev_info(&pdev->dev, "Failed to get rstctl\n");
++ dev_warn(&pdev->dev, "Failed to get rstctl; not using any\n");
+ rctrl = NULL;
+ } else {
+ dev_info(&pdev->dev, "Got rstctl (%s:#%d name %s) label:%s\n",
diff --git a/patches/linux-3.8.13/0604-bone-Put-priorities-in-built-in-capes.patch b/patches/linux-3.8.13/0604-bone-Put-priorities-in-built-in-capes.patch
new file mode 100644
index 0000000..c9daa76
--- /dev/null
+++ b/patches/linux-3.8.13/0604-bone-Put-priorities-in-built-in-capes.patch
@@ -0,0 +1,114 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 22 Apr 2013 17:08:09 +0300
+Subject: [PATCH] bone: Put priorities in built-in capes
+
+Place priority entries to built-in cape entries. That way we can
+make sure that the add one capes take precedence
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 44 +++++++++++++++++------------
+ arch/arm/boot/dts/am33xx.dtsi | 5 ++++
+ 2 files changed, 31 insertions(+), 18 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index e341a08..327e592 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -25,7 +25,7 @@
+
+ am33xx_pinmux: pinmux@44e10800 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&userleds_pins>;
++ pinctrl-0 = <&userled_pins>;
+
+ userled_pins: pinmux_userled_pins {
+ pinctrl-single,pins = <
+@@ -51,11 +51,6 @@
+
+ ocp: ocp {
+
+- /* reset controller comes first (even if disabled) */
+- rstctl: rstctl@0 {
+- status = "disabled";
+- };
+-
+ uart1: serial@44e09000 {
+ status = "okay";
+ };
+@@ -138,10 +133,10 @@
+ slot@4 {
+ ti,cape-override;
+ compatible = "ti,beaglebone-black";
+- board-name = "Bone-LT-eMMC-2G";
++ board-name = "BB-BONE-RST2";
+ version = "00A0";
+ manufacturer = "Texas Instruments";
+- part-number = "BB-BONE-EMMC-2G";
++ part-number = "BB-BONE-RST2";
+ };
+
+ /* geiger cape version A0 without an EEPROM */
+@@ -154,16 +149,6 @@
+ part-number = "BB-BONE-GEIGER";
+ };
+
+- /* Beaglebone black has it soldered on */
+- slot@6 {
+- ti,cape-override;
+- compatible = "ti,beaglebone-black";
+- board-name = "Bone-Black-HDMI";
+- version = "00A0";
+- manufacturer = "Texas Instruments";
+- part-number = "BB-BONELT-HDMI";
+- };
+-
+ /* Nixie cape version A0 without an EEPROM */
+ slot@7 {
+ ti,cape-override;
+@@ -221,6 +206,29 @@
+ manufacturer = "Adafruit";
+ part-number = "BB-BONE-RS232-01";
+ };
++
++ /* Beaglebone black has it soldered on */
++ slot@100 {
++ ti,cape-override;
++ priority = <1>;
++ compatible = "ti,beaglebone-black";
++ board-name = "Bone-LT-eMMC-2G";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONE-EMMC-2G";
++ };
++
++ /* Beaglebone black has it soldered on */
++ slot@101 {
++ ti,cape-override;
++ priority = <1>;
++ compatible = "ti,beaglebone-black";
++ board-name = "Bone-Black-HDMI";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONELT-HDMI";
++ };
++
+ };
+
+ /* mapping between board names and dtb objects */
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 76fa03b..eb0d2d4 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -155,6 +155,11 @@
+ interrupts = <62>;
+ };
+
++ /* reset controller comes first (even if disabled) */
++ rstctl: rstctl@0 {
++ status = "disabled";
++ };
++
+ uart1: serial@44e09000 {
+ compatible = "ti,omap3-uart";
+ ti,hwmods = "uart1";
diff --git a/patches/linux-3.8.13/0605-bone-common-dtsi-remove-reset-cape.patch b/patches/linux-3.8.13/0605-bone-common-dtsi-remove-reset-cape.patch
new file mode 100644
index 0000000..bad7a0d
--- /dev/null
+++ b/patches/linux-3.8.13/0605-bone-common-dtsi-remove-reset-cape.patch
@@ -0,0 +1,30 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 2 May 2013 14:15:13 +0200
+Subject: [PATCH] bone-common dtsi: remove reset cape
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 327e592..ae407c3 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -129,16 +129,6 @@
+ eeprom = <&cape_eeprom3>;
+ };
+
+- /* Beaglebone black has it soldered on */
+- slot@4 {
+- ti,cape-override;
+- compatible = "ti,beaglebone-black";
+- board-name = "BB-BONE-RST2";
+- version = "00A0";
+- manufacturer = "Texas Instruments";
+- part-number = "BB-BONE-RST2";
+- };
+-
+ /* geiger cape version A0 without an EEPROM */
+ slot@5 {
+ ti,cape-override;
diff --git a/patches/linux-3.8.13/0606-mmc-add-missing-select-RSTCTL-in-MMC_OMAP.patch b/patches/linux-3.8.13/0606-mmc-add-missing-select-RSTCTL-in-MMC_OMAP.patch
new file mode 100644
index 0000000..4e1b693
--- /dev/null
+++ b/patches/linux-3.8.13/0606-mmc-add-missing-select-RSTCTL-in-MMC_OMAP.patch
@@ -0,0 +1,24 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Sat, 25 May 2013 20:36:52 +0000
+Subject: [PATCH] mmc: add missing select RSTCTL in MMC_OMAP
+
+CONFIG_MMC_OMAP requires CONFIG_RSTCTL to compile and
+should be selected
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/mmc/host/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 009dabd..86d81ee 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -245,6 +245,7 @@ config MMC_OMAP
+ tristate "TI OMAP Multimedia Card Interface support"
+ depends on ARCH_OMAP
+ select TPS65010 if MACH_OMAP_H2
++ select RSTCTL
+ help
+ This selects the TI OMAP Multimedia card Interface.
+ If you have an OMAP board with a Multimedia Card slot,
diff --git a/patches/linux-3.8.13/0607-soc_camera-QL-mt9l112-camera-driver-for-the-beaglebo.patch b/patches/linux-3.8.13/0607-soc_camera-QL-mt9l112-camera-driver-for-the-beaglebo.patch
new file mode 100644
index 0000000..208feb2
--- /dev/null
+++ b/patches/linux-3.8.13/0607-soc_camera-QL-mt9l112-camera-driver-for-the-beaglebo.patch
@@ -0,0 +1,1606 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 17:43:32 +0300
+Subject: [PATCH] soc_camera: QL/mt9l112 camera driver for the beaglebone
+
+Driver for the Quicklogic camera cape.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/media/platform/soc_camera/Kconfig | 7 +
+ drivers/media/platform/soc_camera/Makefile | 1 +
+ drivers/media/platform/soc_camera/cssp_camera.c | 1560 +++++++++++++++++++++++
+ 3 files changed, 1568 insertions(+)
+ create mode 100644 drivers/media/platform/soc_camera/cssp_camera.c
+
+diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
+index cb6791e..06baabf 100644
+--- a/drivers/media/platform/soc_camera/Kconfig
++++ b/drivers/media/platform/soc_camera/Kconfig
+@@ -86,3 +86,10 @@ config VIDEO_ATMEL_ISI
+ This module makes the ATMEL Image Sensor Interface available
+ as a v4l2 device.
+
++config VIDEO_QL_CAMIF
++ tristate "QuickLogic Camera Interface support (EXPERIMENTAL)"
++ depends on VIDEO_DEV && SOC_CAMERA && SOC_AM33XX && EXPERIMENTAL
++ select VIDEOBUF2_DMA_CONTIG
++ ---help---
++ This is a v4l2 driver for the QuickLogic CAMIF controller.
++
+diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile
+index 136b7f8..d7ba0eb 100644
+--- a/drivers/media/platform/soc_camera/Makefile
++++ b/drivers/media/platform/soc_camera/Makefile
+@@ -10,5 +10,6 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o
+ obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
+ obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
+ obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o
++obj-$(CONFIG_VIDEO_QL_CAMIF) += cssp_camera.o
+
+ ccflags-y += -I$(srctree)/drivers/media/i2c/soc_camera
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+new file mode 100644
+index 0000000..41de42e
+--- /dev/null
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -0,0 +1,1560 @@
++/*
++ * cssp-camera driver
++ *
++ * Based on Vivi driver
++ *
++ * Copyright (C) 2012 QuickLogic Corp.
++ *
++ * Developed for QuickLogic by:
++ * Damian Eppel <damian.eppel@teleca.com>
++ * Przemek Szewczyk <przemek.szewczyk@teleca.com>
++ * Dan Aizenstros <daizenstros@quicklogic.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/init.h>
++#include <linux/module.h>
++#include <linux/gpio.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/spinlock.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
++#include <linux/platform_data/edma.h>
++#include <linux/clk.h>
++// V4L2 Interface *********************
++#include <media/soc_camera.h>
++#include <media/v4l2-mediabus.h>
++#include <media/videobuf2-dma-contig.h>
++#include <media/v4l2-ioctl.h>
++#include <media/v4l2-event.h>
++#include <media/mt9t112.h>
++//*************************************
++#include <linux/of.h>
++#include <linux/of_platform.h>
++#include <linux/of_dma.h>
++#include <linux/of_gpio.h>
++#include <linux/of_i2c.h>
++
++static unsigned video_nr = -1;
++module_param(video_nr, uint, 0644);
++MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
++
++static unsigned int vid_limit = 6;
++module_param(vid_limit, uint, 0644);
++MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
++
++#define VGA_WIDTH 640
++#define VGA_HEIGHT 480
++
++#define MAX_WIDTH 2048
++#define MAX_HEIGHT 1536
++
++#define VGA_RES (VGA_WIDTH * VGA_HEIGHT)
++#define BYTES_PER_PIXEL 2
++
++/* PaRAM.opt: */
++#define TCC(v) (((v) & 0x3f) << 12)
++/* PaRAM.a_b_cnt: */
++#define ACNT(v) ((v) & 0xffff)
++#define BCNT(v) (((v) & 0xffff) << 16)
++/* PaRAM.src_dst_bidx: */
++#define SRCBIDX(v) ((v) & 0xffff)
++#define DSTBIDX(v) (((v) & 0xffff) << 16)
++/* PaRAM.link_bcntrld: */
++#define LINK(v) ((v) & 0xffff)
++#define BCNTRLD(v) (((v) & 0xffff) << 16)
++/* PaRAM.src_dst_cidx: */
++#define SRCCIDX(v) ((v) & 0xffff)
++#define DSTCIDX(v) (((v) & 0xffff) << 16)
++/* PaRAM.ccnt: */
++#define CCNT(v) ((v) & 0xffff)
++
++
++struct cssp_cam_platform_data {
++ struct i2c_board_info *cam_i2c_board_info;
++ const char *cam_clk_name;
++ u32 cam_clk_rate;
++ int dma_ch;
++ int gpio_reset_pin;
++};
++
++struct cssp_cam_platform_data_storage {
++ struct cssp_cam_platform_data pdata;
++ struct i2c_board_info i2c_camera;
++ struct soc_camera_link camera_link;
++ /* only support mt9t112 for now */
++ struct mt9t112_camera_info mt9t111_cam_info;
++};
++
++#define to_cssp_platform_data_storage(_x) container_of(_x, \
++ struct cssp_cam_platform_data_storage, pdata)
++
++
++/* ------------------------------------------------------------------
++ video Basic structures
++ ------------------------------------------------------------------*/
++
++struct cssp_cam_fmt {
++ char *name;
++ u32 fourcc; /* v4l2 format id */
++ int depth;
++ enum v4l2_mbus_pixelcode code;
++};
++
++/* buffer for one video frame */
++struct cssp_cam_buffer {
++ /* common v4l buffer stuff -- must be first */
++ struct vb2_buffer vb;
++ struct list_head list;
++ struct cssp_cam_fmt *fmt;
++};
++
++struct cssp_cam_dmaqueue {
++ struct list_head active;
++};
++
++struct cssp_cam_dev {
++ struct v4l2_device v4l2_dev;
++ struct v4l2_ctrl_handler ctrl_handler;
++ struct v4l2_subdev *subdev;
++
++ spinlock_t slock;
++ struct mutex mutex;
++
++ /* various device info */
++ struct video_device *vdev;
++ struct platform_device *pdev;
++
++ struct cssp_cam_dmaqueue vidq;
++ void *dma_cont_ctx;
++ int streaming_started;
++ struct vb2_buffer *current_vb;
++
++ /* video capture */
++ struct cssp_cam_fmt *fmt;
++ u32 width;
++ u32 height;
++ u32 bytesperline;
++ u32 sizeimage;
++ enum v4l2_colorspace colorspace;
++ struct vb2_queue vb_vidq;
++ enum v4l2_field field;
++
++ /* Camera Sensor */
++ struct i2c_board_info *camera_board_info;
++ struct clk *camera_clk;
++
++ void __iomem *reg_base_virt;
++ unsigned int reg_base_phys;
++ resource_size_t reg_size;
++ u16 mode;
++
++ int dma_ch;
++ struct edmacc_param dma_tr_params;
++
++ u64 dma_mask;
++ int dma_req_len;
++
++ int frame_cnt;
++
++ int reset_pin;
++
++ int rev;
++
++ /* OF build platform data here */
++ struct cssp_cam_platform_data_storage *pstore;
++};
++
++/*
++ * ---------------------------------------------------------------------------
++ * QuickLoigc Camera Interface registers
++ * ---------------------------------------------------------------------------
++ */
++
++#define REG_MODE 0x00000
++#define REG_DATA 0x10000
++
++/* MODE bit shifts */
++#define FMT_2X8_EN BIT(15) /* Enable 2 byte format on CAMIF bus (0 - 10 bit, 1 - 16 bit 2x8) */
++#define PCLK_POL BIT(14) /* PCLK polarity (0 - rising edge, 1 - falling edge */
++#define HS_EN BIT(13) /* High speed bus (0 =< 50 MHz, 1 > 50 MHz) */
++#define ENABLE BIT(12)
++#define LDR_EN BIT(11) /* Large DMA Request Support (0 - 32 bytes, 1 - 128 bytes) */
++#define REV 0xFF /* Chip Revision mask */
++
++
++static struct cssp_cam_fmt formats[] = {
++ {
++ .name = "4:2:2, packed, YUYV",
++ .fourcc = V4L2_PIX_FMT_YUYV,
++ .depth = 16,
++ .code = V4L2_MBUS_FMT_YUYV8_2X8,
++ },
++/*
++ * UYVY doesn't work properly. VYUY and YVYU are not tested.
++ * So disable the UYVY, VYUY and YVYU modes for now
++ */
++#if 0
++ {
++ .name = "4:2:2, packed, UYVY",
++ .fourcc = V4L2_PIX_FMT_UYVY,
++ .depth = 16,
++ .code = V4L2_MBUS_FMT_UYVY8_2X8,
++ },
++ {
++ .name = "4:2:2, packed, VYUY",
++ .fourcc = V4L2_PIX_FMT_VYUY,
++ .depth = 16,
++ .code = V4L2_MBUS_FMT_VYUY8_2X8,
++ },
++ {
++ .name = "4:2:2, packed, YVYU",
++ .fourcc = V4L2_PIX_FMT_YVYU,
++ .depth = 16,
++ .code = V4L2_MBUS_FMT_YVYU8_2X8,
++ },
++#endif
++ {
++ .name = "RGB565 (LE)",
++ .fourcc = V4L2_PIX_FMT_RGB565,
++ .depth = 16,
++ .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
++ },
++ {
++ .name = "RGB555 (LE)",
++ .fourcc = V4L2_PIX_FMT_RGB555,
++ .depth = 16,
++ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
++ },
++};
++
++
++/***************************************************************************/
++
++
++static int configure_gpio(int nr, int val, const char *name)
++{
++ unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
++ int ret;
++ if (!gpio_is_valid(nr))
++ return 0;
++ ret = gpio_request_one(nr, flags, name);
++ if (!ret)
++ gpio_export(nr, 0);
++ return ret;
++}
++
++static int reset_cssp(struct cssp_cam_dev *cam)
++{
++ struct platform_device *pdev = cam->pdev;
++ struct cssp_cam_platform_data *pdata = pdev->dev.platform_data;
++ int err;
++
++ cam->reset_pin = pdata->gpio_reset_pin;
++ if (!gpio_is_valid(cam->reset_pin))
++ return 0;
++
++ err = configure_gpio(cam->reset_pin, 0, "cssp_reset");
++ if (err) {
++ dev_err(&pdev->dev, "failed to configure cssp reset pin\n");
++ return -1;
++ }
++
++ mdelay(1);
++
++ gpio_direction_output(cam->reset_pin, 1);
++
++ return err;
++}
++
++static int trigger_dma_transfer_to_buf(struct cssp_cam_dev *dev, struct vb2_buffer *vb)
++{
++ dma_addr_t dma_buf = vb2_dma_contig_plane_dma_addr(vb, 0);
++
++ if (!dma_buf) {
++ /* Is this possible? Release the vb2_buffer with an error here, */
++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
++ dev->current_vb = NULL;
++ return -ENOMEM;
++ }
++
++ dev->dma_tr_params.dst = dma_buf;
++
++ // Enable DMA
++ edma_write_slot(dev->dma_ch, &dev->dma_tr_params);
++
++ dev->current_vb = vb;
++
++ // Enable data capture
++ dev->mode |= ENABLE;
++ writew(dev->mode, dev->reg_base_virt + REG_MODE);
++ readw(dev->reg_base_virt + REG_MODE);
++
++ return 0;
++}
++
++static void dequeue_buffer_for_dma(struct cssp_cam_dev *dev)
++{
++ struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
++ unsigned long flags = 0;
++
++ spin_lock_irqsave(&dev->slock, flags);
++ if (!list_empty(&dma_q->active)) {
++ struct cssp_cam_buffer *buf;
++
++ buf = list_entry(dma_q->active.next, struct cssp_cam_buffer, list);
++ list_del(&buf->list);
++ spin_unlock_irqrestore(&dev->slock, flags);
++
++ buf->fmt = dev->fmt;
++
++ trigger_dma_transfer_to_buf(dev, &buf->vb);
++ } else {
++ spin_unlock_irqrestore(&dev->slock, flags);
++ }
++}
++
++static void dma_callback(unsigned lch, u16 ch_status, void *data)
++{
++ struct cssp_cam_dev *dev = data;
++ struct vb2_buffer *vb;
++ struct edmacc_param dma_tr_params;
++
++ // Disable data capture
++ dev->mode &= ~ENABLE;
++ writew(dev->mode, dev->reg_base_virt + REG_MODE);
++ readw(dev->reg_base_virt + REG_MODE);
++
++ if (ch_status == DMA_COMPLETE) {
++
++ vb = dev->current_vb;
++
++ edma_read_slot(dev->dma_ch, &dma_tr_params);
++ if ((dma_tr_params.opt != 0) ||
++ (dma_tr_params.src != 0) ||
++ (dma_tr_params.a_b_cnt != 0) ||
++ (dma_tr_params.dst != 0) ||
++ (dma_tr_params.src_dst_bidx != 0) ||
++ (dma_tr_params.link_bcntrld != 0xffff) ||
++ (dma_tr_params.src_dst_cidx != 0) ||
++ (dma_tr_params.ccnt != 0)) {
++
++ trigger_dma_transfer_to_buf(dev, dev->current_vb);
++ return;
++ }
++
++ vb->v4l2_buf.field = dev->field;
++ vb->v4l2_buf.sequence = dev->frame_cnt++;
++ do_gettimeofday(&vb->v4l2_buf.timestamp);
++ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
++ dev->current_vb = NULL;
++
++ /* check if we have new buffer queued */
++ dequeue_buffer_for_dma(dev);
++ } else {
++ /* we got a missed interrupt so just start a new DMA with the existing buffer */
++ if (dev->current_vb != NULL) {
++ if (trigger_dma_transfer_to_buf(dev, dev->current_vb))
++ dev_err(&dev->pdev->dev, "No buffer allocated!\n");
++ }
++ }
++}
++
++static int configure_edma(struct cssp_cam_dev *cam)
++{
++ struct platform_device *pdev = cam->pdev;
++ struct cssp_cam_platform_data *pdata = pdev->dev.platform_data;
++ struct edmacc_param *param;
++ int dma_channel;
++
++ dma_channel = pdata->dma_ch;
++
++ /* wtf? do we need to this here? */
++ pdev->dev.dma_mask = &cam->dma_mask;
++ pdev->dev.coherent_dma_mask = (u32)~0;
++ if (dma_set_mask(&pdev->dev, (u32)~0)) {
++ dev_err(&pdev->dev, "failed setting mask for DMA\n");
++ return -EINVAL;
++ }
++ cam->dma_ch = edma_alloc_channel(dma_channel, dma_callback, cam, EVENTQ_0);
++ if (cam->dma_ch < 0) {
++ dev_err(&pdev->dev, "allocating channel for DMA failed\n");
++ return -EBUSY;
++ }
++
++ cam->dma_req_len = cam->rev > 3 ? 128 : 32;
++
++ param = &cam->dma_tr_params;
++ param->opt = TCINTEN | TCC(cam->dma_ch);
++ param->src = cam->reg_base_phys + REG_DATA;
++ param->a_b_cnt = ACNT(cam->dma_req_len) |
++ BCNT((VGA_WIDTH * BYTES_PER_PIXEL) / cam->dma_req_len);
++ param->src_dst_bidx = SRCBIDX(0) | DSTBIDX(cam->dma_req_len);
++ param->link_bcntrld = BCNTRLD((VGA_WIDTH * BYTES_PER_PIXEL) /
++ cam->dma_req_len) | LINK(0xffff);
++ param->src_dst_cidx = SRCCIDX(0) | DSTCIDX(cam->dma_req_len);
++ param->ccnt = CCNT(VGA_HEIGHT);
++
++ return 0;
++}
++
++static int configure_cssp(struct cssp_cam_dev *cam)
++{
++ struct platform_device *pdev = cam->pdev;
++ int ret = 0;
++ unsigned int val;
++ struct resource *res;
++
++ ret = reset_cssp(cam);
++ if (ret)
++ return ret;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (res == NULL) {
++ dev_err(&pdev->dev, "no mem resource\n");
++ return -ENODEV;
++ }
++
++ /*
++ * Request the region.
++ */
++ if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
++ dev_err(&pdev->dev, "request_mem_region failed\n");
++ return -EBUSY;
++ }
++
++ cam->reg_base_phys = res->start;
++ cam->reg_size = resource_size(res);
++
++ cam->reg_base_virt = ioremap(cam->reg_base_phys, cam->reg_size);
++ if (cam->reg_base_virt == NULL) {
++ dev_err(&pdev->dev, "ioremap of registers region failed\n");
++ release_mem_region(cam->reg_base_phys, cam->reg_size);
++ return -ENOMEM;
++ }
++
++ /* double reads */
++ readw(cam->reg_base_virt + REG_MODE);
++ val = readw(cam->reg_base_virt + REG_MODE);
++ cam->rev = val & REV;
++ dev_info(&pdev->dev, "CSSP Revision %c%d\n",
++ 'A' + ((cam->rev & 0xf0) >> 4), cam->rev & 0x0f);
++
++ cam->dma_req_len = cam->rev > 3 ? 128 : 32;
++
++ return 0;
++}
++
++static int configure_camera_sensor(struct cssp_cam_dev *cam)
++{
++ struct i2c_board_info *info = cam->camera_board_info;
++ struct i2c_client *client;
++ struct i2c_adapter *adapter;
++ struct v4l2_subdev *subdev;
++ struct v4l2_mbus_framefmt f_format = {
++ .width = VGA_WIDTH,
++ .height = VGA_HEIGHT,
++ .code = V4L2_MBUS_FMT_YUYV8_2X8,
++ .colorspace = V4L2_COLORSPACE_JPEG,
++ };
++
++ /* Enable the clock just for the time of loading the camera driver and disable after that */
++ /* It is going to be be re-enabled later, when camera will be in use */
++ clk_enable(cam->camera_clk);
++ udelay(5); // let the clock stabilize
++
++ adapter = i2c_get_adapter(((struct soc_camera_link *)(info->platform_data))->i2c_adapter_id);
++ if (!adapter) {
++ dev_err(&cam->pdev->dev, "failed to get i2c adapter...\n");
++ return -ENODEV;
++ }
++
++ client = i2c_new_device(adapter, info);
++ i2c_put_adapter(adapter);
++
++ if (client == NULL) {
++ return -ENODEV;
++ }
++
++ subdev = (struct v4l2_subdev *)i2c_get_clientdata(client);
++ if (subdev == NULL) {
++ i2c_unregister_device(client);
++ return -ENODEV;
++ }
++
++ cam->subdev = subdev;
++
++ v4l2_subdev_call(subdev, video, s_mbus_fmt, &f_format);
++
++ clk_disable(cam->camera_clk);
++
++ return 0;
++}
++
++static int start_camera_sensor(struct cssp_cam_dev *cam)
++{
++ clk_enable(cam->camera_clk);
++ udelay(5); /* let the clock stabilize */
++
++ v4l2_subdev_call(cam->subdev, video, s_stream, 1);
++
++ return 0;
++}
++
++static void stop_camera_sensor(struct cssp_cam_dev *cam)
++{
++ v4l2_subdev_call(cam->subdev, video, s_stream, 0);
++
++ clk_disable(cam->camera_clk);
++
++ return;
++}
++
++static struct cssp_cam_fmt *get_format(struct v4l2_format *f)
++{
++ struct cssp_cam_fmt *fmt;
++ unsigned int k;
++
++ for (k = 0; k < ARRAY_SIZE(formats); k++) {
++ fmt = &formats[k];
++ if (fmt->fourcc == f->fmt.pix.pixelformat)
++ break;
++ }
++
++ if (k == ARRAY_SIZE(formats))
++ return NULL;
++
++ return &formats[k];
++}
++
++
++/* ------------------------------------------------------------------
++ Videobuf operations
++ ------------------------------------------------------------------*/
++
++static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
++ unsigned int *nbuffers, unsigned int *nplanes,
++ unsigned int sizes[], void *alloc_ctxs[])
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
++ unsigned long size;
++
++ size = dev->sizeimage;
++
++ if (0 == *nbuffers)
++ *nbuffers = 32;
++
++ while (size * *nbuffers > vid_limit * 1024 * 1024)
++ (*nbuffers)--;
++
++ *nplanes = 1;
++
++ sizes[0] = size;
++
++ alloc_ctxs[0] = dev->dma_cont_ctx;
++
++ dev->frame_cnt = 0;
++
++ dev_dbg(&dev->pdev->dev, "%s, count=%d, size=%ld\n", __func__,
++ *nbuffers, size);
++
++ return 0;
++}
++
++static int buffer_init(struct vb2_buffer *vb)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
++
++ BUG_ON(NULL == dev->fmt);
++
++ /*
++ * This callback is called once per buffer, after its allocation.
++ *
++ * Vivi does not allow changing format during streaming, but it is
++ * possible to do so when streaming is paused (i.e. in streamoff state).
++ * Buffers however are not freed when going into streamoff and so
++ * buffer size verification has to be done in buffer_prepare, on each
++ * qbuf.
++ * It would be best to move verification code here to buf_init and
++ * s_fmt though.
++ */
++
++ return 0;
++}
++
++static int buffer_prepare(struct vb2_buffer *vb)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
++ struct cssp_cam_buffer *buf =
++ container_of(vb, struct cssp_cam_buffer, vb);
++ unsigned long size;
++
++ dev_dbg(&dev->pdev->dev, "%s, field=%d\n", __func__,
++ vb->v4l2_buf.field);
++
++ BUG_ON(NULL == dev->fmt);
++
++ /*
++ * Theses properties only change when queue is idle, see s_fmt.
++ * The below checks should not be performed here, on each
++ * buffer_prepare (i.e. on each qbuf). Most of the code in this function
++ * should thus be moved to buffer_init and s_fmt.
++ */
++ if (dev->width < 48 || dev->width > MAX_WIDTH ||
++ dev->height < 32 || dev->height > MAX_HEIGHT)
++ return -EINVAL;
++
++ size = dev->sizeimage;
++ if (vb2_plane_size(vb, 0) < size) {
++ dev_err(&dev->pdev->dev, "%s data will not fit into "
++ "plane (%lu < %lu)\n",
++ __func__, vb2_plane_size(vb, 0), size);
++ return -EINVAL;
++ }
++
++ vb2_set_plane_payload(&buf->vb, 0, size);
++
++ buf->fmt = dev->fmt;
++
++ return 0;
++}
++
++static int buffer_finish(struct vb2_buffer *vb)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++ return 0;
++}
++
++static void buffer_cleanup(struct vb2_buffer *vb)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++}
++
++static void buffer_queue(struct vb2_buffer *vb)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
++ struct cssp_cam_buffer *buf = container_of(vb, struct cssp_cam_buffer, vb);
++ struct cssp_cam_dmaqueue *vidq = &dev->vidq;
++ unsigned long flags = 0;
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
++ if (dev->streaming_started && !dev->current_vb) {
++ trigger_dma_transfer_to_buf(dev, &buf->vb);
++ } else {
++ spin_lock_irqsave(&dev->slock, flags);
++ list_add_tail(&buf->list, &vidq->active);
++ spin_unlock_irqrestore(&dev->slock, flags);
++ }
++}
++
++static int start_streaming(struct vb2_queue *vq, unsigned int count)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
++ struct platform_device *pdev = dev->pdev;
++ int ret;
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
++ ret = start_camera_sensor(dev);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "start_camera_sensor failed\n");
++ return ret;
++ }
++
++ // Enable DMA
++ ret = edma_start(dev->dma_ch);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "edma_start failed\n");
++ return ret;
++ }
++ dev->streaming_started = 1;
++
++ /* check if we have new buffer queued */
++ dequeue_buffer_for_dma(dev);
++
++ return 0;
++}
++
++/* abort streaming and wait for last buffer */
++static int stop_streaming(struct vb2_queue *vq)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
++ struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
++ // Disable DMA
++ edma_stop(dev->dma_ch);
++
++ // Disable data capture
++ dev->mode &= ~ENABLE;
++ writew(dev->mode, dev->reg_base_virt + REG_MODE);
++
++ stop_camera_sensor(dev);
++
++ dev->streaming_started = 0;
++
++ /* Release all active buffers */
++ while (!list_empty(&dma_q->active)) {
++ struct cssp_cam_buffer *buf;
++
++ buf = list_entry(dma_q->active.next,
++ struct cssp_cam_buffer, list);
++ list_del(&buf->list);
++ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
++
++ dev_dbg(&dev->pdev->dev, "[%p/%d] done\n",
++ buf, buf->vb.v4l2_buf.index);
++ }
++
++ dev->current_vb = NULL;
++
++ return 0;
++}
++
++static void cssp_cam_lock(struct vb2_queue *vq)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
++ mutex_lock(&dev->mutex);
++}
++
++static void cssp_cam_unlock(struct vb2_queue *vq)
++{
++ struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
++ mutex_unlock(&dev->mutex);
++}
++
++static struct vb2_ops cssp_cam_video_qops = {
++ .queue_setup = queue_setup,
++ .buf_init = buffer_init,
++ .buf_prepare = buffer_prepare,
++ .buf_finish = buffer_finish,
++ .buf_cleanup = buffer_cleanup,
++ .buf_queue = buffer_queue,
++ .start_streaming = start_streaming,
++ .stop_streaming = stop_streaming,
++ .wait_prepare = cssp_cam_unlock,
++ .wait_finish = cssp_cam_lock,
++};
++
++/* ------------------------------------------------------------------
++ IOCTL vidioc handling
++ ------------------------------------------------------------------*/
++
++static int vidioc_querycap(struct file *file, void *priv,
++ struct v4l2_capability *cap)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ strcpy(cap->driver, "cssp_camera");
++ strcpy(cap->card, "cssp_camera");
++ strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
++ V4L2_CAP_READWRITE;
++ return 0;
++}
++
++static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_fmtdesc *f)
++{
++ struct cssp_cam_fmt *fmt;
++
++ if (f->index >= ARRAY_SIZE(formats))
++ return -EINVAL;
++
++ fmt = &formats[f->index];
++
++ strlcpy(f->description, fmt->name, sizeof(f->description));
++ f->pixelformat = fmt->fourcc;
++ return 0;
++}
++
++static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ f->fmt.pix.width = dev->width;
++ f->fmt.pix.height = dev->height;
++ f->fmt.pix.field = dev->field;
++ f->fmt.pix.pixelformat = dev->fmt->fourcc;
++ f->fmt.pix.bytesperline = dev->bytesperline;
++ f->fmt.pix.sizeimage = dev->sizeimage;
++ f->fmt.pix.colorspace = dev->colorspace;
++
++ return 0;
++}
++
++static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ struct cssp_cam_fmt *fmt;
++ struct v4l2_mbus_framefmt mbus_fmt;
++ struct v4l2_pix_format *pix = &f->fmt.pix;
++
++ fmt = get_format(f);
++ if (!fmt) {
++ dev_err(&dev->pdev->dev, "Fourcc format (0x%08x) invalid.\n",
++ f->fmt.pix.pixelformat);
++ return -EINVAL;
++ }
++
++ v4l2_fill_mbus_format(&mbus_fmt, pix, fmt->code);
++ v4l2_subdev_call(dev->subdev, video, try_mbus_fmt, &mbus_fmt);
++ v4l2_fill_pix_format(pix, &mbus_fmt);
++ pix->bytesperline = (pix->width * fmt->depth) >> 3;
++ pix->sizeimage = pix->height * pix->bytesperline;
++
++ if ((pix->sizeimage % dev->dma_req_len) != 0)
++ return -EINVAL;
++
++ switch (mbus_fmt.field) {
++ case V4L2_FIELD_ANY:
++ pix->field = V4L2_FIELD_NONE;
++ break;
++ case V4L2_FIELD_NONE:
++ break;
++ default:
++ dev_err(&dev->pdev->dev, "Field type %d unsupported.\n", mbus_fmt.field);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
++ struct v4l2_format *f)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ struct vb2_queue *q = &dev->vb_vidq;
++ struct v4l2_pix_format *pix = &f->fmt.pix;
++ struct v4l2_mbus_framefmt mbus_fmt;
++ int i = 0, rem;
++ u32 bytesperline, height;
++
++ int ret = vidioc_try_fmt_vid_cap(file, priv, f);
++ if (ret < 0)
++ return ret;
++
++ if (vb2_is_streaming(q)) {
++ dev_err(&dev->pdev->dev, "%s device busy\n", __func__);
++ return -EBUSY;
++ }
++
++ dev->fmt = get_format(f);
++ dev->width = f->fmt.pix.width;
++ dev->height = f->fmt.pix.height;
++ dev->field = f->fmt.pix.field;
++ dev->colorspace = f->fmt.pix.colorspace;
++ dev->bytesperline = f->fmt.pix.bytesperline;
++ dev->sizeimage = f->fmt.pix.sizeimage;
++
++ /* Set the sensor into the new format */
++ v4l2_fill_mbus_format(&mbus_fmt, pix, dev->fmt->code);
++ v4l2_subdev_call(dev->subdev, video, s_mbus_fmt, &mbus_fmt);
++
++ /* Calculate DMA transfer parameters based on DMA request length */
++ bytesperline = dev->bytesperline;
++ do {
++ rem = bytesperline % dev->dma_req_len;
++ if (rem != 0) {
++ bytesperline <<= 1;
++ i++;
++ }
++ } while (rem != 0);
++ height = dev->height >> i;
++
++ /* Set the EDMA for the new resolution */
++ dev->dma_tr_params.a_b_cnt = ACNT(dev->dma_req_len) | BCNT(bytesperline / dev->dma_req_len);
++ dev->dma_tr_params.link_bcntrld = BCNTRLD(bytesperline / dev->dma_req_len) | LINK(0xffff);
++ dev->dma_tr_params.ccnt = CCNT(height);
++
++ return 0;
++}
++
++static int vidioc_reqbufs(struct file *file, void *priv,
++ struct v4l2_requestbuffers *p)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ return vb2_reqbufs(&dev->vb_vidq, p);
++}
++
++static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ return vb2_querybuf(&dev->vb_vidq, p);
++}
++
++static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ return vb2_qbuf(&dev->vb_vidq, p);
++}
++
++static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
++}
++
++static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ return vb2_streamon(&dev->vb_vidq, i);
++}
++
++static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ return vb2_streamoff(&dev->vb_vidq, i);
++}
++
++static int vidioc_log_status(struct file *file, void *priv)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name);
++ return 0;
++}
++
++static int vidioc_enum_input(struct file *file, void *priv,
++ struct v4l2_input *inp)
++{
++ if (inp->index > 0)
++ return -EINVAL;
++
++ inp->type = V4L2_INPUT_TYPE_CAMERA;
++ sprintf(inp->name, "Camera %u", inp->index);
++
++ return 0;
++}
++
++static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
++{
++ *i = 0;
++
++ return 0;
++}
++
++static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
++{
++ if (i > 0)
++ return -EINVAL;
++
++ return 0;
++}
++
++static int vidioc_subscribe_event(struct v4l2_fh *fh,
++ const struct v4l2_event_subscription *sub)
++{
++ switch (sub->type) {
++ case V4L2_EVENT_CTRL:
++ return v4l2_event_subscribe(fh, sub, 0, NULL);
++ default:
++ return -EINVAL;
++ }
++}
++
++static const struct v4l2_ioctl_ops cssp_cam_ioctl_ops = {
++ .vidioc_querycap = vidioc_querycap,
++ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
++ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
++ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
++ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
++ .vidioc_reqbufs = vidioc_reqbufs,
++ .vidioc_querybuf = vidioc_querybuf,
++ .vidioc_qbuf = vidioc_qbuf,
++ .vidioc_dqbuf = vidioc_dqbuf,
++ .vidioc_enum_input = vidioc_enum_input,
++ .vidioc_g_input = vidioc_g_input,
++ .vidioc_s_input = vidioc_s_input,
++ .vidioc_streamon = vidioc_streamon,
++ .vidioc_streamoff = vidioc_streamoff,
++ .vidioc_log_status = vidioc_log_status,
++ .vidioc_subscribe_event = vidioc_subscribe_event,
++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
++};
++
++
++/* ------------------------------------------------------------------
++ File operations
++ ------------------------------------------------------------------*/
++
++static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ struct v4l2_fh *fh = file->private_data;
++ struct vb2_queue *q = &dev->vb_vidq;
++ unsigned int res;
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
++ res = vb2_poll(q, file, wait);
++ if (v4l2_event_pending(fh))
++ res |= POLLPRI;
++ else
++ poll_wait(file, &fh->wait, wait);
++ return res;
++}
++
++static int video_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct cssp_cam_dev *dev = video_drvdata(file);
++ int ret;
++
++ dev_dbg(&dev->pdev->dev, "mmap called, vma=0x%08lx\n",
++ (unsigned long)vma);
++
++ ret = vb2_mmap(&dev->vb_vidq, vma);
++ dev_dbg(&dev->pdev->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
++ (unsigned long)vma->vm_start,
++ (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
++ ret);
++ return ret;
++}
++
++static ssize_t video_read(struct file *file, char __user *buf,
++ size_t size, loff_t *offset)
++{
++ struct cssp_cam_dev *cam_dev = video_drvdata(file);
++
++ dev_dbg(&cam_dev->pdev->dev, "%s\n", __func__);
++
++ return vb2_read(&cam_dev->vb_vidq, buf, size, offset,
++ file->f_flags & O_NONBLOCK);
++}
++
++static int video_close(struct file *file)
++{
++ struct video_device *vdev = video_devdata(file);
++ struct cssp_cam_dev *cam_dev = video_drvdata(file);
++
++ dev_dbg(&cam_dev->pdev->dev, "close called (dev=%s), file %p\n",
++ video_device_node_name(vdev), file);
++
++ if (v4l2_fh_is_singular_file(file))
++ vb2_queue_release(&cam_dev->vb_vidq);
++ return v4l2_fh_release(file);
++}
++
++static const struct v4l2_file_operations cssp_cam_fops = {
++ .owner = THIS_MODULE,
++ .open = v4l2_fh_open,
++ .release = video_close,
++ .read = video_read,
++ .poll = video_poll,
++ .unlocked_ioctl = video_ioctl2,
++ .mmap = video_mmap,
++};
++
++
++/* ------------------------------------------------------------------
++ Driver initialization
++ ------------------------------------------------------------------*/
++
++static struct video_device cssp_cam_template = {
++ .name = "cssp_camera",
++ .fops = &cssp_cam_fops,
++ .ioctl_ops = &cssp_cam_ioctl_ops,
++ .minor = -1,
++ .release = video_device_release,
++};
++
++static int video_probe(struct cssp_cam_dev *cam_dev)
++{
++ struct video_device *vfd;
++ struct v4l2_ctrl_handler *hdl;
++ struct vb2_queue *q;
++ int ret = 0;
++
++ snprintf(cam_dev->v4l2_dev.name, sizeof(cam_dev->v4l2_dev.name),
++ "%s-%03d", "cssp_camera", 0);
++ ret = v4l2_device_register(NULL, &cam_dev->v4l2_dev);
++ if (ret)
++ goto free_dev;
++
++ cam_dev->fmt = &formats[0];
++ cam_dev->width = VGA_WIDTH;
++ cam_dev->height = VGA_HEIGHT;
++ cam_dev->sizeimage = VGA_WIDTH * VGA_HEIGHT * BYTES_PER_PIXEL;
++ hdl = &cam_dev->ctrl_handler;
++ v4l2_ctrl_handler_init(hdl, 0);
++
++ if (hdl->error) {
++ ret = hdl->error;
++ goto unreg_dev;
++ }
++ cam_dev->v4l2_dev.ctrl_handler = hdl;
++
++ /* initialize locks */
++ spin_lock_init(&cam_dev->slock);
++
++ /* initialize queue */
++ q = &cam_dev->vb_vidq;
++ memset(q, 0, sizeof(cam_dev->vb_vidq));
++ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ q->io_modes = VB2_MMAP | VB2_READ;
++ q->drv_priv = cam_dev;
++ q->buf_struct_size = sizeof(struct cssp_cam_buffer);
++ q->ops = &cssp_cam_video_qops;
++ q->mem_ops = &vb2_dma_contig_memops;
++
++ ret = vb2_queue_init(q);
++ if (ret != 0) {
++ goto unreg_dev;
++ }
++
++ mutex_init(&cam_dev->mutex);
++
++ /* init video dma queues */
++ INIT_LIST_HEAD(&cam_dev->vidq.active);
++
++ ret = -ENOMEM;
++ vfd = video_device_alloc();
++ if (!vfd)
++ goto unreg_dev;
++
++ *vfd = cssp_cam_template;
++ vfd->v4l2_dev = &cam_dev->v4l2_dev;
++ set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
++
++ /*
++ * Provide a mutex to v4l2 core. It will be used to protect
++ * all fops and v4l2 ioctls.
++ */
++ vfd->lock = &cam_dev->mutex;
++
++ ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
++ if (ret < 0)
++ goto rel_vdev;
++
++ video_set_drvdata(vfd, cam_dev);
++
++ if (video_nr != -1)
++ video_nr++;
++
++ cam_dev->vdev = vfd;
++ v4l2_info(&cam_dev->v4l2_dev, "V4L2 device registered as %s\n",
++ video_device_node_name(vfd));
++
++ return 0;
++
++rel_vdev:
++ video_device_release(vfd);
++unreg_dev:
++ v4l2_ctrl_handler_free(hdl);
++ v4l2_device_unregister(&cam_dev->v4l2_dev);
++free_dev:
++ return ret;
++}
++
++static int video_remove(struct cssp_cam_dev *cam_dev)
++{
++ if (cam_dev->dma_cont_ctx != NULL)
++ vb2_dma_contig_cleanup_ctx(cam_dev->dma_cont_ctx);
++
++ v4l2_info(&cam_dev->v4l2_dev, "unregistering %s\n",
++ video_device_node_name(cam_dev->vdev));
++ video_unregister_device(cam_dev->vdev);
++ v4l2_device_unregister(&cam_dev->v4l2_dev);
++ v4l2_ctrl_handler_free(&cam_dev->ctrl_handler);
++
++ return 0;
++}
++
++#ifdef CONFIG_OF
++
++static const struct of_device_id cssp_camera_of_match[] = {
++ { .compatible = "cssp-camera", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, cssp_camera_of_match);
++
++struct cssp_cam_platform_data *
++of_get_cssp_platform_data(struct platform_device *pdev)
++{
++ struct cssp_cam_platform_data *pdata;
++ struct cssp_cam_platform_data_storage *pstore;
++ struct device *dev = &pdev->dev;
++ struct device_node *np, *nps, *npc, *npa;
++ struct i2c_adapter *adap;
++ struct of_phandle_args args;
++ u32 val, valarr[9];
++ int ret, found, gpio_orientation_pin;
++
++ np = dev->of_node;
++ nps = NULL;
++ npc = NULL;
++ npa = NULL;
++ adap = NULL;
++ memset(&args, 0, sizeof(args));
++ pstore = NULL;
++ gpio_orientation_pin = -1;
++
++ if (np == NULL) {
++ dev_err(dev, "No OF device node\n");
++ goto err_fail;
++ }
++ pstore = devm_kzalloc(dev, sizeof(*pstore), GFP_KERNEL);
++ if (pstore == NULL) {
++ dev_err(dev, "Failed to allocate platform data storage\n");
++ goto err_fail;
++ }
++
++ /* link the structures together */
++ pdata = &pstore->pdata;
++ pdata->cam_i2c_board_info = &pstore->i2c_camera;
++ pstore->i2c_camera.platform_data = &pstore->camera_link;
++ pstore->camera_link.priv = &pstore->mt9t111_cam_info;
++
++ ret = of_property_read_string(np, "cssp,camera-clk-name",
++ &pdata->cam_clk_name);
++ if (ret != 0) {
++ dev_err(dev, "No cssp,camera-clk-name property\n");
++ goto err_fail;
++ }
++
++ ret = of_property_read_u32(np, "cssp,camera-clk-rate",
++ &pdata->cam_clk_rate);
++ if (ret != 0) {
++ dev_err(dev, "no cssp,camera-clk-rate property\n");
++ goto err_fail;
++ }
++
++ /* we don't use the dma accessors, but we use the format */
++ ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", 0, &args);
++ if (ret != 0 || args.args_count < 1) {
++ dev_err(dev, "No valid dmas property\n");
++ goto err_fail;
++ }
++ pdata->dma_ch = args.args[0];
++ /* release ref */
++ of_node_put(args.np);
++ args.np = NULL;
++
++ /* can possibly fail */
++ pdata->gpio_reset_pin = of_get_named_gpio(np,
++ "reset-gpio", 0);
++
++ gpio_orientation_pin = of_get_named_gpio(np,
++ "orientation-gpio", 0);
++
++ /* get sensor node */
++ nps = of_get_child_by_name(np, "cssp,sensor");
++ if (nps == NULL) {
++ dev_err(dev, "Failed to get sensor node\n");
++ goto err_fail;
++ }
++
++ /* find the i2c adapter number */
++ npa = of_parse_phandle(nps, "i2c-adapter", 0);
++ if (np == NULL) {
++ dev_err(dev, "Failed to get i2c-adapter property");
++ goto err_fail;
++ }
++ adap = of_find_i2c_adapter_by_node(npa);
++ if (adap == NULL) {
++ dev_err(dev, "Failed to find i2c-adapter");
++ goto err_fail;
++ }
++ pstore->camera_link.i2c_adapter_id = adap->nr;
++
++ /* release i2c adapter device ref */
++ put_device(&adap->dev);
++ adap = NULL;
++
++ /* release i2c adapter device node */
++ of_node_put(npa);
++ npa = NULL;
++
++ /* now find the sensor node */
++ for_each_available_child_of_node(nps, npc) {
++ /* we only support a single sensor for now */
++ if (of_device_is_compatible(npc, "aptina,mt9t112")) {
++ strncpy(pstore->i2c_camera.type, "mt9t112",
++ sizeof(pstore->i2c_camera.type));
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found) {
++ dev_err(dev, "Failed to find sensor node");
++ goto err_fail;
++ }
++
++ if (of_property_read_u32(npc, "reg", &val) != 0) {
++ dev_err(dev, "Could not get sensor reg property\n");
++ goto err_fail;
++ }
++ pstore->i2c_camera.addr = val;
++
++ if (of_property_read_u32_array(npc, "pll-divider", valarr, ARRAY_SIZE(valarr)) != 0) {
++ dev_err(dev, "Could not get pll-divider property\n");
++ goto err_fail;
++ }
++ pstore->mt9t111_cam_info.divider.m = valarr[0];
++ pstore->mt9t111_cam_info.divider.n = valarr[1];
++ pstore->mt9t111_cam_info.divider.p1 = valarr[2];
++ pstore->mt9t111_cam_info.divider.p2 = valarr[3];
++ pstore->mt9t111_cam_info.divider.p3 = valarr[4];
++ pstore->mt9t111_cam_info.divider.p4 = valarr[5];
++ pstore->mt9t111_cam_info.divider.p5 = valarr[6];
++ pstore->mt9t111_cam_info.divider.p6 = valarr[7];
++ pstore->mt9t111_cam_info.divider.p7 = valarr[8];
++
++ if (of_property_read_u32(npc, "flags", &val) != 0) {
++ dev_err(dev, "Could not get sensor flags property\n");
++ goto err_fail;
++ }
++
++ /* read orientation gpio and set/clr MT9T112_FLAG_VFLIP */
++ if (gpio_is_valid(gpio_orientation_pin)) {
++ ret = gpio_request(gpio_orientation_pin, "camera orientation");
++ if (ret != 0) {
++ dev_err(dev, "Could not gpio_request orientation\n");
++ goto err_fail;
++ }
++ ret = gpio_direction_input(gpio_orientation_pin);
++ if (ret != 0) {
++ dev_err(dev, "Could not set orientation to input\n");
++ gpio_free(gpio_orientation_pin);
++ goto err_fail;
++ }
++ ret = gpio_get_value(gpio_orientation_pin);
++ if (ret < 0) {
++ dev_err(dev, "Could not get orientation value\n");
++ gpio_free(gpio_orientation_pin);
++ goto err_fail;
++ }
++ gpio_free(gpio_orientation_pin);
++
++ /* set orientation flag */
++
++ /*
++ * But the driver in mainline doesn't support flip
++ * Commented out for now...
++ *
++ * if (ret)
++ * val |= MT9T112_FLAG_VFLIP;
++ * else
++ * val &= ~MT9T112_FLAG_VFLIP
++ */
++ }
++ pstore->mt9t111_cam_info.flags = val;
++
++ /* release refs */
++
++ of_node_put(npc);
++ npc = NULL;
++ of_node_put(nps);
++ nps = NULL;
++
++ return pdata;
++
++err_fail:
++ /* NULL is handled as a NOP */
++ of_node_put(nps);
++ of_node_put(npc);
++ of_node_put(npa);
++
++ /* release adapter */
++ if (adap != NULL)
++ put_device(&adap->dev);
++
++ /* free memory (even if it will be automatically freed it's good practice) */
++ if (pstore != NULL)
++ devm_kfree(dev, pstore);
++
++ return NULL;
++}
++
++#else
++struct cssp_cam_platform_data *of_get_cssp_platform_data(struct platform_device *pdev)
++{
++ return NULL;
++}
++#endif
++
++static int cssp_cam_probe(struct platform_device *pdev)
++{
++ struct cssp_cam_dev *cam_dev;
++ struct cssp_cam_platform_data *pdata;
++ struct pinctrl *pinctrl;
++ int ret = 0, use_of_pdata = 0;
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ pdata = pdev->dev.platform_data;
++
++ /* if not found, try DT */
++ if (pdata == NULL) {
++ pdata = of_get_cssp_platform_data(pdev);
++ use_of_pdata = pdata != NULL;
++ }
++
++ if (pdata == NULL) {
++ dev_err(&pdev->dev, "missing platform data\n");
++ return -ENODEV;
++ }
++ pdev->dev.platform_data = pdata;
++
++ if (pdata->cam_i2c_board_info == NULL) {
++ dev_err(&pdev->dev, "missing camera i2c board info\n");
++ return -ENODEV;
++ }
++
++ cam_dev = kzalloc(sizeof(*cam_dev), GFP_KERNEL);
++ if (!cam_dev)
++ return -ENOMEM;
++
++ /* keep the pointer of the of pdata storage */
++ if (use_of_pdata)
++ cam_dev->pstore = to_cssp_platform_data_storage(pdata);
++
++ cam_dev->pdev = pdev;
++ platform_set_drvdata(pdev, cam_dev);
++
++ cam_dev->camera_board_info = pdata->cam_i2c_board_info;
++
++ cam_dev->camera_clk = clk_get(&pdev->dev, pdata->cam_clk_name);
++ if (IS_ERR(cam_dev->camera_clk)) {
++ ret = PTR_ERR(cam_dev->camera_clk);
++ dev_err(&pdev->dev, "cannot clk_get %s\n", pdata->cam_clk_name);
++ goto fail0;
++ }
++
++ /* 32MHz */
++ ret = clk_set_rate(cam_dev->camera_clk, pdata->cam_clk_rate);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "failed to set clk rate\n");
++ goto fail1;
++ }
++
++ if (clk_get_rate(cam_dev->camera_clk) != pdata->cam_clk_rate) {
++ dev_err(&pdev->dev, "No accurate clock found\n");
++ goto fail1;
++ }
++
++ clk_prepare(cam_dev->camera_clk);
++
++ ret = configure_cssp(cam_dev);
++ if (ret) {
++ dev_err(&pdev->dev, "configure_cssp failed\n");
++ goto fail1;
++ }
++
++ ret = configure_edma(cam_dev);
++ if (ret) {
++ dev_err(&pdev->dev, "configure_dma failed\n");
++ goto fail2;
++ }
++
++ cam_dev->mode = FMT_2X8_EN | PCLK_POL | HS_EN; // falling edge
++ if (cam_dev->rev > 3)
++ cam_dev->mode |= LDR_EN;
++
++ ret = configure_camera_sensor(cam_dev);
++ if (ret) {
++ dev_err(&pdev->dev, "camera sensor configuration failed\n");
++ goto fail3;
++ }
++
++ cam_dev->dma_cont_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
++ if (IS_ERR(cam_dev->dma_cont_ctx)) {
++ ret = PTR_ERR(cam_dev->dma_cont_ctx);
++ goto fail3;
++ }
++
++ ret = video_probe(cam_dev);
++ if (ret)
++ goto fail4;
++
++ dev_err(&pdev->dev, "Loaded OK.\n");
++
++ return 0;
++
++fail4:
++ vb2_dma_contig_cleanup_ctx(cam_dev->dma_cont_ctx);
++
++fail3:
++ edma_free_channel(cam_dev->dma_ch);
++fail2:
++ if (gpio_is_valid(cam_dev->reset_pin))
++ gpio_free(cam_dev->reset_pin);
++
++ iounmap(cam_dev->reg_base_virt);
++ release_mem_region(cam_dev->reg_base_phys, cam_dev->reg_size);
++
++fail1:
++ clk_put(cam_dev->camera_clk);
++
++fail0:
++ kfree(cam_dev);
++
++ return ret;
++}
++
++static int cssp_cam_remove(struct platform_device *pdev)
++{
++ struct cssp_cam_dev *cam = platform_get_drvdata(pdev);
++
++ iounmap(cam->reg_base_virt);
++
++ release_mem_region(cam->reg_base_phys, cam->reg_size);
++
++ if (gpio_is_valid(cam->reset_pin))
++ gpio_free(cam->reset_pin);
++
++ if (cam->dma_ch)
++ edma_free_channel(cam->dma_ch);
++
++ video_remove(cam);
++
++ clk_put(cam->camera_clk);
++
++ kfree(cam);
++
++ dev_info(&pdev->dev, "removed\n");
++
++ return 0;
++}
++
++
++static struct platform_driver cssp_cam_driver = {
++ .probe = cssp_cam_probe,
++ .remove = cssp_cam_remove,
++ .driver = {
++ .name = "cssp-camera",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(cssp_camera_of_match),
++ },
++};
++
++module_platform_driver(cssp_cam_driver);
++
++
++/*
++ * Macros sets license, author and description
++ */
++MODULE_LICENSE("GPLv2");
++MODULE_AUTHOR("Dan Aizenstros, Damian Eppel, Przemek Szewczyk");
++MODULE_DESCRIPTION("QuickLogic Camera Interface driver");
++
diff --git a/patches/linux-3.8.13/0608-capes-Add-BB-BONE-CAM3-cape.patch b/patches/linux-3.8.13/0608-capes-Add-BB-BONE-CAM3-cape.patch
new file mode 100644
index 0000000..f59fd15
--- /dev/null
+++ b/patches/linux-3.8.13/0608-capes-Add-BB-BONE-CAM3-cape.patch
@@ -0,0 +1,202 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 16:51:56 +0300
+Subject: [PATCH] capes: Add BB-BONE-CAM3 cape
+
+Add the cape definition for the CAM3 cape
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/BB-BONE-CAM3-01-00A2.dts | 184 +++++++++++++++++++++++++++++++
+ 1 file changed, 184 insertions(+)
+ create mode 100644 firmware/capes/BB-BONE-CAM3-01-00A2.dts
+
+diff --git a/firmware/capes/BB-BONE-CAM3-01-00A2.dts b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
+new file mode 100644
+index 0000000..97bdcfd
+--- /dev/null
++++ b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
+@@ -0,0 +1,184 @@
++/*
++ * Copyright (C) 2013 Circuit Co.
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone";
++
++ /* identification */
++ part-number = "BB-BONE-CAM3-01";
++ version = "00A2", "A2";
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ gpmc_pins: pinmux_gpmc_pins {
++ pinctrl-single,pins = <
++ 0x000 0x30 /* gpmc_ad0.gpmc_ad0 MODE0 | INPUT | PULLUP */
++ 0x004 0x30 /* gpmc_ad1.gpmc_ad1 MODE0 | INPUT | PULLUP */
++ 0x008 0x30 /* gpmc_ad2.gpmc_ad2 MODE0 | INPUT | PULLUP */
++ 0x00C 0x30 /* gpmc_ad3.gpmc_ad3 MODE0 | INPUT | PULLUP */
++ 0x010 0x30 /* gpmc_ad4.gpmc_ad4 MODE0 | INPUT | PULLUP */
++ 0x014 0x30 /* gpmc_ad5.gpmc_ad5 MODE0 | INPUT | PULLUP */
++ 0x018 0x30 /* gpmc_ad6.gpmc_ad6 MODE0 | INPUT | PULLUP */
++ 0x01C 0x30 /* gpmc_ad7.gpmc_ad7 MODE0 | INPUT | PULLUP */
++ 0x020 0x30 /* gpmc_ad8.gpmc_ad8 MODE0 | INPUT | PULLUP */
++ 0x024 0x30 /* gpmc_ad9.gpmc_ad9 MODE0 | INPUT | PULLUP */
++ 0x028 0x30 /* gpmc_ad10.gpmc_ad10 MODE0 | INPUT | PULLUP */
++ 0x02C 0x30 /* gpmc_ad11.gpmc_ad11 MODE0 | INPUT | PULLUP */
++ 0x030 0x30 /* gpmc_ad12.gpmc_ad12 MODE0 | INPUT | PULLUP */
++ 0x034 0x30 /* gpmc_ad13.gpmc_ad13 MODE0 | INPUT | PULLUP */
++ 0x038 0x30 /* gpmc_ad14.gpmc_ad14 MODE0 | INPUT | PULLUP */
++ 0x03C 0x30 /* gpmc_ad15.gpmc_ad15 MODE0 | INPUT | PULLUP */
++ 0x074 0x30 /* gpmc_wpn.gpmc_wpn MODE0 | INPUT | PULLUP */ /* WAS MODE 7 */
++ 0x080 0x08 /* gpmc_wait0.gpmc_cscn1 MODE0 | OUTPUT */
++ 0x08C 0x28 /* gpmc_clk.gpmc_clk MODE0 | INPUT */
++ 0x090 0x08 /* gpmc_advn_ale.gpmc_advn_ale MODE0 | OUTPUT */
++ 0x094 0x08 /* gpmc_oen_ren.gpmc_oen_ren MODE0 | OUTPUT */
++ 0x098 0x08 /* gpmc_wen.gpmc_wen MODE0 | OUTPUT */
++ 0x09C 0x08 /* gpmc_ben0_cle.gpmc_ben0_cle MODE0 | OUTPUT */
++ >;
++ };
++ cssp_camera_pins: pinmux_cssp_camera_pins {
++ pinctrl-single,pins = <
++ /* clkout2 */
++ 0x1B4 0x03 /* xdma_event_intr1.clkout2 MODE3 | OUTPUT clkout2 */
++
++ /* dmar */
++ 0x164 0x2e /* ecap0_in_pwm0_out.xdma_event_intr2 MODE6 | INPUT */
++
++ /* cssp camera */
++ 0x158 0x07 /* spi0_d1.gpio0_4 MODE7 | OUTPUT, QL CSSP and Camera Sensor Reset */
++ 0x15C 0x17 /* spi0_cs0.gpio0_5 MODE7 | OUTPUT | PULLUP, 1V8 and 2V8 Power Enable */
++ 0x070 0x2f /* gpmc_wait0.gpio0_30 MODE0 | INPUT | PULLUPDIS, Sensor orientation detect: low -> frontfacing, high -> backfacing */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&gpmc>;
++ depth = <1>; /* only create devices on depth 1 */
++
++ /* stupid warnings */
++ #address-cells = <1>;
++ #size-cells = <1>;
++ ranges;
++
++ __overlay__ {
++
++ status = "okay";
++
++ #address-cells = <2>;
++ #size-cells = <1>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpmc_pins>;
++
++ /* chip select ranges */
++ ranges = <0 0 0x08000000 0x10000000>, /* bootloader has this enabled */
++ <1 0 0x18000000 0x08000000>,
++ <2 0 0x20000000 0x08000000>,
++ <3 0 0x28000000 0x08000000>,
++ <4 0 0x30000000 0x08000000>,
++ <5 0 0x38000000 0x04000000>,
++ <6 0 0x3c000000 0x04000000>;
++
++ /*
++ * This is complete and utter cr*p
++ * It doesn't belong here, but we don't
++ * have a memory controller abstraction.
++ * So we muddle along...
++ */
++ camera {
++ compatible = "cssp-camera";
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&cssp_camera_pins>;
++
++ reg = <1 0 0x01000000>; /* CS1 */
++
++ bank-width = <2>; /* GPMC_CONFIG1_DEVICESIZE(1) */
++
++ gpmc,burst-read; /* GPMC_CONFIG1_READMULTIPLE_SUPP */
++ gpmc,sync-read; /* GPMC_CONFIG1_READTYPE_SYNC */
++ gpmc,sync-write; /* GPMC_CONFIG1_WRITETYPE_SYNC */
++ gpmc,clk-activation-ns = <20>; /* GPMC_CONFIG1_CLKACTIVATIONTIME(2) */
++ gpmc,burst-length = <16>; /* GPMC_CONFIG1_PAGE_LEN(2) */
++ gpmc,mux-add-data = <2>; /* GPMC_CONFIG1_MUXTYPE(2) */
++
++ gpmc,sync-clk-ps = <20000>; /* CONFIG2 */
++
++ gpmc,cs-on-ns = <1>;
++ gpmc,cs-rd-off-ns = <160>;
++ gpmc,cs-wr-off-ns = <310>;
++
++ gpmc,adv-on-ns = <0>; /* CONFIG3 */
++ gpmc,adv-rd-off-ns = <40>;
++ gpmc,adv-wr-off-ns = <40>;
++
++ gpmc,we-on-ns = <60>; /* CONFIG4 */
++ gpmc,we-off-ns = <310>;
++ gpmc,oe-on-ns = <60>;
++ gpmc,oe-off-ns = <160>;
++
++ gpmc,page-burst-access-ns = <20>; /* CONFIG 5 */
++ gpmc,access-ns = <140>;
++ gpmc,rd-cycle-ns = <160>;
++ gpmc,wr-cycle-ns = <310>;
++
++ gpmc,wr-access-ns = <100>; /* CONFIG 6 */
++ gpmc,wr-data-mux-bus-ns = <60>;
++
++ gpmc,bus-turnaround-ns = <40>; /* CONFIG6:3:0 = 4 */
++ gpmc,cycle2cycle-samecsen; /* CONFIG6:7 = 1 */
++ gpmc,cycle2cycle-delay-ns = <40>; /* CONFIG6:11:8 = 4 */
++
++ /* not using dma engine yet, but we can get the channel number here */
++ dmas = <&edma 20>;
++ dma-names = "cssp";
++
++ /* clocks */
++ cssp,camera-clk-name = "adjustable_clkout2_ck";
++ cssp,camera-clk-rate = <32000000>;
++
++ /* reset */
++ reset-gpio = <&gpio1 4 0>;
++
++ /* orientation; -> MT9T112_FLAG_VFLIP */
++ orientation-gpio = <&gpio1 30 0>;
++
++ /* camera sensor */
++ cssp,sensor {
++ i2c-adapter = <&i2c2>;
++
++ /* need it to stop the whinning */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* fake i2c device node */
++ m59t112 {
++ compatible = "aptina,mt9t112";
++ reg = <0x3c>;
++
++ /* m, n, p1-7 */
++ flags = <0>;
++ pll-divider = <24 1 0 7 0 10 14 7 0>;
++ };
++ };
++ };
++
++ };
++ };
++
++};
diff --git a/patches/linux-3.8.13/0609-cssp_camera-Correct-license-identifier.patch b/patches/linux-3.8.13/0609-cssp_camera-Correct-license-identifier.patch
new file mode 100644
index 0000000..974b5d7
--- /dev/null
+++ b/patches/linux-3.8.13/0609-cssp_camera-Correct-license-identifier.patch
@@ -0,0 +1,24 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 1 May 2013 20:49:48 +0300
+Subject: [PATCH] cssp_camera: Correct license identifier
+
+GPLv2 != GPL v2 for license reasons
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/media/platform/soc_camera/cssp_camera.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+index 41de42e..0bc6a28 100644
+--- a/drivers/media/platform/soc_camera/cssp_camera.c
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -1554,7 +1554,7 @@ module_platform_driver(cssp_cam_driver);
+ /*
+ * Macros sets license, author and description
+ */
+-MODULE_LICENSE("GPLv2");
++MODULE_LICENSE("GPL v2");
+ MODULE_AUTHOR("Dan Aizenstros, Damian Eppel, Przemek Szewczyk");
+ MODULE_DESCRIPTION("QuickLogic Camera Interface driver");
+
diff --git a/patches/linux-3.8.13/0610-cssp_camera-increase-delays-make-sensor-detection-wo.patch b/patches/linux-3.8.13/0610-cssp_camera-increase-delays-make-sensor-detection-wo.patch
new file mode 100644
index 0000000..45c09f7
--- /dev/null
+++ b/patches/linux-3.8.13/0610-cssp_camera-increase-delays-make-sensor-detection-wo.patch
@@ -0,0 +1,32 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 2 May 2013 12:06:12 +0200
+Subject: [PATCH] cssp_camera: increase delays make sensor detection work
+ better
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/media/platform/soc_camera/cssp_camera.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+index 0bc6a28..0a0cd8f 100644
+--- a/drivers/media/platform/soc_camera/cssp_camera.c
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -471,7 +471,7 @@ static int configure_camera_sensor(struct cssp_cam_dev *cam)
+ /* Enable the clock just for the time of loading the camera driver and disable after that */
+ /* It is going to be be re-enabled later, when camera will be in use */
+ clk_enable(cam->camera_clk);
+- udelay(5); // let the clock stabilize
++ mdelay(50); // let the clock stabilize
+
+ adapter = i2c_get_adapter(((struct soc_camera_link *)(info->platform_data))->i2c_adapter_id);
+ if (!adapter) {
+@@ -504,7 +504,7 @@ static int configure_camera_sensor(struct cssp_cam_dev *cam)
+ static int start_camera_sensor(struct cssp_cam_dev *cam)
+ {
+ clk_enable(cam->camera_clk);
+- udelay(5); /* let the clock stabilize */
++ mdelay(100); /* let the clock stabilize */
+
+ v4l2_subdev_call(cam->subdev, video, s_stream, 1);
+
diff --git a/patches/linux-3.8.13/0611-mt9t112-forward-port-optimizations-from-Angstrom-3.2.patch b/patches/linux-3.8.13/0611-mt9t112-forward-port-optimizations-from-Angstrom-3.2.patch
new file mode 100644
index 0000000..1beec04
--- /dev/null
+++ b/patches/linux-3.8.13/0611-mt9t112-forward-port-optimizations-from-Angstrom-3.2.patch
@@ -0,0 +1,585 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 2 May 2013 12:06:27 +0200
+Subject: [PATCH] mt9t112: forward port optimizations from Angstrom 3.2 kernel
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/media/i2c/soc_camera/mt9t112.c | 502 +++++++++++++++++++++++++++++++-
+ include/media/mt9t112.h | 2 +
+ 2 files changed, 502 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
+index de7cd83..d83d217 100644
+--- a/drivers/media/i2c/soc_camera/mt9t112.c
++++ b/drivers/media/i2c/soc_camera/mt9t112.c
+@@ -33,6 +33,8 @@
+ /* you can check PLL/clock info */
+ /* #define EXT_CLOCK 24000000 */
+
++//#define TEST_PATTERN
++
+ /************************************************************************
+ macro
+ ************************************************************************/
+@@ -67,6 +69,8 @@
+
+ #define mt9t112_reg_read(ret, client, a) \
+ ECHECKER(ret, __mt9t112_reg_read(client, a))
++#define mt9t112_mcu_read(ret, client, a) \
++ ECHECKER(ret, __mt9t112_mcu_read(client, a))
+
+ /*
+ * Logical address
+@@ -85,6 +89,33 @@ struct mt9t112_format {
+ u16 order;
+ };
+
++struct mt9t112_resolution_param {
++ u16 col_strt;
++ u16 row_end;
++ u16 col_end;
++ u16 read_mode;
++ u16 fine_cor;
++ u16 fine_min;
++ u16 fine_max;
++ u16 base_lines;
++ u16 min_lin_len;
++ u16 line_len;
++ u16 con_width;
++ u16 con_height;
++ u16 s_f1_50;
++ u16 s_f2_50;
++ u16 s_f1_60;
++ u16 s_f2_60;
++ u16 per_50;
++ u16 per_50_M;
++ u16 per_60;
++ u16 fd_w_height;
++ u16 tx_water;
++ u16 max_fd_50;
++ u16 max_fd_60;
++ u16 targ_fd;
++};
++
+ struct mt9t112_priv {
+ struct v4l2_subdev subdev;
+ struct mt9t112_camera_info *info;
+@@ -96,6 +127,7 @@ struct mt9t112_priv {
+ /* for flags */
+ #define INIT_DONE (1 << 0)
+ #define PCLK_RISING (1 << 1)
++ struct mt9t112_resolution_param resolution;
+ };
+
+ /************************************************************************
+@@ -412,6 +444,453 @@ static int mt9t112_set_pll_dividers(const struct i2c_client *client,
+ return ret;
+ }
+
++static int mt9t112_set_resolution_params(const struct i2c_client *client)
++{
++ int ret = 1;
++ struct mt9t112_priv *priv = to_mt9t112(client);
++ struct mt9t112_resolution_param *resolution = &priv->resolution;
++
++ if ((priv->frame.width == 1280) && (priv->frame.height == 720)) {
++ resolution->col_strt = 0x0004;
++ resolution->row_end = 0x05AD;
++ resolution->col_end = 0x050B;
++ resolution->read_mode = 0x002C;
++ resolution->fine_cor = 0x008C;
++ resolution->fine_min = 0x01F1;
++ resolution->fine_max = 0x00FF;
++ resolution->base_lines = 0x032D;
++ resolution->min_lin_len = 0x0378;
++ resolution->line_len = 0x091C;
++ resolution->con_width = 0x0508;
++ resolution->con_height = 0x02D8;
++ resolution->s_f1_50 = 0x23;
++ resolution->s_f2_50 = 0x25;
++ resolution->s_f1_60 = 0x2B;
++ resolution->s_f2_60 = 0x2D;
++ resolution->per_50 = 0xDC;
++ resolution->per_50_M = 0x00;
++ resolution->per_60 = 0xB7;
++ resolution->fd_w_height = 0x05;
++ resolution->tx_water = 0x0210;
++ resolution->max_fd_50 = 0x0004;
++ resolution->max_fd_60 = 0x0004;
++ resolution->targ_fd = 0x0004;
++ } else if ((priv->frame.width <= 1024) && (priv->frame.height <= 768) &&
++ (priv->frame.width != priv->frame.height)) {
++ resolution->col_strt = 0x000;
++ resolution->row_end = 0x60D;
++ resolution->col_end = 0x80D;
++ resolution->read_mode = 0x046C;
++ resolution->fine_cor = 0x00CC;
++ resolution->fine_min = 0x0381;
++ resolution->fine_max = 0x024F;
++ resolution->base_lines = 0x0364;
++ resolution->min_lin_len = 0x05D0;
++ resolution->line_len = 0x07AC;
++ resolution->con_width = 0x0408;
++ resolution->con_height = 0x0308;
++ resolution->s_f1_50 = 0x23;
++ resolution->s_f2_50 = 0x25;
++ resolution->s_f1_60 = 0x2A;
++ resolution->s_f2_60 = 0x2C;
++ resolution->per_50 = 0x05;
++ resolution->per_50_M = 0x01;
++ resolution->per_60 = 0xD9;
++ resolution->fd_w_height = 0x06;
++ resolution->max_fd_50 = 0x0003;
++ resolution->max_fd_60 = 0x0004;
++ resolution->targ_fd = 0x0003;
++ if ((priv->frame.width == 1024) && (priv->frame.height == 768)) {
++ resolution->tx_water = 0x0218;
++ } else if ((priv->frame.width == 800) && (priv->frame.height == 480)) {
++ resolution->tx_water = 0x02DA;
++ } else { // 640 x 480 but use it with everything else until we figure out how to calc it
++ resolution->tx_water = 0x0352;
++ }
++ } else {
++ ret = 0;
++ }
++
++ return ret;
++}
++
++static int mt9t112_pll_setup_custom_pll(const struct i2c_client *client)
++{
++/*
++; Bypass PLL: Unchecked
++; Input Frequency: 32.000
++; Target Pads Frequency: 96.000
++; Target I2C Clock Frequency: 100.000
++; Target VCO Frequency: Unspecified
++; For Parallel Output: Checked
++; "M" Value: Unspecified
++; "N" Value: Unspecified
++;
++; Target Pads Clock Frequency: 96 MHz
++; Input Clock Frequency: 32 MHz
++;
++; Actual Pads Clock Frequency: 96 MHz
++; Sensor Core Clock Frequency: 54.857 MHz
++; SOC Clock Frequency: 54.857 MHz
++; MCU Clock Frequency: 96 MHz
++; I2C Master Clock Frequency: 99.740 KHz
++;
++; M = 24
++; N = 1
++; Fpdf = 16 MHz
++; Fvco = 768 MHz
++; P2 = 8
++; P4 = 14
++; P5 = 14
++; P6 = 8
++*/
++ int data, i, ret;
++
++ mt9t112_reg_mask_set(ret, client, 0x14, 1, 1); // Bypass PLL
++ mt9t112_reg_mask_set(ret, client, 0X14, 2, 0); // Power-down PLL
++ mt9t112_reg_write(ret, client, 0x0014, 0x2145); // PLL control: BYPASS PLL = 8517
++ mt9t112_reg_write(ret, client, 0x0010, 0x0118); // PLL Dividers = 280
++ mt9t112_reg_write(ret, client, 0x0012, 0x0070); // PLL P Dividers = 112
++ mt9t112_reg_write(ret, client, 0x002A, 0x77EE); // PLL P Dividers 4-5-6 = 30685
++ mt9t112_reg_write(ret, client, 0x001A, 0x218); // Reset Misc. Control = 536
++ mt9t112_reg_write(ret, client, 0x0014, 0x2545); // PLL control: TEST_BYPASS on = 9541
++ mt9t112_reg_write(ret, client, 0x0014, 0x2547); // PLL control: PLL_ENABLE on = 9543
++ mt9t112_reg_write(ret, client, 0x0014, 0x2447); // PLL control: SEL_LOCK_DET on = 9287
++ mt9t112_reg_write(ret, client, 0x0014, 0x2047); // PLL control: TEST_BYPASS off = 8263
++
++ // Wait for the PLL to lock
++ for (i=0; i<1000; i++) {
++ mt9t112_reg_read(data, client, 0x0014);
++ if (0x8000 & data)
++ break;
++
++ mdelay(10);
++ }
++
++ mt9t112_reg_write(ret, client, 0x0014, 0x2046); // PLL control: PLL_BYPASS off = 8262
++ mt9t112_reg_write(ret, client, 0x0022, 0x0280); // Reference clock count for 20 us = 640
++ mt9t112_reg_write(ret, client, 0x001E, 0x0777); // Pad Slew Rate = 1911
++ mt9t112_reg_write(ret, client, 0x0016, 0x0400); // JPEG Clock = 1024
++
++ return ret;
++}
++
++static int mt9t112_sysctl_startup_K26A_rev_3(const struct i2c_client *client)
++{
++ int ret;
++
++ // reset
++ mt9t112_reset(client);
++
++ // Setup PLL
++ mt9t112_pll_setup_custom_pll(client);
++
++ // crank up the output slew rate (don't forget to enable these bits in TX_SS)
++ mt9t112_reg_write(ret, client, 0x001E, 0x0777);
++
++ return ret;
++}
++
++static int mt9t112_high_speed_overrides(const struct i2c_client *client)
++{
++ int ret;
++
++// Use this section to apply settings that are specific to this revision of SOC
++// or for any other specialized settings
++
++// clear the "Output Buffer Enable Adaptive Clock" bit to enable the SYSCTL
++// slew rate settings, change this in the variables and register
++
++ // PRI_A_CONFIG_JPEG_OB_TX_CONTROL_VAR
++ mt9t112_mcu_write(ret, client, VAR(26, 160), 0x082E);
++ // PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
++ mt9t112_mcu_write(ret, client, VAR(27, 160), 0x082E);
++ //SEC_A_CONFIG_JPEG_OB_TX_CONTROL_VAR
++ mt9t112_mcu_write(ret, client, VAR(28, 160), 0x082E);
++ //SEC_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
++ mt9t112_mcu_write(ret, client, VAR(29, 160), 0x082E);
++ mt9t112_reg_mask_set(ret, client, 0x3C52, 0x0040, 0); // set this value in HW
++
++ // Set correct values for Context B FIFO control
++ // CAM1_CTX_B_RX_FIFO_TRIGGER_MARK
++ mt9t112_mcu_write(ret, client, VAR(18, 142), 32);
++ // PRI_B_CONFIG_IO_OB_MANUAL_FLAG
++ mt9t112_mcu_write(ret, client, VAR(27, 172), 0);
++
++ return ret;
++}
++
++static int mt9t112_go(const struct i2c_client *client)
++{
++ int data, i, ret;
++
++ // release MCU from standby
++ mt9t112_reg_mask_set(ret, client, 0x0018, 0x0001, 0);
++
++ // wait for K26A to come out of standby
++ for (i=0; i<100; i++) {
++ mt9t112_reg_read(data, client, 0x0018);
++ if (!(0x4000 & data))
++ break;
++
++ mdelay(10);
++ }
++
++ return ret;
++}
++
++static int mt9t112_continue(const struct i2c_client *client)
++{
++ int data, i, ret;
++
++ // clear powerup stop bit
++ mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0);
++
++ // wait for sequencer to enter preview state
++ for (i=0; i<100; i++) {
++ mt9t112_mcu_read(data, client, VAR8(1, 1));
++ if (data == 3)
++ break;
++
++ mdelay(10);
++ }
++
++ return ret;
++}
++
++static int mt9t112_mcu_powerup_stop_enable(const struct i2c_client *client)
++{
++ int ret;
++
++ // set powerup stop bit
++ mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 1);
++
++ return ret;
++}
++
++static int mt9t112_custom_setup(const struct i2c_client *client)
++{
++ struct mt9t112_priv *priv = to_mt9t112(client);
++ struct mt9t112_resolution_param *resolution = &priv->resolution;
++ int ret;
++
++ //I2C Master Clock Divider
++ mt9t112_mcu_write(ret, client, 0x6006, 0x0100); // = 275
++ //Output Width (A)
++ mt9t112_mcu_write(ret, client, 0x6800, priv->frame.width);
++ //Output Height (A)
++ mt9t112_mcu_write(ret, client, 0x6802, priv->frame.height);
++ //JPEG (A)
++ mt9t112_mcu_write(ret, client, 0xE88E, 0x00); // = 0
++ //Adaptive Output Clock (A)
++ mt9t112_mcu_mask_set(ret, client, 0x68A0, 0x0040, 0x0000); // = 0
++ //Row Start (A)
++ mt9t112_mcu_write(ret, client, 0x4802, 0x000); // = 0
++ //Column Start (A)
++ mt9t112_mcu_write(ret, client, 0x4804, resolution->col_strt);
++ //Row End (A)
++ mt9t112_mcu_write(ret, client, 0x4806, resolution->row_end);
++ //Column End (A)
++ mt9t112_mcu_write(ret, client, 0x4808, resolution->col_end);
++ //Row Speed (A)
++ mt9t112_mcu_write(ret, client, 0x480A, 0x0111); // = 273
++ //Read Mode (A)
++ mt9t112_mcu_write(ret, client, 0x480C, resolution->read_mode);
++ //Fine Correction (A)
++ mt9t112_mcu_write(ret, client, 0x480F, resolution->fine_cor);
++ //Fine IT Min (A)
++ mt9t112_mcu_write(ret, client, 0x4811, resolution->fine_min);
++ //Fine IT Max Margin (A)
++ mt9t112_mcu_write(ret, client, 0x4813, resolution->fine_max);
++ //Base Frame Lines (A)
++ mt9t112_mcu_write(ret, client, 0x481D, resolution->base_lines);
++ //Min Line Length (A)
++ mt9t112_mcu_write(ret, client, 0x481F, resolution->min_lin_len);
++ //Line Length (A)
++ mt9t112_mcu_write(ret, client, 0x4825, resolution->line_len);
++ //Contex Width (A)
++ mt9t112_mcu_write(ret, client, 0x482B, resolution->con_width);
++ //Context Height (A)
++ mt9t112_mcu_write(ret, client, 0x482D, resolution->con_height);
++ //Output Width (B)
++ mt9t112_mcu_write(ret, client, 0x6C00, 0x0800); // = 2048
++ //Output Height (B)
++ mt9t112_mcu_write(ret, client, 0x6C02, 0x0600); // = 1536
++ //JPEG (B)
++ mt9t112_mcu_write(ret, client, 0xEC8E, 0x01); // = 1
++ //Adaptive Output Clock (B)
++ mt9t112_mcu_mask_set(ret, client, 0x6CA0, 0x0040, 0x0000); // = 0
++ //Row Start (B)
++ mt9t112_mcu_write(ret, client, 0x484A, 0x004); // = 4
++ //Column Start (B)
++ mt9t112_mcu_write(ret, client, 0x484C, 0x004); // = 4
++ //Row End (B)
++ mt9t112_mcu_write(ret, client, 0x484E, 0x60B); // = 1547
++ //Column End (B)
++ mt9t112_mcu_write(ret, client, 0x4850, 0x80B); // = 2059
++ //Row Speed (B)
++ mt9t112_mcu_write(ret, client, 0x4852, 0x0111); // = 273
++ //Read Mode (B)
++ mt9t112_mcu_write(ret, client, 0x4854, 0x0024); // = 36
++ //Fine Correction (B)
++ mt9t112_mcu_write(ret, client, 0x4857, 0x008C); // = 140
++ //Fine IT Min (B)
++ mt9t112_mcu_write(ret, client, 0x4859, 0x01F1); // = 497
++ //Fine IT Max Margin (B)
++ mt9t112_mcu_write(ret, client, 0x485B, 0x00FF); // = 255
++ //Base Frame Lines (B)
++ mt9t112_mcu_write(ret, client, 0x4865, 0x06AE); // = 1710
++ //Min Line Length (B)
++ mt9t112_mcu_write(ret, client, 0x4867, 0x0378); // = 888
++ //Line Length (B)
++ mt9t112_mcu_write(ret, client, 0x486D, 0x0A3A); // = 2618
++ //Contex Width (B)
++ mt9t112_mcu_write(ret, client, 0x4873, 0x0808); // = 2056
++ //Context Height (B)
++ mt9t112_mcu_write(ret, client, 0x4875, 0x0608); // = 1544
++ //search_f1_50
++ mt9t112_mcu_write(ret, client, 0xC8A5, resolution->s_f1_50);
++ //search_f2_50
++ mt9t112_mcu_write(ret, client, 0xC8A6, resolution->s_f2_50);
++ //search_f1_60
++ mt9t112_mcu_write(ret, client, 0xC8A7, resolution->s_f1_60);
++ //search_f2_60
++ mt9t112_mcu_write(ret, client, 0xC8A8, resolution->s_f2_60);
++ //period_50Hz (A)
++ mt9t112_mcu_write(ret, client, 0xC844, resolution->per_50);
++ //period_50Hz (A MSB)
++ mt9t112_mcu_write(ret, client, 0xC92F, resolution->per_50_M);
++ //period_60Hz (A)
++ mt9t112_mcu_write(ret, client, 0xC845, resolution->per_60);
++ //period_60Hz (A MSB)
++ mt9t112_mcu_write(ret, client, 0xC92D, 0x00); // = 0
++ //period_50Hz (B)
++ mt9t112_mcu_write(ret, client, 0xC88C, 0xD2); // = 210
++ //period_50Hz (B) MSB
++ mt9t112_mcu_write(ret, client, 0xC930, 0x00); // = 0
++ //period_60Hz (B)
++ mt9t112_mcu_write(ret, client, 0xC88D, 0xAF); // = 175
++ //period_60Hz (B) MSB
++ mt9t112_mcu_write(ret, client, 0xC92E, 0x00); // = 0
++ //FD Window Height
++ mt9t112_mcu_write(ret, client, 0xB825, resolution->fd_w_height);
++ //Stat_min
++ mt9t112_mcu_write(ret, client, 0xA009, 0x02); // = 2
++ //Stat_max
++ mt9t112_mcu_write(ret, client, 0xA00A, 0x03); // = 3
++ //Min_amplitude
++ mt9t112_mcu_write(ret, client, 0xA00C, 0x0A); // = 10
++ //RX FIFO Watermark (A)
++ mt9t112_mcu_write(ret, client, 0x4846, 0x0080); // = 128
++ //TX FIFO Watermark (A)
++ mt9t112_mcu_write(ret, client, 0x68AA, resolution->tx_water);
++ //Max FD Zone 50 Hz
++ mt9t112_mcu_write(ret, client, 0x6815, resolution->max_fd_50);
++ //Max FD Zone 60 Hz
++ mt9t112_mcu_write(ret, client, 0x6817, resolution->max_fd_60);
++ //AE Target FD Zone
++ mt9t112_mcu_write(ret, client, 0x682D, resolution->targ_fd);
++ //RX FIFO Watermark (B)
++ mt9t112_mcu_write(ret, client, 0x488E, 0x0080); // = 128
++ //TX FIFO Watermark (B)
++ mt9t112_mcu_write(ret, client, 0x6CAA, 0x01D0); // = 464
++ //Refresh Sequencer Mode
++ mt9t112_mcu_write(ret, client, 0x8400, 0x06); // = 6
++ //Refresh Sequencer
++ mt9t112_mcu_write(ret, client, 0x8400, 0x05); // = 5
++
++#ifdef TEST_PATTERN
++ mt9t112_mcu_write(ret, client, VAR(24, 0x03), 0x100);
++ mt9t112_mcu_write(ret, client, VAR(24, 0x25), 0x0B); // B - Color Bar Test Pattern (supposed to be 6 ?)
++#endif
++
++ return ret;
++}
++
++static int mt9t112_optimal_power_consumption(const struct i2c_client *client)
++{
++ int ret;
++
++ // Analog setting B
++
++ mt9t112_reg_write(ret, client, 0x3084, 0x2409);
++ mt9t112_reg_write(ret, client, 0x3092, 0x0A49);
++ mt9t112_reg_write(ret, client, 0x3094, 0x4949);
++ mt9t112_reg_write(ret, client, 0x3096, 0x4950);
++
++ return ret;
++}
++
++static int mt9t112_blooming_row_pattern(const struct i2c_client *client)
++{
++ int ret;
++
++ // Improve high light image quality
++ // [CAM1_CTX_A_COARSE_ITMIN]
++ mt9t112_mcu_write(ret, client, 0x4815, 0x0004);
++ // [CAM1_CTX_B_COARSE_ITMIN]
++ mt9t112_mcu_write(ret, client, 0x485D, 0x0004);
++
++ return ret;
++}
++
++static int mt9t112_set_orientation(const struct i2c_client *client, int flip)
++{
++ int ret;
++
++ // if flip = 0 set [normal]
++ // if flip = 1 set [horizontal mirror]
++ // if flip = 2 set [vertical flip]
++ // if flip = 3 set [rotate 180]
++ flip &= 0x3;
++
++ // [CAM1_CTX_A_READ_MODE]
++ mt9t112_mcu_mask_set(ret, client, VAR(18, 0x000C), 0x0003, flip);
++ // [CAM1_CTX_A_PIXEL_ORDER]
++ mt9t112_mcu_write(ret, client, VAR8(18, 0x000E), flip);
++
++ // [CAM1_CTX_B_READ_MODE]
++ mt9t112_mcu_mask_set(ret, client, VAR(18, 0x0054), 0x0003, flip);
++ // [CAM1_CTX_B_PIXEL_ORDER]
++ mt9t112_mcu_write(ret, client, VAR8(18, 0x0056), flip);
++
++ // [SEQ_CMD]
++ mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
++
++ return ret;
++}
++
++static int mt9t112_init_camera_optimized(const struct i2c_client *client)
++{
++ int ret;
++
++ // basic startup
++ ECHECKER(ret, mt9t112_sysctl_startup_K26A_rev_3(client));
++
++ // enable powerup stop
++ ECHECKER(ret, mt9t112_mcu_powerup_stop_enable(client));
++
++ // start MCU
++ ECHECKER(ret, mt9t112_go(client));
++
++ // customize the configuration
++ ECHECKER(ret, mt9t112_custom_setup(client));
++
++ // enable operation with fastest clocks
++ ECHECKER(ret, mt9t112_high_speed_overrides(client));
++
++ // Optimal power consumption setting
++ ECHECKER(ret, mt9t112_optimal_power_consumption(client));
++
++ // load anti-blooming settings
++ ECHECKER(ret, mt9t112_blooming_row_pattern(client));
++
++ // continue after powerup stop
++ ECHECKER(ret, mt9t112_continue(client));
++
++ return ret;
++}
++
+ static int mt9t112_init_pll(const struct i2c_client *client)
+ {
+ struct mt9t112_priv *priv = to_mt9t112(client);
+@@ -802,6 +1281,7 @@ static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct mt9t112_priv *priv = to_mt9t112(client);
+ int ret = 0;
++ int optimize = 0;
+
+ if (!enable) {
+ /* FIXME
+@@ -830,15 +1310,33 @@ static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
+ priv->flags |= INIT_DONE;
+ }
+
++ // fill the structure with new resolution parameters
++ optimize = mt9t112_set_resolution_params(client);
++
++ if (optimize)
++ ECHECKER(ret, mt9t112_init_camera_optimized(client));
++ else
++ ECHECKER(ret, mt9t112_init_camera(client));
++
++ /* Invert PCLK (Data sampled on falling edge of pixclk) */
++ mt9t112_reg_write(ret, client, 0x3C20, (PCLK_RISING & priv->flags ? 0x0001 : 0x0000));
++ mdelay(5);
++
+ mt9t112_mcu_write(ret, client, VAR(26, 7), priv->format->fmt);
+ mt9t112_mcu_write(ret, client, VAR(26, 9), priv->format->order);
+ mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
+
+- mt9t112_set_a_frame_size(client,
++ if (!optimize) {
++ mt9t112_set_a_frame_size(client,
+ priv->frame.width,
+ priv->frame.height);
+
+- ECHECKER(ret, mt9t112_auto_focus_trigger(client));
++ ECHECKER(ret, mt9t112_auto_focus_trigger(client));
++ }
++
++ if (priv->info->flags & MT9T112_FLAG_VFLIP) {
++ ECHECKER(ret, mt9t112_set_orientation(client, 2));
++ }
+
+ dev_dbg(&client->dev, "format : %d\n", priv->format->code);
+ dev_dbg(&client->dev, "size : %d x %d\n",
+diff --git a/include/media/mt9t112.h b/include/media/mt9t112.h
+index a43c74a..bab2746 100644
+--- a/include/media/mt9t112.h
++++ b/include/media/mt9t112.h
+@@ -13,6 +13,8 @@
+
+ #define MT9T112_FLAG_PCLK_RISING_EDGE (1 << 0)
+ #define MT9T112_FLAG_DATAWIDTH_8 (1 << 1) /* default width is 10 */
++#define MT9T112_FLAG_VFLIP (1 << 2)
++#define MT9T112_FLAG_HFLIP (1 << 3)
+
+ struct mt9t112_pll_divider {
+ u8 m, n;
diff --git a/patches/linux-3.8.13/0612-cssp_camera-Use-flip-if-available.patch b/patches/linux-3.8.13/0612-cssp_camera-Use-flip-if-available.patch
new file mode 100644
index 0000000..8be0a94
--- /dev/null
+++ b/patches/linux-3.8.13/0612-cssp_camera-Use-flip-if-available.patch
@@ -0,0 +1,53 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 2 May 2013 14:16:40 +0300
+Subject: [PATCH] cssp_camera: Use flip if available.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/media/platform/soc_camera/cssp_camera.c | 19 ++++++++-----------
+ 1 file changed, 8 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+index 0a0cd8f..788acc4 100644
+--- a/drivers/media/platform/soc_camera/cssp_camera.c
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -16,7 +16,7 @@
+ *
+ */
+
+-
++#define DEBUG
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/gpio.h>
+@@ -1345,15 +1345,12 @@ of_get_cssp_platform_data(struct platform_device *pdev)
+
+ /* set orientation flag */
+
+- /*
+- * But the driver in mainline doesn't support flip
+- * Commented out for now...
+- *
+- * if (ret)
+- * val |= MT9T112_FLAG_VFLIP;
+- * else
+- * val &= ~MT9T112_FLAG_VFLIP
+- */
++#ifdef MT9T112_FLAG_VFLIP
++ if (ret)
++ val |= MT9T112_FLAG_VFLIP;
++ else
++ val &= ~MT9T112_FLAG_VFLIP;
++#endif
+ }
+ pstore->mt9t111_cam_info.flags = val;
+
+@@ -1376,7 +1373,7 @@ err_fail:
+ if (adap != NULL)
+ put_device(&adap->dev);
+
+- /* free memory (even if it will be automatically freed it's good practice) */
++ /* free memory (even if automatically freed it's good practice) */
+ if (pstore != NULL)
+ devm_kfree(dev, pstore);
+
diff --git a/patches/linux-3.8.13/0613-cssp_camera-Fix-it-for-small-resolutions.patch b/patches/linux-3.8.13/0613-cssp_camera-Fix-it-for-small-resolutions.patch
new file mode 100644
index 0000000..67eb34c
--- /dev/null
+++ b/patches/linux-3.8.13/0613-cssp_camera-Fix-it-for-small-resolutions.patch
@@ -0,0 +1,932 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 9 May 2013 23:01:53 +0300
+Subject: [PATCH] cssp_camera: Fix it for small resolutions
+
+This should make it work reliably for resolutions up to 1024x768
+
+1280x960 and higher hang, or crash..
+---
+ drivers/media/platform/soc_camera/cssp_camera.c | 567 +++++++++++++++++------
+ 1 file changed, 415 insertions(+), 152 deletions(-)
+
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+index 788acc4..62d8702 100644
+--- a/drivers/media/platform/soc_camera/cssp_camera.c
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -53,13 +53,12 @@ static unsigned int vid_limit = 6;
+ module_param(vid_limit, uint, 0644);
+ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+-#define VGA_WIDTH 640
+-#define VGA_HEIGHT 480
++#define INIT_WIDTH 640
++#define INIT_HEIGHT 480
+
+ #define MAX_WIDTH 2048
+ #define MAX_HEIGHT 1536
+
+-#define VGA_RES (VGA_WIDTH * VGA_HEIGHT)
+ #define BYTES_PER_PIXEL 2
+
+ /* PaRAM.opt: */
+@@ -117,10 +116,14 @@ struct cssp_cam_buffer {
+ struct vb2_buffer vb;
+ struct list_head list;
+ struct cssp_cam_fmt *fmt;
++ unsigned long queued_jiffies;
+ };
+
++#define to_cssp_cam_buffer(_x) container_of(_x, struct cssp_cam_buffer, vb)
++
+ struct cssp_cam_dmaqueue {
+ struct list_head active;
++ int count;
+ };
+
+ struct cssp_cam_dev {
+@@ -138,7 +141,9 @@ struct cssp_cam_dev {
+ struct cssp_cam_dmaqueue vidq;
+ void *dma_cont_ctx;
+ int streaming_started;
+- struct vb2_buffer *current_vb;
++ struct vb2_buffer *current_vb[2];
++ void *spillover;
++ dma_addr_t spillover_dma_addr;
+
+ /* video capture */
+ struct cssp_cam_fmt *fmt;
+@@ -160,10 +165,13 @@ struct cssp_cam_dev {
+ u16 mode;
+
+ int dma_ch;
++ int dma_link[2];
+ struct edmacc_param dma_tr_params;
++ struct edmacc_param dma_link_params;
+
+ u64 dma_mask;
+ int dma_req_len;
++ int dma_req_shift;
+
+ int frame_cnt;
+
+@@ -241,6 +249,65 @@ static struct cssp_cam_fmt formats[] = {
+
+ /***************************************************************************/
+
++static inline dma_addr_t vb2_dma_contig_cookie(void *a, void *b)
++{
++ /* Same functionality as the vb2_dma_contig_plane_paddr */
++ dma_addr_t *paddr = vb2_dma_contig_memops.cookie(b);
++
++ return *paddr;
++}
++
++/* MFC definitions */
++
++static void set_capture_enable_no_lock(struct cssp_cam_dev *dev, int enable)
++{
++ u16 val;
++
++ // readw(dev->reg_base_virt + REG_MODE);
++ if (enable) {
++ ioread16(dev->reg_base_virt + REG_MODE);
++ iowrite16(dev->mode & ~ENABLE, dev->reg_base_virt + REG_MODE);
++ ioread16(dev->reg_base_virt + REG_MODE);
++ iowrite16(dev->mode | ENABLE, dev->reg_base_virt + REG_MODE);
++ } else {
++ ioread16(dev->reg_base_virt + REG_MODE);
++ iowrite16(dev->mode | ENABLE, dev->reg_base_virt + REG_MODE);
++ ioread16(dev->reg_base_virt + REG_MODE);
++ iowrite16(dev->mode & ~ENABLE, dev->reg_base_virt + REG_MODE);
++ }
++
++ val = ioread16(dev->reg_base_virt + REG_MODE);
++ dev_dbg(&dev->pdev->dev, "%s enable=%d val=0x%04x\n", __func__,
++ enable, val);
++}
++
++static int set_capture_enable(struct cssp_cam_dev *dev, int enable)
++{
++ unsigned long flags;
++ unsigned long tmo;
++
++ spin_lock_irqsave(&dev->slock, flags);
++ set_capture_enable_no_lock(dev, enable);
++ spin_unlock_irqrestore(&dev->slock, flags);
++
++ /* sigh, check whether the device gets data */
++ if (enable) {
++ tmo = jiffies + msecs_to_jiffies(1000);
++ while ((ioread16(dev->reg_base_virt + REG_MODE) & 0x0100) != 0) {
++ if (time_after(jiffies, tmo))
++ break;
++ cpu_relax();
++ }
++
++ if (time_after(jiffies, tmo)) {
++ spin_lock_irqsave(&dev->slock, flags);
++ set_capture_enable_no_lock(dev, 0);
++ spin_unlock_irqrestore(&dev->slock, flags);
++ return -EAGAIN;
++ }
++ }
++ return 0;
++}
+
+ static int configure_gpio(int nr, int val, const char *name)
+ {
+@@ -277,96 +344,209 @@ static int reset_cssp(struct cssp_cam_dev *cam)
+ return err;
+ }
+
+-static int trigger_dma_transfer_to_buf(struct cssp_cam_dev *dev, struct vb2_buffer *vb)
++#if 0
++static void dump_slot(struct cssp_cam_dev *cam, int slot, char *name)
+ {
+- dma_addr_t dma_buf = vb2_dma_contig_plane_dma_addr(vb, 0);
++ struct device *dev = &cam->pdev->dev;
++ struct edmacc_param p;
+
+- if (!dma_buf) {
+- /* Is this possible? Release the vb2_buffer with an error here, */
+- vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+- dev->current_vb = NULL;
+- return -ENOMEM;
+- }
++ if (slot < 0)
++ return;
++
++ edma_read_slot(slot, &p);
++ dev_dbg(dev, "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n",
++ name, slot, p.opt, p.src, p.a_b_cnt, p.dst);
++ dev_dbg(dev, " src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n",
++ p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt);
++}
++#endif
+
+- dev->dma_tr_params.dst = dma_buf;
++void enqueue_dma(struct cssp_cam_dev *dev, int ch, struct vb2_buffer *vb)
++{
++ dma_addr_t dma_buf;
++ int i, rem;
++ u32 bytesperline, height;
++ u16 acnt, bcnt, ccnt;
++ struct edmacc_param params;
+
+- // Enable DMA
+- edma_write_slot(dev->dma_ch, &dev->dma_tr_params);
++ /* Calculate DMA transfer parameters based on DMA request length */
++ bytesperline = dev->bytesperline;
++ i = 0;
++ do {
++ rem = bytesperline % dev->dma_req_len;
++ if (rem != 0) {
++ bytesperline <<= 1;
++ i++;
++ }
++ } while (rem != 0);
++ height = dev->height >> i;
++ acnt = dev->dma_req_len;
++ bcnt = bytesperline / dev->dma_req_len;
++ ccnt = height;
+
+- dev->current_vb = vb;
++ if (vb != NULL)
++ dma_buf = vb2_dma_contig_plane_dma_addr(vb, 0);
++ else
++ dma_buf = dev->spillover_dma_addr;
++
++ edma_set_src(ch, dev->reg_base_phys + REG_DATA, INCR, W8BIT);
++ edma_set_dest(ch, dma_buf, INCR, W8BIT);
++ edma_set_src_index(ch, 0, 0);
++ edma_set_dest_index(ch,
++ dev->dma_req_len, /* dest bidx */
++ dev->dma_req_len); /* dest cidx */
++ edma_set_transfer_params(ch,
++ dev->dma_req_len, /* acnt */
++ bytesperline / dev->dma_req_len, /* bcnt */
++ height, /* ccnt */
++ bytesperline / dev->dma_req_len, /* bcnt_rld */
++ ASYNC);
+
+- // Enable data capture
+- dev->mode |= ENABLE;
+- writew(dev->mode, dev->reg_base_virt + REG_MODE);
+- readw(dev->reg_base_virt + REG_MODE);
++ /*
++ * Issue transfer completion IRQ when the channel completes
++ * a transfer, and then always reload from the same slot
++ */
++ edma_read_slot(ch, &params);
++ params.opt |= TCINTEN | EDMA_TCC(EDMA_CHAN_SLOT(dev->dma_ch));
++ params.link_bcntrld = (params.link_bcntrld & ~0xffff) |
++ ((EDMA_CHAN_SLOT(dev->dma_link[0]) << 5) & 0xffff);
++ edma_write_slot(ch, &params);
++
++#if 0
++ {
++ struct edmacc_param p;
++
++ edma_read_slot(ch, &p);
++ dev_dbg(&dev->pdev->dev,
++ "1. opt=%08x, src=%08x, a_b_cnt=%08x dst=%08x src_dst_bidx=%08x "
++ "link_bcntrld=%08x src_dst_cidx=%08x ccnt=%08x\n",
++ p.opt, p.src, p.a_b_cnt, p.dst, p.src_dst_bidx,
++ p.link_bcntrld, p.src_dst_cidx, p.ccnt);
++
++ p.opt = TCINTEN | TCC(dev->dma_ch);
++ p.src = dev->reg_base_phys + REG_DATA;
++ p.dst = dma_buf;
++ p.a_b_cnt = ACNT(dev->dma_req_len) | BCNT((INIT_WIDTH * BYTES_PER_PIXEL) / dev->dma_req_len);
++ p.src_dst_bidx = SRCBIDX(0) | DSTBIDX(dev->dma_req_len);
++ p.link_bcntrld = BCNTRLD((INIT_WIDTH * BYTES_PER_PIXEL) / dev->dma_req_len) | LINK(0xffff);
++ p.src_dst_cidx = SRCCIDX(0) | DSTCIDX(dev->dma_req_len);
++ p.ccnt = CCNT(INIT_HEIGHT);
++
++ dev_dbg(&dev->pdev->dev,
++ "2. opt=%08x, src=%08x, a_b_cnt=%08x dst=%08x src_dst_bidx=%08x "
++ "link_bcntrld=%08x src_dst_cidx=%08x ccnt=%08x\n",
++ p.opt, p.src, p.a_b_cnt, p.dst, p.src_dst_bidx,
++ p.link_bcntrld, p.src_dst_cidx, p.ccnt);
++
++ }
++#endif
++
++ // dump_slot(dev, ch, "q");
++
++ /*
++ param->a_b_cnt = ACNT(dev->dma_req_len) | BCNT(bytesperline / dev->dma_req_len);
++ param->src_dst_bidx = SRCBIDX(0) | DSTBIDX(dev->dma_req_len);
++ param->link_bcntrld = BCNTRLD(bytesperline / dev->dma_req_len) | LINK(0xffff);
++ param->src_dst_cidx = SRCCIDX(0) | DSTCIDX(dev->dma_req_len);
++ param->ccnt = CCNT(height);
++ */
+
+- return 0;
+ }
+
+-static void dequeue_buffer_for_dma(struct cssp_cam_dev *dev)
++static int fillup_dma(struct cssp_cam_dev *dev)
+ {
+ struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
+- unsigned long flags = 0;
++ struct cssp_cam_buffer *buf;
++ struct vb2_buffer *vb;
++ int i, ch, cnt;
++ unsigned long flags;
+
+ spin_lock_irqsave(&dev->slock, flags);
+- if (!list_empty(&dma_q->active)) {
+- struct cssp_cam_buffer *buf;
+
+- buf = list_entry(dma_q->active.next, struct cssp_cam_buffer, list);
++ /* while there's a buffer queued, and there's space */
++ cnt = 0;
++ while (!list_empty(&dma_q->active) &&
++ (dev->current_vb[0] == NULL || dev->current_vb[1] == NULL)) {
++
++ if (dev->current_vb[0] == NULL) {
++ i = 0;
++ ch = dev->dma_ch;
++ } else {
++ i = 1;
++ ch = dev->dma_link[0];
++ }
++
++ buf = list_entry(dma_q->active.next,
++ struct cssp_cam_buffer, list);
+ list_del(&buf->list);
+- spin_unlock_irqrestore(&dev->slock, flags);
++ dma_q->count--;
+
+- buf->fmt = dev->fmt;
++ vb = &buf->vb;
++ enqueue_dma(dev, ch, vb);
++ dev->current_vb[i] = vb;
+
+- trigger_dma_transfer_to_buf(dev, &buf->vb);
+- } else {
+- spin_unlock_irqrestore(&dev->slock, flags);
++ cnt++;
++ /* dev_dbg(&pdev->dev, "queued vb %p (#=%d, ch=%d)\n", vb, i, ch); */
+ }
++ spin_unlock_irqrestore(&dev->slock, flags);
++
++ return cnt;
+ }
+
+ static void dma_callback(unsigned lch, u16 ch_status, void *data)
+ {
+ struct cssp_cam_dev *dev = data;
+ struct vb2_buffer *vb;
+- struct edmacc_param dma_tr_params;
++ unsigned long flags;
++ struct cssp_cam_buffer *buf;
++ struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
++ int ch;
+
+- // Disable data capture
+- dev->mode &= ~ENABLE;
+- writew(dev->mode, dev->reg_base_virt + REG_MODE);
+- readw(dev->reg_base_virt + REG_MODE);
+-
+- if (ch_status == DMA_COMPLETE) {
+-
+- vb = dev->current_vb;
+-
+- edma_read_slot(dev->dma_ch, &dma_tr_params);
+- if ((dma_tr_params.opt != 0) ||
+- (dma_tr_params.src != 0) ||
+- (dma_tr_params.a_b_cnt != 0) ||
+- (dma_tr_params.dst != 0) ||
+- (dma_tr_params.src_dst_bidx != 0) ||
+- (dma_tr_params.link_bcntrld != 0xffff) ||
+- (dma_tr_params.src_dst_cidx != 0) ||
+- (dma_tr_params.ccnt != 0)) {
+-
+- trigger_dma_transfer_to_buf(dev, dev->current_vb);
+- return;
+- }
++ if (ch_status != DMA_COMPLETE) {
++ dev_dbg(&dev->pdev->dev, "%s - missed interrupt\n",
++ __func__);
++ return;
++ }
++
++ spin_lock_irqsave(&dev->slock, flags);
++
++ vb = dev->current_vb[0];
++ dev->current_vb[0] = dev->current_vb[1];
++ dev->current_vb[1] = NULL;
++
++ /* if there's a buffer, link to the next */
++ ch = dev->dma_link[0];
++
++ if (!list_empty(&dma_q->active)) {
++
++ buf = list_entry(dma_q->active.next,
++ struct cssp_cam_buffer, list);
++ list_del(&buf->list);
++ dma_q->count--;
++
++ enqueue_dma(dev, ch, &buf->vb);
++ dev->current_vb[1] = &buf->vb;
++ } else {
++ /* no buffer, we need to put the spillover there */
++ enqueue_dma(dev, ch, NULL);
++ }
++
++ spin_unlock_irqrestore(&dev->slock, flags);
++
++ /* fillup_dma(dev); */
++
++ if (vb != NULL) {
++ /* queue the current buffer */
++ buf = to_cssp_cam_buffer(vb);
+
+ vb->v4l2_buf.field = dev->field;
+ vb->v4l2_buf.sequence = dev->frame_cnt++;
+ do_gettimeofday(&vb->v4l2_buf.timestamp);
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+- dev->current_vb = NULL;
+
+- /* check if we have new buffer queued */
+- dequeue_buffer_for_dma(dev);
+- } else {
+- /* we got a missed interrupt so just start a new DMA with the existing buffer */
+- if (dev->current_vb != NULL) {
+- if (trigger_dma_transfer_to_buf(dev, dev->current_vb))
+- dev_err(&dev->pdev->dev, "No buffer allocated!\n");
+- }
++ dev_dbg(&dev->pdev->dev, "[%p/%d] done\n",
++ buf, buf->vb.v4l2_buf.index);
++
+ }
+ }
+
+@@ -374,8 +554,8 @@ static int configure_edma(struct cssp_cam_dev *cam)
+ {
+ struct platform_device *pdev = cam->pdev;
+ struct cssp_cam_platform_data *pdata = pdev->dev.platform_data;
+- struct edmacc_param *param;
+ int dma_channel;
++ int ret;
+
+ dma_channel = pdata->dma_ch;
+
+@@ -386,24 +566,22 @@ static int configure_edma(struct cssp_cam_dev *cam)
+ dev_err(&pdev->dev, "failed setting mask for DMA\n");
+ return -EINVAL;
+ }
+- cam->dma_ch = edma_alloc_channel(dma_channel, dma_callback, cam, EVENTQ_0);
+- if (cam->dma_ch < 0) {
++ ret = edma_alloc_channel(dma_channel, dma_callback, cam, EVENTQ_0);
++ if (ret < 0) {
+ dev_err(&pdev->dev, "allocating channel for DMA failed\n");
+- return -EBUSY;
++ return ret;
+ }
++ cam->dma_ch = ret;
++ dev_info(&pdev->dev, "dma_ch=%d\n", cam->dma_ch);
+
+- cam->dma_req_len = cam->rev > 3 ? 128 : 32;
+-
+- param = &cam->dma_tr_params;
+- param->opt = TCINTEN | TCC(cam->dma_ch);
+- param->src = cam->reg_base_phys + REG_DATA;
+- param->a_b_cnt = ACNT(cam->dma_req_len) |
+- BCNT((VGA_WIDTH * BYTES_PER_PIXEL) / cam->dma_req_len);
+- param->src_dst_bidx = SRCBIDX(0) | DSTBIDX(cam->dma_req_len);
+- param->link_bcntrld = BCNTRLD((VGA_WIDTH * BYTES_PER_PIXEL) /
+- cam->dma_req_len) | LINK(0xffff);
+- param->src_dst_cidx = SRCCIDX(0) | DSTCIDX(cam->dma_req_len);
+- param->ccnt = CCNT(VGA_HEIGHT);
++ /* allocate link channels */
++ ret = edma_alloc_slot(EDMA_CTLR(cam->dma_ch), EDMA_SLOT_ANY);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "allocating slot for DMA failed\n");
++ return ret;
++ }
++ cam->dma_link[0] = ret;
++ dev_info(&pdev->dev, "dma_link[0]=%d\n", cam->dma_link[0]);
+
+ return 0;
+ }
+@@ -450,7 +628,13 @@ static int configure_cssp(struct cssp_cam_dev *cam)
+ dev_info(&pdev->dev, "CSSP Revision %c%d\n",
+ 'A' + ((cam->rev & 0xf0) >> 4), cam->rev & 0x0f);
+
+- cam->dma_req_len = cam->rev > 3 ? 128 : 32;
++ if (cam->rev > 3) {
++ cam->dma_req_len = 128;
++ cam->dma_req_shift = 7;
++ } else {
++ cam->dma_req_len = 32;
++ cam->dma_req_shift = 5;
++ }
+
+ return 0;
+ }
+@@ -461,17 +645,19 @@ static int configure_camera_sensor(struct cssp_cam_dev *cam)
+ struct i2c_client *client;
+ struct i2c_adapter *adapter;
+ struct v4l2_subdev *subdev;
++ int ret;
+ struct v4l2_mbus_framefmt f_format = {
+- .width = VGA_WIDTH,
+- .height = VGA_HEIGHT,
++ .width = INIT_WIDTH,
++ .height = INIT_HEIGHT,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ };
+
+ /* Enable the clock just for the time of loading the camera driver and disable after that */
+ /* It is going to be be re-enabled later, when camera will be in use */
+- clk_enable(cam->camera_clk);
+- mdelay(50); // let the clock stabilize
++ ret = clk_prepare_enable(cam->camera_clk);
++ BUG_ON(ret != 0);
++ mdelay(1); // let the clock stabilize
+
+ adapter = i2c_get_adapter(((struct soc_camera_link *)(info->platform_data))->i2c_adapter_id);
+ if (!adapter) {
+@@ -496,17 +682,21 @@ static int configure_camera_sensor(struct cssp_cam_dev *cam)
+
+ v4l2_subdev_call(subdev, video, s_mbus_fmt, &f_format);
+
+- clk_disable(cam->camera_clk);
++ clk_disable_unprepare(cam->camera_clk);
+
+ return 0;
+ }
+
+ static int start_camera_sensor(struct cssp_cam_dev *cam)
+ {
+- clk_enable(cam->camera_clk);
+- mdelay(100); /* let the clock stabilize */
++ int ret;
+
+- v4l2_subdev_call(cam->subdev, video, s_stream, 1);
++ ret = v4l2_subdev_call(cam->subdev, video, s_stream, 1);
++ if (ret != 0) {
++ dev_err(&cam->pdev->dev, "%s: v4l2_subdev_call failed\n",
++ __func__);
++ return ret;
++ }
+
+ return 0;
+ }
+@@ -514,10 +704,6 @@ static int start_camera_sensor(struct cssp_cam_dev *cam)
+ static void stop_camera_sensor(struct cssp_cam_dev *cam)
+ {
+ v4l2_subdev_call(cam->subdev, video, s_stream, 0);
+-
+- clk_disable(cam->camera_clk);
+-
+- return;
+ }
+
+ static struct cssp_cam_fmt *get_format(struct v4l2_format *f)
+@@ -577,18 +763,6 @@ static int buffer_init(struct vb2_buffer *vb)
+
+ BUG_ON(NULL == dev->fmt);
+
+- /*
+- * This callback is called once per buffer, after its allocation.
+- *
+- * Vivi does not allow changing format during streaming, but it is
+- * possible to do so when streaming is paused (i.e. in streamoff state).
+- * Buffers however are not freed when going into streamoff and so
+- * buffer size verification has to be done in buffer_prepare, on each
+- * qbuf.
+- * It would be best to move verification code here to buf_init and
+- * s_fmt though.
+- */
+-
+ return 0;
+ }
+
+@@ -649,30 +823,34 @@ static void buffer_queue(struct vb2_buffer *vb)
+ struct cssp_cam_dmaqueue *vidq = &dev->vidq;
+ unsigned long flags = 0;
+
+- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+-
+- if (dev->streaming_started && !dev->current_vb) {
+- trigger_dma_transfer_to_buf(dev, &buf->vb);
+- } else {
+- spin_lock_irqsave(&dev->slock, flags);
+- list_add_tail(&buf->list, &vidq->active);
+- spin_unlock_irqrestore(&dev->slock, flags);
+- }
++ /* just add it to the queue */
++ spin_lock_irqsave(&dev->slock, flags);
++ list_add_tail(&buf->list, &vidq->active);
++ vidq->count++;
++ spin_unlock_irqrestore(&dev->slock, flags);
+ }
+
+ static int start_streaming(struct vb2_queue *vq, unsigned int count)
+ {
+ struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
+ struct platform_device *pdev = dev->pdev;
+- int ret;
++ int ret, retries;
+
+- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++ dev_dbg(&dev->pdev->dev, "%s count=%d\n", __func__, count);
+
+- ret = start_camera_sensor(dev);
++ retries = 0;
++
++ set_capture_enable(dev, 0);
++
++ ret = clk_prepare_enable(dev->camera_clk);
+ if (ret != 0) {
+- dev_err(&pdev->dev, "start_camera_sensor failed\n");
++ dev_err(&pdev->dev, "%s: clk_enable failed\n",
++ __func__);
+ return ret;
+ }
++ mdelay(20); /* let the clock stabilize */
++
++ fillup_dma(dev);
+
+ // Enable DMA
+ ret = edma_start(dev->dma_ch);
+@@ -680,10 +858,25 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
+ dev_err(&pdev->dev, "edma_start failed\n");
+ return ret;
+ }
+- dev->streaming_started = 1;
+
+- /* check if we have new buffer queued */
+- dequeue_buffer_for_dma(dev);
++again:
++ ret = start_camera_sensor(dev);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "start_camera_sensor failed\n");
++ return ret;
++ }
++
++ // Enable data capture
++ ret = set_capture_enable(dev, 1);
++ if (ret != 0) {
++ retries++;
++ dev_warn(&pdev->dev, "no stream; retry #%d\n", retries);
++ if (retries < 3)
++ goto again;
++ goto again;
++ }
++
++ dev->streaming_started = 1;
+
+ return 0;
+ }
+@@ -693,6 +886,10 @@ static int stop_streaming(struct vb2_queue *vq)
+ {
+ struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
+ struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
++ struct cssp_cam_buffer *buf;
++ unsigned long flags;
++ struct vb2_buffer *vb;
++ int i;
+
+ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+@@ -700,27 +897,43 @@ static int stop_streaming(struct vb2_queue *vq)
+ edma_stop(dev->dma_ch);
+
+ // Disable data capture
+- dev->mode &= ~ENABLE;
+- writew(dev->mode, dev->reg_base_virt + REG_MODE);
++ set_capture_enable(dev, 0);
+
+ stop_camera_sensor(dev);
+
++ clk_disable_unprepare(dev->camera_clk);
++
+ dev->streaming_started = 0;
+
+ /* Release all active buffers */
++ spin_lock_irqsave(&dev->slock, flags);
++
++ for (i = 0; i < 2; i++) {
++ vb = dev->current_vb[i];
++ if (vb == NULL)
++ continue;
++ dev->current_vb[i] = NULL;
++
++ buf = to_cssp_cam_buffer(vb);
++
++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
++
++ dev_dbg(&dev->pdev->dev, "[%p/%d] in flight\n",
++ buf, buf->vb.v4l2_buf.index);
++ }
++
+ while (!list_empty(&dma_q->active)) {
+- struct cssp_cam_buffer *buf;
+
+ buf = list_entry(dma_q->active.next,
+ struct cssp_cam_buffer, list);
+ list_del(&buf->list);
++
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+
+- dev_dbg(&dev->pdev->dev, "[%p/%d] done\n",
++ dev_dbg(&dev->pdev->dev, "[%p/%d] queued\n",
+ buf, buf->vb.v4l2_buf.index);
+ }
+-
+- dev->current_vb = NULL;
++ spin_unlock_irqrestore(&dev->slock, flags);
+
+ return 0;
+ }
+@@ -759,6 +972,8 @@ static int vidioc_querycap(struct file *file, void *priv,
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
+
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ strcpy(cap->driver, "cssp_camera");
+ strcpy(cap->card, "cssp_camera");
+ strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
+@@ -770,8 +985,11 @@ static int vidioc_querycap(struct file *file, void *priv,
+ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+ {
++ struct cssp_cam_dev *dev = video_drvdata(file);
+ struct cssp_cam_fmt *fmt;
+
++ dev_dbg(&dev->pdev->dev, "%s index=%d\n", __func__, f->index);
++
+ if (f->index >= ARRAY_SIZE(formats))
+ return -EINVAL;
+
+@@ -787,6 +1005,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
+
++ dev_dbg(&dev->pdev->dev, "%s: dev->width=%u dev->height=%u "
++ "dev->sizeimage=%u\n", __func__,
++ dev->width, dev->height, dev->sizeimage);
++
+ f->fmt.pix.width = dev->width;
+ f->fmt.pix.height = dev->height;
+ f->fmt.pix.field = dev->field;
+@@ -806,6 +1028,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ fmt = get_format(f);
+ if (!fmt) {
+ dev_err(&dev->pdev->dev, "Fourcc format (0x%08x) invalid.\n",
+@@ -843,12 +1067,16 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct vb2_queue *q = &dev->vb_vidq;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+ struct v4l2_mbus_framefmt mbus_fmt;
+- int i = 0, rem;
+- u32 bytesperline, height;
++ int ret;
+
+- int ret = vidioc_try_fmt_vid_cap(file, priv, f);
+- if (ret < 0)
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
++ ret = vidioc_try_fmt_vid_cap(file, priv, f);
++ if (ret < 0) {
++ dev_err(&dev->pdev->dev, "%s: vidioc_try_fmt_vid_cap failed\n",
++ __func__);
+ return ret;
++ }
+
+ if (vb2_is_streaming(q)) {
+ dev_err(&dev->pdev->dev, "%s device busy\n", __func__);
+@@ -863,26 +1091,13 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ dev->bytesperline = f->fmt.pix.bytesperline;
+ dev->sizeimage = f->fmt.pix.sizeimage;
+
++ dev_dbg(&dev->pdev->dev, "width=%u height=%u byteperline=%u\n",
++ dev->width, dev->height, dev->bytesperline);
++
+ /* Set the sensor into the new format */
+ v4l2_fill_mbus_format(&mbus_fmt, pix, dev->fmt->code);
+ v4l2_subdev_call(dev->subdev, video, s_mbus_fmt, &mbus_fmt);
+
+- /* Calculate DMA transfer parameters based on DMA request length */
+- bytesperline = dev->bytesperline;
+- do {
+- rem = bytesperline % dev->dma_req_len;
+- if (rem != 0) {
+- bytesperline <<= 1;
+- i++;
+- }
+- } while (rem != 0);
+- height = dev->height >> i;
+-
+- /* Set the EDMA for the new resolution */
+- dev->dma_tr_params.a_b_cnt = ACNT(dev->dma_req_len) | BCNT(bytesperline / dev->dma_req_len);
+- dev->dma_tr_params.link_bcntrld = BCNTRLD(bytesperline / dev->dma_req_len) | LINK(0xffff);
+- dev->dma_tr_params.ccnt = CCNT(height);
+-
+ return 0;
+ }
+
+@@ -890,36 +1105,57 @@ static int vidioc_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *p)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ return vb2_reqbufs(&dev->vb_vidq, p);
+ }
+
+ static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ return vb2_querybuf(&dev->vb_vidq, p);
+ }
+
+ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ return vb2_qbuf(&dev->vb_vidq, p);
+ }
+
+ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
++ u16 val;
++
++ val = ioread16(dev->reg_base_virt + REG_MODE);
++ dev_dbg(&dev->pdev->dev, "%s MODE=0x%04x\n", __func__,
++ val);
++
+ return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
+ }
+
+ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ return vb2_streamon(&dev->vb_vidq, i);
+ }
+
+ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ return vb2_streamoff(&dev->vb_vidq, i);
+ }
+
+@@ -927,6 +1163,8 @@ static int vidioc_log_status(struct file *file, void *priv)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
+
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name);
+ return 0;
+ }
+@@ -934,6 +1172,10 @@ static int vidioc_log_status(struct file *file, void *priv)
+ static int vidioc_enum_input(struct file *file, void *priv,
+ struct v4l2_input *inp)
+ {
++ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ if (inp->index > 0)
+ return -EINVAL;
+
+@@ -945,6 +1187,10 @@ static int vidioc_enum_input(struct file *file, void *priv,
+
+ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+ {
++ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ *i = 0;
+
+ return 0;
+@@ -952,6 +1198,10 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+
+ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+ {
++ struct cssp_cam_dev *dev = video_drvdata(file);
++
++ dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++
+ if (i > 0)
+ return -EINVAL;
+
+@@ -1088,9 +1338,10 @@ static int video_probe(struct cssp_cam_dev *cam_dev)
+ goto free_dev;
+
+ cam_dev->fmt = &formats[0];
+- cam_dev->width = VGA_WIDTH;
+- cam_dev->height = VGA_HEIGHT;
+- cam_dev->sizeimage = VGA_WIDTH * VGA_HEIGHT * BYTES_PER_PIXEL;
++ cam_dev->width = INIT_WIDTH;
++ cam_dev->height = INIT_HEIGHT;
++ cam_dev->bytesperline = INIT_WIDTH * BYTES_PER_PIXEL;
++ cam_dev->sizeimage = cam_dev->bytesperline * INIT_HEIGHT;
+ hdl = &cam_dev->ctrl_handler;
+ v4l2_ctrl_handler_init(hdl, 0);
+
+@@ -1450,8 +1701,6 @@ static int cssp_cam_probe(struct platform_device *pdev)
+ goto fail1;
+ }
+
+- clk_prepare(cam_dev->camera_clk);
+-
+ ret = configure_cssp(cam_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "configure_cssp failed\n");
+@@ -1484,6 +1733,20 @@ static int cssp_cam_probe(struct platform_device *pdev)
+ if (ret)
+ goto fail4;
+
++ cam_dev->spillover = vb2_dma_contig_memops.alloc(cam_dev->dma_cont_ctx,
++ MAX_WIDTH * MAX_HEIGHT * BYTES_PER_PIXEL);
++ if (cam_dev->spillover == NULL) {
++ ret = -ENOMEM;
++ goto fail4;
++ }
++ cam_dev->spillover_dma_addr = vb2_dma_contig_cookie(
++ cam_dev->dma_cont_ctx, cam_dev->spillover);
++
++ dev_info(&pdev->dev, "spillover at %p, size %d, phys 0x%08lx\n",
++ cam_dev->spillover,
++ MAX_WIDTH * MAX_HEIGHT * BYTES_PER_PIXEL,
++ (unsigned long)cam_dev->spillover_dma_addr);
++
+ dev_err(&pdev->dev, "Loaded OK.\n");
+
+ return 0;
+@@ -1551,7 +1814,7 @@ module_platform_driver(cssp_cam_driver);
+ /*
+ * Macros sets license, author and description
+ */
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPLv2");
+ MODULE_AUTHOR("Dan Aizenstros, Damian Eppel, Przemek Szewczyk");
+ MODULE_DESCRIPTION("QuickLogic Camera Interface driver");
+
diff --git a/patches/linux-3.8.13/0614-cssp_camera-Increase-delay-after-enabling-clocks-to-.patch b/patches/linux-3.8.13/0614-cssp_camera-Increase-delay-after-enabling-clocks-to-.patch
new file mode 100644
index 0000000..1d777a1
--- /dev/null
+++ b/patches/linux-3.8.13/0614-cssp_camera-Increase-delay-after-enabling-clocks-to-.patch
@@ -0,0 +1,30 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 10 May 2013 09:27:26 +0300
+Subject: [PATCH] cssp_camera: Increase delay after enabling clocks to 100ms
+
+---
+ drivers/media/platform/soc_camera/cssp_camera.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+index 62d8702..2c10f61 100644
+--- a/drivers/media/platform/soc_camera/cssp_camera.c
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -657,7 +657,7 @@ static int configure_camera_sensor(struct cssp_cam_dev *cam)
+ /* It is going to be be re-enabled later, when camera will be in use */
+ ret = clk_prepare_enable(cam->camera_clk);
+ BUG_ON(ret != 0);
+- mdelay(1); // let the clock stabilize
++ msleep(100); // let the clock stabilize
+
+ adapter = i2c_get_adapter(((struct soc_camera_link *)(info->platform_data))->i2c_adapter_id);
+ if (!adapter) {
+@@ -848,7 +848,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
+ __func__);
+ return ret;
+ }
+- mdelay(20); /* let the clock stabilize */
++ msleep(100); /* let the clock stabilize */
+
+ fillup_dma(dev);
+
diff --git a/patches/linux-3.8.13/0615-Debugging-camera-stuff.patch b/patches/linux-3.8.13/0615-Debugging-camera-stuff.patch
new file mode 100644
index 0000000..59d05e2
--- /dev/null
+++ b/patches/linux-3.8.13/0615-Debugging-camera-stuff.patch
@@ -0,0 +1,93 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 10 May 2013 10:41:45 +0300
+Subject: [PATCH] Debugging camera stuff
+
+---
+ drivers/media/i2c/soc_camera/mt9t112.c | 4 ++--
+ drivers/media/platform/soc_camera/cssp_camera.c | 16 +++-------------
+ 2 files changed, 5 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
+index d83d217..3154c1f 100644
+--- a/drivers/media/i2c/soc_camera/mt9t112.c
++++ b/drivers/media/i2c/soc_camera/mt9t112.c
+@@ -16,7 +16,7 @@
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+-
++#define DEBUG
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/init.h>
+@@ -31,7 +31,7 @@
+ #include <media/v4l2-common.h>
+
+ /* you can check PLL/clock info */
+-/* #define EXT_CLOCK 24000000 */
++#define EXT_CLOCK 32000000
+
+ //#define TEST_PATTERN
+
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+index 2c10f61..7c8d40e 100644
+--- a/drivers/media/platform/soc_camera/cssp_camera.c
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -544,8 +544,8 @@ static void dma_callback(unsigned lch, u16 ch_status, void *data)
+ do_gettimeofday(&vb->v4l2_buf.timestamp);
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+
+- dev_dbg(&dev->pdev->dev, "[%p/%d] done\n",
+- buf, buf->vb.v4l2_buf.index);
++ /* dev_dbg(&dev->pdev->dev, "[%p/%d] done\n",
++ buf, buf->vb.v4l2_buf.index); */
+
+ }
+ }
+@@ -773,9 +773,6 @@ static int buffer_prepare(struct vb2_buffer *vb)
+ container_of(vb, struct cssp_cam_buffer, vb);
+ unsigned long size;
+
+- dev_dbg(&dev->pdev->dev, "%s, field=%d\n", __func__,
+- vb->v4l2_buf.field);
+-
+ BUG_ON(NULL == dev->fmt);
+
+ /*
+@@ -806,7 +803,6 @@ static int buffer_prepare(struct vb2_buffer *vb)
+ static int buffer_finish(struct vb2_buffer *vb)
+ {
+ struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+ return 0;
+ }
+
+@@ -1124,8 +1120,6 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
+
+- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+-
+ return vb2_qbuf(&dev->vb_vidq, p);
+ }
+
+@@ -1134,10 +1128,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+ struct cssp_cam_dev *dev = video_drvdata(file);
+ u16 val;
+
+- val = ioread16(dev->reg_base_virt + REG_MODE);
+- dev_dbg(&dev->pdev->dev, "%s MODE=0x%04x\n", __func__,
+- val);
+-
+ return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
+ }
+
+@@ -1251,7 +1241,7 @@ static unsigned int video_poll(struct file *file, struct poll_table_struct *wait
+ struct vb2_queue *q = &dev->vb_vidq;
+ unsigned int res;
+
+- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
++ /* dev_dbg(&dev->pdev->dev, "%s\n", __func__); */
+
+ res = vb2_poll(q, file, wait);
+ if (v4l2_event_pending(fh))
diff --git a/patches/linux-3.8.13/0616-cssp_camera-Make-it-work-with-Beaglebone-black.patch b/patches/linux-3.8.13/0616-cssp_camera-Make-it-work-with-Beaglebone-black.patch
new file mode 100644
index 0000000..0824d6c
--- /dev/null
+++ b/patches/linux-3.8.13/0616-cssp_camera-Make-it-work-with-Beaglebone-black.patch
@@ -0,0 +1,112 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 10 May 2013 14:07:49 +0300
+Subject: [PATCH] cssp_camera: Make it work with Beaglebone black
+
+Using the reset control framework, the camera works on the black.
+I love it when a plan comes together...
+---
+ drivers/media/platform/soc_camera/cssp_camera.c | 25 +++++++++++++++++++++--
+ firmware/capes/BB-BONE-CAM3-01-00A2.dts | 5 +++++
+ 2 files changed, 28 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
+index 7c8d40e..119c432 100644
+--- a/drivers/media/platform/soc_camera/cssp_camera.c
++++ b/drivers/media/platform/soc_camera/cssp_camera.c
+@@ -45,6 +45,8 @@
+ #include <linux/of_gpio.h>
+ #include <linux/of_i2c.h>
+
++#include <linux/rstctl.h>
++
+ static unsigned video_nr = -1;
+ module_param(video_nr, uint, 0644);
+ MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
+@@ -181,6 +183,8 @@ struct cssp_cam_dev {
+
+ /* OF build platform data here */
+ struct cssp_cam_platform_data_storage *pstore;
++
++ struct rstctl *rctrl;
+ };
+
+ /*
+@@ -802,7 +806,6 @@ static int buffer_prepare(struct vb2_buffer *vb)
+
+ static int buffer_finish(struct vb2_buffer *vb)
+ {
+- struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+ return 0;
+ }
+
+@@ -1126,7 +1129,6 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+ {
+ struct cssp_cam_dev *dev = video_drvdata(file);
+- u16 val;
+
+ return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
+ }
+@@ -1634,6 +1636,21 @@ static int cssp_cam_probe(struct platform_device *pdev)
+ struct cssp_cam_platform_data *pdata;
+ struct pinctrl *pinctrl;
+ int ret = 0, use_of_pdata = 0;
++ struct rstctl *rctrl;
++
++ rctrl = rstctl_get(&pdev->dev, NULL);
++ if (IS_ERR(rctrl)) {
++ dev_info(&pdev->dev, "Failed to get rstctl; nevermind\n");
++ rctrl = NULL;
++ } else {
++ dev_info(&pdev->dev, "Got rstctl (%s:#%d name %s) label:%s\n",
++ rctrl->rdev->rdesc->name,
++ rctrl->line - rctrl->rdev->rdesc->lines,
++ rctrl->line->name, rctrl->label);
++
++ /* always assert to keep the emmc at reset */
++ rstctl_assert(rctrl);
++ }
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+@@ -1670,6 +1687,8 @@ static int cssp_cam_probe(struct platform_device *pdev)
+ cam_dev->pdev = pdev;
+ platform_set_drvdata(pdev, cam_dev);
+
++ cam_dev->rctrl = rctrl;
++
+ cam_dev->camera_board_info = pdata->cam_i2c_board_info;
+
+ cam_dev->camera_clk = clk_get(&pdev->dev, pdata->cam_clk_name);
+@@ -1780,6 +1799,8 @@ static int cssp_cam_remove(struct platform_device *pdev)
+
+ clk_put(cam->camera_clk);
+
++ rstctl_put(cam->rctrl);
++
+ kfree(cam);
+
+ dev_info(&pdev->dev, "removed\n");
+diff --git a/firmware/capes/BB-BONE-CAM3-01-00A2.dts b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
+index 97bdcfd..e546f08 100644
+--- a/firmware/capes/BB-BONE-CAM3-01-00A2.dts
++++ b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
+@@ -158,6 +158,10 @@
+ /* orientation; -> MT9T112_FLAG_VFLIP */
+ orientation-gpio = <&gpio1 30 0>;
+
++ /* reset controller (for the black) */
++ reset = <&rstctl 0 0>;
++ reset-names = "eMMC_RSTn-CAM3";
++
+ /* camera sensor */
+ cssp,sensor {
+ i2c-adapter = <&i2c2>;
+@@ -176,6 +180,7 @@
+ pll-divider = <24 1 0 7 0 10 14 7 0>;
+ };
+ };
++
+ };
+
+ };
diff --git a/patches/linux-3.8.13/0617-bone-capemgr-Introduce-simple-resource-tracking.patch b/patches/linux-3.8.13/0617-bone-capemgr-Introduce-simple-resource-tracking.patch
new file mode 100644
index 0000000..fa139fb
--- /dev/null
+++ b/patches/linux-3.8.13/0617-bone-capemgr-Introduce-simple-resource-tracking.patch
@@ -0,0 +1,163 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 16 May 2013 18:11:19 +0300
+Subject: [PATCH] bone: capemgr: Introduce simple resource tracking
+
+Now each cape can declare an exclusive-use property which is
+a string list of every resource it requires.
+Attempting to load a cape that uses the same resource will fail.
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 127 +++++++++++++++++++++++++++++++-
+ 1 file changed, 125 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 820852d..2820e39 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -1149,6 +1149,116 @@ static void bone_capemgr_info_sysfs_unregister(struct bone_capemgr_info *info)
+ device_remove_file(dev, &dev_attr_slots);
+ }
+
++/* verify the overlay */
++static int bone_capemgr_verify_overlay(struct bone_cape_slot *slot)
++{
++ struct bone_capemgr_info *info = slot->info;
++ struct device *dev = &info->pdev->dev;
++ struct bone_baseboard *bbrd = &info->baseboard;
++ struct device_node *node = slot->overlay;
++ struct property *prop;
++ struct bone_cape_slot *slotn;
++ int err, counta, countb, i, j;
++ const char *ra, *rb;
++
++ /* validate */
++ if (node == NULL) {
++ dev_err(dev, "slot #%d: No overlay "
++ "for '%s'\n",
++ slot->slotno, slot->part_number);
++ return -EINVAL;
++ }
++
++ /* check if the slot is compatible with the board */
++ prop = of_find_property(node, "compatible", NULL);
++
++ /* no compatible property? */
++ if (prop == NULL) {
++ dev_err(dev, "slot #%d: No compatible property "
++ "for '%s'\n",
++ slot->slotno, slot->part_number);
++ return -EINVAL;
++ }
++
++ /* verify that the cape is baseboard compatible */
++ if (of_multi_prop_cmp(prop, bbrd->compatible_name) != 0) {
++ dev_err(dev, "slot #%d: Incompatible with baseboard "
++ "for '%s'\n",
++ slot->slotno, slot->part_number);
++ return -EINVAL;
++ }
++
++ /* count the strings */
++ counta = of_property_count_strings(node, "exclusive-use");
++ /* no valid property, or no resources; no matter, it's OK */
++ if (counta <= 0)
++ return 0;
++
++ /* and now check if there's a resource conflict */
++ err = 0;
++ mutex_lock(&info->slots_list_mutex);
++ for (i = 0; i < counta; i++) {
++
++ ra = NULL;
++ err = of_property_read_string_index(node, "exclusive-use",
++ i, &ra);
++ if (err != 0) {
++ dev_err(dev, "slot #%d: Could not read string #%d\n",
++ slot->slotno, i);
++ break;
++ }
++
++ list_for_each_entry(slotn, &info->slot_list, node) {
++
++ /* don't check against self */
++ if (slot == slotn)
++ continue;
++
++ /* only check against loaded or loading slots */
++ if (!slotn->loaded && !slotn->loading)
++ continue;
++
++ countb = of_property_count_strings(slotn->overlay,
++ "exclusive-use");
++ /* no valid property, or resources; it's OK */
++ if (countb <= 0)
++ continue;
++
++
++ for (j = 0; j < countb; j++) {
++
++ /* count the resources */
++ rb = NULL;
++ err = of_property_read_string_index(
++ slotn->overlay, "exclusive-use",
++ j, &rb);
++ if (err != 0) {
++ /* error, but we don't care */
++ err = 0;
++ break;
++ }
++
++ /* ignore case; just in case ;) */
++ if (strcasecmp(ra, rb) == 0) {
++
++ /* resource conflict */
++ err = -EEXIST;
++ dev_err(dev, "slot #%d: %s conflict "
++ "%s (#%d:%s)\n", slot->slotno,
++ slot->part_number, ra,
++ slotn->slotno,
++ slotn->part_number);
++ goto out;
++ }
++ }
++ }
++ }
++out:
++ mutex_unlock(&info->slots_list_mutex);
++
++ return err;
++}
++
+ static int bone_capemgr_load(struct bone_cape_slot *slot)
+ {
+ struct bone_capemgr_info *info = slot->info;
+@@ -1273,6 +1383,13 @@ static int bone_capemgr_load(struct bone_cape_slot *slot)
+ goto err_fail;
+ }
+
++ err = bone_capemgr_verify_overlay(slot);
++ if (err != 0) {
++ dev_err(dev, "slot #%d: Failed verification\n",
++ slot->slotno);
++ goto err_fail;
++ }
++
+ /* now build an overlay info array */
+ err = of_build_overlay_info(slot->overlay,
+ &slot->ovinfo_cnt, &slot->ovinfo);
+@@ -1665,8 +1782,14 @@ static int bone_capemgr_loader(void *data)
+
+ slot->loading = 0;
+
+- dev_info(dev, "loader: done slot-%d %s:%s (prio %d)\n", slot->slotno,
+- slot->part_number, slot->version, slot->priority);
++ if (ret == 0)
++ dev_info(dev, "loader: done slot-%d %s:%s (prio %d)\n",
++ slot->slotno, slot->part_number, slot->version,
++ slot->priority);
++ else
++ dev_err(dev, "loader: failed to load slot-%d %s:%s (prio %d)\n",
++ slot->slotno, slot->part_number, slot->version,
++ slot->priority);
+
+ /* we're done, wake up all */
+ wake_up_interruptible_all(&info->load_wq);
diff --git a/patches/linux-3.8.13/0618-capes-Add-resources-to-capes.patch b/patches/linux-3.8.13/0618-capes-Add-resources-to-capes.patch
new file mode 100644
index 0000000..38c4c9c
--- /dev/null
+++ b/patches/linux-3.8.13/0618-capes-Add-resources-to-capes.patch
@@ -0,0 +1,705 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 16 May 2013 18:13:19 +0300
+Subject: [PATCH] capes: Add resources to capes.
+
+Start adding the resource list of each cape.
+---
+ firmware/capes/BB-BONE-AUDI-01-00A0.dts | 15 ++++++++-
+ firmware/capes/BB-BONE-CAM3-01-00A2.dts | 45 +++++++++++++++++++++++++--
+ firmware/capes/BB-BONE-GPEVT-00A0.dts | 2 +-
+ firmware/capes/BB-BONE-PRU-01-00A0.dts | 7 +++++
+ firmware/capes/BB-BONE-PRU-02-00A0.dts | 7 +++++
+ firmware/capes/BB-BONE-PWMT-00A0.dts | 2 +-
+ firmware/capes/BB-BONE-RST-00A0.dts | 2 +-
+ firmware/capes/BB-BONE-RST2-00A0.dts | 2 +-
+ firmware/capes/BB-BONE-eMMC1-01-00A0.dts | 2 +-
+ firmware/capes/am33xx_pwm-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P8_13-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P8_19-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P8_34-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P8_36-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P8_45-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P8_46-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_14-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_16-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_21-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_22-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_28-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_29-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_31-00A0.dts | 2 +-
+ firmware/capes/bone_pwm_P9_42-00A0.dts | 2 +-
+ firmware/capes/cape-bone-2g-emmc1.dts | 18 +++++++++++
+ firmware/capes/cape-bone-dvi-00A1.dts | 2 +-
+ firmware/capes/cape-bone-dvi-00A2.dts | 2 +-
+ firmware/capes/cape-bone-lcd3-00A0.dts | 41 ++++++++++++++++++++++++
+ firmware/capes/cape-bone-lcd3-00A2.dts | 39 +++++++++++++++++++++++
+ firmware/capes/cape-bone-tester-00A0.dts | 2 +-
+ firmware/capes/cape-bone-weather-00A0.dts | 19 +++++------
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 34 +++++++++++++++++++-
+ 32 files changed, 235 insertions(+), 36 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-AUDI-01-00A0.dts b/firmware/capes/BB-BONE-AUDI-01-00A0.dts
+index 8e1256e..5e145b9 100644
+--- a/firmware/capes/BB-BONE-AUDI-01-00A0.dts
++++ b/firmware/capes/BB-BONE-AUDI-01-00A0.dts
+@@ -9,12 +9,25 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-AUDI-01";
+ version = "00A0", "A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.14", /* leds: gpio1_18 */
++ "P9.16", /* leds: gpio1_19 */
++ "P9.31", /* mcasp0: mcasp0_aclkx */
++ "P9.29", /* mcasp0: mcasp0_fsx */
++ "P9.28", /* mcasp0: mcasp0_axr2 */
++ "P9.25", /* mcasp0: mcasp0_ahclkx */
++ /* the hardware ip uses */
++ "gpio1_18", "gpio1_19",
++ "mcasp0";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/BB-BONE-CAM3-01-00A2.dts b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
+index e546f08..2470a76 100644
+--- a/firmware/capes/BB-BONE-CAM3-01-00A2.dts
++++ b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
+@@ -9,12 +9,53 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-CAM3-01";
+ version = "00A2", "A2";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.25", /* gpmc: gpmc_ad0 */
++ "P8.24", /* gpmc: gpmc_ad1 */
++ "P8.5", /* gpmc: gpmc_ad2 */
++ "P8.6", /* gpmc: gpmc_ad3 */
++ "P8.23", /* gpmc: gpmc_ad4 */
++ "P8.22", /* gpmc: gpmc_ad5 */
++ "P8.3", /* gpmc: gpmc_ad6 */
++ "P8.4", /* gpmc: gpmc_ad7 */
++ "P8.19", /* gpmc: gpmc_ad8 */
++ "P8.13", /* gpmc: gpmc_ad9 */
++ "P8.14", /* gpmc: gpmc_ad10 */
++ "P8.17", /* gpmc: gpmc_ad11 */
++ "P8.12", /* gpmc: gpmc_ad12 */
++ "P8.11", /* gpmc: gpmc_ad13 */
++ "P8.16", /* gpmc: gpmc_ad14 */
++ "P8.15", /* gpmc: gpmc_ad15 */
++ "P9.13", /* gpmc: gpmc_wpn */
++ "P8.21", /* gpmc: gpmc_csn1 */
++ "P8.18", /* gpmc: gpmc_clk */
++ "P8.7", /* gpmc: gpmc_advn_ale */
++ "P8.8", /* gpmc: gpmc_oen_ren */
++ "P8.10", /* gpmc: gpmc_wen */
++ "P8.9", /* gpmc: gpmc_ben0_cle */
++ "P9.41", /* cssp: clkout2 */
++ "P9.42", /* cssp: xdma_event_intr2 */
++ "P9.18", /* cssp: gpio0_4 */
++ "P9.17", /* cssp: gpio0_5 */
++ "P9.11", /* cssp: gpio0_30 */
++
++ /* the hardware IP uses */
++ "gpio0_4",
++ "gpio0_5",
++ "gpio0_30",
++ "gpmc",
++ "clkout2",
++ /* the reset pin */
++ "eMMC_RSTn";
++
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+@@ -41,7 +82,7 @@
+ 0x038 0x30 /* gpmc_ad14.gpmc_ad14 MODE0 | INPUT | PULLUP */
+ 0x03C 0x30 /* gpmc_ad15.gpmc_ad15 MODE0 | INPUT | PULLUP */
+ 0x074 0x30 /* gpmc_wpn.gpmc_wpn MODE0 | INPUT | PULLUP */ /* WAS MODE 7 */
+- 0x080 0x08 /* gpmc_wait0.gpmc_cscn1 MODE0 | OUTPUT */
++ 0x080 0x08 /* gpmc_cscn1.gpmc_cscn1 MODE0 | OUTPUT */
+ 0x08C 0x28 /* gpmc_clk.gpmc_clk MODE0 | INPUT */
+ 0x090 0x08 /* gpmc_advn_ale.gpmc_advn_ale MODE0 | OUTPUT */
+ 0x094 0x08 /* gpmc_oen_ren.gpmc_oen_ren MODE0 | OUTPUT */
+diff --git a/firmware/capes/BB-BONE-GPEVT-00A0.dts b/firmware/capes/BB-BONE-GPEVT-00A0.dts
+index 80f9016..112a6d1 100644
+--- a/firmware/capes/BB-BONE-GPEVT-00A0.dts
++++ b/firmware/capes/BB-BONE-GPEVT-00A0.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-GPEVT";
+diff --git a/firmware/capes/BB-BONE-PRU-01-00A0.dts b/firmware/capes/BB-BONE-PRU-01-00A0.dts
+index 29ab671..9bf2c7a 100644
+--- a/firmware/capes/BB-BONE-PRU-01-00A0.dts
++++ b/firmware/capes/BB-BONE-PRU-01-00A0.dts
+@@ -15,6 +15,13 @@
+ part-number = "BB-BONE-PRU-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.27", /* pru0: pr1_pru0_pru_r30_5 */
++ /* the hardware IP uses */
++ "pru0";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/BB-BONE-PRU-02-00A0.dts b/firmware/capes/BB-BONE-PRU-02-00A0.dts
+index ddb63f7..13389c7 100644
+--- a/firmware/capes/BB-BONE-PRU-02-00A0.dts
++++ b/firmware/capes/BB-BONE-PRU-02-00A0.dts
+@@ -15,6 +15,13 @@
+ part-number = "BB-BONE-PRU-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.27", /* pru0: pr1_pru0_pru_r30_5 */
++ /* the hardware IP uses */
++ "pru0";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/BB-BONE-PWMT-00A0.dts b/firmware/capes/BB-BONE-PWMT-00A0.dts
+index fb2b8b1..02c2c0e 100644
+--- a/firmware/capes/BB-BONE-PWMT-00A0.dts
++++ b/firmware/capes/BB-BONE-PWMT-00A0.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-PWMT";
+diff --git a/firmware/capes/BB-BONE-RST-00A0.dts b/firmware/capes/BB-BONE-RST-00A0.dts
+index acdcda4..12c696f 100644
+--- a/firmware/capes/BB-BONE-RST-00A0.dts
++++ b/firmware/capes/BB-BONE-RST-00A0.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-RST";
+diff --git a/firmware/capes/BB-BONE-RST2-00A0.dts b/firmware/capes/BB-BONE-RST2-00A0.dts
+index 6904cc5..50b3a60 100644
+--- a/firmware/capes/BB-BONE-RST2-00A0.dts
++++ b/firmware/capes/BB-BONE-RST2-00A0.dts
+@@ -7,7 +7,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-RST2";
+diff --git a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+index 0776bee..ac3c0c3 100644
+--- a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
++++ b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-eMMC1-01";
+diff --git a/firmware/capes/am33xx_pwm-00A0.dts b/firmware/capes/am33xx_pwm-00A0.dts
+index 609c1db..fa8d770 100644
+--- a/firmware/capes/am33xx_pwm-00A0.dts
++++ b/firmware/capes/am33xx_pwm-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "test1";
+diff --git a/firmware/capes/bone_pwm_P8_13-00A0.dts b/firmware/capes/bone_pwm_P8_13-00A0.dts
+index 6c2168a..d7a22f8 100644
+--- a/firmware/capes/bone_pwm_P8_13-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_13-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P8_13";
+diff --git a/firmware/capes/bone_pwm_P8_19-00A0.dts b/firmware/capes/bone_pwm_P8_19-00A0.dts
+index f5f7454..c8071766 100644
+--- a/firmware/capes/bone_pwm_P8_19-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_19-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P8_19";
+diff --git a/firmware/capes/bone_pwm_P8_34-00A0.dts b/firmware/capes/bone_pwm_P8_34-00A0.dts
+index be227bf..44e4ff7 100644
+--- a/firmware/capes/bone_pwm_P8_34-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_34-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P8_34";
+diff --git a/firmware/capes/bone_pwm_P8_36-00A0.dts b/firmware/capes/bone_pwm_P8_36-00A0.dts
+index 7ca8694c..12fe6ef 100644
+--- a/firmware/capes/bone_pwm_P8_36-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_36-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P8_36";
+diff --git a/firmware/capes/bone_pwm_P8_45-00A0.dts b/firmware/capes/bone_pwm_P8_45-00A0.dts
+index 3bc8103..07c8457 100644
+--- a/firmware/capes/bone_pwm_P8_45-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_45-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P8_45";
+diff --git a/firmware/capes/bone_pwm_P8_46-00A0.dts b/firmware/capes/bone_pwm_P8_46-00A0.dts
+index 4cc6170..147a3c6 100644
+--- a/firmware/capes/bone_pwm_P8_46-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_46-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P8_46";
+diff --git a/firmware/capes/bone_pwm_P9_14-00A0.dts b/firmware/capes/bone_pwm_P9_14-00A0.dts
+index 6a6c01a..0c6c784 100644
+--- a/firmware/capes/bone_pwm_P9_14-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_14-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_14";
+diff --git a/firmware/capes/bone_pwm_P9_16-00A0.dts b/firmware/capes/bone_pwm_P9_16-00A0.dts
+index a1ee9d8..252ee8c 100644
+--- a/firmware/capes/bone_pwm_P9_16-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_16-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_16";
+diff --git a/firmware/capes/bone_pwm_P9_21-00A0.dts b/firmware/capes/bone_pwm_P9_21-00A0.dts
+index e667f81..f2d540a 100644
+--- a/firmware/capes/bone_pwm_P9_21-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_21-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_21";
+diff --git a/firmware/capes/bone_pwm_P9_22-00A0.dts b/firmware/capes/bone_pwm_P9_22-00A0.dts
+index f7c5ed2..df338f7 100644
+--- a/firmware/capes/bone_pwm_P9_22-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_22-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_22";
+diff --git a/firmware/capes/bone_pwm_P9_28-00A0.dts b/firmware/capes/bone_pwm_P9_28-00A0.dts
+index 96df33d..ace91df 100644
+--- a/firmware/capes/bone_pwm_P9_28-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_28-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_28";
+diff --git a/firmware/capes/bone_pwm_P9_29-00A0.dts b/firmware/capes/bone_pwm_P9_29-00A0.dts
+index 5cff5a8..33ae722 100644
+--- a/firmware/capes/bone_pwm_P9_29-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_29-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_29";
+diff --git a/firmware/capes/bone_pwm_P9_31-00A0.dts b/firmware/capes/bone_pwm_P9_31-00A0.dts
+index 8126597..8096f62 100644
+--- a/firmware/capes/bone_pwm_P9_31-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_31-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_31";
+diff --git a/firmware/capes/bone_pwm_P9_42-00A0.dts b/firmware/capes/bone_pwm_P9_42-00A0.dts
+index 7ffcb9b..5ba487f 100644
+--- a/firmware/capes/bone_pwm_P9_42-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_42-00A0.dts
+@@ -10,7 +10,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "bone_pwm_P9_42";
+diff --git a/firmware/capes/cape-bone-2g-emmc1.dts b/firmware/capes/cape-bone-2g-emmc1.dts
+index bf26ae1..90067d5 100644
+--- a/firmware/capes/cape-bone-2g-emmc1.dts
++++ b/firmware/capes/cape-bone-2g-emmc1.dts
+@@ -16,6 +16,24 @@
+ part-number = "*"; /* any part number */
+ version = "*"; /* any version */
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.21", /* mmc1: mmc1_clk */
++ "P8.20", /* mmc1: mmc1_cmd */
++ "P8.25", /* mmc1: mmc1_dat0 */
++ "P8.24", /* mmc1: mmc1_dat1 */
++ "P8.5", /* mmc1: mmc1_dat2 */
++ "P8.6", /* mmc1: mmc1_dat3 */
++ "P8.23", /* mmc1: mmc1_dat4 */
++ "P8.22", /* mmc1: mmc1_dat5 */
++ "P8.3", /* mmc1: mmc1_dat6 */
++ "P8.4", /* mmc1: mmc1_dat7 */
++ /* the hardware IP uses */
++ "mmc1",
++ /* the reset pin */
++ "eMMC_RSTn";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index ed9099c..b320d4f 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-DVID-01";
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+index a3cd39d..d5c49bb 100644
+--- a/firmware/capes/cape-bone-dvi-00A2.dts
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+ part-number = "BB-BONE-DVID-01";
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index 1ac8462..a2f8b35 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -15,6 +15,47 @@
+ part-number = "BB-BONE-LCD3-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ "P9.14", /* led: gpio1_18 */
++ "P9.16", /* led: gpio1_19 */
++ "P9.15", /* keys: gpio1_16 */
++ "P9.23", /* keys: gpio1_17 */
++ "P9.27", /* keys: gpio3_19 */
++ "P9.12", /* keys: gpio1_28 */
++ "P9.42", /* keys: gpio0_7 */
++ /* the hardware IP uses */
++ "gpio1_18",
++ "gpio1_19",
++ "gpio1_16",
++ "gpio1_17",
++ "gpio3_19",
++ "gpio0_7",
++ "lcd",
++ "tps-bl",
++ "tscadc";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index 9c7bb17..c2cdedc 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -15,6 +15,45 @@
+ part-number = "BB-BONE-LCD3-01";
+ version = "00A2";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ "P9.27", /* led: gpio3_19 */
++ "P9.14", /* bl: ehrpwm1a*/
++ "P9.15", /* keys: gpio1_16*/
++ "P9.23", /* keys: gpio1_17*/
++ "P9.16", /* keys: gpio1_19*/
++ "P9.21", /* keys: gpio0_3*/
++ /* the hardware IP uses */
++ "gpio3_19",
++ "gpio1_16",
++ "gpio1_17",
++ "gpio1_19",
++ "gpio0_3",
++ "lcd",
++ "ehrpwm1a",
++ "tscadc";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index 4d7dc68..b5b1be8 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -9,7 +9,7 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone", "ti,beaglebone-black";
++ compatible = "ti,beaglebone";
+
+ /* identification */
+ part-number = "BB-BONE-TESTER";
+diff --git a/firmware/capes/cape-bone-weather-00A0.dts b/firmware/capes/cape-bone-weather-00A0.dts
+index 76284d6..7cb479a 100644
+--- a/firmware/capes/cape-bone-weather-00A0.dts
++++ b/firmware/capes/cape-bone-weather-00A0.dts
+@@ -9,11 +9,12 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
+- part-number = "BB-BONE-WTHR-01";
+- version = "00A0";
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+- fragment@0 {
++ part-number = "BB-BONE-WTHR-01";
++ version = "00A0";
++
++ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+ weather_cape_w1_pins: pinmux_weather_cape_w1_pins {
+@@ -22,9 +23,9 @@
+ >;
+ };
+ };
+- };
++ };
+
+- fragment@1 {
++ fragment@1 {
+ target = <&i2c2>;
+
+ __overlay__ {
+@@ -50,9 +51,9 @@
+ reg = <0x77>;
+ };
+ };
+- };
++ };
+
+- fragment@2 {
++ fragment@2 {
+ target = <&ocp>;
+ __overlay__ {
+ onewire@0 {
+@@ -64,5 +65,5 @@
+ gpios = <&gpio2 3 0>;
+ };
+ };
+- };
++ };
+ };
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index e5f714a..5fdbd9e 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -9,10 +9,42 @@
+ /plugin/;
+
+ / {
+- compatible = "ti,beaglebone";
++ compatible = "ti,beaglebone-black";
+ part-number = "BB-BONELT-HDMI";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.25", /* mcasp0: mcasp0_ahclkx */
++ "P9.28", /* mcasp0: mcasp0_axr2 */
++ "P9.29", /* mcasp0: mcasp0_fsx */
++ "P9.31", /* mcasp0: mcasp0_aclkx */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ /* the hardware IP uses */
++ "gpio1_27",
++ "mcasp0",
++ "lcd";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
diff --git a/patches/linux-3.8.13/0619-capes-Update-most-of-the-capes-with-resource-definit.patch b/patches/linux-3.8.13/0619-capes-Update-most-of-the-capes-with-resource-definit.patch
new file mode 100644
index 0000000..70046c8
--- /dev/null
+++ b/patches/linux-3.8.13/0619-capes-Update-most-of-the-capes-with-resource-definit.patch
@@ -0,0 +1,1100 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 17 May 2013 18:38:30 +0300
+Subject: [PATCH] capes: Update most of the capes with resource definitions
+
+Updated all the standard capes with their resource definitions.
+---
+ firmware/capes/BB-BONE-GPEVT-00A0.dts | 7 ++++
+ firmware/capes/BB-BONE-LCD4-01-00A0.dts | 31 +++++++++++++++
+ firmware/capes/BB-BONE-LCD4-01-00A1.dts | 46 +++++++++++++++++++++--
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 46 +++++++++++++++++++++--
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 48 ++++++++++++++++++++++--
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 47 ++++++++++++++++++++++-
+ firmware/capes/BB-BONE-PWMT-00A0.dts | 9 ++++-
+ firmware/capes/BB-BONE-eMMC1-01-00A0.dts | 16 ++++++++
+ firmware/capes/BB-BONELT-BT-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P8_13-00A0.dts | 13 ++++++-
+ firmware/capes/bone_pwm_P8_19-00A0.dts | 13 ++++++-
+ firmware/capes/bone_pwm_P8_34-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P8_36-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P8_45-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P8_46-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_14-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_16-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_21-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_22-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_28-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_29-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_31-00A0.dts | 7 ++++
+ firmware/capes/bone_pwm_P9_42-00A0.dts | 7 ++++
+ firmware/capes/cape-bone-adafruit-lcd-00A0.dts | 31 +++++++++++----
+ firmware/capes/cape-bone-adafruit-rtc-00A0.dts | 15 ++++++++
+ firmware/capes/cape-bone-dvi-00A0.dts | 32 ++++++++++++++++
+ firmware/capes/cape-bone-dvi-00A1.dts | 37 ++++++++++++++++++
+ firmware/capes/cape-bone-dvi-00A2.dts | 32 ++++++++++++++++
+ firmware/capes/cape-bone-geiger-00A0.dts | 15 ++++++++
+ firmware/capes/cape-bone-iio-00A0.dts | 13 +++++++
+ firmware/capes/cape-bone-mrf24j40-00A0.dts | 16 ++++++++
+ firmware/capes/cape-bone-nixie-00A0.dts | 18 ++++++++-
+ firmware/capes/cape-bone-tester-00A0.dts | 2 +
+ firmware/capes/cape-bone-weather-00A0.dts | 7 ++++
+ 34 files changed, 559 insertions(+), 26 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-GPEVT-00A0.dts b/firmware/capes/BB-BONE-GPEVT-00A0.dts
+index 112a6d1..e773dee 100644
+--- a/firmware/capes/BB-BONE-GPEVT-00A0.dts
++++ b/firmware/capes/BB-BONE-GPEVT-00A0.dts
+@@ -13,6 +13,13 @@
+ part-number = "BB-BONE-GPEVT";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.7",
++ /* the hardware IP uses */
++ "gpio2_2";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A0.dts b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+index b1c7e00..4b6f3cc 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A0.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+@@ -15,6 +15,37 @@
+ part-number = "BB-BONE-LCD4-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ "P9.16", /* tsc: gpio1_19 */
++ "P9.14", /* led: gpio1_18 */
++ /* the hardware IP uses */
++ "gpio1_19",
++ "gpio1_18",
++ "lcd",
++ "tps-bl";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A1.dts b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+index bd3c2a8..b424c09 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A1.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+@@ -15,13 +15,53 @@
+ part-number = "BB-BONE-LCD4-01";
+ version = "00A1";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ "P9.27", /* lcd: gpio3_19 */
++ "P9.12", /* led: gpio1_28 */
++ "P9.14", /* pwm: ehrpwm1a */
++ "P9.15", /* keys: gpio1_16 */
++ "P9.23", /* keys: gpio1_17 */
++ "P9.16", /* keys: gpio1_19 */
++ "P9.21", /* keys: gpio0_3 */
++ /* the hardware IP uses */
++ "gpio3_19",
++ "gpio1_28",
++ "gpio1_16",
++ "gpio1_17",
++ "gpio1_19",
++ "gpio0_3",
++ "lcd",
++ "ehrpwm1a";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+
+- bone_lcd4_cape_led_00A2_pins: pinmux_bone_lcd4_cape_led_00A2_pins {
++ bone_lcd4_cape_led_00A1_pins: pinmux_bone_lcd4_cape_led_00A1_pins {
+ pinctrl-single,pins = <
+- 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ 0x078 0x2f /* gpmc_be1n.gpio1_28, INPUT | PULLDIS | MODE7 */
+ >;
+ };
+
+@@ -129,7 +169,7 @@
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+
+- pinctrl-0 = <&bone_lcd4_cape_led_00A2_pins>;
++ pinctrl-0 = <&bone_lcd4_cape_led_00A1_pins>;
+
+ lcd4-led0 {
+ label = "lcd4:green:usr0";
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index d1eac3b..77ef5ec 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -15,13 +15,53 @@
+ part-number = "BB-BONE-LCD7-01";
+ version = "00A2";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ "P8.20", /* lcd: gpio1_31 */
++ "P9.12", /* led: gpio1_28 */
++ "P9.14", /* pwm: ehrpwm1a */
++ "P9.15", /* keys: gpio1_16 */
++ "P9.23", /* keys: gpio1_17 */
++ "P9.16", /* keys: gpio1_19 */
++ "P9.27", /* keys: gpio3_19 */
++ /* the hardware IP uses */
++ "gpio1_31",
++ "gpio1_28",
++ "gpio1_16",
++ "gpio1_17",
++ "gpio1_19",
++ "gpio3_19",
++ "lcd",
++ "ehrpwm1a";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+
+ bone_lcd7_cape_led_00A2_pins: pinmux_bone_lcd7_cape_led_00A2_pins {
+ pinctrl-single,pins = <
+- 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ 0x078 0x2f /* gpmc_be1n.gpio1_28, INPUT | PULLDIS | MODE7 */
+ >;
+ };
+
+@@ -33,7 +73,7 @@
+
+ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+ pinctrl-single,pins = <
+- //0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
+ 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 */
+@@ -62,8 +102,8 @@
+ 0x040 0x2f /* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
++ 0x198 0x2f /* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
+ 0x1a4 0x2f /* KEY_ENTER mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+- // gpio3_16 KEY_DOWN
+ >;
+ };
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index 979fd73..f5fab09 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -15,6 +15,48 @@
+ part-number = "BB-BONE-LCD7-01";
+ version = "00A3";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ "P8.20", /* lcd: gpio1_31 */
++ "P9.12", /* led: gpio1_28 */
++ "P9.14", /* pwm: ehrpwm1a */
++ "P9.15", /* keys: gpio1_16 */
++ "P9.23", /* keys: gpio1_17 */
++ "P9.16", /* keys: gpio1_19 */
++ "P9.30", /* keys: gpio3_16 */
++ "P9.21", /* keys: gpio0_3 */
++ /* the hardware IP uses */
++ "gpio1_31",
++ "gpio1_28",
++ "gpio1_16",
++ "gpio1_17",
++ "gpio1_19",
++ "gpio3_16",
++ "gpio0_3",
++ "lcd",
++ "ehrpwm1a";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+@@ -33,7 +75,7 @@
+
+ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+ pinctrl-single,pins = <
+- //0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
+ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa3 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 */
+@@ -62,8 +104,8 @@
+ 0x040 0x2f /* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+- 0x1a3 0x2f /* TSC_INTn mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+- // gpio3_16 KEY_DOWN
++ 0x198 0x2f /* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
++ 0x070 0x2f /* KEY_ENTER gpmc_wait0.gpio0_3, INPUT | PULLDIS | MODE7 */
+ >;
+ };
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+index 6f34b79..81553e6 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A4.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -15,6 +15,48 @@
+ part-number = "BB-BONE-LCD7-01";
+ version = "00A4";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ "P8.20", /* lcd: gpio1_31 */
++ "P9.12", /* led: gpio1_28 */
++ "P9.14", /* pwm: ehrpwm1a */
++ "P9.15", /* keys: gpio1_16 */
++ "P9.23", /* keys: gpio1_17 */
++ "P9.16", /* keys: gpio1_19 */
++ "P9.30", /* keys: gpio3_16 */
++ "P9.21", /* keys: gpio0_3 */
++ /* the hardware IP uses */
++ "gpio1_31",
++ "gpio1_28",
++ "gpio1_16",
++ "gpio1_17",
++ "gpio1_19",
++ "gpio3_16",
++ "gpio0_3",
++ "lcd",
++ "ehrpwm1a";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+@@ -33,7 +75,7 @@
+
+ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+ pinctrl-single,pins = <
+- //0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
+ 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 */
+@@ -62,8 +104,9 @@
+ 0x040 0x2f /* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
++ 0x198 0x2f /* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
++ 0x070 0x2f /* KEY_ENTER gpmc_wait0.gpio0_3, INPUT | PULLDIS | MODE7 */
+ 0x1a4 0x2f /* TSC_INTn mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+- // gpio3_16 KEY_DOWN
+ >;
+ };
+
+diff --git a/firmware/capes/BB-BONE-PWMT-00A0.dts b/firmware/capes/BB-BONE-PWMT-00A0.dts
+index 02c2c0e..49747c9 100644
+--- a/firmware/capes/BB-BONE-PWMT-00A0.dts
++++ b/firmware/capes/BB-BONE-PWMT-00A0.dts
+@@ -15,11 +15,18 @@
+ part-number = "BB-BONE-PWMT";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.22", /* pwm: ehrpwm0a */
++ /* the hardware ip uses */
++ "ehrpwm0a";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+ pwm_test_pins: pinmux_pwm_test_pins {
+- pinctrl-single,pins = <0x150 0x3>; /* spi0_sclk = ehrpwm0A = P9_14 = Heater_HBP | MODE 3 */
++ pinctrl-single,pins = <0x150 0x3>; /* spi0_sclk = ehrpwm0A = P9_14 | MODE 3 */
+ };
+ };
+ };
+diff --git a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+index ac3c0c3..44c01fe 100644
+--- a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
++++ b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
+@@ -15,6 +15,22 @@
+ part-number = "BB-BONE-eMMC1-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.21", /* mmc1: mmc1_clk */
++ "P8.20", /* mmc1: mmc1_cmd */
++ "P8.25", /* mmc1: mmc1_dat0 */
++ "P8.24", /* mmc1: mmc1_dat1 */
++ "P8.5", /* mmc1: mmc1_dat2 */
++ "P8.6", /* mmc1: mmc1_dat3 */
++ "P8.23", /* mmc1: mmc1_dat4 */
++ "P8.22", /* mmc1: mmc1_dat5 */
++ "P8.3", /* mmc1: mmc1_dat6 */
++ "P8.4", /* mmc1: mmc1_dat7 */
++ /* the hardware IP uses */
++ "mmc1";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/BB-BONELT-BT-00A0.dts b/firmware/capes/BB-BONELT-BT-00A0.dts
+index 94b9a12..dc3b386 100644
+--- a/firmware/capes/BB-BONELT-BT-00A0.dts
++++ b/firmware/capes/BB-BONELT-BT-00A0.dts
+@@ -15,6 +15,13 @@
+ part-number = "BB-BONELT-BT";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.43", /* bt: gpio2_8 */
++ /* the hardware IP uses */
++ "gpio2_8";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P8_13-00A0.dts b/firmware/capes/bone_pwm_P8_13-00A0.dts
+index d7a22f8..dde034e 100644
+--- a/firmware/capes/bone_pwm_P8_13-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_13-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P8_13";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.13", /* pwm: ehrpwm2B */
++ /* the hardware IP uses */
++ "ehrpwm2B";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+@@ -32,8 +39,10 @@
+ compatible = "pwm_test";
+ pwms = <&ehrpwm2 1 500000 1>;
+ pwm-names = "PWM_P8_13";
+- pinctrl-names = "default";
+- pinctrl-0 = <&pwm_P8_13>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_13>;
++
+ enabled = <1>;
+ duty = <0>;
+ status = "okay";
+diff --git a/firmware/capes/bone_pwm_P8_19-00A0.dts b/firmware/capes/bone_pwm_P8_19-00A0.dts
+index c8071766..ea52f65 100644
+--- a/firmware/capes/bone_pwm_P8_19-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_19-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P8_19";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.19", /* pwm: ehrpwm2A */
++ /* the hardware IP uses */
++ "ehrpwm2A";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+@@ -32,8 +39,10 @@
+ compatible = "pwm_test";
+ pwms = <&ehrpwm2 0 500000 1>;
+ pwm-names = "PWM_P8_19";
+- pinctrl-names = "default";
+- pinctrl-0 = <&pwm_P8_19>;
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_P8_19>;
++
+ enabled = <1>;
+ duty = <0>;
+ status = "okay";
+diff --git a/firmware/capes/bone_pwm_P8_34-00A0.dts b/firmware/capes/bone_pwm_P8_34-00A0.dts
+index 44e4ff7..d7b22bd 100644
+--- a/firmware/capes/bone_pwm_P8_34-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_34-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P8_34";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.34", /* pwm: ehrpwm1B */
++ /* the hardware IP uses */
++ "ehrpwm1B";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P8_36-00A0.dts b/firmware/capes/bone_pwm_P8_36-00A0.dts
+index 12fe6ef..ab1f436 100644
+--- a/firmware/capes/bone_pwm_P8_36-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_36-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P8_36";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.36", /* pwm: ehrpwm1A */
++ /* the hardware IP uses */
++ "ehrpwm1A";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P8_45-00A0.dts b/firmware/capes/bone_pwm_P8_45-00A0.dts
+index 07c8457..a612209 100644
+--- a/firmware/capes/bone_pwm_P8_45-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_45-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P8_45";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* pwm: ehrpwm2A */
++ /* the hardware IP uses */
++ "ehrpwm2A";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P8_46-00A0.dts b/firmware/capes/bone_pwm_P8_46-00A0.dts
+index 147a3c6..45e4432 100644
+--- a/firmware/capes/bone_pwm_P8_46-00A0.dts
++++ b/firmware/capes/bone_pwm_P8_46-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P8_46";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.46", /* pwm: ehrpwm2B */
++ /* the hardware IP uses */
++ "ehrpwm2B";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_14-00A0.dts b/firmware/capes/bone_pwm_P9_14-00A0.dts
+index 0c6c784..23c3c89 100644
+--- a/firmware/capes/bone_pwm_P9_14-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_14-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_14";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.14", /* pwm: ehrpwm1A */
++ /* the hardware IP uses */
++ "ehrpwm1A";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_16-00A0.dts b/firmware/capes/bone_pwm_P9_16-00A0.dts
+index 252ee8c..fdb7258 100644
+--- a/firmware/capes/bone_pwm_P9_16-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_16-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_16";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.16", /* pwm: ehrpwm1B */
++ /* the hardware IP uses */
++ "ehrpwm1B";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_21-00A0.dts b/firmware/capes/bone_pwm_P9_21-00A0.dts
+index f2d540a..485ffd7 100644
+--- a/firmware/capes/bone_pwm_P9_21-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_21-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_21";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.21", /* pwm: ehrpwm0B */
++ /* the hardware IP uses */
++ "ehrpwm0B";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_22-00A0.dts b/firmware/capes/bone_pwm_P9_22-00A0.dts
+index df338f7..111e6e4 100644
+--- a/firmware/capes/bone_pwm_P9_22-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_22-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_22";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.22", /* pwm: ehrpwm0A */
++ /* the hardware IP uses */
++ "ehrpwm0A";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_28-00A0.dts b/firmware/capes/bone_pwm_P9_28-00A0.dts
+index ace91df..73c59c9 100644
+--- a/firmware/capes/bone_pwm_P9_28-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_28-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_28";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.28", /* pwm: eCAP2_in_PWM2_out */
++ /* the hardware IP uses */
++ "eCAP2_in_PWM2_out";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_29-00A0.dts b/firmware/capes/bone_pwm_P9_29-00A0.dts
+index 33ae722..16a3533 100644
+--- a/firmware/capes/bone_pwm_P9_29-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_29-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_29";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.29", /* pwm: ehrpwm0B */
++ /* the hardware IP uses */
++ "ehrpwm0B";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_31-00A0.dts b/firmware/capes/bone_pwm_P9_31-00A0.dts
+index 8096f62..467c993 100644
+--- a/firmware/capes/bone_pwm_P9_31-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_31-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_31";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.31", /* pwm: ehrpwm0A */
++ /* the hardware IP uses */
++ "ehrpwm0A";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/bone_pwm_P9_42-00A0.dts b/firmware/capes/bone_pwm_P9_42-00A0.dts
+index 5ba487f..90e1df8 100644
+--- a/firmware/capes/bone_pwm_P9_42-00A0.dts
++++ b/firmware/capes/bone_pwm_P9_42-00A0.dts
+@@ -16,6 +16,13 @@
+ part-number = "bone_pwm_P9_42";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.42", /* pwm: eCAP0_in_PWM0_out */
++ /* the hardware IP uses */
++ "eCAP0_in_PWM0_out";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+index 6fe5dcf..8c0343b 100644
+--- a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
++++ b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+@@ -24,13 +24,29 @@
+ */
+
+ / {
+- compatible = "ti,beaglebone", "ti,beaglebone-black";
+- part-number = "BB-BONE-TFT-01";
+- version = "00A0";
+-
+- fragment@0 {
+- target = <&am33xx_pinmux>;
+- __overlay__ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "BB-BONE-TFT-01";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.19", /* bl: ehrpwm2A */
++ "P9.27", /* lcd: gpio3_19 */
++ "P9.25", /* lcd: gpio3_21 */
++ "P9.31", /* spi: spi1_sclk */
++ "P9.29", /* spi: spi1_d0 */
++ "P9.30", /* spi: spi1_d1 */
++ "P9.28", /* spi: spi1_cs0 */
++ /* the hardware IP uses */
++ "gpio3_19",
++ "gpio3_21",
++ "ehrpwm2A",
++ "spi1";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
+ pwm_backlight_pins: pinmux_pwm_backlight_pins {
+ pinctrl-single,pins = <
+ 0x020 0x4 /* gpmc_ad8.gpio0_22 | MODE4 */
+@@ -122,5 +138,4 @@
+ };
+ };
+ };
+-
+ };
+diff --git a/firmware/capes/cape-bone-adafruit-rtc-00A0.dts b/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
+index 9436fd4..35344fd 100644
+--- a/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
++++ b/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
+@@ -23,6 +23,21 @@
+ part-number = "BB-BONE-RTC-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.19", /* bl: ehrpwm2A */
++ "P9.27", /* lcd: gpio3_19 */
++ "P9.25", /* lcd: gpio3_21 */
++ "P9.31", /* spi: spi1_sclk */
++ "P9.29", /* spi: spi1_d0 */
++ "P9.30", /* spi: spi1_d1 */
++ "P9.28", /* spi: spi1_cs0 */
++ /* the hardware IP uses */
++ "gpio3_19",
++ "gpio3_21",
++ "ehrpwm2A",
++ "spi1";
+
+ fragment@0 {
+ target = <&i2c2>;
+diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
+index 92fc6be..577a474 100644
+--- a/firmware/capes/cape-bone-dvi-00A0.dts
++++ b/firmware/capes/cape-bone-dvi-00A0.dts
+@@ -15,6 +15,38 @@
+ part-number = "BB-BONE-DVID-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.14", /* led: gpio1_18 */
++ "P9.16", /* led: gpio1_19 */
++ "P8.4", /* lcd: gpio1_7 */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ /* the hardware IP uses */
++ "gpio1_18",
++ "gpio1_19",
++ "gpio1_7",
++ "lcd";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
+index b320d4f..ac8b4c5 100644
+--- a/firmware/capes/cape-bone-dvi-00A1.dts
++++ b/firmware/capes/cape-bone-dvi-00A1.dts
+@@ -15,6 +15,43 @@
+ part-number = "BB-BONE-DVID-01";
+ version = "00A1", "A1";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.14", /* led: gpio1_18 */
++ "P9.16", /* led: gpio1_19 */
++ "P9.25", /* mcasp0: mcasp0_ahclkx */
++ "P9.28", /* mcasp0: mcasp0_axr2 */
++ "P9.29", /* mcasp0: mcasp0_fsx */
++ "P9.31", /* mcasp0: mcasp0_aclkx */
++ "P8.4", /* lcd: gpio1_7 */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ /* the hardware IP uses */
++ "gpio1_18",
++ "gpio1_19",
++ "gpio1_7",
++ "mcasp0",
++ "lcd";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
+index d5c49bb..4c54804 100644
+--- a/firmware/capes/cape-bone-dvi-00A2.dts
++++ b/firmware/capes/cape-bone-dvi-00A2.dts
+@@ -15,6 +15,38 @@
+ part-number = "BB-BONE-DVID-01";
+ version = "00A3", "00A2", "A2";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.14", /* led: gpio1_18 */
++ "P9.16", /* led: gpio1_19 */
++ "P8.4", /* lcd: gpio1_7 */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ /* the hardware IP uses */
++ "gpio1_18",
++ "gpio1_19",
++ "gpio1_7",
++ "lcd";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
+index 967e03b..fed2a63 100644
+--- a/firmware/capes/cape-bone-geiger-00A0.dts
++++ b/firmware/capes/cape-bone-geiger-00A0.dts
+@@ -15,6 +15,21 @@
+ part-number = "BB-BONE-GEIGER";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.29", /* led: gpio2_23 */
++ "P8.30", /* led: gpio2_25 */
++ "P9.14", /* geiger: ehrpwm1A */
++ "P9.28", /* geiger: gpio3_17 */
++ "P9.36", /* geiger: AIN5 */
++ /* the hardware IP uses */
++ "gpio2_23",
++ "gpio2_25",
++ "gpio3_17",
++ "ehrpwm1A",
++ "tscadc";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-iio-00A0.dts b/firmware/capes/cape-bone-iio-00A0.dts
+index f1cf814..416712b 100644
+--- a/firmware/capes/cape-bone-iio-00A0.dts
++++ b/firmware/capes/cape-bone-iio-00A0.dts
+@@ -14,6 +14,19 @@
+ /* identification */
+ part-number = "iio-test";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.39", /* AIN0 */
++ "P9.40", /* AIN1 */
++ "P9.37", /* AIN2 */
++ "P9.38", /* AIN3 */
++ "P9.33", /* AIN4 */
++ "P9.36", /* AIN5 */
++ "P9.35", /* AIN6 */
++ /* the hardware IP uses */
++ "tscadc";
++
+ fragment@0 {
+ target = <&ocp>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-mrf24j40-00A0.dts b/firmware/capes/cape-bone-mrf24j40-00A0.dts
+index 0fc2aea..7e7b6b8 100644
+--- a/firmware/capes/cape-bone-mrf24j40-00A0.dts
++++ b/firmware/capes/cape-bone-mrf24j40-00A0.dts
+@@ -16,6 +16,22 @@
+ part-number = "BB-BONE-MRF24J40";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.11", /* gpio1_13 */
++ "P8.16", /* gpio1_14 */
++ "P8.26", /* gpio1_29 */
++ "P9.31", /* spi1_sclk */
++ "P9.29", /* spi1_d0 */
++ "P9.30", /* spi1_d1 */
++ "P9.28", /* spi1_cs0 */
++ /* the hardware IP uses */
++ "gpio1_13",
++ "gpio1_14",
++ "gpio1_29",
++ "spi1";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-nixie-00A0.dts b/firmware/capes/cape-bone-nixie-00A0.dts
+index 7ec2c46..e4ff3ab 100644
+--- a/firmware/capes/cape-bone-nixie-00A0.dts
++++ b/firmware/capes/cape-bone-nixie-00A0.dts
+@@ -15,6 +15,20 @@
+ part-number = "BB-BONE-NIXIE";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.25", /* gpio3_21 */
++ "P8.45", /* ehrpwm2A */
++ "P8.46", /* ehrpwm2B */
++ "P9.31", /* pr1_pru0_pru_r30_0 */
++ "P9.29", /* pr1_pru0_pru_r30_1 */
++ "P9.27", /* pr1_pru0_pru_r30_5 */
++ /* the hardware IP uses */
++ "gpio3_21",
++ "ehrpwm2A", "ehrpwm2B",
++ "pru";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+@@ -28,7 +42,7 @@
+ bone_nixie_cape_pins: pinmux_bone_nixie_cape_pins {
+ pinctrl-single,pins = <
+ 0x0a0 0x03 /* lcd_data0.gpio2_6 | MODE3 */
+- 0x0a4 0x03 /* lcd_data1.gpio2_7 | MODE3 */
++ 0x0a4 0x03 /* lcd_data1.gpio2_7 | MODE3 */
+ >;
+ };
+
+@@ -39,7 +53,7 @@
+ 0x1a4 0x05 /* mcasp0_fsr.pr1_pru1_pru_r30_5, MODE5 | CLK */
+ >;
+ };
+- };
++ };
+ };
+
+ fragment@2 {
+diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
+index b5b1be8..df04f6d 100644
+--- a/firmware/capes/cape-bone-tester-00A0.dts
++++ b/firmware/capes/cape-bone-tester-00A0.dts
+@@ -15,6 +15,8 @@
+ part-number = "BB-BONE-TESTER";
+ version = "00A0";
+
++ /* NOTE: we don't use resources for the tester - it's not a normal cape */
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/cape-bone-weather-00A0.dts b/firmware/capes/cape-bone-weather-00A0.dts
+index 7cb479a..c017cdb 100644
+--- a/firmware/capes/cape-bone-weather-00A0.dts
++++ b/firmware/capes/cape-bone-weather-00A0.dts
+@@ -14,6 +14,13 @@
+ part-number = "BB-BONE-WTHR-01";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.6", /* gpio1_3 */
++ /* the hardware IP uses */
++ "gpio1_3";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
diff --git a/patches/linux-3.8.13/0620-capes-Update-RS232-CAN-capes-with-resources.patch b/patches/linux-3.8.13/0620-capes-Update-RS232-CAN-capes-with-resources.patch
new file mode 100644
index 0000000..d04a4aa
--- /dev/null
+++ b/patches/linux-3.8.13/0620-capes-Update-RS232-CAN-capes-with-resources.patch
@@ -0,0 +1,47 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 20 May 2013 16:11:38 +0300
+Subject: [PATCH] capes: Update RS232 + CAN capes with resources
+
+---
+ firmware/capes/BB-BONE-RS232-00A0.dts | 8 ++++++++
+ firmware/capes/BB-BONE-SERL-01-00A1.dts | 8 ++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/firmware/capes/BB-BONE-RS232-00A0.dts b/firmware/capes/BB-BONE-RS232-00A0.dts
+index 220c85d..ad627c5 100644
+--- a/firmware/capes/BB-BONE-RS232-00A0.dts
++++ b/firmware/capes/BB-BONE-RS232-00A0.dts
+@@ -15,6 +15,14 @@
+ part-number = "BB-BONE-RS232";
+ version = "00A0";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.22", /* rs232: uart2_rxd */
++ "P9.21", /* rs232: uart2_txd */
++ /* the hardware IP uses */
++ "uart2";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
+diff --git a/firmware/capes/BB-BONE-SERL-01-00A1.dts b/firmware/capes/BB-BONE-SERL-01-00A1.dts
+index b0459c8..93b1bfc 100644
+--- a/firmware/capes/BB-BONE-SERL-01-00A1.dts
++++ b/firmware/capes/BB-BONE-SERL-01-00A1.dts
+@@ -14,6 +14,14 @@
+ part-number = "BB-BONE-SERL-01";
+ version = "00A1";
+
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.26", /* dcan1: dcan1_tx */
++ "P9.24", /* dcan1: dcan1_rx */
++ /* the hardware IP uses */
++ "dcan1";
++
+ fragment@0 {
+ target = <&am33xx_pinmux>;
+ __overlay__ {
diff --git a/patches/linux-3.8.13/0621-capemgr-Add-enable_partno-parameter.patch b/patches/linux-3.8.13/0621-capemgr-Add-enable_partno-parameter.patch
new file mode 100644
index 0000000..6415566
--- /dev/null
+++ b/patches/linux-3.8.13/0621-capemgr-Add-enable_partno-parameter.patch
@@ -0,0 +1,114 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 4 Jun 2013 19:42:45 +0300
+Subject: [PATCH] capemgr: Add enable_partno parameter
+
+Add analogous option to disable_partno; this one doesn't require the presence of
+a base dts override.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/misc/cape/beaglebone/capemgr.c | 66 ++++++++++++++++++++++++++++++++
+ 1 file changed, 66 insertions(+)
+
+diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
+index 2820e39..b1a8b65c 100644
+--- a/drivers/misc/cape/beaglebone/capemgr.c
++++ b/drivers/misc/cape/beaglebone/capemgr.c
+@@ -57,6 +57,13 @@ module_param(disable_partno, charp, 0444);
+ MODULE_PARM_DESC(disable_partno,
+ "Comma delimited list of PART-NUMBER[:REV] of disabled capes");
+
++/* enable capes */
++static char *enable_partno = NULL;
++module_param(enable_partno, charp, 0444);
++MODULE_PARM_DESC(enable_partno,
++ "Comma delimited list of PART-NUMBER[:REV] of enabled capes");
++
++
+ struct bone_capemgr_info;
+
+ struct slot_ee_attribute {
+@@ -1812,10 +1819,12 @@ bone_capemgr_probe(struct platform_device *pdev)
+ struct device_node *slots_node, *capemaps_node, *node;
+ struct device_node *eeprom_node;
+ const char *part_number;
++ const char *version;
+ const char *board_name;
+ const char *compatible_name;
+ struct bone_capemap *capemap;
+ int ret, len;
++ char *wbuf, *s, *p, *e;
+
+ /* we don't use platform_data at all; we require OF */
+ if (pnode == NULL)
+@@ -1996,6 +2005,62 @@ bone_capemgr_probe(struct platform_device *pdev)
+ }
+ slots_node = NULL;
+
++ /* iterate over enable_partno (if there) */
++ if (enable_partno && strlen(enable_partno) > 0) {
++
++ /* allocate a temporary buffer */
++ wbuf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
++ if (wbuf == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate temporary buffer\n");
++ ret = -ENOMEM;
++ goto err_exit;
++ }
++
++ /* add any enable_partno capes */
++ s = enable_partno;
++ while (*s) {
++ /* form is PART[:REV],PART.. */
++ p = strchr(s, ',');
++ if (p == NULL)
++ e = s + strlen(s);
++ else
++ e = p;
++
++ /* copy to temp buffer */
++ len = e - s;
++ if (len >= PAGE_SIZE - 1)
++ len = PAGE_SIZE - 1;
++ memcpy(wbuf, s, len);
++ wbuf[len] = '\0';
++
++ /* move to the next */
++ s = *e ? e + 1 : e;
++
++ /* now split the rev part */
++ p = strchr(wbuf, ':');
++ if (p != NULL)
++ *p++ = '\0';
++
++ part_number = wbuf;
++ version = p;
++
++ dev_info(&pdev->dev, "enabled_partno part_number '%s', version '%s'\n",
++ part_number, version ? version : "N/A");
++
++ /* only immediate slots are allowed here */
++ slot = bone_capemgr_add_slot(info, NULL,
++ part_number, version);
++
++ /* we continue even in case of an error */
++ if (IS_ERR_OR_NULL(slot)) {
++ dev_warn(&pdev->dev, "Failed to add slot #%d\n",
++ atomic_read(&info->next_slot_nr) - 1);
++ }
++ }
++
++ devm_kfree(&pdev->dev, wbuf);
++ }
++
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (IS_ERR_VALUE(ret)) {
+@@ -2009,6 +2074,7 @@ bone_capemgr_probe(struct platform_device *pdev)
+
+ /* now load each (take lock to be sure */
+ mutex_lock(&info->slots_list_mutex);
++
+ list_for_each_entry(slot, &info->slot_list, node) {
+
+ /* if matches the disabled ones skip */
diff --git a/patches/linux-3.8.13/0622-cape-GPIOHELP-use-correct-part-number.patch b/patches/linux-3.8.13/0622-cape-GPIOHELP-use-correct-part-number.patch
new file mode 100644
index 0000000..123e82e
--- /dev/null
+++ b/patches/linux-3.8.13/0622-cape-GPIOHELP-use-correct-part-number.patch
@@ -0,0 +1,21 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 5 Jun 2013 10:34:32 +0300
+Subject: [PATCH] cape: GPIOHELP use correct part number
+
+---
+ firmware/capes/BB-GPIOHELP-00A0.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/firmware/capes/BB-GPIOHELP-00A0.dts b/firmware/capes/BB-GPIOHELP-00A0.dts
+index d7e0b4b..ba2a74b 100644
+--- a/firmware/capes/BB-GPIOHELP-00A0.dts
++++ b/firmware/capes/BB-GPIOHELP-00A0.dts
+@@ -12,7 +12,7 @@
+ compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+ /* identification */
+- part-number = "BB-BONE-PRU-01";
++ part-number = "BB-GPIOHELP";
+ version = "00A0";
+
+ /* state the resources this cape uses */
diff --git a/patches/linux-3.8.13/0623-bbb-Add-a-fall-back-non-audio-HDMI-cape.patch b/patches/linux-3.8.13/0623-bbb-Add-a-fall-back-non-audio-HDMI-cape.patch
new file mode 100644
index 0000000..4e3e870
--- /dev/null
+++ b/patches/linux-3.8.13/0623-bbb-Add-a-fall-back-non-audio-HDMI-cape.patch
@@ -0,0 +1,186 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 4 Jun 2013 17:54:45 +0300
+Subject: [PATCH] bbb: Add a fall-back non-audio HDMI cape
+
+When a user cape hogs the audio, allow booting with a HDMI cape which
+only supports video.
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 21 +++++
+ firmware/Makefile | 5 +-
+ firmware/capes/cape-boneblack-hdmin-00A0.dts | 112 ++++++++++++++++++++++++++
+ 3 files changed, 136 insertions(+), 2 deletions(-)
+ create mode 100644 firmware/capes/cape-boneblack-hdmin-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index ae407c3..aa95810 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -219,6 +219,17 @@
+ part-number = "BB-BONELT-HDMI";
+ };
+
++ /* Beaglebone black has it soldered on (but no audio) */
++ slot@102 {
++ ti,cape-override;
++ priority = <2>;
++ compatible = "ti,beaglebone-black";
++ board-name = "Bone-Black-HDMIN";
++ version = "00A0";
++ manufacturer = "Texas Instruments";
++ part-number = "BB-BONELT-HDMIN";
++ };
++
+ };
+
+ /* mapping between board names and dtb objects */
+@@ -349,6 +360,16 @@
+ dtbo = "BB-BONE-RS232-00A0.dtbo";
+ };
+ };
++
++ /* beaglebone black hdmi on board (No audio) */
++ cape@13 {
++ part-number = "BB-BONELT-HDMIN";
++ version@00A0 {
++ version = "00A0";
++ dtbo = "cape-boneblack-hdmin-00A0.dtbo";
++ };
++ };
++
+ };
+ };
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 646eea5..182de29 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -200,8 +200,9 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += \
+ # the weather cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-weather-00A0.dtbo
+
+-# the HDMI virtual cape on the beaglebone-black
+-fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-boneblack-hdmi-00A0.dtbo
++# the HDMI virtual capes on the beaglebone-black
++fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ cape-boneblack-hdmi-00A0.dtbo cape-boneblack-hdmin-00A0.dtbo
+
+ # the Tester cape (tester-side)
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-tester-00A0.dtbo
+diff --git a/firmware/capes/cape-boneblack-hdmin-00A0.dts b/firmware/capes/cape-boneblack-hdmin-00A0.dts
+new file mode 100644
+index 0000000..44ae0ea
+--- /dev/null
++++ b/firmware/capes/cape-boneblack-hdmin-00A0.dts
+@@ -0,0 +1,112 @@
++/*
++* 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone-black";
++ part-number = "BB-BONELT-HDMIN"; /* No audio */
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.45", /* lcd: lcd_data0 */
++ "P8.46", /* lcd: lcd_data1 */
++ "P8.43", /* lcd: lcd_data2 */
++ "P8.44", /* lcd: lcd_data3 */
++ "P8.41", /* lcd: lcd_data4 */
++ "P8.42", /* lcd: lcd_data5 */
++ "P8.39", /* lcd: lcd_data6 */
++ "P8.40", /* lcd: lcd_data7 */
++ "P8.37", /* lcd: lcd_data8 */
++ "P8.38", /* lcd: lcd_data9 */
++ "P8.36", /* lcd: lcd_data10 */
++ "P8.34", /* lcd: lcd_data11 */
++ "P8.35", /* lcd: lcd_data12 */
++ "P8.33", /* lcd: lcd_data13 */
++ "P8.31", /* lcd: lcd_data14 */
++ "P8.32", /* lcd: lcd_data15 */
++ "P8.27", /* lcd: lcd_vsync */
++ "P8.29", /* lcd: lcd_hsync */
++ "P8.28", /* lcd: lcd_pclk */
++ "P8.30", /* lcd: lcd_ac_bias_en */
++ /* the hardware IP uses */
++ "gpio1_27",
++ "lcd";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
++ pinctrl-single,pins = <
++ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
++ 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 */
++ >;
++ };
++ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
++ pinctrl-single,pins = <
++ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++ };
++ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ nxptda: nxptda@0 {
++ compatible = "nxp,nxptda";
++ status = "okay";
++ };
++
++ hdmi {
++ compatible = "tilcdc,slave";
++ i2c = <&i2c0>;
++ pinctrl-names = "default", "off";
++ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
++ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
++ };
++
++ fb {
++ compatible = "ti,am33xx-tilcdc";
++ reg = <0x4830e000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <36>;
++ ti,hwmods = "lcdc";
++ ti,allow-non-reduced-blanking-modes;
++ ti,allow-non-audio-modes;
++ };
++
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0624-capes-HDMI-slaves-need-panel-settings.patch b/patches/linux-3.8.13/0624-capes-HDMI-slaves-need-panel-settings.patch
new file mode 100644
index 0000000..8d763f1
--- /dev/null
+++ b/patches/linux-3.8.13/0624-capes-HDMI-slaves-need-panel-settings.patch
@@ -0,0 +1,57 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 6 Jun 2013 11:47:15 +0300
+Subject: [PATCH] capes: HDMI slaves need panel settings
+
+---
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 13 +++++++++++++
+ firmware/capes/cape-boneblack-hdmin-00A0.dts | 13 +++++++++++++
+ 2 files changed, 26 insertions(+)
+
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index 5fdbd9e..a312bc1 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -110,6 +110,19 @@
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
++
++ panel-info {
++ bpp = <16>;
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ fdd = <16>;
++ sync-edge = <1>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ invert-pxl-clk;
++ };
+ };
+
+ fb {
+diff --git a/firmware/capes/cape-boneblack-hdmin-00A0.dts b/firmware/capes/cape-boneblack-hdmin-00A0.dts
+index 44ae0ea..e193426 100644
+--- a/firmware/capes/cape-boneblack-hdmin-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmin-00A0.dts
+@@ -95,6 +95,19 @@
+ pinctrl-names = "default", "off";
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
++
++ panel-info {
++ bpp = <16>;
++ ac-bias = <255>;
++ ac-bias-intrpt = <0>;
++ dma-burst-sz = <16>;
++ fdd = <16>;
++ sync-edge = <1>;
++ sync-ctrl = <1>;
++ raster-order = <0>;
++ fifo-th = <0>;
++ invert-pxl-clk;
++ };
+ };
+
+ fb {
diff --git a/patches/linux-3.8.13/0625-capes-boneblack-HDMI-capes-have-blacklisted-modes.patch b/patches/linux-3.8.13/0625-capes-boneblack-HDMI-capes-have-blacklisted-modes.patch
new file mode 100644
index 0000000..3ef3b6f
--- /dev/null
+++ b/patches/linux-3.8.13/0625-capes-boneblack-HDMI-capes-have-blacklisted-modes.patch
@@ -0,0 +1,65 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 12 Jun 2013 11:12:26 +0300
+Subject: [PATCH] capes: boneblack HDMI capes have blacklisted modes.
+
+Added a few modes that are known not to work on my end.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ firmware/capes/cape-boneblack-hdmi-00A0.dts | 13 ++++++++++++-
+ firmware/capes/cape-boneblack-hdmin-00A0.dts | 11 +++++++++++
+ 2 files changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+index a312bc1..04b7b54 100644
+--- a/firmware/capes/cape-boneblack-hdmi-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
+@@ -83,7 +83,7 @@
+ pinctrl-single,pins = <
+ 0x1ac 0x30 /* mcasp0_ahclkx, MODE0 | INPUT */
+ 0x19c 0x02 /* mcasp0_ahclkr, */
+- 0x194 0x10 /* mcasp0_fsx, MODE0 | OUTPUT */
++ 0x194 0x10 /* mcasp0_fsx, MODE0 | OUTPUT */
+ 0x190 0x00 /* mcasp0_aclkr.mcasp0_aclkx, MODE0 | OUTPUT_PULLDOWN */
+ 0x1a8 0x1f /* mcasp0_axr1 GPIO1_27 | OUTPUT | PULLUP */
+ >;
+@@ -111,6 +111,17 @@
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
++ modes-blacklisted =
++ "1920x1080@25",
++ "832x624@75";
++
++ // Enable this when we figure out the modes
++ //
++ // modes-whitelisted =
++ // "1920x1080@24",
++ // "1280x720@50", "1280x720@60",
++ // "720x576@50","720x480@60";
++
+ panel-info {
+ bpp = <16>;
+ ac-bias = <255>;
+diff --git a/firmware/capes/cape-boneblack-hdmin-00A0.dts b/firmware/capes/cape-boneblack-hdmin-00A0.dts
+index e193426..ad55c4d 100644
+--- a/firmware/capes/cape-boneblack-hdmin-00A0.dts
++++ b/firmware/capes/cape-boneblack-hdmin-00A0.dts
+@@ -96,6 +96,17 @@
+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
++ modes-blacklisted =
++ "1920x1080@25",
++ "832x624@75";
++
++ // Enable this when we figure out the modes
++ //
++ // modes-whitelisted =
++ // "1920x1080@24",
++ // "1280x720@50", "1280x720@60",
++ // "720x576@50","720x480@60";
++
+ panel-info {
+ bpp = <16>;
+ ac-bias = <255>;
diff --git a/patches/linux-3.8.13/0626-capes-LCD7-Fix-definitions.patch b/patches/linux-3.8.13/0626-capes-LCD7-Fix-definitions.patch
new file mode 100644
index 0000000..68e0063
--- /dev/null
+++ b/patches/linux-3.8.13/0626-capes-LCD7-Fix-definitions.patch
@@ -0,0 +1,106 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 12 Jun 2013 21:02:20 +0300
+Subject: [PATCH] capes: LCD7: Fix definitions
+
+LCD7 rev A3/A4 had some pins wrong
+---
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 8 ++++----
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 11 ++++++-----
+ 2 files changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index f5fab09..76a187d 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -38,7 +38,7 @@
+ "P8.29", /* lcd: lcd_hsync */
+ "P8.28", /* lcd: lcd_pclk */
+ "P8.30", /* lcd: lcd_ac_bias_en */
+- "P8.20", /* lcd: gpio1_31 */
++ "P9.22", /* lcd: gpio0_2 */
+ "P9.12", /* led: gpio1_28 */
+ "P9.14", /* pwm: ehrpwm1a */
+ "P9.15", /* keys: gpio1_16 */
+@@ -47,7 +47,7 @@
+ "P9.30", /* keys: gpio3_16 */
+ "P9.21", /* keys: gpio0_3 */
+ /* the hardware IP uses */
+- "gpio1_31",
++ "gpio0_2",
+ "gpio1_28",
+ "gpio1_16",
+ "gpio1_17",
+@@ -75,7 +75,7 @@
+
+ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+ pinctrl-single,pins = <
+- 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 0x150 0x07 /* spi0_sclk.gpio0_2, OUTPUT | MODE7 - AVDD_EN */
+ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+ 0xa3 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 */
+@@ -275,7 +275,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio2 31 0x0>;
++ ti,power-gpio = <&gpio1 2 0x0>;
+ ti,allow-non-reduced-blanking-modes;
+ };
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+index 81553e6..0c3abff 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A4.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -38,7 +38,7 @@
+ "P8.29", /* lcd: lcd_hsync */
+ "P8.28", /* lcd: lcd_pclk */
+ "P8.30", /* lcd: lcd_ac_bias_en */
+- "P8.20", /* lcd: gpio1_31 */
++ "P9.22", /* lcd: gpio0_2 */
+ "P9.12", /* led: gpio1_28 */
+ "P9.14", /* pwm: ehrpwm1a */
+ "P9.15", /* keys: gpio1_16 */
+@@ -46,13 +46,15 @@
+ "P9.16", /* keys: gpio1_19 */
+ "P9.30", /* keys: gpio3_16 */
+ "P9.21", /* keys: gpio0_3 */
++ "P9.27", /* captouch: gpio3_19 */
+ /* the hardware IP uses */
+- "gpio1_31",
++ "gpio0_2",
+ "gpio1_28",
+ "gpio1_16",
+ "gpio1_17",
+ "gpio1_19",
+ "gpio3_16",
++ "gpio3_19",
+ "gpio0_3",
+ "lcd",
+ "ehrpwm1a";
+@@ -75,7 +77,7 @@
+
+ bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+ pinctrl-single,pins = <
+- 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
++ 0x150 0x07 /* spi0_sclk.gpio0_2, OUTPUT | MODE7 - AVDD_EN */
+ 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 */
+@@ -255,7 +257,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+- ti,power-gpio = <&gpio2 31 0x0>;
++ ti,power-gpio = <&gpio1 2 0x0>;
+ ti,allow-non-reduced-blanking-modes;
+ };
+
+@@ -277,7 +279,6 @@
+ interrupts = <19 0x0>;
+ atmel,irq-gpio = <&gpio4 19 0>;
+ };
+-
+ };
+ };
+ };
diff --git a/patches/linux-3.8.13/0627-capes-LCD7-Fix-enter-key-pinmux.patch b/patches/linux-3.8.13/0627-capes-LCD7-Fix-enter-key-pinmux.patch
new file mode 100644
index 0000000..018df89
--- /dev/null
+++ b/patches/linux-3.8.13/0627-capes-LCD7-Fix-enter-key-pinmux.patch
@@ -0,0 +1,37 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 12 Jun 2013 22:49:19 +0300
+Subject: [PATCH] capes: LCD7: Fix enter key pinmux
+
+---
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 2 +-
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 4 +++-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index 76a187d..8b9cf14 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -105,7 +105,7 @@
+ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+ 0x198 0x2f /* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
+- 0x070 0x2f /* KEY_ENTER gpmc_wait0.gpio0_3, INPUT | PULLDIS | MODE7 */
++ 0x154 0x2f /* KEY_ENTER spi0_d0.gpio0_3, INPUT | PULLDIS | MODE7 */
+ >;
+ };
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+index 0c3abff..a23a809 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A4.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -107,7 +107,9 @@
+ 0x044 0x2f /* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+ 0x04c 0x2f /* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+ 0x198 0x2f /* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
+- 0x070 0x2f /* KEY_ENTER gpmc_wait0.gpio0_3, INPUT | PULLDIS | MODE7 */
++ 0x154 0x2f /* KEY_ENTER spi0_d0.gpio0_3, INPUT | PULLDIS | MODE7 */
++
++ /* the next one should be in the tsc driver */
+ 0x1a4 0x2f /* TSC_INTn mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+ >;
+ };
diff --git a/patches/linux-3.8.13/0628-Fix-timings-for-LCD3-cape.patch b/patches/linux-3.8.13/0628-Fix-timings-for-LCD3-cape.patch
new file mode 100644
index 0000000..d79b898
--- /dev/null
+++ b/patches/linux-3.8.13/0628-Fix-timings-for-LCD3-cape.patch
@@ -0,0 +1,41 @@
+From: David Anders <danders@circuitco.com>
+Date: Thu, 13 Jun 2013 08:37:19 +0200
+Subject: [PATCH] Fix timings for LCD3 cape
+
+In the 3.2 kernel using the da8xx lcdc fb, the HSW, HFP, and HBP are written to the lcdc registers directly as entered. i.e. if HSW=47 , then 47 is written to the register and the value that is generated is the register value plus one (total of 48 clocks).
+
+with the 3.8 kernel using the DRM driver, the code subtracts one from the set value before writing it to the register, i.e. if HSW=47, then 46 is written to the register and the value that is generated is the register value plus one (total of 47 clocks).
+
+specifically with the LCD3 board, the lcd panel does not use data enable as a timing signal. it specifically counts the number of vertical clocks and horizontal clocks to determine data start points. the lcd panel expects for the sum of the HSW and HBP to be 70 pixel clocks. currently it is 68. this is the root cause of the color shift and poor image quality....
+
+the HSW, HFP, and HBP for all three lcd panels needs to be incremented by one.
+---
+ firmware/capes/cape-bone-lcd3-00A2.dts | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index c2cdedc..85085b9 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -245,16 +245,17 @@
+ sync-ctrl = <1>;
+ raster-order = <0>;
+ fifo-th = <0>;
++ invert-pxl-clk;
+ };
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 320x240 {
+ hactive = <320>;
+ vactive = <240>;
+- hback-porch = <21>;
+- hfront-porch = <58>;
+- hsync-len = <47>;
+- vback-porch = <11>;
++ hback-porch = <22>;
++ hfront-porch = <59>;
++ hsync-len = <48>;
++ vback-porch = <12>;
+ vfront-porch = <23>;
+ vsync-len = <2>;
+ clock-frequency = <8000000>;
diff --git a/patches/linux-3.8.13/0629-capes-LCD-capes-updated-with-timing-fixes.patch b/patches/linux-3.8.13/0629-capes-LCD-capes-updated-with-timing-fixes.patch
new file mode 100644
index 0000000..d3dd022
--- /dev/null
+++ b/patches/linux-3.8.13/0629-capes-LCD-capes-updated-with-timing-fixes.patch
@@ -0,0 +1,183 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 13 Jun 2013 12:24:42 +0300
+Subject: [PATCH] capes: LCD capes updated with timing fixes
+
+---
+ firmware/capes/BB-BONE-LCD4-01-00A0.dts | 8 ++++----
+ firmware/capes/BB-BONE-LCD4-01-00A1.dts | 8 ++++----
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 8 ++++----
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 8 ++++----
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 9 +++++----
+ firmware/capes/cape-bone-lcd3-00A0.dts | 13 ++++++++-----
+ firmware/capes/cape-bone-lcd3-00A2.dts | 5 ++++-
+ 7 files changed, 33 insertions(+), 26 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A0.dts b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+index 4b6f3cc..3bef8b6 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A0.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+@@ -166,10 +166,10 @@
+ timing0: 480x272 {
+ hactive = <480>;
+ vactive = <272>;
+- hback-porch = <43>;
+- hfront-porch = <8>;
+- hsync-len = <4>;
+- vback-porch = <12>;
++ hback-porch = <44>;
++ hfront-porch = <9>;
++ hsync-len = <5>;
++ vback-porch = <13>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ clock-frequency = <9000000>;
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A1.dts b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+index b424c09..4d9fceb 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A1.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+@@ -253,10 +253,10 @@
+ timing0: 480x272 {
+ hactive = <480>;
+ vactive = <272>;
+- hback-porch = <43>;
+- hfront-porch = <8>;
+- hsync-len = <4>;
+- vback-porch = <12>;
++ hback-porch = <44>;
++ hfront-porch = <9>;
++ hsync-len = <5>;
++ vback-porch = <13>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ clock-frequency = <9000000>;
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index 77ef5ec..3b834ab 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -254,10 +254,10 @@
+ timing0: 800x480 {
+ hactive = <800>;
+ vactive = <480>;
+- hback-porch = <39>;
+- hfront-porch = <39>;
+- hsync-len = <47>;
+- vback-porch = <29>;
++ hback-porch = <40>;
++ hfront-porch = <40>;
++ hsync-len = <48>;
++ vback-porch = <30>;
+ vfront-porch = <13>;
+ vsync-len = <2>;
+ clock-frequency = <30000000>;
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index 8b9cf14..043ed2b 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -256,10 +256,10 @@
+ timing0: 800x480 {
+ hactive = <800>;
+ vactive = <480>;
+- hback-porch = <39>;
+- hfront-porch = <39>;
+- hsync-len = <47>;
+- vback-porch = <29>;
++ hback-porch = <40>;
++ hfront-porch = <40>;
++ hsync-len = <48>;
++ vback-porch = <30>;
+ vfront-porch = <13>;
+ vsync-len = <2>;
+ clock-frequency = <30000000>;
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+index a23a809..ae4941e 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A4.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -234,16 +234,17 @@
+ sync-ctrl = <1>;
+ raster-order = <0>;
+ fifo-th = <0>;
++ invert-pxl-clk;
+ };
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 800x480 {
+ hactive = <800>;
+ vactive = <480>;
+- hback-porch = <39>;
+- hfront-porch = <39>;
+- hsync-len = <47>;
+- vback-porch = <29>;
++ hback-porch = <40>;
++ hfront-porch = <40>;
++ hsync-len = <48>;
++ vback-porch = <30>;
+ vfront-porch = <13>;
+ vsync-len = <2>;
+ clock-frequency = <30000000>;
+diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
+index a2f8b35..8628219 100644
+--- a/firmware/capes/cape-bone-lcd3-00A0.dts
++++ b/firmware/capes/cape-bone-lcd3-00A0.dts
+@@ -88,7 +88,8 @@
+ 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 */
++ // 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x07 /* lcd_ac_bias_en.gpio2_25 OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT */
+ >;
+ };
+
+@@ -236,16 +237,17 @@
+ sync-ctrl = <1>;
+ raster-order = <0>;
+ fifo-th = <0>;
++ invert-pxl-clk;
+ };
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 320x240 {
+ hactive = <320>;
+ vactive = <240>;
+- hback-porch = <21>;
+- hfront-porch = <58>;
+- hsync-len = <47>;
+- vback-porch = <11>;
++ hback-porch = <22>;
++ hfront-porch = <59>;
++ hsync-len = <48>;
++ vback-porch = <12>;
+ vfront-porch = <23>;
+ vsync-len = <2>;
+ clock-frequency = <8000000>;
+@@ -261,6 +263,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio3 25 0>;
+ };
+
+ };
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index 85085b9..ceee1f5 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -91,7 +91,9 @@
+ 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 */
++ // 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x07 /* lcd_ac_bias_en.gpio2_25 OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT */
++
+ >;
+ };
+
+@@ -271,6 +273,7 @@
+ interrupt-parent = <&intc>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
++ ti,power-gpio = <&gpio3 25 0>;
+ };
+
+ };
diff --git a/patches/linux-3.8.13/0630-Fix-mmc2-being-enabled-when-eMMC-is-disabled.patch b/patches/linux-3.8.13/0630-Fix-mmc2-being-enabled-when-eMMC-is-disabled.patch
new file mode 100644
index 0000000..2ac70ce
--- /dev/null
+++ b/patches/linux-3.8.13/0630-Fix-mmc2-being-enabled-when-eMMC-is-disabled.patch
@@ -0,0 +1,22 @@
+From: Bas Laarhoven <sjml@xs4all.nl>
+Date: Mon, 10 Jun 2013 13:53:35 +0200
+Subject: [PATCH] Fix mmc2 being enabled when eMMC is disabled.
+
+Signed-off-by: Bas Laarhoven <sjml@xs4all.nl>
+---
+ arch/arm/boot/dts/am335x-boneblack.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
+index 1545cca..a7eb55b 100644
+--- a/arch/arm/boot/dts/am335x-boneblack.dts
++++ b/arch/arm/boot/dts/am335x-boneblack.dts
+@@ -46,7 +46,7 @@
+ vmmc-supply = <&vmmcsd_fixed>;
+ bus-width = <8>;
+ ti,non-removable;
+- status = "okay";
++ status = "disabled";
+
+ reset = <&rstctl 0 0>;
+ reset-names = "eMMC_RSTn-CONSUMER";
diff --git a/patches/linux-3.8.13/0631-capes-LCD7-fix-vsync-len-off-by-one.patch b/patches/linux-3.8.13/0631-capes-LCD7-fix-vsync-len-off-by-one.patch
new file mode 100644
index 0000000..6ddab82
--- /dev/null
+++ b/patches/linux-3.8.13/0631-capes-LCD7-fix-vsync-len-off-by-one.patch
@@ -0,0 +1,49 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 13 Jun 2013 18:43:27 +0300
+Subject: [PATCH] capes: LCD7: fix vsync-len off by one
+
+---
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 2 +-
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 2 +-
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index 3b834ab..688e7a1 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -259,7 +259,7 @@
+ hsync-len = <48>;
+ vback-porch = <30>;
+ vfront-porch = <13>;
+- vsync-len = <2>;
++ vsync-len = <3>;
+ clock-frequency = <30000000>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index 043ed2b..43a4a22 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -261,7 +261,7 @@
+ hsync-len = <48>;
+ vback-porch = <30>;
+ vfront-porch = <13>;
+- vsync-len = <2>;
++ vsync-len = <3>;
+ clock-frequency = <30000000>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+index ae4941e..2d0ed3f 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A4.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -246,7 +246,7 @@
+ hsync-len = <48>;
+ vback-porch = <30>;
+ vfront-porch = <13>;
+- vsync-len = <2>;
++ vsync-len = <3>;
+ clock-frequency = <30000000>;
+ hsync-active = <0>;
+ vsync-active = <0>;
diff --git a/patches/linux-3.8.13/0632-LCD-capes-set-default-brightness-to-100.patch b/patches/linux-3.8.13/0632-LCD-capes-set-default-brightness-to-100.patch
new file mode 100644
index 0000000..98875b7
--- /dev/null
+++ b/patches/linux-3.8.13/0632-LCD-capes-set-default-brightness-to-100.patch
@@ -0,0 +1,106 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 20 Jun 2013 10:54:55 -0400
+Subject: [PATCH] LCD capes: set default brightness to 100%
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/BB-BONE-LCD4-01-00A1.dts | 2 +-
+ firmware/capes/BB-BONE-LCD7-01-00A2.dts | 2 +-
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 2 +-
+ firmware/capes/BB-BONE-LCD7-01-00A4.dts | 2 +-
+ firmware/capes/cape-bone-adafruit-lcd-00A0.dts | 2 +-
+ firmware/capes/cape-bone-hexy-00A0.dts | 2 +-
+ firmware/capes/cape-bone-lcd3-00A2.dts | 2 +-
+ 7 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A1.dts b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+index 4d9fceb..633a509 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A1.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+@@ -140,7 +140,7 @@
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "LCD4";
+ 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 */
++ default-brightness-level = <101>; /* index to the array above */
+ status = "okay";
+ };
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+index 688e7a1..03645ad 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A2.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
+@@ -142,7 +142,7 @@
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "LCD7";
+ 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 */
++ default-brightness-level = <101>; /* index to the array above */
+ };
+
+ tscadc {
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index 43a4a22..b90e7c2 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -144,7 +144,7 @@
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "LCD7";
+ 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 */
++ default-brightness-level = <101>; /* index to the array above */
+ };
+
+ tscadc {
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+index 2d0ed3f..3455596 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A4.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
+@@ -149,7 +149,7 @@
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "LCD7";
+ 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 */
++ default-brightness-level = <101>; /* index to the array above */
+ };
+
+ gpio-leds-cape-lcd7 {
+diff --git a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+index 8c0343b..8422bb5 100644
+--- a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
++++ b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
+@@ -134,7 +134,7 @@
+
+ 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 */
++ default-brightness-level = <101>; /* index to the array above */
+ };
+ };
+ };
+diff --git a/firmware/capes/cape-bone-hexy-00A0.dts b/firmware/capes/cape-bone-hexy-00A0.dts
+index f02abd7..358f5e1 100644
+--- a/firmware/capes/cape-bone-hexy-00A0.dts
++++ b/firmware/capes/cape-bone-hexy-00A0.dts
+@@ -119,7 +119,7 @@
+
+ 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 */
++ default-brightness-level = <101>; /* index to the array above */
+ };
+ };
+ };
+diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
+index ceee1f5..f285196 100644
+--- a/firmware/capes/cape-bone-lcd3-00A2.dts
++++ b/firmware/capes/cape-bone-lcd3-00A2.dts
+@@ -140,7 +140,7 @@
+ pwms = <&ehrpwm1 0 500000 0>;
+ pwm-names = "LCD3";
+ 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 */
++ default-brightness-level = <101>; /* index to the array above */
+ status = "okay";
+ };
+
diff --git a/patches/linux-3.8.13/0633-lcd-capes-update-adc-channels.patch b/patches/linux-3.8.13/0633-lcd-capes-update-adc-channels.patch
new file mode 100644
index 0000000..9e09798
--- /dev/null
+++ b/patches/linux-3.8.13/0633-lcd-capes-update-adc-channels.patch
@@ -0,0 +1,50 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 8 Jul 2013 12:56:56 +0200
+Subject: [PATCH] lcd capes: update adc channels
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/capes/BB-BONE-LCD4-01-00A0.dts | 2 +-
+ firmware/capes/BB-BONE-LCD4-01-00A1.dts | 2 +-
+ firmware/capes/BB-BONE-LCD7-01-00A3.dts | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A0.dts b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+index 3bef8b6..f355b06 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A0.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
+@@ -124,7 +124,7 @@
+ };
+
+ adc {
+- ti,adc-channels = <4>;
++ ti,adc-channels = <4 5 6 7>;
+ };
+ };
+
+diff --git a/firmware/capes/BB-BONE-LCD4-01-00A1.dts b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+index 633a509..19f52fc 100644
+--- a/firmware/capes/BB-BONE-LCD4-01-00A1.dts
++++ b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
+@@ -161,7 +161,7 @@
+ };
+
+ adc {
+- ti,adc-channels = <4>;
++ ti,adc-channels = <4 5 6 7>;
+ };
+ };
+
+diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+index b90e7c2..744fc79 100644
+--- a/firmware/capes/BB-BONE-LCD7-01-00A3.dts
++++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
+@@ -164,7 +164,7 @@
+ };
+
+ adc {
+- ti,adc-channels = <4>;
++ ti,adc-channels = <4 5 6 7>;
+ };
+ };
+
diff --git a/patches/linux-3.8.13/0634-bone-renamed-adafruit-RTC-cape.patch b/patches/linux-3.8.13/0634-bone-renamed-adafruit-RTC-cape.patch
new file mode 100644
index 0000000..a27494e
--- /dev/null
+++ b/patches/linux-3.8.13/0634-bone-renamed-adafruit-RTC-cape.patch
@@ -0,0 +1,177 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Sat, 29 Jun 2013 23:51:36 +0000
+Subject: [PATCH] bone: renamed adafruit RTC cape
+
+rename RTC protocape to a more consistent naming
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 2 +-
+ firmware/Makefile | 4 +-
+ firmware/capes/BB-BONE-RTC-00A0.dts | 57 ++++++++++++++++++++++++
+ firmware/capes/cape-bone-adafruit-rtc-00A0.dts | 57 ------------------------
+ 4 files changed, 60 insertions(+), 60 deletions(-)
+ create mode 100644 firmware/capes/BB-BONE-RTC-00A0.dts
+ delete mode 100644 firmware/capes/cape-bone-adafruit-rtc-00A0.dts
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index aa95810..ff4b5d2 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -326,7 +326,7 @@
+ part-number = "BB-BONE-RTC-01";
+ version@00A0 {
+ version = "00A0";
+- dtbo = "cape-bone-adafruit-rtc-00A0.dtbo";
++ dtbo = "BB-BONE-RTC-00A0.dtbo";
+ };
+ };
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index 182de29..e6d178e 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -155,6 +155,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-LCD7-01-00A4.dtbo \
+ BB-BONE-eMMC1-01-00A0.dtbo \
+ BB-BONE-GPEVT-00A0.dtbo \
++ BB-BONE-RTC-00A0.dtbo \
+ BB-BONE-RS232-00A0.dtbo \
+ BB-BONE-SERL-01-00A1.dtbo \
+ cape-bone-iio-00A0.dtbo \
+@@ -186,8 +187,7 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-RST2-00A0.dtbo \
+ BB-BONE-CAM3-01-00A2.dtbo \
+ TT3201-001-01.dtbo \
+- BB-BONE-SERL-03-00A1.dtbo \
+- BB-BONE-PRU-01-00A0.dtbo
++ BB-BONE-SERL-03-00A1.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-RTC-00A0.dts b/firmware/capes/BB-BONE-RTC-00A0.dts
+new file mode 100644
+index 0000000..35344fd
+--- /dev/null
++++ b/firmware/capes/BB-BONE-RTC-00A0.dts
+@@ -0,0 +1,57 @@
++/*
++* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
++/plugin/;
++
++/*
++ * Pin assignments
++ *
++ * Module Connector
++ * SCL -> P9.19
++ * SDA <- P9.20
++ * SQW <- NC
++ *
++ */
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++ part-number = "BB-BONE-RTC-01";
++ version = "00A0";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P8.19", /* bl: ehrpwm2A */
++ "P9.27", /* lcd: gpio3_19 */
++ "P9.25", /* lcd: gpio3_21 */
++ "P9.31", /* spi: spi1_sclk */
++ "P9.29", /* spi: spi1_d0 */
++ "P9.30", /* spi: spi1_d1 */
++ "P9.28", /* spi: spi1_cs0 */
++ /* the hardware IP uses */
++ "gpio3_19",
++ "gpio3_21",
++ "ehrpwm2A",
++ "spi1";
++
++ fragment@0 {
++ target = <&i2c2>;
++
++ __overlay__ {
++ /* shut up DTC warnings */
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ /* DS1307 RTC module */
++ rtc@68 {
++ compatible = "dallas,ds1307";
++ reg = <0x68>;
++ };
++ };
++ };
++};
+diff --git a/firmware/capes/cape-bone-adafruit-rtc-00A0.dts b/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
+deleted file mode 100644
+index 35344fd..0000000
+--- a/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
++++ /dev/null
+@@ -1,57 +0,0 @@
+-/*
+-* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.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/;
+-/plugin/;
+-
+-/*
+- * Pin assignments
+- *
+- * Module Connector
+- * SCL -> P9.19
+- * SDA <- P9.20
+- * SQW <- NC
+- *
+- */
+-
+-/ {
+- compatible = "ti,beaglebone", "ti,beaglebone-black";
+- part-number = "BB-BONE-RTC-01";
+- version = "00A0";
+-
+- /* state the resources this cape uses */
+- exclusive-use =
+- /* the pin header uses */
+- "P8.19", /* bl: ehrpwm2A */
+- "P9.27", /* lcd: gpio3_19 */
+- "P9.25", /* lcd: gpio3_21 */
+- "P9.31", /* spi: spi1_sclk */
+- "P9.29", /* spi: spi1_d0 */
+- "P9.30", /* spi: spi1_d1 */
+- "P9.28", /* spi: spi1_cs0 */
+- /* the hardware IP uses */
+- "gpio3_19",
+- "gpio3_21",
+- "ehrpwm2A",
+- "spi1";
+-
+- fragment@0 {
+- target = <&i2c2>;
+-
+- __overlay__ {
+- /* shut up DTC warnings */
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- /* DS1307 RTC module */
+- rtc@68 {
+- compatible = "dallas,ds1307";
+- reg = <0x68>;
+- };
+- };
+- };
+-};
diff --git a/patches/linux-3.8.13/0635-bone-add-PPS-to-BB-BONE-RTC-cape.patch b/patches/linux-3.8.13/0635-bone-add-PPS-to-BB-BONE-RTC-cape.patch
new file mode 100644
index 0000000..9e4c577
--- /dev/null
+++ b/patches/linux-3.8.13/0635-bone-add-PPS-to-BB-BONE-RTC-cape.patch
@@ -0,0 +1,79 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Sat, 29 Jun 2013 23:51:37 +0000
+Subject: [PATCH] bone: add PPS to BB-BONE-RTC cape
+
+Added PPS input from SQW pin on the DS1307
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ firmware/capes/BB-BONE-RTC-00A0.dts | 43 ++++++++++++++++++++++++-----------
+ 1 file changed, 30 insertions(+), 13 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-RTC-00A0.dts b/firmware/capes/BB-BONE-RTC-00A0.dts
+index 35344fd..e90c12b 100644
+--- a/firmware/capes/BB-BONE-RTC-00A0.dts
++++ b/firmware/capes/BB-BONE-RTC-00A0.dts
+@@ -14,7 +14,7 @@
+ * Module Connector
+ * SCL -> P9.19
+ * SDA <- P9.20
+- * SQW <- NC
++ * SQW/PPS <- P9.15
+ *
+ */
+
+@@ -26,20 +26,22 @@
+ /* state the resources this cape uses */
+ exclusive-use =
+ /* the pin header uses */
+- "P8.19", /* bl: ehrpwm2A */
+- "P9.27", /* lcd: gpio3_19 */
+- "P9.25", /* lcd: gpio3_21 */
+- "P9.31", /* spi: spi1_sclk */
+- "P9.29", /* spi: spi1_d0 */
+- "P9.30", /* spi: spi1_d1 */
+- "P9.28", /* spi: spi1_cs0 */
+- /* the hardware IP uses */
+- "gpio3_19",
+- "gpio3_21",
+- "ehrpwm2A",
+- "spi1";
++ "P9.15"; /*gpio1_16 */
++
+
+ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++ pps_pins: pinmux_pps_pins {
++ pinctrl-single,pins = <
++ 0x040 0x27 /* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++ };
++ };
++
++
++ fragment@1 {
+ target = <&i2c2>;
+
+ __overlay__ {
+@@ -54,4 +56,19 @@
+ };
+ };
+ };
++
++ fragment@2 {
++ target = <&ocp>;
++ __overlay__ {
++ pps {
++ compatible = "pps-gpio";
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pps_pins>;
++
++ gpios = <&gpio2 16 0>;
++ assert-falling-edge;
++ };
++ };
++ };
+ };
diff --git a/patches/linux-3.8.13/0636-firmware-remove-rule-for-cape-bone-adafruit-lcd-00A0.patch b/patches/linux-3.8.13/0636-firmware-remove-rule-for-cape-bone-adafruit-lcd-00A0.patch
new file mode 100644
index 0000000..4f3982e
--- /dev/null
+++ b/patches/linux-3.8.13/0636-firmware-remove-rule-for-cape-bone-adafruit-lcd-00A0.patch
@@ -0,0 +1,21 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 10 Jul 2013 14:32:25 +0200
+Subject: [PATCH] firmware: remove rule for cape-bone-adafruit-lcd-00A0
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index e6d178e..cdfc800 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -140,7 +140,6 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ cape-bone-2g-emmc1.dtbo \
+ cape-bone-adafruit-lcd-00A0.dtbo \
+- cape-bone-adafruit-rtc-00A0.dtbo \
+ cape-bone-dvi-00A0.dtbo \
+ cape-bone-dvi-00A1.dtbo \
+ cape-bone-dvi-00A2.dtbo \
diff --git a/patches/linux-3.8.13/0637-tps65217-Enable-KEY_POWER-press-on-AC-loss-PWR_BUT.patch b/patches/linux-3.8.13/0637-tps65217-Enable-KEY_POWER-press-on-AC-loss-PWR_BUT.patch
new file mode 100644
index 0000000..fb322ba
--- /dev/null
+++ b/patches/linux-3.8.13/0637-tps65217-Enable-KEY_POWER-press-on-AC-loss-PWR_BUT.patch
@@ -0,0 +1,201 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 27 May 2013 17:14:23 +0300
+Subject: [PATCH] tps65217: Enable KEY_POWER press on AC loss / PWR_BUT
+
+Adaption of the original patch by Andrew Bradford <andrew.bradford@omni-id.com>
+Some minor devm_* changes and DT support.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/mfd/tps65217.c | 121 +++++++++++++++++++++++++++++++++++++++++-
+ include/linux/mfd/tps65217.h | 6 +++
+ 2 files changed, 125 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
+index b8f4864..818f2cd 100644
+--- a/drivers/mfd/tps65217.c
++++ b/drivers/mfd/tps65217.c
+@@ -26,6 +26,9 @@
+ #include <linux/err.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
++#include <linux/of_irq.h>
++#include <linux/of_gpio.h>
++#include <linux/interrupt.h>
+
+ #include <linux/mfd/core.h>
+ #include <linux/mfd/tps65217.h>
+@@ -153,6 +156,82 @@ static const struct of_device_id tps65217_of_match[] = {
+ { /* sentinel */ },
+ };
+
++static irqreturn_t tps65217_irq(int irq, void *irq_data)
++{
++ struct tps65217 *tps = irq_data;
++ unsigned int int_reg = 0, status_reg = 0;
++
++ tps65217_reg_read(tps, TPS65217_REG_INT, &int_reg);
++ tps65217_reg_read(tps, TPS65217_REG_STATUS, &status_reg);
++ if (status_reg)
++ dev_dbg(tps->dev, "status now: 0x%X\n", status_reg);
++
++ if (!int_reg)
++ return IRQ_NONE;
++
++ if (int_reg & TPS65217_INT_PBI) {
++ /* Handle push button */
++ dev_dbg(tps->dev, "power button status change\n");
++ input_report_key(tps->pwr_but, KEY_POWER,
++ status_reg & TPS65217_STATUS_PB);
++ input_sync(tps->pwr_but);
++ }
++ if (int_reg & TPS65217_INT_ACI) {
++ /* Handle AC power status change */
++ dev_dbg(tps->dev, "AC power status change\n");
++ /* Press KEY_POWER when AC not present */
++ input_report_key(tps->pwr_but, KEY_POWER,
++ ~status_reg & TPS65217_STATUS_ACPWR);
++ input_sync(tps->pwr_but);
++ }
++ if (int_reg & TPS65217_INT_USBI) {
++ /* Handle USB power status change */
++ dev_dbg(tps->dev, "USB power status change\n");
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int tps65217_probe_pwr_but(struct tps65217 *tps)
++{
++ int ret;
++ unsigned int int_reg;
++
++ tps->pwr_but = devm_input_allocate_device(tps->dev);
++ if (!tps->pwr_but) {
++ dev_err(tps->dev,
++ "Failed to allocated pwr_but input device\n");
++ return -ENOMEM;
++ }
++
++ tps->pwr_but->evbit[0] = BIT_MASK(EV_KEY);
++ tps->pwr_but->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
++ tps->pwr_but->name = "tps65217_pwr_but";
++ ret = input_register_device(tps->pwr_but);
++ if (ret) {
++ /* NOTE: devm managed device */
++ dev_err(tps->dev, "Failed to register button device\n");
++ return ret;
++ }
++ ret = devm_request_threaded_irq(tps->dev,
++ tps->irq, NULL, tps65217_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
++ "tps65217", tps);
++ if (ret != 0) {
++ dev_err(tps->dev, "Failed to request IRQ %d\n", tps->irq);
++ return ret;
++ }
++
++ /* enable the power button interrupt */
++ ret = tps65217_reg_read(tps, TPS65217_REG_INT, &int_reg);
++ if (ret < 0) {
++ dev_err(tps->dev, "Failed to read INT reg\n");
++ return ret;
++ }
++ int_reg &= ~TPS65217_INT_PBM;
++ tps65217_reg_write(tps, TPS65217_REG_INT, int_reg, TPS65217_PROTECT_NONE);
++ return 0;
++}
++
+ static int tps65217_probe(struct i2c_client *client,
+ const struct i2c_device_id *ids)
+ {
+@@ -160,10 +239,13 @@ static int tps65217_probe(struct i2c_client *client,
+ unsigned int version;
+ unsigned int chip_id = ids->driver_data;
+ const struct of_device_id *match;
++ struct device_node *node;
+ bool status_off = false;
++ int irq = -1, irq_gpio = -1;
+ int ret;
+
+- if (client->dev.of_node) {
++ node = client->dev.of_node;
++ if (node) {
+ match = of_match_device(tps65217_of_match, &client->dev);
+ if (!match) {
+ dev_err(&client->dev,
+@@ -171,8 +253,31 @@ static int tps65217_probe(struct i2c_client *client,
+ return -EINVAL;
+ }
+ chip_id = (unsigned int)match->data;
+- status_off = of_property_read_bool(client->dev.of_node,
++ status_off = of_property_read_bool(node,
+ "ti,pmic-shutdown-controller");
++
++ /* at first try to get irq via OF method */
++ irq = irq_of_parse_and_map(node, 0);
++ if (irq <= 0) {
++ irq = -1;
++ irq_gpio = of_get_named_gpio(node, "irq-gpio", 0);
++ if (irq_gpio >= 0) {
++ /* valid gpio; convert to irq */
++ ret = devm_gpio_request_one(&client->dev,
++ irq_gpio, GPIOF_DIR_IN,
++ "tps65217-gpio-irq");
++ if (ret != 0)
++ dev_warn(&client->dev, "Failed to "
++ "request gpio #%d\n", irq_gpio);
++ irq = gpio_to_irq(irq_gpio);
++ if (irq <= 0) {
++ dev_warn(&client->dev, "Failed to "
++ "convert gpio #%d to irq\n",
++ irq_gpio);
++ irq = -1;
++ }
++ }
++ }
+ }
+
+ if (!chip_id) {
+@@ -196,6 +301,18 @@ static int tps65217_probe(struct i2c_client *client,
+ return ret;
+ }
+
++ tps->irq = irq;
++ tps->irq_gpio = irq_gpio;
++
++ /* we got an irq, request it */
++ if (tps->irq >= 0) {
++ ret = tps65217_probe_pwr_but(tps);
++ if (ret < 0) {
++ dev_err(tps->dev, "Failed to probe pwr_but\n");
++ return ret;
++ }
++ }
++
+ ret = mfd_add_devices(tps->dev, -1, tps65217s,
+ ARRAY_SIZE(tps65217s), NULL, 0, NULL);
+ if (ret < 0) {
+diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h
+index 290762f..b138fa3 100644
+--- a/include/linux/mfd/tps65217.h
++++ b/include/linux/mfd/tps65217.h
+@@ -21,6 +21,7 @@
+ #include <linux/i2c.h>
+ #include <linux/regulator/driver.h>
+ #include <linux/regulator/machine.h>
++#include <linux/input.h>
+
+ /* TPS chip id list */
+ #define TPS65217 0xF0
+@@ -274,6 +275,11 @@ struct tps65217 {
+ struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
+ struct tps_info *info[TPS65217_NUM_REGULATOR];
+ struct regmap *regmap;
++
++ /* Power button and IRQ handling */
++ int irq_gpio; /* might not be set */
++ int irq;
++ struct input_dev *pwr_but;
+ };
+
+ static inline struct tps65217 *dev_to_tps65217(struct device *dev)
diff --git a/patches/linux-3.8.13/0638-dt-bone-common-Add-interrupt-for-PMIC.patch b/patches/linux-3.8.13/0638-dt-bone-common-Add-interrupt-for-PMIC.patch
new file mode 100644
index 0000000..5060d56
--- /dev/null
+++ b/patches/linux-3.8.13/0638-dt-bone-common-Add-interrupt-for-PMIC.patch
@@ -0,0 +1,33 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 27 May 2013 17:16:35 +0300
+Subject: [PATCH] dt: bone-common: Add interrupt for PMIC
+
+Add support for the PMIC interrupt, supports power-button presses.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index ff4b5d2..cd009ea 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -431,6 +431,9 @@
+ &tps {
+ ti,pmic-shutdown-controller;
+
++ interrupt-parent = <&intc>;
++ interrupts = <7>; /* NNMI */
++
+ regulators {
+ dcdc1_reg: regulator@0 {
+ regulator-always-on;
+@@ -472,6 +475,7 @@
+ regulator-always-on;
+ };
+ };
++
+ };
+
+ &cpsw_emac0 {
diff --git a/patches/linux-3.8.13/0639-drivers-pps-clients-pps-gpio.c-convert-to-module_pla.patch b/patches/linux-3.8.13/0639-drivers-pps-clients-pps-gpio.c-convert-to-module_pla.patch
new file mode 100644
index 0000000..4be4a8c
--- /dev/null
+++ b/patches/linux-3.8.13/0639-drivers-pps-clients-pps-gpio.c-convert-to-module_pla.patch
@@ -0,0 +1,44 @@
+From: Jan Luebbe <jlu@pengutronix.de>
+Date: Mon, 17 Jun 2013 20:30:28 +0000
+Subject: [PATCH] drivers/pps/clients/pps-gpio.c: convert to
+ module_platform_driver
+
+This removes some boilerplate code (no functional changes).
+
+Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
+Acked-by: Rodolfo Giometti <giometti@enneenne.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/pps/clients/pps-gpio.c | 18 +-----------------
+ 1 file changed, 1 insertion(+), 17 deletions(-)
+
+diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
+index 2bf0c1b..4c53c6d 100644
+--- a/drivers/pps/clients/pps-gpio.c
++++ b/drivers/pps/clients/pps-gpio.c
+@@ -203,23 +203,7 @@ static struct platform_driver pps_gpio_driver = {
+ },
+ };
+
+-static int __init pps_gpio_init(void)
+-{
+- int ret = platform_driver_register(&pps_gpio_driver);
+- if (ret < 0)
+- pr_err("failed to register platform driver\n");
+- return ret;
+-}
+-
+-static void __exit pps_gpio_exit(void)
+-{
+- platform_driver_unregister(&pps_gpio_driver);
+- pr_debug("unregistered platform driver\n");
+-}
+-
+-module_init(pps_gpio_init);
+-module_exit(pps_gpio_exit);
+-
++module_platform_driver(pps_gpio_driver);
+ MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
+ MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
+ MODULE_DESCRIPTION("Use GPIO pin as PPS source");
diff --git a/patches/linux-3.8.13/0640-drivers-pps-clients-pps-gpio.c-convert-to-devm_-help.patch b/patches/linux-3.8.13/0640-drivers-pps-clients-pps-gpio.c-convert-to-devm_-help.patch
new file mode 100644
index 0000000..1065e28
--- /dev/null
+++ b/patches/linux-3.8.13/0640-drivers-pps-clients-pps-gpio.c-convert-to-devm_-help.patch
@@ -0,0 +1,88 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Mon, 17 Jun 2013 20:30:29 +0000
+Subject: [PATCH] drivers/pps/clients/pps-gpio.c: convert to devm_* helpers
+
+Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
+Acked-by: Rodolfo Giometti <giometti@enneenne.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/pps/clients/pps-gpio.c | 22 +++++-----------------
+ 1 file changed, 5 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
+index 4c53c6d..7e0e93b 100644
+--- a/drivers/pps/clients/pps-gpio.c
++++ b/drivers/pps/clients/pps-gpio.c
+@@ -109,7 +109,6 @@ static int pps_gpio_probe(struct platform_device *pdev)
+ struct pps_gpio_device_data *data;
+ int irq;
+ int ret;
+- int err;
+ int pps_default_params;
+ const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+@@ -123,15 +122,13 @@ static int pps_gpio_probe(struct platform_device *pdev)
+ irq = gpio_to_irq(pdata->gpio_pin);
+ if (irq < 0) {
+ pr_err("failed to map GPIO to IRQ: %d\n", irq);
+- err = -EINVAL;
+- goto return_error;
++ return -EINVAL;
+ }
+
+ /* allocate space for device info */
+ data = kzalloc(sizeof(struct pps_gpio_device_data), GFP_KERNEL);
+ if (data == NULL) {
+- err = -ENOMEM;
+- goto return_error;
++ return -ENOMEM;
+ }
+
+ /* initialize PPS specific parts of the bookkeeping data structure. */
+@@ -152,42 +149,33 @@ static int pps_gpio_probe(struct platform_device *pdev)
+ if (data->pps == NULL) {
+ kfree(data);
+ pr_err("failed to register IRQ %d as PPS source\n", irq);
+- err = -EINVAL;
+- goto return_error;
++ return -EINVAL;
+ }
+
+ data->irq = irq;
+ data->pdata = pdata;
+
+ /* register IRQ interrupt handler */
+- ret = request_irq(irq, pps_gpio_irq_handler,
++ ret = devm_request_irq(&pdev->dev, irq, pps_gpio_irq_handler,
+ get_irqf_trigger_flags(pdata), data->info.name, data);
+ if (ret) {
+ pps_unregister_source(data->pps);
+ kfree(data);
+ pr_err("failed to acquire IRQ %d\n", irq);
+- err = -EINVAL;
+- goto return_error;
++ return -EINVAL;
+ }
+
+ platform_set_drvdata(pdev, data);
+ dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", irq);
+
+ return 0;
+-
+-return_error:
+- gpio_free(pdata->gpio_pin);
+- return err;
+ }
+
+ static int pps_gpio_remove(struct platform_device *pdev)
+ {
+ struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
+- const struct pps_gpio_platform_data *pdata = data->pdata;
+
+ platform_set_drvdata(pdev, NULL);
+- free_irq(data->irq, data);
+- gpio_free(pdata->gpio_pin);
+ pps_unregister_source(data->pps);
+ pr_info("removed IRQ %d as PPS source\n", data->irq);
+ kfree(data);
diff --git a/patches/linux-3.8.13/0641-pps-gpio-add-device-tree-binding-and-support.patch b/patches/linux-3.8.13/0641-pps-gpio-add-device-tree-binding-and-support.patch
new file mode 100644
index 0000000..13c7b46
--- /dev/null
+++ b/patches/linux-3.8.13/0641-pps-gpio-add-device-tree-binding-and-support.patch
@@ -0,0 +1,126 @@
+From: =?UTF-8?q?Jan=20L=C3=BCbbe?= <jlu@pengutronix.de>
+Date: Mon, 17 Jun 2013 20:30:30 +0000
+Subject: [PATCH] pps-gpio: add device-tree binding and support
+
+Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
+Acked-by: Rodolfo Giometti <giometti@enneenne.com>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ Documentation/devicetree/bindings/pps/pps-gpio.txt | 20 +++++++
+ drivers/pps/clients/pps-gpio.c | 55 +++++++++++++++++++-
+ 2 files changed, 73 insertions(+), 2 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pps/pps-gpio.txt
+
+diff --git a/Documentation/devicetree/bindings/pps/pps-gpio.txt b/Documentation/devicetree/bindings/pps/pps-gpio.txt
+new file mode 100644
+index 0000000..40bf9c3
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pps/pps-gpio.txt
+@@ -0,0 +1,20 @@
++Device-Tree Bindings for a PPS Signal on GPIO
++
++These properties describe a PPS (pulse-per-second) signal connected to
++a GPIO pin.
++
++Required properties:
++- compatible: should be "pps-gpio"
++- gpios: one PPS GPIO in the format described by ../gpio/gpio.txt
++
++Optional properties:
++- assert-falling-edge: when present, assert is indicated by a falling edge
++ (instead of by a rising edge)
++
++Example:
++ pps {
++ compatible = "pps-gpio";
++ gpios = <&gpio2 6 0>;
++
++ assert-falling-edge;
++ };
+diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
+index 7e0e93b..9b405b3 100644
+--- a/drivers/pps/clients/pps-gpio.c
++++ b/drivers/pps/clients/pps-gpio.c
+@@ -33,6 +33,8 @@
+ #include <linux/pps-gpio.h>
+ #include <linux/gpio.h>
+ #include <linux/list.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
+
+ /* Info for each registered platform device */
+ struct pps_gpio_device_data {
+@@ -104,14 +106,62 @@ get_irqf_trigger_flags(const struct pps_gpio_platform_data *pdata)
+ return flags;
+ }
+
++#ifdef CONFIG_OF
++static const struct of_device_id pps_gpio_dt_ids[] = {
++ { .compatible = "pps-gpio", },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids);
++
++static struct pps_gpio_platform_data *
++of_get_pps_gpio_pdata(struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ struct pps_gpio_platform_data *pdata;
++ int ret;
++
++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
++ if (!pdata)
++ return NULL;
++
++ ret = of_get_gpio(np, 0);
++ if (ret < 0) {
++ pr_err("failed to get GPIO from device tree\n");
++ return NULL;
++ }
++
++ pdata->gpio_pin = ret;
++ pdata->gpio_label = PPS_GPIO_NAME;
++
++ if (of_get_property(np, "assert-falling-edge", NULL))
++ pdata->assert_falling_edge = true;
++
++ return pdata;
++}
++#else
++static struct pps_gpio_platform_data *
++of_get_pps_gpio_pdata(struct platform_device *pdev)
++{
++ return NULL;
++}
++#endif
++
+ static int pps_gpio_probe(struct platform_device *pdev)
+ {
+ struct pps_gpio_device_data *data;
+ int irq;
+ int ret;
+ int pps_default_params;
+- const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
++ struct pps_gpio_platform_data *pdata;
++ const struct of_device_id *match;
++
++ match = of_match_device(pps_gpio_dt_ids, &pdev->dev);
++ if (match)
++ pdev->dev.platform_data = of_get_pps_gpio_pdata(pdev);
++ pdata = pdev->dev.platform_data;
+
++ if (!pdata)
++ return -ENODEV;
+
+ /* GPIO setup */
+ ret = pps_gpio_setup(pdev);
+@@ -187,7 +237,8 @@ static struct platform_driver pps_gpio_driver = {
+ .remove = pps_gpio_remove,
+ .driver = {
+ .name = PPS_GPIO_NAME,
+- .owner = THIS_MODULE
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(pps_gpio_dt_ids),
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0642-leds-leds-pwm-Convert-to-use-devm_get_pwm.patch b/patches/linux-3.8.13/0642-leds-leds-pwm-Convert-to-use-devm_get_pwm.patch
new file mode 100644
index 0000000..b215fc5
--- /dev/null
+++ b/patches/linux-3.8.13/0642-leds-leds-pwm-Convert-to-use-devm_get_pwm.patch
@@ -0,0 +1,84 @@
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Date: Fri, 21 Dec 2012 01:43:55 -0800
+Subject: [PATCH] leds: leds-pwm: Convert to use devm_get_pwm
+
+Update the driver to use the new API for requesting pwm so we can take
+advantage of the pwm_lookup table to find the correct pwm to be used for the
+LED functionality.
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Signed-off-by: Bryan Wu <cooloney@gmail.com>
+---
+ drivers/leds/leds-pwm.c | 19 ++++++-------------
+ include/linux/leds_pwm.h | 2 +-
+ 2 files changed, 7 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index 2157524..351257c 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -67,12 +67,11 @@ static int led_pwm_probe(struct platform_device *pdev)
+ cur_led = &pdata->leds[i];
+ led_dat = &leds_data[i];
+
+- led_dat->pwm = pwm_request(cur_led->pwm_id,
+- cur_led->name);
++ led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
+ if (IS_ERR(led_dat->pwm)) {
+ ret = PTR_ERR(led_dat->pwm);
+- dev_err(&pdev->dev, "unable to request PWM %d\n",
+- cur_led->pwm_id);
++ dev_err(&pdev->dev, "unable to request PWM for %s\n",
++ cur_led->name);
+ goto err;
+ }
+
+@@ -86,10 +85,8 @@ static int led_pwm_probe(struct platform_device *pdev)
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+- if (ret < 0) {
+- pwm_free(led_dat->pwm);
++ if (ret < 0)
+ goto err;
+- }
+ }
+
+ platform_set_drvdata(pdev, leds_data);
+@@ -98,10 +95,8 @@ static int led_pwm_probe(struct platform_device *pdev)
+
+ err:
+ if (i > 0) {
+- for (i = i - 1; i >= 0; i--) {
++ for (i = i - 1; i >= 0; i--)
+ led_classdev_unregister(&leds_data[i].cdev);
+- pwm_free(leds_data[i].pwm);
+- }
+ }
+
+ return ret;
+@@ -115,10 +110,8 @@ static int led_pwm_remove(struct platform_device *pdev)
+
+ leds_data = platform_get_drvdata(pdev);
+
+- for (i = 0; i < pdata->num_leds; i++) {
++ for (i = 0; i < pdata->num_leds; i++)
+ led_classdev_unregister(&leds_data[i].cdev);
+- pwm_free(leds_data[i].pwm);
+- }
+
+ return 0;
+ }
+diff --git a/include/linux/leds_pwm.h b/include/linux/leds_pwm.h
+index 33a0711..a65e964 100644
+--- a/include/linux/leds_pwm.h
++++ b/include/linux/leds_pwm.h
+@@ -7,7 +7,7 @@
+ struct led_pwm {
+ const char *name;
+ const char *default_trigger;
+- unsigned pwm_id;
++ unsigned pwm_id __deprecated;
+ u8 active_low;
+ unsigned max_brightness;
+ unsigned pwm_period_ns;
diff --git a/patches/linux-3.8.13/0643-leds-leds-pwm-Preparing-the-driver-for-device-tree-s.patch b/patches/linux-3.8.13/0643-leds-leds-pwm-Preparing-the-driver-for-device-tree-s.patch
new file mode 100644
index 0000000..d95b7ee
--- /dev/null
+++ b/patches/linux-3.8.13/0643-leds-leds-pwm-Preparing-the-driver-for-device-tree-s.patch
@@ -0,0 +1,104 @@
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Date: Fri, 21 Dec 2012 01:43:56 -0800
+Subject: [PATCH] leds: leds-pwm: Preparing the driver for device tree support
+
+In order to be able to add device tree support for leds-pwm driver we need
+to rearrange the data structures used by the drivers.
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Signed-off-by: Bryan Wu <cooloney@gmail.com>
+---
+ drivers/leds/leds-pwm.c | 39 +++++++++++++++++++++++----------------
+ 1 file changed, 23 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index 351257c..c767837 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -30,6 +30,11 @@ struct led_pwm_data {
+ unsigned int period;
+ };
+
++struct led_pwm_priv {
++ int num_leds;
++ struct led_pwm_data leds[0];
++};
++
+ static void led_pwm_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+ {
+@@ -47,25 +52,29 @@ static void led_pwm_set(struct led_classdev *led_cdev,
+ }
+ }
+
++static inline size_t sizeof_pwm_leds_priv(int num_leds)
++{
++ return sizeof(struct led_pwm_priv) +
++ (sizeof(struct led_pwm_data) * num_leds);
++}
++
+ static int led_pwm_probe(struct platform_device *pdev)
+ {
+ struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
+- struct led_pwm *cur_led;
+- struct led_pwm_data *leds_data, *led_dat;
++ struct led_pwm_priv *priv;
+ int i, ret = 0;
+
+ if (!pdata)
+ return -EBUSY;
+
+- leds_data = devm_kzalloc(&pdev->dev,
+- sizeof(struct led_pwm_data) * pdata->num_leds,
+- GFP_KERNEL);
+- if (!leds_data)
++ priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(pdata->num_leds),
++ GFP_KERNEL);
++ if (!priv)
+ return -ENOMEM;
+
+ for (i = 0; i < pdata->num_leds; i++) {
+- cur_led = &pdata->leds[i];
+- led_dat = &leds_data[i];
++ struct led_pwm *cur_led = &pdata->leds[i];
++ struct led_pwm_data *led_dat = &priv->leds[i];
+
+ led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
+ if (IS_ERR(led_dat->pwm)) {
+@@ -88,15 +97,16 @@ static int led_pwm_probe(struct platform_device *pdev)
+ if (ret < 0)
+ goto err;
+ }
++ priv->num_leds = pdata->num_leds;
+
+- platform_set_drvdata(pdev, leds_data);
++ platform_set_drvdata(pdev, priv);
+
+ return 0;
+
+ err:
+ if (i > 0) {
+ for (i = i - 1; i >= 0; i--)
+- led_classdev_unregister(&leds_data[i].cdev);
++ led_classdev_unregister(&priv->leds[i].cdev);
+ }
+
+ return ret;
+@@ -104,14 +114,11 @@ err:
+
+ static int led_pwm_remove(struct platform_device *pdev)
+ {
++ struct led_pwm_priv *priv = platform_get_drvdata(pdev);
+ int i;
+- struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
+- struct led_pwm_data *leds_data;
+-
+- leds_data = platform_get_drvdata(pdev);
+
+- for (i = 0; i < pdata->num_leds; i++)
+- led_classdev_unregister(&leds_data[i].cdev);
++ for (i = 0; i < priv->num_leds; i++)
++ led_classdev_unregister(&priv->leds[i].cdev);
+
+ return 0;
+ }
diff --git a/patches/linux-3.8.13/0644-leds-leds-pwm-Simplify-cleanup-code.patch b/patches/linux-3.8.13/0644-leds-leds-pwm-Simplify-cleanup-code.patch
new file mode 100644
index 0000000..6338c47
--- /dev/null
+++ b/patches/linux-3.8.13/0644-leds-leds-pwm-Simplify-cleanup-code.patch
@@ -0,0 +1,35 @@
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Date: Fri, 21 Dec 2012 01:44:00 -0800
+Subject: [PATCH] leds: leds-pwm: Simplify cleanup code
+
+The code looks more nicer if we use:
+
+while (i--)
+
+instead:
+if (i > 0)
+ for (i = i - 1; i >= 0; i--)
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Signed-off-by: Bryan Wu <cooloney@gmail.com>
+---
+ drivers/leds/leds-pwm.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index c767837..46f4e44 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -104,10 +104,8 @@ static int led_pwm_probe(struct platform_device *pdev)
+ return 0;
+
+ err:
+- if (i > 0) {
+- for (i = i - 1; i >= 0; i--)
+- led_classdev_unregister(&priv->leds[i].cdev);
+- }
++ while (i--)
++ led_classdev_unregister(&priv->leds[i].cdev);
+
+ return ret;
+ }
diff --git a/patches/linux-3.8.13/0645-leds-leds-pwm-Add-device-tree-bindings.patch b/patches/linux-3.8.13/0645-leds-leds-pwm-Add-device-tree-bindings.patch
new file mode 100644
index 0000000..a4dd235
--- /dev/null
+++ b/patches/linux-3.8.13/0645-leds-leds-pwm-Add-device-tree-bindings.patch
@@ -0,0 +1,240 @@
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Date: Fri, 21 Dec 2012 01:44:01 -0800
+Subject: [PATCH] leds: leds-pwm: Add device tree bindings
+
+The DT binding for the pwm-leds devices are similar to the gpio-leds type.
+LEDs are represented as sub-nodes of the pwm-leds device.
+The code for handling the DT boot is based on the code found in the
+leds-gpio driver and adapted to use PWMs instead of GPIOs.
+To avoid having custom cleanup code in case of DT boot the newly created
+devm_of_pwm_get() API is used to get the correct PWM instance.
+
+For usage see:
+Documentation/devicetree/bindings/leds/leds-pwm.txt
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Bryan Wu <cooloney@gmail.com>
+---
+ .../devicetree/bindings/leds/leds-pwm.txt | 48 +++++++++
+ drivers/leds/leds-pwm.c | 112 ++++++++++++++++----
+ 2 files changed, 140 insertions(+), 20 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/leds/leds-pwm.txt
+
+diff --git a/Documentation/devicetree/bindings/leds/leds-pwm.txt b/Documentation/devicetree/bindings/leds/leds-pwm.txt
+new file mode 100644
+index 0000000..7297107
+--- /dev/null
++++ b/Documentation/devicetree/bindings/leds/leds-pwm.txt
+@@ -0,0 +1,48 @@
++LED connected to PWM
++
++Required properties:
++- compatible : should be "pwm-leds".
++
++Each LED is represented as a sub-node of the pwm-leds device. Each
++node's name represents the name of the corresponding LED.
++
++LED sub-node properties:
++- pwms : PWM property to point to the PWM device (phandle)/port (id) and to
++ specify the period time to be used: <&phandle id period_ns>;
++- pwm-names : (optional) Name to be used by the PWM subsystem for the PWM device
++ For the pwms and pwm-names property please refer to:
++ Documentation/devicetree/bindings/pwm/pwm.txt
++- max-brightness : Maximum brightness possible for the LED
++- label : (optional)
++ see Documentation/devicetree/bindings/leds/common.txt
++- linux,default-trigger : (optional)
++ see Documentation/devicetree/bindings/leds/common.txt
++
++Example:
++
++twl_pwm: pwm {
++ /* provides two PWMs (id 0, 1 for PWM1 and PWM2) */
++ compatible = "ti,twl6030-pwm";
++ #pwm-cells = <2>;
++};
++
++twl_pwmled: pwmled {
++ /* provides one PWM (id 0 for Charing indicator LED) */
++ compatible = "ti,twl6030-pwmled";
++ #pwm-cells = <2>;
++};
++
++pwmleds {
++ compatible = "pwm-leds";
++ kpad {
++ label = "omap4::keypad";
++ pwms = <&twl_pwm 0 7812500>;
++ max-brightness = <127>;
++ };
++
++ charging {
++ label = "omap4:green:chrg";
++ pwms = <&twl_pwmled 0 7812500>;
++ max-brightness = <255>;
++ };
++};
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index 46f4e44..a1ea5f6 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -16,6 +16,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
++#include <linux/of_platform.h>
+ #include <linux/fb.h>
+ #include <linux/leds.h>
+ #include <linux/err.h>
+@@ -58,46 +59,110 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
+ (sizeof(struct led_pwm_data) * num_leds);
+ }
+
+-static int led_pwm_probe(struct platform_device *pdev)
++static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
+ {
+- struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
++ struct device_node *node = pdev->dev.of_node;
++ struct device_node *child;
+ struct led_pwm_priv *priv;
+- int i, ret = 0;
++ int count, ret;
+
+- if (!pdata)
+- return -EBUSY;
++ /* count LEDs in this device, so we know how much to allocate */
++ count = of_get_child_count(node);
++ if (!count)
++ return NULL;
+
+- priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(pdata->num_leds),
++ priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
+ GFP_KERNEL);
+ if (!priv)
+- return -ENOMEM;
++ return NULL;
+
+- for (i = 0; i < pdata->num_leds; i++) {
+- struct led_pwm *cur_led = &pdata->leds[i];
+- struct led_pwm_data *led_dat = &priv->leds[i];
++ for_each_child_of_node(node, child) {
++ struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
+
+- led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
++ led_dat->cdev.name = of_get_property(child, "label",
++ NULL) ? : child->name;
++
++ led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL);
+ if (IS_ERR(led_dat->pwm)) {
+- ret = PTR_ERR(led_dat->pwm);
+ dev_err(&pdev->dev, "unable to request PWM for %s\n",
+- cur_led->name);
++ led_dat->cdev.name);
+ goto err;
+ }
++ /* Get the period from PWM core when n*/
++ led_dat->period = pwm_get_period(led_dat->pwm);
++
++ led_dat->cdev.default_trigger = of_get_property(child,
++ "linux,default-trigger", NULL);
++ of_property_read_u32(child, "max-brightness",
++ &led_dat->cdev.max_brightness);
+
+- led_dat->cdev.name = cur_led->name;
+- led_dat->cdev.default_trigger = cur_led->default_trigger;
+- led_dat->active_low = cur_led->active_low;
+- led_dat->period = cur_led->pwm_period_ns;
+ led_dat->cdev.brightness_set = led_pwm_set;
+ led_dat->cdev.brightness = LED_OFF;
+- led_dat->cdev.max_brightness = cur_led->max_brightness;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+- if (ret < 0)
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to register for %s\n",
++ led_dat->cdev.name);
++ of_node_put(child);
+ goto err;
++ }
++ priv->num_leds++;
++ }
++
++ return priv;
++err:
++ while (priv->num_leds--)
++ led_classdev_unregister(&priv->leds[priv->num_leds].cdev);
++
++ return NULL;
++}
++
++static int led_pwm_probe(struct platform_device *pdev)
++{
++ struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
++ struct led_pwm_priv *priv;
++ int i, ret = 0;
++
++ if (pdata && pdata->num_leds) {
++ priv = devm_kzalloc(&pdev->dev,
++ sizeof_pwm_leds_priv(pdata->num_leds),
++ GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ for (i = 0; i < pdata->num_leds; i++) {
++ struct led_pwm *cur_led = &pdata->leds[i];
++ struct led_pwm_data *led_dat = &priv->leds[i];
++
++ led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
++ if (IS_ERR(led_dat->pwm)) {
++ ret = PTR_ERR(led_dat->pwm);
++ dev_err(&pdev->dev,
++ "unable to request PWM for %s\n",
++ cur_led->name);
++ goto err;
++ }
++
++ led_dat->cdev.name = cur_led->name;
++ led_dat->cdev.default_trigger = cur_led->default_trigger;
++ led_dat->active_low = cur_led->active_low;
++ led_dat->period = cur_led->pwm_period_ns;
++ led_dat->cdev.brightness_set = led_pwm_set;
++ led_dat->cdev.brightness = LED_OFF;
++ led_dat->cdev.max_brightness = cur_led->max_brightness;
++ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
++
++ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
++ if (ret < 0)
++ goto err;
++ }
++ priv->num_leds = pdata->num_leds;
++ } else {
++ priv = led_pwm_create_of(pdev);
++ if (!priv)
++ return -ENODEV;
+ }
+- priv->num_leds = pdata->num_leds;
+
+ platform_set_drvdata(pdev, priv);
+
+@@ -121,12 +186,19 @@ static int led_pwm_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++static const struct of_device_id of_pwm_leds_match[] = {
++ { .compatible = "pwm-leds", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, of_pwm_leds_match);
++
+ static struct platform_driver led_pwm_driver = {
+ .probe = led_pwm_probe,
+ .remove = led_pwm_remove,
+ .driver = {
+ .name = "leds_pwm",
+ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(of_pwm_leds_match),
+ },
+ };
+
diff --git a/patches/linux-3.8.13/0646-leds-leds-pwm-Defer-led_pwm_set-if-PWM-can-sleep.patch b/patches/linux-3.8.13/0646-leds-leds-pwm-Defer-led_pwm_set-if-PWM-can-sleep.patch
new file mode 100644
index 0000000..48ad4e3
--- /dev/null
+++ b/patches/linux-3.8.13/0646-leds-leds-pwm-Defer-led_pwm_set-if-PWM-can-sleep.patch
@@ -0,0 +1,118 @@
+From: Florian Vaussard <florian.vaussard@epfl.ch>
+Date: Mon, 28 Jan 2013 06:00:59 -0800
+Subject: [PATCH] leds: leds-pwm: Defer led_pwm_set() if PWM can sleep
+
+Call to led_pwm_set() can happen inside atomic context, like triggers.
+If the PWM call can sleep, defer using a worker.
+
+Signed-off-by: Florian Vaussard <florian.vaussard@epfl.ch>
+Reviewed-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
+Signed-off-by: Bryan Wu <cooloney@gmail.com>
+---
+ drivers/leds/leds-pwm.c | 50 +++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 42 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index a1ea5f6..faf52c0 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -23,12 +23,16 @@
+ #include <linux/pwm.h>
+ #include <linux/leds_pwm.h>
+ #include <linux/slab.h>
++#include <linux/workqueue.h>
+
+ struct led_pwm_data {
+ struct led_classdev cdev;
+ struct pwm_device *pwm;
++ struct work_struct work;
+ unsigned int active_low;
+ unsigned int period;
++ int duty;
++ bool can_sleep;
+ };
+
+ struct led_pwm_priv {
+@@ -36,6 +40,26 @@ struct led_pwm_priv {
+ struct led_pwm_data leds[0];
+ };
+
++static void __led_pwm_set(struct led_pwm_data *led_dat)
++{
++ int new_duty = led_dat->duty;
++
++ pwm_config(led_dat->pwm, new_duty, led_dat->period);
++
++ if (new_duty == 0)
++ pwm_disable(led_dat->pwm);
++ else
++ pwm_enable(led_dat->pwm);
++}
++
++static void led_pwm_work(struct work_struct *work)
++{
++ struct led_pwm_data *led_dat =
++ container_of(work, struct led_pwm_data, work);
++
++ __led_pwm_set(led_dat);
++}
++
+ static void led_pwm_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+ {
+@@ -44,13 +68,12 @@ static void led_pwm_set(struct led_classdev *led_cdev,
+ unsigned int max = led_dat->cdev.max_brightness;
+ unsigned int period = led_dat->period;
+
+- if (brightness == 0) {
+- pwm_config(led_dat->pwm, 0, period);
+- pwm_disable(led_dat->pwm);
+- } else {
+- pwm_config(led_dat->pwm, brightness * period / max, period);
+- pwm_enable(led_dat->pwm);
+- }
++ led_dat->duty = brightness * period / max;
++
++ if (led_dat->can_sleep)
++ schedule_work(&led_dat->work);
++ else
++ __led_pwm_set(led_dat);
+ }
+
+ static inline size_t sizeof_pwm_leds_priv(int num_leds)
+@@ -100,6 +123,10 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
+ led_dat->cdev.brightness = LED_OFF;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
++ led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
++ if (led_dat->can_sleep)
++ INIT_WORK(&led_dat->work, led_pwm_work);
++
+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to register for %s\n",
+@@ -153,6 +180,10 @@ static int led_pwm_probe(struct platform_device *pdev)
+ led_dat->cdev.max_brightness = cur_led->max_brightness;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
++ led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
++ if (led_dat->can_sleep)
++ INIT_WORK(&led_dat->work, led_pwm_work);
++
+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+ if (ret < 0)
+ goto err;
+@@ -180,8 +211,11 @@ static int led_pwm_remove(struct platform_device *pdev)
+ struct led_pwm_priv *priv = platform_get_drvdata(pdev);
+ int i;
+
+- for (i = 0; i < priv->num_leds; i++)
++ for (i = 0; i < priv->num_leds; i++) {
+ led_classdev_unregister(&priv->leds[i].cdev);
++ if (priv->leds[i].can_sleep)
++ cancel_work_sync(&priv->leds[i].work);
++ }
+
+ return 0;
+ }
diff --git a/patches/linux-3.8.13/0647-leds-pwm-Enable-compilation-on-this-version-of-the-k.patch b/patches/linux-3.8.13/0647-leds-pwm-Enable-compilation-on-this-version-of-the-k.patch
new file mode 100644
index 0000000..88a46ea
--- /dev/null
+++ b/patches/linux-3.8.13/0647-leds-pwm-Enable-compilation-on-this-version-of-the-k.patch
@@ -0,0 +1,54 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 10 Jul 2013 23:50:05 +0300
+Subject: [PATCH] leds: pwm: Enable compilation on this version of the kernel
+
+---
+ drivers/leds/Kconfig | 2 +-
+ drivers/leds/leds-pwm.c | 7 ++++---
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
+index b58bc8a..de3fc297c 100644
+--- a/drivers/leds/Kconfig
++++ b/drivers/leds/Kconfig
+@@ -310,7 +310,7 @@ config LEDS_DAC124S085
+ config LEDS_PWM
+ tristate "PWM driven LED Support"
+ depends on LEDS_CLASS
+- depends on HAVE_PWM
++ depends on PWM
+ help
+ This option enables support for pwm driven LEDs
+
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index faf52c0..730c7c6 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -105,7 +105,8 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
+ led_dat->cdev.name = of_get_property(child, "label",
+ NULL) ? : child->name;
+
+- led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL);
++ /* caution: this is not release automatically */
++ led_dat->pwm = of_pwm_request(child, NULL);
+ if (IS_ERR(led_dat->pwm)) {
+ dev_err(&pdev->dev, "unable to request PWM for %s\n",
+ led_dat->cdev.name);
+@@ -123,7 +124,7 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
+ led_dat->cdev.brightness = LED_OFF;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
+- led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
++ led_dat->can_sleep = 0; /* pwm_can_sleep(led_dat->pwm); */
+ if (led_dat->can_sleep)
+ INIT_WORK(&led_dat->work, led_pwm_work);
+
+@@ -180,7 +181,7 @@ static int led_pwm_probe(struct platform_device *pdev)
+ led_dat->cdev.max_brightness = cur_led->max_brightness;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
+- led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
++ led_dat->can_sleep = 0; /* pwm_can_sleep(led_dat->pwm); */
+ if (led_dat->can_sleep)
+ INIT_WORK(&led_dat->work, led_pwm_work);
+
diff --git a/patches/linux-3.8.13/0648-capes-Add-bacon-cape.patch b/patches/linux-3.8.13/0648-capes-Add-bacon-cape.patch
new file mode 100644
index 0000000..74f7860
--- /dev/null
+++ b/patches/linux-3.8.13/0648-capes-Add-bacon-cape.patch
@@ -0,0 +1,247 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 10 Jul 2013 23:51:05 +0300
+Subject: [PATCH] capes: Add bacon cape
+
+This is the full Linux driver enable bacon cape definition.
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/BB-BONE-BACON-00A0.dts | 216 +++++++++++++++++++++++++++++++++
+ 2 files changed, 218 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-BACON-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index cdfc800..e0e7522 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -186,7 +186,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-RST2-00A0.dtbo \
+ BB-BONE-CAM3-01-00A2.dtbo \
+ TT3201-001-01.dtbo \
+- BB-BONE-SERL-03-00A1.dtbo
++ BB-BONE-SERL-03-00A1.dtbo \
++ BB-BONE-BACON-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-BACON-00A0.dts b/firmware/capes/BB-BONE-BACON-00A0.dts
+new file mode 100644
+index 0000000..87f5f01
+--- /dev/null
++++ b/firmware/capes/BB-BONE-BACON-00A0.dts
+@@ -0,0 +1,216 @@
++/*
++ * Copyright (C) 2013 Circuit Co.
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-BACON";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.36", /* AIN5 */
++ "P8.19", /* gpio-keys: gpio0_23 */
++ "P9.14", /* pwm: ehrpwm1A */
++ "P9.16", /* pwm: ehrpwm1B */
++ "P9.42", /* pwm: eCAP0_in_PWM0_out */
++ "P9.17", /* shift: gpio0_5 LATCH */
++ "P9.18", /* shift: gpio0_4 SERIAL */
++ "P9.22", /* shift: gpio0_2 CLOCK */
++ /* the hardware IP uses */
++ "tscadc",
++ "gpio0_23",
++ "ehrpwm1A",
++ "ehrpwm1B",
++ "eCAP0_in_PWM0_out",
++ "gpio0_5",
++ "gpio0_4",
++ "gpio0_2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bacon_key_pins: pinmux_bacon_key_pins {
++ pinctrl-single,pins = <
++ 0x020 0x2f /* gpmc_ad8.gpio0_22, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ bacon_ehrpwm1_pins: pinmux_bacon_ehrpwm1_pins {
++ pinctrl-single,pins = <
++ 0x048 0x6 /* P9_14 (ZCZ ball U14) | MODE 6 */
++ 0x04c 0x6 /* P9_16 (ZCZ ball T14) | MODE 6 */
++ >;
++ };
++
++ bacon_ecap0_pins: pinmux_bacon_ecap0_pins {
++ pinctrl-single,pins = <
++ 0x164 0x0 /* P9_42 (ZCZ ball C18) | MODE 0 */
++ >;
++ };
++
++ bacon_gpiohelp_pins: pinmux_bacon_gpio_helper_pins {
++ pinctrl-single,pins = <
++ 0x15c 0x0f /* P9 17 spi0_cs0.gpio0_5 | MODE7 | OUTPUT */
++ 0x158 0x0f /* P9 18 spi0_d1.gpio0_4 | MODE7 | OUTPUT */
++ 0x150 0x0f /* P9 22 spi0_sclk.gpio0_2 | MODE7 | OUTPUT */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ adc {
++ ti,adc-channels = <8>; /* 8 channels (but only 5 is used) */
++ };
++ };
++
++ bacon_helper {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ /* report micro-volts */
++ vsense-scale = <100000 100000 100000 100000 100000 100000 100000 100000>;
++ status = "okay";
++ };
++
++ /* the single button */
++ bacon_gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_key_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ button@0 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 22 0x1>; /* really gpio0_23 */
++ gpio-key,wakeup;
++ };
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&epwmss0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@4 {
++ target = <&ecap0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_ecap0_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@5 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@6 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_ehrpwm1_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@7 {
++ target = <&ocp>;
++ __overlay__ {
++ bacon_pwm_leds {
++ compatible = "pwm-leds";
++
++ bacon_pwm_green {
++ label = "bacon::green";
++ pwms = <&ehrpwm1 0 500000 0>;
++ max-brightness = <255>;
++ };
++
++ bacon_pwm_blue {
++ label = "bacon::blue";
++ pwms = <&ehrpwm1 1 500000 0>;
++ max-brightness = <255>;
++ };
++
++ bacon_pwm_red {
++ label = "bacon::red";
++ pwms = <&ecap0 0 500000 0>;
++ max-brightness = <255>;
++ };
++ };
++ };
++ };
++
++ fragment@8 {
++ target = <&ocp>;
++ __overlay__ {
++
++ bacon_gpiohelp {
++ compatible = "gpio-of-helper";
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_gpiohelp_pins>;
++
++ /* declare your gpios */
++ LATCH {
++ gpio-name = "LATCH";
++ gpio = <&gpio1 5 0x00>; /* gpio1 is gpio0 */
++ output;
++ init-high;
++ };
++
++ SERIAL {
++ gpio-name = "SERIAL";
++ gpio = <&gpio1 4 0x00>; /* gpio1 is gpio0 */
++ output;
++ init-low;
++ };
++
++ CLOCK {
++ gpio-name = "CLOCK";
++ gpio = <&gpio1 2 0x00>; /* gpio1 is gpio0 */
++ output;
++ init-low;
++ };
++ };
++ };
++ };
++
++
++
++};
diff --git a/patches/linux-3.8.13/0649-cape-bacon-Cosmetic-change-of-the-adc-helper-name.patch b/patches/linux-3.8.13/0649-cape-bacon-Cosmetic-change-of-the-adc-helper-name.patch
new file mode 100644
index 0000000..0d608a5
--- /dev/null
+++ b/patches/linux-3.8.13/0649-cape-bacon-Cosmetic-change-of-the-adc-helper-name.patch
@@ -0,0 +1,21 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Jul 2013 10:01:50 +0300
+Subject: [PATCH] cape: bacon: Cosmetic change of the adc helper name
+
+---
+ firmware/capes/BB-BONE-BACON-00A0.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/firmware/capes/BB-BONE-BACON-00A0.dts b/firmware/capes/BB-BONE-BACON-00A0.dts
+index 87f5f01..d25c1baa 100644
+--- a/firmware/capes/BB-BONE-BACON-00A0.dts
++++ b/firmware/capes/BB-BONE-BACON-00A0.dts
+@@ -89,7 +89,7 @@
+ };
+ };
+
+- bacon_helper {
++ bacon_adc_helper {
+ compatible = "bone-iio-helper";
+ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
+ /* report micro-volts */
diff --git a/patches/linux-3.8.13/0650-cape-bacon-educational-edition.patch b/patches/linux-3.8.13/0650-cape-bacon-educational-edition.patch
new file mode 100644
index 0000000..8e7e7d5
--- /dev/null
+++ b/patches/linux-3.8.13/0650-cape-bacon-educational-edition.patch
@@ -0,0 +1,199 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Jul 2013 10:04:22 +0300
+Subject: [PATCH] cape: bacon: educational edition
+
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/BB-BONE-BACONE-00A0.dts | 169 ++++++++++++++++++++++++++++++++
+ 2 files changed, 171 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-BACONE-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index e0e7522..d2c6161 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -187,7 +187,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ BB-BONE-CAM3-01-00A2.dtbo \
+ TT3201-001-01.dtbo \
+ BB-BONE-SERL-03-00A1.dtbo \
+- BB-BONE-BACON-00A0.dtbo
++ BB-BONE-BACON-00A0.dtbo \
++ BB-BONE-BACONE-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-BACONE-00A0.dts b/firmware/capes/BB-BONE-BACONE-00A0.dts
+new file mode 100644
+index 0000000..a02173d
+--- /dev/null
++++ b/firmware/capes/BB-BONE-BACONE-00A0.dts
+@@ -0,0 +1,169 @@
++/*
++ * Copyright (C) 2013 Circuit Co.
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-BACONE";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.36", /* AIN5 */
++ "P8.19", /* gpio-keys: gpio0_23 */
++ "P9.14", /* pwm: ehrpwm1A */
++ "P9.16", /* pwm: ehrpwm1B */
++ "P9.42", /* pwm: eCAP0_in_PWM0_out */
++ "P9.17", /* shift: gpio0_5 LATCH */
++ "P9.18", /* shift: gpio0_4 SERIAL */
++ "P9.22", /* shift: gpio0_2 CLOCK */
++ /* the hardware IP uses */
++ "tscadc",
++ "gpio0_23",
++ "ehrpwm1A",
++ "ehrpwm1B",
++ "eCAP0_in_PWM0_out",
++ "gpio0_5",
++ "gpio0_4",
++ "gpio0_2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bacon_ehrpwm1_pins: pinmux_bacon_ehrpwm1_pins {
++ pinctrl-single,pins = <
++ 0x048 0x6 /* P9_14 (ZCZ ball U14) | MODE 6 */
++ 0x04c 0x6 /* P9_16 (ZCZ ball T14) | MODE 6 */
++ >;
++ };
++
++ bacon_ecap0_pins: pinmux_bacon_ecap0_pins {
++ pinctrl-single,pins = <
++ 0x164 0x0 /* P9_42 (ZCZ ball C18) | MODE 0 */
++ >;
++ };
++
++ bacon_gpiohelp_pins: pinmux_bacon_gpio_helper_pins {
++ pinctrl-single,pins = <
++ 0x020 0x2f /* gpmc_ad8.gpio0_22, INPUT | PULLDIS | MODE7 */
++ 0x15c 0x0f /* P9 17 spi0_cs0.gpio0_5 | MODE7 | OUTPUT */
++ 0x158 0x0f /* P9 18 spi0_d1.gpio0_4 | MODE7 | OUTPUT */
++ 0x150 0x0f /* P9 22 spi0_sclk.gpio0_2 | MODE7 | OUTPUT */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ adc {
++ ti,adc-channels = <8>; /* 8 channels (but only 5 is used) */
++ };
++ };
++
++ bacon_adc_helper {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ /* report micro-volts */
++ vsense-scale = <100000 100000 100000 100000 100000 100000 100000 100000>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&epwmss0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@4 {
++ target = <&ecap0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_ecap0_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@5 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@6 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_ehrpwm1_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@8 {
++ target = <&ocp>;
++ __overlay__ {
++
++ bacon_gpiohelp {
++ compatible = "gpio-of-helper";
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_gpiohelp_pins>;
++
++ /* declare your gpios */
++ LATCH {
++ gpio-name = "LATCH";
++ gpio = <&gpio1 5 0x00>; /* gpio1 is gpio0 */
++ output;
++ init-high;
++ };
++
++ SERIAL {
++ gpio-name = "SERIAL";
++ gpio = <&gpio1 4 0x00>; /* gpio1 is gpio0 */
++ output;
++ init-low;
++ };
++
++ CLOCK {
++ gpio-name = "CLOCK";
++ gpio = <&gpio1 2 0x00>; /* gpio1 is gpio0 */
++ output;
++ init-low;
++ };
++
++ BUTTON {
++ gpio-name = "BUTTON";
++ gpio = <&gpio1 22 0x01>; /* gpio1 is gpio0 */
++ input;
++ };
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0651-capes-bacon-Update-with-new-ADC-driver-method.patch b/patches/linux-3.8.13/0651-capes-bacon-Update-with-new-ADC-driver-method.patch
new file mode 100644
index 0000000..2630d28
--- /dev/null
+++ b/patches/linux-3.8.13/0651-capes-bacon-Update-with-new-ADC-driver-method.patch
@@ -0,0 +1,35 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 11 Jul 2013 20:03:56 +0300
+Subject: [PATCH] capes: bacon: Update with new ADC driver method
+
+---
+ firmware/capes/BB-BONE-BACON-00A0.dts | 2 +-
+ firmware/capes/BB-BONE-BACONE-00A0.dts | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/firmware/capes/BB-BONE-BACON-00A0.dts b/firmware/capes/BB-BONE-BACON-00A0.dts
+index d25c1baa..96a1a36 100644
+--- a/firmware/capes/BB-BONE-BACON-00A0.dts
++++ b/firmware/capes/BB-BONE-BACON-00A0.dts
+@@ -85,7 +85,7 @@
+ status = "okay";
+
+ adc {
+- ti,adc-channels = <8>; /* 8 channels (but only 5 is used) */
++ ti,adc-channels = <0 1 2 3 4 5 6 7>; /* 8 channels (but only #5 is used) */
+ };
+ };
+
+diff --git a/firmware/capes/BB-BONE-BACONE-00A0.dts b/firmware/capes/BB-BONE-BACONE-00A0.dts
+index a02173d..07fa753 100644
+--- a/firmware/capes/BB-BONE-BACONE-00A0.dts
++++ b/firmware/capes/BB-BONE-BACONE-00A0.dts
+@@ -80,7 +80,7 @@
+ status = "okay";
+
+ adc {
+- ti,adc-channels = <8>; /* 8 channels (but only 5 is used) */
++ ti,adc-channels = <0 1 2 3 4 5 6 7>; /* 8 channels (but only #5 is used) */
+ };
+ };
+
diff --git a/patches/linux-3.8.13/0652-capes-BACON-Educational-cape-with-free-form-muxing.patch b/patches/linux-3.8.13/0652-capes-BACON-Educational-cape-with-free-form-muxing.patch
new file mode 100644
index 0000000..189117b
--- /dev/null
+++ b/patches/linux-3.8.13/0652-capes-BACON-Educational-cape-with-free-form-muxing.patch
@@ -0,0 +1,234 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Mon, 15 Jul 2013 23:00:35 +0300
+Subject: [PATCH] capes: BACON Educational cape with free form muxing
+
+---
+ firmware/Makefile | 3 +-
+ firmware/capes/BB-BONE-BACONE2-00A0.dts | 204 +++++++++++++++++++++++++++++++
+ 2 files changed, 206 insertions(+), 1 deletion(-)
+ create mode 100644 firmware/capes/BB-BONE-BACONE2-00A0.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index d2c6161..cea34e6 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -188,7 +188,8 @@ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+ TT3201-001-01.dtbo \
+ BB-BONE-SERL-03-00A1.dtbo \
+ BB-BONE-BACON-00A0.dtbo \
+- BB-BONE-BACONE-00A0.dtbo
++ BB-BONE-BACONE-00A0.dtbo \
++ BB-BONE-BACONE2-00A0.dtbo
+
+ # the geiger cape
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+diff --git a/firmware/capes/BB-BONE-BACONE2-00A0.dts b/firmware/capes/BB-BONE-BACONE2-00A0.dts
+new file mode 100644
+index 0000000..5118f71
+--- /dev/null
++++ b/firmware/capes/BB-BONE-BACONE2-00A0.dts
+@@ -0,0 +1,204 @@
++/*
++ * Copyright (C) 2013 Circuit Co.
++ *
++ * 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/;
++/plugin/;
++
++/ {
++ compatible = "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "BB-BONE-BACONE2";
++
++ /* state the resources this cape uses */
++ exclusive-use =
++ /* the pin header uses */
++ "P9.36", /* AIN5 */
++ "P8.19", /* gpio-keys: gpio0_23 */
++ "P9.14", /* pwm: ehrpwm1A */
++ "P9.16", /* pwm: ehrpwm1B */
++ "P9.42", /* pwm: eCAP0_in_PWM0_out */
++ "P9.17", /* shift: gpio0_5 LATCH */
++ "P9.18", /* shift: gpio0_4 SERIAL */
++ "P9.22", /* shift: gpio0_2 CLOCK */
++ /* the hardware IP uses */
++ "tscadc",
++ "gpio0_23",
++ "ehrpwm1A",
++ "ehrpwm1B",
++ "eCAP0_in_PWM0_out",
++ "gpio0_5",
++ "gpio0_4",
++ "gpio0_2";
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bacon_ehrpwm1_pins: pinmux_bacon_ehrpwm1_pins {
++ pinctrl-single,pins = <
++ 0x048 0x6 /* P9_14 (ZCZ ball U14) | MODE 6 */
++ 0x04c 0x6 /* P9_16 (ZCZ ball T14) | MODE 6 */
++ >;
++ };
++
++ bacon_ecap0_pins: pinmux_bacon_ecap0_pins {
++ pinctrl-single,pins = <
++ 0x164 0x0 /* P9_42 (ZCZ ball C18) | MODE 0 */
++ >;
++ };
++
++ bacon_gpiohelp_pins: pinmux_bacon_gpio_helper_pins {
++ pinctrl-single,pins = <
++ 0x020 0x2f /* gpmc_ad8.gpio0_22, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ bacon_LATCH_in_pins: pinmux_bacon_LATCH_in_pins {
++ pinctrl-single,pins = <
++ 0x15c 0x0f /* P9 17 spi0_cs0.gpio0_5 | MODE7 | OUTPUT */
++ >;
++ };
++
++ bacon_LATCH_out_pins: pinmux_bacon_LATCH_out_pins {
++ pinctrl-single,pins = <
++ 0x15c 0x2f /* P9 17 spi0_cs0.gpio0_5 | MODE7 | PULLDIS | INPUT */
++ >;
++ };
++
++ bacon_SERIAL_in_pins: pinmux_bacon_SERIAL_in_pins {
++ pinctrl-single,pins = <
++ 0x158 0x2f /* P9 18 spi0_d1.gpio0_4 | MODE7 | PULLDIS | INPUT */
++ >;
++ };
++
++ bacon_SERIAL_out_pins: pinmux_bacon_SERIAL_out_pins {
++ pinctrl-single,pins = <
++ 0x158 0x0f /* P9 18 spi0_d1.gpio0_4 | MODE7 | OUTPUT */
++ >;
++ };
++
++ bacon_CLOCK_in_pins: pinmux_bacon_CLOCK_in_pins {
++ pinctrl-single,pins = <
++ 0x150 0x2f /* P9 22 spi0_sclk.gpio0_2 | MODE7 | PULLDIS | INPUT */
++ >;
++ };
++
++ bacon_CLOCK_out_pins: pinmux_bacon_CLOCK_out_pins {
++ pinctrl-single,pins = <
++ 0x150 0x0f /* P9 22 spi0_sclk.gpio0_2 | MODE7 | OUTPUT */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++ /* avoid stupid warning */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++
++ adc {
++ ti,adc-channels = <0 1 2 3 4 5 6 7>; /* 8 channels (but only #5 is used) */
++ };
++ };
++
++ bacon_adc_helper {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ /* report micro-volts */
++ vsense-scale = <100000 100000 100000 100000 100000 100000 100000 100000>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@3 {
++ target = <&epwmss0>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@4 {
++ target = <&ecap0>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_ecap0_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@5 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@6 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_ehrpwm1_pins>;
++ status = "okay";
++ };
++ };
++
++ fragment@8 {
++ target = <&ocp>;
++ __overlay__ {
++
++ LATCH_helper {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++ pinctrl-names = "in", "out";
++ pinctrl-0 = <&bacon_LATCH_in_pins>;
++ pinctrl-1 = <&bacon_LATCH_out_pins>;
++ };
++
++ SERIAL_helper {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++ pinctrl-names = "in", "out";
++ pinctrl-0 = <&bacon_SERIAL_in_pins>;
++ pinctrl-1 = <&bacon_SERIAL_out_pins>;
++ };
++
++ CLOCK_helper {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++ pinctrl-names = "in", "out";
++ pinctrl-0 = <&bacon_CLOCK_in_pins>;
++ pinctrl-1 = <&bacon_CLOCK_out_pins>;
++ };
++
++ bacon_gpiohelp {
++ compatible = "gpio-of-helper";
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bacon_gpiohelp_pins>;
++
++ BUTTON {
++ gpio-name = "BUTTON";
++ gpio = <&gpio1 22 0x01>; /* gpio1 is gpio0 */
++ input;
++ };
++ };
++ };
++ };
++};
diff --git a/patches/linux-3.8.13/0653-firmware-add-BeBoPr-cape.patch b/patches/linux-3.8.13/0653-firmware-add-BeBoPr-cape.patch
new file mode 100644
index 0000000..a6b6e2d
--- /dev/null
+++ b/patches/linux-3.8.13/0653-firmware-add-BeBoPr-cape.patch
@@ -0,0 +1,446 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 17 Jul 2013 09:05:27 +0200
+Subject: [PATCH] firmware: add BeBoPr cape
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ firmware/Makefile | 1 +
+ firmware/capes/2191-R2.dts | 417 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 418 insertions(+)
+ create mode 100644 firmware/capes/2191-R2.dts
+
+diff --git a/firmware/Makefile b/firmware/Makefile
+index cea34e6..677d634 100644
+--- a/firmware/Makefile
++++ b/firmware/Makefile
+@@ -138,6 +138,7 @@ fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
+
+ # all the generic capes
+ fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
++ 2191-R2.dtbo \
+ cape-bone-2g-emmc1.dtbo \
+ cape-bone-adafruit-lcd-00A0.dtbo \
+ cape-bone-dvi-00A0.dtbo \
+diff --git a/firmware/capes/2191-R2.dts b/firmware/capes/2191-R2.dts
+new file mode 100644
+index 0000000..d179b05
+--- /dev/null
++++ b/firmware/capes/2191-R2.dts
+@@ -0,0 +1,417 @@
++/*
++ * Copyright (C) 2013 Bas Laarhoven
++ *
++ * 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.
++ *
++ * version 1.1 - 2013-06-17 cleanup for release
++ */
++/dts-v1/;
++/plugin/;
++
++/ {
++ compatible = "aes,bebopr", "ti,beaglebone", "ti,beaglebone-black";
++
++ /* identification */
++ part-number = "2191";
++ version = "R2";
++
++ exclusive-use =
++ /* state the resources this cape uses */
++
++ /* ------ IO POWER ------ */
++
++ "P8.3", /* gpio1.6 gpio38 old Enable */
++ "P8.5", /* gpio1.2 gpio34 old Enablen */
++ "P8.7", /* timer4 gpio66 new Enablen */
++
++ /* ------ PWM ------ */
++
++ "P8.36", /* gpio2.16 J4_PWM */
++ "P8.45", /* pru1.r30.0 J3_PWM */
++ "P8.46", /* pru1.r30.1 J2_PWM */
++ "ehrpwm1A",
++ "ehrpwm2A",
++ "ehrpwm2B",
++
++ /* ------ STEPPERS ------ */
++
++ "P8.41", /* gpio2.10 #X_ENA */
++ "P8.44", /* gpio2.9 #X_DIR */
++ "P8.43", /* gpio2.8 #X_STP */
++ "P8.40", /* gpio2.13 #Y_ENA */
++ "P8.39", /* gpio2.12 #Y_DIR */
++ "P8.42", /* gpio2.11 #Y_STP */
++ "P8.28", /* gpio2.24 #Z_ENA */
++ "P8.29", /* gpio2.23 #Z_DIR */
++ "P8.27", /* gpio2.22 #Z_STP */
++ "P8.20", /* gpio1.31 #E_ENA */
++ "P8.21", /* gpio1.30 #E_DIR */
++ "P8.30", /* gpio2.25 #E_STP */
++ "pru1",
++ "pruss",
++
++ /* ------ SENSORS ------ */
++
++ "P8.31", /* gpio0.10 #X_MIN */
++ "P8.32", /* gpio0.11 #X_MAX */
++ "P8.35", /* gpio0.8 #Y_MIN */
++ "P8.33", /* gpio0.9 #Y_MAX */
++ "P8.38", /* gpio2.15 #Z_MIN */
++ "P8.37", /* gpio2.14 #Z_MAX */
++
++ /* ------ ADC ------ */
++
++ "P9.40", /* AIN1 */
++ "P9.38", /* AIN3 */
++ "P9.36", /* AIN5 */
++ "tscadc",
++
++ /* ------ LED ------ */
++
++ "P8.25"; /* gpio1.0 LED */
++
++
++
++ /* ----------- IO POWER ------------ */
++
++ fragment@0 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bebopr_io_ena_pins: pinmux_bebopr_io_ena_pins {
++ pinctrl-single,pins = <
++ 0x018 0x07 /* P8-3 GPIO1_6 gpmc_ad6.gpio1[6] */
++ 0x008 0x07 /* P8-5 GPIO1_2 gpmc_ad2.gpio1[2] */
++ 0x090 0x07 /* P8-7 TIMER4 gpmc_advn_ale.gpio2[2] */
++ >;
++ };
++ };
++ };
++
++ fragment@1 {
++ target = <&ocp>;
++ __overlay__ {
++
++ bebopr_io_ena {
++ compatible = "aes,bebopr";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bebopr_io_ena_pins>;
++
++ bebopr-io-enable {
++ label = "bebopr:io_enables";
++ gpios = <&gpio2 2 1>, <&gpio2 6 0>, <&gpio3 2 1>;
++ default-state = "off";
++ };
++ };
++ };
++ };
++
++ /* ----------- PWM ------------ */
++
++ fragment@15 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ P8_46_ehrpwm_pin: pinmux_P8_46_ehrpwm_pin {
++ pinctrl-single,pins = <0x0a4 0x3>; /* P8_46 (ZCZ ball R2) | MODE 3 */
++ };
++
++ P8_46_gpio_pin: pinmux_P8_46_gpio_pin {
++ pinctrl-single,pins = <0x0a4 0x7>; /* P8_46 (ZCZ ball R2) | MODE 7 */
++ };
++
++ P8_46_pruss_pin: pinmux_P8_46_pruss_pin {
++ pinctrl-single,pins = <0x0a4 0x5>; /* P8_46 (ZCZ ball R2) | MODE 5 */
++ };
++
++ P8_45_ehrpwm_pin: pinmux_P8_45_ehrpwm_pin {
++ pinctrl-single,pins = <0x0a0 0x3>; /* P8_45 (ZCZ ball R1) | MODE 3 */
++ };
++
++ P8_45_gpio_pin: pinmux_P8_45_gpio_pin {
++ pinctrl-single,pins = <0x0a0 0x7>; /* P8_45 (ZCZ ball R1) | MODE 7 */
++ };
++
++ P8_45_pruss_pin: pinmux_P8_45_pruss_pin {
++ pinctrl-single,pins = <0x0a0 0x5>; /* P8_45 (ZCZ ball R1) | MODE 5 */
++ };
++
++ P8_36_ehrpwm_pin: pinmux_P8_36_ehrpwm_pin {
++ pinctrl-single,pins = <0x0c8 0x2>; /* P8_36 (ZCZ ball U3) | MODE 2 */
++ };
++
++ P8_36_gpio_pin: pinmux_P8_36_gpio_pin {
++ pinctrl-single,pins = <0x0c8 0x7>; /* P8_36 (ZCZ ball U3) | MODE 7 */
++ };
++ };
++ };
++
++ fragment@16 {
++ target = <&ocp>;
++ __overlay__ {
++
++ bebopr_pwm_J2_pinmux {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++
++ pinctrl-names = "default", "gpio", "pruss";
++ pinctrl-0 = <&P8_46_ehrpwm_pin>;
++ pinctrl-1 = <&P8_46_gpio_pin>;
++ pinctrl-2 = <&P8_46_pruss_pin>;
++ };
++
++ bebopr_pwm_J3_pinmux {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++
++ pinctrl-names = "default", "gpio", "pruss";
++ pinctrl-0 = <&P8_45_ehrpwm_pin>;
++ pinctrl-1 = <&P8_45_gpio_pin>;
++ pinctrl-2 = <&P8_45_pruss_pin>;
++ };
++
++ bebopr_pwm_J4_pinmux {
++ compatible = "bone-pinmux-helper";
++ status = "okay";
++
++ pinctrl-names = "default", "gpio";
++ pinctrl-0 = <&P8_36_ehrpwm_pin>;
++ pinctrl-1 = <&P8_36_gpio_pin>;
++ };
++
++ bebopr_pwm_J2 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm2 1 10000000 0>;
++ pwm-names = "PWM_J2_FAN";
++ enabled = <0>;
++ duty = <0>;
++ status = "okay";
++ };
++
++ bebopr_pwm_J3 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm2 0 10000000 0>;
++ pwm-names = "PWM_J3_EXTR";
++ enabled = <0>;
++ duty = <0>;
++ status = "okay";
++ };
++
++ bebopr_pwm_J4 {
++ compatible = "pwm_test";
++ pwms = <&ehrpwm1 0 100000000 0>;
++ pwm-names = "PWM_J4_BED";
++ enabled = <0>;
++ duty = <0>;
++ status = "okay";
++ };
++ };
++ };
++
++ fragment@11 {
++ target = <&epwmss1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@12 {
++ target = <&ehrpwm1>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@13 {
++ target = <&epwmss2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ fragment@14 {
++ target = <&ehrpwm2>;
++ __overlay__ {
++ status = "okay";
++ };
++ };
++
++ /* ----------- STEPPERS ------------ */
++
++ fragment@21 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bebopr_pruss_pins: pinmux_bebopr_pruss_pins {
++ status = "okay";
++ pinctrl-single,pins = <
++ 0xb0 5 /* #X_ENA, pr1_pru1_pru_r30_4, P8_41, gpio2.10, mode5 out */
++ 0xac 5 /* #X_DIR, pr1_pru1_pru_r30_3, P8_44, gpio2.9, mode5 out */
++ 0xa8 5 /* #X_STP, pr1_pru1_pru_r30_2, P8_43, gpio2.8, mode5 out */
++ 0xbc 5 /* #Y_ENA, pr1_pru1_pru_r30_7, P8_40, gpio2.13, mode5 out */
++ 0xb8 5 /* #Y_DIR, pr1_pru1_pru_r30_6, P8_39, gpio2.12, mode5 out */
++ 0xb4 5 /* #Y_STP, pr1_pru1_pru_r30_5, P8_42, gpio2.11, mode5 out */
++ 0xe8 5 /* #Z_ENA, pr1_pru1_pru_r30_10, P8_28, gpio2.24, mode5 out */
++ 0xe4 5 /* #Z_DIR, pr1_pru1_pru_r30_9, P8_29, gpio2.23, mode5 out */
++ 0xe0 5 /* #Z_STP, pr1_pru1_pru_r30_8, P8_27, gpio2.22, mode5 out */
++ 0x84 5 /* #E_ENA, pr1_pru1_pru_r30_13, P8_20, gpio1.31, mode5 out */
++ 0x80 5 /* #E_DIR, pr1_pru1_pru_r30_12, P8_21, gpio1.30, mode5 out */
++ 0xec 5 /* #E_STP, pr1_pru1_pru_r30_11, P8_30, gpio2.25, mode5 out */
++ >;
++ };
++ };
++ };
++
++
++ fragment@22 {
++ target = <&pruss>;
++ __overlay__ {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bebopr_pruss_pins>;
++ };
++ };
++
++ fragment@23 {
++ target = <&ocp>;
++ __overlay__ {
++
++ bebopr_pruss {
++ compatible = "pruss_uio";
++ status = "okay";
++
++ pinctrl-names = "default";
++ pinctrl-0 = <&bebopr_pruss_pins>;
++
++ stepper_x {
++ pin-names = "bebopr:x_ena", "bebopr:x_dir", "bebpor:x_stp";
++ gpios = <&gpio3 10 0>, <&gpio3 9 0>, <&gpio3 8 0>;
++ };
++ stepper_y {
++ pin-names = "bebopr:y_ena", "bebopr:y_dir", "bebpor:y_stp";
++ gpios = <&gpio3 13 0>, <&gpio3 12 0>, <&gpio3 11 0>;
++ };
++ stepper_z {
++ pin-names = "bebopr:z_ena", "bebopr:z_dir", "bebpor:z_stp";
++ gpios = <&gpio3 24 0>, <&gpio3 23 0>, <&gpio3 22 0>;
++ };
++ stepper_e {
++ pin-names = "bebopr:e_ena", "bebopr:e_dir", "bebpor:e_stp";
++ gpios = <&gpio2 31 0>, <&gpio2 30 0>, <&gpio3 25 0>;
++ };
++ };
++ };
++ };
++
++ /* ----------- SENSORS ------------ */
++
++ fragment@31 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bebopr_sensor_pins: pinmux_bebopr_sensor_pins {
++ pinctrl-single,pins = <
++ /* all inputs with pull-downs */
++ 0xd8 0x2f /* #X_MIN, P8_31, gpio0.10, mode7 in */
++ 0xdc 0x2f /* #X_MAX, P8_32, gpio0.11, mode7 in */
++ 0xd0 0x2f /* #Y_MIN, P8_35, gpio0.8, mode7 in */
++ 0xd4 0x2f /* #Y_MAX, P8_33, gpio0.9 , mode7 in */
++ 0xc4 0x2f /* #Z_MIN, P8_38, gpio2.15, mode7 in */
++ 0xc0 0x2f /* #Z_MAX, P8_37, gpio2.14, mode7 in */
++ >;
++ };
++ };
++ };
++
++ fragment@33 {
++ target = <&ocp>;
++ __overlay__ {
++
++ compatible = "bone-pinmux-helper";
++
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bebopr_sensor_pins>;
++
++ sensors_x {
++ pin-names = "bebopr:x_min", "bebopr:x_max";
++ gpios = <&gpio1 10 0>, <&gpio1 11 0>;
++ };
++ sensors_y {
++ pin-names = "bebopr:y_min", "bebopr:y_max";
++ gpios = <&gpio1 8 0>, <&gpio1 9 0>;
++ };
++ sensors_z {
++ pin-names = "bebopr:z_min", "bebopr:z_max";
++ gpios = <&gpio3 15 0>, <&gpio3 14 0>;
++ };
++ };
++ };
++
++ /* ----------- ADC ------------ */
++
++ fragment@41 {
++ target = <&ocp>;
++ __overlay__ {
++
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ tscadc {
++ compatible = "ti,ti-tscadc";
++ reg = <0x44e0d000 0x1000>;
++ interrupt-parent = <&intc>;
++ interrupts = <16>;
++ ti,hwmods = "adc_tsc";
++ status = "okay";
++ adc {
++ ti,adc-channels = <8>;
++ };
++ };
++
++ bebopr_adc {
++ compatible = "bone-iio-helper";
++ vsense-name = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
++ vsense-scale = < 228 228 228 228 228 228 228 228>;
++ status = "okay";
++ };
++ };
++ };
++
++ /* ----------- LED ------------ */
++
++ fragment@51 {
++ target = <&am33xx_pinmux>;
++ __overlay__ {
++
++ bebopr_led_pins: pinmux_bebopr_led_pins {
++ pinctrl-single,pins = <
++ 0x000 0x07 /* P8-25 GPIO1_0 gpmc_ad0 .gpio1[0] */
++ >;
++ };
++ };
++ };
++
++
++ fragment@52 {
++ target = <&ocp>;
++ __overlay__ {
++
++ bebopr_leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bebopr_led_pins>;
++
++ status_led {
++ label = "bebopr:status_led";
++ gpios = <&gpio2 0 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++ };
++ };
++ };
++
++};
diff --git a/patches/linux-3.8.13/0701-Release-distrokit-beaglebone-20130720.patch b/patches/linux-3.8.13/0701-Release-distrokit-beaglebone-20130720.patch
new file mode 100644
index 0000000..cf75680
--- /dev/null
+++ b/patches/linux-3.8.13/0701-Release-distrokit-beaglebone-20130720.patch
@@ -0,0 +1,22 @@
+From: Jan Luebbe <jlu@pengutronix.de>
+Date: Sat, 20 Jul 2013 14:27:34 +0200
+Subject: [PATCH] Release distrokit/beaglebone/20130720
+
+Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index 183eff3..0bef6ba 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ VERSION = 3
+ PATCHLEVEL = 8
+ SUBLEVEL = 13
+-EXTRAVERSION =
++EXTRAVERSION =-20130720
+ NAME = Displaced Humerus Anterior
+
+ # *DOCUMENTATION*
diff --git a/patches/linux-3.8.13/series b/patches/linux-3.8.13/series
new file mode 100644
index 0000000..ae0b3f4
--- /dev/null
+++ b/patches/linux-3.8.13/series
@@ -0,0 +1,663 @@
+# umpf-base: v3.8.13
+# umpf-name: distrokit/beaglebone
+# umpf-version: distrokit/beaglebone/20130720
+# umpf-topic: topic/distrokit/beaglebone/board
+# umpf-hashinfo: 6fbec96b98a35ba475bb821a60c903566f35a575
+# umpf-topic-range: dbf932a9b316d5b29b3e220e5a30e7a165ad2992..6fbec96b98a35ba475bb821a60c903566f35a575
+0001-Without-MACH_-option-Early-printk-DEBUG_LL.patch
+0002-ARM-OMAP-Hack-AM33xx-clock-data-to-allow-JTAG-use.patch
+0003-video-st7735fb-add-st7735-framebuffer-driver.patch
+0004-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
+0005-of-Add-generic-device-tree-DMA-helpers.patch
+0006-of-dma-fix-build-break-for-CONFIG_OF.patch
+0007-of-dma-fix-typos-in-generic-dma-binding-definition.patch
+0008-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
+0009-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
+0010-dmaengine-add-dma_get_channel_caps.patch
+0011-dma-edma-add-device_channel_caps-support.patch
+0012-mmc-davinci-get-SG-segment-limits-with-dma_get_chann.patch
+0013-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
+0014-ARM-edma-remove-unused-transfer-controller-handlers.patch
+0015-ARM-edma-add-AM33XX-support-to-the-private-EDMA-API.patch
+0016-dmaengine-edma-enable-build-for-AM33XX.patch
+0017-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
+0018-ARM-dts-add-AM33XX-EDMA-support.patch
+0019-dmaengine-add-dma_request_slave_channel_compat.patch
+0020-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
+0021-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch
+0022-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
+0023-ARM-dts-add-AM33XX-MMC-support.patch
+0024-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
+0025-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
+0026-ARM-dts-add-AM33XX-SPI-DMA-support.patch
+0027-ARM-dts-Add-SPI-Flash-support-to-am335x-evm.patch
+0028-Documentation-bindings-add-spansion.patch
+0029-ARM-dts-enable-spi1-node-and-pinmux-on-BeagleBone.patch
+0030-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
+0031-misc-add-gpevt-driver.patch
+0032-ARM-dts-add-BeagleBone-gpevt-support.patch
+0033-ARM-configs-working-dmaengine-configs-for-da8xx-and-.patch
+0034-ARM-dts-Add-UART4-support-to-BeagleBone.patch
+0035-gpevnt-Remove-__devinit.patch
+0036-ARM-OMAP2-am33xx-hwmod-Fix-register-offset-NULL-chec.patch
+0037-rtc-OMAP-Add-system-pm_power_off-to-rtc-driver.patch
+0038-ARM-dts-AM33XX-Set-pmic-shutdown-controller-for-Beag.patch
+0039-ARM-dts-AM33XX-Enable-system-power-off-control-in-am.patch
+0040-i2c-pinctrl-ify-i2c-omap.c.patch
+0041-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
+0042-beaglebone-DT-set-default-triggers-for-LEDS.patch
+0043-beaglebone-add-a-cpu-led-trigger.patch
+0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch
+0045-mfd-input-iio-ti_am335x_adc-use-one-structure-for-ti.patch
+0046-input-ti_am33x_tsc-Step-enable-bits-made-configurabl.patch
+0047-input-ti_am33x_tsc-Order-of-TSC-wires-made-configura.patch
+0048-input-ti_am33x_tsc-remove-unwanted-fifo-flush.patch
+0049-input-ti_am33x_tsc-Add-DT-support.patch
+0050-iio-ti_am335x_adc-Add-DT-support.patch
+0051-arm-dts-AM335x-evm-Add-TSC-ADC-MFD-device-support.patch
+0052-mfd-ti_am335x_tscadc-Add-DT-support.patch
+0053-iio-ti_tscadc-provide-datasheet_name-and-scan_type.patch
+0054-mfd-ti_tscadc-deal-with-partial-activation.patch
+0055-input-ti_am335x_adc-use-only-FIFO0-and-clean-up-a-li.patch
+0056-input-ti_am335x_tsc-ACK-the-HW_PEN-irq-in-ISR.patch
+0057-input-ti_am335x_tsc-return-IRQ_NONE-if-there-was-no-.patch
+0058-iio-ti_am335x_adc-Allow-to-specify-input-line.patch
+0059-iio-ti_am335x_adc-check-if-we-found-the-value.patch
+0060-MFD-ti_tscadc-disable-TSC-control.patch
+0061-IIO-ADC-ti_adc-Fix-1st-sample-read.patch
+0062-input-ti_tsc-Enable-shared-IRQ-TSC.patch
+0063-Revert.-Backport-IIO.patch
+0064-iio-ti_am335x_adc-Added-iio_voltageX_scale.patch
+0065-iio-ti_am335x_adc-Add-the-in-kernel-IIO-map-interfac.patch
+0066-pinctrl-pinctrl-single-must-be-initialized-early.patch
+0067-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
+0068-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
+0069-am335x-evm-hack-around-i2c-node-names.patch
+0070-tsl2550-fix-lux1_input-error-in-low-light.patch
+0071-viafb-rename-display_timing-to-via_display_timing.patch
+0072-video-add-display_timing-and-videomode.patch
+0073-video-add-of-helper-for-display-timings-videomode.patch
+0074-fbmon-add-videomode-helpers.patch
+0075-fbmon-add-of_videomode-helpers.patch
+0076-drm_modes-add-videomode-helpers.patch
+0077-drm_modes-add-of_videomode-helpers.patch
+0078-fbmon-fix-build-error.patch
+0079-of-display-timings-use-of_get_child_by_name.patch
+0080-da8xx-Allow-use-by-am33xx-based-devices.patch
+0081-video-da8xx-fb-fb_check_var-enhancement.patch
+0082-video-da8xx-fb-simplify-lcd_reset.patch
+0083-video-da8xx-fb-use-modedb-helper-to-update-var.patch
+0084-video-da8xx-fb-remove-unneeded-var-initialization.patch
+0085-video-da8xx-fb-store-current-display-information.patch
+0086-video-da8xx-fb-store-clk-rate-even-if-CPUFREQ.patch
+0087-video-da8xx-fb-pix-clk-and-clk-div-handling-cleanup.patch
+0088-video-da8xx-fb-store-struct-device.patch
+0089-video-da8xx-fb-report-correct-pixclock.patch
+0090-video-da8xx-fb-fb_set_par-support.patch
+0091-ARM-dts-AM33XX-Add-lcdc-node.patch
+0092-ARM-dts-AM33XX-Add-am335x-evm-lcdc-panel-timings.patch
+0093-ARM-dts-AM33XX-Add-am335x-evm-lcdc-pincontrol-info.patch
+0094-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-panel-timings.patch
+0095-ARM-dts-AM33XX-Add-am335x-evmsk-lcdc-pincontrol-info.patch
+0096-ARM-OMAP-AM33xx-hwmod-Corrects-PWM-subsystem-HWMOD-e.patch
+0097-ARM-OMAP-AM33xx-hwmod-Add-parent-child-relationship-.patch
+0098-ARM-dts-AM33XX-Add-PWMSS-device-tree-nodes.patch
+0099-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch
+0100-ARM-dts-AM33XX-Add-PWM-backlight-DT-data-to-am335x-e.patch
+0101-clk-divider-prepare-for-minimum-divider.patch
+0102-clk-divider-handle-minimum-divider.patch
+0103-ARM-OMAP2-dpll-round-rate-to-closest-value.patch
+0104-ARM-OMAP2-dpll-am335x-avoid-freqsel.patch
+0105-ARM-OMAP2-clock-DEFINE_STRUCT_CLK_FLAGS-helper.patch
+0106-ARM-AM33XX-clock-SET_RATE_PARENT-in-lcd-path.patch
+0107-video-da8xx-fb-make-io-operations-safe.patch
+0108-video-da8xx-fb-fix-24bpp-raster-configuration.patch
+0109-video-da8xx-fb-enable-sync-lost-intr-for-v2-ip.patch
+0110-video-da8xx-fb-use-devres.patch
+0111-video-da8xx-fb-ensure-non-null-cfg-in-pdata.patch
+0112-video-da8xx-fb-reorganize-panel-detection.patch
+0113-video-da8xx-fb-minimal-dt-support.patch
+0114-video-da8xx-fb-invoke-platform-callback-safely.patch
+0115-video-da8xx-fb-obtain-fb_videomode-info-from-dt.patch
+0116-video-da8xx-fb-ensure-pdata-only-for-non-dt.patch
+0117-video-da8xx-fb-setup-struct-lcd_ctrl_config-for-dt.patch
+0118-video-da8xx-fb-CCF-clock-divider-handling.patch
+0119-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
+0120-Control-module-EHRPWM-clk-enabling.patch
+0121-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
+0122-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch
+0123-pwm-export-of_pwm_request.patch
+0124-pwm-pwm-tiehrpwm-Update-the-clock-handling-of-pwm-ti.patch
+0125-ARM-AM33XX-clk-Add-clock-node-for-EHRPWM-TBCLK.patch
+0126-HACK-am33xx.dtsi-turn-on-all-PWMs.patch
+0127-pwm-add-sysfs-interface.patch
+0128-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
+0129-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
+0130-ARM-OMAP2xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch
+0131-ARM-OMAP2xxx-hwmod-Add-DMA-support-for-SHAM-module.patch
+0132-ARM-OMAP3xxx-hwmod-Convert-SHAM-crypto-device-data-t.patch
+0133-ARM-OMAP2-Remove-unnecessary-message-when-no-SHA-IP-.patch
+0134-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch
+0135-ARM-AM33XX-Add-sha0-crypto-clock-data.patch
+0136-ARM-AM33XX-hwmod-Update-and-uncomment-SHA0-module-da.patch
+0137-ARM-dts-Add-SHAM-data-and-documentation-for-AM33XX.patch
+0138-ARM-OMAP2xxx-hwmod-Convert-AES-crypto-devcie-data-to.patch
+0139-ARM-OMAP3xxx-hwmod-Convert-AES-crypto-device-data-to.patch
+0140-ARM-OMAP2-Remove-unnecessary-message-when-no-AES-IP-.patch
+0141-ARM-OMAP2-Only-manually-add-hwmod-data-when-DT-not-u.patch
+0142-ARM-AM33XX-Add-aes0-crypto-clock-data.patch
+0143-ARM-AM33XX-hwmod-Update-and-uncomment-AES0-module-da.patch
+0144-ARM-dts-Add-AES-data-and-documentation-for-AM33XX.patch
+0145-crypto-omap-sham-Remove-unnecessary-pr_info-noise.patch
+0146-crypto-omap-sham-Convert-to-use-pm_runtime-API.patch
+0147-crypto-omap-sham-Add-suspend-resume-support.patch
+0148-crypto-omap-sham-Add-code-to-use-dmaengine-API.patch
+0149-crypto-omap-sham-Remove-usage-of-private-DMA-API.patch
+0150-crypto-omap-sham-Add-Device-Tree-Support.patch
+0151-crypto-omap-sham-Convert-to-dma_request_slave_channe.patch
+0152-crypto-omap-sham-Add-OMAP4-AM33XX-SHAM-Support.patch
+0153-crypto-omap-sham-Add-SHA224-and-SHA256-Support.patch
+0154-crypto-omap-aes-Remmove-unnecessary-pr_info-noise.patch
+0155-crypto-omap-aes-Don-t-reset-controller-for-every-ope.patch
+0156-crypto-omap-aes-Convert-to-use-pm_runtime-API.patch
+0157-crypto-omap-aes-Add-suspend-resume-support.patch
+0158-crypto-omap-aes-Add-code-to-use-dmaengine-API.patch
+0159-crypto-omap-aes-Remove-usage-of-private-DMA-API.patch
+0160-crypto-omap-aes-Add-Device-Tree-Support.patch
+0161-crypto-omap-aes-Convert-to-dma_request_slave_channel.patch
+0162-crypto-omap-aes-Add-OMAP4-AM33XX-AES-Support.patch
+0163-crypto-omap-aes-Add-CTR-algorithm-Support.patch
+0164-6lowpan-Refactor-packet-delivery-into-a-function.patch
+0165-6lowpan-Handle-uncompressed-IPv6-packets-over-6LoWPA.patch
+0166-wpan-whitespace-fix.patch
+0167-6lowpan-use-stack-buffer-instead-of-heap.patch
+0168-wpan-use-stack-buffer-instead-of-heap.patch
+0169-mrf24j40-pinctrl-support.patch
+0170-mrf24j40-Warn-if-transmit-interrupts-timeout.patch
+0171-mrf24j40-Increase-max-SPI-speed-to-10MHz.patch
+0172-mrf24j40-Fix-byte-order-of-IEEE-address.patch
+0173-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch
+0174-6lowpan-next-header-is-not-properly-set-upon-decompr.patch
+0175-6lowpan-always-enable-link-layer-acknowledgments.patch
+0176-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch
+0177-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch
+0178-6lowpan-fix-first-fragment-FRAG1-handling.patch
+0179-6lowpan-add-debug-messages-for-6LoWPAN-fragmentation.patch
+0180-6lowpan-store-fragment-tag-values-per-device-instead.patch
+0181-mac802154-add-mac802154_dev_get_dsn.patch
+0182-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch
+0183-6lowpan-use-the-PANID-provided-by-the-device-instead.patch
+0184-6lowpan-modify-udp-compression-uncompression-to-matc.patch
+0185-6lowpan-fix-a-small-formatting-issue.patch
+0186-6lowpan-use-IEEE802154_ADDR_LEN-instead-of-a-magic-n.patch
+0187-gpio-keys-Pinctrl-fy.patch
+0188-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
+0189-pwm-backlight-Pinctrl-fy.patch
+0190-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
+0191-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
+0192-beaglebone-enable-emmc-for-bonelt.patch
+0193-Fix-appended-dtb-rule.patch
+0194-deb-pkg-Simplify-architecture-matching-for-cross-bui.patch
+0195-Without-MACH_-option-Early-printk-DEBUG_LL.patch
+0196-ARM-7668-1-fix-memset-related-crashes-caused-by-rece.patch
+0197-ARM-7670-1-fix-the-memset-fix.patch
+0198-regulator-core-if-voltage-scaling-fails-restore-orig.patch
+0199-omap2-twl-common-Add-default-power-configuration.patch
+0200-omap2-irq-fix-interrupt-latency.patch
+0201-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch
+0202-video-add-timings-for-hd720.patch
+0203-Beagle-expansion-add-buddy-param-for-expansionboard-.patch
+0204-Beagle-expansion-add-zippy.patch
+0205-Beagle-expansion-add-zippy2.patch
+0206-Beagle-expansion-add-trainer.patch
+0207-Beagle-expansion-add-CircuitCo-ulcd-Support.patch
+0208-Beagle-expansion-add-wifi.patch
+0209-Beagle-expansion-add-beaglefpga.patch
+0210-Beagle-expansion-add-spidev.patch
+0211-Beagle-expansion-add-Aptina-li5m03-camera.patch
+0212-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch
+0213-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch
+0214-backlight-Add-TLC59108-backlight-control-driver.patch
+0215-tlc59108-adjust-for-beagleboard-uLCD7.patch
+0216-zeroMAP-Open-your-eyes.patch
+0217-ARM-OMAP-Beagle-use-TWL4030-generic-reset-script.patch
+0218-panda-fix-wl12xx-regulator.patch
+0219-ti-st-st-kim-fixing-firmware-path.patch
+0220-am33xx-cpsw-default-to-ethernet-hwaddr-from-efuse-if.patch
+0221-Attempted-SMC911x-BQL-patch.patch
+0222-cpsw-Fix-interrupt-storm-among-other-things.patch
+0223-beaglebone-TT3201-MCP2515-fixes.patch
+0224-add-proper-db.txt-for-CRDA.patch
+0225-mcp251x-add-device-tree-support.patch
+0226-am33xx-Add-clock-for-the-lcdc-DRM-driver.patch
+0227-drm-small-fix-in-drm_send_vblank_event.patch
+0228-drm-cma-add-debugfs-helpers.patch
+0229-drm-i2c-encoder-helper-wrappers.patch
+0230-drm-nouveau-use-i2c-encoder-helper-wrappers.patch
+0231-drm-i2c-give-i2c-it-s-own-Kconfig.patch
+0232-drm-tilcdc-add-TI-LCD-Controller-DRM-driver-v4.patch
+0233-drm-i2c-nxp-tda998x-v3.patch
+0234-drm-tilcdc-add-encoder-slave.patch
+0235-drm-tilcdc-add-support-for-LCD-panels-v5.patch
+0236-drm-lcdc-Power-control-GPIO-support.patch
+0237-drm-tilcdc-Fix-scheduling-while-atomic-from-irq-hand.patch
+0238-add-dvi-pinmuxes-to-am33xx.dtsi.patch
+0239-add-defconfig-file-to-use-as-.config.patch
+0240-am33xx-musb-Add-OF-definitions.patch
+0241-Mark-the-device-as-PRIVATE.patch
+0242-omap_hsmmc-Bug-fixes-pinctl-gpio-reset.patch
+0243-tps65217-bl-Locate-backlight-node-correctly.patch
+0244-arm-Export-cache-flush-management-symbols-when-MULTI.patch
+0245-am335x-bone-dtsi-Clean-up.patch
+0246-am335x-bone-dtsi-Introduce-new-I2C-entries.patch
+0247-am335x-dt-Add-I2C0-pinctrl-entries.patch
+0248-Cleanup-am33xx.dtsi.patch
+0249-Fix-platform-device-resource-linking.patch
+0250-Link-platform-device-resources-properly.patch
+0251-Properly-handle-resources-for-omap_devices.patch
+0252-omap-Avoid-crashes-in-the-case-of-hwmod-misconfigura.patch
+0253-i2c-EEPROM-In-kernel-memory-accessor-interface.patch
+0254-Fix-util_is_printable_string.patch
+0255-fdtdump-properly-handle-multi-string-properties.patch
+0256-dtc-Dynamic-symbols-fixup-support.patch
+0257-dtc-Add-DTCO-rule-for-DTB-objects.patch
+0258-OF-Compile-Device-Tree-sources-with-resolve-option.patch
+0259-firmware-update-.gitignore-with-dtbo-objects.patch
+0260-OF-Introduce-device-tree-node-flag-helpers.patch
+0261-OF-export-of_property_notify.patch
+0262-OF-Export-all-DT-proc-update-functions.patch
+0263-OF-Introduce-utility-helper-functions.patch
+0264-OF-Introduce-Device-Tree-resolve-support.patch
+0265-OF-Introduce-DT-overlay-support.patch
+0266-capemgr-Capemgr-makefiles-and-Kconfig-fragments.patch
+0267-capemgr-Beaglebone-capemanager.patch
+0268-capemgr-Add-beaglebone-s-cape-driver-bindings.patch
+0269-capemgr-am33xx-family-DT-bindings.patch
+0270-bone-geiger-Geiger-bone-driver.patch
+0271-capemgr-firmware-makefiles-for-DT-objects.patch
+0272-capemgr-emmc2-cape-definition.patch
+0273-capemgr-DVI-capes-definitions.patch
+0274-capemgr-Geiger-cape-definition.patch
+0275-capemgr-LCD3-cape-definition.patch
+0276-capemgr-Add-weather-cape-definition.patch
+0277-ehrpwm-add-missing-dts-nodes.patch
+0278-am33xx-DT-Update-am33xx.dsi-with-the-new-PWM-DT-bind.patch
+0279-geiger-cape-Update-to-using-the-new-PWM-interface.patch
+0280-lcd3-cape-Change-into-using-the-lcdc-DRM-driver-inst.patch
+0281-am33xx-Add-default-config.patch
+0282-lcd3-cape-Convert-to-using-the-proper-touchscreen-dr.patch
+0283-geiger-cape-Convert-to-using-the-new-ADC-driver.patch
+0284-cape-dvi-Convert-DVI-capes-to-the-new-LCDC-DRM-drive.patch
+0285-boneblack-Add-default-HDMI-cape.patch
+0286-cape-bone-dvi-Use-720p-mode-as-default.patch
+0287-am33xx.dtsi-Make-the-MUSB-not-crash-on-load.patch
+0288-regulator-DUMMY_REGULATOR-should-work-for-OF-too.patch
+0289-OF-Overlay-Remove-excessive-debugging-crud.patch
+0290-of-i2c-Export-single-device-registration-method.patch
+0291-OF-Overlay-I2C-client-devices-special-handling.patch
+0292-omap-Fix-bug-on-partial-resource-addition.patch
+0293-ASoC-davinci-mcasp-Add-pinctrl-support.patch
+0294-ASoC-Davinci-machine-Add-device-tree-binding.patch
+0295-am33xx-Add-mcasp0-and-mcasp1-device-tree-entries.patch
+0296-ASoC-dts-OMAP2-AM33xx-HACK-Add-missing-dma-info.patch
+0297-ASoC-Davinci-McASP-remove-unused-header-include.patch
+0298-ASoC-AM33XX-Add-support-for-AM33xx-SoC-Audio.patch
+0299-am33xx-mcasp-Add-dma-channel-definitions.patch
+0300-ARM-OMAP2-AM33xx-removed-invalid-McASP-HWMOD-data.patch
+0301-davinci-evm-Header-include-move-fix.patch
+0302-bone-dvi-cape-Add-DT-definition-for-00A2-revision.patch
+0303-bone-dvi-cape-Update-A1-cape-definition-with-sound.patch
+0304-sndsoc-mcasp-Get-DMA-channels-via-byname.patch
+0305-sound-soc-Davinci-Remove-__devinit-__devexit.patch
+0306-st7735fb-Remove-__devinit-__devexit.patch
+0307-capemgr-Remove-__devinit-__devexit.patch
+0308-capes-fw-target-firmware-directory-change.patch
+0309-am33xx-edma-Always-update-unused-channel-list.patch
+0310-defconfig-Update-bone-default-config.patch
+0311-capes-add-dvi-a2-and-lcd3-a2-dts-files.patch
+0312-capemgr-catch-up-with-lcdc-tilcdc-rename.patch
+0313-firmware-fix-dvi-a1-target.patch
+0314-capes-remove-tda-from-hdmi-cape-lcdc-handles-it-by-t.patch
+0315-tilcdc-magic-debug-statement-makes-power-gpio-work-o.patch
+0316-capemgr-add-dts-overlay-for-LCD7-00A2-cape.patch
+0317-HACK-am33xx.dtsi-enable-all-PWMs.patch
+0318-beaglebone-Add-nixie-cape-prototype-driver.patch
+0319-beaglebone-Add-nixie-cape-device-tree-entry.patch
+0320-am335x-bone-common.dtsi-Cleanup-test-remnants.patch
+0321-omap_hsmmc-Add-ti-vcc-aux-disable-is-sleep-DT-proper.patch
+0322-bone-common-ti-vcc-aux-disable-is-sleep-enable.patch
+0323-am33xx-disable-NAPI.patch
+0324-capemgr-Fixed-AIN-name-display-in-error-message.patch
+0325-am33xx.dtsi-remove-duplicate-nodes.patch
+0326-cape-dtbos-update-to-latest-OF-videomode-bindings.patch
+0327-beaglebone-uncomment-eMMC-override.patch
+0328-bone-capes-Update-with-new-tscadc-bindings.patch
+0329-am33xx.dtsi-Update-and-disable-status-of-nodes.patch
+0330-bone-capes-Adapt-to-new-pwms-setup.patch
+0331-tilcdc-introduce-panel-tfp410-power-down-gpio-contro.patch
+0332-bone-dvi-Update-to-new-style-tilcdc-bindings.patch
+0333-tilcdc-tfp410-Rework-power-down-GPIO-logic.patch
+0334-tilcdc-Add-reduced-blanking-mode-checks.patch
+0335-cape-dvi-Switch-all-DVI-capes-to-using-the-TFTP410-p.patch
+0336-beaglebone-switch-eMMC-to-8bit-mode.patch
+0337-Pinmux-helper-driver.patch
+0338-OF-Clear-detach-flag-on-attach.patch
+0339-OF-overlay-Fix-overlay-revert-failure.patch
+0340-bone-capemgr-Make-sure-cape-removal-works.patch
+0341-bone-capemgr-Fix-crash-when-trying-to-remove-non-exi.patch
+0342-beaglebone-LCD7-cape-enable-PWM-and-allow-the-specif.patch
+0343-bone-capemgr-Introduce-pinmux-helper.patch
+0344-bone-geiger-Fix-comment-to-match-the-contents.patch
+0345-of-overlay-Handle-I2C-devices-already-registered-by-.patch
+0346-pinmux-helper-Add-runtime-configuration-capability.patch
+0347-pinmux-helper-Switch-to-using-kmalloc.patch
+0348-i2c-DTify-pca954x-driver.patch
+0349-tty-Add-JHD629-I2C-LCD-Keypad-TTY-driver.patch
+0350-grove-i2c-Add-rudimentary-grove-i2c-motor-control-dr.patch
+0351-tty-jhd629-i2c-Clean-keypad-buffer-when-starting.patch
+0352-am335x-bone-common-Remove-SPI-unused-pinmux-config.patch
+0353-bone-capemgr-Force-a-slot-to-load-unconditionally.patch
+0354-beaglebone-Added-Adafruit-prototype-cape.patch
+0355-tilcdc-Enable-reduced-blanking-check-only-on-DVI-sla.patch
+0356-cape-adafruit-Use-the-correct-spi-bus-spi1-no-spi0.patch
+0357-BBB-tester-Introduce-board-DTS.patch
+0358-BBB-tester-Introduce-cape-describing-the-contents-of.patch
+0359-bone-tester-Add-overrides-for-BB-BONE-TESTER.patch
+0360-cape-tester-Add-uart-specific-default-pinmux-state.patch
+0361-cape-tester-Add-pinmux-helper-for-drvvbus-gpio.patch
+0362-cape-Added-support-for-IIO-helper-cape.patch
+0363-cape-Added-example-IIO-tester-dynamics-overlay.patch
+0364-docs-Added-capemanager-extra_override-usage.patch
+0365-capemgr-Added-module-param-descriptions.patch
+0366-beaglebone-Add-Adafruit-RTC-prototype-cape.patch
+0367-cape-vsense-scale-division-by-zero-check.patch
+0368-capes-add-cape-for-beaglebone-based-Hexy-robot.patch
+0369-Extend-bone-iio-helper.patch
+0370-Update-iio-helper-with-more-channels.patch
+0371-Add-ADC-IIO-helper.patch
+0372-Changing-DT-data-to-make-selection-of-standard-i.e.-.patch
+0373-Enhancing-to-support-extra-device-tree-options-for-t.patch
+0374-add-WIP-support-LCD4-rev-00A4.patch
+0375-add-eMMC-cape-support.patch
+0376-Remove-UART-pins-from-the-expansion-set.patch
+0377-Remove-LCD-pins-from-the-expansion-test-part.patch
+0378-Remove-I2C2-pins-from-expansion-test.patch
+0379-Add-expansion-test-cape-fragment.patch
+0380-tilcdc-added-some-extra-debug-and-softened-the-wordi.patch
+0381-Make-sure-various-timings-fit-within-the-bits-availa.patch
+0382-fix-cape-bone-hexy.patch
+0383-firmware-DT-Fragment-for-MRF24J40-BeagleBone-Cape.patch
+0384-firmware-capes-Update-MRF24J40-cape-to-work-with-lat.patch
+0385-am335x-bone-common-DT-Override-for-MRF24J40-Cape.patch
+0386-beaglebone-black-limit-LDO3-to-1.8V.patch
+0387-beaglebone-black-add-new-fixed-regulator-for-uSD-eMM.patch
+0388-capemgr-Implement-disable-overrides-on-the-cmd-line.patch
+0389-tilcdc-Enable-pinmux-states.patch
+0390-cape-Add-a-simple-cape-for-handling-the-uSD-button.patch
+0391-beaglebone-add-support-for-DVI-00A3.patch
+0392-beaglebone-remove-audio-section-from-DVID-rev-2-and-.patch
+0393-beaglebone-add-dts-for-audio-cape.patch
+0394-cape-bone-hexy-add-iio-helper.patch
+0395-cape-Add-CAPE-BONE-EXPTEST-to-capemaps.patch
+0396-tester-button-cape.patch
+0397-pwm_test-fix-some-issues.patch
+0398-pwm_test-Clean-up-and-make-it-work-on-DT-correctly.patch
+0399-capes-Add-PWM-test-example-cape.patch
+0400-Sync-tester-DTS-with-am335x-common.patch
+0401-Add-in-missing-cape-bone-tester-back-in.patch
+0402-cape-bone-hexy-move-OLED-to-different-reset-gpio.patch
+0403-firmware-capes-added-dts-file-for-every-PWM-pin.patch
+0404-capes-add-LCD7-A3.patch
+0405-capes-add-basic-support-for-LCD4-capes.patch
+0406-OF-overlay-Add-depth-option-for-device-creation.patch
+0407-capes-Add-BB-BONE-GPEVT-cape.patch
+0408-clock-Export-__clock_set_parent.patch
+0409-omap-clk-Add-adjustable-clkout2.patch
+0410-am33xx-Update-DTS-EDMA.patch
+0411-bone-Added-RS232-prototype-cape-DT-object.patch
+0412-Add-support-for-BB-BONE_SERL-01-00A1-CanBus-cape.patch
+0413-capes-Add-virtual-capes-serving-as-examples.patch
+0414-capes-Add-TowerTech-TT3201-CAN-Bus-Cape-TT3201-001-3.patch
+0415-capes-Add-commented-out-example-of-use-of-spi1_cs1.patch
+0416-cape-LCD4-Correct-key-active-polarity.patch
+0417-capes-lcd3-Correct-button-polarity.patch
+0418-cape-Fix-LCD7-keys-polarity.patch
+0419-gpio-Introduce-GPIO-OF-helper.patch
+0420-capes-ADC-GPIO-helper-capes.patch
+0421-capes-RS232-Cape-support-added.patch
+0422-uio-uio_pruss-port-to-AM33xx.patch
+0423-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch
+0424-ARM-dts-AM33xx-PRUSS-support.patch
+0425-uio_pruss-add-dt-support-replicape-00A1.patch
+0426-pruss-Make-sure-it-works-when-no-child-nodes-are-pre.patch
+0427-am33xx-pru-Very-simple-led-cape-via-GPO-of-the-PRU.patch
+0428-PRU-remote-proc-wip.patch
+0429-Add-sysfs-entry-for-DDR-sync.patch
+0430-virtio-ring-Introduce-dma-mapping-for-real-devices.patch
+0431-virtio_console-Simplify-virtio_console-for-h-w-devic.patch
+0432-rpmsg-Make-the-buffers-number-and-size-configurable.patch
+0433-remoteproc-Use-driver-ops-for-allocation-of-virtqueu.patch
+0434-rproc-core-Allow-bootup-without-resources.patch
+0435-tools-virtio-fix-build-for-3.8.patch
+0436-rproc-pru-PRU-remoteproc-updated-to-work-with-virtio.patch
+0437-capes-pru-Update-with-PRU-03-PRU-04.patch
+0438-rproc-PRU-Add-downcall-RPC-capability.patch
+0439-rproc-pru-Implement-a-software-defined-PWM-channel-s.patch
+0440-capes-PRU-PWM-channels-information.patch
+0441-drivers-usb-phy-add-a-new-driver-for-usb-part-of-con.patch
+0442-drivers-usb-start-using-the-control-module-driver.patch
+0443-usb-otg-Add-an-API-to-bind-the-USB-controller-and-PH.patch
+0444-usb-otg-utils-add-facilities-in-phy-lib-to-support-m.patch
+0445-ARM-OMAP-USB-Add-phy-binding-information.patch
+0446-drivers-usb-musb-omap-make-use-of-the-new-PHY-lib-AP.patch
+0447-usb-otg-add-device-tree-support-to-otg-library.patch
+0448-USB-MUSB-OMAP-get-PHY-by-phandle-for-dt-boot.patch
+0449-MUSB-Hack-around-to-make-host-port-to-work.patch
+0450-make-sure-we-register-unregister-the-NOP-xceiver-onl.patch
+0451-ARM-OMAP-am335x-musb-use-250-for-power.patch
+0452-ARM-OMAP2-MUSB-Specify-omap4-has-mailbox.patch
+0453-usb-musb-avoid-stopping-the-session-in-host-mode.patch
+0454-beaglebone-black-1ghz-hack.patch
+0455-ARM-AM33xx-Add-SoC-specific-restart-hook.patch
+0456-iio-common-Add-STMicroelectronics-common-library.patch
+0457-iio-accel-Add-STMicroelectronics-accelerometers-driv.patch
+0458-iio-gyro-Add-STMicroelectronics-gyroscopes-driver.patch
+0459-iio-magnetometer-Add-STMicroelectronics-magnetometer.patch
+0460-iio-magn-Add-sensors_supported-in-st_magn_sensors.patch
+0461-pwm-pca9685-skeleton-i2c-client-driver-for-PCA9685-1.patch
+0462-Invensense-MPU6050-Device-Driver.patch
+0463-iio-imu-inv_mpu6050-depends-on-IIO_BUFFER.patch
+0464-using-kfifo_in_spinlocked-instead-of-separate-code.patch
+0465-W1-w1-gpio-switch-to-using-dev_pm_ops.patch
+0466-W1-w1-gpio-guard-DT-IDs-with-CONFIG_OF.patch
+0467-W1-w1-gpio-rework-handling-of-platform-data.patch
+0468-W1-w1-gpio-switch-to-using-managed-resources-devm.patch
+0469-ARM-OMAP-Clear-GPMC-bits-when-applying-new-setting.patch
+0470-ARM-omap2-gpmc-Mark-local-scoped-functions-static.patch
+0471-ARM-omap2-gpmc-Remove-unused-gpmc_round_ns_to_ticks-.patch
+0472-ARM-omap2-gpmc-Fix-gpmc_cs_reserved-return-value.patch
+0473-ARM-omap2-gpmc-nand-Print-something-useful-on-CS-req.patch
+0474-ARM-omap2-gpmc-onenand-Print-something-useful-on-CS-.patch
+0475-ARM-omap2-gpmc-onenand-Replace-pr_err-with-dev_err.patch
+0476-ARM-omap2-gpmc-onenand-Replace-printk-KERN_ERR-with-.patch
+0477-ARM-omap2-gpmc-Remove-redundant-chip-select-out-of-r.patch
+0478-ARM-OMAP2-Simplify-code-configuring-ONENAND-devices.patch
+0479-ARM-OMAP2-Add-variable-to-store-number-of-GPMC-waitp.patch
+0480-ARM-OMAP2-Add-structure-for-storing-GPMC-settings.patch
+0481-ARM-OMAP2-Add-function-for-configuring-GPMC-settings.patch
+0482-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch
+0483-ARM-OMAP2-Convert-NAND-to-use-gpmc_cs_program_settin.patch
+0484-ARM-OMAP2-Convert-SMC91x-to-use-gpmc_cs_program_sett.patch
+0485-ARM-OMAP2-Convert-TUSB-to-use-gpmc_cs_program_settin.patch
+0486-ARM-OMAP2-Don-t-configure-of-chip-select-options-in-.patch
+0487-ARM-OMAP2-Add-function-to-read-GPMC-settings-from-de.patch
+0488-ARM-OMAP2-Add-additional-GPMC-timing-parameters.patch
+0489-ARM-OMAP2-Add-device-tree-support-for-NOR-flash.patch
+0490-ARM-OMAP2-Convert-NAND-to-retrieve-GPMC-settings-fro.patch
+0491-ARM-OMAP2-Convert-ONENAND-to-retrieve-GPMC-settings-.patch
+0492-ARM-OMAP2-Detect-incorrectly-aligned-GPMC-base-addre.patch
+0493-ARM-OMAP2-Remove-unnecesssary-GPMC-definitions-and-v.patch
+0494-ARM-OMAP2-Allow-GPMC-probe-to-complete-even-if-CS-ma.patch
+0495-ARM-OMAP2-return-ENODEV-if-GPMC-child-device-creatio.patch
+0496-ARM-OMAP2-rename-gpmc_probe_nor_child-to-gpmc_probe_.patch
+0497-ARM-OMAP2-Add-GPMC-DT-support-for-Ethernet-child-nod.patch
+0498-mtd-omap-nand-pass-device_node-in-platform-data.patch
+0499-ARM-OMAP-gpmc-nand-drop-__init-annotation.patch
+0500-ARM-OMAP-gpmc-enable-hwecc-for-AM33xx-SoCs.patch
+0501-ARM-OMAP-gpmc-don-t-create-devices-from-initcall-on-.patch
+0502-ARM-OMAP2-gpmc-onenand-drop-__init-annotation.patch
+0503-gpmc-Add-missing-gpmc-includes.patch
+0504-mtd-omap-onenand-pass-device_node-in-platform-data.patch
+0505-ARM-OMAP2-Convert-ONENAND-to-use-gpmc_cs_program_set.patch
+0506-omap-gpmc-Various-driver-fixes.patch
+0507-gpmc-Add-DT-node-for-gpmc-on-am33xx.patch
+0508-CHROMIUM-Input-atmel_mxt_ts-refactor-i2c-error-handl.patch
+0509-CHROMIUM-Input-atmel_mxt_ts-register-input-device-be.patch
+0510-CHROMIUM-Input-atmel_mxt_ts-refactor-input-device-cr.patch
+0511-CHROMIUM-Input-atmel_mxt_ts-handle-bootloader-mode-a.patch
+0512-CHROMIUM-Input-atmel_mxt_ts-handle-errors-during-fw-.patch
+0513-CHROMIUM-Input-atmel_mxt_ts-destroy-state-before-fw-.patch
+0514-CHROMIUM-Input-atmel_mxt_ts-refactor-bootloader-entr.patch
+0515-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-assert-in-m.patch
+0516-CHROMIUM-Input-atmel_mxt_ts-wait-for-CHG-after-bootl.patch
+0517-CHROMIUM-Input-atmel_mxt_ts-change-MXT_BOOT_LOW-to-0.patch
+0518-CHROMIUM-Input-atmel_mxt_ts-Increase-FWRESET_TIME.patch
+0519-CHROMIUM-Input-atmel_mxt_ts-add-calibrate-sysfs-entr.patch
+0520-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch
+0521-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-to-read-.patch
+0522-CHROMIUM-Input-atmel_mxt_ts-verify-info-block-checks.patch
+0523-CHROMIUM-Input-atmel_mxt_tx-add-matrix_size-sysfs-en.patch
+0524-CHROMIUM-Input-atmel_mxt_ts-define-helper-functions-.patch
+0525-CHROMIUM-Input-atmel_mxt_ts-add-debugfs-infrastructu.patch
+0526-CHROMIUM-Input-atmel_mxt_ts-add-deltas-and-refs-debu.patch
+0527-CHROMIUM-Input-atmel_mxt_ts-add-device-id-for-touchp.patch
+0528-CHROMIUM-Input-atmel_mxt_ts-Read-resolution-from-dev.patch
+0529-CHROMIUM-Input-atmel_mxt_ts-Report-TOUCH-MAJOR-in-te.patch
+0530-CHROMIUM-Input-atmel_mxt_ts-add-new-object-types.patch
+0531-CHROMIUM-INPUT-atmel_mxt_ts-Increase-the-wait-times-.patch
+0532-CHROMIUM-Input-atmel_mxt_ts-dump-mxt_read-write_reg.patch
+0533-CHROMIUM-Input-atmel_mxt_ts-take-an-instance-for-mxt.patch
+0534-CHROMIUM-Input-atmel_mxt_ts-allow-writing-to-object-.patch
+0535-CHROMIUM-Input-atmel_mxt_ts-add-backupnv-sysfs-entry.patch
+0536-CHROMIUM-Input-atmel_mxt_ts-read-num-messages-then-a.patch
+0537-CHROMIUM-Input-atmel_mxt_ts-remove-mxt_make_highchg.patch
+0538-CHROMIUM-Input-atmel_mxt_ts-Remove-matrix-size-updat.patch
+0539-CHROMIUM-Input-atmel_mxt_ts-parse-vector-field-of-da.patch
+0540-CHROMIUM-Input-atmel_mxt_ts-Add-IDLE-DEEP-SLEEP-mode.patch
+0541-CHROMIUM-Input-atmel_mxt_ts-Move-object-from-sysfs-t.patch
+0542-CHROMIUM-Input-atmel_mxt_ts-Set-default-irqflags-whe.patch
+0543-CHROMIUM-Input-atmel_mxt_ts-Support-the-case-with-no.patch
+0544-CHROMIUM-Input-atmel_mxt_ts-Wait-on-auto-calibration.patch
+0545-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch
+0546-CHROMIUM-Input-atmel_mxt_ts-Add-sysfs-entry-for-r-w-.patch
+0547-CHROMIUM-Input-atmel_mxt_ts-add-sysfs-entry-for-writ.patch
+0548-CHROMIUM-Input-atmel_mxt_ts-make-mxt_initialize-asyn.patch
+0549-CHROMIUM-Input-atmel_mxt_ts-move-backup_nv-to-handle.patch
+0550-CHROMIUM-Input-atmel_mxt_ts-Add-defines-for-T9-Touch.patch
+0551-CHROMIUM-Input-atmel_mxt_ts-disable-reporting-on-sto.patch
+0552-CHROMIUM-Input-atmel_mxt_ts-Suppress-handle-messages.patch
+0553-CHROMIUM-Input-atmel_mxt_ts-save-and-restore-t9_ctrl.patch
+0554-CHROMIUM-Input-atmel_mxt_ts-enable-RPTEN-if-can-wake.patch
+0555-CHROMIUM-Input-atmel_mxt_ts-release-all-fingers-on-r.patch
+0556-CHROMIUM-Input-atmel_mxt_ts-make-suspend-power-acqui.patch
+0557-CHROMIUM-Input-atmel_mxt_ts-recalibrate-on-system-re.patch
+0558-CHROMIUM-Input-atmel_mxt_ts-Use-correct-max-touch_ma.patch
+0559-CHROMIUM-Input-atmel_mxt_ts-Add-support-for-T65-Lens.patch
+0560-CHROMIUM-Input-atmel_mxt_ts-On-Tpads-enable-T42-disa.patch
+0561-CHROMIUM-Input-atmel_mxt_ts-Set-power-wakeup-to-disa.patch
+0562-CHROMIUM-Input-atmel_mxt_ts-mxt_stop-on-lid-close.patch
+0563-CHROMIUM-Input-atmel_mxt_ts-Disable-T9-on-mxt_stop.patch
+0564-CHROMIUM-Input-atmel_mxt_ts-Set-T9-in-mxt_resume-bas.patch
+0565-video-ssd1307fb-Add-support-for-SSD1306-OLED-control.patch
+0566-ssd1307fb-Rework-the-communication-functions.patch
+0567-ssd1307fb-Speed-up-the-communication-with-the-contro.patch
+0568-ssd1307fb-Make-use-of-horizontal-addressing-mode.patch
+0569-SSD1307fb-1Hz-8Hz-defio-updates.patch
+0570-ARM-force-march-armv7a-for-thumb2-builds-http-lists..patch
+0571-headers_install-Fix-build-failures-on-deep-directory.patch
+0572-libtraceevent-Remove-hard-coded-include-to-usr-local.patch
+0573-Make-single-.dtb-targets-also-with-DTC_FLAGS.patch
+0574-video-Add-generic-HDMI-infoframe-helpers.patch
+0575-BeagleBone-Black-TDA998x-Initial-HDMI-Audio-support.patch
+0576-Clean-up-some-formating-and-debug-in-Davinci-MCASP-d.patch
+0577-tilcdc-Prune-modes-that-can-t-support-audio.patch
+0578-Enable-output-of-correct-AVI-Infoframe-type-hdmi.patch
+0579-drm-am335x-add-support-for-2048-lines-vertical.patch
+0580-drm-tda998x-Adding-extra-CEA-mode-for-1920x1080-24.patch
+0581-tilcdc-Remove-superfluous-newlines-from-DBG-messages.patch
+0582-tilcdc-1280x1024x60-bw-1920x1080x24-bw.patch
+0583-tilcdc-Only-support-Audio-on-50-60-Hz-modes.patch
+0584-drm-i2c-nxp-tda998x-fix-EDID-reading-on-TDA19988-dev.patch
+0585-tilcdc-Allow-non-audio-modes-when-we-don-t-support-t.patch
+0586-drm-i2c-nxp-tda998x-ensure-VIP-output-mux-is-properl.patch
+0587-drm-i2c-nxp-tda998x-fix-npix-nline-programming.patch
+0588-drm-tilcdc-Clear-bits-of-register-we-re-going-to-set.patch
+0589-DRM-tda998x-add-missing-include.patch
+0590-drm-i2c-nxp-tda998x-prepare-for-video-input-configur.patch
+0591-WIP-of-new-tda998x-patches.patch
+0592-tilcdc-Slave-panel-settings-read-from-DT-now.patch
+0593-drm-tda998x-Revert-WIP-to-previous-state.patch
+0594-tilcdc-More-refined-audio-mode-compatibility-check.patch
+0595-drm-tilcdc-Implement-whitelist-blacklist-mode-suppor.patch
+0596-boneblack-Remove-default-pinmuxing-for-MMC1.patch
+0597-capemgr-Implement-cape-priorities.patch
+0598-rstctl-Reset-control-subsystem.patch
+0599-omap_hsmmc-Enable-rstctl-bindings.patch
+0600-bone-Add-rstctl-DT-binding-for-beaglebone.patch
+0601-bone-eMMC-Add-rstctl-rstctl-DT-bindings.patch
+0602-capes-Add-testing-capes-for-rstctl.patch
+0603-omap_hsmmc-Bail-out-when-rstctl-error-is-unrecoverab.patch
+0604-bone-Put-priorities-in-built-in-capes.patch
+0605-bone-common-dtsi-remove-reset-cape.patch
+0606-mmc-add-missing-select-RSTCTL-in-MMC_OMAP.patch
+0607-soc_camera-QL-mt9l112-camera-driver-for-the-beaglebo.patch
+0608-capes-Add-BB-BONE-CAM3-cape.patch
+0609-cssp_camera-Correct-license-identifier.patch
+0610-cssp_camera-increase-delays-make-sensor-detection-wo.patch
+0611-mt9t112-forward-port-optimizations-from-Angstrom-3.2.patch
+0612-cssp_camera-Use-flip-if-available.patch
+0613-cssp_camera-Fix-it-for-small-resolutions.patch
+0614-cssp_camera-Increase-delay-after-enabling-clocks-to-.patch
+0615-Debugging-camera-stuff.patch
+0616-cssp_camera-Make-it-work-with-Beaglebone-black.patch
+0617-bone-capemgr-Introduce-simple-resource-tracking.patch
+0618-capes-Add-resources-to-capes.patch
+0619-capes-Update-most-of-the-capes-with-resource-definit.patch
+0620-capes-Update-RS232-CAN-capes-with-resources.patch
+0621-capemgr-Add-enable_partno-parameter.patch
+0622-cape-GPIOHELP-use-correct-part-number.patch
+0623-bbb-Add-a-fall-back-non-audio-HDMI-cape.patch
+0624-capes-HDMI-slaves-need-panel-settings.patch
+0625-capes-boneblack-HDMI-capes-have-blacklisted-modes.patch
+0626-capes-LCD7-Fix-definitions.patch
+0627-capes-LCD7-Fix-enter-key-pinmux.patch
+0628-Fix-timings-for-LCD3-cape.patch
+0629-capes-LCD-capes-updated-with-timing-fixes.patch
+0630-Fix-mmc2-being-enabled-when-eMMC-is-disabled.patch
+0631-capes-LCD7-fix-vsync-len-off-by-one.patch
+0632-LCD-capes-set-default-brightness-to-100.patch
+0633-lcd-capes-update-adc-channels.patch
+0634-bone-renamed-adafruit-RTC-cape.patch
+0635-bone-add-PPS-to-BB-BONE-RTC-cape.patch
+0636-firmware-remove-rule-for-cape-bone-adafruit-lcd-00A0.patch
+0637-tps65217-Enable-KEY_POWER-press-on-AC-loss-PWR_BUT.patch
+0638-dt-bone-common-Add-interrupt-for-PMIC.patch
+0639-drivers-pps-clients-pps-gpio.c-convert-to-module_pla.patch
+0640-drivers-pps-clients-pps-gpio.c-convert-to-devm_-help.patch
+0641-pps-gpio-add-device-tree-binding-and-support.patch
+0642-leds-leds-pwm-Convert-to-use-devm_get_pwm.patch
+0643-leds-leds-pwm-Preparing-the-driver-for-device-tree-s.patch
+0644-leds-leds-pwm-Simplify-cleanup-code.patch
+0645-leds-leds-pwm-Add-device-tree-bindings.patch
+0646-leds-leds-pwm-Defer-led_pwm_set-if-PWM-can-sleep.patch
+0647-leds-pwm-Enable-compilation-on-this-version-of-the-k.patch
+0648-capes-Add-bacon-cape.patch
+0649-cape-bacon-Cosmetic-change-of-the-adc-helper-name.patch
+0650-cape-bacon-educational-edition.patch
+0651-capes-bacon-Update-with-new-ADC-driver-method.patch
+0652-capes-BACON-Educational-cape-with-free-form-muxing.patch
+0653-firmware-add-BeBoPr-cape.patch
+# umpf-release: distrokit/beaglebone/20130720
+# umpf-topic-range: 6fbec96b98a35ba475bb821a60c903566f35a575..cf474a9f0f33aea786d56c1f447d4a837f754a0f
+0701-Release-distrokit-beaglebone-20130720.patch
+# umpf-end