brcm2708: update to latest version
authorÁlvaro Fernández Rojas <noltari@gmail.com>
Thu, 7 Apr 2016 19:25:10 +0000 (21:25 +0200)
committerÁlvaro Fernández Rojas <noltari@gmail.com>
Thu, 7 Apr 2016 19:25:10 +0000 (21:25 +0200)
As usual these patches were extracted from the raspberry pi repo:
https://github.com/raspberrypi/linux/commits/rpi-4.4.y

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
376 files changed:
target/linux/brcm2708/bcm2708/config-4.4
target/linux/brcm2708/bcm2709/config-4.4
target/linux/brcm2708/bcm2710/config-4.4
target/linux/brcm2708/image/Makefile
target/linux/brcm2708/image/config.txt
target/linux/brcm2708/patches-4.4/0001-smsx95xx-fix-crimes-against-truesize.patch
target/linux/brcm2708/patches-4.4/0002-smsc95xx-Disable-turbo-mode-by-default.patch
target/linux/brcm2708/patches-4.4/0003-vmstat-Workaround-for-issue-where-dirty-page-count-g.patch
target/linux/brcm2708/patches-4.4/0004-BCM2835_DT-Fix-I2S-register-map.patch
target/linux/brcm2708/patches-4.4/0005-irq-bcm2836-Prevent-spurious-interrupts-and-trap-the.patch
target/linux/brcm2708/patches-4.4/0006-irqchip-bcm2835-Add-FIQ-support.patch
target/linux/brcm2708/patches-4.4/0007-irqchip-irq-bcm2835-Add-2836-FIQ-support.patch
target/linux/brcm2708/patches-4.4/0008-serial-8250-Don-t-crash-when-nr_uarts-is-0.patch
target/linux/brcm2708/patches-4.4/0009-pinctrl-bcm2835-Set-base-to-0-give-expected-gpio-num.patch
target/linux/brcm2708/patches-4.4/0010-pinctrl-bcm2835-Fix-interrupt-handling-for-GPIOs-28-.patch
target/linux/brcm2708/patches-4.4/0011-pinctrl-bcm2835-Only-request-the-interrupts-listed-i.patch
target/linux/brcm2708/patches-4.4/0012-spi-bcm2835-Support-pin-groups-other-than-7-11.patch
target/linux/brcm2708/patches-4.4/0013-ARM-bcm2835-Set-Serial-number-and-Revision.patch
target/linux/brcm2708/patches-4.4/0014-bcm2835-i2s-get-base-address-for-DMA-from-devicetree.patch
target/linux/brcm2708/patches-4.4/0015-bcm2835-i2s-add-24bit-support-update-bclk_ratio-to-m.patch
target/linux/brcm2708/patches-4.4/0016-bcm2835-i2s-setup-clock-only-if-CPU-is-clock-master.patch
target/linux/brcm2708/patches-4.4/0017-bcm2835-i2s-Eliminate-debugfs-directory-error.patch
target/linux/brcm2708/patches-4.4/0018-bcm2835-i2s-Register-PCM-device.patch
target/linux/brcm2708/patches-4.4/0019-bcm2835-i2s-Enable-MMAP-support-via-a-DT-property.patch
target/linux/brcm2708/patches-4.4/0020-dmaengine-bcm2835-Add-slave-dma-support.patch
target/linux/brcm2708/patches-4.4/0021-dmaengine-bcm2835-set-residue_granularity-field.patch
target/linux/brcm2708/patches-4.4/0022-dmaengine-bcm2835-Load-driver-early-and-support-lega.patch
target/linux/brcm2708/patches-4.4/0023-bcm2835-dma-Fix-dreq-not-set-for-slave-transfers.patch
target/linux/brcm2708/patches-4.4/0024-bcm2835-dma-Limit-cyclic-transfers-on-lite-channels-.patch
target/linux/brcm2708/patches-4.4/0025-bcm2835-Add-support-for-uart1.patch
target/linux/brcm2708/patches-4.4/0026-firmware-bcm2835-Add-missing-property-tags.patch
target/linux/brcm2708/patches-4.4/0027-Main-bcm2708-bcm2709-linux-port.patch
target/linux/brcm2708/patches-4.4/0028-squash-include-ARCH_BCM2708-ARCH_BCM2709.patch
target/linux/brcm2708/patches-4.4/0029-Add-dwc_otg-driver.patch
target/linux/brcm2708/patches-4.4/0030-bcm2708-framebuffer-driver.patch
target/linux/brcm2708/patches-4.4/0031-dmaengine-Add-support-for-BCM2708.patch
target/linux/brcm2708/patches-4.4/0032-Add-blk_pos-parameter-to-mmc-multi_io_quirk-callback.patch [deleted file]
target/linux/brcm2708/patches-4.4/0032-MMC-added-alternative-MMC-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0033-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0033-MMC-added-alternative-MMC-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0034-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch [deleted file]
target/linux/brcm2708/patches-4.4/0034-cma-Add-vc_cma-driver-to-enable-use-of-CMA.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0035-bcm2708-alsa-sound-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0035-cma-Add-vc_cma-driver-to-enable-use-of-CMA.patch [deleted file]
target/linux/brcm2708/patches-4.4/0036-bcm2708-alsa-sound-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0036-bcm2708-vchiq-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0037-bcm2708-vchiq-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0037-vc_mem-Add-vc_mem-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0038-vc_mem-Add-vc_mem-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0038-vcsm-VideoCore-shared-memory-service-for-BCM2835.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0039-Add-dev-gpiomem-device-for-rootless-user-GPIO-access.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0039-vcsm-VideoCore-shared-memory-service-for-BCM2835.patch [deleted file]
target/linux/brcm2708/patches-4.4/0040-Add-SMI-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0040-Add-dev-gpiomem-device-for-rootless-user-GPIO-access.patch [deleted file]
target/linux/brcm2708/patches-4.4/0041-Add-SMI-NAND-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0041-Add-SMI-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0042-Add-SMI-NAND-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0042-lirc-added-support-for-RaspberryPi-GPIO.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0043-Add-cpufreq-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0043-lirc-added-support-for-RaspberryPi-GPIO.patch [deleted file]
target/linux/brcm2708/patches-4.4/0044-Add-cpufreq-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0044-Added-hwmon-thermal-driver-for-reporting-core-temper.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0045-Add-Chris-Boot-s-i2c-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0045-Added-hwmon-thermal-driver-for-reporting-core-temper.patch [deleted file]
target/linux/brcm2708/patches-4.4/0046-Add-Chris-Boot-s-i2c-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0046-char-broadcom-Add-vcio-module.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0047-char-broadcom-Add-vcio-module.patch [deleted file]
target/linux/brcm2708/patches-4.4/0047-firmware-bcm2835-Support-ARCH_BCM270x.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0048-bcm2835-add-v4l2-camera-device.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0048-firmware-bcm2835-Support-ARCH_BCM270x.patch [deleted file]
target/linux/brcm2708/patches-4.4/0049-bcm2835-add-v4l2-camera-device.patch [deleted file]
target/linux/brcm2708/patches-4.4/0049-scripts-Add-mkknlimg-and-knlinfo-scripts-from-tools-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0050-fdt-Add-support-for-the-CONFIG_CMDLINE_EXTEND-option.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0050-scripts-Add-mkknlimg-and-knlinfo-scripts-from-tools-.patch [deleted file]
target/linux/brcm2708/patches-4.4/0051-BCM2708-Add-core-Device-Tree-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0051-fdt-Add-support-for-the-CONFIG_CMDLINE_EXTEND-option.patch [deleted file]
target/linux/brcm2708/patches-4.4/0052-BCM2708-Add-core-Device-Tree-support.patch [deleted file]
target/linux/brcm2708/patches-4.4/0052-bcm2835-Match-with-BCM2708-Device-Trees.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0053-bcm2835-Match-with-BCM2708-Device-Trees.patch [deleted file]
target/linux/brcm2708/patches-4.4/0053-fbdev-add-FBIOCOPYAREA-ioctl.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0054-fbdev-add-FBIOCOPYAREA-ioctl.patch [deleted file]
target/linux/brcm2708/patches-4.4/0057-Speed-up-console-framebuffer-imageblit-function.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0058-Allow-mac-address-to-be-set-in-smsc95xx.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0058-Speed-up-console-framebuffer-imageblit-function.patch [deleted file]
target/linux/brcm2708/patches-4.4/0059-Allow-mac-address-to-be-set-in-smsc95xx.patch [deleted file]
target/linux/brcm2708/patches-4.4/0059-enabling-the-realtime-clock-1-wire-chip-DS1307-and-1.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0060-Added-Device-IDs-for-August-DVB-T-205.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0060-enabling-the-realtime-clock-1-wire-chip-DS1307-and-1.patch [deleted file]
target/linux/brcm2708/patches-4.4/0061-Added-Device-IDs-for-August-DVB-T-205.patch [deleted file]
target/linux/brcm2708/patches-4.4/0061-config-Enable-CONFIG_MEMCG-but-leave-it-disabled-due.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0062-ASoC-Add-support-for-PCM5102A-codec.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0062-config-Enable-CONFIG_MEMCG-but-leave-it-disabled-due.patch [deleted file]
target/linux/brcm2708/patches-4.4/0063-ASoC-Add-support-for-HifiBerry-DAC.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0063-ASoC-Add-support-for-PCM5102A-codec.patch [deleted file]
target/linux/brcm2708/patches-4.4/0064-ASoC-Add-support-for-HifiBerry-DAC.patch [deleted file]
target/linux/brcm2708/patches-4.4/0064-ASoC-Add-support-for-Rpi-DAC.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0065-ASoC-Add-support-for-Rpi-DAC.patch [deleted file]
target/linux/brcm2708/patches-4.4/0065-ASoC-wm8804-Implement-MCLK-configuration-options-add.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0066-ASoC-BCM-Add-support-for-HiFiBerry-Digi.-Driver-is-b.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0066-ASoC-wm8804-Implement-MCLK-configuration-options-add.patch [deleted file]
target/linux/brcm2708/patches-4.4/0067-ASoC-BCM-Add-support-for-HiFiBerry-Digi.-Driver-is-b.patch [deleted file]
target/linux/brcm2708/patches-4.4/0067-ASoC-wm8804-Set-idle_bias_off-to-false-Idle-bias-has.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0068-ASoC-wm8804-Set-idle_bias_off-to-false-Idle-bias-has.patch [deleted file]
target/linux/brcm2708/patches-4.4/0068-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0069-Add-IQaudIO-Sound-Card-support-for-Raspberry-Pi.patch [deleted file]
target/linux/brcm2708/patches-4.4/0069-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0070-Added-support-for-HiFiBerry-DAC.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0070-hid-Reduce-default-mouse-polling-interval-to-60Hz.patch [deleted file]
target/linux/brcm2708/patches-4.4/0071-Added-driver-for-HiFiBerry-Amp-amplifier-add-on-boar.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0071-Added-support-for-HiFiBerry-DAC.patch [deleted file]
target/linux/brcm2708/patches-4.4/0072-Added-driver-for-HiFiBerry-Amp-amplifier-add-on-boar.patch [deleted file]
target/linux/brcm2708/patches-4.4/0072-Update-ds1307-driver-for-device-tree-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0073-BCM270x_DT-Add-pwr_led-and-the-required-input-trigge.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0073-Update-ds1307-driver-for-device-tree-support.patch [deleted file]
target/linux/brcm2708/patches-4.4/0074-BCM270x_DT-Add-pwr_led-and-the-required-input-trigge.patch [deleted file]
target/linux/brcm2708/patches-4.4/0074-enc28j60-Add-device-tree-compatible-string-and-an-ov.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0075-Add-driver-for-rpi-proto.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0075-enc28j60-Add-device-tree-compatible-string-and-an-ov.patch [deleted file]
target/linux/brcm2708/patches-4.4/0076-Add-driver-for-rpi-proto.patch [deleted file]
target/linux/brcm2708/patches-4.4/0076-config-Add-default-configs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0077-bcm2835-bcm2835_defconfig.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0077-config-Add-default-configs.patch [deleted file]
target/linux/brcm2708/patches-4.4/0078-bcm2835-bcm2835_defconfig.patch [deleted file]
target/linux/brcm2708/patches-4.4/0078-rpi-ft5406-Add-touchscreen-driver-for-pi-LCD-display.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0079-Improve-__copy_to_user-and-__copy_from_user-performa.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0079-rpi-ft5406-Add-touchscreen-driver-for-pi-LCD-display.patch [deleted file]
target/linux/brcm2708/patches-4.4/0080-Improve-__copy_to_user-and-__copy_from_user-performa.patch [deleted file]
target/linux/brcm2708/patches-4.4/0080-gpio-poweroff-Allow-it-to-work-on-Raspberry-Pi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0081-gpio-poweroff-Allow-it-to-work-on-Raspberry-Pi.patch [deleted file]
target/linux/brcm2708/patches-4.4/0081-spidev-Add-spidev-compatible-string-to-silence-warni.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0082-scripts-dtc-Add-overlay-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0082-spidev-Add-spidev-compatible-string-to-silence-warni.patch [deleted file]
target/linux/brcm2708/patches-4.4/0083-mfd-Add-Raspberry-Pi-Sense-HAT-core-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0083-scripts-dtc-Add-overlay-support.patch [deleted file]
target/linux/brcm2708/patches-4.4/0084-RaspiDAC3-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0084-mfd-Add-Raspberry-Pi-Sense-HAT-core-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0085-RaspiDAC3-support.patch [deleted file]
target/linux/brcm2708/patches-4.4/0085-tpa6130a2-Add-headphone-switch-control.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0086-irq-bcm2835-Fix-building-with-2708.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0086-tpa6130a2-Add-headphone-switch-control.patch [deleted file]
target/linux/brcm2708/patches-4.4/0087-irq-bcm2835-Fix-building-with-2708.patch [deleted file]
target/linux/brcm2708/patches-4.4/0087-rpi_display-add-backlight-driver-and-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0088-bcm2835-dma-Fix-up-convert-to-DMA-pool.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0088-rpi_display-add-backlight-driver-and-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.4/0089-bcm2835-dma-Fix-up-convert-to-DMA-pool.patch [deleted file]
target/linux/brcm2708/patches-4.4/0089-scripts-Multi-platform-support-for-mkknlimg-and-knli.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0090-drm-vc4-Add-suport-for-3D-rendering-using-the-V3D-en.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0090-scripts-Multi-platform-support-for-mkknlimg-and-knli.patch [deleted file]
target/linux/brcm2708/patches-4.4/0091-drm-vc4-Add-suport-for-3D-rendering-using-the-V3D-en.patch [deleted file]
target/linux/brcm2708/patches-4.4/0091-drm-vc4-Force-HDMI-to-connected.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0092-drm-vc4-Force-HDMI-to-connected.patch [deleted file]
target/linux/brcm2708/patches-4.4/0092-drm-vc4-bo-cache-locking-fixes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0093-drm-vc4-bo-cache-locking-cleanup.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0093-drm-vc4-bo-cache-locking-fixes.patch [deleted file]
target/linux/brcm2708/patches-4.4/0094-drm-vc4-Use-job_lock-to-protect-seqno_cb_list.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0094-drm-vc4-bo-cache-locking-cleanup.patch [deleted file]
target/linux/brcm2708/patches-4.4/0095-drm-vc4-Drop-struct_mutex-around-CL-validation.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0095-drm-vc4-Use-job_lock-to-protect-seqno_cb_list.patch [deleted file]
target/linux/brcm2708/patches-4.4/0096-drm-vc4-Drop-struct_mutex-around-CL-validation.patch
target/linux/brcm2708/patches-4.4/0097-drm-vc4-Add-support-for-more-display-plane-formats.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0097-drm-vc4-Drop-struct_mutex-around-CL-validation.patch [deleted file]
target/linux/brcm2708/patches-4.4/0098-drm-vc4-Add-support-for-more-display-plane-formats.patch [deleted file]
target/linux/brcm2708/patches-4.4/0098-drm-vc4-No-need-to-stop-the-stopped-threads.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0099-drm-vc4-No-need-to-stop-the-stopped-threads.patch [deleted file]
target/linux/brcm2708/patches-4.4/0099-drm-vc4-Remove-extra-barrier-s-aroudn-CTnCA-CTnEA-se.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0100-drm-vc4-Fix-a-typo-in-a-V3D-debug-register.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0100-drm-vc4-Remove-extra-barrier-s-aroudn-CTnCA-CTnEA-se.patch [deleted file]
target/linux/brcm2708/patches-4.4/0101-drm-vc4-Enable-VC4-modules-and-increase-CMA-size-wit.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0101-drm-vc4-Fix-a-typo-in-a-V3D-debug-register.patch [deleted file]
target/linux/brcm2708/patches-4.4/0102-drm-vc4-Enable-VC4-modules-and-increase-CMA-size-wit.patch [deleted file]
target/linux/brcm2708/patches-4.4/0102-squash-fixups.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0103-squash-add-missing-vc4-kms-v3d-overlay.dtb-to-makefi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0103-squash-fixups.patch [deleted file]
target/linux/brcm2708/patches-4.4/0104-clk-bcm2835-Also-build-the-driver-for-downstream-ker.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0104-squash-add-missing-vc4-kms-v3d-overlay.dtb-to-makefi.patch [deleted file]
target/linux/brcm2708/patches-4.4/0105-clk-bcm2835-Also-build-the-driver-for-downstream-ker.patch [deleted file]
target/linux/brcm2708/patches-4.4/0105-dts-Added-overlay-for-gpio_ir_recv-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0106-Build-i2c_gpio-module-and-add-a-device-tree-overlay-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0106-dts-Added-overlay-for-gpio_ir_recv-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0107-Build-i2c_gpio-module-and-add-a-device-tree-overlay-.patch [deleted file]
target/linux/brcm2708/patches-4.4/0107-New-overlay-for-PiScreen2r.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0108-New-overlay-for-PiScreen2r.patch [deleted file]
target/linux/brcm2708/patches-4.4/0108-dts-Added-overlay-for-Adafruit-PiTFT-2.8-capacitive-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0109-Add-support-for-the-HiFiBerry-DAC-Pro.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0109-dts-Added-overlay-for-Adafruit-PiTFT-2.8-capacitive-.patch [deleted file]
target/linux/brcm2708/patches-4.4/0110-Add-support-for-the-HiFiBerry-DAC-Pro.patch [deleted file]
target/linux/brcm2708/patches-4.4/0110-BCM270X_DT-Add-at86rf233-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0111-BCM270X_DT-Add-at86rf233-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.4/0111-mm-Remove-the-PFN-busy-warning.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0112-drm-Put-an-optional-field-in-the-driver-struct-for-G.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0112-mm-Remove-the-PFN-busy-warning.patch [deleted file]
target/linux/brcm2708/patches-4.4/0113-drm-Put-an-optional-field-in-the-driver-struct-for-G.patch [deleted file]
target/linux/brcm2708/patches-4.4/0113-drm-vc4-Add-an-interface-for-capturing-the-GPU-state.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0114-drm-vc4-Add-an-interface-for-capturing-the-GPU-state.patch [deleted file]
target/linux/brcm2708/patches-4.4/0114-drm-vc4-Update-a-bunch-of-code-to-match-upstream-sub.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0115-drm-Use-the-driver-s-gem_object_free-function-from-C.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0115-drm-vc4-Update-a-bunch-of-code-to-match-upstream-sub.patch [deleted file]
target/linux/brcm2708/patches-4.4/0116-drm-Use-the-driver-s-gem_object_free-function-from-C.patch [deleted file]
target/linux/brcm2708/patches-4.4/0116-drm-vc4-Add-support-for-MSAA-rendering.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0117-drm-vc4-A-few-more-non-functional-changes-to-sync-to.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0117-drm-vc4-Add-support-for-MSAA-rendering.patch [deleted file]
target/linux/brcm2708/patches-4.4/0118-drm-vc4-A-few-more-non-functional-changes-to-sync-to.patch [deleted file]
target/linux/brcm2708/patches-4.4/0118-drm-vc4-Use-hpd-gpios-for-HDMI-GPIO-like-what-landed.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0119-drm-vc4-Synchronize-validation-code-for-v2-submissio.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0119-drm-vc4-Use-hpd-gpios-for-HDMI-GPIO-like-what-landed.patch [deleted file]
target/linux/brcm2708/patches-4.4/0120-MMC-Do-not-use-mmc_debug-if-CONFIG_MMC_BCM2835-is-no.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0120-drm-vc4-Synchronize-validation-code-for-v2-submissio.patch [deleted file]
target/linux/brcm2708/patches-4.4/0121-Extend-clock-timeout-fix-modprobe-baudrate-parameter.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0121-MMC-Do-not-use-mmc_debug-if-CONFIG_MMC_BCM2835-is-no.patch [deleted file]
target/linux/brcm2708/patches-4.4/0122-Extend-clock-timeout-fix-modprobe-baudrate-parameter.patch [deleted file]
target/linux/brcm2708/patches-4.4/0122-bcm270x_dt-Add-dwc2-and-dwc-otg-overlays.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0123-BCM270X_DT-Add-the-sdtweak-overlay-for-tuning-sdhost.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0123-bcm270x_dt-Add-dwc2-and-dwc-otg-overlays.patch [deleted file]
target/linux/brcm2708/patches-4.4/0124-BCM270X_DT-Add-the-sdtweak-overlay-for-tuning-sdhost.patch [deleted file]
target/linux/brcm2708/patches-4.4/0124-bcm2835-mmc-Don-t-override-bus-width-capabilities-fr.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0125-SDIO-overlay-add-bus_width-parameter.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0125-bcm2835-mmc-Don-t-override-bus-width-capabilities-fr.patch [deleted file]
target/linux/brcm2708/patches-4.4/0126-SDIO-overlay-add-bus_width-parameter.patch [deleted file]
target/linux/brcm2708/patches-4.4/0126-bcm2835-extend-allowed-range-of-channels-and-sampler.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0127-FIXUP-BCM270X_DT-random-HWRNG-dtparam-default-is-on.patch [deleted file]
target/linux/brcm2708/patches-4.4/0127-bcm2835-restrict-channels-rate-to-8-960000.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0128-bcm2835-extend-allowed-range-of-channels-and-sampler.patch [deleted file]
target/linux/brcm2708/patches-4.4/0128-rpi-update-vc_vchi_audioserv_defs.h.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0129-bcm2835-implement-channel-map-API.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0129-bcm2835-restrict-channels-rate-to-8-960000.patch [deleted file]
target/linux/brcm2708/patches-4.4/0130-bcm2835-access-controls-under-the-audio-mutex.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0130-rpi-update-vc_vchi_audioserv_defs.h.patch [deleted file]
target/linux/brcm2708/patches-4.4/0131-bcm2835-always-use-2-4-8-channels-for-multichannel-l.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0131-bcm2835-implement-channel-map-API.patch [deleted file]
target/linux/brcm2708/patches-4.4/0132-bcm2835-access-controls-under-the-audio-mutex.patch [deleted file]
target/linux/brcm2708/patches-4.4/0132-bcm2835-only-allow-stereo-if-analogue-jack-is-select.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0133-bcm2835-always-use-2-4-8-channels-for-multichannel-l.patch [deleted file]
target/linux/brcm2708/patches-4.4/0133-bcm2835-interpolate-audio-delay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0134-bcm2835-only-allow-stereo-if-analogue-jack-is-select.patch [deleted file]
target/linux/brcm2708/patches-4.4/0134-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0135-bcm2835-interpolate-audio-delay.patch [deleted file]
target/linux/brcm2708/patches-4.4/0135-bcm2835-sdhost-Add-debug_flags-dtparam.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0136-BCM270X_DT-Add-sdio_overclock-parameter-to-sdio-over.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0136-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch [deleted file]
target/linux/brcm2708/patches-4.4/0137-bcm2835-sdhost-Add-debug_flags-dtparam.patch [deleted file]
target/linux/brcm2708/patches-4.4/0137-rtc-ds1307-add-support-for-the-DT-property-wakeup-so.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0138-BCM270X_DT-Add-sdio_overclock-parameter-to-sdio-over.patch [deleted file]
target/linux/brcm2708/patches-4.4/0138-dt-overlay-add-wittypi-overlay.dts.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0139-FIXUP-i2c_bcm2708-Don-t-change-module-baudrate-param.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0139-rtc-ds1307-add-support-for-the-DT-property-wakeup-so.patch [deleted file]
target/linux/brcm2708/patches-4.4/0140-Allow-up-to-24dB-digital-gain-to-be-applied-when-usi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0140-dt-overlay-add-wittypi-overlay.dts.patch [deleted file]
target/linux/brcm2708/patches-4.4/0141-BCM270X_DT-Disable-DMA-for-bcm2835-sdhost-on-Pi2.patch [deleted file]
target/linux/brcm2708/patches-4.4/0141-Limit-PCM512x-Digital-gain-to-0dB-by-default-with-Hi.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0142-BCM270X_DT-Adjust-overlay-README-formatting.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0142-FIXUP-i2c_bcm2708-Don-t-change-module-baudrate-param.patch [deleted file]
target/linux/brcm2708/patches-4.4/0143-Allow-up-to-24dB-digital-gain-to-be-applied-when-usi.patch [deleted file]
target/linux/brcm2708/patches-4.4/0143-pinctrl-bcm2835-Fix-cut-and-paste-error-in-pull-pars.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0144-Limit-PCM512x-Digital-gain-to-0dB-by-default-with-Hi.patch [deleted file]
target/linux/brcm2708/patches-4.4/0144-bcm2835-sdhost-Major-revision.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0145-BCM270X_DT-Add-dtparams-for-the-SD-interface.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0145-BCM270X_DT-Adjust-overlay-README-formatting.patch [deleted file]
target/linux/brcm2708/patches-4.4/0146-FIXUP-Overlay-README-Restore-spaces-deleted-in-error.patch [deleted file]
target/linux/brcm2708/patches-4.4/0146-dcw_otg-trim-xfer-length-when-buffer-larger-than-all.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0147-bcm2835-sdhost-Restore-ATOMIC-flag-to-PIO-sg-mapping.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0148-Revert-BCM270X_DT-Disable-DMA-for-bcm2835-sdhost-on-.patch [deleted file]
target/linux/brcm2708/patches-4.4/0148-Updated-smsc95xx-driver-to-check-for-a-valid-MAC-add.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0149-bcm2835-sdhost-Major-revision.patch [deleted file]
target/linux/brcm2708/patches-4.4/0149-dcw_otg-Make-trimming-messages-less-noisy.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0150-BCM270X_DT-Add-dtparams-for-the-SD-interface.patch [deleted file]
target/linux/brcm2708/patches-4.4/0150-BCM270X_DT-at86rf233-overlay-drop-to-3MHz.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0151-bcm2835-sdhost-Downgrade-log-message-status.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0151-dcw_otg-trim-xfer-length-when-buffer-larger-than-all.patch [deleted file]
target/linux/brcm2708/patches-4.4/0152-bcm2835-sdhost-Restore-ATOMIC-flag-to-PIO-sg-mapping.patch [deleted file]
target/linux/brcm2708/patches-4.4/0152-config-Enable-HCI-over-UARTs.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0153-Revert-Add-blk_pos-parameter-to-mmc-multi_io_quirk-c.patch [deleted file]
target/linux/brcm2708/patches-4.4/0153-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0154-Updated-smsc95xx-driver-to-check-for-a-valid-MAC-add.patch [deleted file]
target/linux/brcm2708/patches-4.4/0154-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0155-clk-bcm2835-Add-bindings-for-the-auxiliary-periphera.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0155-dcw_otg-Make-trimming-messages-less-noisy.patch [deleted file]
target/linux/brcm2708/patches-4.4/0156-BCM270X_DT-at86rf233-overlay-drop-to-3MHz.patch [deleted file]
target/linux/brcm2708/patches-4.4/0156-clk-bcm2835-Add-a-driver-for-the-auxiliary-periphera.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0157-Aux-SPI-1-2-implementation.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0157-bcm2835-sdhost-Downgrade-log-message-status.patch [deleted file]
target/linux/brcm2708/patches-4.4/0158-ASoC-bcm-add-missing-.owner-fields-in-sound-card-dri.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0158-config-Enable-HCI-over-UARTs.patch [deleted file]
target/linux/brcm2708/patches-4.4/0159-hci_h5-Don-t-send-conf_req-when-ACTIVE.patch [deleted file]
target/linux/brcm2708/patches-4.4/0159-smsx95xx-Add-option-to-disable-the-crimes-against-tr.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0160-amba_pl011-Don-t-use-DT-aliases-for-numbering.patch [deleted file]
target/linux/brcm2708/patches-4.4/0160-bcm2835-virtgpio-Virtual-GPIO-driver.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0161-BCM270X_DT-Add-Pi3-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0161-clk-bcm2835-Add-bindings-for-the-auxiliary-periphera.patch [deleted file]
target/linux/brcm2708/patches-4.4/0162-DT-Add-overlays-to-configure-I2C-pins.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0162-clk-bcm2835-Add-a-driver-for-the-auxiliary-periphera.patch [deleted file]
target/linux/brcm2708/patches-4.4/0163-Aux-SPI-1-2-implementation.patch [deleted file]
target/linux/brcm2708/patches-4.4/0163-bcm2835-camera-fix-a-bug-in-computation-of-frame-tim.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0164-ASoC-bcm-add-missing-.owner-fields-in-sound-card-dri.patch [deleted file]
target/linux/brcm2708/patches-4.4/0164-BCM270X_DT-Add-pi3-disable-bt-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0165-BCM270X_DT-Add-pi3-miniuart-bt-DT-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0165-smsx95xx-Add-option-to-disable-the-crimes-against-tr.patch [deleted file]
target/linux/brcm2708/patches-4.4/0166-Pi3-DT-Add-dtparams-for-the-SD-interface.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0166-bcm2835-virtgpio-Virtual-GPIO-driver.patch [deleted file]
target/linux/brcm2708/patches-4.4/0167-BCM270X_DT-Add-Pi3-support.patch [deleted file]
target/linux/brcm2708/patches-4.4/0167-vchiq_arm-Tweak-the-logging-output.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0168-FIXUP-BCM270X_DT-Update-to-latest-Pi3-DTS.patch [deleted file]
target/linux/brcm2708/patches-4.4/0168-bcm2835-sdhost-Only-claim-one-DMA-channel.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0169-DT-Add-overlays-to-configure-I2C-pins.patch [deleted file]
target/linux/brcm2708/patches-4.4/0169-bcm2835-mmc-Only-claim-one-DMA-channel.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0170-bcm2835-camera-fix-a-bug-in-computation-of-frame-tim.patch [deleted file]
target/linux/brcm2708/patches-4.4/0170-config-rebuild-with-savedefconfig.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0171-BCM270X_DT-Add-pi3-disable-bt-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.4/0171-config-Add-module-for-mcp3422-ADC.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0172-BCM270X_DT-Add-pi3-miniuart-bt-DT-overlay.patch [deleted file]
target/linux/brcm2708/patches-4.4/0172-Pi3-DT-Add-pull-ups-on-the-UART-RX-lines.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0173-Pi3-DT-Add-dtparams-for-the-SD-interface.patch [deleted file]
target/linux/brcm2708/patches-4.4/0174-BCM270X_DT-rpi-display-overlay-add-swapxy-param.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0174-vchiq_arm-Tweak-the-logging-output.patch [deleted file]
target/linux/brcm2708/patches-4.4/0175-Remove-I2S-config-from-bt_pins.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0175-bcm2835-sdhost-Only-claim-one-DMA-channel.patch [deleted file]
target/linux/brcm2708/patches-4.4/0176-Revert-scripts-dtc-Add-overlay-support.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0176-bcm2835-mmc-Only-claim-one-DMA-channel.patch [deleted file]
target/linux/brcm2708/patches-4.4/0177-config-rebuild-with-savedefconfig.patch [deleted file]
target/linux/brcm2708/patches-4.4/0177-scripts-dtc-Update-to-upstream-version-1.4.1.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0178-config-Add-module-for-mcp3422-ADC.patch [deleted file]
target/linux/brcm2708/patches-4.4/0178-configfs-implement-binary-attributes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0179-OF-DT-Overlay-configfs-interface.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0179-Pi3-DT-Add-pull-ups-on-the-UART-RX-lines.patch [deleted file]
target/linux/brcm2708/patches-4.4/0180-Protect-__release_resource-against-resources-without.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0181-BCM270X_DT-Add-a-.dtbo-target-use-for-overlays.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0182-scripts-knlinfo-Decode-DDTK-atom.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0183-Enable-Dynamic-Device-Tree-for-bcmrpi_defconfig-and-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0184-SQUASH-Add-CONFIG_OF_CONFIGFS-to-bcmrpi_defconfig.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0185-dts-kbuild-dtbs_install-installs-.dtbo-files-too.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0186-bcm2835-sdhost-Workaround-for-slow-sectors.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0187-BCM270X_DT-Add-labels-to-spidev-nodes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0188-BCM270X_DT-Use-spidev-labels-in-overlays.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0189-BCM270X_DT-Build-and-document-the-wittypi-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0190-scripts-dtc-Fix-UMR-causing-corrupt-dtbo-overlay-fil.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0191-BCM270X_DT-Add-dtparam-for-uart1.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0192-dwc-overlay-Use-label-so-overrides-can-apply.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0193-drm-vc4-Add-a-debugfs-node-for-tracking-execution-st.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0194-drm-vc4-Include-vc4_drm.h-in-uapi-in-downstream-buil.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0195-drm-vc4-Validate-that-WAIT_BO-padding-is-cleared.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0196-drm-vc4-Fix-the-clear-color-for-the-first-tile-rende.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0197-drm-vc4-Return-an-ERR_PTR-from-BO-creation-instead-o.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0198-drm-vc4-Fix-ERESTARTSYS-error-return-from-BO-waits.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0199-drm-vc4-Drop-error-message-on-seqno-wait-timeouts.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0200-BCM270X_DT-Add-1-bit-SDIO-using-minimal-pins.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0202-Add-overlay-and-enable-support-for-QCA7000-board.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0203-serial-Take-care-starting-a-hung-up-tty-s-port.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0204-pi3-miniuart-bt-overlay-Correct-and-clarify-info.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0205-pwm-overlays-Params-must-have-in-overlay-targets.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0206-BCM270X_DT-Switch-Compute-Module-to-MMC.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0207-dwc_otg-Don-t-free-qh-align-buffers-in-atomic-contex.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0208-dwc_otg-Enable-the-hack-for-Split-Interrupt-transact.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0209-BCM270X_DT-Remove-explicit-claiming-of-UART-pins.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0210-lirc_rpi-Lower-IR-reception-error-to-debug.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0211-vchiq_arm-Access-the-dequeue_pending-flag-locked.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0212-BCM270X_DT-Add-pi3-act-led-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0213-vchiq_arm-Service-callbacks-must-not-fail.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0214-Add-configs-and-overlay-for-PCA9548-I2C-mux.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0215-BCM270X_DT-Add-DS1339-to-i2c-rtc-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0216-copy_from_user-CPU_SW_DOMAIN_PAN-compatibility.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0217-bcm2835-sdhost-Adjust-to-core-clock-changes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0218-BCM270X_DT-Document-hazards-of-sdhost-overlay.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0219-cpufreq-Temporarily-ignore-io_is_busy-1.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0220-Revert-cpufreq-Temporarily-ignore-io_is_busy-1.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0221-net-sched-add-skb_at_tc_ingress-helper.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0222-net-fix-bridge-multicast-packet-checksum-validation.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0223-bpf-add-skb_postpush_rcsum-and-fix-dev_forward_skb-o.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0224-bcm2835-sdhost-Precalc-divisors-and-overclocks.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0225-Revert-bcm2835-sdhost-Precalc-divisors-and-overclock.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0226-Revert-bcm2835-sdhost-Adjust-to-core-clock-changes.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0227-bcm2835-sdhost-Firmware-manages-the-clock-divisor.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0228-Revert-Revert-cpufreq-Temporarily-ignore-io_is_busy-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0229-config-Enabled-IPV6_SUBTREES.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0230-add-smsc95xx-packetsize-module_param.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0231-reboot-Use-power-off-rather-than-busy-spinning-when-.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/0232-Revert-bcm2835-dma-Fix-dreq-not-set-for-slave-transf.patch [new file with mode: 0644]
target/linux/brcm2708/patches-4.4/1001-smsc95xx-disable-hw-csum.patch [deleted file]

index 1209f5e48a62dabe554ed4891b14f7651615105b..2b66d0ff002a5d33206db42ed822caff7171e6bb 100644 (file)
@@ -266,6 +266,7 @@ CONFIG_NO_HZ_IDLE=y
 CONFIG_OABI_COMPAT=y
 CONFIG_OF=y
 CONFIG_OF_ADDRESS=y
+CONFIG_OF_CONFIGFS=y
 CONFIG_OF_EARLY_FLATTREE=y
 CONFIG_OF_FLATTREE=y
 CONFIG_OF_GPIO=y
index 87ca365f6aacda7c4b35b66fc08ed9b084454de6..3127775c3a1b4788bded6e6d51e5d5fc4720f164 100644 (file)
@@ -283,6 +283,7 @@ CONFIG_NR_CPUS=4
 CONFIG_OABI_COMPAT=y
 CONFIG_OF=y
 CONFIG_OF_ADDRESS=y
+CONFIG_OF_CONFIGFS=y
 CONFIG_OF_EARLY_FLATTREE=y
 CONFIG_OF_FLATTREE=y
 CONFIG_OF_GPIO=y
index 8614c8f828dbe2dec2c1ce67a3fdd2c896405565..8ff865685d7ec6cbc00998a42c298438f96b2a5c 100644 (file)
@@ -283,6 +283,7 @@ CONFIG_NR_CPUS=4
 CONFIG_OABI_COMPAT=y
 CONFIG_OF=y
 CONFIG_OF_ADDRESS=y
+CONFIG_OF_CONFIGFS=y
 CONFIG_OF_EARLY_FLATTREE=y
 CONFIG_OF_FLATTREE=y
 CONFIG_OF_GPIO=y
index ad71c5679f837f4572cb8e2e57d27676a165825c..04c27ccf8300b3f72049c6a57ce6582e7472bbef 100644 (file)
@@ -33,7 +33,7 @@ define Build/boot-img
        mcopy -i $@.boot $(word 1,$^) ::kernel.img
        $(foreach dts,$(shell echo $(DEVICE_DTS)),mcopy -i $@.boot $(DTS_DIR)/$(dts).dtb ::;)
        mmd -i $@.boot ::/overlays
-       mcopy -i $@.boot $(DTS_DIR)/overlays/*.dtb ::/overlays/
+       mcopy -i $@.boot $(DTS_DIR)/overlays/*.dtbo ::/overlays/
        mcopy -i $@.boot $(DTS_DIR)/overlays/README ::/overlays/
 endef
 
index 75b1cab7af51afd26c81553a44693f67fac04bd7..8c96f1fe97c41afdd4751e9ca63abcce5b408e92 100644 (file)
 ##     Stop start.elf from filling in ATAGS (memory from 0x100) before
 ##     launching kernel
 ##
-disable_commandline_tags=2
+#disable_commandline_tags=2
+
+## enable_uart
+##     Enables or disables uart pin multiplexing
+##     Raspberry Pi 1/2: if unset, uart is enabled by default
+##     Raspberry Pi 3: if unset uart is disabled by default
+##
+enable_uart=1
 
 ## cmdline (string)
 ##     Command line parameters. Can be used instead of cmdline.txt file
@@ -491,7 +498,7 @@ disable_commandline_tags=2
 ## kernel_address
 ##     Address to load kernel.img file at
 ##
-kernel_address=0x8000
+#kernel_address=0x8000
 
 ## ramfsfile (string)
 ##     ramfs file to load
@@ -515,21 +522,21 @@ kernel_address=0x8000
 ## device_tree_address
 ##     Address to load device_tree at
 ##
-device_tree_address=0x100
+#device_tree_address=0x100
 
 ## init_uart_baud
 ##     Initial uart baud rate.
 ##
 ##     Default 115200
 ##
-init_uart_baud=115200
+#init_uart_baud=115200
 
 ## init_uart_clock
 ##     Initial uart clock.
 ##
 ##     Default 3000000 (3MHz)
 ##
-init_uart_clock=3000000
+#init_uart_clock=3000000
 
 ## init_emmc_clock
 ##     Initial emmc clock, increasing this can speedup your SD-card.
index 960b448932c407670d1c23dbc69c8d8d19248e0d..ee4ff9d2b3fd48abdffb3738e18125da982457a4 100644 (file)
@@ -1,7 +1,7 @@
-From b6cc28abbbf710379772d3da9227ce66926c46a3 Mon Sep 17 00:00:00 2001
+From 23b133903a357066adb48bceb76aba8bd30d8c66 Mon Sep 17 00:00:00 2001
 From: Steve Glendinning <steve.glendinning@smsc.com>
 Date: Thu, 19 Feb 2015 18:47:12 +0000
-Subject: [PATCH 001/170] smsx95xx: fix crimes against truesize
+Subject: [PATCH 001/232] smsx95xx: fix crimes against truesize
 
 smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings.
 
index 8ed786b5380c6b3e0094c35426b3a0c4923b58e4..f3f7a4bf2d41a9d5b0060071d781945b54c20e1a 100644 (file)
@@ -1,7 +1,7 @@
-From 37e24d2f0af32632a17692076dddcf176d1af1f7 Mon Sep 17 00:00:00 2001
+From e7515ee9af1d150d50b55d8f8f53d735a23cb253 Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix@gmail.com>
 Date: Fri, 17 Apr 2015 16:58:45 +0100
-Subject: [PATCH 002/170] smsc95xx: Disable turbo mode by default
+Subject: [PATCH 002/232] smsc95xx: Disable turbo mode by default
 
 ---
  drivers/net/usb/smsc95xx.c | 2 +-
index 63d51ba50633a2ac72d11408469047095ca85c1e..9a6d94f9e75134340bb2e17df5415fc0b95c76e3 100644 (file)
@@ -1,7 +1,7 @@
-From d5cb475205138f9df1fdbb74d8810ab1928696ea Mon Sep 17 00:00:00 2001
+From 849ff5353023c95d40040ecfd279e216074b3d1c Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix@gmail.com>
 Date: Wed, 18 Jun 2014 13:42:01 +0100
-Subject: [PATCH 003/170] vmstat: Workaround for issue where dirty page count
+Subject: [PATCH 003/232] vmstat: Workaround for issue where dirty page count
  goes negative
 
 See:
index 0d348cabcd6bb51ea46dd4e6e20029bef252b209..a171fbfa401f190933b063acefc22cd3f6f4fbec 100644 (file)
@@ -1,7 +1,7 @@
-From 249a499b1d4b6f8a57b3377d4f505841e99f60c8 Mon Sep 17 00:00:00 2001
+From d29365673ed37e7688bd3f35c4a5ad719f878190 Mon Sep 17 00:00:00 2001
 From: Robert Tiemann <rtie@gmx.de>
 Date: Mon, 20 Jul 2015 11:01:25 +0200
-Subject: [PATCH 004/170] BCM2835_DT: Fix I2S register map
+Subject: [PATCH 004/232] BCM2835_DT: Fix I2S register map
 
 ---
  Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt   | 4 ++--
index a2e71925cd05131783c5a6d02318fe5054244b0b..7db83aec0d049db7643fc46549febcdc6f7700c8 100644 (file)
@@ -1,7 +1,7 @@
-From c24657505a2aac71d0409b0ef703fc21ecab4b2e Mon Sep 17 00:00:00 2001
+From c891de13b385afb3e4b2c97ac5bbea7e2d97252f Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil@raspberrypi.org>
 Date: Fri, 4 Dec 2015 17:41:50 +0000
-Subject: [PATCH 005/170] irq-bcm2836: Prevent spurious interrupts, and trap
+Subject: [PATCH 005/232] irq-bcm2836: Prevent spurious interrupts, and trap
  them early
 
 The old arch-specific IRQ macros included a dsb to ensure the
index 16d431e4cbed2040bc076973acdbc9655c39579e..81d1295ece07fc9413bce4ee1184cf7ef001b067 100644 (file)
@@ -1,7 +1,7 @@
-From 229bcf2e73ce37e8a18d68773471024c848d84bd Mon Sep 17 00:00:00 2001
+From 60f7ee79b375d72f5ef46ec542b925b1f1428bad Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Fri, 12 Jun 2015 19:01:05 +0200
-Subject: [PATCH 006/170] irqchip: bcm2835: Add FIQ support
+Subject: [PATCH 006/232] irqchip: bcm2835: Add FIQ support
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index 6025b7a9b18c03d38e76178d23913196391eabbd..e95993c86a5b6540ea415e6406f2fa53df35c1a8 100644 (file)
@@ -1,7 +1,7 @@
-From 6780f0a5c6af19f2b9850e961a0f81fbfdfa48fe Mon Sep 17 00:00:00 2001
+From 890dccbb9c60be182adefb61b3ede805ccba1a91 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Fri, 23 Oct 2015 16:26:55 +0200
-Subject: [PATCH 007/170] irqchip: irq-bcm2835: Add 2836 FIQ support
+Subject: [PATCH 007/232] irqchip: irq-bcm2835: Add 2836 FIQ support
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index 5c624a8db06a82257c7ac1487f00b4707f2886a5..6961269a3274546ef77eab24fc4fbd961e6ad1a7 100644 (file)
@@ -1,7 +1,7 @@
-From 4b9529b98c01569dff06f4e67ba28a47318e5ea5 Mon Sep 17 00:00:00 2001
+From 9a27662aac88f95b3de1915333a0265614f88a0d Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil@raspberrypi.org>
 Date: Tue, 30 Jun 2015 14:12:42 +0100
-Subject: [PATCH 008/170] serial: 8250: Don't crash when nr_uarts is 0
+Subject: [PATCH 008/232] serial: 8250: Don't crash when nr_uarts is 0
 
 ---
  drivers/tty/serial/8250/8250_core.c | 2 ++
index fca587747c58879709650b89f4301145fb4509d7..a75621d54ea06f6669d93124950792e93f67e7e5 100644 (file)
@@ -1,7 +1,7 @@
-From 5fd6ab82b1027504faa66cf4fc8b999fafaacd12 Mon Sep 17 00:00:00 2001
+From 4d7ff05e4d4d8d8adb4e7b4dd5fa8f63ae2be0f6 Mon Sep 17 00:00:00 2001
 From: notro <notro@tronnes.org>
 Date: Thu, 10 Jul 2014 13:59:47 +0200
-Subject: [PATCH 009/170] pinctrl-bcm2835: Set base to 0 give expected gpio
+Subject: [PATCH 009/232] pinctrl-bcm2835: Set base to 0 give expected gpio
  numbering
 
 Signed-off-by: Noralf Tronnes <notro@tronnes.org>
index da3406b41315a070553780a73df13ba32fed9da6..278ff9fec5a493835fa7111ee61dd04c5ef26c8b 100644 (file)
@@ -1,7 +1,7 @@
-From 4254ef2647e89061427836443eac60351b3306a7 Mon Sep 17 00:00:00 2001
+From 969dc44a700e1be13c3f80445d40c1fe51cc4370 Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil@raspberrypi.org>
 Date: Tue, 24 Feb 2015 13:40:50 +0000
-Subject: [PATCH 010/170] pinctrl-bcm2835: Fix interrupt handling for GPIOs
+Subject: [PATCH 010/232] pinctrl-bcm2835: Fix interrupt handling for GPIOs
  28-31 and 46-53
 
 Contrary to the documentation, the BCM2835 GPIO controller actually has
index 02656d90607f1bb300b40ad513055196fe434eb0..49315e5884a65bc0b050e97620b115903b0a0803 100644 (file)
@@ -1,7 +1,7 @@
-From 93b12e64d0e2a8a65189dedd667e00b0a0fab60a Mon Sep 17 00:00:00 2001
+From b949246bf51fa852bad45136cdd6bcd91a29539e Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil@raspberrypi.org>
 Date: Thu, 26 Feb 2015 09:58:22 +0000
-Subject: [PATCH 011/170] pinctrl-bcm2835: Only request the interrupts listed
+Subject: [PATCH 011/232] pinctrl-bcm2835: Only request the interrupts listed
  in the DTB
 
 Although the GPIO controller can generate three interrupts (four counting
index 46c37ec973346d2751a07b585c5243f547dfaab9..92aa046f227221e3d170333c3e4feeb910d3eab6 100644 (file)
@@ -1,7 +1,7 @@
-From bb8ff388ad26721eebb7249afb6f6f57bc196de4 Mon Sep 17 00:00:00 2001
+From 19bcdacc5a67abe6a2d604a39ddfed5a54c77b2e Mon Sep 17 00:00:00 2001
 From: Phil Elwell <phil@raspberrypi.org>
 Date: Wed, 24 Jun 2015 14:10:44 +0100
-Subject: [PATCH 012/170] spi-bcm2835: Support pin groups other than 7-11
+Subject: [PATCH 012/232] spi-bcm2835: Support pin groups other than 7-11
 
 The spi-bcm2835 driver automatically uses GPIO chip-selects due to
 some unreliability of the native ones. In doing so it chooses the
index a0860d1dbf18d41ef3e902e1fb826cc4d981aed1..a571cdb202c792e590058fd9ca326e1fa5de0cee 100644 (file)
@@ -1,7 +1,7 @@
-From bfcfed788d152e828747ea889a88f8b179217ddb Mon Sep 17 00:00:00 2001
+From 7ce5cbfba6e930c2178f342a4390972f1efd75ef Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Wed, 3 Jun 2015 12:26:13 +0200
-Subject: [PATCH 013/170] ARM: bcm2835: Set Serial number and Revision
+Subject: [PATCH 013/232] ARM: bcm2835: Set Serial number and Revision
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index 0e4726d45815785f4f6b247379bca944078a1b53..fa35faaf5699d7364e762f45542632a710397879 100644 (file)
@@ -1,7 +1,7 @@
-From fb968a02c00e2722df2dcfec6f54b7524ff5a155 Mon Sep 17 00:00:00 2001
+From 569baa856d805e594011f2d1444b6849c291544d Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sun, 11 Oct 2015 16:44:05 +0200
-Subject: [PATCH 014/170] bcm2835-i2s: get base address for DMA from devicetree
+Subject: [PATCH 014/232] bcm2835-i2s: get base address for DMA from devicetree
 
 Code copied from spi-bcm2835. Get physical address from devicetree
 instead of using hardcoded constant.
index 79fe1b43a9496c7a37464215450a9db8aded7f3a..a1fbf79ef0da84b113b0e1735cea56257abd681e 100644 (file)
@@ -1,7 +1,7 @@
-From abbe565abfe075b76e01b9671c6fc4cf42cc0328 Mon Sep 17 00:00:00 2001
+From c61a7aef15a1aee86e1de59dca2ad7002995f9cf Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sun, 11 Oct 2015 15:21:16 +0200
-Subject: [PATCH 015/170] bcm2835-i2s: add 24bit support, update bclk_ratio to
+Subject: [PATCH 015/232] bcm2835-i2s: add 24bit support, update bclk_ratio to
  more correct values
 
 Code ported from bcm2708-i2s driver in Raspberry Pi tree.
index 810f83fb8e508ca563b41b88f4b3204f8122289f..ec224b93e0ba8a95b970e0b4217d705c5ec8d5e4 100644 (file)
@@ -1,7 +1,7 @@
-From b2cc62cd13099d6d2f21b9927df248aa3bdd8d5b Mon Sep 17 00:00:00 2001
+From e2a75ce0e2b6319150e14401f9822adba7895c9c Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sun, 11 Oct 2015 15:25:51 +0200
-Subject: [PATCH 016/170] bcm2835-i2s: setup clock only if CPU is clock master
+Subject: [PATCH 016/232] bcm2835-i2s: setup clock only if CPU is clock master
 
 Code ported from bcm2708-i2s driver in Raspberry Pi tree.
 
index 93c83fd682a04f48eceb43924b70236e0c893f8e..82d15f42d07362f82209f24a94311ff6284661fd 100644 (file)
@@ -1,7 +1,7 @@
-From 71b2c93cd332be280b9ca7f293e463f30d5fb108 Mon Sep 17 00:00:00 2001
+From 433841fc5958e1ddbd503b579a022fb67defd74b Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sun, 11 Oct 2015 15:49:51 +0200
-Subject: [PATCH 017/170] bcm2835-i2s: Eliminate debugfs directory error
+Subject: [PATCH 017/232] bcm2835-i2s: Eliminate debugfs directory error
 
 Code ported from bcm2708-i2s driver in Raspberry Pi tree.
 
index 1b547fd6b9dc2fd95ee7fca76c25964d7887a45a..1dc721a696e7dc7a7b09838997cbf11c2cb796b8 100644 (file)
@@ -1,7 +1,7 @@
-From fae43fcaa20df1d39c09c98372100bb1dedd6090 Mon Sep 17 00:00:00 2001
+From 7b4481818fe920904457496db40d59dd3d0a83bb Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sun, 11 Oct 2015 15:35:20 +0200
-Subject: [PATCH 018/170] bcm2835-i2s: Register PCM device
+Subject: [PATCH 018/232] bcm2835-i2s: Register PCM device
 
 Code ported from bcm2708-i2s driver in Raspberry Pi tree.
 
index e68391ccce07044721e33bbae9ada7c51a83938b..e3d7e4382375099ca6d5b3f20b829d69bdeb92f7 100644 (file)
@@ -1,7 +1,7 @@
-From c9e2eeee4889f965a29744718bbff2de409ac649 Mon Sep 17 00:00:00 2001
+From 027ba808e84799c97ae1c64f8424ac8eb7235cc4 Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sun, 11 Oct 2015 15:55:21 +0200
-Subject: [PATCH 019/170] bcm2835-i2s: Enable MMAP support via a DT property
+Subject: [PATCH 019/232] bcm2835-i2s: Enable MMAP support via a DT property
 
 Code ported from bcm2708-i2s driver in Raspberry Pi tree.
 
index 97d6af04902f30ab599c01b6c6a31f549c18532d..344b39c3fd14d4b943e95df97a10050f67b185da 100644 (file)
@@ -1,7 +1,7 @@
-From dc5b926436bccc4efbb1695ec3696b5db6746d3b Mon Sep 17 00:00:00 2001
+From 8a349301238aabb40c9da5ca8c8492b6b8d146f6 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Thu, 9 Apr 2015 12:34:11 +0200
-Subject: [PATCH 020/170] dmaengine: bcm2835: Add slave dma support
+Subject: [PATCH 020/232] dmaengine: bcm2835: Add slave dma support
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index 14d217d3b601abccc1901b55e5f920480033902f..4655513f73bb488b27412245c17bccb35d11c86f 100644 (file)
@@ -1,7 +1,7 @@
-From 9c6955f3fbfbb46242c63b4640886b9a0d87910a Mon Sep 17 00:00:00 2001
+From 290f55520c62025da992d6be0002fc1e3738cfdb Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Sat, 3 Oct 2015 15:58:59 +0200
-Subject: [PATCH 021/170] dmaengine: bcm2835: set residue_granularity field
+Subject: [PATCH 021/232] dmaengine: bcm2835: set residue_granularity field
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index bc4e2028de02efaf6acc2483b83f3dcbac1814ed..a03aed37fb49ff4569665cdb9a24f23aa3aeb697 100644 (file)
@@ -1,7 +1,7 @@
-From 8da7ee8d9b714dbbac842fb5ae0471b52e0393ec Mon Sep 17 00:00:00 2001
+From 6f56fff39c811953809b011f59c49a2122c4d173 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Sat, 3 Oct 2015 22:22:55 +0200
-Subject: [PATCH 022/170] dmaengine: bcm2835: Load driver early and support
+Subject: [PATCH 022/232] dmaengine: bcm2835: Load driver early and support
  legacy API
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
index 2f512e2aaa09f854373593bf89ac7553d737eac6..fe6dbcaf2d190efca3d104666e7068a3c1c404df 100644 (file)
@@ -1,7 +1,7 @@
-From 0f3a30eb7ad7e709fdc6447c70bc3f1d5704eb63 Mon Sep 17 00:00:00 2001
+From df03f00c5e21559185b5a61ea5e8238e10959ab1 Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sat, 10 Oct 2015 12:29:18 +0200
-Subject: [PATCH 023/170] bcm2835-dma: Fix dreq not set for slave transfers
+Subject: [PATCH 023/232] bcm2835-dma: Fix dreq not set for slave transfers
 
 Set dreq to slave_id if it is not set like in bcm2708-dmaengine.
 ---
index 01217c9784850afaee6af8fdccdb6a4e68332985..60a0ec92178f30362da0d36b9c06445539867bd7 100644 (file)
@@ -1,7 +1,7 @@
-From 305370f7caaecafbabb77b630380dbc0c436bb4c Mon Sep 17 00:00:00 2001
+From 052c2005b6ecedc5abad86632f5781adda310aa7 Mon Sep 17 00:00:00 2001
 From: Matthias Reichl <hias@horus.com>
 Date: Sun, 11 Oct 2015 12:28:30 +0200
-Subject: [PATCH 024/170] bcm2835-dma: Limit cyclic transfers on lite channels
+Subject: [PATCH 024/232] bcm2835-dma: Limit cyclic transfers on lite channels
  to 32k
 
 Transfers larger than 32k cause repeated clicking with I2S soundcards.
index 6a5d2cb14a10221afd3127548caad25a4da9c78e..9dfd26bc4eb2258480419fdfe16be6784a0745b6 100644 (file)
@@ -1,7 +1,7 @@
-From d801c33b7e2fb0d02ac11b95ea92b7d692286ffc Mon Sep 17 00:00:00 2001
+From a72021ae99021409319d552dad744572b20febfb Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Sat, 15 Aug 2015 20:50:02 +0200
-Subject: [PATCH 025/170] bcm2835: Add support for uart1
+Subject: [PATCH 025/232] bcm2835: Add support for uart1
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index bde8c0a6c3b49e6c631717311f6f9ca3fefce10c..2a7252ace580a7dd59a3e1145b04baa4875f09b9 100644 (file)
@@ -1,7 +1,7 @@
-From 5e90e32b539720ad8c6c8d7ec462378685924f22 Mon Sep 17 00:00:00 2001
+From 4364707caa6d3d9edf84fa8469a04f33e1ba5d76 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
 Date: Fri, 26 Jun 2015 14:21:20 +0200
-Subject: [PATCH 026/170] firmware: bcm2835: Add missing property tags
+Subject: [PATCH 026/232] firmware: bcm2835: Add missing property tags
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index 7a0f569c2e5fa8e4b856332f04d0ae09b7cacad5..83fd1db70c2e6d2378fd944aa8f1eec3b1af6ce6 100644 (file)
@@ -1,7 +1,7 @@
-From 894f124497e95c9af506af2ed7335857f2e71358 Mon Sep 17 00:00:00 2001
+From cd721670ab8c729d0c62e99a1d173c2575b63282 Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix@gmail.com>
 Date: Sun, 12 May 2013 12:24:19 +0100
-Subject: [PATCH 027/170] Main bcm2708/bcm2709 linux port
+Subject: [PATCH 027/232] Main bcm2708/bcm2709 linux port
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index c35eb6fbb2a3a347b7391a791bfae6e9be41967c..10e1a2f4c7c361152a4bfa36d501b6cfa58c1efa 100644 (file)
@@ -1,7 +1,7 @@
-From 74b2c26348d94949561979a9a3ad61adcac74398 Mon Sep 17 00:00:00 2001
+From 812484cc27980e3351360200478e7044de983f40 Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix@gmail.com>
 Date: Wed, 11 Nov 2015 21:01:15 +0000
-Subject: [PATCH 028/170] squash: include ARCH_BCM2708 / ARCH_BCM2709
+Subject: [PATCH 028/232] squash: include ARCH_BCM2708 / ARCH_BCM2709
 
 ---
  drivers/char/hw_random/Kconfig    |  2 +-
index b1e5a49be02636a8a9dad5ba61b23c060cc1a36c..41d79b1710eeb35273baf45de40bc15c051894c6 100644 (file)
@@ -1,7 +1,7 @@
-From a03df8d0f93365689c718f3d1fb62695e9fffe31 Mon Sep 17 00:00:00 2001
+From 7efc2851a46faa1aceda5f6ec255d0e814812ccf Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix@gmail.com>
 Date: Wed, 1 May 2013 19:46:17 +0100
-Subject: [PATCH 029/170] Add dwc_otg driver
+Subject: [PATCH 029/232] Add dwc_otg driver
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index 4dccb5e759fb399ff71fab1156ef6dd4a437efde..b2983fe57a49993e4c7ff097833ba9b6e88830aa 100644 (file)
@@ -1,7 +1,7 @@
-From 845f985818d3d9ba162ab1102da78b0e39eaedba Mon Sep 17 00:00:00 2001
+From d3b7394edae550f295e185be4651ed43529e7042 Mon Sep 17 00:00:00 2001
 From: popcornmix <popcornmix@gmail.com>
 Date: Wed, 17 Jun 2015 17:06:34 +0100
-Subject: [PATCH 030/170] bcm2708 framebuffer driver
+Subject: [PATCH 030/232] bcm2708 framebuffer driver
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
index 9796cb5f49246b9b8efc15b62756649c15961309..687c3eb424225d1255f6be8fe6708a320688ba9b 100644 (file)
@@ -1,7 +1,7 @@
-From a35139d316b78606bfdeb0f10656ba6f1729c83f Mon Sep 17 00:00:00 2001
+From 99b7c3cfd05f5898e96d7c44c5970880f2c0cd16 Mon Sep 17 00:00:00 2001
 From: Florian Meier <florian.meier@koalo.de>
 Date: Fri, 22 Nov 2013 14:22:53 +0100
-Subject: [PATCH 031/170] dmaengine: Add support for BCM2708
+Subject: [PATCH 031/232] dmaengine: Add support for BCM2708
 MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
diff --git a/target/linux/brcm2708/patches-4.4/0032-Add-blk_pos-parameter-to-mmc-multi_io_quirk-callback.patch b/target/linux/brcm2708/patches-4.4/0032-Add-blk_pos-parameter-to-mmc-multi_io_quirk-callback.patch
deleted file mode 100644 (file)
index 46835f1..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-From 462591cf98f15614620667e93b7f8bc0da6e86da Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Fri, 17 Apr 2015 19:30:22 +0100
-Subject: [PATCH 032/170] Add blk_pos parameter to mmc multi_io_quirk callback
-
----
- drivers/mmc/card/block.c          | 1 +
- drivers/mmc/host/omap_hsmmc.c     | 4 +++-
- drivers/mmc/host/sh_mobile_sdhi.c | 4 +++-
- drivers/mmc/host/tmio_mmc_pio.c   | 4 +++-
- include/linux/mmc/host.h          | 4 +++-
- 5 files changed, 13 insertions(+), 4 deletions(-)
-
---- a/drivers/mmc/card/block.c
-+++ b/drivers/mmc/card/block.c
-@@ -1518,6 +1518,7 @@ static void mmc_blk_rw_rq_prep(struct mm
-                       brq->data.blocks = card->host->ops->multi_io_quirk(card,
-                                               (rq_data_dir(req) == READ) ?
-                                               MMC_DATA_READ : MMC_DATA_WRITE,
-+                                              blk_rq_pos(req),
-                                               brq->data.blocks);
-       }
---- a/drivers/mmc/host/omap_hsmmc.c
-+++ b/drivers/mmc/host/omap_hsmmc.c
-@@ -1832,7 +1832,9 @@ static void omap_hsmmc_conf_bus_power(st
- }
- static int omap_hsmmc_multi_io_quirk(struct mmc_card *card,
--                                   unsigned int direction, int blk_size)
-+                                   unsigned int direction,
-+                                   u32 blk_pos,
-+                                   int blk_size)
- {
-       /* This controller can't do multiblock reads due to hw bugs */
-       if (direction == MMC_DATA_READ)
---- a/drivers/mmc/host/sh_mobile_sdhi.c
-+++ b/drivers/mmc/host/sh_mobile_sdhi.c
-@@ -170,7 +170,9 @@ static int sh_mobile_sdhi_write16_hook(s
- }
- static int sh_mobile_sdhi_multi_io_quirk(struct mmc_card *card,
--                                       unsigned int direction, int blk_size)
-+                                       unsigned int direction,
-+                                       u32 blk_pos,
-+                                       int blk_size)
- {
-       /*
-        * In Renesas controllers, when performing a
---- a/drivers/mmc/host/tmio_mmc_pio.c
-+++ b/drivers/mmc/host/tmio_mmc_pio.c
-@@ -1003,7 +1003,9 @@ static int tmio_mmc_get_ro(struct mmc_ho
- }
- static int tmio_multi_io_quirk(struct mmc_card *card,
--                             unsigned int direction, int blk_size)
-+                             unsigned int direction,
-+                             u32 blk_pos,
-+                             int blk_size)
- {
-       struct tmio_mmc_host *host = mmc_priv(card->host);
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -143,7 +143,9 @@ struct mmc_host_ops {
-        * I/O. Returns the number of supported blocks for the request.
-        */
-       int     (*multi_io_quirk)(struct mmc_card *card,
--                                unsigned int direction, int blk_size);
-+                                unsigned int direction,
-+                                u32 blk_pos,
-+                                int blk_size);
- };
- struct mmc_card;
diff --git a/target/linux/brcm2708/patches-4.4/0032-MMC-added-alternative-MMC-driver.patch b/target/linux/brcm2708/patches-4.4/0032-MMC-added-alternative-MMC-driver.patch
new file mode 100644 (file)
index 0000000..e74c70c
--- /dev/null
@@ -0,0 +1,1691 @@
+From 65c8aadfd88010efb2d2a2821fea7aac978b6c78 Mon Sep 17 00:00:00 2001
+From: gellert <gellert@raspberrypi.org>
+Date: Fri, 15 Aug 2014 16:35:06 +0100
+Subject: [PATCH 032/232] MMC: added alternative MMC driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+mmc: Disable CMD23 transfers on all cards
+
+Pending wire-level investigation of these types of transfers
+and associated errors on bcm2835-mmc, disable for now. Fallback of
+CMD18/CMD25 transfers will be used automatically by the MMC layer.
+
+Reported/Tested-by: Gellert Weisz <gellert@raspberrypi.org>
+
+mmc: bcm2835-mmc: enable DT support for all architectures
+
+Both ARCH_BCM2835 and ARCH_BCM270x are built with OF now.
+Enable Device Tree support for all architectures.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+mmc: bcm2835-mmc: fix probe error handling
+
+Probe error handling is broken in several places.
+Simplify error handling by using device managed functions.
+Replace pr_{err,info} with dev_{err,info}.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+bcm2835-mmc: Add locks when accessing sdhost registers
+
+bcm2835-mmc: Add range of debug options for slowing things down
+
+bcm2835-mmc: Add option to disable some delays
+
+bcm2835-mmc: Add option to disable MMC_QUIRK_BLK_NO_CMD23
+
+bcm2835-mmc: Default to disabling MMC_QUIRK_BLK_NO_CMD23
+
+bcm2835-mmc: Adding overclocking option
+
+Allow a different clock speed to be substitued for a requested 50MHz.
+This option is exposed using the "overclock_50" DT parameter.
+Note that the mmc interface is restricted to EVEN integer divisions of
+250MHz, and the highest sensible option is 63 (250/4 = 62.5), the
+next being 125 (250/2) which is much too high.
+
+Use at your own risk.
+
+bcm2835-mmc: Round up the overclock, so 62 works for 62.5Mhz
+
+Also only warn once for each overclock setting.
+
+mmc: bcm2835-mmc: Make available on ARCH_BCM2835
+
+Make the bcm2835-mmc driver available for use on ARCH_BCM2835.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+BCM270x_DT: add bcm2835-mmc entry
+
+Add Device Tree entry for bcm2835-mmc.
+In non-DT mode, don't add the device in the board file.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+
+bcm2835-mmc: Don't overwrite MMC capabilities from DT
+---
+ drivers/mmc/core/quirks.c      |    6 +
+ drivers/mmc/host/Kconfig       |   29 +
+ drivers/mmc/host/Makefile      |    1 +
+ drivers/mmc/host/bcm2835-mmc.c | 1542 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 1578 insertions(+)
+ create mode 100644 drivers/mmc/host/bcm2835-mmc.c
+
+--- a/drivers/mmc/core/quirks.c
++++ b/drivers/mmc/core/quirks.c
+@@ -53,6 +53,7 @@ static const struct mmc_fixup mmc_fixup_
+ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
+ {
++      extern unsigned mmc_debug;
+       const struct mmc_fixup *f;
+       u64 rev = cid_rev_card(card);
+@@ -77,5 +78,10 @@ void mmc_fixup_device(struct mmc_card *c
+                       f->vendor_fixup(card, f->data);
+               }
+       }
++      /* SDHCI on BCM2708 - bug causes a certain sequence of CMD23 operations to fail.
++       * Disable this flag for all cards (fall-back to CMD25/CMD18 multi-block transfers).
++       */
++      if (mmc_debug & (1<<13))
++      card->quirks |= MMC_QUIRK_BLK_NO_CMD23;
+ }
+ EXPORT_SYMBOL(mmc_fixup_device);
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -4,6 +4,35 @@
+ comment "MMC/SD/SDIO Host Controller Drivers"
++config MMC_BCM2835
++      tristate "MMC support on BCM2835"
++      depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835
++      help
++        This selects the MMC Interface on BCM2835.
++
++        If you have a controller with this interface, say Y or M here.
++
++        If unsure, say N.
++
++config MMC_BCM2835_DMA
++      bool "DMA support on BCM2835 Arasan controller"
++      depends on MMC_BCM2835
++      help
++        Enable DMA support on the Arasan SDHCI controller in Broadcom 2708
++        based chips.
++
++        If unsure, say N.
++
++config MMC_BCM2835_PIO_DMA_BARRIER
++      int "Block count limit for PIO transfers"
++      depends on MMC_BCM2835 && MMC_BCM2835_DMA
++      range 0 256
++      default 2
++      help
++        The inclusive limit in bytes under which PIO will be used instead of DMA
++
++        If unsure, say 2 here.
++
+ config MMC_ARMMMCI
+       tristate "ARM AMBA Multimedia Card Interface support"
+       depends on ARM_AMBA
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C)  += sdhci-s3c
+ obj-$(CONFIG_MMC_SDHCI_SIRF)          += sdhci-sirf.o
+ obj-$(CONFIG_MMC_SDHCI_F_SDH30)       += sdhci_f_sdh30.o
+ obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
++obj-$(CONFIG_MMC_BCM2835)     += bcm2835-mmc.o
+ obj-$(CONFIG_MMC_WBSD)                += wbsd.o
+ obj-$(CONFIG_MMC_AU1X)                += au1xmmc.o
+ obj-$(CONFIG_MMC_MTK)         += mtk-sd.o
+--- /dev/null
++++ b/drivers/mmc/host/bcm2835-mmc.c
+@@ -0,0 +1,1542 @@
++/*
++ * BCM2835 MMC host driver.
++ *
++ * Author:      Gellert Weisz <gellert@raspberrypi.org>
++ *              Copyright 2014
++ *
++ * Based on
++ *  sdhci-bcm2708.c by Broadcom
++ *  sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko
++ *  sdhci.c and sdhci-pci.c by Pierre Ossman
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/delay.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/sd.h>
++#include <linux/scatterlist.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/blkdev.h>
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
++#include <linux/of_dma.h>
++
++#include "sdhci.h"
++
++
++#define DRIVER_NAME "mmc-bcm2835"
++
++#define DBG(f, x...) \
++pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x)
++
++#ifndef CONFIG_MMC_BCM2835_DMA
++ #define FORCE_PIO
++#endif
++
++
++/* the inclusive limit in bytes under which PIO will be used instead of DMA */
++#ifdef CONFIG_MMC_BCM2835_PIO_DMA_BARRIER
++#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_PIO_DMA_BARRIER
++#else
++#define PIO_DMA_BARRIER 00
++#endif
++
++#define MIN_FREQ 400000
++#define TIMEOUT_VAL 0xE
++#define BCM2835_SDHCI_WRITE_DELAY(f)  (((2 * 1000000) / f) + 1)
++
++
++unsigned mmc_debug;
++unsigned mmc_debug2;
++
++struct bcm2835_host {
++      spinlock_t                              lock;
++
++      void __iomem                    *ioaddr;
++      u32                                             bus_addr;
++
++      struct mmc_host                 *mmc;
++
++      u32                                             timeout;
++
++      int                                             clock;  /* Current clock speed */
++      u8                                              pwr;    /* Current voltage */
++
++      unsigned int                    max_clk;                /* Max possible freq */
++      unsigned int                    timeout_clk;    /* Timeout freq (KHz) */
++      unsigned int                    clk_mul;                /* Clock Muliplier value */
++
++      struct tasklet_struct   finish_tasklet;         /* Tasklet structures */
++
++      struct timer_list               timer;                  /* Timer for timeouts */
++
++      struct sg_mapping_iter  sg_miter;               /* SG state for PIO */
++      unsigned int                    blocks;                 /* remaining PIO blocks */
++
++      int                                             irq;                    /* Device IRQ */
++
++
++      u32                                             ier;                    /* cached registers */
++
++      struct mmc_request              *mrq;                   /* Current request */
++      struct mmc_command              *cmd;                   /* Current command */
++      struct mmc_data                 *data;                  /* Current data request */
++      unsigned int                    data_early:1;           /* Data finished before cmd */
++
++      wait_queue_head_t               buf_ready_int;          /* Waitqueue for Buffer Read Ready interrupt */
++
++      u32                                             thread_isr;
++
++      u32                                             shadow;
++
++      /*DMA part*/
++      struct dma_chan                 *dma_chan_rx;           /* DMA channel for reads */
++      struct dma_chan                 *dma_chan_tx;           /* DMA channel for writes */
++      struct dma_async_tx_descriptor  *tx_desc;       /* descriptor */
++
++      bool                                    have_dma;
++      bool                                    use_dma;
++      /*end of DMA part*/
++
++      int                                             max_delay;      /* maximum length of time spent waiting */
++
++      int                                             flags;                          /* Host attributes */
++#define SDHCI_REQ_USE_DMA     (1<<2)  /* Use DMA for this req. */
++#define SDHCI_DEVICE_DEAD     (1<<3)  /* Device unresponsive */
++#define SDHCI_AUTO_CMD12      (1<<6)  /* Auto CMD12 support */
++#define SDHCI_AUTO_CMD23      (1<<7)  /* Auto CMD23 support */
++#define SDHCI_SDIO_IRQ_ENABLED        (1<<9)  /* SDIO irq enabled */
++
++      u32                             overclock_50;   /* frequency to use when 50MHz is requested (in MHz) */
++      u32                             max_overclock;  /* Highest reported */
++};
++
++
++static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg, int from)
++{
++      unsigned delay;
++      lockdep_assert_held_once(&host->lock);
++      writel(val, host->ioaddr + reg);
++      udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ)));
++
++      delay = ((mmc_debug >> 16) & 0xf) << ((mmc_debug >> 20) & 0xf);
++      if (delay && !((1<<from) & mmc_debug2))
++              udelay(delay);
++}
++
++static inline void mmc_raw_writel(struct bcm2835_host *host, u32 val, int reg)
++{
++      unsigned delay;
++      lockdep_assert_held_once(&host->lock);
++      writel(val, host->ioaddr + reg);
++
++      delay = ((mmc_debug >> 24) & 0xf) << ((mmc_debug >> 28) & 0xf);
++      if (delay)
++              udelay(delay);
++}
++
++static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg)
++{
++      lockdep_assert_held_once(&host->lock);
++      return readl(host->ioaddr + reg);
++}
++
++static inline void bcm2835_mmc_writew(struct bcm2835_host *host, u16 val, int reg)
++{
++      u32 oldval = (reg == SDHCI_COMMAND) ? host->shadow :
++              bcm2835_mmc_readl(host, reg & ~3);
++      u32 word_num = (reg >> 1) & 1;
++      u32 word_shift = word_num * 16;
++      u32 mask = 0xffff << word_shift;
++      u32 newval = (oldval & ~mask) | (val << word_shift);
++
++      if (reg == SDHCI_TRANSFER_MODE)
++              host->shadow = newval;
++      else
++              bcm2835_mmc_writel(host, newval, reg & ~3, 0);
++
++}
++
++static inline void bcm2835_mmc_writeb(struct bcm2835_host *host, u8 val, int reg)
++{
++      u32 oldval = bcm2835_mmc_readl(host, reg & ~3);
++      u32 byte_num = reg & 3;
++      u32 byte_shift = byte_num * 8;
++      u32 mask = 0xff << byte_shift;
++      u32 newval = (oldval & ~mask) | (val << byte_shift);
++
++      bcm2835_mmc_writel(host, newval, reg & ~3, 1);
++}
++
++
++static inline u16 bcm2835_mmc_readw(struct bcm2835_host *host, int reg)
++{
++      u32 val = bcm2835_mmc_readl(host, (reg & ~3));
++      u32 word_num = (reg >> 1) & 1;
++      u32 word_shift = word_num * 16;
++      u32 word = (val >> word_shift) & 0xffff;
++
++      return word;
++}
++
++static inline u8 bcm2835_mmc_readb(struct bcm2835_host *host, int reg)
++{
++      u32 val = bcm2835_mmc_readl(host, (reg & ~3));
++      u32 byte_num = reg & 3;
++      u32 byte_shift = byte_num * 8;
++      u32 byte = (val >> byte_shift) & 0xff;
++
++      return byte;
++}
++
++static void bcm2835_mmc_unsignal_irqs(struct bcm2835_host *host, u32 clear)
++{
++      u32 ier;
++
++      ier = bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE);
++      ier &= ~clear;
++      /* change which requests generate IRQs - makes no difference to
++         the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */
++      bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE, 2);
++}
++
++
++static void bcm2835_mmc_dumpregs(struct bcm2835_host *host)
++{
++      pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
++              mmc_hostname(host->mmc));
++
++      pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
++              bcm2835_mmc_readl(host, SDHCI_DMA_ADDRESS),
++              bcm2835_mmc_readw(host, SDHCI_HOST_VERSION));
++      pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
++              bcm2835_mmc_readw(host, SDHCI_BLOCK_SIZE),
++              bcm2835_mmc_readw(host, SDHCI_BLOCK_COUNT));
++      pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
++              bcm2835_mmc_readl(host, SDHCI_ARGUMENT),
++              bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE));
++      pr_debug(DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
++              bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE),
++              bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL));
++      pr_debug(DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
++              bcm2835_mmc_readb(host, SDHCI_POWER_CONTROL),
++              bcm2835_mmc_readb(host, SDHCI_BLOCK_GAP_CONTROL));
++      pr_debug(DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
++              bcm2835_mmc_readb(host, SDHCI_WAKE_UP_CONTROL),
++              bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL));
++      pr_debug(DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
++              bcm2835_mmc_readb(host, SDHCI_TIMEOUT_CONTROL),
++              bcm2835_mmc_readl(host, SDHCI_INT_STATUS));
++      pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
++              bcm2835_mmc_readl(host, SDHCI_INT_ENABLE),
++              bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE));
++      pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
++              bcm2835_mmc_readw(host, SDHCI_ACMD12_ERR),
++              bcm2835_mmc_readw(host, SDHCI_SLOT_INT_STATUS));
++      pr_debug(DRIVER_NAME ": Caps:     0x%08x | Caps_1:   0x%08x\n",
++              bcm2835_mmc_readl(host, SDHCI_CAPABILITIES),
++              bcm2835_mmc_readl(host, SDHCI_CAPABILITIES_1));
++      pr_debug(DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
++              bcm2835_mmc_readw(host, SDHCI_COMMAND),
++              bcm2835_mmc_readl(host, SDHCI_MAX_CURRENT));
++      pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
++              bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2));
++
++      pr_debug(DRIVER_NAME ": ===========================================\n");
++}
++
++
++static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask)
++{
++      unsigned long timeout;
++      unsigned long flags;
++
++      spin_lock_irqsave(&host->lock, flags);
++      bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET);
++
++      if (mask & SDHCI_RESET_ALL)
++              host->clock = 0;
++
++      /* Wait max 100 ms */
++      timeout = 100;
++
++      /* hw clears the bit when it's done */
++      while (bcm2835_mmc_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
++              if (timeout == 0) {
++                      pr_err("%s: Reset 0x%x never completed.\n",
++                              mmc_hostname(host->mmc), (int)mask);
++                      bcm2835_mmc_dumpregs(host);
++                      return;
++              }
++              timeout--;
++              spin_unlock_irqrestore(&host->lock, flags);
++              mdelay(1);
++              spin_lock_irqsave(&host->lock, flags);
++      }
++
++      if (100-timeout > 10 && 100-timeout > host->max_delay) {
++              host->max_delay = 100-timeout;
++              pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
++      }
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
++
++static void bcm2835_mmc_init(struct bcm2835_host *host, int soft)
++{
++      unsigned long flags;
++      if (soft)
++              bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
++      else
++              bcm2835_mmc_reset(host, SDHCI_RESET_ALL);
++
++      host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
++                  SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
++                  SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
++                  SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
++                  SDHCI_INT_RESPONSE;
++
++      spin_lock_irqsave(&host->lock, flags);
++      bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 3);
++      bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 3);
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (soft) {
++              /* force clock reconfiguration */
++              host->clock = 0;
++              bcm2835_mmc_set_ios(host->mmc, &host->mmc->ios);
++      }
++}
++
++
++
++static void bcm2835_mmc_finish_data(struct bcm2835_host *host);
++
++static void bcm2835_mmc_dma_complete(void *param)
++{
++      struct bcm2835_host *host = param;
++      struct dma_chan *dma_chan;
++      unsigned long flags;
++      u32 dir_data;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (host->data && !(host->data->flags & MMC_DATA_WRITE)) {
++              /* otherwise handled in SDHCI IRQ */
++              dma_chan = host->dma_chan_rx;
++              dir_data = DMA_FROM_DEVICE;
++
++              dma_unmap_sg(dma_chan->device->dev,
++                   host->data->sg, host->data->sg_len,
++                   dir_data);
++
++              bcm2835_mmc_finish_data(host);
++      }
++
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_bcm2835_mmc_read_block_pio(struct bcm2835_host *host)
++{
++      unsigned long flags;
++      size_t blksize, len, chunk;
++
++      u32 uninitialized_var(scratch);
++      u8 *buf;
++
++      blksize = host->data->blksz;
++      chunk = 0;
++
++      local_irq_save(flags);
++
++      while (blksize) {
++              if (!sg_miter_next(&host->sg_miter))
++                      BUG();
++
++              len = min(host->sg_miter.length, blksize);
++
++              blksize -= len;
++              host->sg_miter.consumed = len;
++
++              buf = host->sg_miter.addr;
++
++              while (len) {
++                      if (chunk == 0) {
++                              scratch = bcm2835_mmc_readl(host, SDHCI_BUFFER);
++                              chunk = 4;
++                      }
++
++                      *buf = scratch & 0xFF;
++
++                      buf++;
++                      scratch >>= 8;
++                      chunk--;
++                      len--;
++              }
++      }
++
++      sg_miter_stop(&host->sg_miter);
++
++      local_irq_restore(flags);
++}
++
++static void bcm2835_bcm2835_mmc_write_block_pio(struct bcm2835_host *host)
++{
++      unsigned long flags;
++      size_t blksize, len, chunk;
++      u32 scratch;
++      u8 *buf;
++
++      blksize = host->data->blksz;
++      chunk = 0;
++      chunk = 0;
++      scratch = 0;
++
++      local_irq_save(flags);
++
++      while (blksize) {
++              if (!sg_miter_next(&host->sg_miter))
++                      BUG();
++
++              len = min(host->sg_miter.length, blksize);
++
++              blksize -= len;
++              host->sg_miter.consumed = len;
++
++              buf = host->sg_miter.addr;
++
++              while (len) {
++                      scratch |= (u32)*buf << (chunk * 8);
++
++                      buf++;
++                      chunk++;
++                      len--;
++
++                      if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
++                              mmc_raw_writel(host, scratch, SDHCI_BUFFER);
++                              chunk = 0;
++                              scratch = 0;
++                      }
++              }
++      }
++
++      sg_miter_stop(&host->sg_miter);
++
++      local_irq_restore(flags);
++}
++
++
++static void bcm2835_mmc_transfer_pio(struct bcm2835_host *host)
++{
++      u32 mask;
++
++      BUG_ON(!host->data);
++
++      if (host->blocks == 0)
++              return;
++
++      if (host->data->flags & MMC_DATA_READ)
++              mask = SDHCI_DATA_AVAILABLE;
++      else
++              mask = SDHCI_SPACE_AVAILABLE;
++
++      while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) {
++
++              if (host->data->flags & MMC_DATA_READ)
++                      bcm2835_bcm2835_mmc_read_block_pio(host);
++              else
++                      bcm2835_bcm2835_mmc_write_block_pio(host);
++
++              host->blocks--;
++
++              /* QUIRK used in sdhci.c removes the 'if' */
++              /* but it seems this is unnecessary */
++              if (host->blocks == 0)
++                      break;
++
++
++      }
++}
++
++
++static void bcm2835_mmc_transfer_dma(struct bcm2835_host *host)
++{
++      u32 len, dir_data, dir_slave;
++      struct dma_async_tx_descriptor *desc = NULL;
++      struct dma_chan *dma_chan;
++
++
++      WARN_ON(!host->data);
++
++      if (!host->data)
++              return;
++
++      if (host->blocks == 0)
++              return;
++
++      if (host->data->flags & MMC_DATA_READ) {
++              dma_chan = host->dma_chan_rx;
++              dir_data = DMA_FROM_DEVICE;
++              dir_slave = DMA_DEV_TO_MEM;
++      } else {
++              dma_chan = host->dma_chan_tx;
++              dir_data = DMA_TO_DEVICE;
++              dir_slave = DMA_MEM_TO_DEV;
++      }
++
++      BUG_ON(!dma_chan->device);
++      BUG_ON(!dma_chan->device->dev);
++      BUG_ON(!host->data->sg);
++
++      len = dma_map_sg(dma_chan->device->dev, host->data->sg,
++                       host->data->sg_len, dir_data);
++      if (len > 0) {
++              desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg,
++                                             len, dir_slave,
++                                             DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++      } else {
++              dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n");
++      }
++      if (desc) {
++              unsigned long flags;
++              spin_lock_irqsave(&host->lock, flags);
++              bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL |
++                                                  SDHCI_INT_SPACE_AVAIL);
++              host->tx_desc = desc;
++              desc->callback = bcm2835_mmc_dma_complete;
++              desc->callback_param = host;
++              spin_unlock_irqrestore(&host->lock, flags);
++              dmaengine_submit(desc);
++              dma_async_issue_pending(dma_chan);
++      }
++
++}
++
++
++
++static void bcm2835_mmc_set_transfer_irqs(struct bcm2835_host *host)
++{
++      u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
++      u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
++
++      if (host->use_dma)
++              host->ier = (host->ier & ~pio_irqs) | dma_irqs;
++      else
++              host->ier = (host->ier & ~dma_irqs) | pio_irqs;
++
++      bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 4);
++      bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 4);
++}
++
++
++static void bcm2835_mmc_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd)
++{
++      u8 count;
++      struct mmc_data *data = cmd->data;
++
++      WARN_ON(host->data);
++
++      if (data || (cmd->flags & MMC_RSP_BUSY)) {
++              count = TIMEOUT_VAL;
++              bcm2835_mmc_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
++      }
++
++      if (!data)
++              return;
++
++      /* Sanity checks */
++      BUG_ON(data->blksz * data->blocks > 524288);
++      BUG_ON(data->blksz > host->mmc->max_blk_size);
++      BUG_ON(data->blocks > 65535);
++
++      host->data = data;
++      host->data_early = 0;
++      host->data->bytes_xfered = 0;
++
++
++      if (!(host->flags & SDHCI_REQ_USE_DMA)) {
++              int flags;
++
++              flags = SG_MITER_ATOMIC;
++              if (host->data->flags & MMC_DATA_READ)
++                      flags |= SG_MITER_TO_SG;
++              else
++                      flags |= SG_MITER_FROM_SG;
++              sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
++              host->blocks = data->blocks;
++      }
++
++      host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER;
++
++      bcm2835_mmc_set_transfer_irqs(host);
++
++      /* Set the DMA boundary value and block size */
++      bcm2835_mmc_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
++              data->blksz), SDHCI_BLOCK_SIZE);
++      bcm2835_mmc_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
++
++      BUG_ON(!host->data);
++}
++
++static void bcm2835_mmc_set_transfer_mode(struct bcm2835_host *host,
++      struct mmc_command *cmd)
++{
++      u16 mode;
++      struct mmc_data *data = cmd->data;
++
++      if (data == NULL) {
++              /* clear Auto CMD settings for no data CMDs */
++              mode = bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE);
++              bcm2835_mmc_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
++                              SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
++              return;
++      }
++
++      WARN_ON(!host->data);
++
++      mode = SDHCI_TRNS_BLK_CNT_EN;
++
++      if ((mmc_op_multi(cmd->opcode) || data->blocks > 1)) {
++              mode |= SDHCI_TRNS_MULTI;
++
++              /*
++               * If we are sending CMD23, CMD12 never gets sent
++               * on successful completion (so no Auto-CMD12).
++               */
++              if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12))
++                      mode |= SDHCI_TRNS_AUTO_CMD12;
++              else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {
++                      mode |= SDHCI_TRNS_AUTO_CMD23;
++                      bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2, 5);
++              }
++      }
++
++      if (data->flags & MMC_DATA_READ)
++              mode |= SDHCI_TRNS_READ;
++      if (host->flags & SDHCI_REQ_USE_DMA)
++              mode |= SDHCI_TRNS_DMA;
++
++      bcm2835_mmc_writew(host, mode, SDHCI_TRANSFER_MODE);
++}
++
++void bcm2835_mmc_send_command(struct bcm2835_host *host, struct mmc_command *cmd)
++{
++      int flags;
++      u32 mask;
++      unsigned long timeout;
++
++      WARN_ON(host->cmd);
++
++      /* Wait max 10 ms */
++      timeout = 1000;
++
++      mask = SDHCI_CMD_INHIBIT;
++      if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
++              mask |= SDHCI_DATA_INHIBIT;
++
++      /* We shouldn't wait for data inihibit for stop commands, even
++         though they might use busy signaling */
++      if (host->mrq->data && (cmd == host->mrq->data->stop))
++              mask &= ~SDHCI_DATA_INHIBIT;
++
++      while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) {
++              if (timeout == 0) {
++                      pr_err("%s: Controller never released inhibit bit(s).\n",
++                              mmc_hostname(host->mmc));
++                      bcm2835_mmc_dumpregs(host);
++                      cmd->error = -EIO;
++                      tasklet_schedule(&host->finish_tasklet);
++                      return;
++              }
++              timeout--;
++              udelay(10);
++      }
++
++      if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) {
++              host->max_delay = (1000-timeout)/100;
++              pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
++      }
++
++      timeout = jiffies;
++      if (!cmd->data && cmd->busy_timeout > 9000)
++              timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
++      else
++              timeout += 10 * HZ;
++      mod_timer(&host->timer, timeout);
++
++      host->cmd = cmd;
++
++      bcm2835_mmc_prepare_data(host, cmd);
++
++      bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT, 6);
++
++      bcm2835_mmc_set_transfer_mode(host, cmd);
++
++      if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
++              pr_err("%s: Unsupported response type!\n",
++                      mmc_hostname(host->mmc));
++              cmd->error = -EINVAL;
++              tasklet_schedule(&host->finish_tasklet);
++              return;
++      }
++
++      if (!(cmd->flags & MMC_RSP_PRESENT))
++              flags = SDHCI_CMD_RESP_NONE;
++      else if (cmd->flags & MMC_RSP_136)
++              flags = SDHCI_CMD_RESP_LONG;
++      else if (cmd->flags & MMC_RSP_BUSY)
++              flags = SDHCI_CMD_RESP_SHORT_BUSY;
++      else
++              flags = SDHCI_CMD_RESP_SHORT;
++
++      if (cmd->flags & MMC_RSP_CRC)
++              flags |= SDHCI_CMD_CRC;
++      if (cmd->flags & MMC_RSP_OPCODE)
++              flags |= SDHCI_CMD_INDEX;
++
++      if (cmd->data)
++              flags |= SDHCI_CMD_DATA;
++
++      bcm2835_mmc_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
++}
++
++
++static void bcm2835_mmc_finish_data(struct bcm2835_host *host)
++{
++      struct mmc_data *data;
++
++      BUG_ON(!host->data);
++
++      data = host->data;
++      host->data = NULL;
++
++      if (data->error)
++              data->bytes_xfered = 0;
++      else
++              data->bytes_xfered = data->blksz * data->blocks;
++
++      /*
++       * Need to send CMD12 if -
++       * a) open-ended multiblock transfer (no CMD23)
++       * b) error in multiblock transfer
++       */
++      if (data->stop &&
++          (data->error ||
++           !host->mrq->sbc)) {
++
++              /*
++               * The controller needs a reset of internal state machines
++               * upon error conditions.
++               */
++              if (data->error) {
++                      bcm2835_mmc_reset(host, SDHCI_RESET_CMD);
++                      bcm2835_mmc_reset(host, SDHCI_RESET_DATA);
++              }
++
++              bcm2835_mmc_send_command(host, data->stop);
++      } else
++              tasklet_schedule(&host->finish_tasklet);
++}
++
++static void bcm2835_mmc_finish_command(struct bcm2835_host *host)
++{
++      int i;
++
++      BUG_ON(host->cmd == NULL);
++
++      if (host->cmd->flags & MMC_RSP_PRESENT) {
++              if (host->cmd->flags & MMC_RSP_136) {
++                      /* CRC is stripped so we need to do some shifting. */
++                      for (i = 0; i < 4; i++) {
++                              host->cmd->resp[i] = bcm2835_mmc_readl(host,
++                                      SDHCI_RESPONSE + (3-i)*4) << 8;
++                              if (i != 3)
++                                      host->cmd->resp[i] |=
++                                              bcm2835_mmc_readb(host,
++                                              SDHCI_RESPONSE + (3-i)*4-1);
++                      }
++              } else {
++                      host->cmd->resp[0] = bcm2835_mmc_readl(host, SDHCI_RESPONSE);
++              }
++      }
++
++      host->cmd->error = 0;
++
++      /* Finished CMD23, now send actual command. */
++      if (host->cmd == host->mrq->sbc) {
++              host->cmd = NULL;
++              bcm2835_mmc_send_command(host, host->mrq->cmd);
++
++              if (host->mrq->cmd->data && host->use_dma) {
++                      /* DMA transfer starts now, PIO starts after interrupt */
++                      bcm2835_mmc_transfer_dma(host);
++              }
++      } else {
++
++              /* Processed actual command. */
++              if (host->data && host->data_early)
++                      bcm2835_mmc_finish_data(host);
++
++              if (!host->cmd->data)
++                      tasklet_schedule(&host->finish_tasklet);
++
++              host->cmd = NULL;
++      }
++}
++
++
++static void bcm2835_mmc_timeout_timer(unsigned long data)
++{
++      struct bcm2835_host *host;
++      unsigned long flags;
++
++      host = (struct bcm2835_host *)data;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (host->mrq) {
++              pr_err("%s: Timeout waiting for hardware interrupt.\n",
++                      mmc_hostname(host->mmc));
++              bcm2835_mmc_dumpregs(host);
++
++              if (host->data) {
++                      host->data->error = -ETIMEDOUT;
++                      bcm2835_mmc_finish_data(host);
++              } else {
++                      if (host->cmd)
++                              host->cmd->error = -ETIMEDOUT;
++                      else
++                              host->mrq->cmd->error = -ETIMEDOUT;
++
++                      tasklet_schedule(&host->finish_tasklet);
++              }
++      }
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++
++static void bcm2835_mmc_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable)
++{
++      if (!(host->flags & SDHCI_DEVICE_DEAD)) {
++              if (enable)
++                      host->ier |= SDHCI_INT_CARD_INT;
++              else
++                      host->ier &= ~SDHCI_INT_CARD_INT;
++
++              bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 7);
++              bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 7);
++              mmiowb();
++      }
++}
++
++static void bcm2835_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++      struct bcm2835_host *host = mmc_priv(mmc);
++      unsigned long flags;
++
++      spin_lock_irqsave(&host->lock, flags);
++      if (enable)
++              host->flags |= SDHCI_SDIO_IRQ_ENABLED;
++      else
++              host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
++
++      bcm2835_mmc_enable_sdio_irq_nolock(host, enable);
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_mmc_cmd_irq(struct bcm2835_host *host, u32 intmask)
++{
++
++      BUG_ON(intmask == 0);
++
++      if (!host->cmd) {
++              pr_err("%s: Got command interrupt 0x%08x even "
++                      "though no command operation was in progress.\n",
++                      mmc_hostname(host->mmc), (unsigned)intmask);
++              bcm2835_mmc_dumpregs(host);
++              return;
++      }
++
++      if (intmask & SDHCI_INT_TIMEOUT)
++              host->cmd->error = -ETIMEDOUT;
++      else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
++                      SDHCI_INT_INDEX)) {
++                      host->cmd->error = -EILSEQ;
++      }
++
++      if (host->cmd->error) {
++              tasklet_schedule(&host->finish_tasklet);
++              return;
++      }
++
++      if (intmask & SDHCI_INT_RESPONSE)
++              bcm2835_mmc_finish_command(host);
++
++}
++
++static void bcm2835_mmc_data_irq(struct bcm2835_host *host, u32 intmask)
++{
++      struct dma_chan *dma_chan;
++      u32 dir_data;
++
++      BUG_ON(intmask == 0);
++
++      if (!host->data) {
++              /*
++               * The "data complete" interrupt is also used to
++               * indicate that a busy state has ended. See comment
++               * above in sdhci_cmd_irq().
++               */
++              if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
++                      if (intmask & SDHCI_INT_DATA_END) {
++                              bcm2835_mmc_finish_command(host);
++                              return;
++                      }
++              }
++
++              pr_debug("%s: Got data interrupt 0x%08x even "
++                      "though no data operation was in progress.\n",
++                      mmc_hostname(host->mmc), (unsigned)intmask);
++              bcm2835_mmc_dumpregs(host);
++
++              return;
++      }
++
++      if (intmask & SDHCI_INT_DATA_TIMEOUT)
++              host->data->error = -ETIMEDOUT;
++      else if (intmask & SDHCI_INT_DATA_END_BIT)
++              host->data->error = -EILSEQ;
++      else if ((intmask & SDHCI_INT_DATA_CRC) &&
++              SDHCI_GET_CMD(bcm2835_mmc_readw(host, SDHCI_COMMAND))
++                      != MMC_BUS_TEST_R)
++              host->data->error = -EILSEQ;
++
++      if (host->use_dma) {
++              if  (host->data->flags & MMC_DATA_WRITE) {
++                      /* IRQ handled here */
++
++                      dma_chan = host->dma_chan_tx;
++                      dir_data = DMA_TO_DEVICE;
++                      dma_unmap_sg(dma_chan->device->dev,
++                               host->data->sg, host->data->sg_len,
++                               dir_data);
++
++                      bcm2835_mmc_finish_data(host);
++              }
++
++      } else {
++              if (host->data->error)
++                      bcm2835_mmc_finish_data(host);
++              else {
++                      if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
++                              bcm2835_mmc_transfer_pio(host);
++
++                      if (intmask & SDHCI_INT_DATA_END) {
++                              if (host->cmd) {
++                                      /*
++                                       * Data managed to finish before the
++                                       * command completed. Make sure we do
++                                       * things in the proper order.
++                                       */
++                                      host->data_early = 1;
++                              } else {
++                                      bcm2835_mmc_finish_data(host);
++                              }
++                      }
++              }
++      }
++}
++
++
++static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id)
++{
++      irqreturn_t result = IRQ_NONE;
++      struct bcm2835_host *host = dev_id;
++      u32 intmask, mask, unexpected = 0;
++      int max_loops = 16;
++
++      spin_lock(&host->lock);
++
++      intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
++
++      if (!intmask || intmask == 0xffffffff) {
++              result = IRQ_NONE;
++              goto out;
++      }
++
++      do {
++              /* Clear selected interrupts. */
++              mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
++                                SDHCI_INT_BUS_POWER);
++              bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS, 8);
++
++
++              if (intmask & SDHCI_INT_CMD_MASK)
++                      bcm2835_mmc_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
++
++              if (intmask & SDHCI_INT_DATA_MASK)
++                      bcm2835_mmc_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
++
++              if (intmask & SDHCI_INT_BUS_POWER)
++                      pr_err("%s: Card is consuming too much power!\n",
++                              mmc_hostname(host->mmc));
++
++              if (intmask & SDHCI_INT_CARD_INT) {
++                      bcm2835_mmc_enable_sdio_irq_nolock(host, false);
++                      host->thread_isr |= SDHCI_INT_CARD_INT;
++                      result = IRQ_WAKE_THREAD;
++              }
++
++              intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
++                           SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
++                           SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
++                           SDHCI_INT_CARD_INT);
++
++              if (intmask) {
++                      unexpected |= intmask;
++                      bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS, 9);
++              }
++
++              if (result == IRQ_NONE)
++                      result = IRQ_HANDLED;
++
++              intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
++      } while (intmask && --max_loops);
++out:
++      spin_unlock(&host->lock);
++
++      if (unexpected) {
++              pr_err("%s: Unexpected interrupt 0x%08x.\n",
++                         mmc_hostname(host->mmc), unexpected);
++              bcm2835_mmc_dumpregs(host);
++      }
++
++      return result;
++}
++
++static irqreturn_t bcm2835_mmc_thread_irq(int irq, void *dev_id)
++{
++      struct bcm2835_host *host = dev_id;
++      unsigned long flags;
++      u32 isr;
++
++      spin_lock_irqsave(&host->lock, flags);
++      isr = host->thread_isr;
++      host->thread_isr = 0;
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (isr & SDHCI_INT_CARD_INT) {
++              sdio_run_irqs(host->mmc);
++
++              spin_lock_irqsave(&host->lock, flags);
++              if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
++                      bcm2835_mmc_enable_sdio_irq_nolock(host, true);
++              spin_unlock_irqrestore(&host->lock, flags);
++      }
++
++      return isr ? IRQ_HANDLED : IRQ_NONE;
++}
++
++
++
++void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock)
++{
++      int div = 0; /* Initialized for compiler warning */
++      int real_div = div, clk_mul = 1;
++      u16 clk = 0;
++      unsigned long timeout;
++      unsigned int input_clock = clock;
++
++      if (host->overclock_50 && (clock == 50000000))
++              clock = host->overclock_50 * 1000000 + 999999;
++
++      host->mmc->actual_clock = 0;
++
++      bcm2835_mmc_writew(host, 0, SDHCI_CLOCK_CONTROL);
++
++      if (clock == 0)
++              return;
++
++      /* Version 3.00 divisors must be a multiple of 2. */
++      if (host->max_clk <= clock)
++              div = 1;
++      else {
++              for (div = 2; div < SDHCI_MAX_DIV_SPEC_300;
++                       div += 2) {
++                      if ((host->max_clk / div) <= clock)
++                              break;
++              }
++      }
++
++      real_div = div;
++      div >>= 1;
++
++      if (real_div)
++              clock = (host->max_clk * clk_mul) / real_div;
++      host->mmc->actual_clock = clock;
++
++      if ((clock > input_clock) && (clock > host->max_overclock)) {
++              pr_warn("%s: Overclocking to %dHz\n",
++                      mmc_hostname(host->mmc), clock);
++              host->max_overclock = clock;
++      }
++
++      clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
++      clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
++              << SDHCI_DIVIDER_HI_SHIFT;
++      clk |= SDHCI_CLOCK_INT_EN;
++      bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
++
++      /* Wait max 20 ms */
++      timeout = 20;
++      while (!((clk = bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL))
++              & SDHCI_CLOCK_INT_STABLE)) {
++              if (timeout == 0) {
++                      pr_err("%s: Internal clock never "
++                              "stabilised.\n", mmc_hostname(host->mmc));
++                      bcm2835_mmc_dumpregs(host);
++                      return;
++              }
++              timeout--;
++              mdelay(1);
++      }
++
++      if (20-timeout > 10 && 20-timeout > host->max_delay) {
++              host->max_delay = 20-timeout;
++              pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
++      }
++
++      clk |= SDHCI_CLOCK_CARD_EN;
++      bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
++}
++
++static void bcm2835_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++      struct bcm2835_host *host;
++      unsigned long flags;
++
++      host = mmc_priv(mmc);
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      WARN_ON(host->mrq != NULL);
++
++      host->mrq = mrq;
++
++      if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
++              bcm2835_mmc_send_command(host, mrq->sbc);
++      else
++              bcm2835_mmc_send_command(host, mrq->cmd);
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (!(mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) && mrq->cmd->data && host->use_dma) {
++              /* DMA transfer starts now, PIO starts after interrupt */
++              bcm2835_mmc_transfer_dma(host);
++      }
++}
++
++
++static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++
++      struct bcm2835_host *host = mmc_priv(mmc);
++      unsigned long flags;
++      u8 ctrl;
++      u16 clk, ctrl_2;
++
++      pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n",
++               ios->clock, ios->power_mode, ios->bus_width,
++               ios->timing, ios->signal_voltage, ios->drv_type);
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (!ios->clock || ios->clock != host->clock) {
++              bcm2835_mmc_set_clock(host, ios->clock);
++              host->clock = ios->clock;
++      }
++
++      if (host->pwr != SDHCI_POWER_330) {
++              host->pwr = SDHCI_POWER_330;
++              bcm2835_mmc_writeb(host, SDHCI_POWER_330 | SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
++      }
++
++      ctrl = bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL);
++
++      /* set bus width */
++      ctrl &= ~SDHCI_CTRL_8BITBUS;
++      if (ios->bus_width == MMC_BUS_WIDTH_4)
++              ctrl |= SDHCI_CTRL_4BITBUS;
++      else
++              ctrl &= ~SDHCI_CTRL_4BITBUS;
++
++      ctrl &= ~SDHCI_CTRL_HISPD; /* NO_HISPD_BIT */
++
++
++      bcm2835_mmc_writeb(host, ctrl, SDHCI_HOST_CONTROL);
++      /*
++       * We only need to set Driver Strength if the
++       * preset value enable is not set.
++       */
++      ctrl_2 = bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2);
++      ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
++      if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
++              ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
++      else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C)
++              ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
++
++      bcm2835_mmc_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
++
++      /* Reset SD Clock Enable */
++      clk = bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL);
++      clk &= ~SDHCI_CLOCK_CARD_EN;
++      bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
++
++      /* Re-enable SD Clock */
++      bcm2835_mmc_set_clock(host, host->clock);
++      bcm2835_mmc_writeb(host, ctrl, SDHCI_HOST_CONTROL);
++
++      mmiowb();
++
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++
++static struct mmc_host_ops bcm2835_ops = {
++      .request = bcm2835_mmc_request,
++      .set_ios = bcm2835_mmc_set_ios,
++      .enable_sdio_irq = bcm2835_mmc_enable_sdio_irq,
++};
++
++
++static void bcm2835_mmc_tasklet_finish(unsigned long param)
++{
++      struct bcm2835_host *host;
++      unsigned long flags;
++      struct mmc_request *mrq;
++
++      host = (struct bcm2835_host *)param;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      /*
++       * If this tasklet gets rescheduled while running, it will
++       * be run again afterwards but without any active request.
++       */
++      if (!host->mrq) {
++              spin_unlock_irqrestore(&host->lock, flags);
++              return;
++      }
++
++      del_timer(&host->timer);
++
++      mrq = host->mrq;
++
++      /*
++       * The controller needs a reset of internal state machines
++       * upon error conditions.
++       */
++      if (!(host->flags & SDHCI_DEVICE_DEAD) &&
++          ((mrq->cmd && mrq->cmd->error) ||
++               (mrq->data && (mrq->data->error ||
++                (mrq->data->stop && mrq->data->stop->error))))) {
++
++              spin_unlock_irqrestore(&host->lock, flags);
++              bcm2835_mmc_reset(host, SDHCI_RESET_CMD);
++              bcm2835_mmc_reset(host, SDHCI_RESET_DATA);
++              spin_lock_irqsave(&host->lock, flags);
++      }
++
++      host->mrq = NULL;
++      host->cmd = NULL;
++      host->data = NULL;
++
++      mmiowb();
++
++      spin_unlock_irqrestore(&host->lock, flags);
++      mmc_request_done(host->mmc, mrq);
++}
++
++
++
++static int bcm2835_mmc_add_host(struct bcm2835_host *host)
++{
++      struct mmc_host *mmc = host->mmc;
++      struct device *dev = mmc->parent;
++#ifndef FORCE_PIO
++      struct dma_slave_config cfg;
++#endif
++      int ret;
++
++      bcm2835_mmc_reset(host, SDHCI_RESET_ALL);
++
++      host->clk_mul = 0;
++
++      mmc->f_max = host->max_clk;
++      mmc->f_max = host->max_clk;
++      mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
++
++      /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */
++      host->timeout_clk = mmc->f_max / 1000;
++      mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
++
++      /* host controller capabilities */
++      mmc->caps |= MMC_CAP_CMD23 | MMC_CAP_ERASE | MMC_CAP_NEEDS_POLL |
++              MMC_CAP_SDIO_IRQ | MMC_CAP_SD_HIGHSPEED |
++              MMC_CAP_MMC_HIGHSPEED | MMC_CAP_4_BIT_DATA;
++
++      mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
++
++      host->flags = SDHCI_AUTO_CMD23;
++
++      dev_info(dev, "mmc_debug:%x mmc_debug2:%x\n", mmc_debug, mmc_debug2);
++#ifdef FORCE_PIO
++      dev_info(dev, "Forcing PIO mode\n");
++      host->have_dma = false;
++#else
++      if (IS_ERR_OR_NULL(host->dma_chan_tx) ||
++          IS_ERR_OR_NULL(host->dma_chan_rx)) {
++              dev_err(dev, "%s: Unable to initialise DMA channels. Falling back to PIO\n",
++                      DRIVER_NAME);
++              host->have_dma = false;
++      } else {
++              dev_info(dev, "DMA channels allocated");
++              host->have_dma = true;
++
++              cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++              cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++              cfg.slave_id = 11;              /* DREQ channel */
++
++              cfg.direction = DMA_MEM_TO_DEV;
++              cfg.src_addr = 0;
++              cfg.dst_addr = host->bus_addr + SDHCI_BUFFER;
++              ret = dmaengine_slave_config(host->dma_chan_tx, &cfg);
++
++              cfg.direction = DMA_DEV_TO_MEM;
++              cfg.src_addr = host->bus_addr + SDHCI_BUFFER;
++              cfg.dst_addr = 0;
++              ret = dmaengine_slave_config(host->dma_chan_rx, &cfg);
++      }
++#endif
++      mmc->max_segs = 128;
++      mmc->max_req_size = 524288;
++      mmc->max_seg_size = mmc->max_req_size;
++      mmc->max_blk_size = 512;
++      mmc->max_blk_count =  65535;
++
++      /* report supported voltage ranges */
++      mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++
++      tasklet_init(&host->finish_tasklet,
++              bcm2835_mmc_tasklet_finish, (unsigned long)host);
++
++      setup_timer(&host->timer, bcm2835_mmc_timeout_timer, (unsigned long)host);
++      init_waitqueue_head(&host->buf_ready_int);
++
++      bcm2835_mmc_init(host, 0);
++      ret = devm_request_threaded_irq(dev, host->irq, bcm2835_mmc_irq,
++                                      bcm2835_mmc_thread_irq, IRQF_SHARED,
++                                      mmc_hostname(mmc), host);
++      if (ret) {
++              dev_err(dev, "Failed to request IRQ %d: %d\n", host->irq, ret);
++              goto untasklet;
++      }
++
++      mmiowb();
++      mmc_add_host(mmc);
++
++      return 0;
++
++untasklet:
++      tasklet_kill(&host->finish_tasklet);
++
++      return ret;
++}
++
++static int bcm2835_mmc_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct device_node *node = dev->of_node;
++      struct clk *clk;
++      struct resource *iomem;
++      struct bcm2835_host *host;
++      struct mmc_host *mmc;
++      const __be32 *addr;
++      int ret;
++
++      mmc = mmc_alloc_host(sizeof(*host), dev);
++      if (!mmc)
++              return -ENOMEM;
++
++      mmc->ops = &bcm2835_ops;
++      host = mmc_priv(mmc);
++      host->mmc = mmc;
++      host->timeout = msecs_to_jiffies(1000);
++      spin_lock_init(&host->lock);
++
++      iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      host->ioaddr = devm_ioremap_resource(dev, iomem);
++      if (IS_ERR(host->ioaddr)) {
++              ret = PTR_ERR(host->ioaddr);
++              goto err;
++      }
++
++      addr = of_get_address(node, 0, NULL, NULL);
++      if (!addr) {
++              dev_err(dev, "could not get DMA-register address\n");
++              return -ENODEV;
++      }
++      host->bus_addr = be32_to_cpup(addr);
++      pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
++               (unsigned long)host->ioaddr,
++               (unsigned long)iomem->start,
++               (unsigned long)host->bus_addr);
++
++#ifndef FORCE_PIO
++      if (node) {
++              host->dma_chan_tx = dma_request_slave_channel(dev, "tx");
++              host->dma_chan_rx = dma_request_slave_channel(dev, "rx");
++      } else {
++              dma_cap_mask_t mask;
++
++              dma_cap_zero(mask);
++              /* we don't care about the channel, any would work */
++              dma_cap_set(DMA_SLAVE, mask);
++              host->dma_chan_tx = dma_request_channel(mask, NULL, NULL);
++              host->dma_chan_rx = dma_request_channel(mask, NULL, NULL);
++      }
++#endif
++      clk = devm_clk_get(dev, NULL);
++      if (IS_ERR(clk)) {
++              dev_err(dev, "could not get clk\n");
++              ret = PTR_ERR(clk);
++              goto err;
++      }
++
++      host->max_clk = clk_get_rate(clk);
++
++      host->irq = platform_get_irq(pdev, 0);
++      if (host->irq <= 0) {
++              dev_err(dev, "get IRQ failed\n");
++              ret = -EINVAL;
++              goto err;
++      }
++
++      if (node) {
++              mmc_of_parse(mmc);
++
++              /* Read any custom properties */
++              of_property_read_u32(node,
++                                   "brcm,overclock-50",
++                                   &host->overclock_50);
++      } else {
++              mmc->caps |= MMC_CAP_4_BIT_DATA;
++      }
++
++      ret = bcm2835_mmc_add_host(host);
++      if (ret)
++              goto err;
++
++      platform_set_drvdata(pdev, host);
++
++      return 0;
++err:
++      mmc_free_host(mmc);
++
++      return ret;
++}
++
++static int bcm2835_mmc_remove(struct platform_device *pdev)
++{
++      struct bcm2835_host *host = platform_get_drvdata(pdev);
++      unsigned long flags;
++      int dead;
++      u32 scratch;
++
++      dead = 0;
++      scratch = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
++      if (scratch == (u32)-1)
++              dead = 1;
++
++
++      if (dead) {
++              spin_lock_irqsave(&host->lock, flags);
++
++              host->flags |= SDHCI_DEVICE_DEAD;
++
++              if (host->mrq) {
++                      pr_err("%s: Controller removed during "
++                              " transfer!\n", mmc_hostname(host->mmc));
++
++                      host->mrq->cmd->error = -ENOMEDIUM;
++                      tasklet_schedule(&host->finish_tasklet);
++              }
++
++              spin_unlock_irqrestore(&host->lock, flags);
++      }
++
++      mmc_remove_host(host->mmc);
++
++      if (!dead)
++              bcm2835_mmc_reset(host, SDHCI_RESET_ALL);
++
++      free_irq(host->irq, host);
++
++      del_timer_sync(&host->timer);
++
++      tasklet_kill(&host->finish_tasklet);
++
++      mmc_free_host(host->mmc);
++      platform_set_drvdata(pdev, NULL);
++
++      return 0;
++}
++
++
++static const struct of_device_id bcm2835_mmc_match[] = {
++      { .compatible = "brcm,bcm2835-mmc" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, bcm2835_mmc_match);
++
++
++
++static struct platform_driver bcm2835_mmc_driver = {
++      .probe      = bcm2835_mmc_probe,
++      .remove     = bcm2835_mmc_remove,
++      .driver     = {
++              .name           = DRIVER_NAME,
++              .owner          = THIS_MODULE,
++              .of_match_table = bcm2835_mmc_match,
++      },
++};
++module_platform_driver(bcm2835_mmc_driver);
++
++module_param(mmc_debug, uint, 0644);
++module_param(mmc_debug2, uint, 0644);
++MODULE_ALIAS("platform:mmc-bcm2835");
++MODULE_DESCRIPTION("BCM2835 SDHCI driver");
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Gellert Weisz");
diff --git a/target/linux/brcm2708/patches-4.4/0033-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch b/target/linux/brcm2708/patches-4.4/0033-Adding-bcm2835-sdhost-driver-and-an-overlay-to-enabl.patch
new file mode 100644 (file)
index 0000000..46b07df
--- /dev/null
@@ -0,0 +1,2022 @@
+From c58bec0d84082837415562c6567396e9e5ba62f7 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 25 Mar 2015 17:49:47 +0000
+Subject: [PATCH 033/232] Adding bcm2835-sdhost driver, and an overlay to
+ enable it
+
+BCM2835 has two SD card interfaces. This driver uses the other one.
+
+bcm2835-sdhost: Error handling fix, and code clarification
+
+bcm2835-sdhost: Adding overclocking option
+
+Allow a different clock speed to be substitued for a requested 50MHz.
+This option is exposed using the "overclock_50" DT parameter.
+Note that the sdhost interface is restricted to integer divisions of
+core_freq, and the highest sensible option for a core_freq of 250MHz
+is 84 (250/3 = 83.3MHz), the next being 125 (250/2) which is much too
+high.
+
+Use at your own risk.
+
+bcm2835-sdhost: Round up the overclock, so 62 works for 62.5Mhz
+
+Also only warn once for each overclock setting.
+
+bcm2835-sdhost: Improve error handling and recovery
+
+1) Expose the hw_reset method to the MMC framework, removing many
+   internal calls by the driver.
+
+2) Reduce overclock setting on error.
+
+3) Increase timeout to cope with high capacity cards.
+
+4) Add properties and parameters to control pio_limit and debug.
+
+5) Reduce messages at probe time.
+
+bcm2835-sdhost: Further improve overclock back-off
+
+bcm2835-sdhost: Clear HBLC for PIO mode
+
+Also update pio_limit default in overlay README.
+
+bcm2835-sdhost: Add the ERASE capability
+
+See: https://github.com/raspberrypi/linux/issues/1076
+
+bcm2835-sdhost: Ignore CRC7 for MMC CMD1
+
+It seems that the sdhost interface returns CRC7 errors for CMD1,
+which is the MMC-specific SEND_OP_COND. Returning these errors to
+the MMC layer causes a downward spiral, but ignoring them seems
+to be harmless.
+
+bcm2835-mmc/sdhost: Remove ARCH_BCM2835 differences
+
+The bcm2835-mmc driver (and -sdhost driver that copied from it)
+contains code to handle SDIO interrupts in a threaded interrupt
+handler rather than waking the MMC framework thread. The change
+follows a patch from Russell King that adds the facility as the
+preferred way of working.
+
+However, the new code path is only present in ARCH_BCM2835
+builds, which I have taken to be a way of testing the waters
+rather than making the change across the board; I can't see
+any technical reason why it wouldn't be enabled for MACH_BCM270X
+builds. So this patch standardises on the ARCH_BCM2835 code,
+removing the old code paths.
+
+bcm2835-sdhost: Don't log timeout errors unless debug=1
+
+The MMC card-discovery process generates timeouts. This is
+expected behaviour, so reporting it to the user serves no purpose.
+Suppress the reporting of timeout errors unless the debug flag
+is on.
+---
+ drivers/mmc/host/Kconfig          |   10 +
+ drivers/mmc/host/Makefile         |    1 +
+ drivers/mmc/host/bcm2835-sdhost.c | 1907 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1918 insertions(+)
+ create mode 100644 drivers/mmc/host/bcm2835-sdhost.c
+
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER
+         If unsure, say 2 here.
++config MMC_BCM2835_SDHOST
++      tristate "Support for the SDHost controller on BCM2708/9"
++      depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835
++      help
++        This selects the SDHost controller on BCM2835/6.
++
++        If you have a controller with this interface, say Y or M here.
++
++        If unsure, say N.
++
+ config MMC_ARMMMCI
+       tristate "ARM AMBA Multimedia Card Interface support"
+       depends on ARM_AMBA
+--- a/drivers/mmc/host/Makefile
++++ b/drivers/mmc/host/Makefile
+@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C)  += sdhci-s3c
+ obj-$(CONFIG_MMC_SDHCI_SIRF)          += sdhci-sirf.o
+ obj-$(CONFIG_MMC_SDHCI_F_SDH30)       += sdhci_f_sdh30.o
+ obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
++obj-$(CONFIG_MMC_BCM2835_SDHOST)      += bcm2835-sdhost.o
+ obj-$(CONFIG_MMC_BCM2835)     += bcm2835-mmc.o
+ obj-$(CONFIG_MMC_WBSD)                += wbsd.o
+ obj-$(CONFIG_MMC_AU1X)                += au1xmmc.o
+--- /dev/null
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -0,0 +1,1907 @@
++/*
++ * BCM2835 SD host driver.
++ *
++ * Author:      Phil Elwell <phil@raspberrypi.org>
++ *              Copyright 2015
++ *
++ * Based on
++ *  mmc-bcm2835.c by Gellert Weisz
++ * which is, in turn, based on
++ *  sdhci-bcm2708.c by Broadcom
++ *  sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko
++ *  sdhci.c and sdhci-pci.c by Pierre Ossman
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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/>.
++ */
++
++#define SAFE_READ_THRESHOLD     4
++#define SAFE_WRITE_THRESHOLD    4
++#define ALLOW_DMA               1
++#define ALLOW_CMD23             0
++#define ALLOW_FAST              1
++#define USE_BLOCK_IRQ           1
++
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/sd.h>
++#include <linux/scatterlist.h>
++#include <linux/of_address.h>
++#include <linux/of_irq.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/blkdev.h>
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
++#include <linux/of_dma.h>
++#include <linux/time.h>
++
++#define DRIVER_NAME "sdhost-bcm2835"
++
++#define SDCMD  0x00 /* Command to SD card              - 16 R/W */
++#define SDARG  0x04 /* Argument to SD card             - 32 R/W */
++#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
++#define SDCDIV 0x0c /* Start value for clock divider   - 11 R/W */
++#define SDRSP0 0x10 /* SD card response (31:0)         - 32 R   */
++#define SDRSP1 0x14 /* SD card response (63:32)        - 32 R   */
++#define SDRSP2 0x18 /* SD card response (95:64)        - 32 R   */
++#define SDRSP3 0x1c /* SD card response (127:96)       - 32 R   */
++#define SDHSTS 0x20 /* SD host status                  - 11 R   */
++#define SDVDD  0x30 /* SD card power control           -  1 R/W */
++#define SDEDM  0x34 /* Emergency Debug Mode            - 13 R/W */
++#define SDHCFG 0x38 /* Host configuration              -  2 R/W */
++#define SDHBCT 0x3c /* Host byte count (debug)         - 32 R/W */
++#define SDDATA 0x40 /* Data to/from SD card            - 32 R/W */
++#define SDHBLC 0x50 /* Host block count (SDIO/SDHC)    -  9 R/W */
++
++#define SDCMD_NEW_FLAG                  0x8000
++#define SDCMD_FAIL_FLAG                 0x4000
++#define SDCMD_BUSYWAIT                  0x800
++#define SDCMD_NO_RESPONSE               0x400
++#define SDCMD_LONG_RESPONSE             0x200
++#define SDCMD_WRITE_CMD                 0x80
++#define SDCMD_READ_CMD                  0x40
++#define SDCMD_CMD_MASK                  0x3f
++
++#define SDCDIV_MAX_CDIV                 0x7ff
++
++#define SDHSTS_BUSY_IRPT                0x400
++#define SDHSTS_BLOCK_IRPT               0x200
++#define SDHSTS_SDIO_IRPT                0x100
++#define SDHSTS_REW_TIME_OUT             0x80
++#define SDHSTS_CMD_TIME_OUT             0x40
++#define SDHSTS_CRC16_ERROR              0x20
++#define SDHSTS_CRC7_ERROR               0x10
++#define SDHSTS_FIFO_ERROR               0x08
++/* Reserved */
++/* Reserved */
++#define SDHSTS_DATA_FLAG                0x01
++
++#define SDHSTS_TRANSFER_ERROR_MASK      (SDHSTS_CRC7_ERROR|SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR)
++#define SDHSTS_ERROR_MASK               (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK)
++
++#define SDHCFG_BUSY_IRPT_EN     (1<<10)
++#define SDHCFG_BLOCK_IRPT_EN    (1<<8)
++#define SDHCFG_SDIO_IRPT_EN     (1<<5)
++#define SDHCFG_DATA_IRPT_EN     (1<<4)
++#define SDHCFG_SLOW_CARD        (1<<3)
++#define SDHCFG_WIDE_EXT_BUS     (1<<2)
++#define SDHCFG_WIDE_INT_BUS     (1<<1)
++#define SDHCFG_REL_CMD_LINE     (1<<0)
++
++#define SDEDM_FORCE_DATA_MODE   (1<<19)
++#define SDEDM_CLOCK_PULSE       (1<<20)
++#define SDEDM_BYPASS            (1<<21)
++
++#define SDEDM_WRITE_THRESHOLD_SHIFT 9
++#define SDEDM_READ_THRESHOLD_SHIFT 14
++#define SDEDM_THRESHOLD_MASK     0x1f
++
++#define MHZ 1000000
++
++
++struct bcm2835_host {
++      spinlock_t              lock;
++
++      void __iomem            *ioaddr;
++      u32                     bus_addr;
++
++      struct mmc_host         *mmc;
++
++      u32                     pio_timeout;    /* In jiffies */
++
++      int                     clock;          /* Current clock speed */
++
++      bool                    slow_card;      /* Force 11-bit divisor */
++
++      unsigned int            max_clk;        /* Max possible freq */
++
++      struct tasklet_struct   finish_tasklet; /* Tasklet structures */
++
++      struct timer_list       timer;          /* Timer for timeouts */
++
++      struct timer_list       pio_timer;      /* PIO error detection timer */
++
++      struct sg_mapping_iter  sg_miter;       /* SG state for PIO */
++      unsigned int            blocks;         /* remaining PIO blocks */
++
++      int                     irq;            /* Device IRQ */
++
++
++      /* cached registers */
++      u32                     hcfg;
++      u32                     cdiv;
++
++      struct mmc_request              *mrq;                   /* Current request */
++      struct mmc_command              *cmd;                   /* Current command */
++      struct mmc_data                 *data;                  /* Current data request */
++      unsigned int                    data_complete:1;        /* Data finished before cmd */
++
++      unsigned int                    flush_fifo:1;           /* Drain the fifo when finishing */
++
++      unsigned int                    use_busy:1;             /* Wait for busy interrupt */
++
++      unsigned int                    debug:1;                /* Enable debug output */
++
++      u32                             thread_isr;
++
++      /*DMA part*/
++      struct dma_chan                 *dma_chan_rx;           /* DMA channel for reads */
++      struct dma_chan                 *dma_chan_tx;           /* DMA channel for writes */
++
++      bool                            allow_dma;
++      bool                            have_dma;
++      bool                            use_dma;
++      /*end of DMA part*/
++
++      int                             max_delay;      /* maximum length of time spent waiting */
++      struct timeval                  stop_time;      /* when the last stop was issued */
++      u32                             delay_after_stop; /* minimum time between stop and subsequent data transfer */
++      u32                             overclock_50;   /* frequency to use when 50MHz is requested (in MHz) */
++      u32                             overclock;      /* Current frequency if overclocked, else zero */
++      u32                             pio_limit;      /* Maximum block count for PIO (0 = always DMA) */
++};
++
++
++static inline void bcm2835_sdhost_write(struct bcm2835_host *host, u32 val, int reg)
++{
++      writel(val, host->ioaddr + reg);
++}
++
++static inline u32 bcm2835_sdhost_read(struct bcm2835_host *host, int reg)
++{
++      return readl(host->ioaddr + reg);
++}
++
++static inline u32 bcm2835_sdhost_read_relaxed(struct bcm2835_host *host, int reg)
++{
++      return readl_relaxed(host->ioaddr + reg);
++}
++
++static void bcm2835_sdhost_dumpcmd(struct bcm2835_host *host,
++                                 struct mmc_command *cmd,
++                                 const char *label)
++{
++      if (cmd)
++              pr_info("%s:%c%s op %d arg 0x%x flags 0x%x - resp %08x %08x %08x %08x, err %d\n",
++                      mmc_hostname(host->mmc),
++                      (cmd == host->cmd) ? '>' : ' ',
++                      label, cmd->opcode, cmd->arg, cmd->flags,
++                      cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3],
++                      cmd->error);
++}
++
++static void bcm2835_sdhost_dumpregs(struct bcm2835_host *host)
++{
++      bcm2835_sdhost_dumpcmd(host, host->mrq->sbc, "sbc");
++      bcm2835_sdhost_dumpcmd(host, host->mrq->cmd, "cmd");
++      if (host->mrq->data)
++              pr_err("%s: data blocks %x blksz %x - err %d\n",
++                     mmc_hostname(host->mmc),
++                     host->mrq->data->blocks,
++                     host->mrq->data->blksz,
++                     host->mrq->data->error);
++      bcm2835_sdhost_dumpcmd(host, host->mrq->stop, "stop");
++
++      pr_info("%s: =========== REGISTER DUMP ===========\n",
++              mmc_hostname(host->mmc));
++
++      pr_info("%s: SDCMD  0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDCMD));
++      pr_info("%s: SDARG  0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDARG));
++      pr_info("%s: SDTOUT 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDTOUT));
++      pr_info("%s: SDCDIV 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDCDIV));
++      pr_info("%s: SDRSP0 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDRSP0));
++      pr_info("%s: SDRSP1 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDRSP1));
++      pr_info("%s: SDRSP2 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDRSP2));
++      pr_info("%s: SDRSP3 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDRSP3));
++      pr_info("%s: SDHSTS 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDHSTS));
++      pr_info("%s: SDVDD  0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDVDD));
++      pr_info("%s: SDEDM  0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDEDM));
++      pr_info("%s: SDHCFG 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDHCFG));
++      pr_info("%s: SDHBCT 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDHBCT));
++      pr_info("%s: SDHBLC 0x%08x\n",
++              mmc_hostname(host->mmc),
++              bcm2835_sdhost_read(host, SDHBLC));
++
++      pr_info("%s: ===========================================\n",
++              mmc_hostname(host->mmc));
++}
++
++
++static void bcm2835_sdhost_set_power(struct bcm2835_host *host, bool on)
++{
++      bcm2835_sdhost_write(host, on ? 1 : 0, SDVDD);
++}
++
++
++static void bcm2835_sdhost_reset_internal(struct bcm2835_host *host)
++{
++      u32 temp;
++
++      bcm2835_sdhost_set_power(host, false);
++
++      bcm2835_sdhost_write(host, 0, SDCMD);
++      bcm2835_sdhost_write(host, 0, SDARG);
++      bcm2835_sdhost_write(host, 0xf00000, SDTOUT);
++      bcm2835_sdhost_write(host, 0, SDCDIV);
++      bcm2835_sdhost_write(host, 0x7f8, SDHSTS); /* Write 1s to clear */
++      bcm2835_sdhost_write(host, 0, SDHCFG);
++      bcm2835_sdhost_write(host, 0, SDHBCT);
++      bcm2835_sdhost_write(host, 0, SDHBLC);
++
++      /* Limit fifo usage due to silicon bug */
++      temp = bcm2835_sdhost_read(host, SDEDM);
++      temp &= ~((SDEDM_THRESHOLD_MASK<<SDEDM_READ_THRESHOLD_SHIFT) |
++                (SDEDM_THRESHOLD_MASK<<SDEDM_WRITE_THRESHOLD_SHIFT));
++      temp |= (SAFE_READ_THRESHOLD << SDEDM_READ_THRESHOLD_SHIFT) |
++              (SAFE_WRITE_THRESHOLD << SDEDM_WRITE_THRESHOLD_SHIFT);
++      bcm2835_sdhost_write(host, temp, SDEDM);
++      mdelay(10);
++      bcm2835_sdhost_set_power(host, true);
++      mdelay(10);
++      host->clock = 0;
++      bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++      bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
++      mmiowb();
++}
++
++
++static void bcm2835_sdhost_reset(struct mmc_host *mmc)
++{
++      struct bcm2835_host *host = mmc_priv(mmc);
++      unsigned long flags;
++      if (host->debug)
++              pr_info("%s: reset\n", mmc_hostname(mmc));
++      spin_lock_irqsave(&host->lock, flags);
++
++      bcm2835_sdhost_reset_internal(host);
++
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
++
++static void bcm2835_sdhost_init(struct bcm2835_host *host, int soft)
++{
++      pr_debug("bcm2835_sdhost_init(%d)\n", soft);
++
++      /* Set interrupt enables */
++      host->hcfg = SDHCFG_BUSY_IRPT_EN;
++
++      bcm2835_sdhost_reset_internal(host);
++
++      if (soft) {
++              /* force clock reconfiguration */
++              host->clock = 0;
++              bcm2835_sdhost_set_ios(host->mmc, &host->mmc->ios);
++      }
++}
++
++static bool bcm2835_sdhost_is_write_complete(struct bcm2835_host *host)
++{
++      bool write_complete = ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1);
++
++      if (!write_complete) {
++              /* Request an IRQ for the last block */
++              host->hcfg |= SDHCFG_BLOCK_IRPT_EN;
++              bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++              if ((bcm2835_sdhost_read(host, SDEDM) & 0xf) == 1) {
++                      /* The write has now completed. Disable the interrupt
++                         and clear the status flag */
++                      host->hcfg &= ~SDHCFG_BLOCK_IRPT_EN;
++                      bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++                      bcm2835_sdhost_write(host, SDHSTS_BLOCK_IRPT, SDHSTS);
++                      write_complete = true;
++              }
++      }
++
++      return write_complete;
++}
++
++static void bcm2835_sdhost_wait_write_complete(struct bcm2835_host *host)
++{
++      int timediff;
++#ifdef DEBUG
++      static struct timeval start_time;
++      static int max_stall_time = 0;
++      static int total_stall_time = 0;
++      struct timeval before, after;
++
++      do_gettimeofday(&before);
++      if (max_stall_time == 0)
++              start_time = before;
++#endif
++
++      timediff = 0;
++
++      while (1) {
++              u32 edm = bcm2835_sdhost_read(host, SDEDM);
++              if ((edm & 0xf) == 1)
++                      break;
++              timediff++;
++              if (timediff > 5000000) {
++#ifdef DEBUG
++                      do_gettimeofday(&after);
++                      timediff = (after.tv_sec - before.tv_sec)*1000000 +
++                              (after.tv_usec - before.tv_usec);
++
++                      pr_err(" wait_write_complete - still waiting after %dus\n",
++                             timediff);
++#else
++                      pr_err(" wait_write_complete - still waiting after %d retries\n",
++                             timediff);
++#endif
++                      bcm2835_sdhost_dumpregs(host);
++                      host->data->error = -ETIMEDOUT;
++                      return;
++              }
++      }
++
++#ifdef DEBUG
++      do_gettimeofday(&after);
++      timediff = (after.tv_sec - before.tv_sec)*1000000 + (after.tv_usec - before.tv_usec);
++
++      total_stall_time += timediff;
++      if (timediff > max_stall_time)
++              max_stall_time = timediff;
++
++      if ((after.tv_sec - start_time.tv_sec) > 10) {
++              pr_debug(" wait_write_complete - max wait %dus, total %dus\n",
++                       max_stall_time, total_stall_time);
++              start_time = after;
++              max_stall_time = 0;
++              total_stall_time = 0;
++      }
++#endif
++}
++
++static void bcm2835_sdhost_finish_data(struct bcm2835_host *host);
++
++static void bcm2835_sdhost_dma_complete(void *param)
++{
++      struct bcm2835_host *host = param;
++      struct dma_chan *dma_chan;
++      unsigned long flags;
++      u32 dir_data;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (host->data) {
++              bool write_complete;
++              if (USE_BLOCK_IRQ)
++                      write_complete = bcm2835_sdhost_is_write_complete(host);
++              else {
++                      bcm2835_sdhost_wait_write_complete(host);
++                      write_complete = true;
++              }
++              pr_debug("dma_complete() - write_complete=%d\n",
++                       write_complete);
++
++              if (write_complete || (host->data->flags & MMC_DATA_READ))
++              {
++                      if (write_complete) {
++                              dma_chan = host->dma_chan_tx;
++                              dir_data = DMA_TO_DEVICE;
++                      } else {
++                              dma_chan = host->dma_chan_rx;
++                              dir_data = DMA_FROM_DEVICE;
++                      }
++
++                      dma_unmap_sg(dma_chan->device->dev,
++                                   host->data->sg, host->data->sg_len,
++                                   dir_data);
++
++                      bcm2835_sdhost_finish_data(host);
++              }
++      }
++
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static bool data_transfer_wait(struct bcm2835_host *host)
++{
++      unsigned long timeout = 1000000;
++      while (timeout)
++      {
++              u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS);
++              if (sdhsts & SDHSTS_DATA_FLAG) {
++                      bcm2835_sdhost_write(host, SDHSTS_DATA_FLAG, SDHSTS);
++                      break;
++              }
++              timeout--;
++      }
++      if (timeout == 0) {
++          pr_err("%s: Data %s timeout\n",
++                 mmc_hostname(host->mmc),
++                 (host->data->flags & MMC_DATA_READ) ? "read" : "write");
++          bcm2835_sdhost_dumpregs(host);
++          host->data->error = -ETIMEDOUT;
++          return false;
++      }
++      return true;
++}
++
++static void bcm2835_sdhost_read_block_pio(struct bcm2835_host *host)
++{
++      unsigned long flags;
++      size_t blksize, len;
++      u32 *buf;
++
++      blksize = host->data->blksz;
++
++      local_irq_save(flags);
++
++      while (blksize) {
++              if (!sg_miter_next(&host->sg_miter))
++                      BUG();
++
++              len = min(host->sg_miter.length, blksize);
++              BUG_ON(len % 4);
++
++              blksize -= len;
++              host->sg_miter.consumed = len;
++
++              buf = (u32 *)host->sg_miter.addr;
++
++              while (len) {
++                      if (!data_transfer_wait(host))
++                              break;
++
++                      *(buf++) = bcm2835_sdhost_read(host, SDDATA);
++                      len -= 4;
++              }
++
++              if (host->data->error)
++                      break;
++      }
++
++      sg_miter_stop(&host->sg_miter);
++
++      local_irq_restore(flags);
++}
++
++static void bcm2835_sdhost_write_block_pio(struct bcm2835_host *host)
++{
++      unsigned long flags;
++      size_t blksize, len;
++      u32 *buf;
++
++      blksize = host->data->blksz;
++
++      local_irq_save(flags);
++
++      while (blksize) {
++              if (!sg_miter_next(&host->sg_miter))
++                      BUG();
++
++              len = min(host->sg_miter.length, blksize);
++              BUG_ON(len % 4);
++
++              blksize -= len;
++              host->sg_miter.consumed = len;
++
++              buf = host->sg_miter.addr;
++
++              while (len) {
++                      if (!data_transfer_wait(host))
++                              break;
++
++                      bcm2835_sdhost_write(host, *(buf++), SDDATA);
++                      len -= 4;
++              }
++
++              if (host->data->error)
++                      break;
++      }
++
++      sg_miter_stop(&host->sg_miter);
++
++      local_irq_restore(flags);
++}
++
++
++static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host)
++{
++      u32 sdhsts;
++      bool is_read;
++      BUG_ON(!host->data);
++
++      is_read = (host->data->flags & MMC_DATA_READ) != 0;
++      if (is_read)
++              bcm2835_sdhost_read_block_pio(host);
++      else
++              bcm2835_sdhost_write_block_pio(host);
++
++      sdhsts = bcm2835_sdhost_read(host, SDHSTS);
++      if (sdhsts & (SDHSTS_CRC16_ERROR |
++                    SDHSTS_CRC7_ERROR |
++                    SDHSTS_FIFO_ERROR)) {
++              pr_err("%s: %s transfer error - HSTS %x\n",
++                     mmc_hostname(host->mmc),
++                     is_read ? "read" : "write",
++                     sdhsts);
++              host->data->error = -EILSEQ;
++      } else if ((sdhsts & (SDHSTS_CMD_TIME_OUT |
++                            SDHSTS_REW_TIME_OUT))) {
++              pr_err("%s: %s timeout error - HSTS %x\n",
++                     mmc_hostname(host->mmc),
++                     is_read ? "read" : "write",
++                     sdhsts);
++              host->data->error = -ETIMEDOUT;
++      } else if (!is_read && !host->data->error) {
++              /* Start a timer in case a transfer error occurs because
++                 there is no error interrupt */
++              mod_timer(&host->pio_timer, jiffies + host->pio_timeout);
++      }
++}
++
++
++static void bcm2835_sdhost_transfer_dma(struct bcm2835_host *host)
++{
++      u32 len, dir_data, dir_slave;
++      struct dma_async_tx_descriptor *desc = NULL;
++      struct dma_chan *dma_chan;
++
++      pr_debug("bcm2835_sdhost_transfer_dma()\n");
++
++      WARN_ON(!host->data);
++
++      if (!host->data)
++              return;
++
++      if (host->data->flags & MMC_DATA_READ) {
++              dma_chan = host->dma_chan_rx;
++              dir_data = DMA_FROM_DEVICE;
++              dir_slave = DMA_DEV_TO_MEM;
++      } else {
++              dma_chan = host->dma_chan_tx;
++              dir_data = DMA_TO_DEVICE;
++              dir_slave = DMA_MEM_TO_DEV;
++      }
++
++      BUG_ON(!dma_chan->device);
++      BUG_ON(!dma_chan->device->dev);
++      BUG_ON(!host->data->sg);
++
++      len = dma_map_sg(dma_chan->device->dev, host->data->sg,
++                       host->data->sg_len, dir_data);
++      if (len > 0) {
++              desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg,
++                                             len, dir_slave,
++                                             DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++      } else {
++              dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n");
++      }
++      if (desc) {
++              desc->callback = bcm2835_sdhost_dma_complete;
++              desc->callback_param = host;
++              dmaengine_submit(desc);
++              dma_async_issue_pending(dma_chan);
++      }
++
++}
++
++
++static void bcm2835_sdhost_set_transfer_irqs(struct bcm2835_host *host)
++{
++      u32 all_irqs = SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN |
++              SDHCFG_BUSY_IRPT_EN;
++      if (host->use_dma)
++              host->hcfg = (host->hcfg & ~all_irqs) |
++                      SDHCFG_BUSY_IRPT_EN;
++      else
++              host->hcfg = (host->hcfg & ~all_irqs) |
++                      SDHCFG_DATA_IRPT_EN |
++                      SDHCFG_BUSY_IRPT_EN;
++
++      bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++}
++
++
++static void bcm2835_sdhost_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd)
++{
++      struct mmc_data *data = cmd->data;
++
++      WARN_ON(host->data);
++
++      if (!data)
++              return;
++
++      /* Sanity checks */
++      BUG_ON(data->blksz * data->blocks > 524288);
++      BUG_ON(data->blksz > host->mmc->max_blk_size);
++      BUG_ON(data->blocks > 65535);
++
++      host->data = data;
++      host->data_complete = 0;
++      host->flush_fifo = 0;
++      host->data->bytes_xfered = 0;
++
++      host->use_dma = host->have_dma && (data->blocks > host->pio_limit);
++      if (!host->use_dma) {
++              int flags;
++
++              flags = SG_MITER_ATOMIC;
++              if (data->flags & MMC_DATA_READ)
++                      flags |= SG_MITER_TO_SG;
++              else
++                      flags |= SG_MITER_FROM_SG;
++              sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
++              host->blocks = data->blocks;
++      }
++
++      bcm2835_sdhost_set_transfer_irqs(host);
++
++      bcm2835_sdhost_write(host, data->blksz, SDHBCT);
++      bcm2835_sdhost_write(host, host->use_dma ? data->blocks : 0, SDHBLC);
++
++      BUG_ON(!host->data);
++}
++
++
++void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command *cmd)
++{
++      u32 sdcmd, sdhsts;
++      unsigned long timeout;
++      int delay;
++
++      WARN_ON(host->cmd);
++
++      if (cmd->data)
++              pr_debug("%s: send_command %d 0x%x "
++                       "(flags 0x%x) - %s %d*%d\n",
++                       mmc_hostname(host->mmc),
++                       cmd->opcode, cmd->arg, cmd->flags,
++                       (cmd->data->flags & MMC_DATA_READ) ?
++                       "read" : "write", cmd->data->blocks,
++                       cmd->data->blksz);
++      else
++              pr_debug("%s: send_command %d 0x%x (flags 0x%x)\n",
++                       mmc_hostname(host->mmc),
++                       cmd->opcode, cmd->arg, cmd->flags);
++
++      /* Wait max 100 ms */
++      timeout = 10000;
++
++      while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) {
++              if (timeout == 0) {
++                      pr_err("%s: previous command never completed.\n",
++                              mmc_hostname(host->mmc));
++                      bcm2835_sdhost_dumpregs(host);
++                      cmd->error = -EIO;
++                      tasklet_schedule(&host->finish_tasklet);
++                      return;
++              }
++              timeout--;
++              udelay(10);
++      }
++
++      delay = (10000 - timeout)/100;
++      if (delay > host->max_delay) {
++              host->max_delay = delay;
++              pr_warning("%s: controller hung for %d ms\n",
++                         mmc_hostname(host->mmc),
++                         host->max_delay);
++      }
++
++      timeout = jiffies;
++      if (!cmd->data && cmd->busy_timeout > 9000)
++              timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
++      else
++              timeout += 10 * HZ;
++      mod_timer(&host->timer, timeout);
++
++      host->cmd = cmd;
++
++      /* Clear any error flags */
++      sdhsts = bcm2835_sdhost_read(host, SDHSTS);
++      if (sdhsts & SDHSTS_ERROR_MASK)
++              bcm2835_sdhost_write(host, sdhsts, SDHSTS);
++
++      bcm2835_sdhost_prepare_data(host, cmd);
++
++      bcm2835_sdhost_write(host, cmd->arg, SDARG);
++
++      if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
++              pr_err("%s: unsupported response type!\n",
++                      mmc_hostname(host->mmc));
++              cmd->error = -EINVAL;
++              tasklet_schedule(&host->finish_tasklet);
++              return;
++      }
++
++      sdcmd = cmd->opcode & SDCMD_CMD_MASK;
++
++      if (!(cmd->flags & MMC_RSP_PRESENT))
++              sdcmd |= SDCMD_NO_RESPONSE;
++      else {
++              if (cmd->flags & MMC_RSP_136)
++                      sdcmd |= SDCMD_LONG_RESPONSE;
++              if (cmd->flags & MMC_RSP_BUSY) {
++                      sdcmd |= SDCMD_BUSYWAIT;
++                      host->use_busy = 1;
++              }
++      }
++
++      if (cmd->data) {
++              if (host->delay_after_stop) {
++                      struct timeval now;
++                      int time_since_stop;
++                      do_gettimeofday(&now);
++                      time_since_stop = (now.tv_sec - host->stop_time.tv_sec);
++                      if (time_since_stop < 2) {
++                              /* Possibly less than one second */
++                              time_since_stop = time_since_stop * 1000000 +
++                                      (now.tv_usec - host->stop_time.tv_usec);
++                              if (time_since_stop < host->delay_after_stop)
++                                      udelay(host->delay_after_stop -
++                                             time_since_stop);
++                      }
++              }
++
++              if (cmd->data->flags & MMC_DATA_WRITE)
++                      sdcmd |= SDCMD_WRITE_CMD;
++              if (cmd->data->flags & MMC_DATA_READ)
++                      sdcmd |= SDCMD_READ_CMD;
++      }
++
++      bcm2835_sdhost_write(host, sdcmd | SDCMD_NEW_FLAG, SDCMD);
++}
++
++
++static void bcm2835_sdhost_finish_command(struct bcm2835_host *host);
++static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host);
++
++static void bcm2835_sdhost_finish_data(struct bcm2835_host *host)
++{
++      struct mmc_data *data;
++
++      data = host->data;
++      BUG_ON(!data);
++
++      pr_debug("finish_data(error %d, stop %d, sbc %d)\n",
++             data->error, data->stop ? 1 : 0,
++             host->mrq->sbc ? 1 : 0);
++
++      host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN);
++      bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++
++      if (data->error) {
++              data->bytes_xfered = 0;
++      } else
++              data->bytes_xfered = data->blksz * data->blocks;
++
++      host->data_complete = 1;
++
++      if (host->cmd) {
++              /*
++               * Data managed to finish before the
++               * command completed. Make sure we do
++               * things in the proper order.
++               */
++              pr_debug("Finished early - HSTS %x\n",
++                       bcm2835_sdhost_read(host, SDHSTS));
++      }
++      else
++              bcm2835_sdhost_transfer_complete(host);
++}
++
++
++static void bcm2835_sdhost_transfer_complete(struct bcm2835_host *host)
++{
++      struct mmc_data *data;
++
++      BUG_ON(host->cmd);
++      BUG_ON(!host->data);
++      BUG_ON(!host->data_complete);
++
++      data = host->data;
++      host->data = NULL;
++
++      pr_debug("transfer_complete(error %d, stop %d)\n",
++             data->error, data->stop ? 1 : 0);
++
++      /*
++       * Need to send CMD12 if -
++       * a) open-ended multiblock transfer (no CMD23)
++       * b) error in multiblock transfer
++       */
++      if (data->stop &&
++          (data->error ||
++           !host->mrq->sbc)) {
++              host->flush_fifo = 1;
++              bcm2835_sdhost_send_command(host, data->stop);
++              if (host->delay_after_stop)
++                      do_gettimeofday(&host->stop_time);
++              if (!host->use_busy)
++                      bcm2835_sdhost_finish_command(host);
++      } else {
++              tasklet_schedule(&host->finish_tasklet);
++      }
++}
++
++static void bcm2835_sdhost_finish_command(struct bcm2835_host *host)
++{
++      u32 sdcmd;
++      unsigned long timeout;
++#ifdef DEBUG
++      struct timeval before, after;
++      int timediff = 0;
++#endif
++
++      pr_debug("finish_command(%x)\n", bcm2835_sdhost_read(host, SDCMD));
++
++      BUG_ON(!host->cmd || !host->mrq);
++
++#ifdef DEBUG
++      do_gettimeofday(&before);
++#endif
++      /* Wait max 100 ms */
++      timeout = 10000;
++      for (sdcmd = bcm2835_sdhost_read(host, SDCMD);
++           (sdcmd & SDCMD_NEW_FLAG) && timeout;
++           timeout--) {
++              if (host->flush_fifo) {
++                      while (bcm2835_sdhost_read(host, SDHSTS) &
++                             SDHSTS_DATA_FLAG)
++                              (void)bcm2835_sdhost_read(host, SDDATA);
++              }
++              udelay(10);
++              sdcmd = bcm2835_sdhost_read(host, SDCMD);
++      }
++#ifdef DEBUG
++      do_gettimeofday(&after);
++      timediff = (after.tv_sec - before.tv_sec)*1000000 +
++              (after.tv_usec - before.tv_usec);
++
++      pr_debug(" finish_command - waited %dus\n", timediff);
++#endif
++
++      if (timeout == 0) {
++              pr_err("%s: command never completed.\n",
++                     mmc_hostname(host->mmc));
++              bcm2835_sdhost_dumpregs(host);
++              host->cmd->error = -EIO;
++              tasklet_schedule(&host->finish_tasklet);
++              return;
++      }
++
++      if (host->flush_fifo) {
++              for (timeout = 100;
++                   (bcm2835_sdhost_read(host, SDHSTS) & SDHSTS_DATA_FLAG) && timeout;
++                   timeout--) {
++                      (void)bcm2835_sdhost_read(host, SDDATA);
++              }
++              host->flush_fifo = 0;
++              if (timeout == 0) {
++                      pr_err("%s: FIFO never drained.\n",
++                             mmc_hostname(host->mmc));
++                      bcm2835_sdhost_dumpregs(host);
++                      host->cmd->error = -EIO;
++                      tasklet_schedule(&host->finish_tasklet);
++                      return;
++              }
++      }
++
++      /* Check for errors */
++      if (sdcmd & SDCMD_FAIL_FLAG)
++      {
++              u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS);
++
++              if (host->debug)
++                      pr_info("%s: error detected - CMD %x, HSTS %03x, EDM %x\n",
++                              mmc_hostname(host->mmc), sdcmd, sdhsts,
++                              bcm2835_sdhost_read(host, SDEDM));
++
++              if ((sdhsts & SDHSTS_CRC7_ERROR) &&
++                  (host->cmd->opcode == 1)) {
++                      if (host->debug)
++                              pr_info("%s: ignoring CRC7 error for CMD1\n",
++                                      mmc_hostname(host->mmc));
++              } else {
++                      if (sdhsts & SDHSTS_CMD_TIME_OUT) {
++                              if (host->debug)
++                                      pr_err("%s: command %d timeout\n",
++                                             mmc_hostname(host->mmc),
++                                             host->cmd->opcode);
++                              host->cmd->error = -ETIMEDOUT;
++                      } else {
++                              pr_err("%s: unexpected command %d error\n",
++                                     mmc_hostname(host->mmc),
++                                     host->cmd->opcode);
++                              bcm2835_sdhost_dumpregs(host);
++                              host->cmd->error = -EIO;
++                      }
++                      tasklet_schedule(&host->finish_tasklet);
++                      return;
++              }
++      }
++
++      if (host->cmd->flags & MMC_RSP_PRESENT) {
++              if (host->cmd->flags & MMC_RSP_136) {
++                      int i;
++                      for (i = 0; i < 4; i++)
++                              host->cmd->resp[3 - i] = bcm2835_sdhost_read(host, SDRSP0 + i*4);
++                      pr_debug("%s: finish_command %08x %08x %08x %08x\n",
++                               mmc_hostname(host->mmc),
++                               host->cmd->resp[0], host->cmd->resp[1], host->cmd->resp[2], host->cmd->resp[3]);
++              } else {
++                      host->cmd->resp[0] = bcm2835_sdhost_read(host, SDRSP0);
++                      pr_debug("%s: finish_command %08x\n",
++                               mmc_hostname(host->mmc),
++                               host->cmd->resp[0]);
++              }
++      }
++
++      host->cmd->error = 0;
++
++      if (host->cmd == host->mrq->sbc) {
++              /* Finished CMD23, now send actual command. */
++              host->cmd = NULL;
++              bcm2835_sdhost_send_command(host, host->mrq->cmd);
++
++              if (host->cmd->data && host->use_dma)
++                      /* DMA transfer starts now, PIO starts after irq */
++                      bcm2835_sdhost_transfer_dma(host);
++
++              if (!host->use_busy)
++                      bcm2835_sdhost_finish_command(host);
++      } else if (host->cmd == host->mrq->stop)
++              /* Finished CMD12 */
++              tasklet_schedule(&host->finish_tasklet);
++      else {
++              /* Processed actual command. */
++              host->cmd = NULL;
++              if (!host->data)
++                      tasklet_schedule(&host->finish_tasklet);
++              else if (host->data_complete)
++                      bcm2835_sdhost_transfer_complete(host);
++      }
++}
++
++static void bcm2835_sdhost_timeout(unsigned long data)
++{
++      struct bcm2835_host *host;
++      unsigned long flags;
++
++      host = (struct bcm2835_host *)data;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (host->mrq) {
++              pr_err("%s: timeout waiting for hardware interrupt.\n",
++                      mmc_hostname(host->mmc));
++              bcm2835_sdhost_dumpregs(host);
++
++              if (host->data) {
++                      host->data->error = -ETIMEDOUT;
++                      bcm2835_sdhost_finish_data(host);
++              } else {
++                      if (host->cmd)
++                              host->cmd->error = -ETIMEDOUT;
++                      else
++                              host->mrq->cmd->error = -ETIMEDOUT;
++
++                      pr_debug("timeout_timer tasklet_schedule\n");
++                      tasklet_schedule(&host->finish_tasklet);
++              }
++      }
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_sdhost_pio_timeout(unsigned long data)
++{
++      struct bcm2835_host *host;
++      unsigned long flags;
++
++      host = (struct bcm2835_host *)data;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (host->data) {
++              u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS);
++
++              if (sdhsts & SDHSTS_REW_TIME_OUT) {
++                      pr_err("%s: transfer timeout\n",
++                             mmc_hostname(host->mmc));
++                      if (host->debug)
++                              bcm2835_sdhost_dumpregs(host);
++              } else {
++                      pr_err("%s: unexpected transfer timeout\n",
++                             mmc_hostname(host->mmc));
++                      bcm2835_sdhost_dumpregs(host);
++              }
++
++              bcm2835_sdhost_write(host, SDHSTS_TRANSFER_ERROR_MASK,
++                                   SDHSTS);
++
++              host->data->error = -ETIMEDOUT;
++
++              bcm2835_sdhost_finish_data(host);
++      }
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void bcm2835_sdhost_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable)
++{
++      if (enable)
++              host->hcfg |= SDHCFG_SDIO_IRPT_EN;
++      else
++              host->hcfg &= ~SDHCFG_SDIO_IRPT_EN;
++      bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++      mmiowb();
++}
++
++static void bcm2835_sdhost_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++      struct bcm2835_host *host = mmc_priv(mmc);
++      unsigned long flags;
++
++      pr_debug("%s: enable_sdio_irq(%d)\n", mmc_hostname(mmc), enable);
++      spin_lock_irqsave(&host->lock, flags);
++      bcm2835_sdhost_enable_sdio_irq_nolock(host, enable);
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static u32 bcm2835_sdhost_busy_irq(struct bcm2835_host *host, u32 intmask)
++{
++      const u32 handled = (SDHSTS_REW_TIME_OUT | SDHSTS_CMD_TIME_OUT |
++                           SDHSTS_CRC16_ERROR | SDHSTS_CRC7_ERROR |
++                           SDHSTS_FIFO_ERROR);
++
++      if (!host->cmd) {
++              pr_err("%s: got command busy interrupt 0x%08x even "
++                      "though no command operation was in progress.\n",
++                      mmc_hostname(host->mmc), (unsigned)intmask);
++              bcm2835_sdhost_dumpregs(host);
++              return 0;
++      }
++
++      if (!host->use_busy) {
++              pr_err("%s: got command busy interrupt 0x%08x even "
++                      "though not expecting one.\n",
++                      mmc_hostname(host->mmc), (unsigned)intmask);
++              bcm2835_sdhost_dumpregs(host);
++              return 0;
++      }
++      host->use_busy = 0;
++
++      if (intmask & SDHSTS_ERROR_MASK)
++      {
++              pr_err("sdhost_busy_irq: intmask %x, data %p\n", intmask, host->mrq->data);
++              if (intmask & SDHSTS_CRC7_ERROR)
++                      host->cmd->error = -EILSEQ;
++              else if (intmask & (SDHSTS_CRC16_ERROR |
++                                  SDHSTS_FIFO_ERROR)) {
++                      if (host->mrq->data)
++                              host->mrq->data->error = -EILSEQ;
++                      else
++                              host->cmd->error = -EILSEQ;
++              } else if (intmask & SDHSTS_REW_TIME_OUT) {
++                      if (host->mrq->data)
++                              host->mrq->data->error = -ETIMEDOUT;
++                      else
++                              host->cmd->error = -ETIMEDOUT;
++              } else if (intmask & SDHSTS_CMD_TIME_OUT)
++                      host->cmd->error = -ETIMEDOUT;
++
++              bcm2835_sdhost_dumpregs(host);
++              tasklet_schedule(&host->finish_tasklet);
++      }
++      else
++              bcm2835_sdhost_finish_command(host);
++
++      return handled;
++}
++
++static u32 bcm2835_sdhost_data_irq(struct bcm2835_host *host, u32 intmask)
++{
++      const u32 handled = (SDHSTS_REW_TIME_OUT |
++                           SDHSTS_CRC16_ERROR |
++                           SDHSTS_FIFO_ERROR);
++
++      /* There are no dedicated data/space available interrupt
++         status bits, so it is necessary to use the single shared
++         data/space available FIFO status bits. It is therefore not
++         an error to get here when there is no data transfer in
++         progress. */
++      if (!host->data)
++              return 0;
++
++      if (intmask & (SDHSTS_CRC16_ERROR |
++                     SDHSTS_FIFO_ERROR |
++                     SDHSTS_REW_TIME_OUT)) {
++              if (intmask & (SDHSTS_CRC16_ERROR |
++                             SDHSTS_FIFO_ERROR))
++                      host->data->error = -EILSEQ;
++              else
++                      host->data->error = -ETIMEDOUT;
++
++              bcm2835_sdhost_dumpregs(host);
++              tasklet_schedule(&host->finish_tasklet);
++              return handled;
++      }
++
++      /* Use the block interrupt for writes after the first block */
++      if (host->data->flags & MMC_DATA_WRITE) {
++              host->hcfg &= ~(SDHCFG_DATA_IRPT_EN);
++              host->hcfg |= SDHCFG_BLOCK_IRPT_EN;
++              bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++              if (host->data->error)
++                      bcm2835_sdhost_finish_data(host);
++              else
++                      bcm2835_sdhost_transfer_pio(host);
++      } else {
++              if (!host->data->error) {
++                      bcm2835_sdhost_transfer_pio(host);
++                      host->blocks--;
++              }
++              if ((host->blocks == 0) || host->data->error)
++                      bcm2835_sdhost_finish_data(host);
++      }
++
++      return handled;
++}
++
++static u32 bcm2835_sdhost_block_irq(struct bcm2835_host *host, u32 intmask)
++{
++      struct dma_chan *dma_chan;
++      u32 dir_data;
++      const u32 handled = (SDHSTS_REW_TIME_OUT |
++                           SDHSTS_CRC16_ERROR |
++                           SDHSTS_FIFO_ERROR);
++
++      if (!host->data) {
++              pr_err("%s: got block interrupt 0x%08x even "
++                      "though no data operation was in progress.\n",
++                      mmc_hostname(host->mmc), (unsigned)intmask);
++              bcm2835_sdhost_dumpregs(host);
++              return handled;
++      }
++
++      if (intmask & (SDHSTS_CRC16_ERROR |
++                     SDHSTS_FIFO_ERROR |
++                     SDHSTS_REW_TIME_OUT)) {
++              if (intmask & (SDHSTS_CRC16_ERROR |
++                             SDHSTS_FIFO_ERROR))
++                      host->data->error = -EILSEQ;
++              else
++                      host->data->error = -ETIMEDOUT;
++
++              if (host->debug)
++                      bcm2835_sdhost_dumpregs(host);
++              tasklet_schedule(&host->finish_tasklet);
++              return handled;
++      }
++
++      if (!host->use_dma) {
++              BUG_ON(!host->blocks);
++              host->blocks--;
++              if ((host->blocks == 0) || host->data->error) {
++                      /* Cancel the timer */
++                      del_timer(&host->pio_timer);
++
++                      bcm2835_sdhost_finish_data(host);
++              } else {
++                      bcm2835_sdhost_transfer_pio(host);
++
++                      /* Reset the timer */
++                      mod_timer(&host->pio_timer,
++                                jiffies + host->pio_timeout);
++              }
++      } else if (host->data->flags & MMC_DATA_WRITE) {
++              dma_chan = host->dma_chan_tx;
++              dir_data = DMA_TO_DEVICE;
++              dma_unmap_sg(dma_chan->device->dev,
++                           host->data->sg, host->data->sg_len,
++                           dir_data);
++
++              bcm2835_sdhost_finish_data(host);
++      }
++
++      return handled;
++}
++
++
++static irqreturn_t bcm2835_sdhost_irq(int irq, void *dev_id)
++{
++      irqreturn_t result = IRQ_NONE;
++      struct bcm2835_host *host = dev_id;
++      u32 unexpected = 0, early = 0;
++      int loops = 0;
++
++      spin_lock(&host->lock);
++
++      for (loops = 0; loops < 1; loops++) {
++              u32 intmask, handled;
++
++              intmask = bcm2835_sdhost_read(host, SDHSTS);
++              handled = intmask & (SDHSTS_BUSY_IRPT |
++                                   SDHSTS_BLOCK_IRPT |
++                                   SDHSTS_SDIO_IRPT |
++                                   SDHSTS_DATA_FLAG);
++              if ((handled == SDHSTS_DATA_FLAG) &&
++                  (loops == 0) && !host->data) {
++                      pr_err("%s: sdhost_irq data interrupt 0x%08x even "
++                             "though no data operation was in progress.\n",
++                             mmc_hostname(host->mmc),
++                             (unsigned)intmask);
++
++                      bcm2835_sdhost_dumpregs(host);
++              }
++
++              if (!handled)
++                      break;
++
++              if (loops)
++                      early |= handled;
++
++              result = IRQ_HANDLED;
++
++              /* Clear all interrupts and notifications */
++              bcm2835_sdhost_write(host, intmask, SDHSTS);
++
++              if (intmask & SDHSTS_BUSY_IRPT)
++                      handled |= bcm2835_sdhost_busy_irq(host, intmask);
++
++              /* There is no true data interrupt status bit, so it is
++                 necessary to qualify the data flag with the interrupt
++                 enable bit */
++              if ((intmask & SDHSTS_DATA_FLAG) &&
++                  (host->hcfg & SDHCFG_DATA_IRPT_EN))
++                      handled |= bcm2835_sdhost_data_irq(host, intmask);
++
++              if (intmask & SDHSTS_BLOCK_IRPT)
++                      handled |= bcm2835_sdhost_block_irq(host, intmask);
++
++              if (intmask & SDHSTS_SDIO_IRPT) {
++                      bcm2835_sdhost_enable_sdio_irq_nolock(host, false);
++                      host->thread_isr |= SDHSTS_SDIO_IRPT;
++                      result = IRQ_WAKE_THREAD;
++              }
++
++              unexpected |= (intmask & ~handled);
++      }
++
++      mmiowb();
++
++      spin_unlock(&host->lock);
++
++      if (early)
++              pr_debug("%s: early %x (loops %d)\n",
++                       mmc_hostname(host->mmc), early, loops);
++
++      if (unexpected) {
++              pr_err("%s: unexpected interrupt 0x%08x.\n",
++                         mmc_hostname(host->mmc), unexpected);
++              bcm2835_sdhost_dumpregs(host);
++      }
++
++      return result;
++}
++
++static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id)
++{
++      struct bcm2835_host *host = dev_id;
++      unsigned long flags;
++      u32 isr;
++
++      spin_lock_irqsave(&host->lock, flags);
++      isr = host->thread_isr;
++      host->thread_isr = 0;
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (isr & SDHSTS_SDIO_IRPT) {
++              sdio_run_irqs(host->mmc);
++
++/* Is this necessary? Why re-enable an interrupt which is enabled?
++              spin_lock_irqsave(&host->lock, flags);
++              if (host->flags & SDHSTS_SDIO_IRPT_ENABLED)
++                      bcm2835_sdhost_enable_sdio_irq_nolock(host, true);
++              spin_unlock_irqrestore(&host->lock, flags);
++*/
++      }
++
++      return isr ? IRQ_HANDLED : IRQ_NONE;
++}
++
++
++
++void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock)
++{
++      int div = 0; /* Initialized for compiler warning */
++      unsigned int input_clock = clock;
++
++      if (host->debug)
++              pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock);
++
++      if ((host->overclock_50 > 50) &&
++          (clock == 50*MHZ)) {
++              clock = host->overclock_50 * MHZ + (MHZ - 1);
++      }
++
++      /* The SDCDIV register has 11 bits, and holds (div - 2).
++         But in data mode the max is 50MHz wihout a minimum, and only the
++         bottom 3 bits are used. Since the switch over is automatic (unless
++         we have marked the card as slow...), chosen values have to make
++         sense in both modes.
++         Ident mode must be 100-400KHz, so can range check the requested
++         clock. CMD15 must be used to return to data mode, so this can be
++         monitored.
++
++         clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz
++                           4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz
++
++                       623->400KHz/27.8MHz
++                       reset value (507)->491159/50MHz
++
++         BUT, the 3-bit clock divisor in data mode is too small if the
++         core clock is higher than 250MHz, so instead use the SLOW_CARD
++         configuration bit to force the use of the ident clock divisor
++         at all times.
++      */
++
++      host->mmc->actual_clock = 0;
++
++      if (clock < 100000) {
++          /* Can't stop the clock, but make it as slow as possible
++           * to show willing
++           */
++          host->cdiv = SDCDIV_MAX_CDIV;
++          bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
++          return;
++      }
++
++      div = host->max_clk / clock;
++      if (div < 2)
++              div = 2;
++      if ((host->max_clk / div) > clock)
++              div++;
++      div -= 2;
++
++      if (div > SDCDIV_MAX_CDIV)
++          div = SDCDIV_MAX_CDIV;
++
++      clock = host->max_clk / (div + 2);
++      host->mmc->actual_clock = clock;
++
++      if (clock > input_clock) {
++              /* Save the closest value, to make it easier
++                 to reduce in the event of error */
++              host->overclock_50 = (clock/MHZ);
++
++              if (clock != host->overclock) {
++                      pr_warn("%s: overclocking to %dHz\n",
++                              mmc_hostname(host->mmc), clock);
++                      host->overclock = clock;
++              }
++      }
++      else if (host->overclock)
++      {
++              host->overclock = 0;
++              if (clock == 50 * MHZ)
++                      pr_warn("%s: cancelling overclock\n",
++                              mmc_hostname(host->mmc));
++      }
++
++      host->cdiv = div;
++      bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
++
++      /* Set the timeout to 500ms */
++      bcm2835_sdhost_write(host, host->mmc->actual_clock/2, SDTOUT);
++
++      if (host->debug)
++              pr_info("%s: clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n",
++                      mmc_hostname(host->mmc), input_clock,
++                      host->max_clk, host->cdiv, host->mmc->actual_clock);
++}
++
++static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++      struct bcm2835_host *host;
++      unsigned long flags;
++
++      host = mmc_priv(mmc);
++
++      if (host->debug) {
++              struct mmc_command *cmd = mrq->cmd;
++              BUG_ON(!cmd);
++              if (cmd->data)
++                      pr_info("%s: cmd %d 0x%x (flags 0x%x) - %s %d*%d\n",
++                              mmc_hostname(mmc),
++                              cmd->opcode, cmd->arg, cmd->flags,
++                              (cmd->data->flags & MMC_DATA_READ) ?
++                              "read" : "write", cmd->data->blocks,
++                              cmd->data->blksz);
++              else
++                      pr_info("%s: cmd %d 0x%x (flags 0x%x)\n",
++                              mmc_hostname(mmc),
++                              cmd->opcode, cmd->arg, cmd->flags);
++      }
++
++      /* Reset the error statuses in case this is a retry */
++      if (mrq->cmd)
++              mrq->cmd->error = 0;
++      if (mrq->data)
++              mrq->data->error = 0;
++      if (mrq->stop)
++              mrq->stop->error = 0;
++
++      if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
++              pr_err("%s: unsupported block size (%d bytes)\n",
++                     mmc_hostname(mmc), mrq->data->blksz);
++              mrq->cmd->error = -EINVAL;
++              mmc_request_done(mmc, mrq);
++              return;
++      }
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      WARN_ON(host->mrq != NULL);
++
++      host->mrq = mrq;
++
++      if (mrq->sbc)
++              bcm2835_sdhost_send_command(host, mrq->sbc);
++      else
++              bcm2835_sdhost_send_command(host, mrq->cmd);
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (!mrq->sbc && mrq->cmd->data && host->use_dma)
++              /* DMA transfer starts now, PIO starts after irq */
++              bcm2835_sdhost_transfer_dma(host);
++
++      if (!host->use_busy)
++              bcm2835_sdhost_finish_command(host);
++}
++
++
++static void bcm2835_sdhost_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++
++      struct bcm2835_host *host = mmc_priv(mmc);
++      unsigned long flags;
++
++      if (host->debug)
++              pr_info("%s: ios clock %d, pwr %d, bus_width %d, "
++                      "timing %d, vdd %d, drv_type %d\n",
++                      mmc_hostname(mmc),
++                      ios->clock, ios->power_mode, ios->bus_width,
++                      ios->timing, ios->signal_voltage, ios->drv_type);
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (!ios->clock || ios->clock != host->clock) {
++              bcm2835_sdhost_set_clock(host, ios->clock);
++              host->clock = ios->clock;
++      }
++
++      /* set bus width */
++      host->hcfg &= ~SDHCFG_WIDE_EXT_BUS;
++      if (ios->bus_width == MMC_BUS_WIDTH_4)
++              host->hcfg |= SDHCFG_WIDE_EXT_BUS;
++
++      host->hcfg |= SDHCFG_WIDE_INT_BUS;
++
++      /* Disable clever clock switching, to cope with fast core clocks */
++      host->hcfg |= SDHCFG_SLOW_CARD;
++
++      bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
++
++      mmiowb();
++
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static int bcm2835_sdhost_multi_io_quirk(struct mmc_card *card,
++                                       unsigned int direction,
++                                       u32 blk_pos, int blk_size)
++{
++      /* There is a bug in the host controller hardware that makes
++         reading the final sector of the card as part of a multiple read
++         problematic. Detect that case and shorten the read accordingly.
++      */
++      /* csd.capacity is in weird units - convert to sectors */
++      u32 card_sectors = (card->csd.capacity << (card->csd.read_blkbits - 9));
++
++      if ((direction == MMC_DATA_READ) &&
++          ((blk_pos + blk_size) == card_sectors))
++              blk_size--;
++
++      return blk_size;
++}
++
++
++static struct mmc_host_ops bcm2835_sdhost_ops = {
++      .request = bcm2835_sdhost_request,
++      .set_ios = bcm2835_sdhost_set_ios,
++      .enable_sdio_irq = bcm2835_sdhost_enable_sdio_irq,
++      .hw_reset = bcm2835_sdhost_reset,
++      .multi_io_quirk = bcm2835_sdhost_multi_io_quirk,
++};
++
++
++static void bcm2835_sdhost_tasklet_finish(unsigned long param)
++{
++      struct bcm2835_host *host;
++      unsigned long flags;
++      struct mmc_request *mrq;
++
++      host = (struct bcm2835_host *)param;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      /*
++       * If this tasklet gets rescheduled while running, it will
++       * be run again afterwards but without any active request.
++       */
++      if (!host->mrq) {
++              spin_unlock_irqrestore(&host->lock, flags);
++              return;
++      }
++
++      del_timer(&host->timer);
++
++      mrq = host->mrq;
++
++      /* Drop the overclock after any data corruption, or after any
++         error overclocked */
++      if (host->overclock) {
++              if ((mrq->cmd && mrq->cmd->error) ||
++                  (mrq->data && mrq->data->error) ||
++                  (mrq->stop && mrq->stop->error)) {
++                      host->overclock_50--;
++                      pr_warn("%s: reducing overclock due to errors\n",
++                              mmc_hostname(host->mmc));
++                      bcm2835_sdhost_set_clock(host,50*MHZ);
++                      mrq->cmd->error = -EILSEQ;
++                      mrq->cmd->retries = 1;
++              }
++      }
++
++      host->mrq = NULL;
++      host->cmd = NULL;
++      host->data = NULL;
++
++      mmiowb();
++
++      spin_unlock_irqrestore(&host->lock, flags);
++      mmc_request_done(host->mmc, mrq);
++}
++
++
++
++int bcm2835_sdhost_add_host(struct bcm2835_host *host)
++{
++      struct mmc_host *mmc;
++      struct dma_slave_config cfg;
++      char pio_limit_string[20];
++      int ret;
++
++      mmc = host->mmc;
++
++      bcm2835_sdhost_reset_internal(host);
++
++      mmc->f_max = host->max_clk;
++      mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV;
++
++      mmc->max_busy_timeout =  (~(unsigned int)0)/(mmc->f_max/1000);
++
++      pr_debug("f_max %d, f_min %d, max_busy_timeout %d\n",
++               mmc->f_max, mmc->f_min, mmc->max_busy_timeout);
++
++      /* host controller capabilities */
++      mmc->caps |= /* MMC_CAP_SDIO_IRQ |*/ MMC_CAP_4_BIT_DATA |
++              MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
++              MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | MMC_CAP_ERASE |
++              (ALLOW_CMD23 * MMC_CAP_CMD23);
++
++      spin_lock_init(&host->lock);
++
++      if (host->allow_dma) {
++              if (IS_ERR_OR_NULL(host->dma_chan_tx) ||
++                  IS_ERR_OR_NULL(host->dma_chan_rx)) {
++                      pr_err("%s: unable to initialise DMA channels. "
++                             "Falling back to PIO\n",
++                             mmc_hostname(mmc));
++                      host->have_dma = false;
++              } else {
++                      host->have_dma = true;
++
++                      cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++                      cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++                      cfg.slave_id = 13;              /* DREQ channel */
++
++                      cfg.direction = DMA_MEM_TO_DEV;
++                      cfg.src_addr = 0;
++                      cfg.dst_addr = host->bus_addr + SDDATA;
++                      ret = dmaengine_slave_config(host->dma_chan_tx, &cfg);
++
++                      cfg.direction = DMA_DEV_TO_MEM;
++                      cfg.src_addr = host->bus_addr + SDDATA;
++                      cfg.dst_addr = 0;
++                      ret = dmaengine_slave_config(host->dma_chan_rx, &cfg);
++              }
++      } else {
++              host->have_dma = false;
++      }
++
++      mmc->max_segs = 128;
++      mmc->max_req_size = 524288;
++      mmc->max_seg_size = mmc->max_req_size;
++      mmc->max_blk_size = 512;
++      mmc->max_blk_count =  65535;
++
++      /* report supported voltage ranges */
++      mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++
++      tasklet_init(&host->finish_tasklet,
++              bcm2835_sdhost_tasklet_finish, (unsigned long)host);
++
++      setup_timer(&host->timer, bcm2835_sdhost_timeout,
++                  (unsigned long)host);
++
++      setup_timer(&host->pio_timer, bcm2835_sdhost_pio_timeout,
++                  (unsigned long)host);
++
++      bcm2835_sdhost_init(host, 0);
++      ret = request_threaded_irq(host->irq, bcm2835_sdhost_irq,
++                                 bcm2835_sdhost_thread_irq,
++                                 IRQF_SHARED, mmc_hostname(mmc), host);
++      if (ret) {
++              pr_err("%s: failed to request IRQ %d: %d\n",
++                     mmc_hostname(mmc), host->irq, ret);
++              goto untasklet;
++      }
++
++      mmiowb();
++      mmc_add_host(mmc);
++
++      pio_limit_string[0] = '\0';
++      if (host->have_dma && (host->pio_limit > 0))
++              sprintf(pio_limit_string, " (>%d)", host->pio_limit);
++      pr_info("%s: %s loaded - DMA %s%s\n",
++              mmc_hostname(mmc), DRIVER_NAME,
++              host->have_dma ? "enabled" : "disabled",
++              pio_limit_string);
++
++      return 0;
++
++untasklet:
++      tasklet_kill(&host->finish_tasklet);
++
++      return ret;
++}
++
++static int bcm2835_sdhost_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct device_node *node = dev->of_node;
++      struct clk *clk;
++      struct resource *iomem;
++      struct bcm2835_host *host;
++      struct mmc_host *mmc;
++      const __be32 *addr;
++      int ret;
++
++      pr_debug("bcm2835_sdhost_probe\n");
++      mmc = mmc_alloc_host(sizeof(*host), dev);
++      if (!mmc)
++              return -ENOMEM;
++
++      mmc->ops = &bcm2835_sdhost_ops;
++      host = mmc_priv(mmc);
++      host->mmc = mmc;
++      host->pio_timeout = msecs_to_jiffies(500);
++      host->max_delay = 1; /* Warn if over 1ms */
++      spin_lock_init(&host->lock);
++
++      iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      host->ioaddr = devm_ioremap_resource(dev, iomem);
++      if (IS_ERR(host->ioaddr)) {
++              ret = PTR_ERR(host->ioaddr);
++              goto err;
++      }
++
++      addr = of_get_address(node, 0, NULL, NULL);
++      if (!addr) {
++              dev_err(dev, "could not get DMA-register address\n");
++              return -ENODEV;
++      }
++      host->bus_addr = be32_to_cpup(addr);
++      pr_debug(" - ioaddr %lx, iomem->start %lx, bus_addr %lx\n",
++               (unsigned long)host->ioaddr,
++               (unsigned long)iomem->start,
++               (unsigned long)host->bus_addr);
++
++      host->allow_dma = ALLOW_DMA;
++
++      if (node) {
++              /* Read any custom properties */
++              of_property_read_u32(node,
++                                   "brcm,delay-after-stop",
++                                   &host->delay_after_stop);
++              of_property_read_u32(node,
++                                   "brcm,overclock-50",
++                                   &host->overclock_50);
++              of_property_read_u32(node,
++                                   "brcm,pio-limit",
++                                   &host->pio_limit);
++              host->allow_dma = ALLOW_DMA &&
++                      !of_property_read_bool(node, "brcm,force-pio");
++              host->debug = of_property_read_bool(node, "brcm,debug");
++      }
++
++      if (host->allow_dma) {
++              if (node) {
++                      host->dma_chan_tx =
++                              dma_request_slave_channel(dev, "tx");
++                      host->dma_chan_rx =
++                              dma_request_slave_channel(dev, "rx");
++              } else {
++                      dma_cap_mask_t mask;
++
++                      dma_cap_zero(mask);
++                      /* we don't care about the channel, any would work */
++                      dma_cap_set(DMA_SLAVE, mask);
++                      host->dma_chan_tx =
++                              dma_request_channel(mask, NULL, NULL);
++                      host->dma_chan_rx =
++                              dma_request_channel(mask, NULL, NULL);
++              }
++      }
++
++      clk = devm_clk_get(dev, NULL);
++      if (IS_ERR(clk)) {
++              dev_err(dev, "could not get clk\n");
++              ret = PTR_ERR(clk);
++              goto err;
++      }
++
++      host->max_clk = clk_get_rate(clk);
++
++      host->irq = platform_get_irq(pdev, 0);
++      if (host->irq <= 0) {
++              dev_err(dev, "get IRQ failed\n");
++              ret = -EINVAL;
++              goto err;
++      }
++
++      pr_debug(" - max_clk %lx, irq %d\n",
++               (unsigned long)host->max_clk,
++               (int)host->irq);
++
++      if (node)
++              mmc_of_parse(mmc);
++      else
++              mmc->caps |= MMC_CAP_4_BIT_DATA;
++
++      ret = bcm2835_sdhost_add_host(host);
++      if (ret)
++              goto err;
++
++      platform_set_drvdata(pdev, host);
++
++      pr_debug("bcm2835_sdhost_probe -> OK\n");
++
++      return 0;
++
++err:
++      pr_debug("bcm2835_sdhost_probe -> err %d\n", ret);
++      mmc_free_host(mmc);
++
++      return ret;
++}
++
++static int bcm2835_sdhost_remove(struct platform_device *pdev)
++{
++      struct bcm2835_host *host = platform_get_drvdata(pdev);
++
++      pr_debug("bcm2835_sdhost_remove\n");
++
++      mmc_remove_host(host->mmc);
++
++      bcm2835_sdhost_set_power(host, false);
++
++      free_irq(host->irq, host);
++
++      del_timer_sync(&host->timer);
++
++      tasklet_kill(&host->finish_tasklet);
++
++      mmc_free_host(host->mmc);
++      platform_set_drvdata(pdev, NULL);
++
++      pr_debug("bcm2835_sdhost_remove - OK\n");
++      return 0;
++}
++
++
++static const struct of_device_id bcm2835_sdhost_match[] = {
++      { .compatible = "brcm,bcm2835-sdhost" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, bcm2835_sdhost_match);
++
++
++
++static struct platform_driver bcm2835_sdhost_driver = {
++      .probe      = bcm2835_sdhost_probe,
++      .remove     = bcm2835_sdhost_remove,
++      .driver     = {
++              .name           = DRIVER_NAME,
++              .owner          = THIS_MODULE,
++              .of_match_table = bcm2835_sdhost_match,
++      },
++};
++module_platform_driver(bcm2835_sdhost_driver);
++
++MODULE_ALIAS("platform:sdhost-bcm2835");
++MODULE_DESCRIPTION("BCM2835 SDHost driver");
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Phil Elwell");
diff --git a/target/linux/brcm2708/patches-4.4/0033-MMC-added-alternative-MMC-driver.patch b/target/linux/brcm2708/patches-4.4/0033-MMC-added-alternative-MMC-driver.patch
deleted file mode 100644 (file)
index f599628..0000000
+++ /dev/null
@@ -1,1691 +0,0 @@
-From 3d0ca77d187abbbde572f4a73b1f864ffb8b5d8a Mon Sep 17 00:00:00 2001
-From: gellert <gellert@raspberrypi.org>
-Date: Fri, 15 Aug 2014 16:35:06 +0100
-Subject: [PATCH 033/170] MMC: added alternative MMC driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-mmc: Disable CMD23 transfers on all cards
-
-Pending wire-level investigation of these types of transfers
-and associated errors on bcm2835-mmc, disable for now. Fallback of
-CMD18/CMD25 transfers will be used automatically by the MMC layer.
-
-Reported/Tested-by: Gellert Weisz <gellert@raspberrypi.org>
-
-mmc: bcm2835-mmc: enable DT support for all architectures
-
-Both ARCH_BCM2835 and ARCH_BCM270x are built with OF now.
-Enable Device Tree support for all architectures.
-
-Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
-
-mmc: bcm2835-mmc: fix probe error handling
-
-Probe error handling is broken in several places.
-Simplify error handling by using device managed functions.
-Replace pr_{err,info} with dev_{err,info}.
-
-Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
-
-bcm2835-mmc: Add locks when accessing sdhost registers
-
-bcm2835-mmc: Add range of debug options for slowing things down
-
-bcm2835-mmc: Add option to disable some delays
-
-bcm2835-mmc: Add option to disable MMC_QUIRK_BLK_NO_CMD23
-
-bcm2835-mmc: Default to disabling MMC_QUIRK_BLK_NO_CMD23
-
-bcm2835-mmc: Adding overclocking option
-
-Allow a different clock speed to be substitued for a requested 50MHz.
-This option is exposed using the "overclock_50" DT parameter.
-Note that the mmc interface is restricted to EVEN integer divisions of
-250MHz, and the highest sensible option is 63 (250/4 = 62.5), the
-next being 125 (250/2) which is much too high.
-
-Use at your own risk.
-
-bcm2835-mmc: Round up the overclock, so 62 works for 62.5Mhz
-
-Also only warn once for each overclock setting.
-
-mmc: bcm2835-mmc: Make available on ARCH_BCM2835
-
-Make the bcm2835-mmc driver available for use on ARCH_BCM2835.
-
-Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
-
-BCM270x_DT: add bcm2835-mmc entry
-
-Add Device Tree entry for bcm2835-mmc.
-In non-DT mode, don't add the device in the board file.
-
-Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
-
-bcm2835-mmc: Don't overwrite MMC capabilities from DT
----
- drivers/mmc/core/quirks.c      |    6 +
- drivers/mmc/host/Kconfig       |   29 +
- drivers/mmc/host/Makefile      |    1 +
- drivers/mmc/host/bcm2835-mmc.c | 1542 ++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 1578 insertions(+)
- create mode 100644 drivers/mmc/host/bcm2835-mmc.c
-
---- a/drivers/mmc/core/quirks.c
-+++ b/drivers/mmc/core/quirks.c
-@@ -53,6 +53,7 @@ static const struct mmc_fixup mmc_fixup_
- void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
- {
-+      extern unsigned mmc_debug;
-       const struct mmc_fixup *f;
-       u64 rev = cid_rev_card(card);
-@@ -77,5 +78,10 @@ void mmc_fixup_device(struct mmc_card *c
-                       f->vendor_fixup(card, f->data);
-               }
-       }
-+      /* SDHCI on BCM2708 - bug causes a certain sequence of CMD23 operations to fail.
-+       * Disable this flag for all cards (fall-back to CMD25/CMD18 multi-block transfers).
-+       */
-+      if (mmc_debug & (1<<13))
-+      card->quirks |= MMC_QUIRK_BLK_NO_CMD23;
- }
- EXPORT_SYMBOL(mmc_fixup_device);
---- a/drivers/mmc/host/Kconfig
-+++ b/drivers/mmc/host/Kconfig
-@@ -4,6 +4,35 @@
- comment "MMC/SD/SDIO Host Controller Drivers"
-+config MMC_BCM2835
-+      tristate "MMC support on BCM2835"
-+      depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835
-+      help
-+        This selects the MMC Interface on BCM2835.
-+
-+        If you have a controller with this interface, say Y or M here.
-+
-+        If unsure, say N.
-+
-+config MMC_BCM2835_DMA
-+      bool "DMA support on BCM2835 Arasan controller"
-+      depends on MMC_BCM2835
-+      help
-+        Enable DMA support on the Arasan SDHCI controller in Broadcom 2708
-+        based chips.
-+
-+        If unsure, say N.
-+
-+config MMC_BCM2835_PIO_DMA_BARRIER
-+      int "Block count limit for PIO transfers"
-+      depends on MMC_BCM2835 && MMC_BCM2835_DMA
-+      range 0 256
-+      default 2
-+      help
-+        The inclusive limit in bytes under which PIO will be used instead of DMA
-+
-+        If unsure, say 2 here.
-+
- config MMC_ARMMMCI
-       tristate "ARM AMBA Multimedia Card Interface support"
-       depends on ARM_AMBA
---- a/drivers/mmc/host/Makefile
-+++ b/drivers/mmc/host/Makefile
-@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C)  += sdhci-s3c
- obj-$(CONFIG_MMC_SDHCI_SIRF)          += sdhci-sirf.o
- obj-$(CONFIG_MMC_SDHCI_F_SDH30)       += sdhci_f_sdh30.o
- obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
-+obj-$(CONFIG_MMC_BCM2835)     += bcm2835-mmc.o
- obj-$(CONFIG_MMC_WBSD)                += wbsd.o
- obj-$(CONFIG_MMC_AU1X)                += au1xmmc.o
- obj-$(CONFIG_MMC_MTK)         += mtk-sd.o
---- /dev/null
-+++ b/drivers/mmc/host/bcm2835-mmc.c
-@@ -0,0 +1,1542 @@
-+/*
-+ * BCM2835 MMC host driver.
-+ *
-+ * Author:      Gellert Weisz <gellert@raspberrypi.org>
-+ *              Copyright 2014
-+ *
-+ * Based on
-+ *  sdhci-bcm2708.c by Broadcom
-+ *  sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko
-+ *  sdhci.c and sdhci-pci.c by Pierre Ossman
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/delay.h>
-+#include <linux/module.h>
-+#include <linux/io.h>
-+#include <linux/mmc/mmc.h>
-+#include <linux/mmc/host.h>
-+#include <linux/mmc/sd.h>
-+#include <linux/scatterlist.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/clk.h>
-+#include <linux/platform_device.h>
-+#include <linux/err.h>
-+#include <linux/blkdev.h>
-+#include <linux/dmaengine.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/of_dma.h>
-+
-+#include "sdhci.h"
-+
-+
-+#define DRIVER_NAME "mmc-bcm2835"
-+
-+#define DBG(f, x...) \
-+pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x)
-+
-+#ifndef CONFIG_MMC_BCM2835_DMA
-+ #define FORCE_PIO
-+#endif
-+
-+
-+/* the inclusive limit in bytes under which PIO will be used instead of DMA */
-+#ifdef CONFIG_MMC_BCM2835_PIO_DMA_BARRIER
-+#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_PIO_DMA_BARRIER
-+#else
-+#define PIO_DMA_BARRIER 00
-+#endif
-+
-+#define MIN_FREQ 400000
-+#define TIMEOUT_VAL 0xE
-+#define BCM2835_SDHCI_WRITE_DELAY(f)  (((2 * 1000000) / f) + 1)
-+
-+
-+unsigned mmc_debug;
-+unsigned mmc_debug2;
-+
-+struct bcm2835_host {
-+      spinlock_t                              lock;
-+
-+      void __iomem                    *ioaddr;
-+      u32                                             bus_addr;
-+
-+      struct mmc_host                 *mmc;
-+
-+      u32                                             timeout;
-+
-+      int                                             clock;  /* Current clock speed */
-+      u8                                              pwr;    /* Current voltage */
-+
-+      unsigned int                    max_clk;                /* Max possible freq */
-+      unsigned int                    timeout_clk;    /* Timeout freq (KHz) */
-+      unsigned int                    clk_mul;                /* Clock Muliplier value */
-+
-+      struct tasklet_struct   finish_tasklet;         /* Tasklet structures */
-+
-+      struct timer_list               timer;                  /* Timer for timeouts */
-+
-+      struct sg_mapping_iter  sg_miter;               /* SG state for PIO */
-+      unsigned int                    blocks;                 /* remaining PIO blocks */
-+
-+      int                                             irq;                    /* Device IRQ */
-+
-+
-+      u32                                             ier;                    /* cached registers */
-+
-+      struct mmc_request              *mrq;                   /* Current request */
-+      struct mmc_command              *cmd;                   /* Current command */
-+      struct mmc_data                 *data;                  /* Current data request */
-+      unsigned int                    data_early:1;           /* Data finished before cmd */
-+
-+      wait_queue_head_t               buf_ready_int;          /* Waitqueue for Buffer Read Ready interrupt */
-+
-+      u32                                             thread_isr;
-+
-+      u32                                             shadow;
-+
-+      /*DMA part*/
-+      struct dma_chan                 *dma_chan_rx;           /* DMA channel for reads */
-+      struct dma_chan                 *dma_chan_tx;           /* DMA channel for writes */
-+      struct dma_async_tx_descriptor  *tx_desc;       /* descriptor */
-+
-+      bool                                    have_dma;
-+      bool                                    use_dma;
-+      /*end of DMA part*/
-+
-+      int                                             max_delay;      /* maximum length of time spent waiting */
-+
-+      int                                             flags;                          /* Host attributes */
-+#define SDHCI_REQ_USE_DMA     (1<<2)  /* Use DMA for this req. */
-+#define SDHCI_DEVICE_DEAD     (1<<3)  /* Device unresponsive */
-+#define SDHCI_AUTO_CMD12      (1<<6)  /* Auto CMD12 support */
-+#define SDHCI_AUTO_CMD23      (1<<7)  /* Auto CMD23 support */
-+#define SDHCI_SDIO_IRQ_ENABLED        (1<<9)  /* SDIO irq enabled */
-+
-+      u32                             overclock_50;   /* frequency to use when 50MHz is requested (in MHz) */
-+      u32                             max_overclock;  /* Highest reported */
-+};
-+
-+
-+static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg, int from)
-+{
-+      unsigned delay;
-+      lockdep_assert_held_once(&host->lock);
-+      writel(val, host->ioaddr + reg);
-+      udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ)));
-+
-+      delay = ((mmc_debug >> 16) & 0xf) << ((mmc_debug >> 20) & 0xf);
-+      if (delay && !((1<<from) & mmc_debug2))
-+              udelay(delay);
-+}
-+
-+static inline void mmc_raw_writel(struct bcm2835_host *host, u32 val, int reg)
-+{
-+      unsigned delay;
-+      lockdep_assert_held_once(&host->lock);
-+      writel(val, host->ioaddr + reg);
-+
-+      delay = ((mmc_debug >> 24) & 0xf) << ((mmc_debug >> 28) & 0xf);
-+      if (delay)
-+              udelay(delay);
-+}
-+
-+static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg)
-+{
-+      lockdep_assert_held_once(&host->lock);
-+      return readl(host->ioaddr + reg);
-+}
-+
-+static inline void bcm2835_mmc_writew(struct bcm2835_host *host, u16 val, int reg)
-+{
-+      u32 oldval = (reg == SDHCI_COMMAND) ? host->shadow :
-+              bcm2835_mmc_readl(host, reg & ~3);
-+      u32 word_num = (reg >> 1) & 1;
-+      u32 word_shift = word_num * 16;
-+      u32 mask = 0xffff << word_shift;
-+      u32 newval = (oldval & ~mask) | (val << word_shift);
-+
-+      if (reg == SDHCI_TRANSFER_MODE)
-+              host->shadow = newval;
-+      else
-+              bcm2835_mmc_writel(host, newval, reg & ~3, 0);
-+
-+}
-+
-+static inline void bcm2835_mmc_writeb(struct bcm2835_host *host, u8 val, int reg)
-+{
-+      u32 oldval = bcm2835_mmc_readl(host, reg & ~3);
-+      u32 byte_num = reg & 3;
-+      u32 byte_shift = byte_num * 8;
-+      u32 mask = 0xff << byte_shift;
-+      u32 newval = (oldval & ~mask) | (val << byte_shift);
-+
-+      bcm2835_mmc_writel(host, newval, reg & ~3, 1);
-+}
-+
-+
-+static inline u16 bcm2835_mmc_readw(struct bcm2835_host *host, int reg)
-+{
-+      u32 val = bcm2835_mmc_readl(host, (reg & ~3));
-+      u32 word_num = (reg >> 1) & 1;
-+      u32 word_shift = word_num * 16;
-+      u32 word = (val >> word_shift) & 0xffff;
-+
-+      return word;
-+}
-+
-+static inline u8 bcm2835_mmc_readb(struct bcm2835_host *host, int reg)
-+{
-+      u32 val = bcm2835_mmc_readl(host, (reg & ~3));
-+      u32 byte_num = reg & 3;
-+      u32 byte_shift = byte_num * 8;
-+      u32 byte = (val >> byte_shift) & 0xff;
-+
-+      return byte;
-+}
-+
-+static void bcm2835_mmc_unsignal_irqs(struct bcm2835_host *host, u32 clear)
-+{
-+      u32 ier;
-+
-+      ier = bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE);
-+      ier &= ~clear;
-+      /* change which requests generate IRQs - makes no difference to
-+         the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */
-+      bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE, 2);
-+}
-+
-+
-+static void bcm2835_mmc_dumpregs(struct bcm2835_host *host)
-+{
-+      pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
-+              mmc_hostname(host->mmc));
-+
-+      pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version:  0x%08x\n",
-+              bcm2835_mmc_readl(host, SDHCI_DMA_ADDRESS),
-+              bcm2835_mmc_readw(host, SDHCI_HOST_VERSION));
-+      pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt:  0x%08x\n",
-+              bcm2835_mmc_readw(host, SDHCI_BLOCK_SIZE),
-+              bcm2835_mmc_readw(host, SDHCI_BLOCK_COUNT));
-+      pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
-+              bcm2835_mmc_readl(host, SDHCI_ARGUMENT),
-+              bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE));
-+      pr_debug(DRIVER_NAME ": Present:  0x%08x | Host ctl: 0x%08x\n",
-+              bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE),
-+              bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL));
-+      pr_debug(DRIVER_NAME ": Power:    0x%08x | Blk gap:  0x%08x\n",
-+              bcm2835_mmc_readb(host, SDHCI_POWER_CONTROL),
-+              bcm2835_mmc_readb(host, SDHCI_BLOCK_GAP_CONTROL));
-+      pr_debug(DRIVER_NAME ": Wake-up:  0x%08x | Clock:    0x%08x\n",
-+              bcm2835_mmc_readb(host, SDHCI_WAKE_UP_CONTROL),
-+              bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL));
-+      pr_debug(DRIVER_NAME ": Timeout:  0x%08x | Int stat: 0x%08x\n",
-+              bcm2835_mmc_readb(host, SDHCI_TIMEOUT_CONTROL),
-+              bcm2835_mmc_readl(host, SDHCI_INT_STATUS));
-+      pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
-+              bcm2835_mmc_readl(host, SDHCI_INT_ENABLE),
-+              bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE));
-+      pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
-+              bcm2835_mmc_readw(host, SDHCI_ACMD12_ERR),
-+              bcm2835_mmc_readw(host, SDHCI_SLOT_INT_STATUS));
-+      pr_debug(DRIVER_NAME ": Caps:     0x%08x | Caps_1:   0x%08x\n",
-+              bcm2835_mmc_readl(host, SDHCI_CAPABILITIES),
-+              bcm2835_mmc_readl(host, SDHCI_CAPABILITIES_1));
-+      pr_debug(DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
-+              bcm2835_mmc_readw(host, SDHCI_COMMAND),
-+              bcm2835_mmc_readl(host, SDHCI_MAX_CURRENT));
-+      pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
-+              bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2));
-+
-+      pr_debug(DRIVER_NAME ": ===========================================\n");
-+}
-+
-+
-+static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask)
-+{
-+      unsigned long timeout;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+      bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET);
-+
-+      if (mask & SDHCI_RESET_ALL)
-+              host->clock = 0;
-+
-+      /* Wait max 100 ms */
-+      timeout = 100;
-+
-+      /* hw clears the bit when it's done */
-+      while (bcm2835_mmc_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
-+              if (timeout == 0) {
-+                      pr_err("%s: Reset 0x%x never completed.\n",
-+                              mmc_hostname(host->mmc), (int)mask);
-+                      bcm2835_mmc_dumpregs(host);
-+                      return;
-+              }
-+              timeout--;
-+              spin_unlock_irqrestore(&host->lock, flags);
-+              mdelay(1);
-+              spin_lock_irqsave(&host->lock, flags);
-+      }
-+
-+      if (100-timeout > 10 && 100-timeout > host->max_delay) {
-+              host->max_delay = 100-timeout;
-+              pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
-+      }
-+      spin_unlock_irqrestore(&host->lock, flags);
-+}
-+
-+static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
-+
-+static void bcm2835_mmc_init(struct bcm2835_host *host, int soft)
-+{
-+      unsigned long flags;
-+      if (soft)
-+              bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
-+      else
-+              bcm2835_mmc_reset(host, SDHCI_RESET_ALL);
-+
-+      host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
-+                  SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
-+                  SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
-+                  SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
-+                  SDHCI_INT_RESPONSE;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+      bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 3);
-+      bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 3);
-+      spin_unlock_irqrestore(&host->lock, flags);
-+
-+      if (soft) {
-+              /* force clock reconfiguration */
-+              host->clock = 0;
-+              bcm2835_mmc_set_ios(host->mmc, &host->mmc->ios);
-+      }
-+}
-+
-+
-+
-+static void bcm2835_mmc_finish_data(struct bcm2835_host *host);
-+
-+static void bcm2835_mmc_dma_complete(void *param)
-+{
-+      struct bcm2835_host *host = param;
-+      struct dma_chan *dma_chan;
-+      unsigned long flags;
-+      u32 dir_data;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+
-+      if (host->data && !(host->data->flags & MMC_DATA_WRITE)) {
-+              /* otherwise handled in SDHCI IRQ */
-+              dma_chan = host->dma_chan_rx;
-+              dir_data = DMA_FROM_DEVICE;
-+
-+              dma_unmap_sg(dma_chan->device->dev,
-+                   host->data->sg, host->data->sg_len,
-+                   dir_data);
-+
-+              bcm2835_mmc_finish_data(host);
-+      }
-+
-+      spin_unlock_irqrestore(&host->lock, flags);
-+}
-+
-+static void bcm2835_bcm2835_mmc_read_block_pio(struct bcm2835_host *host)
-+{
-+      unsigned long flags;
-+      size_t blksize, len, chunk;
-+
-+      u32 uninitialized_var(scratch);
-+      u8 *buf;
-+
-+      blksize = host->data->blksz;
-+      chunk = 0;
-+
-+      local_irq_save(flags);
-+
-+      while (blksize) {
-+              if (!sg_miter_next(&host->sg_miter))
-+                      BUG();
-+
-+              len = min(host->sg_miter.length, blksize);
-+
-+              blksize -= len;
-+              host->sg_miter.consumed = len;
-+
-+              buf = host->sg_miter.addr;
-+
-+              while (len) {
-+                      if (chunk == 0) {
-+                              scratch = bcm2835_mmc_readl(host, SDHCI_BUFFER);
-+                              chunk = 4;
-+                      }
-+
-+                      *buf = scratch & 0xFF;
-+
-+                      buf++;
-+                      scratch >>= 8;
-+                      chunk--;
-+                      len--;
-+              }
-+      }
-+
-+      sg_miter_stop(&host->sg_miter);
-+
-+      local_irq_restore(flags);
-+}
-+
-+static void bcm2835_bcm2835_mmc_write_block_pio(struct bcm2835_host *host)
-+{
-+      unsigned long flags;
-+      size_t blksize, len, chunk;
-+      u32 scratch;
-+      u8 *buf;
-+
-+      blksize = host->data->blksz;
-+      chunk = 0;
-+      chunk = 0;
-+      scratch = 0;
-+
-+      local_irq_save(flags);
-+
-+      while (blksize) {
-+              if (!sg_miter_next(&host->sg_miter))
-+                      BUG();
-+
-+              len = min(host->sg_miter.length, blksize);
-+
-+              blksize -= len;
-+              host->sg_miter.consumed = len;
-+
-+              buf = host->sg_miter.addr;
-+
-+              while (len) {
-+                      scratch |= (u32)*buf << (chunk * 8);
-+
-+                      buf++;
-+                      chunk++;
-+                      len--;
-+
-+                      if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
-+                              mmc_raw_writel(host, scratch, SDHCI_BUFFER);
-+                              chunk = 0;
-+                              scratch = 0;
-+                      }
-+              }
-+      }
-+
-+      sg_miter_stop(&host->sg_miter);
-+
-+      local_irq_restore(flags);
-+}
-+
-+
-+static void bcm2835_mmc_transfer_pio(struct bcm2835_host *host)
-+{
-+      u32 mask;
-+
-+      BUG_ON(!host->data);
-+
-+      if (host->blocks == 0)
-+              return;
-+
-+      if (host->data->flags & MMC_DATA_READ)
-+              mask = SDHCI_DATA_AVAILABLE;
-+      else
-+              mask = SDHCI_SPACE_AVAILABLE;
-+
-+      while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) {
-+
-+              if (host->data->flags & MMC_DATA_READ)
-+                      bcm2835_bcm2835_mmc_read_block_pio(host);
-+              else
-+                      bcm2835_bcm2835_mmc_write_block_pio(host);
-+
-+              host->blocks--;
-+
-+              /* QUIRK used in sdhci.c removes the 'if' */
-+              /* but it seems this is unnecessary */
-+              if (host->blocks == 0)
-+                      break;
-+
-+
-+      }
-+}
-+
-+
-+static void bcm2835_mmc_transfer_dma(struct bcm2835_host *host)
-+{
-+      u32 len, dir_data, dir_slave;
-+      struct dma_async_tx_descriptor *desc = NULL;
-+      struct dma_chan *dma_chan;
-+
-+
-+      WARN_ON(!host->data);
-+
-+      if (!host->data)
-+              return;
-+
-+      if (host->blocks == 0)
-+              return;
-+
-+      if (host->data->flags & MMC_DATA_READ) {
-+              dma_chan = host->dma_chan_rx;
-+              dir_data = DMA_FROM_DEVICE;
-+              dir_slave = DMA_DEV_TO_MEM;
-+      } else {
-+              dma_chan = host->dma_chan_tx;
-+              dir_data = DMA_TO_DEVICE;
-+              dir_slave = DMA_MEM_TO_DEV;
-+      }
-+
-+      BUG_ON(!dma_chan->device);
-+      BUG_ON(!dma_chan->device->dev);
-+      BUG_ON(!host->data->sg);
-+
-+      len = dma_map_sg(dma_chan->device->dev, host->data->sg,
-+                       host->data->sg_len, dir_data);
-+      if (len > 0) {
-+              desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg,
-+                                             len, dir_slave,
-+                                             DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+      } else {
-+              dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n");
-+      }
-+      if (desc) {
-+              unsigned long flags;
-+              spin_lock_irqsave(&host->lock, flags);
-+              bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL |
-+                                                  SDHCI_INT_SPACE_AVAIL);
-+              host->tx_desc = desc;
-+              desc->callback = bcm2835_mmc_dma_complete;
-+              desc->callback_param = host;
-+              spin_unlock_irqrestore(&host->lock, flags);
-+              dmaengine_submit(desc);
-+              dma_async_issue_pending(dma_chan);
-+      }
-+
-+}
-+
-+
-+
-+static void bcm2835_mmc_set_transfer_irqs(struct bcm2835_host *host)
-+{
-+      u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
-+      u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
-+
-+      if (host->use_dma)
-+              host->ier = (host->ier & ~pio_irqs) | dma_irqs;
-+      else
-+              host->ier = (host->ier & ~dma_irqs) | pio_irqs;
-+
-+      bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 4);
-+      bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 4);
-+}
-+
-+
-+static void bcm2835_mmc_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd)
-+{
-+      u8 count;
-+      struct mmc_data *data = cmd->data;
-+
-+      WARN_ON(host->data);
-+
-+      if (data || (cmd->flags & MMC_RSP_BUSY)) {
-+              count = TIMEOUT_VAL;
-+              bcm2835_mmc_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
-+      }
-+
-+      if (!data)
-+              return;
-+
-+      /* Sanity checks */
-+      BUG_ON(data->blksz * data->blocks > 524288);
-+      BUG_ON(data->blksz > host->mmc->max_blk_size);
-+      BUG_ON(data->blocks > 65535);
-+
-+      host->data = data;
-+      host->data_early = 0;
-+      host->data->bytes_xfered = 0;
-+
-+
-+      if (!(host->flags & SDHCI_REQ_USE_DMA)) {
-+              int flags;
-+
-+              flags = SG_MITER_ATOMIC;
-+              if (host->data->flags & MMC_DATA_READ)
-+                      flags |= SG_MITER_TO_SG;
-+              else
-+                      flags |= SG_MITER_FROM_SG;
-+              sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
-+              host->blocks = data->blocks;
-+      }
-+
-+      host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER;
-+
-+      bcm2835_mmc_set_transfer_irqs(host);
-+
-+      /* Set the DMA boundary value and block size */
-+      bcm2835_mmc_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
-+              data->blksz), SDHCI_BLOCK_SIZE);
-+      bcm2835_mmc_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
-+
-+      BUG_ON(!host->data);
-+}
-+
-+static void bcm2835_mmc_set_transfer_mode(struct bcm2835_host *host,
-+      struct mmc_command *cmd)
-+{
-+      u16 mode;
-+      struct mmc_data *data = cmd->data;
-+
-+      if (data == NULL) {
-+              /* clear Auto CMD settings for no data CMDs */
-+              mode = bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE);
-+              bcm2835_mmc_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
-+                              SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
-+              return;
-+      }
-+
-+      WARN_ON(!host->data);
-+
-+      mode = SDHCI_TRNS_BLK_CNT_EN;
-+
-+      if ((mmc_op_multi(cmd->opcode) || data->blocks > 1)) {
-+              mode |= SDHCI_TRNS_MULTI;
-+
-+              /*
-+               * If we are sending CMD23, CMD12 never gets sent
-+               * on successful completion (so no Auto-CMD12).
-+               */
-+              if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12))
-+                      mode |= SDHCI_TRNS_AUTO_CMD12;
-+              else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) {
-+                      mode |= SDHCI_TRNS_AUTO_CMD23;
-+                      bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2, 5);
-+              }
-+      }
-+
-+      if (data->flags & MMC_DATA_READ)
-+              mode |= SDHCI_TRNS_READ;
-+      if (host->flags & SDHCI_REQ_USE_DMA)
-+              mode |= SDHCI_TRNS_DMA;
-+
-+      bcm2835_mmc_writew(host, mode, SDHCI_TRANSFER_MODE);
-+}
-+
-+void bcm2835_mmc_send_command(struct bcm2835_host *host, struct mmc_command *cmd)
-+{
-+      int flags;
-+      u32 mask;
-+      unsigned long timeout;
-+
-+      WARN_ON(host->cmd);
-+
-+      /* Wait max 10 ms */
-+      timeout = 1000;
-+
-+      mask = SDHCI_CMD_INHIBIT;
-+      if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
-+              mask |= SDHCI_DATA_INHIBIT;
-+
-+      /* We shouldn't wait for data inihibit for stop commands, even
-+         though they might use busy signaling */
-+      if (host->mrq->data && (cmd == host->mrq->data->stop))
-+              mask &= ~SDHCI_DATA_INHIBIT;
-+
-+      while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) {
-+              if (timeout == 0) {
-+                      pr_err("%s: Controller never released inhibit bit(s).\n",
-+                              mmc_hostname(host->mmc));
-+                      bcm2835_mmc_dumpregs(host);
-+                      cmd->error = -EIO;
-+                      tasklet_schedule(&host->finish_tasklet);
-+                      return;
-+              }
-+              timeout--;
-+              udelay(10);
-+      }
-+
-+      if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) {
-+              host->max_delay = (1000-timeout)/100;
-+              pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
-+      }
-+
-+      timeout = jiffies;
-+      if (!cmd->data && cmd->busy_timeout > 9000)
-+              timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ;
-+      else
-+              timeout += 10 * HZ;
-+      mod_timer(&host->timer, timeout);
-+
-+      host->cmd = cmd;
-+
-+      bcm2835_mmc_prepare_data(host, cmd);
-+
-+      bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT, 6);
-+
-+      bcm2835_mmc_set_transfer_mode(host, cmd);
-+
-+      if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
-+              pr_err("%s: Unsupported response type!\n",
-+                      mmc_hostname(host->mmc));
-+              cmd->error = -EINVAL;
-+              tasklet_schedule(&host->finish_tasklet);
-+              return;
-+      }
-+
-+      if (!(cmd->flags & MMC_RSP_PRESENT))
-+              flags = SDHCI_CMD_RESP_NONE;
-+      else if (cmd->flags & MMC_RSP_136)
-+              flags = SDHCI_CMD_RESP_LONG;
-+      else if (cmd->flags & MMC_RSP_BUSY)
-+              flags = SDHCI_CMD_RESP_SHORT_BUSY;
-+      else
-+              flags = SDHCI_CMD_RESP_SHORT;
-+
-+      if (cmd->flags & MMC_RSP_CRC)
-+              flags |= SDHCI_CMD_CRC;
-+      if (cmd->flags & MMC_RSP_OPCODE)
-+              flags |= SDHCI_CMD_INDEX;
-+
-+      if (cmd->data)
-+              flags |= SDHCI_CMD_DATA;
-+
-+      bcm2835_mmc_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
-+}
-+
-+
-+static void bcm2835_mmc_finish_data(struct bcm2835_host *host)
-+{
-+      struct mmc_data *data;
-+
-+      BUG_ON(!host->data);
-+
-+      data = host->data;
-+      host->data = NULL;
-+
-+      if (data->error)
-+              data->bytes_xfered = 0;
-+      else
-+              data->bytes_xfered = data->blksz * data->blocks;
-+
-+      /*
-+       * Need to send CMD12 if -
-+       * a) open-ended multiblock transfer (no CMD23)
-+       * b) error in multiblock transfer
-+       */
-+      if (data->stop &&
-+          (data->error ||
-+           !host->mrq->sbc)) {
-+
-+              /*
-+               * The controller needs a reset of internal state machines
-+               * upon error conditions.
-+               */
-+              if (data->error) {
-+                      bcm2835_mmc_reset(host, SDHCI_RESET_CMD);
-+                      bcm2835_mmc_reset(host, SDHCI_RESET_DATA);
-+              }
-+
-+              bcm2835_mmc_send_command(host, data->stop);
-+      } else
-+              tasklet_schedule(&host->finish_tasklet);
-+}
-+
-+static void bcm2835_mmc_finish_command(struct bcm2835_host *host)
-+{
-+      int i;
-+
-+      BUG_ON(host->cmd == NULL);
-+
-+      if (host->cmd->flags & MMC_RSP_PRESENT) {
-+              if (host->cmd->flags & MMC_RSP_136) {
-+                      /* CRC is stripped so we need to do some shifting. */
-+                      for (i = 0; i < 4; i++) {
-+                              host->cmd->resp[i] = bcm2835_mmc_readl(host,
-+                                      SDHCI_RESPONSE + (3-i)*4) << 8;
-+                              if (i != 3)
-+                                      host->cmd->resp[i] |=
-+                                              bcm2835_mmc_readb(host,
-+                                              SDHCI_RESPONSE + (3-i)*4-1);
-+                      }
-+              } else {
-+                      host->cmd->resp[0] = bcm2835_mmc_readl(host, SDHCI_RESPONSE);
-+              }
-+      }
-+
-+      host->cmd->error = 0;
-+
-+      /* Finished CMD23, now send actual command. */
-+      if (host->cmd == host->mrq->sbc) {
-+              host->cmd = NULL;
-+              bcm2835_mmc_send_command(host, host->mrq->cmd);
-+
-+              if (host->mrq->cmd->data && host->use_dma) {
-+                      /* DMA transfer starts now, PIO starts after interrupt */
-+                      bcm2835_mmc_transfer_dma(host);
-+              }
-+      } else {
-+
-+              /* Processed actual command. */
-+              if (host->data && host->data_early)
-+                      bcm2835_mmc_finish_data(host);
-+
-+              if (!host->cmd->data)
-+                      tasklet_schedule(&host->finish_tasklet);
-+
-+              host->cmd = NULL;
-+      }
-+}
-+
-+
-+static void bcm2835_mmc_timeout_timer(unsigned long data)
-+{
-+      struct bcm2835_host *host;
-+      unsigned long flags;
-+
-+      host = (struct bcm2835_host *)data;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+
-+      if (host->mrq) {
-+              pr_err("%s: Timeout waiting for hardware interrupt.\n",
-+                      mmc_hostname(host->mmc));
-+              bcm2835_mmc_dumpregs(host);
-+
-+              if (host->data) {
-+                      host->data->error = -ETIMEDOUT;
-+                      bcm2835_mmc_finish_data(host);
-+              } else {
-+                      if (host->cmd)
-+                              host->cmd->error = -ETIMEDOUT;
-+                      else
-+                              host->mrq->cmd->error = -ETIMEDOUT;
-+
-+                      tasklet_schedule(&host->finish_tasklet);
-+              }
-+      }
-+
-+      mmiowb();
-+      spin_unlock_irqrestore(&host->lock, flags);
-+}
-+
-+
-+static void bcm2835_mmc_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable)
-+{
-+      if (!(host->flags & SDHCI_DEVICE_DEAD)) {
-+              if (enable)
-+                      host->ier |= SDHCI_INT_CARD_INT;
-+              else
-+                      host->ier &= ~SDHCI_INT_CARD_INT;
-+
-+              bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 7);
-+              bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 7);
-+              mmiowb();
-+      }
-+}
-+
-+static void bcm2835_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
-+{
-+      struct bcm2835_host *host = mmc_priv(mmc);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+      if (enable)
-+              host->flags |= SDHCI_SDIO_IRQ_ENABLED;
-+      else
-+              host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
-+
-+      bcm2835_mmc_enable_sdio_irq_nolock(host, enable);
-+      spin_unlock_irqrestore(&host->lock, flags);
-+}
-+
-+static void bcm2835_mmc_cmd_irq(struct bcm2835_host *host, u32 intmask)
-+{
-+
-+      BUG_ON(intmask == 0);
-+
-+      if (!host->cmd) {
-+              pr_err("%s: Got command interrupt 0x%08x even "
-+                      "though no command operation was in progress.\n",
-+                      mmc_hostname(host->mmc), (unsigned)intmask);
-+              bcm2835_mmc_dumpregs(host);
-+              return;
-+      }
-+
-+      if (intmask & SDHCI_INT_TIMEOUT)
-+              host->cmd->error = -ETIMEDOUT;
-+      else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
-+                      SDHCI_INT_INDEX)) {
-+                      host->cmd->error = -EILSEQ;
-+      }
-+
-+      if (host->cmd->error) {
-+              tasklet_schedule(&host->finish_tasklet);
-+              return;
-+      }
-+
-+      if (intmask & SDHCI_INT_RESPONSE)
-+              bcm2835_mmc_finish_command(host);
-+
-+}
-+
-+static void bcm2835_mmc_data_irq(struct bcm2835_host *host, u32 intmask)
-+{
-+      struct dma_chan *dma_chan;
-+      u32 dir_data;
-+
-+      BUG_ON(intmask == 0);
-+
-+      if (!host->data) {
-+              /*
-+               * The "data complete" interrupt is also used to
-+               * indicate that a busy state has ended. See comment
-+               * above in sdhci_cmd_irq().
-+               */
-+              if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
-+                      if (intmask & SDHCI_INT_DATA_END) {
-+                              bcm2835_mmc_finish_command(host);
-+                              return;
-+                      }
-+              }
-+
-+              pr_debug("%s: Got data interrupt 0x%08x even "
-+                      "though no data operation was in progress.\n",
-+                      mmc_hostname(host->mmc), (unsigned)intmask);
-+              bcm2835_mmc_dumpregs(host);
-+
-+              return;
-+      }
-+
-+      if (intmask & SDHCI_INT_DATA_TIMEOUT)
-+              host->data->error = -ETIMEDOUT;
-+      else if (intmask & SDHCI_INT_DATA_END_BIT)
-+              host->data->error = -EILSEQ;
-+      else if ((intmask & SDHCI_INT_DATA_CRC) &&
-+              SDHCI_GET_CMD(bcm2835_mmc_readw(host, SDHCI_COMMAND))
-+                      != MMC_BUS_TEST_R)
-+              host->data->error = -EILSEQ;
-+
-+      if (host->use_dma) {
-+              if  (host->data->flags & MMC_DATA_WRITE) {
-+                      /* IRQ handled here */
-+
-+                      dma_chan = host->dma_chan_tx;
-+                      dir_data = DMA_TO_DEVICE;
-+                      dma_unmap_sg(dma_chan->device->dev,
-+                               host->data->sg, host->data->sg_len,
-+                               dir_data);
-+
-+                      bcm2835_mmc_finish_data(host);
-+              }
-+
-+      } else {
-+              if (host->data->error)
-+                      bcm2835_mmc_finish_data(host);
-+              else {
-+                      if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
-+                              bcm2835_mmc_transfer_pio(host);
-+
-+                      if (intmask & SDHCI_INT_DATA_END) {
-+                              if (host->cmd) {
-+                                      /*
-+                                       * Data managed to finish before the
-+                                       * command completed. Make sure we do
-+                                       * things in the proper order.
-+                                       */
-+                                      host->data_early = 1;
-+                              } else {
-+                                      bcm2835_mmc_finish_data(host);
-+                              }
-+                      }
-+              }
-+      }
-+}
-+
-+
-+static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id)
-+{
-+      irqreturn_t result = IRQ_NONE;
-+      struct bcm2835_host *host = dev_id;
-+      u32 intmask, mask, unexpected = 0;
-+      int max_loops = 16;
-+
-+      spin_lock(&host->lock);
-+
-+      intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
-+
-+      if (!intmask || intmask == 0xffffffff) {
-+              result = IRQ_NONE;
-+              goto out;
-+      }
-+
-+      do {
-+              /* Clear selected interrupts. */
-+              mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
-+                                SDHCI_INT_BUS_POWER);
-+              bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS, 8);
-+
-+
-+              if (intmask & SDHCI_INT_CMD_MASK)
-+                      bcm2835_mmc_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
-+
-+              if (intmask & SDHCI_INT_DATA_MASK)
-+                      bcm2835_mmc_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
-+
-+              if (intmask & SDHCI_INT_BUS_POWER)
-+                      pr_err("%s: Card is consuming too much power!\n",
-+                              mmc_hostname(host->mmc));
-+
-+              if (intmask & SDHCI_INT_CARD_INT) {
-+                      bcm2835_mmc_enable_sdio_irq_nolock(host, false);
-+                      host->thread_isr |= SDHCI_INT_CARD_INT;
-+                      result = IRQ_WAKE_THREAD;
-+              }
-+
-+              intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
-+                           SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
-+                           SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
-+                           SDHCI_INT_CARD_INT);
-+
-+              if (intmask) {
-+                      unexpected |= intmask;
-+                      bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS, 9);
-+              }
-+
-+              if (result == IRQ_NONE)
-+                      result = IRQ_HANDLED;
-+
-+              intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS);
-+      } while (intmask && --max_loops);
-+out:
-+      spin_unlock(&host->lock);
-+
-+      if (unexpected) {
-+              pr_err("%s: Unexpected interrupt 0x%08x.\n",
-+                         mmc_hostname(host->mmc), unexpected);
-+              bcm2835_mmc_dumpregs(host);
-+      }
-+
-+      return result;
-+}
-+
-+static irqreturn_t bcm2835_mmc_thread_irq(int irq, void *dev_id)
-+{
-+      struct bcm2835_host *host = dev_id;
-+      unsigned long flags;
-+      u32 isr;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+      isr = host->thread_isr;
-+      host->thread_isr = 0;
-+      spin_unlock_irqrestore(&host->lock, flags);
-+
-+      if (isr & SDHCI_INT_CARD_INT) {
-+              sdio_run_irqs(host->mmc);
-+
-+              spin_lock_irqsave(&host->lock, flags);
-+              if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
-+                      bcm2835_mmc_enable_sdio_irq_nolock(host, true);
-+              spin_unlock_irqrestore(&host->lock, flags);
-+      }
-+
-+      return isr ? IRQ_HANDLED : IRQ_NONE;
-+}
-+
-+
-+
-+void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock)
-+{
-+      int div = 0; /* Initialized for compiler warning */
-+      int real_div = div, clk_mul = 1;
-+      u16 clk = 0;
-+      unsigned long timeout;
-+      unsigned int input_clock = clock;
-+
-+      if (host->overclock_50 && (clock == 50000000))
-+              clock = host->overclock_50 * 1000000 + 999999;
-+
-+      host->mmc->actual_clock = 0;
-+
-+      bcm2835_mmc_writew(host, 0, SDHCI_CLOCK_CONTROL);
-+
-+      if (clock == 0)
-+              return;
-+
-+      /* Version 3.00 divisors must be a multiple of 2. */
-+      if (host->max_clk <= clock)
-+              div = 1;
-+      else {
-+              for (div = 2; div < SDHCI_MAX_DIV_SPEC_300;
-+                       div += 2) {
-+                      if ((host->max_clk / div) <= clock)
-+                              break;
-+              }
-+      }
-+
-+      real_div = div;
-+      div >>= 1;
-+
-+      if (real_div)
-+              clock = (host->max_clk * clk_mul) / real_div;
-+      host->mmc->actual_clock = clock;
-+
-+      if ((clock > input_clock) && (clock > host->max_overclock)) {
-+              pr_warn("%s: Overclocking to %dHz\n",
-+                      mmc_hostname(host->mmc), clock);
-+              host->max_overclock = clock;
-+      }
-+
-+      clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
-+      clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
-+              << SDHCI_DIVIDER_HI_SHIFT;
-+      clk |= SDHCI_CLOCK_INT_EN;
-+      bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
-+
-+      /* Wait max 20 ms */
-+      timeout = 20;
-+      while (!((clk = bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL))
-+              & SDHCI_CLOCK_INT_STABLE)) {
-+              if (timeout == 0) {
-+                      pr_err("%s: Internal clock never "
-+                              "stabilised.\n", mmc_hostname(host->mmc));
-+                      bcm2835_mmc_dumpregs(host);
-+                      return;
-+              }
-+              timeout--;
-+              mdelay(1);
-+      }
-+
-+      if (20-timeout > 10 && 20-timeout > host->max_delay) {
-+              host->max_delay = 20-timeout;
-+              pr_warning("Warning: MMC controller hung for %d ms\n", host->max_delay);
-+      }
-+
-+      clk |= SDHCI_CLOCK_CARD_EN;
-+      bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL);
-+}
-+
-+static void bcm2835_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
-+{
-+      struct bcm2835_host *host;
-+      unsigned long flags;
-+
-+      host = mmc_priv(mmc);
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+
-+      WARN_ON(host->mrq != NULL);
-+
-+      host->mrq = mrq;
-+
-+      if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
-+              bcm2835_mmc_send_command(host, mrq->sbc);
-+      else
-+              bcm2835_mmc_send_command(host, mrq->cmd);
-+
-+      mmiowb();
-+      spin_unlock_irqrestore(&host->lock, flags);
-+
-+      if (!(mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) && mrq->cmd->data && host->use_dma) {
-+              /* DMA transfer starts now, PIO starts after interrupt */
-+              bcm2835_mmc_transfer_dma(host);
-+      }
-+}
-+
-+
-+static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-+{
-+
-+      struct bcm2835_host *host = mmc_priv(mmc);
-+      unsigned long flags;
-+      u8 ctrl;
-+      u16 clk, ctrl_2;
-+
-+      pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n",
-+               ios->clock, ios->power_mode, ios->bus_width,
-+               ios->timing, ios->signal_voltage, ios->drv_type);
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+
-+      if (!ios->clock || ios->clock != host->clock) {
-+              bcm2835_mmc_set_clock(host, ios->clock);
-+              host->clock = ios->clock;
-+      }
-+
-+      if (host->pwr != SDHCI_POWER_330) {
-+              host->pwr = SDHCI_POWER_330;
-+              bcm2835_mmc_writeb(host, SDHCI_POWER_330 | SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
-+      }
-+
-+      ctrl = bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL);
-+
-+      /* set bus width */
-+      ctrl &= ~SDHCI_CTRL_8BITBUS;
-+      if (ios->bus_width == MMC_BUS_WIDTH_4)
-+              ctrl |= SDHCI_CTRL_4BITBUS;
-+      else
-+              ctrl &= ~SDHCI_CTRL_4BITBUS;
-+
-+      ctrl &= ~SDHCI_CTRL_HISPD; /* NO_HISPD_BIT */
-+
-+
-+      bcm2835_mmc_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-+      /*
-+       * We only need to set Driver Strength if the
-+       * preset value enable is not set.
-+       */
-+      ctrl_2 = bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2);
-+      ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
-+      if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
-+              ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
-+