3.4: Armadillo 800 and Marzen patches added
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Dec 2012 23:02:06 +0000 (15:02 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Dec 2012 23:02:06 +0000 (15:02 -0800)
207 files changed:
patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch [new file with mode: 0644]
patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch [new file with mode: 0644]
patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch [new file with mode: 0644]
patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch [new file with mode: 0644]
patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch [new file with mode: 0644]
patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch [new file with mode: 0644]
patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch [new file with mode: 0644]
patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch [new file with mode: 0644]
patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch [new file with mode: 0644]
patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch [new file with mode: 0644]
patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch [new file with mode: 0644]
patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch [new file with mode: 0644]
patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch [new file with mode: 0644]
patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch [new file with mode: 0644]
patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch [new file with mode: 0644]
patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch [new file with mode: 0644]
patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch [new file with mode: 0644]
patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch [new file with mode: 0644]
patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch [new file with mode: 0644]
patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch [new file with mode: 0644]
patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch [new file with mode: 0644]
patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch [new file with mode: 0644]
patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch [new file with mode: 0644]
patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch [new file with mode: 0644]
patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch [new file with mode: 0644]
patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch [new file with mode: 0644]
patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch [new file with mode: 0644]
patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch [new file with mode: 0644]
patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch [new file with mode: 0644]
patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch [new file with mode: 0644]
patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch [new file with mode: 0644]
patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch [new file with mode: 0644]
patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch [new file with mode: 0644]
patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch [new file with mode: 0644]
patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch [new file with mode: 0644]
patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch [new file with mode: 0644]
patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch [new file with mode: 0644]
patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch [new file with mode: 0644]
patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch [new file with mode: 0644]
patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch [new file with mode: 0644]
patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch [new file with mode: 0644]
patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch [new file with mode: 0644]
patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch [new file with mode: 0644]
patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch [new file with mode: 0644]
patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch [new file with mode: 0644]
patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch [new file with mode: 0644]
patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch [new file with mode: 0644]
patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch [new file with mode: 0644]
patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch [new file with mode: 0644]
patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch [new file with mode: 0644]
patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch [new file with mode: 0644]
patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch [new file with mode: 0644]
patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch [new file with mode: 0644]
patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch [new file with mode: 0644]
patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch [new file with mode: 0644]
patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch [new file with mode: 0644]
patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch [new file with mode: 0644]
patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch [new file with mode: 0644]
patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch [new file with mode: 0644]
patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch [new file with mode: 0644]
patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch [new file with mode: 0644]
patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch [new file with mode: 0644]
patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch [new file with mode: 0644]
patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch [new file with mode: 0644]
patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch [new file with mode: 0644]
patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch [new file with mode: 0644]
patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch [new file with mode: 0644]
patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch [new file with mode: 0644]
patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch [new file with mode: 0644]
patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch [new file with mode: 0644]
patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch [new file with mode: 0644]
patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch [new file with mode: 0644]
patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch [new file with mode: 0644]
patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch [new file with mode: 0644]
patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch [new file with mode: 0644]
patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch [new file with mode: 0644]
patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch [new file with mode: 0644]
patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch [new file with mode: 0644]
patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch [new file with mode: 0644]
patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch [new file with mode: 0644]
patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch [new file with mode: 0644]
patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch [new file with mode: 0644]
patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch [new file with mode: 0644]
patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch [new file with mode: 0644]
patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch [new file with mode: 0644]
patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch [new file with mode: 0644]
patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch [new file with mode: 0644]
patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch [new file with mode: 0644]
patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch [new file with mode: 0644]
patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch [new file with mode: 0644]
patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch [new file with mode: 0644]
patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch [new file with mode: 0644]
patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch [new file with mode: 0644]
patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch [new file with mode: 0644]
patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch [new file with mode: 0644]
patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch [new file with mode: 0644]
patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch [new file with mode: 0644]
patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch [new file with mode: 0644]
patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch [new file with mode: 0644]
patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch [new file with mode: 0644]
patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch [new file with mode: 0644]
patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch [new file with mode: 0644]
patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch [new file with mode: 0644]
patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch [new file with mode: 0644]
patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch [new file with mode: 0644]
patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch [new file with mode: 0644]
patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch [new file with mode: 0644]
patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch [new file with mode: 0644]
patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch [new file with mode: 0644]
patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch [new file with mode: 0644]
patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch [new file with mode: 0644]
patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch [new file with mode: 0644]
patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch [new file with mode: 0644]
patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch [new file with mode: 0644]
patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch [new file with mode: 0644]
patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch [new file with mode: 0644]
patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch [new file with mode: 0644]
patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch [new file with mode: 0644]
patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch [new file with mode: 0644]
patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch [new file with mode: 0644]
patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch [new file with mode: 0644]
patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch [new file with mode: 0644]
patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch [new file with mode: 0644]
patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch [new file with mode: 0644]
patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch [new file with mode: 0644]
patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch [new file with mode: 0644]
patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch [new file with mode: 0644]
patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch [new file with mode: 0644]
patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch [new file with mode: 0644]
patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch [new file with mode: 0644]
patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch [new file with mode: 0644]
patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch [new file with mode: 0644]
patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch [new file with mode: 0644]
patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch [new file with mode: 0644]
patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch [new file with mode: 0644]
patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch [new file with mode: 0644]
patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch [new file with mode: 0644]
patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch [new file with mode: 0644]
patches.marzen/0032-sh-intc-initial-irqdomain-support.patch [new file with mode: 0644]
patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch [new file with mode: 0644]
patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch [new file with mode: 0644]
patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch [new file with mode: 0644]
patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch [new file with mode: 0644]
patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch [new file with mode: 0644]
patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch [new file with mode: 0644]
patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch [new file with mode: 0644]
patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch [new file with mode: 0644]
patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch [new file with mode: 0644]
patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch [new file with mode: 0644]
patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch [new file with mode: 0644]
patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch [new file with mode: 0644]
patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch [new file with mode: 0644]
patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch [new file with mode: 0644]
patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch [new file with mode: 0644]
patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch [new file with mode: 0644]
patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch [new file with mode: 0644]
patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch [new file with mode: 0644]
patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch [new file with mode: 0644]
patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch [new file with mode: 0644]
patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch [new file with mode: 0644]
patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch [new file with mode: 0644]
patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch [new file with mode: 0644]
patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch [new file with mode: 0644]
patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch [new file with mode: 0644]
patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch [new file with mode: 0644]
patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch [new file with mode: 0644]
patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch [new file with mode: 0644]
patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch [new file with mode: 0644]
patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch [new file with mode: 0644]
patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch [new file with mode: 0644]
patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch [new file with mode: 0644]
patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch [new file with mode: 0644]
patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch [new file with mode: 0644]
patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch [new file with mode: 0644]
patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch [new file with mode: 0644]
patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch [new file with mode: 0644]
patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch [new file with mode: 0644]
patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch [new file with mode: 0644]
patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch [new file with mode: 0644]
patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch [new file with mode: 0644]
patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch [new file with mode: 0644]
patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch [new file with mode: 0644]
patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch [new file with mode: 0644]
patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch [new file with mode: 0644]
patches.marzen/0078-mmc-tmio-add-regulator-support.patch [new file with mode: 0644]
patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch [new file with mode: 0644]
patches.marzen/0080-mmc-tmio-support-caps2-flags.patch [new file with mode: 0644]
patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch [new file with mode: 0644]
patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch [new file with mode: 0644]
patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch [new file with mode: 0644]
patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch [new file with mode: 0644]
patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch [new file with mode: 0644]
patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch [new file with mode: 0644]
patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch [new file with mode: 0644]
patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch [new file with mode: 0644]
patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch [new file with mode: 0644]
patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch [new file with mode: 0644]
patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch [new file with mode: 0644]
patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch [new file with mode: 0644]
patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch [new file with mode: 0644]
patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch [new file with mode: 0644]
patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch [new file with mode: 0644]
patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch [new file with mode: 0644]
patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch [new file with mode: 0644]
patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch [new file with mode: 0644]
patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch [new file with mode: 0644]
series

diff --git a/patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch b/patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch
new file mode 100644 (file)
index 0000000..5316285
--- /dev/null
@@ -0,0 +1,115 @@
+From 4d3626f914a2b4023a3edf428640e578527ac0c8 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:43:00 -0700
+Subject: ARM: shmobile: add common DMAEngine definitions
+
+Current shmobile have DMAEngine specific settings on each CPU code,
+but SH-ARM DMAC use same value.
+
+This patch adds new dma-register.h header to share definitions
+and reduce a waste of code on SH-ARM architecture.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 5ca1d44f6a99b29ab164a06f4ec71950d6939fb5)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/dma-register.h | 84 ++++++++++++++++++++++
+ 1 file changed, 84 insertions(+)
+ create mode 100644 arch/arm/mach-shmobile/include/mach/dma-register.h
+
+diff --git a/arch/arm/mach-shmobile/include/mach/dma-register.h b/arch/arm/mach-shmobile/include/mach/dma-register.h
+new file mode 100644
+index 0000000..97c40bd
+--- /dev/null
++++ b/arch/arm/mach-shmobile/include/mach/dma-register.h
+@@ -0,0 +1,84 @@
++/*
++ * SH-ARM CPU-specific DMA definitions, used by both DMA drivers
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp
++ *
++ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
++ *
++ * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h
++ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef DMA_REGISTER_H
++#define DMA_REGISTER_H
++
++/*
++ *            Direct Memory Access Controller
++ */
++
++/* Transmit sizes and respective CHCR register values */
++enum {
++      XMIT_SZ_8BIT            = 0,
++      XMIT_SZ_16BIT           = 1,
++      XMIT_SZ_32BIT           = 2,
++      XMIT_SZ_64BIT           = 7,
++      XMIT_SZ_128BIT          = 3,
++      XMIT_SZ_256BIT          = 4,
++      XMIT_SZ_512BIT          = 5,
++};
++
++/* log2(size / 8) - used to calculate number of transfers */
++static const unsigned int dma_ts_shift[] = {
++      [XMIT_SZ_8BIT]          = 0,
++      [XMIT_SZ_16BIT]         = 1,
++      [XMIT_SZ_32BIT]         = 2,
++      [XMIT_SZ_64BIT]         = 3,
++      [XMIT_SZ_128BIT]        = 4,
++      [XMIT_SZ_256BIT]        = 5,
++      [XMIT_SZ_512BIT]        = 6,
++};
++
++#define TS_LOW_BIT    0x3 /* --xx */
++#define TS_HI_BIT     0xc /* xx-- */
++
++#define TS_LOW_SHIFT  (3)
++#define TS_HI_SHIFT   (20 - 2)        /* 2 bits for shifted low TS */
++
++#define TS_INDEX2VAL(i) \
++      ((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\
++       (((i) & TS_HI_BIT)  << TS_HI_SHIFT))
++
++#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
++#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
++
++
++/*
++ *            USB High-Speed DMAC
++ */
++/* Transmit sizes and respective CHCR register values */
++enum {
++      USBTS_XMIT_SZ_8BYTE             = 0,
++      USBTS_XMIT_SZ_16BYTE            = 1,
++      USBTS_XMIT_SZ_32BYTE            = 2,
++};
++
++/* log2(size / 8) - used to calculate number of transfers */
++static const unsigned int dma_usbts_shift[] = {
++      [USBTS_XMIT_SZ_8BYTE]   = 3,
++      [USBTS_XMIT_SZ_16BYTE]  = 4,
++      [USBTS_XMIT_SZ_32BYTE]  = 5,
++};
++
++#define USBTS_LOW_BIT 0x3 /* --xx */
++#define USBTS_HI_BIT  0x0 /* ---- */
++
++#define USBTS_LOW_SHIFT       6
++#define USBTS_HI_SHIFT        0
++
++#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
++
++#endif /* DMA_REGISTER_H */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch b/patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch
new file mode 100644 (file)
index 0000000..2acaf3d
--- /dev/null
@@ -0,0 +1,260 @@
+From c13b4e8e39cad46f37b794ba12b8a97569767e25 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:24:46 -0700
+Subject: ARM: shmobile: soc-core: add R-mobile PM domain common APIs
+
+This patch adds Renesas R-mobile series common PM domain APIs.
+R-mobile CPU can use/switch this API
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 8f45b112fc66ef6869ccca4c3966976982f496a9)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Makefile                  |   1 +
+ arch/arm/mach-shmobile/include/mach/pm-rmobile.h |  44 ++++++
+ arch/arm/mach-shmobile/pm-rmobile.c              | 167 +++++++++++++++++++++++
+ 3 files changed, 212 insertions(+)
+ create mode 100644 arch/arm/mach-shmobile/include/mach/pm-rmobile.h
+ create mode 100644 arch/arm/mach-shmobile/pm-rmobile.c
+
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index e7c2590..53846a1e 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_R8A7740)   += entry-intc.o
+ # PM objects
+ obj-$(CONFIG_SUSPEND)         += suspend.o
+ obj-$(CONFIG_CPU_IDLE)                += cpuidle.o
++obj-$(CONFIG_ARCH_SHMOBILE)   += pm-rmobile.o
+ obj-$(CONFIG_ARCH_SH7372)     += pm-sh7372.o sleep-sh7372.o
+ obj-$(CONFIG_ARCH_R8A7779)    += pm-r8a7779.o
+diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
+new file mode 100644
+index 0000000..5a40284
+--- /dev/null
++++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
+@@ -0,0 +1,44 @@
++/*
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ *
++ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#ifndef PM_RMOBILE_H
++#define PM_RMOBILE_H
++
++#include <linux/pm_domain.h>
++
++struct platform_device;
++
++struct rmobile_pm_domain {
++      struct generic_pm_domain genpd;
++      struct dev_power_governor *gov;
++      int (*suspend)(void);
++      void (*resume)(void);
++      unsigned int bit_shift;
++      bool no_debug;
++};
++
++static inline
++struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
++{
++      return container_of(d, struct rmobile_pm_domain, genpd);
++}
++
++#ifdef CONFIG_PM
++extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd);
++extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
++                                      struct platform_device *pdev);
++extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
++                                  struct rmobile_pm_domain *rmobile_sd);
++#else
++#define rmobile_init_pm_domain(pd) do { } while (0)
++#define rmobile_add_device_to_domain(pd, pdev) do { } while (0)
++#define rmobile_pm_add_subdomain(pd, sd) do { } while (0)
++#endif /* CONFIG_PM */
++
++#endif /* PM_RMOBILE_H */
+diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
+new file mode 100644
+index 0000000..a856254
+--- /dev/null
++++ b/arch/arm/mach-shmobile/pm-rmobile.c
+@@ -0,0 +1,167 @@
++/*
++ * rmobile power management support
++ *
++ * Copyright (C) 2012  Renesas Solutions Corp.
++ * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
++ *
++ * based on pm-sh7372.c
++ *  Copyright (C) 2011 Magnus Damm
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/console.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++#include <linux/pm_clock.h>
++#include <asm/io.h>
++#include <mach/pm-rmobile.h>
++
++/* SYSC */
++#define SPDCR         0xe6180008
++#define SWUCR         0xe6180014
++#define PSTR          0xe6180080
++
++#define PSTR_RETRIES  100
++#define PSTR_DELAY_US 10
++
++#ifdef CONFIG_PM
++static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
++{
++      struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
++      unsigned int mask = 1 << rmobile_pd->bit_shift;
++
++      if (rmobile_pd->suspend) {
++              int ret = rmobile_pd->suspend();
++
++              if (ret)
++                      return ret;
++      }
++
++      if (__raw_readl(PSTR) & mask) {
++              unsigned int retry_count;
++              __raw_writel(mask, SPDCR);
++
++              for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
++                      if (!(__raw_readl(SPDCR) & mask))
++                              break;
++                      cpu_relax();
++              }
++      }
++
++      if (!rmobile_pd->no_debug)
++              pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
++                       genpd->name, mask, __raw_readl(PSTR));
++
++      return 0;
++}
++
++static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
++                               bool do_resume)
++{
++      unsigned int mask = 1 << rmobile_pd->bit_shift;
++      unsigned int retry_count;
++      int ret = 0;
++
++      if (__raw_readl(PSTR) & mask)
++              goto out;
++
++      __raw_writel(mask, SWUCR);
++
++      for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
++              if (!(__raw_readl(SWUCR) & mask))
++                      break;
++              if (retry_count > PSTR_RETRIES)
++                      udelay(PSTR_DELAY_US);
++              else
++                      cpu_relax();
++      }
++      if (!retry_count)
++              ret = -EIO;
++
++      if (!rmobile_pd->no_debug)
++              pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
++                       rmobile_pd->genpd.name, mask, __raw_readl(PSTR));
++
++out:
++      if (ret == 0 && rmobile_pd->resume && do_resume)
++              rmobile_pd->resume();
++
++      return ret;
++}
++
++static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
++{
++      return __rmobile_pd_power_up(to_rmobile_pd(genpd), true);
++}
++
++static bool rmobile_pd_active_wakeup(struct device *dev)
++{
++      bool (*active_wakeup)(struct device *dev);
++
++      active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
++      return active_wakeup ? active_wakeup(dev) : true;
++}
++
++static int rmobile_pd_stop_dev(struct device *dev)
++{
++      int (*stop)(struct device *dev);
++
++      stop = dev_gpd_data(dev)->ops.stop;
++      if (stop) {
++              int ret = stop(dev);
++              if (ret)
++                      return ret;
++      }
++      return pm_clk_suspend(dev);
++}
++
++static int rmobile_pd_start_dev(struct device *dev)
++{
++      int (*start)(struct device *dev);
++      int ret;
++
++      ret = pm_clk_resume(dev);
++      if (ret)
++              return ret;
++
++      start = dev_gpd_data(dev)->ops.start;
++      if (start)
++              ret = start(dev);
++
++      return ret;
++}
++
++void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
++{
++      struct generic_pm_domain *genpd = &rmobile_pd->genpd;
++      struct dev_power_governor *gov = rmobile_pd->gov;
++
++      pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
++      genpd->dev_ops.stop             = rmobile_pd_stop_dev;
++      genpd->dev_ops.start            = rmobile_pd_start_dev;
++      genpd->dev_ops.active_wakeup    = rmobile_pd_active_wakeup;
++      genpd->dev_irq_safe             = true;
++      genpd->power_off                = rmobile_pd_power_down;
++      genpd->power_on                 = rmobile_pd_power_up;
++      __rmobile_pd_power_up(rmobile_pd, false);
++}
++
++void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
++                               struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++
++      pm_genpd_add_device(&rmobile_pd->genpd, dev);
++      if (pm_clk_no_clocks(dev))
++              pm_clk_add(dev, NULL);
++}
++
++void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
++                           struct rmobile_pm_domain *rmobile_sd)
++{
++      pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd);
++}
++#endif /* CONFIG_PM */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch b/patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch
new file mode 100644 (file)
index 0000000..e133ecf
--- /dev/null
@@ -0,0 +1,55 @@
+From 657ed37c21c4b58b2ce736343d1c653a842f7299 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 8 May 2012 00:00:07 -0300
+Subject: [media] V4L2: sh_mobile_ceu: manage lower 8bit bus
+
+CAMCR::DTIF feild controls camera bus as upper8bit/16bit/lower8bit.
+This patch manages unmanaged lower 8bit bus
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
+(cherry picked from commit 2564f67bc8d56e5c7fc2970f80f41f2d38db3e21)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/media/video/sh_mobile_ceu_camera.c | 8 +++++---
+ include/media/sh_mobile_ceu.h              | 1 +
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
+index 424dfac..4e0b654 100644
+--- a/drivers/media/video/sh_mobile_ceu_camera.c
++++ b/drivers/media/video/sh_mobile_ceu_camera.c
+@@ -881,11 +881,13 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd)
+       value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
+       value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;
+-      value |= pcdev->is_16bit ? 1 << 12 : 0;
+-      /* CSI2 mode */
+-      if (pcdev->pdata->csi2)
++      if (pcdev->pdata->csi2) /* CSI2 mode */
+               value |= 3 << 12;
++      else if (pcdev->is_16bit)
++              value |= 1 << 12;
++      else if (pcdev->pdata->flags & SH_CEU_FLAG_LOWER_8BIT)
++              value |= 2 << 12;
+       ceu_write(pcdev, CAMCR, value);
+diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h
+index a90a765..6fdb6ad 100644
+--- a/include/media/sh_mobile_ceu.h
++++ b/include/media/sh_mobile_ceu.h
+@@ -5,6 +5,7 @@
+ #define SH_CEU_FLAG_USE_16BIT_BUS     (1 << 1) /* use 16bit bus width */
+ #define SH_CEU_FLAG_HSYNC_LOW         (1 << 2) /* default High if possible */
+ #define SH_CEU_FLAG_VSYNC_LOW         (1 << 3) /* default High if possible */
++#define SH_CEU_FLAG_LOWER_8BIT                (1 << 4) /* default upper 8bit */
+ struct device;
+ struct resource;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch b/patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch
new file mode 100644 (file)
index 0000000..fb5e511
--- /dev/null
@@ -0,0 +1,96 @@
+From 5d792a5a2daa8e2d397c0b5f45ac76c9e0d175ff Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 19 Jun 2012 17:43:56 +0200
+Subject: regulator: support multiple dummy fixed regulators
+
+Currently regulator_register_fixed() uses a constant name to register a
+fixed dummy regulator. This is sufficient in principle, since there is no
+reason to register multiple such regulators. The user can simply supply all
+consumers in one array and use it to initialise such a regulator. However,
+in some cases it can be convenient to register multiple such regulators.
+This is also a prerequisite for the upcoming patch, that will add a voltage
+parameter to this function. The original function is provided as a wrapper
+macro.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit dfad84aeab5f71b33a12e6803a809f698bdef5a2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/regulator/fixed-helper.c | 14 +++++++++++---
+ include/linux/regulator/fixed.h  |  7 +++++--
+ 2 files changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
+index cacd33c..3aa268d 100644
+--- a/drivers/regulator/fixed-helper.c
++++ b/drivers/regulator/fixed-helper.c
+@@ -1,4 +1,5 @@
+ #include <linux/slab.h>
++#include <linux/string.h>
+ #include <linux/platform_device.h>
+ #include <linux/regulator/machine.h>
+ #include <linux/regulator/fixed.h>
+@@ -13,16 +14,18 @@ static void regulator_fixed_release(struct device *dev)
+ {
+       struct fixed_regulator_data *data = container_of(dev,
+                       struct fixed_regulator_data, pdev.dev);
++      kfree(data->cfg.supply_name);
+       kfree(data);
+ }
+ /**
+- * regulator_register_fixed - register a no-op fixed regulator
++ * regulator_register_fixed_name - register a no-op fixed regulator
+  * @id: platform device id
++ * @name: name to be used for the regulator
+  * @supplies: consumers for this regulator
+  * @num_supplies: number of consumers
+  */
+-struct platform_device *regulator_register_fixed(int id,
++struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies)
+ {
+       struct fixed_regulator_data *data;
+@@ -31,7 +34,12 @@ struct platform_device *regulator_register_fixed(int id,
+       if (!data)
+               return NULL;
+-      data->cfg.supply_name = "fixed-dummy";
++      data->cfg.supply_name = kstrdup(name, GFP_KERNEL);
++      if (!data->cfg.supply_name) {
++              kfree(data);
++              return NULL;
++      }
++
+       data->cfg.microvolts = 0;
+       data->cfg.gpio = -EINVAL;
+       data->cfg.enabled_at_boot = 1;
+diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
+index 936a7d8..7bb456c 100644
+--- a/include/linux/regulator/fixed.h
++++ b/include/linux/regulator/fixed.h
+@@ -51,14 +51,17 @@ struct fixed_voltage_config {
+ struct regulator_consumer_supply;
+ #if IS_ENABLED(CONFIG_REGULATOR)
+-struct platform_device *regulator_register_fixed(int id,
++struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies);
+ #else
+-static inline struct platform_device *regulator_register_fixed(int id,
++static inline struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies)
+ {
+       return NULL;
+ }
+ #endif
++#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
++                                              "fixed-dummy", s, ns)
++
+ #endif
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch b/patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch
new file mode 100644 (file)
index 0000000..dccde55
--- /dev/null
@@ -0,0 +1,70 @@
+From c5249f06fd57ea88ef47b750dc11a6f683bd5e5d Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 19 Jun 2012 17:44:39 +0200
+Subject: regulator: extend the fixed dummy voltage regulator to accept voltage
+
+Trivially extend the regulator_register_always_on() helper function to be
+even more useful by adding a voltage parameter to it.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 15719ccc274981b19ad8fe9ac20c94249de8a257)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/regulator/fixed-helper.c | 5 +++--
+ include/linux/regulator/fixed.h  | 6 +++---
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
+index 3aa268d..f9d0279 100644
+--- a/drivers/regulator/fixed-helper.c
++++ b/drivers/regulator/fixed-helper.c
+@@ -24,9 +24,10 @@ static void regulator_fixed_release(struct device *dev)
+  * @name: name to be used for the regulator
+  * @supplies: consumers for this regulator
+  * @num_supplies: number of consumers
++ * @uv: voltage in microvolts
+  */
+ struct platform_device *regulator_register_always_on(int id, const char *name,
+-              struct regulator_consumer_supply *supplies, int num_supplies)
++      struct regulator_consumer_supply *supplies, int num_supplies, int uv)
+ {
+       struct fixed_regulator_data *data;
+@@ -40,7 +41,7 @@ struct platform_device *regulator_register_always_on(int id, const char *name,
+               return NULL;
+       }
+-      data->cfg.microvolts = 0;
++      data->cfg.microvolts = uv;
+       data->cfg.gpio = -EINVAL;
+       data->cfg.enabled_at_boot = 1;
+       data->cfg.init_data = &data->init_data;
+diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
+index 7bb456c..f6372ee 100644
+--- a/include/linux/regulator/fixed.h
++++ b/include/linux/regulator/fixed.h
+@@ -52,16 +52,16 @@ struct regulator_consumer_supply;
+ #if IS_ENABLED(CONFIG_REGULATOR)
+ struct platform_device *regulator_register_always_on(int id, const char *name,
+-              struct regulator_consumer_supply *supplies, int num_supplies);
++              struct regulator_consumer_supply *supplies, int num_supplies, int uv);
+ #else
+ static inline struct platform_device *regulator_register_always_on(int id, const char *name,
+-              struct regulator_consumer_supply *supplies, int num_supplies)
++              struct regulator_consumer_supply *supplies, int num_supplies, int uv)
+ {
+       return NULL;
+ }
+ #endif
+ #define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
+-                                              "fixed-dummy", s, ns)
++                                              "fixed-dummy", s, ns, 0)
+ #endif
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch b/patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch
new file mode 100644 (file)
index 0000000..0f2761d
--- /dev/null
@@ -0,0 +1,32 @@
+From 5f0a6815e3a7c5e73486b7b0a7ffffcf78b81cee Mon Sep 17 00:00:00 2001
+From: Tobias Klauser <tklauser@distanz.ch>
+Date: Mon, 11 Jun 2012 23:55:32 -0700
+Subject: Input: gpio_keys - remove useless reinitialization of pdata->nbuttons
+
+pdata is zeroed using memset just a few lines before, so there is no
+need to set the nbuttons member to 0 again.
+
+Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+(cherry picked from commit 4eceb14f669cb9e9d189019e8fcbf73577fe77a7)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/input/keyboard/gpio_keys.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 62bfce4..cbb1add 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -559,7 +559,6 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
+       pdata->rep = !!of_get_property(node, "autorepeat", NULL);
+       /* First count the subnodes */
+-      pdata->nbuttons = 0;
+       pp = NULL;
+       while ((pp = of_get_next_child(node, pp)))
+               pdata->nbuttons++;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch b/patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch
new file mode 100644 (file)
index 0000000..d0a9ee2
--- /dev/null
@@ -0,0 +1,49 @@
+From ccbea8cbb6f976a4ed42dfba5648bfb543f520d1 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Tue, 3 Apr 2012 11:30:28 -0700
+Subject: Input: st1232 - add device tree support
+
+This patch enables DT support for the st1232 driver
+which is primarily used on the sh7372 Mackerel board.
+
+[dtor@mail.ru: chnaged to use CONFIG_OF and of_match_ptr]
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+(cherry picked from commit e6293d2f8a6cd427a1ef4ddecb16b1d5ae1929cd)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/input/touchscreen/st1232.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
+index cbbf71b..216fabb 100644
+--- a/drivers/input/touchscreen/st1232.c
++++ b/drivers/input/touchscreen/st1232.c
+@@ -255,6 +255,14 @@ static const struct i2c_device_id st1232_ts_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
++#ifdef CONFIG_OF
++static const struct of_device_id st1232_ts_dt_ids[] __devinitconst = {
++      { .compatible = "sitronix,st1232", },
++      { }
++};
++MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
++#endif
++
+ static struct i2c_driver st1232_ts_driver = {
+       .probe          = st1232_ts_probe,
+       .remove         = __devexit_p(st1232_ts_remove),
+@@ -262,6 +270,7 @@ static struct i2c_driver st1232_ts_driver = {
+       .driver = {
+               .name   = ST1232_TS_NAME,
+               .owner  = THIS_MODULE,
++              .of_match_table = of_match_ptr(st1232_ts_dt_ids),
+ #ifdef CONFIG_PM
+               .pm     = &st1232_ts_pm_ops,
+ #endif
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch b/patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch
new file mode 100644 (file)
index 0000000..95252d1
--- /dev/null
@@ -0,0 +1,57 @@
+From 456b9180124a8edec6c90cbd4d2b3f7c8a09a6f7 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Tue, 3 Apr 2012 11:30:28 -0700
+Subject: Input: st1232 - switch to using SIMPLE_DEV_PM_OPS
+
+Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+(cherry picked from commit b3571400395e318306165eabbfbe05a4c3e4366c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/input/touchscreen/st1232.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
+index 216fabb..6cb68a1 100644
+--- a/drivers/input/touchscreen/st1232.c
++++ b/drivers/input/touchscreen/st1232.c
+@@ -218,7 +218,7 @@ static int __devexit st1232_ts_remove(struct i2c_client *client)
+       return 0;
+ }
+-#ifdef CONFIG_PM
++#ifdef CONFIG_PM_SLEEP
+ static int st1232_ts_suspend(struct device *dev)
+ {
+       struct i2c_client *client = to_i2c_client(dev);
+@@ -243,12 +243,11 @@ static int st1232_ts_resume(struct device *dev)
+       return 0;
+ }
+-static const struct dev_pm_ops st1232_ts_pm_ops = {
+-      .suspend        = st1232_ts_suspend,
+-      .resume         = st1232_ts_resume,
+-};
+ #endif
++static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops,
++                       st1232_ts_suspend, st1232_ts_resume);
++
+ static const struct i2c_device_id st1232_ts_id[] = {
+       { ST1232_TS_NAME, 0 },
+       { }
+@@ -271,9 +270,7 @@ static struct i2c_driver st1232_ts_driver = {
+               .name   = ST1232_TS_NAME,
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(st1232_ts_dt_ids),
+-#ifdef CONFIG_PM
+               .pm     = &st1232_ts_pm_ops,
+-#endif
+       },
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch b/patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch
new file mode 100644 (file)
index 0000000..24501ce
--- /dev/null
@@ -0,0 +1,209 @@
+From 38480ba305384441ebefad2684028756f7eab8b2 Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Wed, 4 Apr 2012 18:37:10 +0000
+Subject: net: sh_eth: add support R8A7740
+
+The R8A7740 has a Gigabit Ethernet MAC. This patch supports it.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 73a0d907301ece200d32b4e8ba2da2ca296b507f)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/Kconfig  |   7 ++-
+ drivers/net/ethernet/renesas/sh_eth.c | 114 +++++++++++++++++++++++++++++++++-
+ drivers/net/ethernet/renesas/sh_eth.h |   5 +-
+ 3 files changed, 120 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
+index 3fb2355..46df3a0 100644
+--- a/drivers/net/ethernet/renesas/Kconfig
++++ b/drivers/net/ethernet/renesas/Kconfig
+@@ -4,11 +4,11 @@
+ config SH_ETH
+       tristate "Renesas SuperH Ethernet support"
+-      depends on SUPERH && \
++      depends on (SUPERH || ARCH_SHMOBILE) && \
+               (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
+                CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
+                CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
+-               CPU_SUBTYPE_SH7757)
++               CPU_SUBTYPE_SH7757 || ARCH_R8A7740)
+       select CRC32
+       select NET_CORE
+       select MII
+@@ -17,4 +17,5 @@ config SH_ETH
+       ---help---
+         Renesas SuperH Ethernet device driver.
+         This driver supporting CPUs are:
+-              - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757.
++              - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
++                and R8A7740.
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index d63e09b..be3c221 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -386,6 +386,114 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
+               sh_eth_write(ndev, 0x0, CSMR);
+ }
++#elif defined(CONFIG_ARCH_R8A7740)
++#define SH_ETH_HAS_TSU        1
++static void sh_eth_chip_reset(struct net_device *ndev)
++{
++      struct sh_eth_private *mdp = netdev_priv(ndev);
++      unsigned long mii;
++
++      /* reset device */
++      sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
++      mdelay(1);
++
++      switch (mdp->phy_interface) {
++      case PHY_INTERFACE_MODE_GMII:
++              mii = 2;
++              break;
++      case PHY_INTERFACE_MODE_MII:
++              mii = 1;
++              break;
++      case PHY_INTERFACE_MODE_RMII:
++      default:
++              mii = 0;
++              break;
++      }
++      sh_eth_write(ndev, mii, RMII_MII);
++}
++
++static void sh_eth_reset(struct net_device *ndev)
++{
++      int cnt = 100;
++
++      sh_eth_write(ndev, EDSR_ENALL, EDSR);
++      sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
++      while (cnt > 0) {
++              if (!(sh_eth_read(ndev, EDMR) & 0x3))
++                      break;
++              mdelay(1);
++              cnt--;
++      }
++      if (cnt == 0)
++              printk(KERN_ERR "Device reset fail\n");
++
++      /* Table Init */
++      sh_eth_write(ndev, 0x0, TDLAR);
++      sh_eth_write(ndev, 0x0, TDFAR);
++      sh_eth_write(ndev, 0x0, TDFXR);
++      sh_eth_write(ndev, 0x0, TDFFR);
++      sh_eth_write(ndev, 0x0, RDLAR);
++      sh_eth_write(ndev, 0x0, RDFAR);
++      sh_eth_write(ndev, 0x0, RDFXR);
++      sh_eth_write(ndev, 0x0, RDFFR);
++}
++
++static void sh_eth_set_duplex(struct net_device *ndev)
++{
++      struct sh_eth_private *mdp = netdev_priv(ndev);
++
++      if (mdp->duplex) /* Full */
++              sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
++      else            /* Half */
++              sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
++}
++
++static void sh_eth_set_rate(struct net_device *ndev)
++{
++      struct sh_eth_private *mdp = netdev_priv(ndev);
++
++      switch (mdp->speed) {
++      case 10: /* 10BASE */
++              sh_eth_write(ndev, GECMR_10, GECMR);
++              break;
++      case 100:/* 100BASE */
++              sh_eth_write(ndev, GECMR_100, GECMR);
++              break;
++      case 1000: /* 1000BASE */
++              sh_eth_write(ndev, GECMR_1000, GECMR);
++              break;
++      default:
++              break;
++      }
++}
++
++/* R8A7740 */
++static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
++      .chip_reset     = sh_eth_chip_reset,
++      .set_duplex     = sh_eth_set_duplex,
++      .set_rate       = sh_eth_set_rate,
++
++      .ecsr_value     = ECSR_ICD | ECSR_MPD,
++      .ecsipr_value   = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
++      .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
++
++      .tx_check       = EESR_TC1 | EESR_FTC,
++      .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
++                        EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
++                        EESR_ECI,
++      .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
++                        EESR_TFE,
++
++      .apr            = 1,
++      .mpr            = 1,
++      .tpauser        = 1,
++      .bculr          = 1,
++      .hw_swap        = 1,
++      .no_trimd       = 1,
++      .no_ade         = 1,
++      .tsu            = 1,
++};
++
+ #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+ #define SH_ETH_RESET_DEFAULT  1
+ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+@@ -443,7 +551,7 @@ static void sh_eth_reset(struct net_device *ndev)
+ }
+ #endif
+-#if defined(CONFIG_CPU_SH4)
++#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
+ static void sh_eth_set_receive_align(struct sk_buff *skb)
+ {
+       int reserve;
+@@ -919,6 +1027,10 @@ static int sh_eth_rx(struct net_device *ndev)
+               desc_status = edmac_to_cpu(mdp, rxdesc->status);
+               pkt_len = rxdesc->frame_length;
++#if defined(CONFIG_ARCH_R8A7740)
++              desc_status >>= 16;
++#endif
++
+               if (--boguscnt < 0)
+                       break;
+diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
+index 0fa14afc..57b8e1f 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.h
++++ b/drivers/net/ethernet/renesas/sh_eth.h
+@@ -372,7 +372,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
+ };
+ /* Driver's parameters */
+-#if defined(CONFIG_CPU_SH4)
++#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
+ #define SH4_SKB_RX_ALIGN      32
+ #else
+ #define SH2_SH3_SKB_RX_ALIGN  2
+@@ -381,7 +381,8 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
+ /*
+  * Register's bits
+  */
+-#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
++#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) ||\
++    defined(CONFIG_ARCH_R8A7740)
+ /* EDSR */
+ enum EDSR_BIT {
+       EDSR_ENT = 0x01, EDSR_ENR = 0x02,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch b/patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch
new file mode 100644 (file)
index 0000000..f06a970
--- /dev/null
@@ -0,0 +1,48 @@
+From 02098572c84a88121b0baeb2b96cea47f17f2e3e Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Mon, 28 May 2012 23:07:55 +0000
+Subject: net: sh_eth: fix the rxdesc pointer when rx descriptor empty happens
+
+When Receive Descriptor Empty happens, rxdesc pointer of the driver
+and actual next descriptor of the controller may be mismatch.
+This patch fixes it.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 79fba9f51755c704c0a7d7b7f0df10874dc0a744)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index be3c221..667169b 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -1101,8 +1101,12 @@ static int sh_eth_rx(struct net_device *ndev)
+       /* Restart Rx engine if stopped. */
+       /* If we don't need to check status, don't. -KDU */
+-      if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R))
++      if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
++              /* fix the values for the next receiving */
++              mdp->cur_rx = mdp->dirty_rx = (sh_eth_read(ndev, RDFAR) -
++                                             sh_eth_read(ndev, RDLAR)) >> 4;
+               sh_eth_write(ndev, EDRRR_R, EDRRR);
++      }
+       return 0;
+ }
+@@ -1199,8 +1203,6 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
+               /* Receive Descriptor Empty int */
+               ndev->stats.rx_over_errors++;
+-              if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R)
+-                      sh_eth_write(ndev, EDRRR_R, EDRRR);
+               if (netif_msg_rx_err(mdp))
+                       dev_err(&ndev->dev, "Receive Descriptor Empty\n");
+       }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch b/patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch
new file mode 100644 (file)
index 0000000..9d3e463
--- /dev/null
@@ -0,0 +1,65 @@
+From 1c70638e065f5a6bba99f0e27a3b4a4931c77681 Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Wed, 20 Jun 2012 15:26:34 +0000
+Subject: net: sh_eth: fix the condition to fix the cur_tx/dirty_rx
+
+The following commit couldn't work if the RMCR is not set to 1.
+
+"net: sh_eth: fix the rxdesc pointer when rx descriptor empty happens"
+commit id 79fba9f51755c704c0a7d7b7f0df10874dc0a744
+
+If RMCR is not set, the controller will clear the EDRRR after it received
+a frame. In this case, the driver doesn't need to fix the value of
+cur_rx/dirty_rx. The driver only needs it when the controll detects
+receive descriptors are empty.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit a18e08bdcf845efb7344cea146e683df746bbfb4)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 667169b..79bf09b 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -1011,7 +1011,7 @@ static int sh_eth_txfree(struct net_device *ndev)
+ }
+ /* Packet receive function */
+-static int sh_eth_rx(struct net_device *ndev)
++static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+       struct sh_eth_rxdesc *rxdesc;
+@@ -1102,9 +1102,11 @@ static int sh_eth_rx(struct net_device *ndev)
+       /* Restart Rx engine if stopped. */
+       /* If we don't need to check status, don't. -KDU */
+       if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
+-              /* fix the values for the next receiving */
+-              mdp->cur_rx = mdp->dirty_rx = (sh_eth_read(ndev, RDFAR) -
+-                                             sh_eth_read(ndev, RDLAR)) >> 4;
++              /* fix the values for the next receiving if RDE is set */
++              if (intr_status & EESR_RDE)
++                      mdp->cur_rx = mdp->dirty_rx =
++                              (sh_eth_read(ndev, RDFAR) -
++                               sh_eth_read(ndev, RDLAR)) >> 4;
+               sh_eth_write(ndev, EDRRR_R, EDRRR);
+       }
+@@ -1273,7 +1275,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
+                       EESR_RTSF | /* short frame recv */
+                       EESR_PRE  | /* PHY-LSI recv error */
+                       EESR_CERF)){ /* recv frame CRC error */
+-              sh_eth_rx(ndev);
++              sh_eth_rx(ndev, intr_status);
+       }
+       /* Tx Check */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch b/patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch
new file mode 100644 (file)
index 0000000..66b1134
--- /dev/null
@@ -0,0 +1,196 @@
+From a9d45f3559e2b48428446114ae6817f8a4883de8 Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Date: Mon, 25 Jun 2012 17:34:14 +0000
+Subject: net/sh-eth: Add support selecting MII function for SH7734 and R8A7740
+
+Ethernet IP of SH7734 and R8A7740 has selecting MII register.
+The user needs to change a value according to MII to be used.
+This adds the function to change the value of this register.
+
+Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 5e7a76be0e48217aff6b6f34bdcce4725db999e2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c | 108 ++++++++++++++++++++--------------
+ drivers/net/ethernet/renesas/sh_eth.h |   1 +
+ 2 files changed, 66 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 79bf09b..8d696e0 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -49,6 +49,34 @@
+               NETIF_MSG_RX_ERR| \
+               NETIF_MSG_TX_ERR)
++#if defined(CONFIG_CPU_SUBTYPE_SH7734) || \
++      defined(CONFIG_CPU_SUBTYPE_SH7763) || \
++      defined(CONFIG_ARCH_R8A7740)
++static void sh_eth_select_mii(struct net_device *ndev)
++{
++      u32 value = 0x0;
++      struct sh_eth_private *mdp = netdev_priv(ndev);
++
++      switch (mdp->phy_interface) {
++      case PHY_INTERFACE_MODE_GMII:
++              value = 0x2;
++              break;
++      case PHY_INTERFACE_MODE_MII:
++              value = 0x1;
++              break;
++      case PHY_INTERFACE_MODE_RMII:
++              value = 0x0;
++              break;
++      default:
++              pr_warn("PHY interface mode was not setup. Set to MII.\n");
++              value = 0x1;
++              break;
++      }
++
++      sh_eth_write(ndev, value, RMII_MII);
++}
++#endif
++
+ /* There is CPU dependent code */
+ #if defined(CONFIG_CPU_SUBTYPE_SH7724)
+ #define SH_ETH_RESET_DEFAULT  1
+@@ -283,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
+ #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
+ #define SH_ETH_HAS_TSU        1
+ static void sh_eth_reset_hw_crc(struct net_device *ndev);
++
+ static void sh_eth_chip_reset(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+@@ -292,35 +321,6 @@ static void sh_eth_chip_reset(struct net_device *ndev)
+       mdelay(1);
+ }
+-static void sh_eth_reset(struct net_device *ndev)
+-{
+-      int cnt = 100;
+-
+-      sh_eth_write(ndev, EDSR_ENALL, EDSR);
+-      sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
+-      while (cnt > 0) {
+-              if (!(sh_eth_read(ndev, EDMR) & 0x3))
+-                      break;
+-              mdelay(1);
+-              cnt--;
+-      }
+-      if (cnt == 0)
+-              printk(KERN_ERR "Device reset fail\n");
+-
+-      /* Table Init */
+-      sh_eth_write(ndev, 0x0, TDLAR);
+-      sh_eth_write(ndev, 0x0, TDFAR);
+-      sh_eth_write(ndev, 0x0, TDFXR);
+-      sh_eth_write(ndev, 0x0, TDFFR);
+-      sh_eth_write(ndev, 0x0, RDLAR);
+-      sh_eth_write(ndev, 0x0, RDFAR);
+-      sh_eth_write(ndev, 0x0, RDFXR);
+-      sh_eth_write(ndev, 0x0, RDFFR);
+-
+-      /* Reset HW CRC register */
+-      sh_eth_reset_hw_crc(ndev);
+-}
+-
+ static void sh_eth_set_duplex(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+@@ -377,9 +377,43 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+       .tsu            = 1,
+ #if defined(CONFIG_CPU_SUBTYPE_SH7734)
+       .hw_crc     = 1,
++      .select_mii = 1,
+ #endif
+ };
++static void sh_eth_reset(struct net_device *ndev)
++{
++      int cnt = 100;
++
++      sh_eth_write(ndev, EDSR_ENALL, EDSR);
++      sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
++      while (cnt > 0) {
++              if (!(sh_eth_read(ndev, EDMR) & 0x3))
++                      break;
++              mdelay(1);
++              cnt--;
++      }
++      if (cnt == 0)
++              printk(KERN_ERR "Device reset fail\n");
++
++      /* Table Init */
++      sh_eth_write(ndev, 0x0, TDLAR);
++      sh_eth_write(ndev, 0x0, TDFAR);
++      sh_eth_write(ndev, 0x0, TDFXR);
++      sh_eth_write(ndev, 0x0, TDFFR);
++      sh_eth_write(ndev, 0x0, RDLAR);
++      sh_eth_write(ndev, 0x0, RDFAR);
++      sh_eth_write(ndev, 0x0, RDFXR);
++      sh_eth_write(ndev, 0x0, RDFFR);
++
++      /* Reset HW CRC register */
++      sh_eth_reset_hw_crc(ndev);
++
++      /* Select MII mode */
++      if (sh_eth_my_cpu_data.select_mii)
++              sh_eth_select_mii(ndev);
++}
++
+ static void sh_eth_reset_hw_crc(struct net_device *ndev)
+ {
+       if (sh_eth_my_cpu_data.hw_crc)
+@@ -391,25 +425,12 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
+ static void sh_eth_chip_reset(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+-      unsigned long mii;
+       /* reset device */
+       sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
+       mdelay(1);
+-      switch (mdp->phy_interface) {
+-      case PHY_INTERFACE_MODE_GMII:
+-              mii = 2;
+-              break;
+-      case PHY_INTERFACE_MODE_MII:
+-              mii = 1;
+-              break;
+-      case PHY_INTERFACE_MODE_RMII:
+-      default:
+-              mii = 0;
+-              break;
+-      }
+-      sh_eth_write(ndev, mii, RMII_MII);
++      sh_eth_select_mii(ndev);
+ }
+ static void sh_eth_reset(struct net_device *ndev)
+@@ -492,6 +513,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+       .no_trimd       = 1,
+       .no_ade         = 1,
+       .tsu            = 1,
++      .select_mii     = 1,
+ };
+ #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
+diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
+index 57b8e1f..d6763b1392 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.h
++++ b/drivers/net/ethernet/renesas/sh_eth.h
+@@ -757,6 +757,7 @@ struct sh_eth_cpu_data {
+       unsigned no_trimd:1;            /* E-DMAC DO NOT have TRIMD */
+       unsigned no_ade:1;      /* E-DMAC DO NOT have ADE bit in EESR */
+       unsigned hw_crc:1;      /* E-DMAC have CSMR */
++      unsigned select_mii:1;  /* EtherC have RMII_MII (MII select register) */
+ };
+ struct sh_eth_private {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch b/patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch
new file mode 100644 (file)
index 0000000..1cca1a6
--- /dev/null
@@ -0,0 +1,215 @@
+From d9b780ce68b329aa745868803ec0419a3fd6975f Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Date: Mon, 25 Jun 2012 17:35:12 +0000
+Subject: net/sh-eth: Check return value of sh_eth_reset when chip reset fail
+
+The sh_eth_reset function resets chip, but this performs nothing when failed.
+This changes sh_eth_reset return an error, when this failed in reset.
+
+Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 5cee1d37c9f565f1aa515408863dbb13db67dab9)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c | 88 ++++++++++++++++++++++-------------
+ 1 file changed, 56 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 8d696e0..326cb91 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -130,6 +130,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+ #elif defined(CONFIG_CPU_SUBTYPE_SH7757)
+ #define SH_ETH_HAS_BOTH_MODULES       1
+ #define SH_ETH_HAS_TSU        1
++static int sh_eth_check_reset(struct net_device *ndev);
++
+ static void sh_eth_set_duplex(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+@@ -204,23 +206,19 @@ static void sh_eth_chip_reset_giga(struct net_device *ndev)
+ }
+ static int sh_eth_is_gether(struct sh_eth_private *mdp);
+-static void sh_eth_reset(struct net_device *ndev)
++static int sh_eth_reset(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+-      int cnt = 100;
++      int ret = 0;
+       if (sh_eth_is_gether(mdp)) {
+               sh_eth_write(ndev, 0x03, EDSR);
+               sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
+                               EDMR);
+-              while (cnt > 0) {
+-                      if (!(sh_eth_read(ndev, EDMR) & 0x3))
+-                              break;
+-                      mdelay(1);
+-                      cnt--;
+-              }
+-              if (cnt < 0)
+-                      printk(KERN_ERR "Device reset fail\n");
++
++              ret = sh_eth_check_reset(ndev);
++              if (ret)
++                      goto out;
+               /* Table Init */
+               sh_eth_write(ndev, 0x0, TDLAR);
+@@ -238,6 +236,9 @@ static void sh_eth_reset(struct net_device *ndev)
+               sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
+                               EDMR);
+       }
++
++out:
++      return ret;
+ }
+ static void sh_eth_set_duplex_giga(struct net_device *ndev)
+@@ -310,6 +311,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
+ #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
+ #define SH_ETH_HAS_TSU        1
++static int sh_eth_check_reset(struct net_device *ndev);
+ static void sh_eth_reset_hw_crc(struct net_device *ndev);
+ static void sh_eth_chip_reset(struct net_device *ndev)
+@@ -381,20 +383,16 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+ #endif
+ };
+-static void sh_eth_reset(struct net_device *ndev)
++static int sh_eth_reset(struct net_device *ndev)
+ {
+-      int cnt = 100;
++      int ret = 0;
+       sh_eth_write(ndev, EDSR_ENALL, EDSR);
+       sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
+-      while (cnt > 0) {
+-              if (!(sh_eth_read(ndev, EDMR) & 0x3))
+-                      break;
+-              mdelay(1);
+-              cnt--;
+-      }
+-      if (cnt == 0)
+-              printk(KERN_ERR "Device reset fail\n");
++
++      ret = sh_eth_check_reset(ndev);
++      if (ret)
++              goto out;
+       /* Table Init */
+       sh_eth_write(ndev, 0x0, TDLAR);
+@@ -412,6 +410,8 @@ static void sh_eth_reset(struct net_device *ndev)
+       /* Select MII mode */
+       if (sh_eth_my_cpu_data.select_mii)
+               sh_eth_select_mii(ndev);
++out:
++      return ret;
+ }
+ static void sh_eth_reset_hw_crc(struct net_device *ndev)
+@@ -422,6 +422,8 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev)
+ #elif defined(CONFIG_ARCH_R8A7740)
+ #define SH_ETH_HAS_TSU        1
++static int sh_eth_check_reset(struct net_device *ndev);
++
+ static void sh_eth_chip_reset(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+@@ -433,20 +435,16 @@ static void sh_eth_chip_reset(struct net_device *ndev)
+       sh_eth_select_mii(ndev);
+ }
+-static void sh_eth_reset(struct net_device *ndev)
++static int sh_eth_reset(struct net_device *ndev)
+ {
+-      int cnt = 100;
++      int ret = 0;
+       sh_eth_write(ndev, EDSR_ENALL, EDSR);
+       sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
+-      while (cnt > 0) {
+-              if (!(sh_eth_read(ndev, EDMR) & 0x3))
+-                      break;
+-              mdelay(1);
+-              cnt--;
+-      }
+-      if (cnt == 0)
+-              printk(KERN_ERR "Device reset fail\n");
++
++      ret = sh_eth_check_reset(ndev);
++      if (ret)
++              goto out;
+       /* Table Init */
+       sh_eth_write(ndev, 0x0, TDLAR);
+@@ -457,6 +455,9 @@ static void sh_eth_reset(struct net_device *ndev)
+       sh_eth_write(ndev, 0x0, RDFAR);
+       sh_eth_write(ndev, 0x0, RDFXR);
+       sh_eth_write(ndev, 0x0, RDFFR);
++
++out:
++      return ret;
+ }
+ static void sh_eth_set_duplex(struct net_device *ndev)
+@@ -565,11 +566,31 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
+ #if defined(SH_ETH_RESET_DEFAULT)
+ /* Chip Reset */
+-static void sh_eth_reset(struct net_device *ndev)
++static int  sh_eth_reset(struct net_device *ndev)
+ {
+       sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
+       mdelay(3);
+       sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
++
++      return 0;
++}
++#else
++static int sh_eth_check_reset(struct net_device *ndev)
++{
++      int ret = 0;
++      int cnt = 100;
++
++      while (cnt > 0) {
++              if (!(sh_eth_read(ndev, EDMR) & 0x3))
++                      break;
++              mdelay(1);
++              cnt--;
++      }
++      if (cnt < 0) {
++              printk(KERN_ERR "Device reset fail\n");
++              ret = -ETIMEDOUT;
++      }
++      return ret;
+ }
+ #endif
+@@ -924,7 +945,9 @@ static int sh_eth_dev_init(struct net_device *ndev)
+       u32 val;
+       /* Soft Reset */
+-      sh_eth_reset(ndev);
++      ret = sh_eth_reset(ndev);
++      if (ret)
++              goto out;
+       /* Descriptor format */
+       sh_eth_ring_format(ndev);
+@@ -998,6 +1021,7 @@ static int sh_eth_dev_init(struct net_device *ndev)
+       netif_start_queue(ndev);
++out:
+       return ret;
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch b/patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch
new file mode 100644 (file)
index 0000000..029365f
--- /dev/null
@@ -0,0 +1,94 @@
+From da239ac021220b753bc1f21495ed187275f935aa Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Tue, 26 Jun 2012 19:59:51 +0000
+Subject: net: sh_eth: remove unnecessary function
+
+The sh_eth_timer() called mod_timer() for itself. So, this patch
+removes the function.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit c26502680e59af556211fc3fd3ae0f2aa5d98440)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c | 22 ----------------------
+ drivers/net/ethernet/renesas/sh_eth.h |  1 -
+ 2 files changed, 23 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 326cb91..cf0bc31 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -1339,14 +1339,6 @@ other_irq:
+       return ret;
+ }
+-static void sh_eth_timer(unsigned long data)
+-{
+-      struct net_device *ndev = (struct net_device *)data;
+-      struct sh_eth_private *mdp = netdev_priv(ndev);
+-
+-      mod_timer(&mdp->timer, jiffies + (10 * HZ));
+-}
+-
+ /* PHY state control function */
+ static void sh_eth_adjust_link(struct net_device *ndev)
+ {
+@@ -1594,11 +1586,6 @@ static int sh_eth_open(struct net_device *ndev)
+       if (ret)
+               goto out_free_irq;
+-      /* Set the timer to check for link beat. */
+-      init_timer(&mdp->timer);
+-      mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
+-      setup_timer(&mdp->timer, sh_eth_timer, (unsigned long)ndev);
+-
+       return ret;
+ out_free_irq:
+@@ -1623,9 +1610,6 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
+       /* tx_errors count up */
+       ndev->stats.tx_errors++;
+-      /* timer off */
+-      del_timer_sync(&mdp->timer);
+-
+       /* Free all the skbuffs in the Rx queue. */
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               rxdesc = &mdp->rx_ring[i];
+@@ -1643,10 +1627,6 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
+       /* device init */
+       sh_eth_dev_init(ndev);
+-
+-      /* timer on */
+-      mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
+-      add_timer(&mdp->timer);
+ }
+ /* Packet transmit function */
+@@ -1719,8 +1699,6 @@ static int sh_eth_close(struct net_device *ndev)
+       free_irq(ndev->irq, ndev);
+-      del_timer_sync(&mdp->timer);
+-
+       /* Free all the skbuffs in the Rx queue. */
+       sh_eth_ring_free(ndev);
+diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
+index d6763b1392..5af3f2a 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.h
++++ b/drivers/net/ethernet/renesas/sh_eth.h
+@@ -772,7 +772,6 @@ struct sh_eth_private {
+       struct sh_eth_txdesc *tx_ring;
+       struct sk_buff **rx_skbuff;
+       struct sk_buff **tx_skbuff;
+-      struct timer_list timer;
+       spinlock_t lock;
+       u32 cur_rx, dirty_rx;   /* Producer/consumer ring indices */
+       u32 cur_tx, dirty_tx;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch b/patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch
new file mode 100644 (file)
index 0000000..95923c0
--- /dev/null
@@ -0,0 +1,140 @@
+From c0de8fd97587b151f04aeb92c1946d30e04b3f8a Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Tue, 26 Jun 2012 19:59:58 +0000
+Subject: net: sh_eth: remove unnecessary members/definitions
+
+This patch removes unnecessary members in sh_th_private.
+This patch also removes unnecessary definitions in sh_eth.h
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 2ecbb783c3bf5a63f555c39deef308dcc1902b7f)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c |  7 +---
+ drivers/net/ethernet/renesas/sh_eth.h | 69 -----------------------------------
+ 2 files changed, 1 insertion(+), 75 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index cf0bc31..43e76d2 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -941,7 +941,6 @@ static int sh_eth_dev_init(struct net_device *ndev)
+ {
+       int ret = 0;
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+-      u_int32_t rx_int_var, tx_int_var;
+       u32 val;
+       /* Soft Reset */
+@@ -971,9 +970,7 @@ static int sh_eth_dev_init(struct net_device *ndev)
+       /* Frame recv control */
+       sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
+-      rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
+-      tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
+-      sh_eth_write(ndev, rx_int_var | tx_int_var, TRSCER);
++      sh_eth_write(ndev, DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2, TRSCER);
+       if (mdp->cd->bculr)
+               sh_eth_write(ndev, 0x800, BCULR);       /* Burst sycle set */
+@@ -2336,8 +2333,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
+       /* debug message level */
+       mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
+-      mdp->post_rx = POST_RX >> (devno << 1);
+-      mdp->post_fw = POST_FW >> (devno << 1);
+       /* read and set MAC address */
+       read_mac_address(ndev, pd->mac_addr);
+diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
+index 5af3f2a..37a0702 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.h
++++ b/drivers/net/ethernet/renesas/sh_eth.h
+@@ -585,71 +585,6 @@ enum RPADIR_BIT {
+ /* FDR */
+ #define DEFAULT_FDR_INIT      0x00000707
+-enum phy_offsets {
+-      PHY_CTRL = 0, PHY_STAT = 1, PHY_IDT1 = 2, PHY_IDT2 = 3,
+-      PHY_ANA = 4, PHY_ANL = 5, PHY_ANE = 6,
+-      PHY_16 = 16,
+-};
+-
+-/* PHY_CTRL */
+-enum PHY_CTRL_BIT {
+-      PHY_C_RESET = 0x8000, PHY_C_LOOPBK = 0x4000, PHY_C_SPEEDSL = 0x2000,
+-      PHY_C_ANEGEN = 0x1000, PHY_C_PWRDN = 0x0800, PHY_C_ISO = 0x0400,
+-      PHY_C_RANEG = 0x0200, PHY_C_DUPLEX = 0x0100, PHY_C_COLT = 0x0080,
+-};
+-#define DM9161_PHY_C_ANEGEN 0 /* auto nego special */
+-
+-/* PHY_STAT */
+-enum PHY_STAT_BIT {
+-      PHY_S_100T4 = 0x8000, PHY_S_100X_F = 0x4000, PHY_S_100X_H = 0x2000,
+-      PHY_S_10T_F = 0x1000, PHY_S_10T_H = 0x0800, PHY_S_ANEGC = 0x0020,
+-      PHY_S_RFAULT = 0x0010, PHY_S_ANEGA = 0x0008, PHY_S_LINK = 0x0004,
+-      PHY_S_JAB = 0x0002, PHY_S_EXTD = 0x0001,
+-};
+-
+-/* PHY_ANA */
+-enum PHY_ANA_BIT {
+-      PHY_A_NP = 0x8000, PHY_A_ACK = 0x4000, PHY_A_RF = 0x2000,
+-      PHY_A_FCS = 0x0400, PHY_A_T4 = 0x0200, PHY_A_FDX = 0x0100,
+-      PHY_A_HDX = 0x0080, PHY_A_10FDX = 0x0040, PHY_A_10HDX = 0x0020,
+-      PHY_A_SEL = 0x001e,
+-};
+-/* PHY_ANL */
+-enum PHY_ANL_BIT {
+-      PHY_L_NP = 0x8000, PHY_L_ACK = 0x4000, PHY_L_RF = 0x2000,
+-      PHY_L_FCS = 0x0400, PHY_L_T4 = 0x0200, PHY_L_FDX = 0x0100,
+-      PHY_L_HDX = 0x0080, PHY_L_10FDX = 0x0040, PHY_L_10HDX = 0x0020,
+-      PHY_L_SEL = 0x001f,
+-};
+-
+-/* PHY_ANE */
+-enum PHY_ANE_BIT {
+-      PHY_E_PDF = 0x0010, PHY_E_LPNPA = 0x0008, PHY_E_NPA = 0x0004,
+-      PHY_E_PRX = 0x0002, PHY_E_LPANEGA = 0x0001,
+-};
+-
+-/* DM9161 */
+-enum PHY_16_BIT {
+-      PHY_16_BP4B45 = 0x8000, PHY_16_BPSCR = 0x4000, PHY_16_BPALIGN = 0x2000,
+-      PHY_16_BP_ADPOK = 0x1000, PHY_16_Repeatmode = 0x0800,
+-      PHY_16_TXselect = 0x0400,
+-      PHY_16_Rsvd = 0x0200, PHY_16_RMIIEnable = 0x0100,
+-      PHY_16_Force100LNK = 0x0080,
+-      PHY_16_APDLED_CTL = 0x0040, PHY_16_COLLED_CTL = 0x0020,
+-      PHY_16_RPDCTR_EN = 0x0010,
+-      PHY_16_ResetStMch = 0x0008, PHY_16_PreamSupr = 0x0004,
+-      PHY_16_Sleepmode = 0x0002,
+-      PHY_16_RemoteLoopOut = 0x0001,
+-};
+-
+-#define POST_RX               0x08
+-#define POST_FW               0x04
+-#define POST0_RX      (POST_RX)
+-#define POST0_FW      (POST_FW)
+-#define POST1_RX      (POST_RX >> 2)
+-#define POST1_FW      (POST_FW >> 2)
+-#define POST_ALL      (POST0_RX | POST0_FW | POST1_RX | POST1_FW)
+-
+ /* ARSTR */
+ enum ARSTR_BIT { ARSTR_ARSTR = 0x00000001, };
+@@ -786,10 +721,6 @@ struct sh_eth_private {
+       int msg_enable;
+       int speed;
+       int duplex;
+-      u32 rx_int_var, tx_int_var;     /* interrupt control variables */
+-      char post_rx;           /* POST receive */
+-      char post_fw;           /* POST forward */
+-      struct net_device_stats tsu_stats;      /* TSU forward status */
+       int port;               /* for TSU */
+       int vlan_num_ids;       /* for VLAN tag filter */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch b/patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch
new file mode 100644 (file)
index 0000000..5e09276
--- /dev/null
@@ -0,0 +1,94 @@
+From ec575069aff289fc8d05d09b897bb05e55e90adf Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Tue, 26 Jun 2012 20:00:01 +0000
+Subject: net: sh_eth: fix up the buffer pointers
+
+After freeing the buffer, the driver should change the value of
+the pointer to NULL.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 91c77550000a7d888aaf9f9ac13e3e3485d18560)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c | 31 ++++++++++++++++++++++++-------
+ 1 file changed, 24 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 43e76d2..2dd2ff5 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -788,6 +788,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
+               }
+       }
+       kfree(mdp->rx_skbuff);
++      mdp->rx_skbuff = NULL;
+       /* Free Tx skb ringbuffer */
+       if (mdp->tx_skbuff) {
+@@ -797,6 +798,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
+               }
+       }
+       kfree(mdp->tx_skbuff);
++      mdp->tx_skbuff = NULL;
+ }
+ /* format skb and descriptor buffer */
+@@ -933,10 +935,31 @@ desc_ring_free:
+ skb_ring_free:
+       /* Free Rx and Tx skb ring buffer */
+       sh_eth_ring_free(ndev);
++      mdp->tx_ring = NULL;
++      mdp->rx_ring = NULL;
+       return ret;
+ }
++static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp)
++{
++      int ringsize;
++
++      if (mdp->rx_ring) {
++              ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
++              dma_free_coherent(NULL, ringsize, mdp->rx_ring,
++                                mdp->rx_desc_dma);
++              mdp->rx_ring = NULL;
++      }
++
++      if (mdp->tx_ring) {
++              ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
++              dma_free_coherent(NULL, ringsize, mdp->tx_ring,
++                                mdp->tx_desc_dma);
++              mdp->tx_ring = NULL;
++      }
++}
++
+ static int sh_eth_dev_init(struct net_device *ndev)
+ {
+       int ret = 0;
+@@ -1677,7 +1700,6 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ static int sh_eth_close(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+-      int ringsize;
+       netif_stop_queue(ndev);
+@@ -1700,12 +1722,7 @@ static int sh_eth_close(struct net_device *ndev)
+       sh_eth_ring_free(ndev);
+       /* free DMA buffer */
+-      ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
+-      dma_free_coherent(NULL, ringsize, mdp->rx_ring, mdp->rx_desc_dma);
+-
+-      /* free DMA buffer */
+-      ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
+-      dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma);
++      sh_eth_free_dma_buffer(mdp);
+       pm_runtime_put_sync(&mdp->pdev->dev);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch b/patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch
new file mode 100644 (file)
index 0000000..d1a976c
--- /dev/null
@@ -0,0 +1,407 @@
+From 53432c5cc072269a7e3ac40d2731da16434a24b2 Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Tue, 26 Jun 2012 20:00:03 +0000
+Subject: net: sh_eth: add support for set_ringparam/get_ringparam
+
+This patch supports the ethtool's set_ringparam() and get_ringparam().
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 525b8075edda9c2ab4b81e210505bd7487ea6e56)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/sh_eth.c | 139 ++++++++++++++++++++++++++--------
+ drivers/net/ethernet/renesas/sh_eth.h |   6 ++
+ 2 files changed, 112 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 2dd2ff5..af0b867 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -782,7 +782,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
+       /* Free Rx skb ringbuffer */
+       if (mdp->rx_skbuff) {
+-              for (i = 0; i < RX_RING_SIZE; i++) {
++              for (i = 0; i < mdp->num_rx_ring; i++) {
+                       if (mdp->rx_skbuff[i])
+                               dev_kfree_skb(mdp->rx_skbuff[i]);
+               }
+@@ -792,7 +792,7 @@ static void sh_eth_ring_free(struct net_device *ndev)
+       /* Free Tx skb ringbuffer */
+       if (mdp->tx_skbuff) {
+-              for (i = 0; i < TX_RING_SIZE; i++) {
++              for (i = 0; i < mdp->num_tx_ring; i++) {
+                       if (mdp->tx_skbuff[i])
+                               dev_kfree_skb(mdp->tx_skbuff[i]);
+               }
+@@ -809,8 +809,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
+       struct sk_buff *skb;
+       struct sh_eth_rxdesc *rxdesc = NULL;
+       struct sh_eth_txdesc *txdesc = NULL;
+-      int rx_ringsize = sizeof(*rxdesc) * RX_RING_SIZE;
+-      int tx_ringsize = sizeof(*txdesc) * TX_RING_SIZE;
++      int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
++      int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
+       mdp->cur_rx = mdp->cur_tx = 0;
+       mdp->dirty_rx = mdp->dirty_tx = 0;
+@@ -818,7 +818,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
+       memset(mdp->rx_ring, 0, rx_ringsize);
+       /* build Rx ring buffer */
+-      for (i = 0; i < RX_RING_SIZE; i++) {
++      for (i = 0; i < mdp->num_rx_ring; i++) {
+               /* skb */
+               mdp->rx_skbuff[i] = NULL;
+               skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
+@@ -844,7 +844,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
+               }
+       }
+-      mdp->dirty_rx = (u32) (i - RX_RING_SIZE);
++      mdp->dirty_rx = (u32) (i - mdp->num_rx_ring);
+       /* Mark the last entry as wrapping the ring. */
+       rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL);
+@@ -852,7 +852,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
+       memset(mdp->tx_ring, 0, tx_ringsize);
+       /* build Tx ring buffer */
+-      for (i = 0; i < TX_RING_SIZE; i++) {
++      for (i = 0; i < mdp->num_tx_ring; i++) {
+               mdp->tx_skbuff[i] = NULL;
+               txdesc = &mdp->tx_ring[i];
+               txdesc->status = cpu_to_edmac(mdp, TD_TFP);
+@@ -886,7 +886,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
+               mdp->rx_buf_sz += NET_IP_ALIGN;
+       /* Allocate RX and TX skb rings */
+-      mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
++      mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * mdp->num_rx_ring,
+                               GFP_KERNEL);
+       if (!mdp->rx_skbuff) {
+               dev_err(&ndev->dev, "Cannot allocate Rx skb\n");
+@@ -894,7 +894,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
+               return ret;
+       }
+-      mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * TX_RING_SIZE,
++      mdp->tx_skbuff = kmalloc(sizeof(*mdp->tx_skbuff) * mdp->num_tx_ring,
+                               GFP_KERNEL);
+       if (!mdp->tx_skbuff) {
+               dev_err(&ndev->dev, "Cannot allocate Tx skb\n");
+@@ -903,7 +903,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
+       }
+       /* Allocate all Rx descriptors. */
+-      rx_ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
++      rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
+       mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
+                       GFP_KERNEL);
+@@ -917,7 +917,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
+       mdp->dirty_rx = 0;
+       /* Allocate all Tx descriptors. */
+-      tx_ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
++      tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
+       mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
+                       GFP_KERNEL);
+       if (!mdp->tx_ring) {
+@@ -946,21 +946,21 @@ static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp)
+       int ringsize;
+       if (mdp->rx_ring) {
+-              ringsize = sizeof(struct sh_eth_rxdesc) * RX_RING_SIZE;
++              ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
+               dma_free_coherent(NULL, ringsize, mdp->rx_ring,
+                                 mdp->rx_desc_dma);
+               mdp->rx_ring = NULL;
+       }
+       if (mdp->tx_ring) {
+-              ringsize = sizeof(struct sh_eth_txdesc) * TX_RING_SIZE;
++              ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
+               dma_free_coherent(NULL, ringsize, mdp->tx_ring,
+                                 mdp->tx_desc_dma);
+               mdp->tx_ring = NULL;
+       }
+ }
+-static int sh_eth_dev_init(struct net_device *ndev)
++static int sh_eth_dev_init(struct net_device *ndev, bool start)
+ {
+       int ret = 0;
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+@@ -1008,7 +1008,8 @@ static int sh_eth_dev_init(struct net_device *ndev)
+                    RFLR);
+       sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
+-      sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
++      if (start)
++              sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
+       /* PAUSE Prohibition */
+       val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
+@@ -1023,7 +1024,8 @@ static int sh_eth_dev_init(struct net_device *ndev)
+       sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
+       /* E-MAC Interrupt Enable register */
+-      sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
++      if (start)
++              sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
+       /* Set MAC address */
+       update_mac_address(ndev);
+@@ -1036,10 +1038,12 @@ static int sh_eth_dev_init(struct net_device *ndev)
+       if (mdp->cd->tpauser)
+               sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
+-      /* Setting the Rx mode will start the Rx process. */
+-      sh_eth_write(ndev, EDRRR_R, EDRRR);
++      if (start) {
++              /* Setting the Rx mode will start the Rx process. */
++              sh_eth_write(ndev, EDRRR_R, EDRRR);
+-      netif_start_queue(ndev);
++              netif_start_queue(ndev);
++      }
+ out:
+       return ret;
+@@ -1054,7 +1058,7 @@ static int sh_eth_txfree(struct net_device *ndev)
+       int entry = 0;
+       for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
+-              entry = mdp->dirty_tx % TX_RING_SIZE;
++              entry = mdp->dirty_tx % mdp->num_tx_ring;
+               txdesc = &mdp->tx_ring[entry];
+               if (txdesc->status & cpu_to_edmac(mdp, TD_TACT))
+                       break;
+@@ -1067,7 +1071,7 @@ static int sh_eth_txfree(struct net_device *ndev)
+                       freeNum++;
+               }
+               txdesc->status = cpu_to_edmac(mdp, TD_TFP);
+-              if (entry >= TX_RING_SIZE - 1)
++              if (entry >= mdp->num_tx_ring - 1)
+                       txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
+               ndev->stats.tx_packets++;
+@@ -1082,8 +1086,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+       struct sh_eth_rxdesc *rxdesc;
+-      int entry = mdp->cur_rx % RX_RING_SIZE;
+-      int boguscnt = (mdp->dirty_rx + RX_RING_SIZE) - mdp->cur_rx;
++      int entry = mdp->cur_rx % mdp->num_rx_ring;
++      int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx;
+       struct sk_buff *skb;
+       u16 pkt_len = 0;
+       u32 desc_status;
+@@ -1134,13 +1138,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
+                       ndev->stats.rx_bytes += pkt_len;
+               }
+               rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
+-              entry = (++mdp->cur_rx) % RX_RING_SIZE;
++              entry = (++mdp->cur_rx) % mdp->num_rx_ring;
+               rxdesc = &mdp->rx_ring[entry];
+       }
+       /* Refill the Rx ring buffers. */
+       for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
+-              entry = mdp->dirty_rx % RX_RING_SIZE;
++              entry = mdp->dirty_rx % mdp->num_rx_ring;
+               rxdesc = &mdp->rx_ring[entry];
+               /* The size of the buffer is 16 byte boundary. */
+               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+@@ -1157,7 +1161,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status)
+                       skb_checksum_none_assert(skb);
+                       rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
+               }
+-              if (entry >= RX_RING_SIZE - 1)
++              if (entry >= mdp->num_rx_ring - 1)
+                       rxdesc->status |=
+                               cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL);
+               else
+@@ -1557,6 +1561,71 @@ static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+       }
+ }
++static void sh_eth_get_ringparam(struct net_device *ndev,
++                               struct ethtool_ringparam *ring)
++{
++      struct sh_eth_private *mdp = netdev_priv(ndev);
++
++      ring->rx_max_pending = RX_RING_MAX;
++      ring->tx_max_pending = TX_RING_MAX;
++      ring->rx_pending = mdp->num_rx_ring;
++      ring->tx_pending = mdp->num_tx_ring;
++}
++
++static int sh_eth_set_ringparam(struct net_device *ndev,
++                              struct ethtool_ringparam *ring)
++{
++      struct sh_eth_private *mdp = netdev_priv(ndev);
++      int ret;
++
++      if (ring->tx_pending > TX_RING_MAX ||
++          ring->rx_pending > RX_RING_MAX ||
++          ring->tx_pending < TX_RING_MIN ||
++          ring->rx_pending < RX_RING_MIN)
++              return -EINVAL;
++      if (ring->rx_mini_pending || ring->rx_jumbo_pending)
++              return -EINVAL;
++
++      if (netif_running(ndev)) {
++              netif_tx_disable(ndev);
++              /* Disable interrupts by clearing the interrupt mask. */
++              sh_eth_write(ndev, 0x0000, EESIPR);
++              /* Stop the chip's Tx and Rx processes. */
++              sh_eth_write(ndev, 0, EDTRR);
++              sh_eth_write(ndev, 0, EDRRR);
++              synchronize_irq(ndev->irq);
++      }
++
++      /* Free all the skbuffs in the Rx queue. */
++      sh_eth_ring_free(ndev);
++      /* Free DMA buffer */
++      sh_eth_free_dma_buffer(mdp);
++
++      /* Set new parameters */
++      mdp->num_rx_ring = ring->rx_pending;
++      mdp->num_tx_ring = ring->tx_pending;
++
++      ret = sh_eth_ring_init(ndev);
++      if (ret < 0) {
++              dev_err(&ndev->dev, "%s: sh_eth_ring_init failed.\n", __func__);
++              return ret;
++      }
++      ret = sh_eth_dev_init(ndev, false);
++      if (ret < 0) {
++              dev_err(&ndev->dev, "%s: sh_eth_dev_init failed.\n", __func__);
++              return ret;
++      }
++
++      if (netif_running(ndev)) {
++              sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
++              /* Setting the Rx mode will start the Rx process. */
++              sh_eth_write(ndev, EDRRR_R, EDRRR);
++              netif_wake_queue(ndev);
++      }
++
++      return 0;
++}
++
+ static const struct ethtool_ops sh_eth_ethtool_ops = {
+       .get_settings   = sh_eth_get_settings,
+       .set_settings   = sh_eth_set_settings,
+@@ -1567,6 +1636,8 @@ static const struct ethtool_ops sh_eth_ethtool_ops = {
+       .get_strings    = sh_eth_get_strings,
+       .get_ethtool_stats  = sh_eth_get_ethtool_stats,
+       .get_sset_count     = sh_eth_get_sset_count,
++      .get_ringparam  = sh_eth_get_ringparam,
++      .set_ringparam  = sh_eth_set_ringparam,
+ };
+ /* network device open function */
+@@ -1597,7 +1668,7 @@ static int sh_eth_open(struct net_device *ndev)
+               goto out_free_irq;
+       /* device init */
+-      ret = sh_eth_dev_init(ndev);
++      ret = sh_eth_dev_init(ndev, true);
+       if (ret)
+               goto out_free_irq;
+@@ -1631,7 +1702,7 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
+       ndev->stats.tx_errors++;
+       /* Free all the skbuffs in the Rx queue. */
+-      for (i = 0; i < RX_RING_SIZE; i++) {
++      for (i = 0; i < mdp->num_rx_ring; i++) {
+               rxdesc = &mdp->rx_ring[i];
+               rxdesc->status = 0;
+               rxdesc->addr = 0xBADF00D0;
+@@ -1639,14 +1710,14 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
+                       dev_kfree_skb(mdp->rx_skbuff[i]);
+               mdp->rx_skbuff[i] = NULL;
+       }
+-      for (i = 0; i < TX_RING_SIZE; i++) {
++      for (i = 0; i < mdp->num_tx_ring; i++) {
+               if (mdp->tx_skbuff[i])
+                       dev_kfree_skb(mdp->tx_skbuff[i]);
+               mdp->tx_skbuff[i] = NULL;
+       }
+       /* device init */
+-      sh_eth_dev_init(ndev);
++      sh_eth_dev_init(ndev, true);
+ }
+ /* Packet transmit function */
+@@ -1658,7 +1729,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+       unsigned long flags;
+       spin_lock_irqsave(&mdp->lock, flags);
+-      if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
++      if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) {
+               if (!sh_eth_txfree(ndev)) {
+                       if (netif_msg_tx_queued(mdp))
+                               dev_warn(&ndev->dev, "TxFD exhausted.\n");
+@@ -1669,7 +1740,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+       }
+       spin_unlock_irqrestore(&mdp->lock, flags);
+-      entry = mdp->cur_tx % TX_RING_SIZE;
++      entry = mdp->cur_tx % mdp->num_tx_ring;
+       mdp->tx_skbuff[entry] = skb;
+       txdesc = &mdp->tx_ring[entry];
+       /* soft swap. */
+@@ -1683,7 +1754,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+       else
+               txdesc->buffer_length = skb->len;
+-      if (entry >= TX_RING_SIZE - 1)
++      if (entry >= mdp->num_tx_ring - 1)
+               txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE);
+       else
+               txdesc->status |= cpu_to_edmac(mdp, TD_TACT);
+@@ -2313,6 +2384,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
+       ether_setup(ndev);
+       mdp = netdev_priv(ndev);
++      mdp->num_tx_ring = TX_RING_SIZE;
++      mdp->num_rx_ring = RX_RING_SIZE;
+       mdp->addr = ioremap(res->start, resource_size(res));
+       if (mdp->addr == NULL) {
+               ret = -ENOMEM;
+diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
+index 37a0702..bae84fd 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.h
++++ b/drivers/net/ethernet/renesas/sh_eth.h
+@@ -27,6 +27,10 @@
+ #define TX_TIMEOUT    (5*HZ)
+ #define TX_RING_SIZE  64      /* Tx ring size */
+ #define RX_RING_SIZE  64      /* Rx ring size */
++#define TX_RING_MIN   64
++#define RX_RING_MIN   64
++#define TX_RING_MAX   1024
++#define RX_RING_MAX   1024
+ #define ETHERSMALL            60
+ #define PKT_BUF_SZ            1538
+ #define SH_ETH_TSU_TIMEOUT_MS 500
+@@ -701,6 +705,8 @@ struct sh_eth_private {
+       const u16 *reg_offset;
+       void __iomem *addr;
+       void __iomem *tsu_addr;
++      u32 num_rx_ring;
++      u32 num_tx_ring;
+       dma_addr_t rx_desc_dma;
+       dma_addr_t tx_desc_dma;
+       struct sh_eth_rxdesc *rx_ring;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch b/patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch
new file mode 100644 (file)
index 0000000..91821e1
--- /dev/null
@@ -0,0 +1,71 @@
+From 404932d6f9282b0b5acf10d854fd65611f884521 Mon Sep 17 00:00:00 2001
+From: Phil Edworthy <PHIL.EDWORTHY@renesas.com>
+Date: Tue, 14 Aug 2012 20:33:29 +0000
+Subject: net: sh_eth: Add eth support for R8A7779 device
+
+Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit d0418bb7123f44b23d69ac349eec7daf9103472f)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/renesas/Kconfig  |  4 ++--
+ drivers/net/ethernet/renesas/sh_eth.c | 11 ++++++++---
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
+index 46df3a0..24c2305 100644
+--- a/drivers/net/ethernet/renesas/Kconfig
++++ b/drivers/net/ethernet/renesas/Kconfig
+@@ -8,7 +8,7 @@ config SH_ETH
+               (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
+                CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
+                CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
+-               CPU_SUBTYPE_SH7757 || ARCH_R8A7740)
++               CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || ARCH_R8A7779)
+       select CRC32
+       select NET_CORE
+       select MII
+@@ -18,4 +18,4 @@ config SH_ETH
+         Renesas SuperH Ethernet device driver.
+         This driver supporting CPUs are:
+               - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
+-                and R8A7740.
++                R8A7740 and R8A7779.
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index af0b867..bad8f2e 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -78,7 +78,7 @@ static void sh_eth_select_mii(struct net_device *ndev)
+ #endif
+ /* There is CPU dependent code */
+-#if defined(CONFIG_CPU_SUBTYPE_SH7724)
++#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779)
+ #define SH_ETH_RESET_DEFAULT  1
+ static void sh_eth_set_duplex(struct net_device *ndev)
+ {
+@@ -93,13 +93,18 @@ static void sh_eth_set_duplex(struct net_device *ndev)
+ static void sh_eth_set_rate(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
++      unsigned int bits = ECMR_RTM;
++
++#if defined(CONFIG_ARCH_R8A7779)
++      bits |= ECMR_ELB;
++#endif
+       switch (mdp->speed) {
+       case 10: /* 10BASE */
+-              sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
++              sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR);
+               break;
+       case 100:/* 100BASE */
+-              sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
++              sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR);
+               break;
+       default:
+               break;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch b/patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch
new file mode 100644 (file)
index 0000000..23ec1dd
--- /dev/null
@@ -0,0 +1,239 @@
+From e824e077a91eecb30f3a4124516811ffc382b5a8 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 8 Apr 2012 21:17:50 -0700
+Subject: ASoC: add generic simple-card support
+
+Current ASoC requires card.c file to each platforms in order to
+specifies its CPU and Codecs pair.
+But the differences between these were only value/strings of setting.
+In order to reduce duplicate driver, this patch adds generic/simple-card.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit f2390880ec0264a0ed26b32c23bc23435b4297da)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/sound/simple_card.h     |  38 ++++++++++++++
+ sound/soc/Kconfig               |   3 ++
+ sound/soc/Makefile              |   1 +
+ sound/soc/generic/Kconfig       |   4 ++
+ sound/soc/generic/Makefile      |   3 ++
+ sound/soc/generic/simple-card.c | 114 ++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 163 insertions(+)
+ create mode 100644 include/sound/simple_card.h
+ create mode 100644 sound/soc/generic/Kconfig
+ create mode 100644 sound/soc/generic/Makefile
+ create mode 100644 sound/soc/generic/simple-card.c
+
+diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h
+new file mode 100644
+index 0000000..4b62b8d
+--- /dev/null
++++ b/include/sound/simple_card.h
+@@ -0,0 +1,38 @@
++/*
++ * ASoC simple sound card support
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __SIMPLE_CARD_H
++#define __SIMPLE_CARD_H
++
++#include <sound/soc.h>
++
++struct asoc_simple_dai_init_info {
++      unsigned int fmt;
++      unsigned int cpu_daifmt;
++      unsigned int codec_daifmt;
++      unsigned int sysclk;
++};
++
++struct asoc_simple_card_info {
++      const char *name;
++      const char *card;
++      const char *cpu_dai;
++      const char *codec;
++      const char *platform;
++      const char *codec_dai;
++      struct asoc_simple_dai_init_info *init; /* for snd_link.init */
++
++      /* used in simple-card.c */
++      struct snd_soc_dai_link snd_link;
++      struct snd_soc_card snd_card;
++};
++
++#endif /* __SIMPLE_CARD_H */
+diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
+index 91c9855..38be639 100644
+--- a/sound/soc/Kconfig
++++ b/sound/soc/Kconfig
+@@ -52,5 +52,8 @@ source "sound/soc/txx9/Kconfig"
+ # Supported codecs
+ source "sound/soc/codecs/Kconfig"
++# generic frame-work
++source "sound/soc/generic/Kconfig"
++
+ endif # SND_SOC
+diff --git a/sound/soc/Makefile b/sound/soc/Makefile
+index 2feaf37..b55db9c 100644
+--- a/sound/soc/Makefile
++++ b/sound/soc/Makefile
+@@ -6,6 +6,7 @@ obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
+ obj-$(CONFIG_SND_SOC) += snd-soc-core.o
+ obj-$(CONFIG_SND_SOC) += codecs/
++obj-$(CONFIG_SND_SOC) += generic/
+ obj-$(CONFIG_SND_SOC) += atmel/
+ obj-$(CONFIG_SND_SOC) += au1x/
+ obj-$(CONFIG_SND_SOC) += blackfin/
+diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig
+new file mode 100644
+index 0000000..610f612
+--- /dev/null
++++ b/sound/soc/generic/Kconfig
+@@ -0,0 +1,4 @@
++config SND_SIMPLE_CARD
++      tristate "ASoC Simple sound card support"
++      help
++        This option enables generic simple sound card support
+diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile
+new file mode 100644
+index 0000000..9c3b246
+--- /dev/null
++++ b/sound/soc/generic/Makefile
+@@ -0,0 +1,3 @@
++snd-soc-simple-card-objs      := simple-card.o
++
++obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o
+diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
+new file mode 100644
+index 0000000..b4b4cab
+--- /dev/null
++++ b/sound/soc/generic/simple-card.c
+@@ -0,0 +1,114 @@
++/*
++ * ASoC simple sound card support
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <sound/simple_card.h>
++
++#define asoc_simple_get_card_info(p) \
++      container_of(p->dai_link, struct asoc_simple_card_info, snd_link)
++
++static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
++{
++      struct asoc_simple_card_info *cinfo = asoc_simple_get_card_info(rtd);
++      struct asoc_simple_dai_init_info *iinfo = cinfo->init;
++      struct snd_soc_dai *codec = rtd->codec_dai;
++      struct snd_soc_dai *cpu = rtd->cpu_dai;
++      unsigned int cpu_daifmt = iinfo->fmt | iinfo->cpu_daifmt;
++      unsigned int codec_daifmt = iinfo->fmt | iinfo->codec_daifmt;
++      int ret;
++
++      if (codec_daifmt) {
++              ret = snd_soc_dai_set_fmt(codec, codec_daifmt);
++              if (ret < 0)
++                      return ret;
++      }
++
++      if (iinfo->sysclk) {
++              ret = snd_soc_dai_set_sysclk(codec, 0, iinfo->sysclk, 0);
++              if (ret < 0)
++                      return ret;
++      }
++
++      if (cpu_daifmt) {
++              ret = snd_soc_dai_set_fmt(cpu, cpu_daifmt);
++              if (ret < 0)
++                      return ret;
++      }
++
++      return 0;
++}
++
++static int asoc_simple_card_probe(struct platform_device *pdev)
++{
++      struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
++
++      if (!cinfo) {
++              dev_err(&pdev->dev, "no info for asoc-simple-card\n");
++              return -EINVAL;
++      }
++
++      if (!cinfo->name        ||
++          !cinfo->card        ||
++          !cinfo->cpu_dai     ||
++          !cinfo->codec       ||
++          !cinfo->platform    ||
++          !cinfo->codec_dai) {
++              dev_err(&pdev->dev, "insufficient asoc_simple_card_info settings\n");
++              return -EINVAL;
++      }
++
++      /*
++       * init snd_soc_dai_link
++       */
++      cinfo->snd_link.name            = cinfo->name;
++      cinfo->snd_link.stream_name     = cinfo->name;
++      cinfo->snd_link.cpu_dai_name    = cinfo->cpu_dai;
++      cinfo->snd_link.platform_name   = cinfo->platform;
++      cinfo->snd_link.codec_name      = cinfo->codec;
++      cinfo->snd_link.codec_dai_name  = cinfo->codec_dai;
++
++      /* enable snd_link.init if cinfo has settings */
++      if (cinfo->init)
++              cinfo->snd_link.init    = asoc_simple_card_dai_init;
++
++      /*
++       * init snd_soc_card
++       */
++      cinfo->snd_card.name            = cinfo->card;
++      cinfo->snd_card.owner           = THIS_MODULE;
++      cinfo->snd_card.dai_link        = &cinfo->snd_link;
++      cinfo->snd_card.num_links       = 1;
++      cinfo->snd_card.dev             = &pdev->dev;
++
++      return snd_soc_register_card(&cinfo->snd_card);
++}
++
++static int asoc_simple_card_remove(struct platform_device *pdev)
++{
++      struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
++
++      return snd_soc_unregister_card(&cinfo->snd_card);
++}
++
++static struct platform_driver asoc_simple_card = {
++      .driver = {
++              .name   = "asoc-simple-card",
++      },
++      .probe          = asoc_simple_card_probe,
++      .remove         = asoc_simple_card_remove,
++};
++
++module_platform_driver(asoc_simple_card);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("ASoC Simple Sound Card");
++MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch b/patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch
new file mode 100644 (file)
index 0000000..a612922
--- /dev/null
@@ -0,0 +1,358 @@
+From 69dbe4e265126dd9dcd679d7f707c73fa86b88ef Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 8 Apr 2012 21:18:28 -0700
+Subject: ASoC: sh: fsi: use simple-card instead of fsi-ak4642
+
+This patch uses simple-card driver instead of fsi-ak4642 on each board.
+To select AK4642 driver, each boards select it on Kconfig.
+
+This patch removes fsi-ak4642 driver which is no longer needed
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit af8a2fe12fae1b59178dc96e396e5665bcbea7da)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Kconfig          |   2 +
+ arch/arm/mach-shmobile/board-ap4evb.c   |  15 ++++-
+ arch/arm/mach-shmobile/board-mackerel.c |  15 ++++-
+ arch/sh/boards/Kconfig                  |   1 +
+ arch/sh/boards/mach-se/7724/setup.c     |  15 ++++-
+ include/sound/sh_fsi.h                  |  12 ----
+ sound/soc/sh/Kconfig                    |   8 ---
+ sound/soc/sh/Makefile                   |   2 -
+ sound/soc/sh/fsi-ak4642.c               | 108 --------------------------------
+ 9 files changed, 39 insertions(+), 139 deletions(-)
+ delete mode 100644 sound/soc/sh/fsi-ak4642.c
+
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index 34560ca..2cda0c2 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -58,6 +58,7 @@ config MACH_AP4EVB
+       depends on ARCH_SH7372
+       select ARCH_REQUIRE_GPIOLIB
+       select SH_LCD_MIPI_DSI
++      select SND_SOC_AK4642 if SND_SIMPLE_CARD
+ choice
+       prompt "AP4EVB LCD panel selection"
+@@ -82,6 +83,7 @@ config MACH_MACKEREL
+       bool "mackerel board"
+       depends on ARCH_SH7372
+       select ARCH_REQUIRE_GPIOLIB
++      select SND_SOC_AK4642 if SND_SIMPLE_CARD
+ config MACH_KOTA2
+       bool "KOTA2 board"
+diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
+index b56dde2..b397512 100644
+--- a/arch/arm/mach-shmobile/board-ap4evb.c
++++ b/arch/arm/mach-shmobile/board-ap4evb.c
+@@ -50,6 +50,7 @@
+ #include <media/soc_camera.h>
+ #include <sound/sh_fsi.h>
++#include <sound/simple_card.h>
+ #include <video/sh_mobile_hdmi.h>
+ #include <video/sh_mobile_lcdc.h>
+@@ -785,17 +786,25 @@ static struct platform_device fsi_device = {
+       },
+ };
+-static struct fsi_ak4642_info fsi2_ak4643_info = {
++static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
++      .fmt            = SND_SOC_DAIFMT_LEFT_J,
++      .codec_daifmt   = SND_SOC_DAIFMT_CBM_CFM,
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBS_CFS,
++      .sysclk         = 11289600,
++};
++
++static struct asoc_simple_card_info fsi2_ak4643_info = {
+       .name           = "AK4643",
+       .card           = "FSI2A-AK4643",
+       .cpu_dai        = "fsia-dai",
+       .codec          = "ak4642-codec.0-0013",
+       .platform       = "sh_fsi2",
+-      .id             = FSI_PORT_A,
++      .codec_dai      = "ak4642-hifi",
++      .init           = &fsi2_ak4643_init_info,
+ };
+ static struct platform_device fsi_ak4643_device = {
+-      .name   = "fsi-ak4642-audio",
++      .name   = "asoc-simple-card",
+       .dev    = {
+               .platform_data  = &fsi2_ak4643_info,
+       },
+diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
+index 8c6202b..b63de55 100644
+--- a/arch/arm/mach-shmobile/board-mackerel.c
++++ b/arch/arm/mach-shmobile/board-mackerel.c
+@@ -53,6 +53,7 @@
+ #include <media/soc_camera.h>
+ #include <media/soc_camera_platform.h>
+ #include <sound/sh_fsi.h>
++#include <sound/simple_card.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+@@ -941,17 +942,25 @@ static struct platform_device fsi_device = {
+       },
+ };
+-static struct fsi_ak4642_info fsi2_ak4643_info = {
++static struct asoc_simple_dai_init_info fsi2_ak4643_init_info = {
++      .fmt            = SND_SOC_DAIFMT_LEFT_J,
++      .codec_daifmt   = SND_SOC_DAIFMT_CBM_CFM,
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBS_CFS,
++      .sysclk         = 11289600,
++};
++
++static struct asoc_simple_card_info fsi2_ak4643_info = {
+       .name           = "AK4643",
+       .card           = "FSI2A-AK4643",
+       .cpu_dai        = "fsia-dai",
+       .codec          = "ak4642-codec.0-0013",
+       .platform       = "sh_fsi2",
+-      .id             = FSI_PORT_A,
++      .codec_dai      = "ak4642-hifi",
++      .init           = &fsi2_ak4643_init_info,
+ };
+ static struct platform_device fsi_ak4643_device = {
+-      .name   = "fsi-ak4642-audio",
++      .name   = "asoc-simple-card",
+       .dev    = {
+               .platform_data  = &fsi2_ak4643_info,
+       },
+diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
+index d893411..0da49f3 100644
+--- a/arch/sh/boards/Kconfig
++++ b/arch/sh/boards/Kconfig
+@@ -54,6 +54,7 @@ config SH_7724_SOLUTION_ENGINE
+       select SOLUTION_ENGINE
+       depends on CPU_SUBTYPE_SH7724
+       select ARCH_REQUIRE_GPIOLIB
++      select SND_SOC_AK4642 if SND_SIMPLE_CARD
+       help
+         Select 7724 SolutionEngine if configuring for a Hitachi SH7724
+         evaluation board.
+diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
+index c540b16..5cc5ed4 100644
+--- a/arch/sh/boards/mach-se/7724/setup.c
++++ b/arch/sh/boards/mach-se/7724/setup.c
+@@ -28,6 +28,7 @@
+ #include <video/sh_mobile_lcdc.h>
+ #include <media/sh_mobile_ceu.h>
+ #include <sound/sh_fsi.h>
++#include <sound/simple_card.h>
+ #include <asm/io.h>
+ #include <asm/heartbeat.h>
+ #include <asm/clock.h>
+@@ -304,17 +305,25 @@ static struct platform_device fsi_device = {
+       },
+ };
+-static struct fsi_ak4642_info fsi_ak4642_info = {
++static struct asoc_simple_dai_init_info fsi2_ak4642_init_info = {
++      .fmt            = SND_SOC_DAIFMT_LEFT_J,
++      .codec_daifmt   = SND_SOC_DAIFMT_CBM_CFM,
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBS_CFS,
++      .sysclk         = 11289600,
++};
++
++static struct asoc_simple_card_info fsi_ak4642_info = {
+       .name           = "AK4642",
+       .card           = "FSIA-AK4642",
+       .cpu_dai        = "fsia-dai",
+       .codec          = "ak4642-codec.0-0012",
+       .platform       = "sh_fsi.0",
+-      .id             = FSI_PORT_A,
++      .codec_dai      = "ak4642-hifi",
++      .init           = &fsi2_ak4642_init_info,
+ };
+ static struct platform_device fsi_ak4642_device = {
+-      .name   = "fsi-ak4642-audio",
++      .name   = "asoc-simple-card",
+       .dev    = {
+               .platform_data  = &fsi_ak4642_info,
+       },
+diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
+index b457e87..956e30e 100644
+--- a/include/sound/sh_fsi.h
++++ b/include/sound/sh_fsi.h
+@@ -84,16 +84,4 @@ struct sh_fsi_platform_info {
+       struct sh_fsi_port_info port_b;
+ };
+-/*
+- * for fsi-ak4642
+- */
+-struct fsi_ak4642_info {
+-      const char *name;
+-      const char *card;
+-      const char *cpu_dai;
+-      const char *codec;
+-      const char *platform;
+-      int id;
+-};
+-
+ #endif /* __SOUND_FSI_H */
+diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
+index d8e06a6..c68b90b 100644
+--- a/sound/soc/sh/Kconfig
++++ b/sound/soc/sh/Kconfig
+@@ -46,14 +46,6 @@ config SND_SH7760_AC97
+         This option enables generic sound support for the first
+         AC97 unit of the SH7760.
+-config SND_FSI_AK4642
+-      tristate "FSI-AK4642 sound support"
+-      depends on SND_SOC_SH4_FSI && I2C
+-      select SND_SOC_AK4642
+-      help
+-        This option enables generic sound support for the
+-        FSI - AK4642 unit
+-
+ config SND_FSI_DA7210
+       tristate "FSI-DA7210 sound support"
+       depends on SND_SOC_SH4_FSI && I2C
+diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
+index 94476d4..01808cd 100644
+--- a/sound/soc/sh/Makefile
++++ b/sound/soc/sh/Makefile
+@@ -14,13 +14,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU)      += snd-soc-siu.o
+ ## boards
+ snd-soc-sh7760-ac97-objs      := sh7760-ac97.o
+-snd-soc-fsi-ak4642-objs               := fsi-ak4642.o
+ snd-soc-fsi-da7210-objs               := fsi-da7210.o
+ snd-soc-fsi-hdmi-objs         := fsi-hdmi.o
+ snd-soc-migor-objs            := migor.o
+ obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
+-obj-$(CONFIG_SND_FSI_AK4642)  += snd-soc-fsi-ak4642.o
+ obj-$(CONFIG_SND_FSI_DA7210)  += snd-soc-fsi-da7210.o
+ obj-$(CONFIG_SND_FSI_HDMI)    += snd-soc-fsi-hdmi.o
+ obj-$(CONFIG_SND_SIU_MIGOR)   += snd-soc-migor.o
+diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
+deleted file mode 100644
+index 97f540a..0000000
+--- a/sound/soc/sh/fsi-ak4642.c
++++ /dev/null
+@@ -1,108 +0,0 @@
+-/*
+- * FSI-AK464x sound support for ms7724se
+- *
+- * Copyright (C) 2009 Renesas Solutions Corp.
+- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- */
+-
+-#include <linux/platform_device.h>
+-#include <linux/module.h>
+-#include <sound/sh_fsi.h>
+-
+-struct fsi_ak4642_data {
+-      const char *name;
+-      const char *card;
+-      const char *cpu_dai;
+-      const char *codec;
+-      const char *platform;
+-      int id;
+-};
+-
+-static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
+-{
+-      struct snd_soc_dai *codec = rtd->codec_dai;
+-      struct snd_soc_dai *cpu = rtd->cpu_dai;
+-      int ret;
+-
+-      ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J |
+-                                       SND_SOC_DAIFMT_CBM_CFM);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J |
+-                                     SND_SOC_DAIFMT_CBS_CFS);
+-
+-      return ret;
+-}
+-
+-static struct snd_soc_dai_link fsi_dai_link = {
+-      .codec_dai_name = "ak4642-hifi",
+-      .init           = fsi_ak4642_dai_init,
+-};
+-
+-static struct snd_soc_card fsi_soc_card  = {
+-      .owner          = THIS_MODULE,
+-      .dai_link       = &fsi_dai_link,
+-      .num_links      = 1,
+-};
+-
+-static struct platform_device *fsi_snd_device;
+-
+-static int fsi_ak4642_probe(struct platform_device *pdev)
+-{
+-      int ret = -ENOMEM;
+-      struct fsi_ak4642_info *pinfo = pdev->dev.platform_data;
+-
+-      if (!pinfo) {
+-              dev_err(&pdev->dev, "no info for fsi ak4642\n");
+-              goto out;
+-      }
+-
+-      fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id);
+-      if (!fsi_snd_device)
+-              goto out;
+-
+-      fsi_dai_link.name               = pinfo->name;
+-      fsi_dai_link.stream_name        = pinfo->name;
+-      fsi_dai_link.cpu_dai_name       = pinfo->cpu_dai;
+-      fsi_dai_link.platform_name      = pinfo->platform;
+-      fsi_dai_link.codec_name         = pinfo->codec;
+-      fsi_soc_card.name               = pinfo->card;
+-
+-      platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
+-      ret = platform_device_add(fsi_snd_device);
+-
+-      if (ret)
+-              platform_device_put(fsi_snd_device);
+-
+-out:
+-      return ret;
+-}
+-
+-static int fsi_ak4642_remove(struct platform_device *pdev)
+-{
+-      platform_device_unregister(fsi_snd_device);
+-      return 0;
+-}
+-
+-static struct platform_driver fsi_ak4642 = {
+-      .driver = {
+-              .name   = "fsi-ak4642-audio",
+-      },
+-      .probe          = fsi_ak4642_probe,
+-      .remove         = fsi_ak4642_remove,
+-};
+-
+-module_platform_driver(fsi_ak4642);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
+-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch b/patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch
new file mode 100644 (file)
index 0000000..704a5a6
--- /dev/null
@@ -0,0 +1,246 @@
+From bd1e0d9b157b61d6a283ab31f175f6bab4277cfe Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 8 Apr 2012 21:18:58 -0700
+Subject: ASoC: sh: fsi: use simple-card instead of fsi-hdmi
+
+This patch uses simple-card driver instead of fsi-hdmi on each board.
+This patch removes fsi-hdmi driver which is no longer needed
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit fa063b48046c1f30cb06898559bb34935ade74e1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-ap4evb.c   |  20 +++++-
+ arch/arm/mach-shmobile/board-mackerel.c |  20 +++++-
+ sound/soc/sh/Kconfig                    |   7 --
+ sound/soc/sh/Makefile                   |   2 -
+ sound/soc/sh/fsi-hdmi.c                 | 118 --------------------------------
+ 5 files changed, 38 insertions(+), 129 deletions(-)
+ delete mode 100644 sound/soc/sh/fsi-hdmi.c
+
+diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
+index b397512..8302265 100644
+--- a/arch/arm/mach-shmobile/board-ap4evb.c
++++ b/arch/arm/mach-shmobile/board-ap4evb.c
+@@ -909,8 +909,26 @@ static struct platform_device lcdc1_device = {
+       },
+ };
++static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBM_CFM,
++};
++
++static struct asoc_simple_card_info fsi2_hdmi_info = {
++      .name           = "HDMI",
++      .card           = "FSI2B-HDMI",
++      .cpu_dai        = "fsib-dai",
++      .codec          = "sh-mobile-hdmi",
++      .platform       = "sh_fsi2",
++      .codec_dai      = "sh_mobile_hdmi-hifi",
++      .init           = &fsi2_hdmi_init_info,
++};
++
+ static struct platform_device fsi_hdmi_device = {
+-      .name           = "sh_fsi2_b_hdmi",
++      .name   = "asoc-simple-card",
++      .id     = 1,
++      .dev    = {
++              .platform_data  = &fsi2_hdmi_info,
++      },
+ };
+ static struct gpio_led ap4evb_leds[] = {
+diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
+index b63de55..fb27bac 100644
+--- a/arch/arm/mach-shmobile/board-mackerel.c
++++ b/arch/arm/mach-shmobile/board-mackerel.c
+@@ -503,8 +503,26 @@ static struct platform_device hdmi_lcdc_device = {
+       },
+ };
++static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBM_CFM,
++};
++
++static struct asoc_simple_card_info fsi2_hdmi_info = {
++      .name           = "HDMI",
++      .card           = "FSI2B-HDMI",
++      .cpu_dai        = "fsib-dai",
++      .codec          = "sh-mobile-hdmi",
++      .platform       = "sh_fsi2",
++      .codec_dai      = "sh_mobile_hdmi-hifi",
++      .init           = &fsi2_hdmi_init_info,
++};
++
+ static struct platform_device fsi_hdmi_device = {
+-      .name           = "sh_fsi2_b_hdmi",
++      .name   = "asoc-simple-card",
++      .id     = 1,
++      .dev    = {
++              .platform_data  = &fsi2_hdmi_info,
++      },
+ };
+ static void __init hdmi_init_pm_clock(void)
+diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
+index c68b90b..9ef49c8 100644
+--- a/sound/soc/sh/Kconfig
++++ b/sound/soc/sh/Kconfig
+@@ -54,13 +54,6 @@ config SND_FSI_DA7210
+         This option enables generic sound support for the
+         FSI - DA7210 unit
+-config SND_FSI_HDMI
+-      tristate "FSI-HDMI sound support"
+-      depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI
+-      help
+-        This option enables generic sound support for the
+-        FSI - HDMI unit
+-
+ config SND_SIU_MIGOR
+       tristate "SIU sound support on Migo-R"
+       depends on SH_MIGOR
+diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
+index 01808cd..f37fc3a 100644
+--- a/sound/soc/sh/Makefile
++++ b/sound/soc/sh/Makefile
+@@ -15,10 +15,8 @@ obj-$(CONFIG_SND_SOC_SH4_SIU)       += snd-soc-siu.o
+ ## boards
+ snd-soc-sh7760-ac97-objs      := sh7760-ac97.o
+ snd-soc-fsi-da7210-objs               := fsi-da7210.o
+-snd-soc-fsi-hdmi-objs         := fsi-hdmi.o
+ snd-soc-migor-objs            := migor.o
+ obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
+ obj-$(CONFIG_SND_FSI_DA7210)  += snd-soc-fsi-da7210.o
+-obj-$(CONFIG_SND_FSI_HDMI)    += snd-soc-fsi-hdmi.o
+ obj-$(CONFIG_SND_SIU_MIGOR)   += snd-soc-migor.o
+diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
+deleted file mode 100644
+index 6e41908..0000000
+--- a/sound/soc/sh/fsi-hdmi.c
++++ /dev/null
+@@ -1,118 +0,0 @@
+-/*
+- * FSI - HDMI sound support
+- *
+- * Copyright (C) 2010 Renesas Solutions Corp.
+- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License.  See the file "COPYING" in the main directory of this archive
+- * for more details.
+- */
+-
+-#include <linux/platform_device.h>
+-#include <linux/module.h>
+-#include <sound/sh_fsi.h>
+-
+-struct fsi_hdmi_data {
+-      const char *cpu_dai;
+-      const char *card;
+-      int id;
+-};
+-
+-static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd)
+-{
+-      struct snd_soc_dai *cpu = rtd->cpu_dai;
+-      int ret;
+-
+-      ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM);
+-
+-      return ret;
+-}
+-
+-static struct snd_soc_dai_link fsi_dai_link = {
+-      .name           = "HDMI",
+-      .stream_name    = "HDMI",
+-      .codec_dai_name = "sh_mobile_hdmi-hifi",
+-      .platform_name  = "sh_fsi2",
+-      .codec_name     = "sh-mobile-hdmi",
+-      .init           = fsi_hdmi_dai_init,
+-};
+-
+-static struct snd_soc_card fsi_soc_card  = {
+-      .owner          = THIS_MODULE,
+-      .dai_link       = &fsi_dai_link,
+-      .num_links      = 1,
+-};
+-
+-static struct platform_device *fsi_snd_device;
+-
+-static int fsi_hdmi_probe(struct platform_device *pdev)
+-{
+-      int ret = -ENOMEM;
+-      const struct platform_device_id *id_entry;
+-      struct fsi_hdmi_data *pdata;
+-
+-      id_entry = pdev->id_entry;
+-      if (!id_entry) {
+-              dev_err(&pdev->dev, "unknown fsi hdmi\n");
+-              return -ENODEV;
+-      }
+-
+-      pdata = (struct fsi_hdmi_data *)id_entry->driver_data;
+-
+-      fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
+-      if (!fsi_snd_device)
+-              goto out;
+-
+-      fsi_dai_link.cpu_dai_name       = pdata->cpu_dai;
+-      fsi_soc_card.name               = pdata->card;
+-
+-      platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
+-      ret = platform_device_add(fsi_snd_device);
+-
+-      if (ret)
+-              platform_device_put(fsi_snd_device);
+-
+-out:
+-      return ret;
+-}
+-
+-static int fsi_hdmi_remove(struct platform_device *pdev)
+-{
+-      platform_device_unregister(fsi_snd_device);
+-      return 0;
+-}
+-
+-static struct fsi_hdmi_data fsi2_a_hdmi = {
+-      .cpu_dai        = "fsia-dai",
+-      .card           = "FSI2A-HDMI",
+-      .id             = FSI_PORT_A,
+-};
+-
+-static struct fsi_hdmi_data fsi2_b_hdmi = {
+-      .cpu_dai        = "fsib-dai",
+-      .card           = "FSI2B-HDMI",
+-      .id             = FSI_PORT_B,
+-};
+-
+-static struct platform_device_id fsi_id_table[] = {
+-      /* FSI 2 */
+-      { "sh_fsi2_a_hdmi",     (kernel_ulong_t)&fsi2_a_hdmi },
+-      { "sh_fsi2_b_hdmi",     (kernel_ulong_t)&fsi2_b_hdmi },
+-      {},
+-};
+-
+-static struct platform_driver fsi_hdmi = {
+-      .driver = {
+-              .name   = "fsi-hdmi-audio",
+-      },
+-      .probe          = fsi_hdmi_probe,
+-      .remove         = fsi_hdmi_remove,
+-      .id_table       = fsi_id_table,
+-};
+-
+-module_platform_driver(fsi_hdmi);
+-
+-MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
+-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch b/patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch
new file mode 100644 (file)
index 0000000..037ab31
--- /dev/null
@@ -0,0 +1,210 @@
+From 0baa4d444616c8bd593aaf36ca25639d66da129a Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 8 Apr 2012 21:19:25 -0700
+Subject: ASoC: sh: fsi: use simple-card instead of fsi-da7210
+
+This patch uses simple-card driver instead of fsi-da7210 on each board.
+To select DA7210 driver, each boards select it on Kconfig.
+
+This patch removes fsi-da7210 driver which is no longer needed
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 064bfada66779d95686cacdcbb17551e2c0bf66b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/sh/boards/Kconfig               |  1 +
+ arch/sh/boards/mach-ecovec24/setup.c | 26 ++++++++++++
+ sound/soc/sh/Kconfig                 |  8 ----
+ sound/soc/sh/Makefile                |  2 -
+ sound/soc/sh/fsi-da7210.c            | 81 ------------------------------------
+ 5 files changed, 27 insertions(+), 91 deletions(-)
+ delete mode 100644 sound/soc/sh/fsi-da7210.c
+
+diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
+index 0da49f3..c0241bd 100644
+--- a/arch/sh/boards/Kconfig
++++ b/arch/sh/boards/Kconfig
+@@ -224,6 +224,7 @@ config SH_ECOVEC
+       bool "EcoVec"
+       depends on CPU_SUBTYPE_SH7724
+       select ARCH_REQUIRE_GPIOLIB
++      select SND_SOC_DA7210 if SND_SIMPLE_CARD
+       help
+         Renesas "R0P7724LC0011/21RL (EcoVec)" support.
+diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
+index d12fe9d..299a40a 100644
+--- a/arch/sh/boards/mach-ecovec24/setup.c
++++ b/arch/sh/boards/mach-ecovec24/setup.c
+@@ -32,6 +32,7 @@
+ #include <linux/videodev2.h>
+ #include <video/sh_mobile_lcdc.h>
+ #include <sound/sh_fsi.h>
++#include <sound/simple_card.h>
+ #include <media/sh_mobile_ceu.h>
+ #include <media/soc_camera.h>
+ #include <media/tw9910.h>
+@@ -809,6 +810,30 @@ static struct platform_device fsi_device = {
+       },
+ };
++static struct asoc_simple_dai_init_info fsi_da7210_init_info = {
++      .fmt            = SND_SOC_DAIFMT_I2S,
++      .codec_daifmt   = SND_SOC_DAIFMT_CBM_CFM,
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBS_CFS,
++};
++
++static struct asoc_simple_card_info fsi_da7210_info = {
++      .name           = "DA7210",
++      .card           = "FSIB-DA7210",
++      .cpu_dai        = "fsib-dai",
++      .codec          = "da7210.0-001a",
++      .platform       = "sh_fsi.0",
++      .codec_dai      = "da7210-hifi",
++      .init           = &fsi_da7210_init_info,
++};
++
++static struct platform_device fsi_da7210_device = {
++      .name   = "asoc-simple-card",
++      .dev    = {
++              .platform_data  = &fsi_da7210_info,
++      },
++};
++
++
+ /* IrDA */
+ static struct resource irda_resources[] = {
+       [0] = {
+@@ -945,6 +970,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
+       &camera_devices[1],
+       &camera_devices[2],
+       &fsi_device,
++      &fsi_da7210_device,
+       &irda_device,
+       &vou_device,
+ #if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE)
+diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
+index 9ef49c8..c9fdf63 100644
+--- a/sound/soc/sh/Kconfig
++++ b/sound/soc/sh/Kconfig
+@@ -46,14 +46,6 @@ config SND_SH7760_AC97
+         This option enables generic sound support for the first
+         AC97 unit of the SH7760.
+-config SND_FSI_DA7210
+-      tristate "FSI-DA7210 sound support"
+-      depends on SND_SOC_SH4_FSI && I2C
+-      select SND_SOC_DA7210
+-      help
+-        This option enables generic sound support for the
+-        FSI - DA7210 unit
+-
+ config SND_SIU_MIGOR
+       tristate "SIU sound support on Migo-R"
+       depends on SH_MIGOR
+diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
+index f37fc3a..849b387 100644
+--- a/sound/soc/sh/Makefile
++++ b/sound/soc/sh/Makefile
+@@ -14,9 +14,7 @@ obj-$(CONFIG_SND_SOC_SH4_SIU)        += snd-soc-siu.o
+ ## boards
+ snd-soc-sh7760-ac97-objs      := sh7760-ac97.o
+-snd-soc-fsi-da7210-objs               := fsi-da7210.o
+ snd-soc-migor-objs            := migor.o
+ obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
+-obj-$(CONFIG_SND_FSI_DA7210)  += snd-soc-fsi-da7210.o
+ obj-$(CONFIG_SND_SIU_MIGOR)   += snd-soc-migor.o
+diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
+deleted file mode 100644
+index 1dd3354..0000000
+--- a/sound/soc/sh/fsi-da7210.c
++++ /dev/null
+@@ -1,81 +0,0 @@
+-/*
+- * fsi-da7210.c
+- *
+- * Copyright (C) 2009 Renesas Solutions Corp.
+- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+- *
+- *  This program is free software; you can redistribute  it and/or modify it
+- *  under  the terms of  the GNU General  Public License as published by the
+- *  Free Software Foundation;  either version 2 of the  License, or (at your
+- *  option) any later version.
+- */
+-
+-#include <linux/platform_device.h>
+-#include <linux/module.h>
+-#include <sound/sh_fsi.h>
+-
+-static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
+-{
+-      struct snd_soc_dai *codec = rtd->codec_dai;
+-      struct snd_soc_dai *cpu = rtd->cpu_dai;
+-      int ret;
+-
+-      ret = snd_soc_dai_set_fmt(codec,
+-                                 SND_SOC_DAIFMT_I2S |
+-                                 SND_SOC_DAIFMT_CBM_CFM);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S |
+-                                     SND_SOC_DAIFMT_CBS_CFS);
+-
+-      return ret;
+-}
+-
+-static struct snd_soc_dai_link fsi_da7210_dai = {
+-      .name           = "DA7210",
+-      .stream_name    = "DA7210",
+-      .cpu_dai_name   = "fsib-dai", /* FSI B */
+-      .codec_dai_name = "da7210-hifi",
+-      .platform_name  = "sh_fsi.0",
+-      .codec_name     = "da7210-codec.0-001a",
+-      .init           = fsi_da7210_init,
+-};
+-
+-static struct snd_soc_card fsi_soc_card = {
+-      .name           = "FSI-DA7210",
+-      .owner          = THIS_MODULE,
+-      .dai_link       = &fsi_da7210_dai,
+-      .num_links      = 1,
+-};
+-
+-static struct platform_device *fsi_da7210_snd_device;
+-
+-static int __init fsi_da7210_sound_init(void)
+-{
+-      int ret;
+-
+-      fsi_da7210_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
+-      if (!fsi_da7210_snd_device)
+-              return -ENOMEM;
+-
+-      platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card);
+-      ret = platform_device_add(fsi_da7210_snd_device);
+-      if (ret)
+-              platform_device_put(fsi_da7210_snd_device);
+-
+-      return ret;
+-}
+-
+-static void __exit fsi_da7210_sound_exit(void)
+-{
+-      platform_device_unregister(fsi_da7210_snd_device);
+-}
+-
+-module_init(fsi_da7210_sound_init);
+-module_exit(fsi_da7210_sound_exit);
+-
+-/* Module information */
+-MODULE_DESCRIPTION("ALSA SoC FSI DA2710");
+-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
+-MODULE_LICENSE("GPL");
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch b/patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch
new file mode 100644 (file)
index 0000000..56622e1
--- /dev/null
@@ -0,0 +1,27 @@
+From 09e74410c4effeb137a0aa05425057b740deb997 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 17 May 2012 17:33:49 -0700
+Subject: ASoC: sh: fsi: use register field macro name on IN/OUT_DMAC
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 4d62ec125be98f5a446444e4ce53f4f4e2e1baff)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1218,8 +1218,8 @@ static int fsi_hw_startup(struct fsi_pri
+        * FSI2 chip can select it.
+        */
+       if (fsi_ver >= 2) {
+-              fsi_reg_write(fsi, OUT_DMAC,    (1 << 4));
+-              fsi_reg_write(fsi, IN_DMAC,     (1 << 4));
++              fsi_reg_write(fsi, OUT_DMAC,    VDMD_BACK);
++              fsi_reg_write(fsi, IN_DMAC,     VDMD_BACK);
+       }
+       /* irq clear */
diff --git a/patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch b/patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch
new file mode 100644 (file)
index 0000000..71fc21e
--- /dev/null
@@ -0,0 +1,105 @@
+From 9bc6d811db2dfc4f27805bc62d39e1bc319653e0 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 17 May 2012 17:34:16 -0700
+Subject: ASoC: sh: fsi: add fsi_version() and removed meaningless version
+ check
+
+This patch adds fsi_version() function for accessing version.
+
+And there were some meaningless version check which never hit.
+This patch removed it.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 284c6f6547dd08d8f26e12f4014ec298faa7da03)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |   26 ++++++++------------------
+ 1 file changed, 8 insertions(+), 18 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -322,6 +322,10 @@ static void _fsi_master_mask_set(struct
+ /*
+  *            basic function
+  */
++static int fsi_version(struct fsi_master *master)
++{
++      return master->core->ver;
++}
+ static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
+ {
+@@ -630,11 +634,6 @@ static void fsi_spdif_clk_ctrl(struct fs
+       struct fsi_master *master = fsi_get_master(fsi);
+       u32 mask, val;
+-      if (master->core->ver < 2) {
+-              pr_err("fsi: register access err (%s)\n", __func__);
+-              return;
+-      }
+-
+       mask = BP | SE;
+       val = enable ? mask : 0;
+@@ -649,9 +648,7 @@ static void fsi_spdif_clk_ctrl(struct fs
+ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
+                             long rate, int enable)
+ {
+-      struct fsi_master *master = fsi_get_master(fsi);
+       set_rate_func set_rate = fsi_get_info_set_rate(fsi);
+-      int fsi_ver = master->core->ver;
+       int ret;
+       if (!set_rate)
+@@ -683,10 +680,7 @@ static int fsi_set_master_clk(struct dev
+                       data |= (0x3 << 12);
+                       break;
+               case SH_FSI_ACKMD_32:
+-                      if (fsi_ver < 2)
+-                              dev_err(dev, "unsupported ACKMD\n");
+-                      else
+-                              data |= (0x4 << 12);
++                      data |= (0x4 << 12);
+                       break;
+               }
+@@ -709,10 +703,7 @@ static int fsi_set_master_clk(struct dev
+                       data |= (0x4 << 8);
+                       break;
+               case SH_FSI_BPFMD_16:
+-                      if (fsi_ver < 2)
+-                              dev_err(dev, "unsupported ACKMD\n");
+-                      else
+-                              data |= (0x7 << 8);
++                      data |= (0x7 << 8);
+                       break;
+               }
+@@ -1178,7 +1169,6 @@ static int fsi_hw_startup(struct fsi_pri
+                         struct device *dev)
+ {
+       struct fsi_master *master = fsi_get_master(fsi);
+-      int fsi_ver = master->core->ver;
+       u32 flags = fsi_get_info_flags(fsi);
+       u32 data = 0;
+@@ -1217,7 +1207,7 @@ static int fsi_hw_startup(struct fsi_pri
+        * FSI driver assumed that data package is in-back.
+        * FSI2 chip can select it.
+        */
+-      if (fsi_ver >= 2) {
++      if (fsi_version(master) >= 2) {
+               fsi_reg_write(fsi, OUT_DMAC,    VDMD_BACK);
+               fsi_reg_write(fsi, IN_DMAC,     VDMD_BACK);
+       }
+@@ -1307,7 +1297,7 @@ static int fsi_set_fmt_spdif(struct fsi_
+       struct fsi_master *master = fsi_get_master(fsi);
+       u32 data = 0;
+-      if (master->core->ver < 2)
++      if (fsi_version(master) < 2)
+               return -EINVAL;
+       data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
diff --git a/patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch b/patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch
new file mode 100644 (file)
index 0000000..9d9fe53
--- /dev/null
@@ -0,0 +1,83 @@
+From e41d8c0d85612475f270a3f0318570d4974f148f Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 17 May 2012 17:34:53 -0700
+Subject: ASoC: sh: fsi: use same format for IN/OUT
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 9c59dd342e4dd3c0bab5a9cad1aca7ed9501cbf8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |   22 ++++++----------------
+ 1 file changed, 6 insertions(+), 16 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -212,8 +212,7 @@ struct fsi_priv {
+       struct fsi_stream playback;
+       struct fsi_stream capture;
+-      u32 do_fmt;
+-      u32 di_fmt;
++      u32 fmt;
+       int chan_num:16;
+       int clk_master:1;
+@@ -1192,8 +1191,8 @@ static int fsi_hw_startup(struct fsi_pri
+       fsi_reg_write(fsi, CKG2, data);
+       /* set format */
+-      fsi_reg_write(fsi, DO_FMT, fsi->do_fmt);
+-      fsi_reg_write(fsi, DI_FMT, fsi->di_fmt);
++      fsi_reg_write(fsi, DO_FMT, fsi->fmt);
++      fsi_reg_write(fsi, DI_FMT, fsi->fmt);
+       /* spdif ? */
+       if (fsi_is_spdif(fsi)) {
+@@ -1271,42 +1270,33 @@ static int fsi_dai_trigger(struct snd_pc
+ static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
+ {
+-      u32 data = 0;
+-
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+-              data = CR_I2S;
++              fsi->fmt = CR_I2S;
+               fsi->chan_num = 2;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+-              data = CR_PCM;
++              fsi->fmt = CR_PCM;
+               fsi->chan_num = 2;
+               break;
+       default:
+               return -EINVAL;
+       }
+-      fsi->do_fmt = data;
+-      fsi->di_fmt = data;
+-
+       return 0;
+ }
+ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
+ {
+       struct fsi_master *master = fsi_get_master(fsi);
+-      u32 data = 0;
+       if (fsi_version(master) < 2)
+               return -EINVAL;
+-      data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
++      fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
+       fsi->chan_num = 2;
+       fsi->spdif = 1;
+-      fsi->do_fmt = data;
+-      fsi->di_fmt = data;
+-
+       return 0;
+ }
diff --git a/patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch b/patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch
new file mode 100644 (file)
index 0000000..9d371ff
--- /dev/null
@@ -0,0 +1,53 @@
+From 30a251b30f73fdfa25d8e260c389bd688951b010 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 17 May 2012 17:35:34 -0700
+Subject: ASoC: sh: fsi: call fsi_hw_startup/shutdown from fsi_dai_trigger()
+
+fsi_hw_startup/shutdown() needs the setup of bus width,
+but it is impossible to get parameter of snd_pcm_runtime at this timing.
+So, these functions are changed so that be called from fsi_dai_trigger().
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit f33238e96f619d9888713c07dcd92e4518879282)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1233,7 +1233,9 @@ static int fsi_dai_startup(struct snd_pc
+ {
+       struct fsi_priv *fsi = fsi_get_priv(substream);
+-      return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
++      fsi->rate = 0;
++
++      return 0;
+ }
+ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
+@@ -1241,7 +1243,6 @@ static void fsi_dai_shutdown(struct snd_
+ {
+       struct fsi_priv *fsi = fsi_get_priv(substream);
+-      fsi_hw_shutdown(fsi, dai->dev);
+       fsi->rate = 0;
+ }
+@@ -1255,11 +1256,13 @@ static int fsi_dai_trigger(struct snd_pc
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               fsi_stream_init(fsi, io, substream);
++              fsi_hw_startup(fsi, io, dai->dev);
+               ret = fsi_stream_transfer(io);
+               if (0 == ret)
+                       fsi_stream_start(fsi, io);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
++              fsi_hw_shutdown(fsi, dai->dev);
+               fsi_stream_stop(fsi, io);
+               fsi_stream_quit(fsi, io);
+               break;
diff --git a/patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch b/patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch
new file mode 100644 (file)
index 0000000..2788110
--- /dev/null
@@ -0,0 +1,334 @@
+From 603569524ecf479df58238d5c3556bb0882361b1 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 17 May 2012 17:36:47 -0700
+Subject: ASoC: sh: fsi: enable chip specific data transfer mode
+
+SupherH FSI2 can use special data transfer,
+but it depends on CPU-FSI2 connection style.
+
+We can use 16bit data stream mode if it was valid connection,
+and it is required for 16bit data DMA transfer / SPDIF sound output.
+We can use 24bit data transfer if it was invalid connection.
+
+We can select connection type if CPU is SH7372,
+and it is always valid connection if latest SuperH.
+
+This patch adds new bus_option and fsi_bus_setup()
+for supporting these feature.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 766812e6d5e2e23be1e212cf84902d5e834dd865)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/sound/sh_fsi.h |    6 +
+ sound/soc/sh/fsi.c     |  177 +++++++++++++++++++++++++++++++++++++++----------
+ 2 files changed, 148 insertions(+), 35 deletions(-)
+
+--- a/include/sound/sh_fsi.h
++++ b/include/sound/sh_fsi.h
+@@ -21,10 +21,11 @@
+ /*
+  * flags format
+  *
+- * 0x000000BA
++ * 0x00000CBA
+  *
+  * A:  inversion
+  * B:  format mode
++ * C:  chip specific
+  */
+ /* A: clock inversion */
+@@ -39,6 +40,9 @@
+ #define SH_FSI_FMT_DAI                (0 << 4)
+ #define SH_FSI_FMT_SPDIF      (1 << 4)
++/* C: chip specific */
++#define SH_FSI_OPTION_MASK    0x00000F00
++#define SH_FSI_ENABLE_STREAM_MODE     (1 << 8) /* for 16bit data */
+ /*
+  * set_rate return value
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -133,6 +133,25 @@
+ typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
+ /*
++ * bus options
++ *
++ * 0x000000BA
++ *
++ * A : sample widtht 16bit setting
++ * B : sample widtht 24bit setting
++ */
++
++#define SHIFT_16DATA          0
++#define SHIFT_24DATA          4
++
++#define PACKAGE_24BITBUS_BACK         0
++#define PACKAGE_24BITBUS_FRONT                1
++#define PACKAGE_16BITBUS_STREAM               2
++
++#define BUSOP_SET(s, a)       ((a) << SHIFT_ ## s ## DATA)
++#define BUSOP_GET(s, a)       (((a) >> SHIFT_ ## s ## DATA) & 0xF)
++
++/*
+  * FSI driver use below type name for variable
+  *
+  * xxx_num    : number of data
+@@ -190,6 +209,11 @@ struct fsi_stream {
+       int oerr_num;
+       /*
++       * bus options
++       */
++      u32 bus_option;
++
++      /*
+        * thse are initialized by fsi_handler_init()
+        */
+       struct fsi_stream_handler *handler;
+@@ -499,6 +523,7 @@ static void fsi_stream_init(struct fsi_p
+       io->period_samples      = fsi_frame2sample(fsi, runtime->period_size);
+       io->period_pos          = 0;
+       io->sample_width        = samples_to_bytes(runtime, 1);
++      io->bus_option          = 0;
+       io->oerr_num    = -1; /* ignore 1st err */
+       io->uerr_num    = -1; /* ignore 1st err */
+       fsi_stream_handler_call(io, init, fsi, io);
+@@ -526,6 +551,7 @@ static void fsi_stream_quit(struct fsi_p
+       io->period_samples      = 0;
+       io->period_pos          = 0;
+       io->sample_width        = 0;
++      io->bus_option          = 0;
+       io->oerr_num    = 0;
+       io->uerr_num    = 0;
+       spin_unlock_irqrestore(&master->lock, flags);
+@@ -585,6 +611,53 @@ static int fsi_stream_remove(struct fsi_
+ }
+ /*
++ *    format/bus/dma setting
++ */
++static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io,
++                               u32 bus, struct device *dev)
++{
++      struct fsi_master *master = fsi_get_master(fsi);
++      int is_play = fsi_stream_is_play(fsi, io);
++      u32 fmt = fsi->fmt;
++
++      if (fsi_version(master) >= 2) {
++              u32 dma = 0;
++
++              /*
++               * FSI2 needs DMA/Bus setting
++               */
++              switch (bus) {
++              case PACKAGE_24BITBUS_FRONT:
++                      fmt |= CR_BWS_24;
++                      dma |= VDMD_FRONT;
++                      dev_dbg(dev, "24bit bus / package in front\n");
++                      break;
++              case PACKAGE_16BITBUS_STREAM:
++                      fmt |= CR_BWS_16;
++                      dma |= VDMD_STREAM;
++                      dev_dbg(dev, "16bit bus / stream mode\n");
++                      break;
++              case PACKAGE_24BITBUS_BACK:
++              default:
++                      fmt |= CR_BWS_24;
++                      dma |= VDMD_BACK;
++                      dev_dbg(dev, "24bit bus / package in back\n");
++                      break;
++              }
++
++              if (is_play)
++                      fsi_reg_write(fsi, OUT_DMAC,    dma);
++              else
++                      fsi_reg_write(fsi, IN_DMAC,     dma);
++      }
++
++      if (is_play)
++              fsi_reg_write(fsi, DO_FMT, fmt);
++      else
++              fsi_reg_write(fsi, DI_FMT, fmt);
++}
++
++/*
+  *            irq function
+  */
+@@ -719,11 +792,26 @@ static int fsi_set_master_clk(struct dev
+  */
+ static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
+ {
+-      u16 *buf = (u16 *)_buf;
++      u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
+       int i;
+-      for (i = 0; i < samples; i++)
+-              fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
++      if (enable_stream) {
++              /*
++               * stream mode
++               * see
++               *      fsi_pio_push_init()
++               */
++              u32 *buf = (u32 *)_buf;
++
++              for (i = 0; i < samples / 2; i++)
++                      fsi_reg_write(fsi, DODT, buf[i]);
++      } else {
++              /* normal mode */
++              u16 *buf = (u16 *)_buf;
++
++              for (i = 0; i < samples; i++)
++                      fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
++      }
+ }
+ static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
+@@ -863,12 +951,44 @@ static void fsi_pio_start_stop(struct fs
+               fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+ }
++static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
++{
++      u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
++
++      /*
++       * we can use 16bit stream mode
++       * when "playback" and "16bit data"
++       * and platform allows "stream mode"
++       * see
++       *      fsi_pio_push16()
++       */
++      if (enable_stream)
++              io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
++                               BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
++      else
++              io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
++                               BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
++      return 0;
++}
++
++static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io)
++{
++      /*
++       * always 24bit bus, package back when "capture"
++       */
++      io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
++                       BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
++      return 0;
++}
++
+ static struct fsi_stream_handler fsi_pio_push_handler = {
++      .init           = fsi_pio_push_init,
+       .transfer       = fsi_pio_push,
+       .start_stop     = fsi_pio_start_stop,
+ };
+ static struct fsi_stream_handler fsi_pio_pop_handler = {
++      .init           = fsi_pio_pop_init,
+       .transfer       = fsi_pio_pop,
+       .start_stop     = fsi_pio_start_stop,
+ };
+@@ -910,6 +1030,13 @@ static int fsi_dma_init(struct fsi_priv
+       enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+                               DMA_TO_DEVICE : DMA_FROM_DEVICE;
++      /*
++       * 24bit data : 24bit bus / package in back
++       * 16bit data : 16bit bus / stream mode
++       */
++      io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
++                       BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
++
+       io->dma = dma_map_single(dai->dev, runtime->dma_area,
+                                snd_pcm_lib_buffer_bytes(io->substream), dir);
+       return 0;
+@@ -1046,25 +1173,9 @@ static int fsi_dma_transfer(struct fsi_p
+ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+                                int start)
+ {
+-      u32 bws;
+-      u32 dma;
++      u32 enable = start ? DMA_ON : 0;
+-      switch (io->sample_width * start) {
+-      case 2:
+-              bws = CR_BWS_16;
+-              dma = VDMD_STREAM | DMA_ON;
+-              break;
+-      case 4:
+-              bws = CR_BWS_24;
+-              dma = VDMD_BACK | DMA_ON;
+-              break;
+-      default:
+-              bws = 0;
+-              dma = 0;
+-      }
+-
+-      fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
+-      fsi_reg_write(fsi, OUT_DMAC, dma);
++      fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
+ }
+ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
+@@ -1167,7 +1278,6 @@ static int fsi_hw_startup(struct fsi_pri
+                         struct fsi_stream *io,
+                         struct device *dev)
+ {
+-      struct fsi_master *master = fsi_get_master(fsi);
+       u32 flags = fsi_get_info_flags(fsi);
+       u32 data = 0;
+@@ -1190,10 +1300,6 @@ static int fsi_hw_startup(struct fsi_pri
+       fsi_reg_write(fsi, CKG2, data);
+-      /* set format */
+-      fsi_reg_write(fsi, DO_FMT, fsi->fmt);
+-      fsi_reg_write(fsi, DI_FMT, fsi->fmt);
+-
+       /* spdif ? */
+       if (fsi_is_spdif(fsi)) {
+               fsi_spdif_clk_ctrl(fsi, 1);
+@@ -1201,15 +1307,18 @@ static int fsi_hw_startup(struct fsi_pri
+       }
+       /*
+-       * FIXME
+-       *
+-       * FSI driver assumed that data package is in-back.
+-       * FSI2 chip can select it.
++       * get bus settings
+        */
+-      if (fsi_version(master) >= 2) {
+-              fsi_reg_write(fsi, OUT_DMAC,    VDMD_BACK);
+-              fsi_reg_write(fsi, IN_DMAC,     VDMD_BACK);
++      data = 0;
++      switch (io->sample_width) {
++      case 2:
++              data = BUSOP_GET(16, io->bus_option);
++              break;
++      case 4:
++              data = BUSOP_GET(24, io->bus_option);
++              break;
+       }
++      fsi_format_bus_setup(fsi, io, data, dev);
+       /* irq clear */
+       fsi_irq_disable(fsi, io);
+@@ -1296,7 +1405,7 @@ static int fsi_set_fmt_spdif(struct fsi_
+       if (fsi_version(master) < 2)
+               return -EINVAL;
+-      fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
++      fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
+       fsi->chan_num = 2;
+       fsi->spdif = 1;
diff --git a/patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch b/patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch
new file mode 100644 (file)
index 0000000..380aeb5
--- /dev/null
@@ -0,0 +1,34 @@
+From 8dedb2aa24856018132764d9c3411c7600087b3e Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 24 May 2012 23:55:11 -0700
+Subject: ASoC: fsi: bugfix: enable master clock control on DMA stream
+
+DMA stream handler didn't care about master clock.
+This patch fixes it up.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit e42bb9bfbb43366cd1899c9564d043c41ebd8852)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1173,9 +1173,14 @@ static int fsi_dma_transfer(struct fsi_p
+ static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+                                int start)
+ {
++      struct fsi_master *master = fsi_get_master(fsi);
++      u32 clk  = fsi_is_port_a(fsi) ? CRA  : CRB;
+       u32 enable = start ? DMA_ON : 0;
+       fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
++
++      if (fsi_is_clk_master(fsi))
++              fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+ }
+ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
diff --git a/patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch b/patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch
new file mode 100644 (file)
index 0000000..dcbbc64
--- /dev/null
@@ -0,0 +1,66 @@
+From ce1ff80d007ef6f5c64c65fd0d44b587657ae0c6 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 28 May 2012 23:27:49 -0700
+Subject: ASoC: fsi: bugfix: correct dma area
+
+FSI driver is using dma_sync_single_xxx(),
+but the dma area was not correct.
+This patch fix it up.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 4a1b09b79b07cf70c72a091e8fe0660f68541f30)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |   18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1053,6 +1053,13 @@ static int fsi_dma_quit(struct fsi_priv
+       return 0;
+ }
++static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
++{
++      struct snd_pcm_runtime *runtime = io->substream->runtime;
++
++      return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
++}
++
+ static void fsi_dma_complete(void *data)
+ {
+       struct fsi_stream *io = (struct fsi_stream *)data;
+@@ -1062,7 +1069,7 @@ static void fsi_dma_complete(void *data)
+       enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+               DMA_TO_DEVICE : DMA_FROM_DEVICE;
+-      dma_sync_single_for_cpu(dai->dev, io->dma,
++      dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io),
+                       samples_to_bytes(runtime, io->period_samples), dir);
+       io->buff_sample_pos += io->period_samples;
+@@ -1079,13 +1086,6 @@ static void fsi_dma_complete(void *data)
+       snd_pcm_period_elapsed(io->substream);
+ }
+-static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
+-{
+-      struct snd_pcm_runtime *runtime = io->substream->runtime;
+-
+-      return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
+-}
+-
+ static void fsi_dma_do_work(struct work_struct *work)
+ {
+       struct fsi_stream *io = container_of(work, struct fsi_stream, work);
+@@ -1111,7 +1111,7 @@ static void fsi_dma_do_work(struct work_
+       len     = samples_to_bytes(runtime, io->period_samples);
+       buf     = fsi_dma_get_area(io);
+-      dma_sync_single_for_device(dai->dev, io->dma, len, dir);
++      dma_sync_single_for_device(dai->dev, buf, len, dir);
+       sg_init_table(&sg, 1);
+       sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
diff --git a/patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch b/patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch
new file mode 100644 (file)
index 0000000..a392175
--- /dev/null
@@ -0,0 +1,28 @@
+From d94ab970e6055b3e6f7cab54a405431e47445ae4 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 28 May 2012 23:28:22 -0700
+Subject: ASoC: fsi: bugfix: ensure dma is terminated
+
+FSI DMAEngine has to be stopped certainly at the start/stop time.
+Without this patch, it will include noise on playback.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit fbe42f66c66c279b4ed9b8f515058a09bc731c49)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1179,6 +1179,8 @@ static void fsi_dma_push_start_stop(stru
+       fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
++      dmaengine_terminate_all(io->chan);
++
+       if (fsi_is_clk_master(fsi))
+               fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+ }
diff --git a/patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch b/patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch
new file mode 100644 (file)
index 0000000..8c33120
--- /dev/null
@@ -0,0 +1,74 @@
+From 341b5a7a28c7b1404b9875366b2b2c1dabd06ee8 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 28 May 2012 23:29:36 -0700
+Subject: ASoC: fsi: use dmaengine helper functions
+
+This patch used dmaengine helper functions instead of using hand setting.
+And reduced local variables
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit 5514efdfe0384576ef38c66b1672b6826696fbf3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |   19 ++++---------------
+ 1 file changed, 4 insertions(+), 15 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1090,13 +1090,10 @@ static void fsi_dma_do_work(struct work_
+ {
+       struct fsi_stream *io = container_of(work, struct fsi_stream, work);
+       struct fsi_priv *fsi = fsi_stream_to_priv(io);
+-      struct dma_chan *chan;
+       struct snd_soc_dai *dai;
+       struct dma_async_tx_descriptor *desc;
+-      struct scatterlist sg;
+       struct snd_pcm_runtime *runtime;
+       enum dma_data_direction dir;
+-      dma_cookie_t cookie;
+       int is_play = fsi_stream_is_play(fsi, io);
+       int len;
+       dma_addr_t buf;
+@@ -1105,7 +1102,6 @@ static void fsi_dma_do_work(struct work_
+               return;
+       dai     = fsi_get_dai(io->substream);
+-      chan    = io->chan;
+       runtime = io->substream->runtime;
+       dir     = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+       len     = samples_to_bytes(runtime, io->period_samples);
+@@ -1113,14 +1109,8 @@ static void fsi_dma_do_work(struct work_
+       dma_sync_single_for_device(dai->dev, buf, len, dir);
+-      sg_init_table(&sg, 1);
+-      sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
+-                  len , offset_in_page(buf));
+-      sg_dma_address(&sg) = buf;
+-      sg_dma_len(&sg) = len;
+-
+-      desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir,
+-                                     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++      desc = dmaengine_prep_slave_single(io->chan, buf, len, dir,
++                                         DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!desc) {
+               dev_err(dai->dev, "dmaengine_prep_slave_sg() fail\n");
+               return;
+@@ -1129,13 +1119,12 @@ static void fsi_dma_do_work(struct work_
+       desc->callback          = fsi_dma_complete;
+       desc->callback_param    = io;
+-      cookie = desc->tx_submit(desc);
+-      if (cookie < 0) {
++      if (dmaengine_submit(desc) < 0) {
+               dev_err(dai->dev, "tx_submit() fail\n");
+               return;
+       }
+-      dma_async_issue_pending(chan);
++      dma_async_issue_pending(io->chan);
+       /*
+        * FIXME
diff --git a/patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch b/patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch
new file mode 100644 (file)
index 0000000..4d8ccec
--- /dev/null
@@ -0,0 +1,97 @@
+From 2c50008416a53374914d047b290c1f28842ce4b3 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 24 May 2012 23:56:19 -0700
+Subject: ASoC: fsi: use PIO handler if DMA handler was invalid
+
+PIO handler is not good performance, but works on all platform.
+So, switch to PIO handler if DMA handler was invalid case.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+(cherry picked from commit b1226dc59d55ecde7fc9a338d8cb2a313821fac0)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |   29 ++++++++++++++++++++---------
+ 1 file changed, 20 insertions(+), 9 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -248,7 +248,7 @@ struct fsi_priv {
+ struct fsi_stream_handler {
+       int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
+       int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
+-      int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
++      int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev);
+       int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
+       int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
+       void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
+@@ -572,16 +572,16 @@ static int fsi_stream_transfer(struct fs
+ #define fsi_stream_stop(fsi, io)\
+       fsi_stream_handler_call(io, start_stop, fsi, io, 0)
+-static int fsi_stream_probe(struct fsi_priv *fsi)
++static int fsi_stream_probe(struct fsi_priv *fsi, struct device *dev)
+ {
+       struct fsi_stream *io;
+       int ret1, ret2;
+       io = &fsi->playback;
+-      ret1 = fsi_stream_handler_call(io, probe, fsi, io);
++      ret1 = fsi_stream_handler_call(io, probe, fsi, io, dev);
+       io = &fsi->capture;
+-      ret2 = fsi_stream_handler_call(io, probe, fsi, io);
++      ret2 = fsi_stream_handler_call(io, probe, fsi, io, dev);
+       if (ret1 < 0)
+               return ret1;
+@@ -1174,7 +1174,7 @@ static void fsi_dma_push_start_stop(stru
+               fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+ }
+-static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
++static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
+ {
+       dma_cap_mask_t mask;
+@@ -1182,8 +1182,19 @@ static int fsi_dma_probe(struct fsi_priv
+       dma_cap_set(DMA_SLAVE, mask);
+       io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
+-      if (!io->chan)
+-              return -EIO;
++      if (!io->chan) {
++
++              /* switch to PIO handler */
++              if (fsi_stream_is_play(fsi, io))
++                      fsi->playback.handler   = &fsi_pio_push_handler;
++              else
++                      fsi->capture.handler    = &fsi_pio_pop_handler;
++
++              dev_info(dev, "switch handler (dma => pio)\n");
++
++              /* probe again */
++              return fsi_stream_probe(fsi, dev);
++      }
+       INIT_WORK(&io->work, fsi_dma_do_work);
+@@ -1673,7 +1684,7 @@ static int fsi_probe(struct platform_dev
+       master->fsia.master     = master;
+       master->fsia.info       = &info->port_a;
+       fsi_handler_init(&master->fsia);
+-      ret = fsi_stream_probe(&master->fsia);
++      ret = fsi_stream_probe(&master->fsia, &pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "FSIA stream probe failed\n");
+               goto exit_iounmap;
+@@ -1684,7 +1695,7 @@ static int fsi_probe(struct platform_dev
+       master->fsib.master     = master;
+       master->fsib.info       = &info->port_b;
+       fsi_handler_init(&master->fsib);
+-      ret = fsi_stream_probe(&master->fsib);
++      ret = fsi_stream_probe(&master->fsib, &pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "FSIB stream probe failed\n");
+               goto exit_fsia;
diff --git a/patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch b/patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch
new file mode 100644 (file)
index 0000000..23f861e
--- /dev/null
@@ -0,0 +1,35 @@
+From 223018081111b56755835850e5dbc7a122f5f1b5 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:20 +0200
+Subject: ASoC: fsi: prepare for conversion to the shdma base library
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Liam Girdwood <lrg@ti.com>
+Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit b8373147ed3ca01a968d81f22688f2836a9aeb6b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
+index 53486ff..0540408 100644
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1631,8 +1631,8 @@ static void fsi_handler_init(struct fsi_priv *fsi)
+       fsi->capture.priv       = fsi;
+       if (fsi->info->tx_id) {
+-              fsi->playback.slave.slave_id    = fsi->info->tx_id;
+-              fsi->playback.handler           = &fsi_dma_push_handler;
++              fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id;
++              fsi->playback.handler = &fsi_dma_push_handler;
+       }
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch b/patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch
new file mode 100644 (file)
index 0000000..9e9dfef
--- /dev/null
@@ -0,0 +1,86 @@
+From 575ef93e0d64ff352f0bafc5038468b13796104b Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 7 May 2012 21:06:54 -0700
+Subject: fbdev: sh_mobile_hdmi: add hdmi_bit_set() function
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+(cherry picked from commit 3f521abd6cf1320d65a49cf9fc327b82168b5ba0)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_hdmi.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
+index eafb19d..e201d6f 100644
+--- a/drivers/video/sh_mobile_hdmi.c
++++ b/drivers/video/sh_mobile_hdmi.c
+@@ -236,6 +236,16 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
+       return ioread8(hdmi->base + reg);
+ }
++static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
++{
++      u8 val = hdmi_read(hdmi, reg);
++
++      val &= ~mask;
++      val |= (data & mask);
++
++      hdmi_write(hdmi, val, reg);
++}
++
+ /*
+  *    HDMI sound
+  */
+@@ -693,11 +703,11 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
+       msleep(10);
+       /* PS mode b->d, reset PLLA and PLLB */
+-      hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL);
++      hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL);
+       udelay(10);
+-      hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
++      hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL);
+ }
+ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
+@@ -917,13 +927,13 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
+       u8 status1, status2, mask1, mask2;
+       /* mode_b and PLLA and PLLB reset */
+-      hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL);
++      hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL);
+       /* How long shall reset be held? */
+       udelay(10);
+       /* mode_b and PLLA and PLLB reset release */
+-      hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL);
++      hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL);
+       status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
+       status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
+@@ -1001,7 +1011,7 @@ static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity)
+        */
+       if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
+               /* PS mode d->e. All functions are active */
+-              hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
++              hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL);
+               dev_dbg(hdmi->dev, "HDMI running\n");
+       }
+@@ -1016,7 +1026,7 @@ static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
+       dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi);
+       /* PS mode e->a */
+-      hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
++      hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL);
+ }
+ static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch b/patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch
new file mode 100644 (file)
index 0000000..e03a115
--- /dev/null
@@ -0,0 +1,64 @@
+From 1f09b960ec16950e3791ba297de136bedc56be51 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 7 May 2012 21:07:20 -0700
+Subject: fbdev: sh_mobile_hdmi: add interrupt output option
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+(cherry picked from commit e0defc86423d1b5652826c9317c36dfb6af1cd48)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_hdmi.c | 7 +++++++
+ include/video/sh_mobile_hdmi.h | 8 +++++++-
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
+index e201d6f..0bc39bc 100644
+--- a/drivers/video/sh_mobile_hdmi.c
++++ b/drivers/video/sh_mobile_hdmi.c
+@@ -1186,6 +1186,13 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
++      /* init interrupt polarity */
++      if (pdata->flags & HDMI_OUTPUT_PUSH_PULL)
++              hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL);
++
++      if (pdata->flags & HDMI_OUTPUT_POLARITY_HI)
++              hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL);
++
+       /* Product and revision IDs are 0 in sh-mobile version */
+       dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
+                hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
+diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
+index 728f9de..2699635 100644
+--- a/include/video/sh_mobile_hdmi.h
++++ b/include/video/sh_mobile_hdmi.h
+@@ -18,9 +18,10 @@ struct clk;
+ /*
+  * flags format
+  *
+- * 0x0000000A
++ * 0x000000BA
+  *
+  * A: Audio source select
++ * B: Int output option
+  */
+ /* Audio source select */
+@@ -30,6 +31,11 @@ struct clk;
+ #define HDMI_SND_SRC_DSD      (2 << 0)
+ #define HDMI_SND_SRC_HBR      (3 << 0)
++/* Int output option */
++#define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */
++#define HDMI_OUTPUT_POLARITY_HI       (1 << 5) /* System control : output polarity */
++
++
+ struct sh_mobile_hdmi_info {
+       unsigned int                     flags;
+       long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch b/patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch
new file mode 100644 (file)
index 0000000..d5517c4
--- /dev/null
@@ -0,0 +1,115 @@
+From 6fb22732c461a0efc337cc6cd03fda18e0b2d1cf Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 7 May 2012 21:07:49 -0700
+Subject: fbdev: sh_mobile_hdmi: 32bit register access support
+
+Latest SuperH HDMI allows 32bit access only.
+But the data is 8bit. So, we can keep compatibility by switching 8/32 bit access.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+(cherry picked from commit db6668d83a265a15ffd79dbc8432598808b34bb4)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_hdmi.c | 38 ++++++++++++++++++++++++++++++++++++--
+ include/video/sh_mobile_hdmi.h |  5 ++++-
+ 2 files changed, 40 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
+index 0bc39bc..4d48a80 100644
+--- a/drivers/video/sh_mobile_hdmi.c
++++ b/drivers/video/sh_mobile_hdmi.c
+@@ -222,20 +222,45 @@ struct sh_hdmi {
+       struct delayed_work edid_work;
+       struct fb_videomode mode;
+       struct fb_monspecs monspec;
++
++      /* register access functions */
++      void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg);
++      u8 (*read)(struct sh_hdmi *hdmi, u8 reg);
+ };
+ #define entity_to_sh_hdmi(e)  container_of(e, struct sh_hdmi, entity)
+-static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
++static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg)
+ {
+       iowrite8(data, hdmi->base + reg);
+ }
+-static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
++static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg)
+ {
+       return ioread8(hdmi->base + reg);
+ }
++static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg)
++{
++      iowrite32((u32)data, hdmi->base + (reg * 4));
++      udelay(100);
++}
++
++static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg)
++{
++      return (u8)ioread32(hdmi->base + (reg * 4));
++}
++
++static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
++{
++      hdmi->write(hdmi, data, reg);
++}
++
++static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
++{
++      return hdmi->read(hdmi, reg);
++}
++
+ static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
+ {
+       u8 val = hdmi_read(hdmi, reg);
+@@ -1148,6 +1173,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
+               goto egetclk;
+       }
++      /* select register access functions */
++      if (pdata->flags & HDMI_32BIT_REG) {
++              hdmi->write     = __hdmi_write32;
++              hdmi->read      = __hdmi_read32;
++      } else {
++              hdmi->write     = __hdmi_write8;
++              hdmi->read      = __hdmi_read8;
++      }
++
+       /* An arbitrary relaxed pixclock just to get things started: from standard 480p */
+       rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
+       if (rate > 0)
+diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
+index 2699635..ce8a540 100644
+--- a/include/video/sh_mobile_hdmi.h
++++ b/include/video/sh_mobile_hdmi.h
+@@ -18,10 +18,11 @@ struct clk;
+ /*
+  * flags format
+  *
+- * 0x000000BA
++ * 0x00000CBA
+  *
+  * A: Audio source select
+  * B: Int output option
++ * C: Chip specific option
+  */
+ /* Audio source select */
+@@ -35,6 +36,8 @@ struct clk;
+ #define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */
+ #define HDMI_OUTPUT_POLARITY_HI       (1 << 5) /* System control : output polarity */
++/* Chip specific option */
++#define HDMI_32BIT_REG                (1 << 8)
+ struct sh_mobile_hdmi_info {
+       unsigned int                     flags;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch b/patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch
new file mode 100644 (file)
index 0000000..93db80c
--- /dev/null
@@ -0,0 +1,264 @@
+From ccd4120f4b46b4f6c043108aa6f5bbb8f63f959e Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 7 May 2012 21:08:17 -0700
+Subject: fbdev: sh_mobile_hdmi: add HDMI Control Register support
+
+Latest SuperH HDMI uses not only HDMI Core Register (HTOP0)
+but also HDMI Control Register (HTOP1).
+This patch adds HDMI Control Register support.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+(cherry picked from commit c932b2731116f99a660817e8fa718c9da0798a9c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_hdmi.c | 152 ++++++++++++++++++++++++++++++++++++++++-
+ include/video/sh_mobile_hdmi.h |   1 +
+ 2 files changed, 152 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
+index 4d48a80..930e550 100644
+--- a/drivers/video/sh_mobile_hdmi.c
++++ b/drivers/video/sh_mobile_hdmi.c
+@@ -31,6 +31,7 @@
+ #include "sh_mobile_lcdcfb.h"
++/* HDMI Core Control Register (HTOP0) */
+ #define HDMI_SYSTEM_CTRL                      0x00 /* System control */
+ #define HDMI_L_R_DATA_SWAP_CTRL_RPKT          0x01 /* L/R data swap control,
+                                                       bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
+@@ -201,6 +202,68 @@
+ #define HDMI_REVISION_ID                      0xF1 /* Revision ID */
+ #define HDMI_TEST_MODE                                0xFE /* Test mode */
++/* HDMI Control Register (HTOP1) */
++#define HDMI_HTOP1_TEST_MODE                  0x0000 /* Test mode */
++#define HDMI_HTOP1_VIDEO_INPUT                        0x0008 /* VideoInput */
++#define HDMI_HTOP1_CORE_RSTN                  0x000C /* CoreResetn */
++#define HDMI_HTOP1_PLLBW                      0x0018 /* PLLBW */
++#define HDMI_HTOP1_CLK_TO_PHY                 0x001C /* Clk to Phy */
++#define HDMI_HTOP1_VIDEO_INPUT2                       0x0020 /* VideoInput2 */
++#define HDMI_HTOP1_TISEMP0_1                  0x0024 /* tisemp0-1 */
++#define HDMI_HTOP1_TISEMP2_C                  0x0028 /* tisemp2-c */
++#define HDMI_HTOP1_TISIDRV                    0x002C /* tisidrv */
++#define HDMI_HTOP1_TISEN                      0x0034 /* tisen */
++#define HDMI_HTOP1_TISDREN                    0x0038 /* tisdren  */
++#define HDMI_HTOP1_CISRANGE                   0x003C /* cisrange  */
++#define HDMI_HTOP1_ENABLE_SELECTOR            0x0040 /* Enable Selector */
++#define HDMI_HTOP1_MACRO_RESET                        0x0044 /* Macro reset */
++#define HDMI_HTOP1_PLL_CALIBRATION            0x0048 /* PLL calibration */
++#define HDMI_HTOP1_RE_CALIBRATION             0x004C /* Re-calibration */
++#define HDMI_HTOP1_CURRENT                    0x0050 /* Current */
++#define HDMI_HTOP1_PLL_LOCK_DETECT            0x0054 /* PLL lock detect */
++#define HDMI_HTOP1_PHY_TEST_MODE              0x0058 /* PHY Test Mode */
++#define HDMI_HTOP1_CLK_SET                    0x0080 /* Clock Set */
++#define HDMI_HTOP1_DDC_FAIL_SAFE              0x0084 /* DDC fail safe */
++#define HDMI_HTOP1_PRBS                               0x0088 /* PRBS */
++#define HDMI_HTOP1_EDID_AINC_CONTROL          0x008C /* EDID ainc Control */
++#define HDMI_HTOP1_HTOP_DCL_MODE              0x00FC /* Deep Coloer Mode */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0         0x0100 /* Deep Color:FRC COEF0 */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1         0x0104 /* Deep Color:FRC COEF1 */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2         0x0108 /* Deep Color:FRC COEF2 */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3         0x010C /* Deep Color:FRC COEF3 */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C               0x0110 /* Deep Color:FRC COEF0C */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C               0x0114 /* Deep Color:FRC COEF1C */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C               0x0118 /* Deep Color:FRC COEF2C */
++#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C               0x011C /* Deep Color:FRC COEF3C */
++#define HDMI_HTOP1_HTOP_DCL_FRC_MODE          0x0120 /* Deep Color:FRC Mode */
++#define HDMI_HTOP1_HTOP_DCL_RECT_START1               0x0124 /* Deep Color:Rect Start1 */
++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1                0x0128 /* Deep Color:Rect Size1 */
++#define HDMI_HTOP1_HTOP_DCL_RECT_START2               0x012C /* Deep Color:Rect Start2 */
++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2                0x0130 /* Deep Color:Rect Size2 */
++#define HDMI_HTOP1_HTOP_DCL_RECT_START3               0x0134 /* Deep Color:Rect Start3 */
++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3                0x0138 /* Deep Color:Rect Size3 */
++#define HDMI_HTOP1_HTOP_DCL_RECT_START4               0x013C /* Deep Color:Rect Start4 */
++#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4                0x0140 /* Deep Color:Rect Size4 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1     0x0144 /* Deep Color:Fil Para Y1_1 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2     0x0148 /* Deep Color:Fil Para Y1_2 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1    0x014C /* Deep Color:Fil Para CB1_1 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2    0x0150 /* Deep Color:Fil Para CB1_2 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1    0x0154 /* Deep Color:Fil Para CR1_1 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2    0x0158 /* Deep Color:Fil Para CR1_2 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1     0x015C /* Deep Color:Fil Para Y2_1 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2     0x0160 /* Deep Color:Fil Para Y2_2 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1    0x0164 /* Deep Color:Fil Para CB2_1 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2    0x0168 /* Deep Color:Fil Para CB2_2 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1    0x016C /* Deep Color:Fil Para CR2_1 */
++#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2    0x0170 /* Deep Color:Fil Para CR2_2 */
++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1               0x0174 /* Deep Color:Cor Para Y1 */
++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1      0x0178 /* Deep Color:Cor Para CB1 */
++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1      0x017C /* Deep Color:Cor Para CR1 */
++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2               0x0180 /* Deep Color:Cor Para Y2 */
++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2      0x0184 /* Deep Color:Cor Para CB2 */
++#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2      0x0188 /* Deep Color:Cor Para CR2 */
++#define HDMI_HTOP1_EDID_DATA_READ             0x0200 /* EDID Data Read 128Byte:0x03FC */
++
+ enum hotplug_state {
+       HDMI_HOTPLUG_DISCONNECTED,
+       HDMI_HOTPLUG_CONNECTED,
+@@ -211,6 +274,7 @@ struct sh_hdmi {
+       struct sh_mobile_lcdc_entity entity;
+       void __iomem *base;
++      void __iomem *htop1;
+       enum hotplug_state hp_state;    /* hot-plug status */
+       u8 preprogrammed_vic;           /* use a pre-programmed VIC or
+                                          the external mode */
+@@ -271,6 +335,17 @@ static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
+       hdmi_write(hdmi, val, reg);
+ }
++static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg)
++{
++      iowrite32(data, hdmi->htop1 + reg);
++      udelay(100);
++}
++
++static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg)
++{
++      return ioread32(hdmi->htop1 + reg);
++}
++
+ /*
+  *    HDMI sound
+  */
+@@ -781,7 +856,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
+       /* Read EDID */
+       dev_dbg(hdmi->dev, "Read back EDID code:");
+       for (i = 0; i < 128; i++) {
+-              edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
++              edid[i] = (hdmi->htop1) ?
++                      (u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) :
++                      hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
+ #ifdef DEBUG
+               if ((i % 16) == 0) {
+                       printk(KERN_CONT "\n");
+@@ -1145,10 +1222,58 @@ out:
+       dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
+ }
++static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi)
++{
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE);
++      hdmi_htop1_write(hdmi, 0x0000000b, 0x0010);
++      hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE);
++      hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1);
++      hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2);
++      hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1);
++      hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2);
++      hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1);
++      hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2);
++      hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1);
++      hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2);
++      hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1);
++      hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2);
++      hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1);
++      hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2);
++      hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE);
++      hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW);
++      hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
++      hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
++      hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
++      hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
++      hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE);
++      msleep(100);
++      hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR);
++      msleep(100);
++      hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
++      hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
++      hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
++      hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY);
++      hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2);
++      hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET);
++}
++
+ static int __init sh_hdmi_probe(struct platform_device *pdev)
+ {
+       struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      struct resource *htop1_res;
+       int irq = platform_get_irq(pdev, 0), ret;
+       struct sh_hdmi *hdmi;
+       long rate;
+@@ -1156,6 +1281,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
+       if (!res || !pdata || irq < 0)
+               return -ENODEV;
++      htop1_res = NULL;
++      if (pdata->flags & HDMI_HAS_HTOP1) {
++              htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++              if (!htop1_res) {
++                      dev_err(&pdev->dev, "htop1 needs register base\n");
++                      return -EINVAL;
++              }
++      }
++
+       hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
+       if (!hdmi) {
+               dev_err(&pdev->dev, "Cannot allocate device data\n");
+@@ -1227,6 +1361,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
+       if (pdata->flags & HDMI_OUTPUT_POLARITY_HI)
+               hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL);
++      /* enable htop1 register if needed */
++      if (htop1_res) {
++              hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res));
++              if (!hdmi->htop1) {
++                      dev_err(&pdev->dev, "control register region already claimed\n");
++                      ret = -ENOMEM;
++                      goto emap_htop1;
++              }
++              sh_hdmi_htop1_init(hdmi);
++      }
++
+       /* Product and revision IDs are 0 in sh-mobile version */
+       dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
+                hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
+@@ -1250,6 +1395,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
+ ecodec:
+       free_irq(irq, hdmi);
+ ereqirq:
++      if (hdmi->htop1)
++              iounmap(hdmi->htop1);
++emap_htop1:
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       iounmap(hdmi->base);
+@@ -1281,6 +1429,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
+       pm_runtime_disable(&pdev->dev);
+       clk_disable(hdmi->hdmi_clk);
+       clk_put(hdmi->hdmi_clk);
++      if (hdmi->htop1)
++              iounmap(hdmi->htop1);
+       iounmap(hdmi->base);
+       release_mem_region(res->start, resource_size(res));
+       kfree(hdmi);
+diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
+index ce8a540..63d20ef 100644
+--- a/include/video/sh_mobile_hdmi.h
++++ b/include/video/sh_mobile_hdmi.h
+@@ -38,6 +38,7 @@ struct clk;
+ /* Chip specific option */
+ #define HDMI_32BIT_REG                (1 << 8)
++#define HDMI_HAS_HTOP1                (1 << 9)
+ struct sh_mobile_hdmi_info {
+       unsigned int                     flags;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch b/patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch
new file mode 100644 (file)
index 0000000..ce1fee5
--- /dev/null
@@ -0,0 +1,53 @@
+From 46a0acbafe13b92d4ea16ca47414ac22579f9827 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 14 Jun 2012 09:53:33 +0200
+Subject: fbdev: sh_mipi_dsi: fix a section mismatch
+
+sh_mipi_setup() is called from a .text function, therefore it cannot be
+__init. Additionally, sh_mipi_remove() can be moved to the .devexit.text
+section.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit e6765ffa6897f7fb84469bab2e1be885c57ea519)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mipi_dsi.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
+index 4c6b844..3951fda 100644
+--- a/drivers/video/sh_mipi_dsi.c
++++ b/drivers/video/sh_mipi_dsi.c
+@@ -127,8 +127,7 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
+       sh_mipi_dsi_enable(mipi, false);
+ }
+-static int __init sh_mipi_setup(struct sh_mipi *mipi,
+-                              struct sh_mipi_dsi_info *pdata)
++static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
+ {
+       void __iomem *base = mipi->base;
+       struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
+@@ -551,7 +550,7 @@ efindslot:
+       return ret;
+ }
+-static int __exit sh_mipi_remove(struct platform_device *pdev)
++static int __devexit sh_mipi_remove(struct platform_device *pdev)
+ {
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+@@ -592,7 +591,7 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
+ }
+ static struct platform_driver sh_mipi_driver = {
+-      .remove         = __exit_p(sh_mipi_remove),
++      .remove         = __devexit_p(sh_mipi_remove),
+       .shutdown       = sh_mipi_shutdown,
+       .driver = {
+               .name   = "sh-mipi-dsi",
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch b/patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch
new file mode 100644 (file)
index 0000000..3533502
--- /dev/null
@@ -0,0 +1,31 @@
+From 285591af450384157206e46d4b676f8a5d095c4a Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 22 Nov 2011 00:56:58 +0100
+Subject: fbdev: sh_mobile_lcdc: Constify sh_mobile_lcdc_fix structure
+
+The structure is only read, make it const.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 3281e54c80195b90ed12a5b6cddef4ab42e656e1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index e672698..5461abe 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -1003,7 +1003,7 @@ static int sh_mobile_lcdc_setcolreg(u_int regno,
+       return 0;
+ }
+-static struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
++static const struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
+       .id =           "SH Mobile LCDC",
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_TRUECOLOR,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch b/patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch
new file mode 100644 (file)
index 0000000..015ce4e
--- /dev/null
@@ -0,0 +1,168 @@
+From 2a41d02255f596307db8e41902cfec9877bfe493 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 22 Nov 2011 00:56:58 +0100
+Subject: fbdev: sh_mobile_lcdc: Rename fb operation handlers with a common
+ prefix
+
+Make all fb operation handlers start with sh_mobile_lcdc_ in preparation
+for the multi-plane support.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit d7ad33421863308fe7ddf865737d4d83b64e5b81)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 48 +++++++++++++++++++++-------------------
+ 1 file changed, 25 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 5461abe..799f871 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -384,8 +384,8 @@ sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
+       return true;
+ }
+-static int sh_mobile_check_var(struct fb_var_screeninfo *var,
+-                             struct fb_info *info);
++static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
++                                  struct fb_info *info);
+ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
+                                        enum sh_mobile_lcdc_entity_event event,
+@@ -439,7 +439,7 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
+               fb_videomode_to_var(&var, mode);
+               var.bits_per_pixel = info->var.bits_per_pixel;
+               var.grayscale = info->var.grayscale;
+-              ret = sh_mobile_check_var(&var, info);
++              ret = sh_mobile_lcdc_check_var(&var, info);
+               break;
+       }
+@@ -585,7 +585,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
+       return IRQ_HANDLED;
+ }
+-static int sh_mobile_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
++static int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
+ {
+       unsigned long ldintr;
+       int ret;
+@@ -686,7 +686,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
+ }
+ /*
+- * __sh_mobile_lcdc_start - Configure and tart the LCDC
++ * __sh_mobile_lcdc_start - Configure and start the LCDC
+  * @priv: LCDC device
+  *
+  * Configure all enabled channels and start the LCDC device. All external
+@@ -1035,8 +1035,8 @@ static void sh_mobile_lcdc_imageblit(struct fb_info *info,
+       sh_mobile_lcdc_deferred_io_touch(info);
+ }
+-static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+-                                   struct fb_info *info)
++static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
++                            struct fb_info *info)
+ {
+       struct sh_mobile_lcdc_chan *ch = info->par;
+       struct sh_mobile_lcdc_priv *priv = ch->lcdc;
+@@ -1099,14 +1099,15 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
+       return 0;
+ }
+-static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
+-                     unsigned long arg)
++static int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd,
++                              unsigned long arg)
+ {
++      struct sh_mobile_lcdc_chan *ch = info->par;
+       int retval;
+       switch (cmd) {
+       case FBIO_WAITFORVSYNC:
+-              retval = sh_mobile_wait_for_vsync(info->par);
++              retval = sh_mobile_lcdc_wait_for_vsync(ch);
+               break;
+       default:
+@@ -1158,7 +1159,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
+  * Locking: both .fb_release() and .fb_open() are called with info->lock held if
+  * user == 1, or with console sem held, if user == 0.
+  */
+-static int sh_mobile_release(struct fb_info *info, int user)
++static int sh_mobile_lcdc_release(struct fb_info *info, int user)
+ {
+       struct sh_mobile_lcdc_chan *ch = info->par;
+@@ -1179,7 +1180,7 @@ static int sh_mobile_release(struct fb_info *info, int user)
+       return 0;
+ }
+-static int sh_mobile_open(struct fb_info *info, int user)
++static int sh_mobile_lcdc_open(struct fb_info *info, int user)
+ {
+       struct sh_mobile_lcdc_chan *ch = info->par;
+@@ -1192,7 +1193,8 @@ static int sh_mobile_open(struct fb_info *info, int user)
+       return 0;
+ }
+-static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
++static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
++                                  struct fb_info *info)
+ {
+       struct sh_mobile_lcdc_chan *ch = info->par;
+       struct sh_mobile_lcdc_priv *p = ch->lcdc;
+@@ -1313,7 +1315,7 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
+       return 0;
+ }
+-static int sh_mobile_set_par(struct fb_info *info)
++static int sh_mobile_lcdc_set_par(struct fb_info *info)
+ {
+       struct sh_mobile_lcdc_chan *ch = info->par;
+       int ret;
+@@ -1383,8 +1385,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
+                * mode will reenable the clocks and update the screen in time,
+                * so it does not need this. */
+               if (!info->fbdefio) {
+-                      sh_mobile_wait_for_vsync(ch);
+-                      sh_mobile_wait_for_vsync(ch);
++                      sh_mobile_lcdc_wait_for_vsync(ch);
++                      sh_mobile_lcdc_wait_for_vsync(ch);
+               }
+               sh_mobile_lcdc_clk_off(p);
+       }
+@@ -1402,12 +1404,12 @@ static struct fb_ops sh_mobile_lcdc_ops = {
+       .fb_copyarea    = sh_mobile_lcdc_copyarea,
+       .fb_imageblit   = sh_mobile_lcdc_imageblit,
+       .fb_blank       = sh_mobile_lcdc_blank,
+-      .fb_pan_display = sh_mobile_fb_pan_display,
+-      .fb_ioctl       = sh_mobile_ioctl,
+-      .fb_open        = sh_mobile_open,
+-      .fb_release     = sh_mobile_release,
+-      .fb_check_var   = sh_mobile_check_var,
+-      .fb_set_par     = sh_mobile_set_par,
++      .fb_pan_display = sh_mobile_lcdc_pan,
++      .fb_ioctl       = sh_mobile_lcdc_ioctl,
++      .fb_open        = sh_mobile_lcdc_open,
++      .fb_release     = sh_mobile_lcdc_release,
++      .fb_check_var   = sh_mobile_lcdc_check_var,
++      .fb_set_par     = sh_mobile_lcdc_set_par,
+ };
+ static void
+@@ -1537,7 +1539,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
+       else
+               var->grayscale = ch->format->fourcc;
+-      ret = sh_mobile_check_var(var, info);
++      ret = sh_mobile_lcdc_check_var(var, info);
+       if (ret)
+               return ret;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch b/patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch
new file mode 100644 (file)
index 0000000..85bd66b
--- /dev/null
@@ -0,0 +1,1137 @@
+From ae0b639299213d1d1361aa368c57ee8a3d94214b Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Mon, 12 Dec 2011 18:43:16 +0100
+Subject: fbdev: sh_mobile_lcdc: Implement overlays support
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit c5deac3c9b2284a64326e8799dfe7416bc619c02)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ .../sysfs-devices-platform-sh_mobile_lcdc_fb       |  44 +
+ drivers/video/sh_mobile_lcdcfb.c                   | 932 +++++++++++++++++++--
+ include/video/sh_mobile_lcdc.h                     |   7 +
+ 3 files changed, 911 insertions(+), 72 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb
+
+diff --git a/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb
+new file mode 100644
+index 0000000..2107082
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-devices-platform-sh_mobile_lcdc_fb
+@@ -0,0 +1,44 @@
++What:         /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_alpha
++Date:         May 2012
++Contact:      Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++Description:
++              This file is only available on fb[0-9] devices corresponding
++              to overlay planes.
++
++              Stores the alpha blending value for the overlay. Values range
++              from 0 (transparent) to 255 (opaque). The value is ignored if
++              the mode is not set to Alpha Blending.
++
++What:         /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_mode
++Date:         May 2012
++Contact:      Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++Description:
++              This file is only available on fb[0-9] devices corresponding
++              to overlay planes.
++
++              Selects the composition mode for the overlay. Possible values
++              are
++
++              0 - Alpha Blending
++              1 - ROP3
++
++What:         /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_position
++Date:         May 2012
++Contact:      Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++Description:
++              This file is only available on fb[0-9] devices corresponding
++              to overlay planes.
++
++              Stores the x,y overlay position on the display in pixels. The
++              position format is `[0-9]+,[0-9]+'.
++
++What:         /sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_rop3
++Date:         May 2012
++Contact:      Laurent Pinchart <laurent.pinchart@ideasonboard.com>
++Description:
++              This file is only available on fb[0-9] devices corresponding
++              to overlay planes.
++
++              Stores the raster operation (ROP3) for the overlay. Values
++              range from 0 to 255. The value is ignored if the mode is not
++              set to ROP3.
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 799f871..98e81b3 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -12,6 +12,7 @@
+ #include <linux/backlight.h>
+ #include <linux/clk.h>
+ #include <linux/console.h>
++#include <linux/ctype.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/delay.h>
+ #include <linux/gpio.h>
+@@ -32,12 +33,176 @@
+ #include "sh_mobile_lcdcfb.h"
++/* ----------------------------------------------------------------------------
++ * Overlay register definitions
++ */
++
++#define LDBCR                 0xb00
++#define LDBCR_UPC(n)          (1 << ((n) + 16))
++#define LDBCR_UPF(n)          (1 << ((n) + 8))
++#define LDBCR_UPD(n)          (1 << ((n) + 0))
++#define LDBnBSIFR(n)          (0xb20 + (n) * 0x20 + 0x00)
++#define LDBBSIFR_EN           (1 << 31)
++#define LDBBSIFR_VS           (1 << 29)
++#define LDBBSIFR_BRSEL                (1 << 28)
++#define LDBBSIFR_MX           (1 << 27)
++#define LDBBSIFR_MY           (1 << 26)
++#define LDBBSIFR_CV3          (3 << 24)
++#define LDBBSIFR_CV2          (2 << 24)
++#define LDBBSIFR_CV1          (1 << 24)
++#define LDBBSIFR_CV0          (0 << 24)
++#define LDBBSIFR_CV_MASK      (3 << 24)
++#define LDBBSIFR_LAY_MASK     (0xff << 16)
++#define LDBBSIFR_LAY_SHIFT    16
++#define LDBBSIFR_ROP3_MASK    (0xff << 16)
++#define LDBBSIFR_ROP3_SHIFT   16
++#define LDBBSIFR_AL_PL8               (3 << 14)
++#define LDBBSIFR_AL_PL1               (2 << 14)
++#define LDBBSIFR_AL_PK                (1 << 14)
++#define LDBBSIFR_AL_1         (0 << 14)
++#define LDBBSIFR_AL_MASK      (3 << 14)
++#define LDBBSIFR_SWPL         (1 << 10)
++#define LDBBSIFR_SWPW         (1 << 9)
++#define LDBBSIFR_SWPB         (1 << 8)
++#define LDBBSIFR_RY           (1 << 7)
++#define LDBBSIFR_CHRR_420     (2 << 0)
++#define LDBBSIFR_CHRR_422     (1 << 0)
++#define LDBBSIFR_CHRR_444     (0 << 0)
++#define LDBBSIFR_RPKF_ARGB32  (0x00 << 0)
++#define LDBBSIFR_RPKF_RGB16   (0x03 << 0)
++#define LDBBSIFR_RPKF_RGB24   (0x0b << 0)
++#define LDBBSIFR_RPKF_MASK    (0x1f << 0)
++#define LDBnBSSZR(n)          (0xb20 + (n) * 0x20 + 0x04)
++#define LDBBSSZR_BVSS_MASK    (0xfff << 16)
++#define LDBBSSZR_BVSS_SHIFT   16
++#define LDBBSSZR_BHSS_MASK    (0xfff << 0)
++#define LDBBSSZR_BHSS_SHIFT   0
++#define LDBnBLOCR(n)          (0xb20 + (n) * 0x20 + 0x08)
++#define LDBBLOCR_CVLC_MASK    (0xfff << 16)
++#define LDBBLOCR_CVLC_SHIFT   16
++#define LDBBLOCR_CHLC_MASK    (0xfff << 0)
++#define LDBBLOCR_CHLC_SHIFT   0
++#define LDBnBSMWR(n)          (0xb20 + (n) * 0x20 + 0x0c)
++#define LDBBSMWR_BSMWA_MASK   (0xffff << 16)
++#define LDBBSMWR_BSMWA_SHIFT  16
++#define LDBBSMWR_BSMW_MASK    (0xffff << 0)
++#define LDBBSMWR_BSMW_SHIFT   0
++#define LDBnBSAYR(n)          (0xb20 + (n) * 0x20 + 0x10)
++#define LDBBSAYR_FG1A_MASK    (0xff << 24)
++#define LDBBSAYR_FG1A_SHIFT   24
++#define LDBBSAYR_FG1R_MASK    (0xff << 16)
++#define LDBBSAYR_FG1R_SHIFT   16
++#define LDBBSAYR_FG1G_MASK    (0xff << 8)
++#define LDBBSAYR_FG1G_SHIFT   8
++#define LDBBSAYR_FG1B_MASK    (0xff << 0)
++#define LDBBSAYR_FG1B_SHIFT   0
++#define LDBnBSACR(n)          (0xb20 + (n) * 0x20 + 0x14)
++#define LDBBSACR_FG2A_MASK    (0xff << 24)
++#define LDBBSACR_FG2A_SHIFT   24
++#define LDBBSACR_FG2R_MASK    (0xff << 16)
++#define LDBBSACR_FG2R_SHIFT   16
++#define LDBBSACR_FG2G_MASK    (0xff << 8)
++#define LDBBSACR_FG2G_SHIFT   8
++#define LDBBSACR_FG2B_MASK    (0xff << 0)
++#define LDBBSACR_FG2B_SHIFT   0
++#define LDBnBSAAR(n)          (0xb20 + (n) * 0x20 + 0x18)
++#define LDBBSAAR_AP_MASK      (0xff << 24)
++#define LDBBSAAR_AP_SHIFT     24
++#define LDBBSAAR_R_MASK               (0xff << 16)
++#define LDBBSAAR_R_SHIFT      16
++#define LDBBSAAR_GY_MASK      (0xff << 8)
++#define LDBBSAAR_GY_SHIFT     8
++#define LDBBSAAR_B_MASK               (0xff << 0)
++#define LDBBSAAR_B_SHIFT      0
++#define LDBnBPPCR(n)          (0xb20 + (n) * 0x20 + 0x1c)
++#define LDBBPPCR_AP_MASK      (0xff << 24)
++#define LDBBPPCR_AP_SHIFT     24
++#define LDBBPPCR_R_MASK               (0xff << 16)
++#define LDBBPPCR_R_SHIFT      16
++#define LDBBPPCR_GY_MASK      (0xff << 8)
++#define LDBBPPCR_GY_SHIFT     8
++#define LDBBPPCR_B_MASK               (0xff << 0)
++#define LDBBPPCR_B_SHIFT      0
++#define LDBnBBGCL(n)          (0xb10 + (n) * 0x04)
++#define LDBBBGCL_BGA_MASK     (0xff << 24)
++#define LDBBBGCL_BGA_SHIFT    24
++#define LDBBBGCL_BGR_MASK     (0xff << 16)
++#define LDBBBGCL_BGR_SHIFT    16
++#define LDBBBGCL_BGG_MASK     (0xff << 8)
++#define LDBBBGCL_BGG_SHIFT    8
++#define LDBBBGCL_BGB_MASK     (0xff << 0)
++#define LDBBBGCL_BGB_SHIFT    0
++
+ #define SIDE_B_OFFSET 0x1000
+ #define MIRROR_OFFSET 0x2000
+ #define MAX_XRES 1920
+ #define MAX_YRES 1080
++enum sh_mobile_lcdc_overlay_mode {
++      LCDC_OVERLAY_BLEND,
++      LCDC_OVERLAY_ROP3,
++};
++
++/*
++ * struct sh_mobile_lcdc_overlay - LCDC display overlay
++ *
++ * @channel: LCDC channel this overlay belongs to
++ * @cfg: Overlay configuration
++ * @info: Frame buffer device
++ * @index: Overlay index (0-3)
++ * @base: Overlay registers base address
++ * @enabled: True if the overlay is enabled
++ * @mode: Overlay blending mode (alpha blend or ROP3)
++ * @alpha: Global alpha blending value (0-255, for alpha blending mode)
++ * @rop3: Raster operation (for ROP3 mode)
++ * @fb_mem: Frame buffer virtual memory address
++ * @fb_size: Frame buffer size in bytes
++ * @dma_handle: Frame buffer DMA address
++ * @base_addr_y: Overlay base address (RGB or luma component)
++ * @base_addr_c: Overlay base address (chroma component)
++ * @pan_offset: Current pan offset in bytes
++ * @format: Current pixelf format
++ * @xres: Horizontal visible resolution
++ * @xres_virtual: Horizontal total resolution
++ * @yres: Vertical visible resolution
++ * @yres_virtual: Vertical total resolution
++ * @pitch: Overlay line pitch
++ * @pos_x: Horizontal overlay position
++ * @pos_y: Vertical overlay position
++ */
++struct sh_mobile_lcdc_overlay {
++      struct sh_mobile_lcdc_chan *channel;
++
++      const struct sh_mobile_lcdc_overlay_cfg *cfg;
++      struct fb_info *info;
++
++      unsigned int index;
++      unsigned long base;
++
++      bool enabled;
++      enum sh_mobile_lcdc_overlay_mode mode;
++      unsigned int alpha;
++      unsigned int rop3;
++
++      void *fb_mem;
++      unsigned long fb_size;
++
++      dma_addr_t dma_handle;
++      unsigned long base_addr_y;
++      unsigned long base_addr_c;
++      unsigned long pan_offset;
++
++      const struct sh_mobile_lcdc_format_info *format;
++      unsigned int xres;
++      unsigned int xres_virtual;
++      unsigned int yres;
++      unsigned int yres_virtual;
++      unsigned int pitch;
++      int pos_x;
++      int pos_y;
++};
++
+ struct sh_mobile_lcdc_priv {
+       void __iomem *base;
+       int irq;
+@@ -45,7 +210,10 @@ struct sh_mobile_lcdc_priv {
+       struct device *dev;
+       struct clk *dot_clk;
+       unsigned long lddckr;
++
+       struct sh_mobile_lcdc_chan ch[2];
++      struct sh_mobile_lcdc_overlay overlays[4];
++
+       struct notifier_block notifier;
+       int started;
+       int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
+@@ -141,6 +309,13 @@ static unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan,
+       return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]);
+ }
++static void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl,
++                             int reg, unsigned long data)
++{
++      iowrite32(data, ovl->channel->lcdc->base + reg);
++      iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET);
++}
++
+ static void lcdc_write(struct sh_mobile_lcdc_priv *priv,
+                      unsigned long reg_offs, unsigned long data)
+ {
+@@ -685,6 +860,96 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
+       lcdc_write_chan(ch, LDHAJR, tmp);
+ }
++static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
++{
++      u32 format = 0;
++
++      if (!ovl->enabled) {
++              lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
++              lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0);
++              lcdc_write(ovl->channel->lcdc, LDBCR,
++                         LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
++              return;
++      }
++
++      ovl->base_addr_y = ovl->dma_handle;
++      ovl->base_addr_c = ovl->base_addr_y + ovl->xres
++                         * ovl->yres_virtual;
++
++      switch (ovl->mode) {
++      case LCDC_OVERLAY_BLEND:
++              format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT);
++              break;
++
++      case LCDC_OVERLAY_ROP3:
++              format = LDBBSIFR_EN | LDBBSIFR_BRSEL
++                     | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT);
++              break;
++      }
++
++      switch (ovl->format->fourcc) {
++      case V4L2_PIX_FMT_RGB565:
++      case V4L2_PIX_FMT_NV21:
++      case V4L2_PIX_FMT_NV61:
++      case V4L2_PIX_FMT_NV42:
++              format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
++              break;
++      case V4L2_PIX_FMT_BGR24:
++      case V4L2_PIX_FMT_NV12:
++      case V4L2_PIX_FMT_NV16:
++      case V4L2_PIX_FMT_NV24:
++              format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
++              break;
++      case V4L2_PIX_FMT_BGR32:
++      default:
++              format |= LDBBSIFR_SWPL;
++              break;
++      }
++
++      switch (ovl->format->fourcc) {
++      case V4L2_PIX_FMT_RGB565:
++              format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
++              break;
++      case V4L2_PIX_FMT_BGR24:
++              format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
++              break;
++      case V4L2_PIX_FMT_BGR32:
++              format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
++              break;
++      case V4L2_PIX_FMT_NV12:
++      case V4L2_PIX_FMT_NV21:
++              format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
++              break;
++      case V4L2_PIX_FMT_NV16:
++      case V4L2_PIX_FMT_NV61:
++              format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
++              break;
++      case V4L2_PIX_FMT_NV24:
++      case V4L2_PIX_FMT_NV42:
++              format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
++              break;
++      }
++
++      lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
++
++      lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format);
++
++      lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index),
++              (ovl->yres << LDBBSSZR_BVSS_SHIFT) |
++              (ovl->xres << LDBBSSZR_BHSS_SHIFT));
++      lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index),
++              (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) |
++              (ovl->pos_x << LDBBLOCR_CHLC_SHIFT));
++      lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index),
++              ovl->pitch << LDBBSMWR_BSMW_SHIFT);
++
++      lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
++      lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
++
++      lcdc_write(ovl->channel->lcdc, LDBCR,
++                 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
++}
++
+ /*
+  * __sh_mobile_lcdc_start - Configure and start the LCDC
+  * @priv: LCDC device
+@@ -892,6 +1157,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+               }
+       }
++      for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) {
++              struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k];
++              sh_mobile_lcdc_overlay_setup(ovl);
++      }
++
+       /* Start the LCDC. */
+       __sh_mobile_lcdc_start(priv);
+@@ -975,8 +1245,506 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
+                       sh_mobile_lcdc_clk_off(priv);
+ }
++static int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
++                                    struct fb_info *info)
++{
++      if (var->xres > MAX_XRES || var->yres > MAX_YRES)
++              return -EINVAL;
++
++      /* Make sure the virtual resolution is at least as big as the visible
++       * resolution.
++       */
++      if (var->xres_virtual < var->xres)
++              var->xres_virtual = var->xres;
++      if (var->yres_virtual < var->yres)
++              var->yres_virtual = var->yres;
++
++      if (sh_mobile_format_is_fourcc(var)) {
++              const struct sh_mobile_lcdc_format_info *format;
++
++              format = sh_mobile_format_info(var->grayscale);
++              if (format == NULL)
++                      return -EINVAL;
++              var->bits_per_pixel = format->bpp;
++
++              /* Default to RGB and JPEG color-spaces for RGB and YUV formats
++               * respectively.
++               */
++              if (!format->yuv)
++                      var->colorspace = V4L2_COLORSPACE_SRGB;
++              else if (var->colorspace != V4L2_COLORSPACE_REC709)
++                      var->colorspace = V4L2_COLORSPACE_JPEG;
++      } else {
++              if (var->bits_per_pixel <= 16) {                /* RGB 565 */
++                      var->bits_per_pixel = 16;
++                      var->red.offset = 11;
++                      var->red.length = 5;
++                      var->green.offset = 5;
++                      var->green.length = 6;
++                      var->blue.offset = 0;
++                      var->blue.length = 5;
++                      var->transp.offset = 0;
++                      var->transp.length = 0;
++              } else if (var->bits_per_pixel <= 24) {         /* RGB 888 */
++                      var->bits_per_pixel = 24;
++                      var->red.offset = 16;
++                      var->red.length = 8;
++                      var->green.offset = 8;
++                      var->green.length = 8;
++                      var->blue.offset = 0;
++                      var->blue.length = 8;
++                      var->transp.offset = 0;
++                      var->transp.length = 0;
++              } else if (var->bits_per_pixel <= 32) {         /* RGBA 888 */
++                      var->bits_per_pixel = 32;
++                      var->red.offset = 16;
++                      var->red.length = 8;
++                      var->green.offset = 8;
++                      var->green.length = 8;
++                      var->blue.offset = 0;
++                      var->blue.length = 8;
++                      var->transp.offset = 24;
++                      var->transp.length = 8;
++              } else
++                      return -EINVAL;
++
++              var->red.msb_right = 0;
++              var->green.msb_right = 0;
++              var->blue.msb_right = 0;
++              var->transp.msb_right = 0;
++      }
++
++      /* Make sure we don't exceed our allocated memory. */
++      if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
++          info->fix.smem_len)
++              return -EINVAL;
++
++      return 0;
++}
++
++/* -----------------------------------------------------------------------------
++ * Frame buffer operations - Overlays
++ */
++
++static ssize_t
++overlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++
++      return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha);
++}
++
++static ssize_t
++overlay_alpha_store(struct device *dev, struct device_attribute *attr,
++                  const char *buf, size_t count)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++      unsigned int alpha;
++      char *endp;
++
++      alpha = simple_strtoul(buf, &endp, 10);
++      if (isspace(*endp))
++              endp++;
++
++      if (endp - buf != count)
++              return -EINVAL;
++
++      if (alpha > 255)
++              return -EINVAL;
++
++      if (ovl->alpha != alpha) {
++              ovl->alpha = alpha;
++
++              if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled)
++                      sh_mobile_lcdc_overlay_setup(ovl);
++      }
++
++      return count;
++}
++
++static ssize_t
++overlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++
++      return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode);
++}
++
++static ssize_t
++overlay_mode_store(struct device *dev, struct device_attribute *attr,
++                 const char *buf, size_t count)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++      unsigned int mode;
++      char *endp;
++
++      mode = simple_strtoul(buf, &endp, 10);
++      if (isspace(*endp))
++              endp++;
++
++      if (endp - buf != count)
++              return -EINVAL;
++
++      if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3)
++              return -EINVAL;
++
++      if (ovl->mode != mode) {
++              ovl->mode = mode;
++
++              if (ovl->enabled)
++                      sh_mobile_lcdc_overlay_setup(ovl);
++      }
++
++      return count;
++}
++
++static ssize_t
++overlay_position_show(struct device *dev, struct device_attribute *attr,
++                    char *buf)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++
++      return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y);
++}
++
++static ssize_t
++overlay_position_store(struct device *dev, struct device_attribute *attr,
++                     const char *buf, size_t count)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++      char *endp;
++      int pos_x;
++      int pos_y;
++
++      pos_x = simple_strtol(buf, &endp, 10);
++      if (*endp != ',')
++              return -EINVAL;
++
++      pos_y = simple_strtol(endp + 1, &endp, 10);
++      if (isspace(*endp))
++              endp++;
++
++      if (endp - buf != count)
++              return -EINVAL;
++
++      if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) {
++              ovl->pos_x = pos_x;
++              ovl->pos_y = pos_y;
++
++              if (ovl->enabled)
++                      sh_mobile_lcdc_overlay_setup(ovl);
++      }
++
++      return count;
++}
++
++static ssize_t
++overlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++
++      return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3);
++}
++
++static ssize_t
++overlay_rop3_store(struct device *dev, struct device_attribute *attr,
++                  const char *buf, size_t count)
++{
++      struct fb_info *info = dev_get_drvdata(dev);
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++      unsigned int rop3;
++      char *endp;
++
++      rop3 = !!simple_strtoul(buf, &endp, 10);
++      if (isspace(*endp))
++              endp++;
++
++      if (endp - buf != count)
++              return -EINVAL;
++
++      if (rop3 > 255)
++              return -EINVAL;
++
++      if (ovl->rop3 != rop3) {
++              ovl->rop3 = rop3;
++
++              if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled)
++                      sh_mobile_lcdc_overlay_setup(ovl);
++      }
++
++      return count;
++}
++
++static const struct device_attribute overlay_sysfs_attrs[] = {
++      __ATTR(ovl_alpha, S_IRUGO|S_IWUSR,
++             overlay_alpha_show, overlay_alpha_store),
++      __ATTR(ovl_mode, S_IRUGO|S_IWUSR,
++             overlay_mode_show, overlay_mode_store),
++      __ATTR(ovl_position, S_IRUGO|S_IWUSR,
++             overlay_position_show, overlay_position_store),
++      __ATTR(ovl_rop3, S_IRUGO|S_IWUSR,
++             overlay_rop3_show, overlay_rop3_store),
++};
++
++static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix  = {
++      .id =           "SH Mobile LCDC",
++      .type =         FB_TYPE_PACKED_PIXELS,
++      .visual =       FB_VISUAL_TRUECOLOR,
++      .accel =        FB_ACCEL_NONE,
++      .xpanstep =     0,
++      .ypanstep =     1,
++      .ywrapstep =    0,
++      .capabilities = FB_CAP_FOURCC,
++};
++
++static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
++                                  struct fb_info *info)
++{
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++      unsigned long base_addr_y;
++      unsigned long base_addr_c;
++      unsigned long pan_offset;
++      unsigned long c_offset;
++
++      if (!ovl->format->yuv)
++              pan_offset = var->yoffset * ovl->pitch
++                         + var->xoffset * (ovl->format->bpp / 8);
++      else
++              pan_offset = var->yoffset * ovl->pitch + var->xoffset;
++
++      if (pan_offset == ovl->pan_offset)
++              return 0;       /* No change, do nothing */
++
++      /* Set the source address for the next refresh */
++      base_addr_y = ovl->dma_handle + pan_offset;
++
++      ovl->base_addr_y = base_addr_y;
++      ovl->base_addr_c = base_addr_y;
++
++      if (ovl->format->yuv) {
++              /* Set Y offset */
++              c_offset = var->yoffset * ovl->pitch
++                       * (ovl->format->bpp - 8) / 8;
++              base_addr_c = ovl->dma_handle
++                          + ovl->xres * ovl->yres_virtual
++                          + c_offset;
++              /* Set X offset */
++              if (ovl->format->fourcc == V4L2_PIX_FMT_NV24)
++                      base_addr_c += 2 * var->xoffset;
++              else
++                      base_addr_c += var->xoffset;
++
++              ovl->base_addr_c = base_addr_c;
++      }
++
++      lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
++      lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
++
++      ovl->pan_offset = pan_offset;
++
++      return 0;
++}
++
++static int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd,
++                                    unsigned long arg)
++{
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++
++      switch (cmd) {
++      case FBIO_WAITFORVSYNC:
++              return sh_mobile_lcdc_wait_for_vsync(ovl->channel);
++
++      default:
++              return -ENOIOCTLCMD;
++      }
++}
++
++static int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var,
++                                        struct fb_info *info)
++{
++      return __sh_mobile_lcdc_check_var(var, info);
++}
++
++static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
++{
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++
++      ovl->format =
++              sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
++
++      ovl->xres = info->var.xres;
++      ovl->xres_virtual = info->var.xres_virtual;
++      ovl->yres = info->var.yres;
++      ovl->yres_virtual = info->var.yres_virtual;
++
++      if (ovl->format->yuv)
++              ovl->pitch = info->var.xres;
++      else
++              ovl->pitch = info->var.xres * ovl->format->bpp / 8;
++
++      sh_mobile_lcdc_overlay_setup(ovl);
++
++      info->fix.line_length = ovl->pitch;
++
++      if (sh_mobile_format_is_fourcc(&info->var)) {
++              info->fix.type = FB_TYPE_FOURCC;
++              info->fix.visual = FB_VISUAL_FOURCC;
++      } else {
++              info->fix.type = FB_TYPE_PACKED_PIXELS;
++              info->fix.visual = FB_VISUAL_TRUECOLOR;
++      }
++
++      return 0;
++}
++
++/* Overlay blanking. Disable the overlay when blanked. */
++static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
++{
++      struct sh_mobile_lcdc_overlay *ovl = info->par;
++
++      ovl->enabled = !blank;
++      sh_mobile_lcdc_overlay_setup(ovl);
++
++      /* Prevent the backlight from receiving a blanking event by returning
++       * a non-zero value.
++       */
++      return 1;
++}
++
++static struct fb_ops sh_mobile_lcdc_overlay_ops = {
++      .owner          = THIS_MODULE,
++      .fb_read        = fb_sys_read,
++      .fb_write       = fb_sys_write,
++      .fb_fillrect    = sys_fillrect,
++      .fb_copyarea    = sys_copyarea,
++      .fb_imageblit   = sys_imageblit,
++      .fb_blank       = sh_mobile_lcdc_overlay_blank,
++      .fb_pan_display = sh_mobile_lcdc_overlay_pan,
++      .fb_ioctl       = sh_mobile_lcdc_overlay_ioctl,
++      .fb_check_var   = sh_mobile_lcdc_overlay_check_var,
++      .fb_set_par     = sh_mobile_lcdc_overlay_set_par,
++};
++
++static void
++sh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl)
++{
++      struct fb_info *info = ovl->info;
++
++      if (info == NULL || info->dev == NULL)
++              return;
++
++      unregister_framebuffer(ovl->info);
++}
++
++static int __devinit
++sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl)
++{
++      struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc;
++      struct fb_info *info = ovl->info;
++      unsigned int i;
++      int ret;
++
++      if (info == NULL)
++              return 0;
++
++      ret = register_framebuffer(info);
++      if (ret < 0)
++              return ret;
++
++      dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n",
++               dev_name(lcdc->dev), ovl->index, info->var.xres,
++               info->var.yres, info->var.bits_per_pixel);
++
++      for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) {
++              ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]);
++              if (ret < 0)
++                      return ret;
++      }
++
++      return 0;
++}
++
++static void
++sh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl)
++{
++      struct fb_info *info = ovl->info;
++
++      if (info == NULL || info->device == NULL)
++              return;
++
++      framebuffer_release(info);
++}
++
++static int __devinit
++sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
++{
++      struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc;
++      struct fb_var_screeninfo *var;
++      struct fb_info *info;
++
++      /* Allocate and initialize the frame buffer device. */
++      info = framebuffer_alloc(0, priv->dev);
++      if (info == NULL) {
++              dev_err(priv->dev, "unable to allocate fb_info\n");
++              return -ENOMEM;
++      }
++
++      ovl->info = info;
++
++      info->flags = FBINFO_FLAG_DEFAULT;
++      info->fbops = &sh_mobile_lcdc_overlay_ops;
++      info->device = priv->dev;
++      info->screen_base = ovl->fb_mem;
++      info->par = ovl;
++
++      /* Initialize fixed screen information. Restrict pan to 2 lines steps
++       * for NV12 and NV21.
++       */
++      info->fix = sh_mobile_lcdc_overlay_fix;
++      snprintf(info->fix.id, sizeof(info->fix.id),
++               "SH Mobile LCDC Overlay %u", ovl->index);
++      info->fix.smem_start = ovl->dma_handle;
++      info->fix.smem_len = ovl->fb_size;
++      info->fix.line_length = ovl->pitch;
++
++      if (ovl->format->yuv)
++              info->fix.visual = FB_VISUAL_FOURCC;
++      else
++              info->fix.visual = FB_VISUAL_TRUECOLOR;
++
++      if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 ||
++          ovl->format->fourcc == V4L2_PIX_FMT_NV21)
++              info->fix.ypanstep = 2;
++
++      /* Initialize variable screen information. */
++      var = &info->var;
++      memset(var, 0, sizeof(*var));
++      var->xres = ovl->xres;
++      var->yres = ovl->yres;
++      var->xres_virtual = ovl->xres_virtual;
++      var->yres_virtual = ovl->yres_virtual;
++      var->activate = FB_ACTIVATE_NOW;
++
++      /* Use the legacy API by default for RGB formats, and the FOURCC API
++       * for YUV formats.
++       */
++      if (!ovl->format->yuv)
++              var->bits_per_pixel = ovl->format->bpp;
++      else
++              var->grayscale = ovl->format->fourcc;
++
++      return sh_mobile_lcdc_overlay_check_var(var, info);
++}
++
+ /* -----------------------------------------------------------------------------
+- * Frame buffer operations
++ * Frame buffer operations - main frame buffer
+  */
+ static int sh_mobile_lcdc_setcolreg(u_int regno,
+@@ -1202,9 +1970,7 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
+       unsigned int best_xres = 0;
+       unsigned int best_yres = 0;
+       unsigned int i;
+-
+-      if (var->xres > MAX_XRES || var->yres > MAX_YRES)
+-              return -EINVAL;
++      int ret;
+       /* If board code provides us with a list of available modes, make sure
+        * we use one of them. Find the mode closest to the requested one. The
+@@ -1239,73 +2005,9 @@ static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var,
+               var->yres = best_yres;
+       }
+-      /* Make sure the virtual resolution is at least as big as the visible
+-       * resolution.
+-       */
+-      if (var->xres_virtual < var->xres)
+-              var->xres_virtual = var->xres;
+-      if (var->yres_virtual < var->yres)
+-              var->yres_virtual = var->yres;
+-
+-      if (sh_mobile_format_is_fourcc(var)) {
+-              const struct sh_mobile_lcdc_format_info *format;
+-
+-              format = sh_mobile_format_info(var->grayscale);
+-              if (format == NULL)
+-                      return -EINVAL;
+-              var->bits_per_pixel = format->bpp;
+-
+-              /* Default to RGB and JPEG color-spaces for RGB and YUV formats
+-               * respectively.
+-               */
+-              if (!format->yuv)
+-                      var->colorspace = V4L2_COLORSPACE_SRGB;
+-              else if (var->colorspace != V4L2_COLORSPACE_REC709)
+-                      var->colorspace = V4L2_COLORSPACE_JPEG;
+-      } else {
+-              if (var->bits_per_pixel <= 16) {                /* RGB 565 */
+-                      var->bits_per_pixel = 16;
+-                      var->red.offset = 11;
+-                      var->red.length = 5;
+-                      var->green.offset = 5;
+-                      var->green.length = 6;
+-                      var->blue.offset = 0;
+-                      var->blue.length = 5;
+-                      var->transp.offset = 0;
+-                      var->transp.length = 0;
+-              } else if (var->bits_per_pixel <= 24) {         /* RGB 888 */
+-                      var->bits_per_pixel = 24;
+-                      var->red.offset = 16;
+-                      var->red.length = 8;
+-                      var->green.offset = 8;
+-                      var->green.length = 8;
+-                      var->blue.offset = 0;
+-                      var->blue.length = 8;
+-                      var->transp.offset = 0;
+-                      var->transp.length = 0;
+-              } else if (var->bits_per_pixel <= 32) {         /* RGBA 888 */
+-                      var->bits_per_pixel = 32;
+-                      var->red.offset = 16;
+-                      var->red.length = 8;
+-                      var->green.offset = 8;
+-                      var->green.length = 8;
+-                      var->blue.offset = 0;
+-                      var->blue.length = 8;
+-                      var->transp.offset = 24;
+-                      var->transp.length = 8;
+-              } else
+-                      return -EINVAL;
+-
+-              var->red.msb_right = 0;
+-              var->green.msb_right = 0;
+-              var->blue.msb_right = 0;
+-              var->transp.msb_right = 0;
+-      }
+-
+-      /* Make sure we don't exceed our allocated memory. */
+-      if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
+-          info->fix.smem_len)
+-              return -EINVAL;
++      ret = __sh_mobile_lcdc_check_var(var, info);
++      if (ret < 0)
++              return ret;
+       /* only accept the forced_fourcc for dual channel configurations */
+       if (p->forced_fourcc &&
+@@ -1714,15 +2416,27 @@ static const struct fb_videomode default_720p __devinitconst = {
+ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
+ {
+       struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+-      int i;
++      unsigned int i;
+       fb_unregister_client(&priv->notifier);
++      for (i = 0; i < ARRAY_SIZE(priv->overlays); i++)
++              sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]);
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
+               sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
+       sh_mobile_lcdc_stop(priv);
++      for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) {
++              struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
++
++              sh_mobile_lcdc_overlay_fb_cleanup(ovl);
++
++              if (ovl->fb_mem)
++                      dma_free_coherent(&pdev->dev, ovl->fb_size,
++                                        ovl->fb_mem, ovl->dma_handle);
++      }
++
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+               struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
+@@ -1798,6 +2512,61 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *
+ }
+ static int __devinit
++sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
++                        struct sh_mobile_lcdc_overlay *ovl)
++{
++      const struct sh_mobile_lcdc_format_info *format;
++      int ret;
++
++      if (ovl->cfg->fourcc == 0)
++              return 0;
++
++      /* Validate the format. */
++      format = sh_mobile_format_info(ovl->cfg->fourcc);
++      if (format == NULL) {
++              dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
++              return -EINVAL;
++      }
++
++      ovl->enabled = false;
++      ovl->mode = LCDC_OVERLAY_BLEND;
++      ovl->alpha = 255;
++      ovl->rop3 = 0;
++      ovl->pos_x = 0;
++      ovl->pos_y = 0;
++
++      /* The default Y virtual resolution is twice the panel size to allow for
++       * double-buffering.
++       */
++      ovl->format = format;
++      ovl->xres = ovl->cfg->max_xres;
++      ovl->xres_virtual = ovl->xres;
++      ovl->yres = ovl->cfg->max_yres;
++      ovl->yres_virtual = ovl->yres * 2;
++
++      if (!format->yuv)
++              ovl->pitch = ovl->xres * format->bpp / 8;
++      else
++              ovl->pitch = ovl->xres;
++
++      /* Allocate frame buffer memory. */
++      ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
++                     * format->bpp / 8 * 2;
++      ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size,
++                                         &ovl->dma_handle, GFP_KERNEL);
++      if (!ovl->fb_mem) {
++              dev_err(priv->dev, "unable to allocate buffer\n");
++              return -ENOMEM;
++      }
++
++      ret = sh_mobile_lcdc_overlay_fb_init(ovl);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static int __devinit
+ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
+                           struct sh_mobile_lcdc_chan *ch)
+ {
+@@ -2005,6 +2774,17 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+                       goto err1;
+       }
++      for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
++              struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
++
++              ovl->cfg = &pdata->overlays[i];
++              ovl->channel = &priv->ch[0];
++
++              error = sh_mobile_lcdc_overlay_init(priv, ovl);
++              if (error)
++                      goto err1;
++      }
++
+       error = sh_mobile_lcdc_start(priv);
+       if (error) {
+               dev_err(&pdev->dev, "unable to start hardware\n");
+@@ -2019,6 +2799,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+                       goto err1;
+       }
++      for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) {
++              struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i];
++
++              error = sh_mobile_lcdc_overlay_fb_register(ovl);
++              if (error)
++                      goto err1;
++      }
++
+       /* Failure ignored */
+       priv->notifier.notifier_call = sh_mobile_lcdc_notify;
+       fb_register_client(&priv->notifier);
+diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
+index 7571b27..ff43ffc 100644
+--- a/include/video/sh_mobile_lcdc.h
++++ b/include/video/sh_mobile_lcdc.h
+@@ -166,6 +166,12 @@ struct sh_mobile_lcdc_bl_info {
+       int (*get_brightness)(void);
+ };
++struct sh_mobile_lcdc_overlay_cfg {
++      int fourcc;
++      unsigned int max_xres;
++      unsigned int max_yres;
++};
++
+ struct sh_mobile_lcdc_chan_cfg {
+       int chan;
+       int fourcc;
+@@ -186,6 +192,7 @@ struct sh_mobile_lcdc_chan_cfg {
+ struct sh_mobile_lcdc_info {
+       int clock_source;
+       struct sh_mobile_lcdc_chan_cfg ch[2];
++      struct sh_mobile_lcdc_overlay_cfg overlays[4];
+       struct sh_mobile_meram_info *meram_dev;
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch b/patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch
new file mode 100644 (file)
index 0000000..84b5cc7
--- /dev/null
@@ -0,0 +1,425 @@
+From 5175271a2ba2d97d73adadcaca3ba6b6616b6f23 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 15 Mar 2012 12:40:47 +0100
+Subject: sh_mobile_meram: Rename operations to cache_[alloc|free|update]
+
+The MERAM operations meram_register, meram_unregister and meram_update
+handle LCDC cache. In preparation for "raw" MERAM allocation, rename
+them to more appropriate names.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 4a2371772146b30113c9c837eb32b64f18376c0d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c |  32 ++++---
+ drivers/video/sh_mobile_lcdcfb.h |   2 +-
+ drivers/video/sh_mobile_meram.c  | 176 +++++++++++++++++++--------------------
+ include/video/sh_mobile_meram.h  |  21 ++---
+ 4 files changed, 110 insertions(+), 121 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 98e81b3..e593e81 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -1104,7 +1104,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+       /* Compute frame buffer base address and pitch for each channel. */
+       for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+               int pixelformat;
+-              void *meram;
++              void *cache;
+               ch = &priv->ch[k];
+               if (!ch->enabled)
+@@ -1119,12 +1119,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+                   ch->cfg->meram_cfg == NULL)
+                       continue;
+-              /* we need to de-init configured ICBs before we can
+-               * re-initialize them.
+-               */
+-              if (ch->meram) {
+-                      mdev->ops->meram_unregister(mdev, ch->meram);
+-                      ch->meram = NULL;
++              /* Free the allocated MERAM cache. */
++              if (ch->cache) {
++                      mdev->ops->cache_free(mdev, ch->cache);
++                      ch->cache = NULL;
+               }
+               switch (ch->format->fourcc) {
+@@ -1146,14 +1144,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+                       break;
+               }
+-              meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg,
++              cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg,
+                                       ch->pitch, ch->yres, pixelformat,
+                                       &ch->line_size);
+-              if (!IS_ERR(meram)) {
+-                      mdev->ops->meram_update(mdev, meram,
++              if (!IS_ERR(cache)) {
++                      mdev->ops->cache_update(mdev, cache,
+                                       ch->base_addr_y, ch->base_addr_c,
+                                       &ch->base_addr_y, &ch->base_addr_c);
+-                      ch->meram = meram;
++                      ch->cache = cache;
+               }
+       }
+@@ -1223,12 +1221,12 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
+               sh_mobile_lcdc_display_off(ch);
+-              /* disable the meram */
+-              if (ch->meram) {
++              /* Free the MERAM cache. */
++              if (ch->cache) {
+                       struct sh_mobile_meram_info *mdev;
+                       mdev = priv->meram_dev;
+-                      mdev->ops->meram_unregister(mdev, ch->meram);
+-                      ch->meram = 0;
++                      mdev->ops->cache_free(mdev, ch->cache);
++                      ch->cache = 0;
+               }
+       }
+@@ -1839,11 +1837,11 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
+                       base_addr_c += var->xoffset;
+       }
+-      if (ch->meram) {
++      if (ch->cache) {
+               struct sh_mobile_meram_info *mdev;
+               mdev = priv->meram_dev;
+-              mdev->ops->meram_update(mdev, ch->meram,
++              mdev->ops->cache_update(mdev, ch->cache,
+                                       base_addr_y, base_addr_c,
+                                       &base_addr_y, &base_addr_c);
+       }
+diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
+index 5c3bddd..e53cd11 100644
+--- a/drivers/video/sh_mobile_lcdcfb.h
++++ b/drivers/video/sh_mobile_lcdcfb.h
+@@ -59,7 +59,7 @@ struct sh_mobile_lcdc_chan {
+       unsigned long *reg_offs;
+       unsigned long ldmt1r_value;
+       unsigned long enabled; /* ME and SE in LDCNT2R */
+-      void *meram;
++      void *cache;
+       struct mutex open_lock;         /* protects the use counter */
+       int use_count;
+diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
+index 82ba830..4aa3fcb 100644
+--- a/drivers/video/sh_mobile_meram.c
++++ b/drivers/video/sh_mobile_meram.c
+@@ -194,13 +194,13 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
+ }
+ /* -----------------------------------------------------------------------------
+- * Allocation
++ * LCDC cache planes allocation, init, cleanup and free
+  */
+ /* Allocate ICBs and MERAM for a plane. */
+-static int __meram_alloc(struct sh_mobile_meram_priv *priv,
+-                       struct sh_mobile_meram_fb_plane *plane,
+-                       size_t size)
++static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
++                           struct sh_mobile_meram_fb_plane *plane,
++                           size_t size)
+ {
+       unsigned long mem;
+       unsigned long idx;
+@@ -229,8 +229,8 @@ static int __meram_alloc(struct sh_mobile_meram_priv *priv,
+ }
+ /* Free ICBs and MERAM for a plane. */
+-static void __meram_free(struct sh_mobile_meram_priv *priv,
+-                       struct sh_mobile_meram_fb_plane *plane)
++static void meram_plane_free(struct sh_mobile_meram_priv *priv,
++                           struct sh_mobile_meram_fb_plane *plane)
+ {
+       gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
+                     plane->marker->size * 1024);
+@@ -248,62 +248,6 @@ static int is_nvcolor(int cspace)
+       return 0;
+ }
+-/* Allocate memory for the ICBs and mark them as used. */
+-static struct sh_mobile_meram_fb_cache *
+-meram_alloc(struct sh_mobile_meram_priv *priv,
+-          const struct sh_mobile_meram_cfg *cfg,
+-          int pixelformat)
+-{
+-      struct sh_mobile_meram_fb_cache *cache;
+-      unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
+-      int ret;
+-
+-      if (cfg->icb[0].meram_size == 0)
+-              return ERR_PTR(-EINVAL);
+-
+-      if (nplanes == 2 && cfg->icb[1].meram_size == 0)
+-              return ERR_PTR(-EINVAL);
+-
+-      cache = kzalloc(sizeof(*cache), GFP_KERNEL);
+-      if (cache == NULL)
+-              return ERR_PTR(-ENOMEM);
+-
+-      cache->nplanes = nplanes;
+-
+-      ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size);
+-      if (ret < 0)
+-              goto error;
+-
+-      cache->planes[0].marker->current_reg = 1;
+-      cache->planes[0].marker->pixelformat = pixelformat;
+-
+-      if (cache->nplanes == 1)
+-              return cache;
+-
+-      ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size);
+-      if (ret < 0) {
+-              __meram_free(priv, &cache->planes[0]);
+-              goto error;
+-      }
+-
+-      return cache;
+-
+-error:
+-      kfree(cache);
+-      return ERR_PTR(-ENOMEM);
+-}
+-
+-/* Unmark the specified ICB as used. */
+-static void meram_free(struct sh_mobile_meram_priv *priv,
+-                     struct sh_mobile_meram_fb_cache *cache)
+-{
+-      __meram_free(priv, &cache->planes[0]);
+-      if (cache->nplanes == 2)
+-              __meram_free(priv, &cache->planes[1]);
+-
+-      kfree(cache);
+-}
+-
+ /* Set the next address to fetch. */
+ static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
+                               struct sh_mobile_meram_fb_cache *cache,
+@@ -355,10 +299,10 @@ meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
+       (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
+ /* Initialize MERAM. */
+-static int meram_init(struct sh_mobile_meram_priv *priv,
+-                    struct sh_mobile_meram_fb_plane *plane,
+-                    unsigned int xres, unsigned int yres,
+-                    unsigned int *out_pitch)
++static int meram_plane_init(struct sh_mobile_meram_priv *priv,
++                          struct sh_mobile_meram_fb_plane *plane,
++                          unsigned int xres, unsigned int yres,
++                          unsigned int *out_pitch)
+ {
+       struct sh_mobile_meram_icb *marker = plane->marker;
+       unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
+@@ -427,8 +371,8 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
+       return 0;
+ }
+-static void meram_deinit(struct sh_mobile_meram_priv *priv,
+-                       struct sh_mobile_meram_fb_plane *plane)
++static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
++                              struct sh_mobile_meram_fb_plane *plane)
+ {
+       /* disable ICB */
+       meram_write_icb(priv->base, plane->cache->index,  MExxCTL,
+@@ -441,18 +385,60 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
+ }
+ /* -----------------------------------------------------------------------------
+- * Registration/unregistration
++ * LCDC cache operations
+  */
+-static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
+-                                    const struct sh_mobile_meram_cfg *cfg,
+-                                    unsigned int xres, unsigned int yres,
+-                                    unsigned int pixelformat,
+-                                    unsigned int *pitch)
++/* Allocate memory for the ICBs and mark them as used. */
++static struct sh_mobile_meram_fb_cache *
++meram_cache_alloc(struct sh_mobile_meram_priv *priv,
++                const struct sh_mobile_meram_cfg *cfg,
++                int pixelformat)
++{
++      unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
++      struct sh_mobile_meram_fb_cache *cache;
++      int ret;
++
++      cache = kzalloc(sizeof(*cache), GFP_KERNEL);
++      if (cache == NULL)
++              return ERR_PTR(-ENOMEM);
++
++      cache->nplanes = nplanes;
++
++      ret = meram_plane_alloc(priv, &cache->planes[0],
++                              cfg->icb[0].meram_size);
++      if (ret < 0)
++              goto error;
++
++      cache->planes[0].marker->current_reg = 1;
++      cache->planes[0].marker->pixelformat = pixelformat;
++
++      if (cache->nplanes == 1)
++              return cache;
++
++      ret = meram_plane_alloc(priv, &cache->planes[1],
++                              cfg->icb[1].meram_size);
++      if (ret < 0) {
++              meram_plane_free(priv, &cache->planes[0]);
++              goto error;
++      }
++
++      return cache;
++
++error:
++      kfree(cache);
++      return ERR_PTR(-ENOMEM);
++}
++
++static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
++                                 const struct sh_mobile_meram_cfg *cfg,
++                                 unsigned int xres, unsigned int yres,
++                                 unsigned int pixelformat,
++                                 unsigned int *pitch)
+ {
+       struct sh_mobile_meram_fb_cache *cache;
+       struct sh_mobile_meram_priv *priv = pdata->priv;
+       struct platform_device *pdev = pdata->pdev;
++      unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
+       unsigned int out_pitch;
+       if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+@@ -469,10 +455,16 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
+               return ERR_PTR(-EINVAL);
+       }
++      if (cfg->icb[0].meram_size == 0)
++              return ERR_PTR(-EINVAL);
++
++      if (nplanes == 2 && cfg->icb[1].meram_size == 0)
++              return ERR_PTR(-EINVAL);
++
+       mutex_lock(&priv->lock);
+       /* We now register the ICBs and allocate the MERAM regions. */
+-      cache = meram_alloc(priv, cfg, pixelformat);
++      cache = meram_cache_alloc(priv, cfg, pixelformat);
+       if (IS_ERR(cache)) {
+               dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
+                       PTR_ERR(cache));
+@@ -480,14 +472,14 @@ static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
+       }
+       /* initialize MERAM */
+-      meram_init(priv, &cache->planes[0], xres, yres, &out_pitch);
++      meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
+       *pitch = out_pitch;
+       if (pixelformat == SH_MOBILE_MERAM_PF_NV)
+-              meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2,
+-                      &out_pitch);
++              meram_plane_init(priv, &cache->planes[1],
++                               xres, (yres + 1) / 2, &out_pitch);
+       else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
+-              meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2,
+-                      &out_pitch);
++              meram_plane_init(priv, &cache->planes[1],
++                               2 * xres, (yres + 1) / 2, &out_pitch);
+ err:
+       mutex_unlock(&priv->lock);
+@@ -495,25 +487,29 @@ err:
+ }
+ static void
+-sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data)
++sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
+ {
+       struct sh_mobile_meram_fb_cache *cache = data;
+       struct sh_mobile_meram_priv *priv = pdata->priv;
+       mutex_lock(&priv->lock);
+-      /* deinit & free */
+-      meram_deinit(priv, &cache->planes[0]);
+-      if (cache->nplanes == 2)
+-              meram_deinit(priv, &cache->planes[1]);
++      /* Cleanup and free. */
++      meram_plane_cleanup(priv, &cache->planes[0]);
++      meram_plane_free(priv, &cache->planes[0]);
+-      meram_free(priv, cache);
++      if (cache->nplanes == 2) {
++              meram_plane_cleanup(priv, &cache->planes[1]);
++              meram_plane_free(priv, &cache->planes[1]);
++      }
++
++      kfree(cache);
+       mutex_unlock(&priv->lock);
+ }
+ static void
+-sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
++sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
+                      unsigned long base_addr_y, unsigned long base_addr_c,
+                      unsigned long *icb_addr_y, unsigned long *icb_addr_c)
+ {
+@@ -530,9 +526,9 @@ sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
+ static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
+       .module                 = THIS_MODULE,
+-      .meram_register         = sh_mobile_meram_register,
+-      .meram_unregister       = sh_mobile_meram_unregister,
+-      .meram_update           = sh_mobile_meram_update,
++      .cache_alloc            = sh_mobile_cache_alloc,
++      .cache_free             = sh_mobile_cache_free,
++      .cache_update           = sh_mobile_cache_update,
+ };
+ /* -----------------------------------------------------------------------------
+diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
+index 29b2fd3..8a5afaf 100644
+--- a/include/video/sh_mobile_meram.h
++++ b/include/video/sh_mobile_meram.h
+@@ -41,19 +41,14 @@ struct sh_mobile_meram_cfg {
+ struct module;
+ struct sh_mobile_meram_ops {
+       struct module   *module;
+-      /* register usage of meram */
+-      void *(*meram_register)(struct sh_mobile_meram_info *meram_dev,
+-                              const struct sh_mobile_meram_cfg *cfg,
+-                              unsigned int xres, unsigned int yres,
+-                              unsigned int pixelformat,
+-                              unsigned int *pitch);
+-
+-      /* unregister usage of meram */
+-      void (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
+-                               void *data);
+-
+-      /* update meram settings */
+-      void (*meram_update)(struct sh_mobile_meram_info *meram_dev, void *data,
++
++      /* LCDC cache management */
++      void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev,
++                           const struct sh_mobile_meram_cfg *cfg,
++                           unsigned int xres, unsigned int yres,
++                           unsigned int pixelformat, unsigned int *pitch);
++      void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data);
++      void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data,
+                            unsigned long base_addr_y,
+                            unsigned long base_addr_c,
+                            unsigned long *icb_addr_y,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch b/patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch
new file mode 100644 (file)
index 0000000..64653c1
--- /dev/null
@@ -0,0 +1,265 @@
+From b8fe39bce6f2c38cfa04299077173aff50600687 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 15 Mar 2012 12:40:47 +0100
+Subject: sh_mobile_meram: Use direct function calls for the public API
+
+There's no reason to use abstract operation pointers to implement the
+MERAM API. Replace them by direct function calls.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 6e729b416b44296f5ed503b40ac58c2bffb43caf)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 27 ++++++++--------------
+ drivers/video/sh_mobile_meram.c  | 40 ++++++++++++++++----------------
+ include/video/sh_mobile_meram.h  | 50 ++++++++++++++++++++++++++++------------
+ 3 files changed, 65 insertions(+), 52 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index e593e81..9da4b1b6 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -1115,13 +1115,12 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+               ch->line_size = ch->pitch;
+               /* Enable MERAM if possible. */
+-              if (mdev == NULL || mdev->ops == NULL ||
+-                  ch->cfg->meram_cfg == NULL)
++              if (mdev == NULL || ch->cfg->meram_cfg == NULL)
+                       continue;
+               /* Free the allocated MERAM cache. */
+               if (ch->cache) {
+-                      mdev->ops->cache_free(mdev, ch->cache);
++                      sh_mobile_meram_cache_free(mdev, ch->cache);
+                       ch->cache = NULL;
+               }
+@@ -1144,11 +1143,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+                       break;
+               }
+-              cache = mdev->ops->cache_alloc(mdev, ch->cfg->meram_cfg,
++              cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
+                                       ch->pitch, ch->yres, pixelformat,
+                                       &ch->line_size);
+               if (!IS_ERR(cache)) {
+-                      mdev->ops->cache_update(mdev, cache,
++                      sh_mobile_meram_cache_update(mdev, cache,
+                                       ch->base_addr_y, ch->base_addr_c,
+                                       &ch->base_addr_y, &ch->base_addr_c);
+                       ch->cache = cache;
+@@ -1223,9 +1222,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
+               /* Free the MERAM cache. */
+               if (ch->cache) {
+-                      struct sh_mobile_meram_info *mdev;
+-                      mdev = priv->meram_dev;
+-                      mdev->ops->cache_free(mdev, ch->cache);
++                      sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
+                       ch->cache = 0;
+               }
+@@ -1808,7 +1805,7 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
+       struct sh_mobile_lcdc_priv *priv = ch->lcdc;
+       unsigned long ldrcntr;
+       unsigned long new_pan_offset;
+-      unsigned long base_addr_y, base_addr_c;
++      unsigned long base_addr_y, base_addr_c = 0;
+       unsigned long c_offset;
+       if (!ch->format->yuv)
+@@ -1837,14 +1834,10 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
+                       base_addr_c += var->xoffset;
+       }
+-      if (ch->cache) {
+-              struct sh_mobile_meram_info *mdev;
+-
+-              mdev = priv->meram_dev;
+-              mdev->ops->cache_update(mdev, ch->cache,
+-                                      base_addr_y, base_addr_c,
+-                                      &base_addr_y, &base_addr_c);
+-      }
++      if (ch->cache)
++              sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
++                                           base_addr_y, base_addr_c,
++                                           &base_addr_y, &base_addr_c);
+       ch->base_addr_y = base_addr_y;
+       ch->base_addr_c = base_addr_c;
+diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
+index 4aa3fcb..fdb6fc1 100644
+--- a/drivers/video/sh_mobile_meram.c
++++ b/drivers/video/sh_mobile_meram.c
+@@ -11,6 +11,7 @@
+ #include <linux/device.h>
+ #include <linux/err.h>
++#include <linux/export.h>
+ #include <linux/genalloc.h>
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+@@ -429,11 +430,10 @@ error:
+       return ERR_PTR(-ENOMEM);
+ }
+-static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
+-                                 const struct sh_mobile_meram_cfg *cfg,
+-                                 unsigned int xres, unsigned int yres,
+-                                 unsigned int pixelformat,
+-                                 unsigned int *pitch)
++void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *pdata,
++                                const struct sh_mobile_meram_cfg *cfg,
++                                unsigned int xres, unsigned int yres,
++                                unsigned int pixelformat, unsigned int *pitch)
+ {
+       struct sh_mobile_meram_fb_cache *cache;
+       struct sh_mobile_meram_priv *priv = pdata->priv;
+@@ -441,6 +441,9 @@ static void *sh_mobile_cache_alloc(struct sh_mobile_meram_info *pdata,
+       unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
+       unsigned int out_pitch;
++      if (priv == NULL)
++              return ERR_PTR(-ENODEV);
++
+       if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+           pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
+           pixelformat != SH_MOBILE_MERAM_PF_RGB)
+@@ -485,9 +488,10 @@ err:
+       mutex_unlock(&priv->lock);
+       return cache;
+ }
++EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_alloc);
+-static void
+-sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
++void
++sh_mobile_meram_cache_free(struct sh_mobile_meram_info *pdata, void *data)
+ {
+       struct sh_mobile_meram_fb_cache *cache = data;
+       struct sh_mobile_meram_priv *priv = pdata->priv;
+@@ -507,11 +511,14 @@ sh_mobile_cache_free(struct sh_mobile_meram_info *pdata, void *data)
+       mutex_unlock(&priv->lock);
+ }
+-
+-static void
+-sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
+-                     unsigned long base_addr_y, unsigned long base_addr_c,
+-                     unsigned long *icb_addr_y, unsigned long *icb_addr_c)
++EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_free);
++
++void
++sh_mobile_meram_cache_update(struct sh_mobile_meram_info *pdata, void *data,
++                           unsigned long base_addr_y,
++                           unsigned long base_addr_c,
++                           unsigned long *icb_addr_y,
++                           unsigned long *icb_addr_c)
+ {
+       struct sh_mobile_meram_fb_cache *cache = data;
+       struct sh_mobile_meram_priv *priv = pdata->priv;
+@@ -523,13 +530,7 @@ sh_mobile_cache_update(struct sh_mobile_meram_info *pdata, void *data,
+       mutex_unlock(&priv->lock);
+ }
+-
+-static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
+-      .module                 = THIS_MODULE,
+-      .cache_alloc            = sh_mobile_cache_alloc,
+-      .cache_free             = sh_mobile_cache_free,
+-      .cache_update           = sh_mobile_cache_update,
+-};
++EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
+ /* -----------------------------------------------------------------------------
+  * Power management
+@@ -620,7 +621,6 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
+       for (i = 0; i < MERAM_ICB_NUM; ++i)
+               priv->icbs[i].index = i;
+-      pdata->ops = &sh_mobile_meram_ops;
+       pdata->priv = priv;
+       pdata->pdev = pdev;
+diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
+index 8a5afaf..1134837 100644
+--- a/include/video/sh_mobile_meram.h
++++ b/include/video/sh_mobile_meram.h
+@@ -15,7 +15,6 @@ enum {
+ struct sh_mobile_meram_priv;
+-struct sh_mobile_meram_ops;
+ /*
+  * struct sh_mobile_meram_info - MERAM platform data
+@@ -24,7 +23,6 @@ struct sh_mobile_meram_ops;
+ struct sh_mobile_meram_info {
+       int                             addr_mode;
+       u32                             reserved_icbs;
+-      struct sh_mobile_meram_ops      *ops;
+       struct sh_mobile_meram_priv     *priv;
+       struct platform_device          *pdev;
+ };
+@@ -38,21 +36,43 @@ struct sh_mobile_meram_cfg {
+       struct sh_mobile_meram_icb_cfg icb[2];
+ };
+-struct module;
+-struct sh_mobile_meram_ops {
+-      struct module   *module;
+-
+-      /* LCDC cache management */
+-      void *(*cache_alloc)(struct sh_mobile_meram_info *meram_dev,
+-                           const struct sh_mobile_meram_cfg *cfg,
+-                           unsigned int xres, unsigned int yres,
+-                           unsigned int pixelformat, unsigned int *pitch);
+-      void (*cache_free)(struct sh_mobile_meram_info *meram_dev, void *data);
+-      void (*cache_update)(struct sh_mobile_meram_info *meram_dev, void *data,
++#if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
++    defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
++void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
++                                const struct sh_mobile_meram_cfg *cfg,
++                                unsigned int xres, unsigned int yres,
++                                unsigned int pixelformat,
++                                unsigned int *pitch);
++void sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data);
++void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
++                                unsigned long base_addr_y,
++                                unsigned long base_addr_c,
++                                unsigned long *icb_addr_y,
++                                unsigned long *icb_addr_c);
++#else
++static inline void *
++sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
++                          const struct sh_mobile_meram_cfg *cfg,
++                          unsigned int xres, unsigned int yres,
++                          unsigned int pixelformat,
++                          unsigned int *pitch)
++{
++      return ERR_PTR(-ENODEV);
++}
++
++static inline void
++sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data)
++{
++}
++
++static inline void
++sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
+                            unsigned long base_addr_y,
+                            unsigned long base_addr_c,
+                            unsigned long *icb_addr_y,
+-                           unsigned long *icb_addr_c);
+-};
++                           unsigned long *icb_addr_c)
++{
++}
++#endif
+ #endif /* __VIDEO_SH_MOBILE_MERAM_H__  */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch b/patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch
new file mode 100644 (file)
index 0000000..0602f77
--- /dev/null
@@ -0,0 +1,129 @@
+From 81c446ad9189a068ef555c436c96d651dc86c4da Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 15 Mar 2012 13:18:17 +0100
+Subject: sh_mobile_meram: Add direct MERAM allocation API
+
+The API can be used to allocate and free MERAM blocks directly, without
+going through ICBs.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 239921ec1d969e904676f444a92e6d68a928d98c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_meram.c | 41 +++++++++++++++++++++++++++++++++++++----
+ include/video/sh_mobile_meram.h | 16 ++++++++++++++++
+ 2 files changed, 53 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
+index fdb6fc1..7a0ba8b 100644
+--- a/drivers/video/sh_mobile_meram.c
++++ b/drivers/video/sh_mobile_meram.c
+@@ -195,6 +195,21 @@ static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
+ }
+ /* -----------------------------------------------------------------------------
++ * MERAM allocation and free
++ */
++
++static unsigned long meram_alloc(struct sh_mobile_meram_priv *priv, size_t size)
++{
++      return gen_pool_alloc(priv->pool, size);
++}
++
++static void meram_free(struct sh_mobile_meram_priv *priv, unsigned long mem,
++                     size_t size)
++{
++      gen_pool_free(priv->pool, mem, size);
++}
++
++/* -----------------------------------------------------------------------------
+  * LCDC cache planes allocation, init, cleanup and free
+  */
+@@ -216,7 +231,7 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
+               return -ENOMEM;
+       plane->marker = &priv->icbs[idx];
+-      mem = gen_pool_alloc(priv->pool, size * 1024);
++      mem = meram_alloc(priv, size * 1024);
+       if (mem == 0)
+               return -ENOMEM;
+@@ -233,8 +248,8 @@ static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
+ static void meram_plane_free(struct sh_mobile_meram_priv *priv,
+                            struct sh_mobile_meram_fb_plane *plane)
+ {
+-      gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
+-                    plane->marker->size * 1024);
++      meram_free(priv, priv->meram + plane->marker->offset,
++                 plane->marker->size * 1024);
+       __clear_bit(plane->marker->index, &priv->used_icb);
+       __clear_bit(plane->cache->index, &priv->used_icb);
+@@ -386,9 +401,27 @@ static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
+ }
+ /* -----------------------------------------------------------------------------
+- * LCDC cache operations
++ * MERAM operations
+  */
++unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *pdata,
++                                  size_t size)
++{
++      struct sh_mobile_meram_priv *priv = pdata->priv;
++
++      return meram_alloc(priv, size);
++}
++EXPORT_SYMBOL_GPL(sh_mobile_meram_alloc);
++
++void sh_mobile_meram_free(struct sh_mobile_meram_info *pdata, unsigned long mem,
++                        size_t size)
++{
++      struct sh_mobile_meram_priv *priv = pdata->priv;
++
++      meram_free(priv, mem, size);
++}
++EXPORT_SYMBOL_GPL(sh_mobile_meram_free);
++
+ /* Allocate memory for the ICBs and mark them as used. */
+ static struct sh_mobile_meram_fb_cache *
+ meram_cache_alloc(struct sh_mobile_meram_priv *priv,
+diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
+index 1134837..062e6e7 100644
+--- a/include/video/sh_mobile_meram.h
++++ b/include/video/sh_mobile_meram.h
+@@ -38,6 +38,10 @@ struct sh_mobile_meram_cfg {
+ #if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
+     defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
++unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev,
++                                  size_t size);
++void sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
++                        unsigned long mem, size_t size);
+ void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
+                                 const struct sh_mobile_meram_cfg *cfg,
+                                 unsigned int xres, unsigned int yres,
+@@ -50,6 +54,18 @@ void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
+                                 unsigned long *icb_addr_y,
+                                 unsigned long *icb_addr_c);
+ #else
++static inline unsigned long
++sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev, size_t size)
++{
++      return 0;
++}
++
++static inline void
++sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
++                   unsigned long mem, size_t size)
++{
++}
++
+ static inline void *
+ sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
+                           const struct sh_mobile_meram_cfg *cfg,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch b/patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch
new file mode 100644 (file)
index 0000000..3df2f9a
--- /dev/null
@@ -0,0 +1,37 @@
+From fbcfe8a409c3a0177d599e2b6a73a70fd4dffc8a Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 15 Mar 2012 18:34:05 +0100
+Subject: fbdev: sh_mobile_lcdc: Destroy mutex at remove time
+
+Add a missing mutex_destroy() call when the driver is unbound from the
+device.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 0c75c4e073a8ec35bfd6c8adcceb2b896f2063e2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 9da4b1b6..644c230 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -2444,8 +2444,11 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
+       }
+       for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+-              if (priv->ch[i].bl)
+-                      sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
++              struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
++
++              if (ch->bl)
++                      sh_mobile_lcdc_bl_remove(ch->bl);
++              mutex_destroy(&ch->open_lock);
+       }
+       if (priv->dot_clk) {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch b/patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch
new file mode 100644 (file)
index 0000000..378217b
--- /dev/null
@@ -0,0 +1,72 @@
+From 8a18c739cb6639c5b8e43cc19929f98c532afae7 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 18 Jul 2012 16:29:20 +0200
+Subject: fbdev: sh_mobile_lcdc: Fix line pitch computation
+
+Line pitch depends on the virtual horizontal resolution, compute it
+accordingly.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 16ca21c9a9f64577221c47d8d2f00d13b880aefa)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 644c230..67877cc 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -1580,9 +1580,9 @@ static int sh_mobile_lcdc_overlay_set_par(struct fb_info *info)
+       ovl->yres_virtual = info->var.yres_virtual;
+       if (ovl->format->yuv)
+-              ovl->pitch = info->var.xres;
++              ovl->pitch = info->var.xres_virtual;
+       else
+-              ovl->pitch = info->var.xres * ovl->format->bpp / 8;
++              ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8;
+       sh_mobile_lcdc_overlay_setup(ovl);
+@@ -2024,9 +2024,9 @@ static int sh_mobile_lcdc_set_par(struct fb_info *info)
+       ch->yres_virtual = info->var.yres_virtual;
+       if (ch->format->yuv)
+-              ch->pitch = info->var.xres;
++              ch->pitch = info->var.xres_virtual;
+       else
+-              ch->pitch = info->var.xres * ch->format->bpp / 8;
++              ch->pitch = info->var.xres_virtual * ch->format->bpp / 8;
+       ret = sh_mobile_lcdc_start(ch->lcdc);
+       if (ret < 0)
+@@ -2539,9 +2539,9 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
+       ovl->yres_virtual = ovl->yres * 2;
+       if (!format->yuv)
+-              ovl->pitch = ovl->xres * format->bpp / 8;
++              ovl->pitch = ovl->xres_virtual * format->bpp / 8;
+       else
+-              ovl->pitch = ovl->xres;
++              ovl->pitch = ovl->xres_virtual;
+       /* Allocate frame buffer memory. */
+       ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
+@@ -2628,10 +2628,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
+       if (!format->yuv) {
+               ch->colorspace = V4L2_COLORSPACE_SRGB;
+-              ch->pitch = ch->xres * format->bpp / 8;
++              ch->pitch = ch->xres_virtual * format->bpp / 8;
+       } else {
+               ch->colorspace = V4L2_COLORSPACE_REC709;
+-              ch->pitch = ch->xres;
++              ch->pitch = ch->xres_virtual;
+       }
+       ch->display.width = cfg->panel_cfg.width;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch b/patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch
new file mode 100644 (file)
index 0000000..b14dd22
--- /dev/null
@@ -0,0 +1,53 @@
+From 1cd17c833c8811e06b3dddbe9a9c71e6735a58f9 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 18 Jul 2012 16:59:16 +0200
+Subject: fbdev: sh_mobile_lcdc: Use channel configuration to initialize fb
+ device
+
+Copy the x and y virtual resolutions from the channel information
+instead of recomputing them.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit bd5f2c6911c210af52fa4dc4cf504043ff8a4971)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 67877cc..68011b5 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -2214,14 +2214,14 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
+               info->fix.ypanstep = 2;
+       /* Initialize variable screen information using the first mode as
+-       * default. The default Y virtual resolution is twice the panel size to
+-       * allow for double-buffering.
++       * default.
+        */
+       var = &info->var;
+       fb_videomode_to_var(var, mode);
+       var->width = ch->cfg->panel_cfg.width;
+       var->height = ch->cfg->panel_cfg.height;
+-      var->yres_virtual = var->yres * 2;
++      var->xres_virtual = ch->xres_virtual;
++      var->yres_virtual = ch->yres_virtual;
+       var->activate = FB_ACTIVATE_NOW;
+       /* Use the legacy API by default for RGB formats, and the FOURCC API
+@@ -2619,7 +2619,9 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
+               num_modes = cfg->num_modes;
+       }
+-      /* Use the first mode as default. */
++      /* Use the first mode as default. The default Y virtual resolution is
++       * twice the panel size to allow for double-buffering.
++       */
+       ch->format = format;
+       ch->xres = mode->xres;
+       ch->xres_virtual = mode->xres;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch b/patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch
new file mode 100644 (file)
index 0000000..80ab27b
--- /dev/null
@@ -0,0 +1,72 @@
+From 194360fff0a2a4255630477db84bf7af704109ca Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 18 Jul 2012 17:09:04 +0200
+Subject: fbdev: sh_mobile_lcdc: Support horizontal panning
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 15dede882e564601947f2ce4b647742c0351be6d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 68011b5..d82c1de 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -1493,7 +1493,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix  = {
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_TRUECOLOR,
+       .accel =        FB_ACCEL_NONE,
+-      .xpanstep =     0,
++      .xpanstep =     1,
+       .ypanstep =     1,
+       .ywrapstep =    0,
+       .capabilities = FB_CAP_FOURCC,
+@@ -1714,9 +1714,14 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
+       else
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+-      if (ovl->format->fourcc == V4L2_PIX_FMT_NV12 ||
+-          ovl->format->fourcc == V4L2_PIX_FMT_NV21)
++      switch (ovl->format->fourcc) {
++      case V4L2_PIX_FMT_NV16:
++      case V4L2_PIX_FMT_NV61:
+               info->fix.ypanstep = 2;
++      case V4L2_PIX_FMT_NV12:
++      case V4L2_PIX_FMT_NV21:
++              info->fix.xpanstep = 2;
++      }
+       /* Initialize variable screen information. */
+       var = &info->var;
+@@ -1771,7 +1776,7 @@ static const struct fb_fix_screeninfo sh_mobile_lcdc_fix  = {
+       .type =         FB_TYPE_PACKED_PIXELS,
+       .visual =       FB_VISUAL_TRUECOLOR,
+       .accel =        FB_ACCEL_NONE,
+-      .xpanstep =     0,
++      .xpanstep =     1,
+       .ypanstep =     1,
+       .ywrapstep =    0,
+       .capabilities = FB_CAP_FOURCC,
+@@ -2209,9 +2214,14 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
+       else
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+-      if (ch->format->fourcc == V4L2_PIX_FMT_NV12 ||
+-          ch->format->fourcc == V4L2_PIX_FMT_NV21)
++      switch (ch->format->fourcc) {
++      case V4L2_PIX_FMT_NV16:
++      case V4L2_PIX_FMT_NV61:
+               info->fix.ypanstep = 2;
++      case V4L2_PIX_FMT_NV12:
++      case V4L2_PIX_FMT_NV21:
++              info->fix.xpanstep = 2;
++      }
+       /* Initialize variable screen information using the first mode as
+        * default.
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch b/patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch
new file mode 100644 (file)
index 0000000..ee64fdb
--- /dev/null
@@ -0,0 +1,41 @@
+From 07f80feb4f79273ade0b493d4f173d4721709d74 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 19 Jul 2012 02:29:52 +0200
+Subject: fbdev: sh_mobile_lcdc: Fix overlay registers update during pan
+ operation
+
+Updating overlay registers require switching to overlay update mode.
+This was correctly done when configuring the overlay format and size,
+but not when updating the base address registers during pan operation.
+Fix it.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit 8be7c66995bf06769dc4c5f7a62f3cd62a627e7e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index d82c1de..a502709 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -1539,9 +1539,14 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
+               ovl->base_addr_c = base_addr_c;
+       }
++      lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
++
+       lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y);
+       lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c);
++      lcdc_write(ovl->channel->lcdc, LDBCR,
++                 LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
++
+       ovl->pan_offset = pan_offset;
+       return 0;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch b/patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch
new file mode 100644 (file)
index 0000000..d72596f
--- /dev/null
@@ -0,0 +1,241 @@
+From 896e926e26d250d1b5397c5a39d12fb25c6928b5 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 15 Mar 2012 18:15:37 +0100
+Subject: fbdev: sh_mobile_lcdc: Fix pan offset computation in YUV mode
+
+The chroma plane offset in memory is equal to the luma plane maximum
+size. Fix offset computations.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+(cherry picked from commit a4aa25f6e7885a42c90fe5f0a965403df6cbc943)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 110 ++++++++++++++++++---------------------
+ drivers/video/sh_mobile_lcdcfb.h |   3 +-
+ 2 files changed, 54 insertions(+), 59 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index a502709..8cb653b 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -161,7 +161,7 @@ enum sh_mobile_lcdc_overlay_mode {
+  * @dma_handle: Frame buffer DMA address
+  * @base_addr_y: Overlay base address (RGB or luma component)
+  * @base_addr_c: Overlay base address (chroma component)
+- * @pan_offset: Current pan offset in bytes
++ * @pan_y_offset: Panning linear offset in bytes (luma component)
+  * @format: Current pixelf format
+  * @xres: Horizontal visible resolution
+  * @xres_virtual: Horizontal total resolution
+@@ -191,7 +191,7 @@ struct sh_mobile_lcdc_overlay {
+       dma_addr_t dma_handle;
+       unsigned long base_addr_y;
+       unsigned long base_addr_c;
+-      unsigned long pan_offset;
++      unsigned long pan_y_offset;
+       const struct sh_mobile_lcdc_format_info *format;
+       unsigned int xres;
+@@ -873,8 +873,8 @@ static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
+       }
+       ovl->base_addr_y = ovl->dma_handle;
+-      ovl->base_addr_c = ovl->base_addr_y + ovl->xres
+-                         * ovl->yres_virtual;
++      ovl->base_addr_c = ovl->dma_handle
++                       + ovl->xres_virtual * ovl->yres_virtual;
+       switch (ovl->mode) {
+       case LCDC_OVERLAY_BLEND:
+@@ -1111,7 +1111,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
+                       continue;
+               ch->base_addr_y = ch->dma_handle;
+-              ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
++              ch->base_addr_c = ch->dma_handle
++                              + ch->xres_virtual * ch->yres_virtual;
+               ch->line_size = ch->pitch;
+               /* Enable MERAM if possible. */
+@@ -1505,39 +1506,36 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
+       struct sh_mobile_lcdc_overlay *ovl = info->par;
+       unsigned long base_addr_y;
+       unsigned long base_addr_c;
+-      unsigned long pan_offset;
++      unsigned long y_offset;
+       unsigned long c_offset;
+-      if (!ovl->format->yuv)
+-              pan_offset = var->yoffset * ovl->pitch
+-                         + var->xoffset * (ovl->format->bpp / 8);
+-      else
+-              pan_offset = var->yoffset * ovl->pitch + var->xoffset;
++      if (!ovl->format->yuv) {
++              y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset)
++                       * ovl->format->bpp / 8;
++              c_offset = 0;
++      } else {
++              unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1;
++              unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1;
++
++              y_offset = var->yoffset * ovl->xres_virtual + var->xoffset;
++              c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub
++                       + var->xoffset * 2 / xsub;
++      }
+-      if (pan_offset == ovl->pan_offset)
+-              return 0;       /* No change, do nothing */
++      /* If the Y offset hasn't changed, the C offset hasn't either. There's
++       * nothing to do in that case.
++       */
++      if (y_offset == ovl->pan_y_offset)
++              return 0;
+       /* Set the source address for the next refresh */
+-      base_addr_y = ovl->dma_handle + pan_offset;
++      base_addr_y = ovl->dma_handle + y_offset;
++      base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual
++                  + c_offset;
+       ovl->base_addr_y = base_addr_y;
+-      ovl->base_addr_c = base_addr_y;
+-
+-      if (ovl->format->yuv) {
+-              /* Set Y offset */
+-              c_offset = var->yoffset * ovl->pitch
+-                       * (ovl->format->bpp - 8) / 8;
+-              base_addr_c = ovl->dma_handle
+-                          + ovl->xres * ovl->yres_virtual
+-                          + c_offset;
+-              /* Set X offset */
+-              if (ovl->format->fourcc == V4L2_PIX_FMT_NV24)
+-                      base_addr_c += 2 * var->xoffset;
+-              else
+-                      base_addr_c += var->xoffset;
+-
+-              ovl->base_addr_c = base_addr_c;
+-      }
++      ovl->base_addr_c = base_addr_c;
++      ovl->pan_y_offset = y_offset;
+       lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index));
+@@ -1547,8 +1545,6 @@ static int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var,
+       lcdc_write(ovl->channel->lcdc, LDBCR,
+                  LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index));
+-      ovl->pan_offset = pan_offset;
+-
+       return 0;
+ }
+@@ -1814,35 +1810,33 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
+       struct sh_mobile_lcdc_chan *ch = info->par;
+       struct sh_mobile_lcdc_priv *priv = ch->lcdc;
+       unsigned long ldrcntr;
+-      unsigned long new_pan_offset;
+-      unsigned long base_addr_y, base_addr_c = 0;
++      unsigned long base_addr_y, base_addr_c;
++      unsigned long y_offset;
+       unsigned long c_offset;
+-      if (!ch->format->yuv)
+-              new_pan_offset = var->yoffset * ch->pitch
+-                             + var->xoffset * (ch->format->bpp / 8);
+-      else
+-              new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
++      if (!ch->format->yuv) {
++              y_offset = (var->yoffset * ch->xres_virtual + var->xoffset)
++                       * ch->format->bpp / 8;
++              c_offset = 0;
++      } else {
++              unsigned int xsub = ch->format->bpp < 24 ? 2 : 1;
++              unsigned int ysub = ch->format->bpp < 16 ? 2 : 1;
+-      if (new_pan_offset == ch->pan_offset)
+-              return 0;       /* No change, do nothing */
++              y_offset = var->yoffset * ch->xres_virtual + var->xoffset;
++              c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub
++                       + var->xoffset * 2 / xsub;
++      }
+-      ldrcntr = lcdc_read(priv, _LDRCNTR);
++      /* If the Y offset hasn't changed, the C offset hasn't either. There's
++       * nothing to do in that case.
++       */
++      if (y_offset == ch->pan_y_offset)
++              return 0;
+       /* Set the source address for the next refresh */
+-      base_addr_y = ch->dma_handle + new_pan_offset;
+-      if (ch->format->yuv) {
+-              /* Set y offset */
+-              c_offset = var->yoffset * ch->pitch
+-                       * (ch->format->bpp - 8) / 8;
+-              base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
+-                          + c_offset;
+-              /* Set x offset */
+-              if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
+-                      base_addr_c += 2 * var->xoffset;
+-              else
+-                      base_addr_c += var->xoffset;
+-      }
++      base_addr_y = ch->dma_handle + y_offset;
++      base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
++                  + c_offset;
+       if (ch->cache)
+               sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
+@@ -1851,17 +1845,18 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
+       ch->base_addr_y = base_addr_y;
+       ch->base_addr_c = base_addr_c;
++      ch->pan_y_offset = y_offset;
+       lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
+       if (ch->format->yuv)
+               lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
++      ldrcntr = lcdc_read(priv, _LDRCNTR);
+       if (lcdc_chan_is_sublcd(ch))
+               lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
+       else
+               lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS);
+-      ch->pan_offset = new_pan_offset;
+       sh_mobile_lcdc_deferred_io_touch(info);
+@@ -2734,7 +2729,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
+               }
+               init_waitqueue_head(&ch->frame_end_wait);
+               init_completion(&ch->vsync_completion);
+-              ch->pan_offset = 0;
+               /* probe the backlight is there is one defined */
+               if (ch->cfg->bl_info.max_brightness)
+diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
+index e53cd11..0f92f65 100644
+--- a/drivers/video/sh_mobile_lcdcfb.h
++++ b/drivers/video/sh_mobile_lcdcfb.h
+@@ -47,6 +47,7 @@ struct sh_mobile_lcdc_entity {
+ /*
+  * struct sh_mobile_lcdc_chan - LCDC display channel
+  *
++ * @pan_y_offset: Panning linear offset in bytes (luma component)
+  * @base_addr_y: Frame buffer viewport base address (luma component)
+  * @base_addr_c: Frame buffer viewport base address (chroma component)
+  * @pitch: Frame buffer line pitch
+@@ -68,7 +69,7 @@ struct sh_mobile_lcdc_chan {
+       unsigned long fb_size;
+       dma_addr_t dma_handle;
+-      unsigned long pan_offset;
++      unsigned long pan_y_offset;
+       unsigned long frame_end;
+       wait_queue_head_t frame_end_wait;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch b/patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch
new file mode 100644 (file)
index 0000000..2662cba
--- /dev/null
@@ -0,0 +1,55 @@
+From 633f3cd2b85466e5744a86cbe888d78f30302083 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Thu, 26 Jul 2012 14:36:55 +0200
+Subject: fbdev: sh_mobile_lcdc: Fix vertical panning step
+
+Commit 15dede882e564601947f2ce4b647742c0351be6d added support for
+horizontal panning but accidentally computes the Y pan step value
+incorrectly for NV12/21 and NV16/61 formats. Fix this.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
+(cherry picked from commit ac33a207b13a70bbca6e58094e28bd92b9fc1ff3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/video/sh_mobile_lcdcfb.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
+index 8cb653b..699487c 100644
+--- a/drivers/video/sh_mobile_lcdcfb.c
++++ b/drivers/video/sh_mobile_lcdcfb.c
+@@ -1716,11 +1716,11 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+       switch (ovl->format->fourcc) {
+-      case V4L2_PIX_FMT_NV16:
+-      case V4L2_PIX_FMT_NV61:
+-              info->fix.ypanstep = 2;
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
++              info->fix.ypanstep = 2;
++      case V4L2_PIX_FMT_NV16:
++      case V4L2_PIX_FMT_NV61:
+               info->fix.xpanstep = 2;
+       }
+@@ -2215,11 +2215,11 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+       switch (ch->format->fourcc) {
+-      case V4L2_PIX_FMT_NV16:
+-      case V4L2_PIX_FMT_NV61:
+-              info->fix.ypanstep = 2;
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
++              info->fix.ypanstep = 2;
++      case V4L2_PIX_FMT_NV16:
++      case V4L2_PIX_FMT_NV61:
+               info->fix.xpanstep = 2;
+       }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch b/patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch
new file mode 100644 (file)
index 0000000..e33085a
--- /dev/null
@@ -0,0 +1,83 @@
+From 18ed06783eaf892967a3260bd9056a4aba81bfa0 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 6 Apr 2012 01:28:14 -0700
+Subject: ARM: mach-shmobile: r8a7740: add gpio_irq support
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 9f6b78223b7b49bc06d2e84b15d48f02206ec3c3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/pfc-r8a7740.c | 39 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
+index a4fff69..670fe18 100644
+--- a/arch/arm/mach-shmobile/pfc-r8a7740.c
++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
+@@ -22,6 +22,7 @@
+ #include <linux/kernel.h>
+ #include <linux/gpio.h>
+ #include <mach/r8a7740.h>
++#include <mach/irqs.h>
+ #define CPU_ALL_PORT(fn, pfx, sfx)                                    \
+       PORT_10(fn, pfx, sfx),          PORT_90(fn, pfx, sfx),          \
+@@ -2527,6 +2528,41 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
+       { },
+ };
++static struct pinmux_irq pinmux_irqs[] = {
++      PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0,   PORT13_FN0),   /* IRQ0A */
++      PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0),                /* IRQ1A */
++      PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0,  PORT12_FN0),   /* IRQ2A */
++      PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0,  PORT14_FN0),   /* IRQ3A */
++      PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0,  PORT172_FN0),  /* IRQ4A */
++      PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0,   PORT1_FN0),    /* IRQ5A */
++      PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0),  /* IRQ6A */
++      PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0),  /* IRQ7A */
++      PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0),               /* IRQ8A */
++      PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0),  /* IRQ9A */
++      PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0),                /* IRQ10A */
++      PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0),               /* IRQ11A */
++      PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0,  PORT97_FN0),   /* IRQ12A */
++      PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0,  PORT98_FN0),   /* IRQ13A */
++      PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0,  PORT99_FN0),   /* IRQ14A */
++      PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0,  PORT100_FN0),  /* IRQ15A */
++      PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0,  PORT211_FN0),  /* IRQ16A */
++      PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0),                /* IRQ17A */
++      PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0),                /* IRQ18A */
++      PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0),                /* IRQ19A */
++      PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0),                /* IRQ20A */
++      PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0),               /* IRQ21A */
++      PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0),                /* IRQ22A */
++      PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0),                /* IRQ23A */
++      PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0),               /* IRQ24A */
++      PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0),                /* IRQ25A */
++      PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0,  PORT81_FN0),   /* IRQ26A */
++      PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0,  PORT168_FN0),  /* IRQ27A */
++      PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0,  PORT169_FN0),  /* IRQ28A */
++      PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0,  PORT170_FN0),  /* IRQ29A */
++      PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0,  PORT171_FN0),  /* IRQ30A */
++      PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0,  PORT167_FN0),  /* IRQ31A */
++};
++
+ static struct pinmux_info r8a7740_pinmux_info = {
+       .name           = "r8a7740_pfc",
+       .reserved_id    = PINMUX_RESERVED,
+@@ -2554,6 +2590,9 @@ static struct pinmux_info r8a7740_pinmux_info = {
+       .gpio_data      = pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(pinmux_data),
++
++      .gpio_irq       = pinmux_irqs,
++      .gpio_irq_size  = ARRAY_SIZE(pinmux_irqs),
+ };
+ void r8a7740_pinmux_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch b/patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch
new file mode 100644 (file)
index 0000000..b750ea7
--- /dev/null
@@ -0,0 +1,48 @@
+From 46dccabaa06e08bb7b9b2ac4b46f784b8afba7f0 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 13 Apr 2012 02:41:06 -0700
+Subject: ARM: mach-shmobile: r8a7740: cleanup I2C workaround method
+
+Current workaround of I2C on r8a7740 used mdelay(),
+but it was an overkill.
+This patch cleans up the workaround delay.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 4228716c87f7915410721952bad3e568fb5f2431)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/setup-r8a7740.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -368,19 +368,19 @@ static void r8a7740_i2c_workaround(struc
+       i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
+       i2c_read(reg, ICSTART); /* dummy read */
+-      mdelay(100);
++      udelay(10);
+       i2c_write(reg, ICCR, 0x01);
+-      i2c_read(reg, ICCR);
+       i2c_write(reg, ICSTART, 0x00);
+-      i2c_read(reg, ICSTART);
++
++      udelay(10);
+       i2c_write(reg, ICCR, 0x10);
+-      mdelay(100);
++      udelay(10);
+       i2c_write(reg, ICCR, 0x00);
+-      mdelay(100);
++      udelay(10);
+       i2c_write(reg, ICCR, 0x10);
+-      mdelay(100);
++      udelay(10);
+       iounmap(reg);
+ }
diff --git a/patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch b/patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch
new file mode 100644 (file)
index 0000000..474b8fc
--- /dev/null
@@ -0,0 +1,47 @@
+From 9b696a8092bedbd771c4b8e6a8c12edbd6881444 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 1 Apr 2012 18:46:09 -0700
+Subject: ARM: mach-shmobile: clock-r8a7740: add FSI clock
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 7ee8948d158946e52ea21562f2ceef268439f36e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index 99c4d74..b6fa1b7 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -257,7 +257,7 @@ enum {
+       MSTP222,
+       MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+-      MSTP329, MSTP323,
++      MSTP329, MSTP328, MSTP323,
+       MSTP_NR
+ };
+@@ -280,6 +280,7 @@ static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2,  0, 0), /* SCIFA4 */
+       [MSTP329] = SH_CLK_MSTP32(&r_clk,               SMSTPCR3, 29, 0), /* CMT10 */
++      [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 28, 0), /* FSI */
+       [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
+ };
+@@ -334,6 +335,7 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("sh-sci.6",               &mstp_clks[MSTP230]),
+       CLKDEV_DEV_ID("sh_cmt.10",              &mstp_clks[MSTP329]),
++      CLKDEV_DEV_ID("sh_fsi2",                &mstp_clks[MSTP328]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.1",        &mstp_clks[MSTP323]),
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch b/patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch
new file mode 100644 (file)
index 0000000..3e72e0b
--- /dev/null
@@ -0,0 +1,208 @@
+From a747b7aa896100a6b9dd0dc0828c27ef344f381c Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:07:47 -0700
+Subject: ARM: mach-shmobile: clock-r8a7740: add USB clock
+
+R8A7740 USB needs many clocks for workaround,
+and it has confusing name "usb24s" and "usb24".
+This "usb24s" will be used by other clocks.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit fcca3f0f007d97f095a3ebe8f209021b517309d2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 118 ++++++++++++++++++++++++++++++++-
+ 1 file changed, 116 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index b6fa1b7..b9b1d73 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -47,6 +47,7 @@
+ #define PLLC01CR      0xe6150028
+ #define SUBCKCR               0xe6150080
++#define USBCKCR               0xe615008c
+ #define MSTPSR0               0xe6150030
+ #define MSTPSR1               0xe6150038
+@@ -181,6 +182,100 @@ static struct clk pllc1_div2_clk = {
+       .parent         = &pllc1_clk,
+ };
++/* USB clock */
++static struct clk *usb24s_parents[] = {
++      [0] = &system_clk,
++      [1] = &extal2_clk
++};
++
++static unsigned long usb24s_recalc(struct clk *clk)
++{
++      return clk->parent->rate;
++};
++
++static int usb24s_enable(struct clk *clk)
++{
++      __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
++
++      return 0;
++}
++
++static void usb24s_disable(struct clk *clk)
++{
++      __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
++}
++
++static int usb24s_set_parent(struct clk *clk, struct clk *parent)
++{
++      int i, ret;
++      u32 val;
++
++      if (!clk->parent_table || !clk->parent_num)
++              return -EINVAL;
++
++      /* Search the parent */
++      for (i = 0; i < clk->parent_num; i++)
++              if (clk->parent_table[i] == parent)
++                      break;
++
++      if (i == clk->parent_num)
++              return -ENODEV;
++
++      ret = clk_reparent(clk, parent);
++      if (ret < 0)
++              return ret;
++
++      val = __raw_readl(USBCKCR);
++      val &= ~(1 << 7);
++      val |= i << 7;
++      __raw_writel(val, USBCKCR);
++
++      return 0;
++}
++
++static struct sh_clk_ops usb24s_clk_ops = {
++      .recalc         = usb24s_recalc,
++      .enable         = usb24s_enable,
++      .disable        = usb24s_disable,
++      .set_parent     = usb24s_set_parent,
++};
++
++static struct clk usb24s_clk = {
++      .ops            = &usb24s_clk_ops,
++      .parent_table   = usb24s_parents,
++      .parent_num     = ARRAY_SIZE(usb24s_parents),
++      .parent         = &system_clk,
++};
++
++static unsigned long usb24_recalc(struct clk *clk)
++{
++      return clk->parent->rate /
++              ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
++};
++
++static int usb24_set_rate(struct clk *clk, unsigned long rate)
++{
++      u32 val;
++
++      /* closer to which ? parent->rate or parent->rate/2 */
++      val = __raw_readl(USBCKCR);
++      val &= ~(1 << 6);
++      val |= (rate > (clk->parent->rate / 4) * 3) << 6;
++      __raw_writel(val, USBCKCR);
++
++      return 0;
++}
++
++static struct sh_clk_ops usb24_clk_ops = {
++      .recalc         = usb24_recalc,
++      .set_rate       = usb24_set_rate,
++};
++
++static struct clk usb24_clk = {
++      .ops            = &usb24_clk_ops,
++      .parent         = &usb24s_clk,
++};
++
+ struct clk *main_clks[] = {
+       &extalr_clk,
+       &extal1_clk,
+@@ -196,6 +291,8 @@ struct clk *main_clks[] = {
+       &pllc0_clk,
+       &pllc1_clk,
+       &pllc1_div2_clk,
++      &usb24s_clk,
++      &usb24_clk,
+ };
+ static void div4_kick(struct clk *clk)
+@@ -223,7 +320,7 @@ static struct clk_div4_table div4_table = {
+ enum {
+       DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
+-      DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
++      DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
+       DIV4_NR
+ };
+@@ -234,6 +331,7 @@ struct clk div4_clks[DIV4_NR] = {
+       [DIV4_M1]       = SH_CLK_DIV4(&pllc1_clk, FRQCRA,  4, 0x6fff, CLK_ENABLE_ON_INIT),
+       [DIV4_HP]       = SH_CLK_DIV4(&pllc1_clk, FRQCRB,  4, 0x6fff, 0),
+       [DIV4_HPP]      = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
++      [DIV4_USBP]     = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
+       [DIV4_S]        = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
+       [DIV4_ZB]       = SH_CLK_DIV4(&pllc1_clk, FRQCRC,  8, 0x6fff, 0),
+       [DIV4_M3]       = SH_CLK_DIV4(&pllc1_clk, FRQCRC,  4, 0x6fff, 0),
+@@ -257,7 +355,9 @@ enum {
+       MSTP222,
+       MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+-      MSTP329, MSTP328, MSTP323,
++      MSTP329, MSTP328, MSTP323, MSTP320,
++
++      MSTP416, MSTP407, MSTP406,
+       MSTP_NR
+ };
+@@ -282,6 +382,11 @@ static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP329] = SH_CLK_MSTP32(&r_clk,               SMSTPCR3, 29, 0), /* CMT10 */
+       [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 28, 0), /* FSI */
+       [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
++      [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 20, 0), /* USBF */
++
++      [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 16, 0), /* USBHOST */
++      [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4,  7, 0), /* USB-Func */
++      [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4,  6, 0), /* USB Phy */
+ };
+ static struct clk_lookup lookups[] = {
+@@ -300,6 +405,7 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_CON_ID("pllc0_clk",              &pllc0_clk),
+       CLKDEV_CON_ID("pllc1_clk",              &pllc1_clk),
+       CLKDEV_CON_ID("pllc1_div2_clk",         &pllc1_div2_clk),
++      CLKDEV_CON_ID("usb24s",                 &usb24s_clk),
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("i_clk",                  &div4_clks[DIV4_I]),
+@@ -337,6 +443,14 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("sh_cmt.10",              &mstp_clks[MSTP329]),
+       CLKDEV_DEV_ID("sh_fsi2",                &mstp_clks[MSTP328]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.1",        &mstp_clks[MSTP323]),
++      CLKDEV_DEV_ID("renesas_usbhs",          &mstp_clks[MSTP320]),
++
++      /* ICK */
++      CLKDEV_ICK_ID("host",   "renesas_usbhs",        &mstp_clks[MSTP416]),
++      CLKDEV_ICK_ID("func",   "renesas_usbhs",        &mstp_clks[MSTP407]),
++      CLKDEV_ICK_ID("phy",    "renesas_usbhs",        &mstp_clks[MSTP406]),
++      CLKDEV_ICK_ID("pci",    "renesas_usbhs",        &div4_clks[DIV4_USBP]),
++      CLKDEV_ICK_ID("usb24",  "renesas_usbhs",        &usb24_clk),
+ };
+ void __init r8a7740_clock_init(u8 md_ck)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch b/patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch
new file mode 100644 (file)
index 0000000..86c4379
--- /dev/null
@@ -0,0 +1,57 @@
+From df046bb39c81fb474109a85f21b35345df0b9441 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:08:11 -0700
+Subject: ARM: mach-shmobile: clock-r8a7740: add SDHI clock
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 19ad322de262c810463aeb8769c66474d8b68210)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index b9b1d73..86f7147 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -356,8 +356,9 @@ enum {
+       MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+       MSTP329, MSTP328, MSTP323, MSTP320,
++      MSTP314, MSTP313,
+-      MSTP416, MSTP407, MSTP406,
++      MSTP416, MSTP415, MSTP407, MSTP406,
+       MSTP_NR
+ };
+@@ -383,8 +384,11 @@ static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 28, 0), /* FSI */
+       [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
+       [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 20, 0), /* USBF */
++      [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 14, 0), /* SDHI0 */
++      [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 13, 0), /* SDHI1 */
+       [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 16, 0), /* USBHOST */
++      [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 15, 0), /* SDHI2 */
+       [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4,  7, 0), /* USB-Func */
+       [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4,  6, 0), /* USB Phy */
+ };
+@@ -444,6 +448,10 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("sh_fsi2",                &mstp_clks[MSTP328]),
+       CLKDEV_DEV_ID("i2c-sh_mobile.1",        &mstp_clks[MSTP323]),
+       CLKDEV_DEV_ID("renesas_usbhs",          &mstp_clks[MSTP320]),
++      CLKDEV_DEV_ID("sh_mobile_sdhi.0",       &mstp_clks[MSTP314]),
++      CLKDEV_DEV_ID("sh_mobile_sdhi.1",       &mstp_clks[MSTP313]),
++
++      CLKDEV_DEV_ID("sh_mobile_sdhi.2",       &mstp_clks[MSTP415]),
+       /* ICK */
+       CLKDEV_ICK_ID("host",   "renesas_usbhs",        &mstp_clks[MSTP416]),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch b/patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch
new file mode 100644 (file)
index 0000000..e0c1a38
--- /dev/null
@@ -0,0 +1,48 @@
+From 3b4d84a8de5adaa8ec1b4db8b3409fc75340bd7f Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:08:29 -0700
+Subject: ARM: mach-shmobile: clock-r8a7740: add MMCIF clock
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit f2c2d7e9210c4a82336b208adc88630cd0e77f57)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index 86f7147..89a2f9d 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -356,7 +356,7 @@ enum {
+       MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+       MSTP329, MSTP328, MSTP323, MSTP320,
+-      MSTP314, MSTP313,
++      MSTP314, MSTP313, MSTP312,
+       MSTP416, MSTP415, MSTP407, MSTP406,
+@@ -386,6 +386,7 @@ static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 20, 0), /* USBF */
+       [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 14, 0), /* SDHI0 */
+       [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 13, 0), /* SDHI1 */
++      [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 12, 0), /* MMC */
+       [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 16, 0), /* USBHOST */
+       [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 15, 0), /* SDHI2 */
+@@ -450,6 +451,7 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("renesas_usbhs",          &mstp_clks[MSTP320]),
+       CLKDEV_DEV_ID("sh_mobile_sdhi.0",       &mstp_clks[MSTP314]),
+       CLKDEV_DEV_ID("sh_mobile_sdhi.1",       &mstp_clks[MSTP313]),
++      CLKDEV_DEV_ID("sh_mmcif",               &mstp_clks[MSTP312]),
+       CLKDEV_DEV_ID("sh_mobile_sdhi.2",       &mstp_clks[MSTP415]),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch b/patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch
new file mode 100644 (file)
index 0000000..db69918
--- /dev/null
@@ -0,0 +1,48 @@
+From 02b6fac5cb1a97bb8851976abdd8a229a852907f Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 6 May 2012 18:12:41 -0700
+Subject: ARM: mach-shmobile: clock-r8a7740: use followparent_recalc on usb24s
+
+If the clocks is always same value as the parent clock,
+we can use followparent_recalc() for .recalc
+
+Reported-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit c8241085e8606a14ef48e6d99556133c48aaddaf)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index 89a2f9d..81b54a6 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -188,11 +188,6 @@ static struct clk *usb24s_parents[] = {
+       [1] = &extal2_clk
+ };
+-static unsigned long usb24s_recalc(struct clk *clk)
+-{
+-      return clk->parent->rate;
+-};
+-
+ static int usb24s_enable(struct clk *clk)
+ {
+       __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
+@@ -234,7 +229,7 @@ static int usb24s_set_parent(struct clk *clk, struct clk *parent)
+ }
+ static struct sh_clk_ops usb24s_clk_ops = {
+-      .recalc         = usb24s_recalc,
++      .recalc         = followparent_recalc,
+       .enable         = usb24s_enable,
+       .disable        = usb24s_disable,
+       .set_parent     = usb24s_set_parent,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch b/patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch
new file mode 100644 (file)
index 0000000..f40a999
--- /dev/null
@@ -0,0 +1,232 @@
+From 6dbc9d7efd3ddd2dbc0a1b95b3a237173df5e1d8 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 6 Apr 2012 01:28:59 -0700
+Subject: ARM: mach-shmobile: add armadillo800eva board support.
+
+This adds very basic armadillo800eva board (R-Mobile A1) support
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 4d22e564ca7bb5c7340c782aedd93bed99f3fb41)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Kconfig                 |  11 +-
+ arch/arm/mach-shmobile/Makefile                |   1 +
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 154 +++++++++++++++++++++++++
+ 3 files changed, 164 insertions(+), 2 deletions(-)
+ create mode 100644 arch/arm/mach-shmobile/board-armadillo800eva.c
+
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index 2cda0c2..799e996 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -95,6 +95,11 @@ config MACH_BONITO
+       select ARCH_REQUIRE_GPIOLIB
+       depends on ARCH_R8A7740
++config MACH_ARMADILLO800EVA
++      bool "Armadillo-800 EVA board"
++      depends on ARCH_R8A7740
++      select ARCH_REQUIRE_GPIOLIB
++
+ config MACH_MARZEN
+       bool "MARZEN board"
+       depends on ARCH_R8A7779
+@@ -112,7 +117,8 @@ config MEMORY_START
+       hex "Physical memory start address"
+       default "0x50000000" if MACH_G3EVM
+       default "0x40000000" if MACH_G4EVM || MACH_AP4EVB || MACH_AG5EVM || \
+-                              MACH_MACKEREL || MACH_BONITO
++                              MACH_MACKEREL || MACH_BONITO || \
++                              MACH_ARMADILLO800EVA
+       default "0x41000000" if MACH_KOTA2
+       default "0x00000000"
+       ---help---
+@@ -124,7 +130,8 @@ config MEMORY_SIZE
+       hex "Physical memory size"
+       default "0x08000000" if MACH_G3EVM
+       default "0x08000000" if MACH_G4EVM
+-      default "0x20000000" if MACH_AG5EVM || MACH_BONITO
++      default "0x20000000" if MACH_AG5EVM || MACH_BONITO || \
++                              MACH_ARMADILLO800EVA
+       default "0x1e000000" if MACH_KOTA2
+       default "0x10000000" if MACH_AP4EVB || MACH_MACKEREL
+       default "0x04000000"
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index 53846a1e..b39033b 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -50,6 +50,7 @@ obj-$(CONFIG_MACH_MACKEREL)  += board-mackerel.o
+ obj-$(CONFIG_MACH_KOTA2)      += board-kota2.o
+ obj-$(CONFIG_MACH_BONITO)     += board-bonito.o
+ obj-$(CONFIG_MACH_MARZEN)     += board-marzen.o
++obj-$(CONFIG_MACH_ARMADILLO800EVA)    += board-armadillo800eva.o
+ # Framework support
+ obj-$(CONFIG_SMP)             += $(smp-y)
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+new file mode 100644
+index 0000000..28bc259
+--- /dev/null
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -0,0 +1,154 @@
++/*
++ * armadillo 800 eva board support
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ *
++ */
++
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/gpio.h>
++#include <mach/common.h>
++#include <mach/irqs.h>
++#include <asm/page.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/time.h>
++#include <asm/hardware/cache-l2x0.h>
++#include <mach/r8a7740.h>
++
++/*
++ * CON1               Camera Module
++ * CON2               Extension Bus
++ * CON3               HDMI Output
++ * CON4               Composite Video Output
++ * CON5               H-UDI JTAG
++ * CON6               ARM JTAG
++ * CON7               SD1
++ * CON8               SD2
++ * CON9               RTC BackUp
++ * CON10      Monaural Mic Input
++ * CON11      Stereo Headphone Output
++ * CON12      Audio Line Output(L)
++ * CON13      Audio Line Output(R)
++ * CON14      AWL13 Module
++ * CON15      Extension
++ * CON16      LCD1
++ * CON17      LCD2
++ * CON19      Power Input
++ * CON20      USB1
++ * CON21      USB2
++ * CON22      Serial
++ * CON23      LAN
++ * CON24      USB3
++ * LED1               Camera LED(Yellow)
++ * LED2               Power LED (Green)
++ * ED3-LED6   User LED(Yellow)
++ * LED7               LAN link LED(Green)
++ * LED8               LAN activity LED(Yellow)
++ */
++
++/*
++ * DipSwitch
++ *
++ *                    SW1
++ *
++ * -12345678-+---------------+----------------------------
++ *  1        | boot          | hermit
++ *  0        | boot          | OS auto boot
++ * -12345678-+---------------+----------------------------
++ *   00      | boot device   | eMMC
++ *   10      | boot device   | SDHI0 (CON7)
++ *   01      | boot device   | -
++ *   11      | boot device   | Extension Buss (CS0)
++ * -12345678-+---------------+----------------------------
++ *     0     | Extension Bus | D8-D15 disable, eMMC enable
++ *     1     | Extension Bus | D8-D15 enable,  eMMC disable
++ * -12345678-+---------------+----------------------------
++ *      0    | SDHI1         | COM8 enable,  COM14 disable
++ *      1    | SDHI1         | COM8 enable,  COM14 disable
++ * -12345678-+---------------+----------------------------
++ *        00 | JTAG          | SH-X2
++ *        10 | JTAG          | ARM
++ *        01 | JTAG          | -
++ *        11 | JTAG          | Boundary Scan
++ *-----------+---------------+----------------------------
++ */
++
++/*
++ * board devices
++ */
++static struct platform_device *eva_devices[] __initdata = {
++};
++
++/*
++ * board init
++ */
++static void __init eva_init(void)
++{
++      r8a7740_pinmux_init();
++
++      /* SCIFA1 */
++      gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
++      gpio_request(GPIO_FN_SCIFA1_TXD, NULL);
++
++#ifdef CONFIG_CACHE_L2X0
++      /* Early BRESP enable, Shared attribute override enable, 32K*8way */
++      l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
++#endif
++
++      r8a7740_add_standard_devices();
++
++      platform_add_devices(eva_devices,
++                           ARRAY_SIZE(eva_devices));
++}
++
++static void __init eva_earlytimer_init(void)
++{
++      struct clk *xtal1;
++
++      r8a7740_clock_init(MD_CK0 | MD_CK2);
++
++      xtal1 = clk_get(NULL, "extal1");
++      if (!IS_ERR(xtal1)) {
++              /* armadillo 800 eva extal1 is 24MHz */
++              clk_set_rate(xtal1, 24000000);
++              clk_put(xtal1);
++      }
++
++      shmobile_earlytimer_init();
++}
++
++static void __init eva_add_early_devices(void)
++{
++      r8a7740_add_early_devices();
++
++      /* override timer setup with board-specific code */
++      shmobile_timer.init = eva_earlytimer_init;
++}
++
++MACHINE_START(ARMADILLO800EVA, "armadillo800eva")
++      .map_io         = r8a7740_map_io,
++      .init_early     = eva_add_early_devices,
++      .init_irq       = r8a7740_init_irq,
++      .handle_irq     = shmobile_handle_irq_intc,
++      .init_machine   = eva_init,
++      .timer          = &shmobile_timer,
++MACHINE_END
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch b/patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch
new file mode 100644 (file)
index 0000000..2ee6126
--- /dev/null
@@ -0,0 +1,169 @@
+From 90660861a7540365f6c7c4412f30a74e4a7d9dd3 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 6 Apr 2012 01:29:36 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add defconfig
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit edc4910171f332466fa8f164de3d2395d80163db)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/configs/armadillo800eva_defconfig | 143 +++++++++++++++++++++++++++++
+ 1 file changed, 143 insertions(+)
+ create mode 100644 arch/arm/configs/armadillo800eva_defconfig
+
+diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
+new file mode 100644
+index 0000000..0d20749
+--- /dev/null
++++ b/arch/arm/configs/armadillo800eva_defconfig
+@@ -0,0 +1,143 @@
++CONFIG_EXPERIMENTAL=y
++CONFIG_SYSVIPC=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_UTS_NS is not set
++# CONFIG_IPC_NS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_SLAB=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_ARCH_SHMOBILE=y
++CONFIG_ARCH_R8A7740=y
++CONFIG_MACH_ARMADILLO800EVA=y
++# CONFIG_SH_TIMER_TMU is not set
++# CONFIG_ARM_THUMB is not set
++CONFIG_CPU_BPREDICT_DISABLE=y
++# CONFIG_CACHE_L2X0 is not set
++CONFIG_ARM_ERRATA_430973=y
++CONFIG_ARM_ERRATA_458693=y
++CONFIG_ARM_ERRATA_460075=y
++CONFIG_ARM_ERRATA_720789=y
++CONFIG_ARM_ERRATA_743622=y
++CONFIG_ARM_ERRATA_751472=y
++CONFIG_ARM_ERRATA_754322=y
++CONFIG_AEABI=y
++# CONFIG_OABI_COMPAT is not set
++CONFIG_FORCE_MAX_ZONEORDER=13
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
++CONFIG_CMDLINE_FORCE=y
++CONFIG_KEXEC=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++# CONFIG_SUSPEND is not set
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_WIRELESS is not set
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_SCSI=y
++CONFIG_BLK_DEV_SD=y
++CONFIG_MD=y
++CONFIG_BLK_DEV_DM=y
++CONFIG_NETDEVICES=y
++# CONFIG_NET_VENDOR_BROADCOM is not set
++# CONFIG_NET_VENDOR_CHELSIO is not set
++# CONFIG_NET_VENDOR_FARADAY is not set
++# CONFIG_NET_VENDOR_INTEL is not set
++# CONFIG_NET_VENDOR_MARVELL is not set
++# CONFIG_NET_VENDOR_MICREL is not set
++# CONFIG_NET_VENDOR_NATSEMI is not set
++CONFIG_SH_ETH=y
++# CONFIG_NET_VENDOR_SEEQ is not set
++# CONFIG_NET_VENDOR_STMICRO is not set
++# CONFIG_WLAN is not set
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_KEYBOARD_ATKBD is not set
++CONFIG_KEYBOARD_GPIO=y
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ST1232=y
++# CONFIG_SERIO is not set
++# CONFIG_LEGACY_PTYS is not set
++CONFIG_SERIAL_SH_SCI=y
++CONFIG_SERIAL_SH_SCI_NR_UARTS=8
++CONFIG_SERIAL_SH_SCI_CONSOLE=y
++# CONFIG_HW_RANDOM is not set
++CONFIG_I2C=y
++CONFIG_I2C_SH_MOBILE=y
++# CONFIG_HWMON is not set
++CONFIG_FB=y
++CONFIG_FB_MODE_HELPERS=y
++CONFIG_FB_SH_MOBILE_LCDC=y
++CONFIG_LCD_CLASS_DEVICE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_SOUND=y
++CONFIG_SND=y
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_SND_DRIVERS is not set
++# CONFIG_SND_ARM is not set
++CONFIG_SND_SOC=y
++CONFIG_SND_SOC_SH4_FSI=y
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_UIO=y
++CONFIG_UIO_PDRV_GENIRQ=y
++# CONFIG_DNOTIFY is not set
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_TMPFS=y
++# CONFIG_MISC_FILESYSTEMS is not set
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_NFS_V4_1=y
++CONFIG_ROOT_NFS=y
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++# CONFIG_ENABLE_MUST_CHECK is not set
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_SECTION_MISMATCH=y
++CONFIG_DEBUG_KERNEL=y
++CONFIG_LOCKUP_DETECTOR=y
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
++# CONFIG_DETECT_HUNG_TASK is not set
++# CONFIG_SCHED_DEBUG is not set
++CONFIG_DEBUG_KMEMLEAK=y
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_FTRACE is not set
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_ANSI_CPRNG=y
++CONFIG_XZ_DEC=y
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch b/patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch
new file mode 100644 (file)
index 0000000..7aab5bd
--- /dev/null
@@ -0,0 +1,160 @@
+From 4dac8081711cdd9f55ee3191344bff84f7b573ff Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 6 Apr 2012 01:30:09 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add support LCDC0
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit dad29d1c29b7a8699403e45822065d979309f756)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 105 +++++++++++++++++++++++++
+ 1 file changed, 105 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 28bc259..5cc17a8 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -24,6 +24,7 @@
+ #include <linux/kernel.h>
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
++#include <linux/videodev2.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+ #include <asm/page.h>
+@@ -33,6 +34,7 @@
+ #include <asm/mach/time.h>
+ #include <asm/hardware/cache-l2x0.h>
+ #include <mach/r8a7740.h>
++#include <video/sh_mobile_lcdc.h>
+ /*
+  * CON1               Camera Module
+@@ -92,10 +94,66 @@
+  *-----------+---------------+----------------------------
+  */
++/* LCDC */
++static struct fb_videomode lcdc0_mode = {
++      .name           = "AMPIER/AM-800480",
++      .xres           = 800,
++      .yres           = 480,
++      .left_margin    = 88,
++      .right_margin   = 40,
++      .hsync_len      = 128,
++      .upper_margin   = 20,
++      .lower_margin   = 5,
++      .vsync_len      = 5,
++      .sync           = 0,
++};
++
++static struct sh_mobile_lcdc_info lcdc0_info = {
++      .clock_source   = LCDC_CLK_BUS,
++      .ch[0] = {
++              .chan           = LCDC_CHAN_MAINLCD,
++              .fourcc         = V4L2_PIX_FMT_RGB565,
++              .interface_type = RGB24,
++              .clock_divider  = 5,
++              .flags          = 0,
++              .lcd_modes      = &lcdc0_mode,
++              .num_modes      = 1,
++              .panel_cfg = {
++                      .width  = 111,
++                      .height = 68,
++              },
++      },
++};
++
++static struct resource lcdc0_resources[] = {
++      [0] = {
++              .name   = "LCD0",
++              .start  = 0xfe940000,
++              .end    = 0xfe943fff,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = intcs_evt2irq(0x580),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device lcdc0_device = {
++      .name           = "sh_mobile_lcdc_fb",
++      .num_resources  = ARRAY_SIZE(lcdc0_resources),
++      .resource       = lcdc0_resources,
++      .id             = 0,
++      .dev    = {
++              .platform_data  = &lcdc0_info,
++              .coherent_dma_mask = ~0,
++      },
++};
++
+ /*
+  * board devices
+  */
+ static struct platform_device *eva_devices[] __initdata = {
++      &lcdc0_device,
+ };
+ /*
+@@ -109,6 +167,53 @@ static void __init eva_init(void)
+       gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
+       gpio_request(GPIO_FN_SCIFA1_TXD, NULL);
++      /* LCDC0 */
++      gpio_request(GPIO_FN_LCDC0_SELECT,      NULL);
++      gpio_request(GPIO_FN_LCD0_D0,           NULL);
++      gpio_request(GPIO_FN_LCD0_D1,           NULL);
++      gpio_request(GPIO_FN_LCD0_D2,           NULL);
++      gpio_request(GPIO_FN_LCD0_D3,           NULL);
++      gpio_request(GPIO_FN_LCD0_D4,           NULL);
++      gpio_request(GPIO_FN_LCD0_D5,           NULL);
++      gpio_request(GPIO_FN_LCD0_D6,           NULL);
++      gpio_request(GPIO_FN_LCD0_D7,           NULL);
++      gpio_request(GPIO_FN_LCD0_D8,           NULL);
++      gpio_request(GPIO_FN_LCD0_D9,           NULL);
++      gpio_request(GPIO_FN_LCD0_D10,          NULL);
++      gpio_request(GPIO_FN_LCD0_D11,          NULL);
++      gpio_request(GPIO_FN_LCD0_D12,          NULL);
++      gpio_request(GPIO_FN_LCD0_D13,          NULL);
++      gpio_request(GPIO_FN_LCD0_D14,          NULL);
++      gpio_request(GPIO_FN_LCD0_D15,          NULL);
++      gpio_request(GPIO_FN_LCD0_D16,          NULL);
++      gpio_request(GPIO_FN_LCD0_D17,          NULL);
++      gpio_request(GPIO_FN_LCD0_D18_PORT40,   NULL);
++      gpio_request(GPIO_FN_LCD0_D19_PORT4,    NULL);
++      gpio_request(GPIO_FN_LCD0_D20_PORT3,    NULL);
++      gpio_request(GPIO_FN_LCD0_D21_PORT2,    NULL);
++      gpio_request(GPIO_FN_LCD0_D22_PORT0,    NULL);
++      gpio_request(GPIO_FN_LCD0_D23_PORT1,    NULL);
++      gpio_request(GPIO_FN_LCD0_DCK,          NULL);
++      gpio_request(GPIO_FN_LCD0_VSYN,         NULL);
++      gpio_request(GPIO_FN_LCD0_HSYN,         NULL);
++      gpio_request(GPIO_FN_LCD0_DISP,         NULL);
++      gpio_request(GPIO_FN_LCD0_LCLK_PORT165, NULL);
++
++      gpio_request(GPIO_PORT61, NULL); /* LCDDON */
++      gpio_direction_output(GPIO_PORT61, 1);
++
++      gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */
++      gpio_direction_output(GPIO_PORT202, 0);
++
++      /*
++       * CAUTION
++       *
++       * DBGMD/LCDC0/FSIA MUX
++       * DBGMD_SELECT_B should be set after setting PFC Function.
++       */
++      gpio_request(GPIO_PORT176, NULL);
++      gpio_direction_output(GPIO_PORT176, 1);
++
+ #ifdef CONFIG_CACHE_L2X0
+       /* Early BRESP enable, Shared attribute override enable, 32K*8way */
+       l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch b/patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch
new file mode 100644 (file)
index 0000000..813c5ef
--- /dev/null
@@ -0,0 +1,70 @@
+From 683089b4115c60b9b9f35ec3f5d91122a8a416e1 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 6 Apr 2012 01:31:33 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add support gpio_key
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit f7e7d31a1299e11be780f8e2d235570792849e31)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 5cc17a8..0bce9b8 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -22,8 +22,10 @@
+ #include <linux/clk.h>
+ #include <linux/err.h>
+ #include <linux/kernel.h>
++#include <linux/input.h>
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
++#include <linux/gpio_keys.h>
+ #include <linux/videodev2.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+@@ -149,11 +151,35 @@ static struct platform_device lcdc0_device = {
+       },
+ };
++/* GPIO KEY */
++#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
++
++static struct gpio_keys_button gpio_buttons[] = {
++      GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW1"),
++      GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW2"),
++      GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW3"),
++      GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW4"),
++};
++
++static struct gpio_keys_platform_data gpio_key_info = {
++      .buttons        = gpio_buttons,
++      .nbuttons       = ARRAY_SIZE(gpio_buttons),
++};
++
++static struct platform_device gpio_keys_device = {
++      .name   = "gpio-keys",
++      .id     = -1,
++      .dev    = {
++              .platform_data  = &gpio_key_info,
++      },
++};
++
+ /*
+  * board devices
+  */
+ static struct platform_device *eva_devices[] __initdata = {
+       &lcdc0_device,
++      &gpio_keys_device,
+ };
+ /*
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch b/patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch
new file mode 100644 (file)
index 0000000..a66c245
--- /dev/null
@@ -0,0 +1,109 @@
+From ab1150c0be9d95c57f6f03a56917c77b2af01bce Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 6 Apr 2012 01:32:02 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add support sh_eth
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit d8fed1e254ba1ed38fd2977fdac4c2e35ed5dbc1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 58 ++++++++++++++++++++++++++
+ 1 file changed, 58 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 0bce9b8..d439e7f 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -26,6 +26,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
+ #include <linux/gpio_keys.h>
++#include <linux/sh_eth.h>
+ #include <linux/videodev2.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+@@ -96,6 +97,38 @@
+  *-----------+---------------+----------------------------
+  */
++/* Ether */
++static struct sh_eth_plat_data sh_eth_platdata = {
++      .phy                    = 0x00, /* LAN8710A */
++      .edmac_endian           = EDMAC_LITTLE_ENDIAN,
++      .register_type          = SH_ETH_REG_GIGABIT,
++      .phy_interface          = PHY_INTERFACE_MODE_MII,
++};
++
++static struct resource sh_eth_resources[] = {
++      {
++              .start  = 0xe9a00000,
++              .end    = 0xe9a00800 - 1,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = 0xe9a01800,
++              .end    = 0xe9a02000 - 1,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = evt2irq(0x0500),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device sh_eth_device = {
++      .name = "sh-eth",
++      .dev = {
++              .platform_data = &sh_eth_platdata,
++      },
++      .resource = sh_eth_resources,
++      .num_resources = ARRAY_SIZE(sh_eth_resources),
++};
++
+ /* LCDC */
+ static struct fb_videomode lcdc0_mode = {
+       .name           = "AMPIER/AM-800480",
+@@ -180,6 +213,7 @@ static struct platform_device gpio_keys_device = {
+ static struct platform_device *eva_devices[] __initdata = {
+       &lcdc0_device,
+       &gpio_keys_device,
++      &sh_eth_device,
+ };
+ /*
+@@ -231,6 +265,30 @@ static void __init eva_init(void)
+       gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */
+       gpio_direction_output(GPIO_PORT202, 0);
++      /* GETHER */
++      gpio_request(GPIO_FN_ET_CRS,            NULL);
++      gpio_request(GPIO_FN_ET_MDC,            NULL);
++      gpio_request(GPIO_FN_ET_MDIO,           NULL);
++      gpio_request(GPIO_FN_ET_TX_ER,          NULL);
++      gpio_request(GPIO_FN_ET_RX_ER,          NULL);
++      gpio_request(GPIO_FN_ET_ERXD0,          NULL);
++      gpio_request(GPIO_FN_ET_ERXD1,          NULL);
++      gpio_request(GPIO_FN_ET_ERXD2,          NULL);
++      gpio_request(GPIO_FN_ET_ERXD3,          NULL);
++      gpio_request(GPIO_FN_ET_TX_CLK,         NULL);
++      gpio_request(GPIO_FN_ET_TX_EN,          NULL);
++      gpio_request(GPIO_FN_ET_ETXD0,          NULL);
++      gpio_request(GPIO_FN_ET_ETXD1,          NULL);
++      gpio_request(GPIO_FN_ET_ETXD2,          NULL);
++      gpio_request(GPIO_FN_ET_ETXD3,          NULL);
++      gpio_request(GPIO_FN_ET_PHY_INT,        NULL);
++      gpio_request(GPIO_FN_ET_COL,            NULL);
++      gpio_request(GPIO_FN_ET_RX_DV,          NULL);
++      gpio_request(GPIO_FN_ET_RX_CLK,         NULL);
++
++      gpio_request(GPIO_PORT18, NULL); /* PHY_RST */
++      gpio_direction_output(GPIO_PORT18, 1);
++
+       /*
+        * CAUTION
+        *
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch b/patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch
new file mode 100644 (file)
index 0000000..3dc4e30
--- /dev/null
@@ -0,0 +1,59 @@
+From 6c075ffc555411ed9a75c338058837c617323f16 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Fri, 6 Apr 2012 01:30:42 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add support ST1232
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 46cf668748070e54879d528fa58107abc835dff3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index d439e7f..4d066f9 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -207,6 +207,14 @@ static struct platform_device gpio_keys_device = {
+       },
+ };
++/* I2C */
++static struct i2c_board_info i2c0_devices[] = {
++      {
++              I2C_BOARD_INFO("st1232-ts", 0x55),
++              .irq = evt2irq(0x0340),
++      },
++};
++
+ /*
+  * board devices
+  */
+@@ -265,6 +273,11 @@ static void __init eva_init(void)
+       gpio_request(GPIO_PORT202, NULL); /* LCD0_LED_CONT */
+       gpio_direction_output(GPIO_PORT202, 0);
++      /* Touchscreen */
++      gpio_request(GPIO_FN_IRQ10,     NULL); /* TP_INT */
++      gpio_request(GPIO_PORT166,      NULL); /* TP_RST_B */
++      gpio_direction_output(GPIO_PORT166, 1);
++
+       /* GETHER */
+       gpio_request(GPIO_FN_ET_CRS,            NULL);
+       gpio_request(GPIO_FN_ET_MDC,            NULL);
+@@ -303,6 +316,8 @@ static void __init eva_init(void)
+       l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
+ #endif
++      i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
++
+       r8a7740_add_standard_devices();
+       platform_add_devices(eva_devices,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch b/patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch
new file mode 100644 (file)
index 0000000..f153b6e
--- /dev/null
@@ -0,0 +1,326 @@
+From 1dae1324b5c1a1b5c27de07729b9b52a61037b3e Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:09:08 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add USB function support
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 1c96293e9f8b8ec9620201bcf7f776f0e0f89edb)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 247 ++++++++++++++++++++++++-
+ 1 file changed, 237 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 4d066f9..1d25d5f 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -20,14 +20,17 @@
+  */
+ #include <linux/clk.h>
++#include <linux/delay.h>
+ #include <linux/err.h>
+ #include <linux/kernel.h>
+ #include <linux/input.h>
++#include <linux/irq.h>
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/sh_eth.h>
+ #include <linux/videodev2.h>
++#include <linux/usb/renesas_usbhs.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+ #include <asm/page.h>
+@@ -90,6 +93,9 @@
+  *      0    | SDHI1         | COM8 enable,  COM14 disable
+  *      1    | SDHI1         | COM8 enable,  COM14 disable
+  * -12345678-+---------------+----------------------------
++ *       0   | USB0          | COM20 enable,  COM24 disable
++ *       1   | USB0          | COM20 disable, COM24 enable
++ * -12345678-+---------------+----------------------------
+  *        00 | JTAG          | SH-X2
+  *        10 | JTAG          | ARM
+  *        01 | JTAG          | -
+@@ -97,6 +103,195 @@
+  *-----------+---------------+----------------------------
+  */
++/*
++ * USB function
++ *
++ * When you use USB Function,
++ * set SW1.6 ON, and connect cable to CN24.
++ *
++ * USBF needs workaround on R8A7740 chip.
++ * These are a little bit complex.
++ * see
++ *    usbhsf_power_ctrl()
++ *
++ * CAUTION
++ *
++ * It uses autonomy mode for USB hotplug at this point
++ * (= usbhs_private.platform_callback.get_vbus is NULL),
++ * since we don't know what's happen on PM control
++ * on this workaround.
++ */
++#define USBCR1                0xe605810a
++#define USBH          0xC6700000
++#define USBH_USBCTR   0x10834
++
++struct usbhsf_private {
++      struct clk *phy;
++      struct clk *usb24;
++      struct clk *pci;
++      struct clk *func;
++      struct clk *host;
++      void __iomem *usbh_base;
++      struct renesas_usbhs_platform_info info;
++};
++
++#define usbhsf_get_priv(pdev)                         \
++      container_of(renesas_usbhs_get_info(pdev),      \
++                   struct usbhsf_private, info)
++
++static int usbhsf_get_id(struct platform_device *pdev)
++{
++      return USBHS_GADGET;
++}
++
++static void usbhsf_power_ctrl(struct platform_device *pdev,
++                            void __iomem *base, int enable)
++{
++      struct usbhsf_private *priv = usbhsf_get_priv(pdev);
++
++      /*
++       * Work around for USB Function.
++       * It needs USB host clock, and settings
++       */
++      if (enable) {
++              /*
++               * enable all the related usb clocks
++               * for usb workaround
++               */
++              clk_enable(priv->usb24);
++              clk_enable(priv->pci);
++              clk_enable(priv->host);
++              clk_enable(priv->func);
++              clk_enable(priv->phy);
++
++              /*
++               * set USBCR1
++               *
++               * Port1 is driven by USB function,
++               * Port2 is driven by USB HOST
++               * One HOST (Port1 or Port2 is HOST)
++               * USB PLL input clock = 24MHz
++               */
++              __raw_writew(0xd750, USBCR1);
++              mdelay(1);
++
++              /*
++               * start USB Host
++               */
++              __raw_writel(0x0000000c, priv->usbh_base + USBH_USBCTR);
++              __raw_writel(0x00000008, priv->usbh_base + USBH_USBCTR);
++              mdelay(10);
++
++              /*
++               * USB PHY Power ON
++               */
++              __raw_writew(0xd770, USBCR1);
++              __raw_writew(0x4000, base + 0x102); /* USBF :: SUSPMODE */
++
++      } else {
++              __raw_writel(0x0000010f, priv->usbh_base + USBH_USBCTR);
++              __raw_writew(0xd7c0, USBCR1); /* GPIO */
++
++              clk_disable(priv->phy);
++              clk_disable(priv->func);        /* usb work around */
++              clk_disable(priv->host);        /* usb work around */
++              clk_disable(priv->pci);         /* usb work around */
++              clk_disable(priv->usb24);       /* usb work around */
++      }
++}
++
++static void usbhsf_hardware_exit(struct platform_device *pdev)
++{
++      struct usbhsf_private *priv = usbhsf_get_priv(pdev);
++
++      if (!IS_ERR(priv->phy))
++              clk_put(priv->phy);
++      if (!IS_ERR(priv->usb24))
++              clk_put(priv->usb24);
++      if (!IS_ERR(priv->pci))
++              clk_put(priv->pci);
++      if (!IS_ERR(priv->host))
++              clk_put(priv->host);
++      if (!IS_ERR(priv->func))
++              clk_put(priv->func);
++      if (priv->usbh_base)
++              iounmap(priv->usbh_base);
++
++      priv->phy       = NULL;
++      priv->usb24     = NULL;
++      priv->pci       = NULL;
++      priv->host      = NULL;
++      priv->func      = NULL;
++      priv->usbh_base = NULL;
++}
++
++static int usbhsf_hardware_init(struct platform_device *pdev)
++{
++      struct usbhsf_private *priv = usbhsf_get_priv(pdev);
++
++      priv->phy       = clk_get(&pdev->dev, "phy");
++      priv->usb24     = clk_get(&pdev->dev, "usb24");
++      priv->pci       = clk_get(&pdev->dev, "pci");
++      priv->func      = clk_get(&pdev->dev, "func");
++      priv->host      = clk_get(&pdev->dev, "host");
++      priv->usbh_base = ioremap_nocache(USBH, 0x20000);
++
++      if (IS_ERR(priv->phy)           ||
++          IS_ERR(priv->usb24)         ||
++          IS_ERR(priv->pci)           ||
++          IS_ERR(priv->host)          ||
++          IS_ERR(priv->func)          ||
++          !priv->usbh_base) {
++              dev_err(&pdev->dev, "USB clock setting failed\n");
++              usbhsf_hardware_exit(pdev);
++              return -EIO;
++      }
++
++      /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */
++      clk_set_rate(priv->usb24,
++                   clk_get_rate(clk_get_parent(priv->usb24)));
++
++      return 0;
++}
++
++static struct usbhsf_private usbhsf_private = {
++      .info = {
++              .platform_callback = {
++                      .get_id         = usbhsf_get_id,
++                      .hardware_init  = usbhsf_hardware_init,
++                      .hardware_exit  = usbhsf_hardware_exit,
++                      .power_ctrl     = usbhsf_power_ctrl,
++              },
++              .driver_param = {
++                      .buswait_bwait          = 5,
++                      .detection_delay        = 5,
++              },
++      }
++};
++
++static struct resource usbhsf_resources[] = {
++      {
++              .name   = "USBHS",
++              .start  = 0xe6890000,
++              .end    = 0xe6890104 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              .start  = evt2irq(0x0A20),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device usbhsf_device = {
++      .name   = "renesas_usbhs",
++      .dev = {
++              .platform_data = &usbhsf_private.info,
++      },
++      .id = -1,
++      .num_resources  = ARRAY_SIZE(usbhsf_resources),
++      .resource       = usbhsf_resources,
++};
++
+ /* Ether */
+ static struct sh_eth_plat_data sh_eth_platdata = {
+       .phy                    = 0x00, /* LAN8710A */
+@@ -224,11 +419,41 @@ static struct platform_device *eva_devices[] __initdata = {
+       &sh_eth_device,
+ };
++static void __init eva_clock_init(void)
++{
++      struct clk *system      = clk_get(NULL, "system_clk");
++      struct clk *xtal1       = clk_get(NULL, "extal1");
++      struct clk *usb24s      = clk_get(NULL, "usb24s");
++
++      if (IS_ERR(system)      ||
++          IS_ERR(xtal1)       ||
++          IS_ERR(usb24s)) {
++              pr_err("armadillo800eva board clock init failed\n");
++              goto clock_error;
++      }
++
++      /* armadillo 800 eva extal1 is 24MHz */
++      clk_set_rate(xtal1, 24000000);
++
++      /* usb24s use extal1 (= system) clock (= 24MHz) */
++      clk_set_parent(usb24s, system);
++
++clock_error:
++      if (!IS_ERR(system))
++              clk_put(system);
++      if (!IS_ERR(xtal1))
++              clk_put(xtal1);
++      if (!IS_ERR(usb24s))
++              clk_put(usb24s);
++}
++
+ /*
+  * board init
+  */
+ static void __init eva_init(void)
+ {
++      eva_clock_init();
++
+       r8a7740_pinmux_init();
+       /* SCIFA1 */
+@@ -302,6 +527,18 @@ static void __init eva_init(void)
+       gpio_request(GPIO_PORT18, NULL); /* PHY_RST */
+       gpio_direction_output(GPIO_PORT18, 1);
++      /* USB */
++      gpio_request(GPIO_PORT159, NULL); /* USB_DEVICE_MODE */
++      gpio_direction_input(GPIO_PORT159);
++
++      if (gpio_get_value(GPIO_PORT159)) {
++              /* USB Host */
++      } else {
++              /* USB Func */
++              gpio_request(GPIO_FN_VBUS, NULL);
++              platform_device_register(&usbhsf_device);
++      }
++
+       /*
+        * CAUTION
+        *
+@@ -326,17 +563,7 @@ static void __init eva_init(void)
+ static void __init eva_earlytimer_init(void)
+ {
+-      struct clk *xtal1;
+-
+       r8a7740_clock_init(MD_CK0 | MD_CK2);
+-
+-      xtal1 = clk_get(NULL, "extal1");
+-      if (!IS_ERR(xtal1)) {
+-              /* armadillo 800 eva extal1 is 24MHz */
+-              clk_set_rate(xtal1, 24000000);
+-              clk_put(xtal1);
+-      }
+-
+       shmobile_earlytimer_init();
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch b/patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch
new file mode 100644 (file)
index 0000000..d98a570
--- /dev/null
@@ -0,0 +1,129 @@
+From 4cc08f83ce664539a9c3dab8a1b486002346ee83 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:09:19 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add SDHI0 support
+
+On armadillo800eva board,
+CD (= Card Detect) pin is not connected to SDHI0_CD.
+Then, we can use IRQ31 as card detect irq,
+but it needs chattering removal operation.
+We should use IRQ card detect in the future,
+but this patch use polling mode at this point.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 49c01112d6afdb679276c172ffcd4f1205c1ff97)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 71 ++++++++++++++++++++++++++
+ 1 file changed, 71 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 1d25d5f..ed85686 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -31,6 +31,9 @@
+ #include <linux/sh_eth.h>
+ #include <linux/videodev2.h>
+ #include <linux/usb/renesas_usbhs.h>
++#include <linux/mfd/tmio.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/sh_mobile_sdhi.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+ #include <asm/page.h>
+@@ -402,6 +405,55 @@ static struct platform_device gpio_keys_device = {
+       },
+ };
++/* SDHI0 */
++/*
++ * FIXME
++ *
++ * It use polling mode here, since
++ * CD (= Card Detect) pin is not connected to SDHI0_CD.
++ * We can use IRQ31 as card detect irq,
++ * but it needs chattering removal operation
++ */
++#define IRQ31 evt2irq(0x33E0)
++static struct sh_mobile_sdhi_info sdhi0_info = {
++      .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\
++                        MMC_CAP_NEEDS_POLL,
++      .tmio_ocr_mask  = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
++      .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
++};
++
++static struct resource sdhi0_resources[] = {
++      {
++              .name   = "SDHI0",
++              .start  = 0xe6850000,
++              .end    = 0xe6850100 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      /*
++       * no SH_MOBILE_SDHI_IRQ_CARD_DETECT here
++       */
++      {
++              .name   = SH_MOBILE_SDHI_IRQ_SDCARD,
++              .start  = evt2irq(0x0E20),
++              .flags  = IORESOURCE_IRQ,
++      },
++      {
++              .name   = SH_MOBILE_SDHI_IRQ_SDIO,
++              .start  = evt2irq(0x0E40),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device sdhi0_device = {
++      .name           = "sh_mobile_sdhi",
++      .id             = 0,
++      .dev            = {
++              .platform_data  = &sdhi0_info,
++      },
++      .num_resources  = ARRAY_SIZE(sdhi0_resources),
++      .resource       = sdhi0_resources,
++};
++
+ /* I2C */
+ static struct i2c_board_info i2c0_devices[] = {
+       {
+@@ -417,6 +469,7 @@ static struct platform_device *eva_devices[] __initdata = {
+       &lcdc0_device,
+       &gpio_keys_device,
+       &sh_eth_device,
++      &sdhi0_device,
+ };
+ static void __init eva_clock_init(void)
+@@ -539,6 +592,24 @@ static void __init eva_init(void)
+               platform_device_register(&usbhsf_device);
+       }
++      /* SDHI0 */
++      gpio_request(GPIO_FN_SDHI0_CMD, NULL);
++      gpio_request(GPIO_FN_SDHI0_CLK, NULL);
++      gpio_request(GPIO_FN_SDHI0_D0, NULL);
++      gpio_request(GPIO_FN_SDHI0_D1, NULL);
++      gpio_request(GPIO_FN_SDHI0_D2, NULL);
++      gpio_request(GPIO_FN_SDHI0_D3, NULL);
++      gpio_request(GPIO_FN_SDHI0_WP, NULL);
++
++      gpio_request(GPIO_PORT17, NULL);        /* SDHI0_18/33_B */
++      gpio_request(GPIO_PORT74, NULL);        /* SDHI0_PON */
++      gpio_request(GPIO_PORT75, NULL);        /* SDSLOT1_PON */
++      gpio_direction_output(GPIO_PORT17, 0);
++      gpio_direction_output(GPIO_PORT74, 1);
++      gpio_direction_output(GPIO_PORT75, 1);
++
++      /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */
++
+       /*
+        * CAUTION
+        *
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch b/patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch
new file mode 100644 (file)
index 0000000..ff2fe86
--- /dev/null
@@ -0,0 +1,113 @@
+From 78c21b71d7b4c9b2a5b2a785aca79aee0b9ffba2 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:09:31 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add SDHI1 support
+
+We can switch CON8/CON14 by SW1.5
+SDHI1 is CON8 (SW1.5 = ON)
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 2e3a5ef28f8182c439a5a276ff4c0883c02787f4)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 66 +++++++++++++++++++++++++-
+ 1 file changed, 65 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index ed85686..5f62428 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -93,7 +93,7 @@
+  *     0     | Extension Bus | D8-D15 disable, eMMC enable
+  *     1     | Extension Bus | D8-D15 enable,  eMMC disable
+  * -12345678-+---------------+----------------------------
+- *      0    | SDHI1         | COM8 enable,  COM14 disable
++ *      0    | SDHI1         | COM8 disable, COM14 enable
+  *      1    | SDHI1         | COM8 enable,  COM14 disable
+  * -12345678-+---------------+----------------------------
+  *       0   | USB0          | COM20 enable,  COM24 disable
+@@ -454,6 +454,44 @@ static struct platform_device sdhi0_device = {
+       .resource       = sdhi0_resources,
+ };
++/* SDHI1 */
++static struct sh_mobile_sdhi_info sdhi1_info = {
++      .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
++      .tmio_ocr_mask  = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
++      .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
++};
++
++static struct resource sdhi1_resources[] = {
++      [0] = {
++              .name   = "SDHI1",
++              .start  = 0xe6860000,
++              .end    = 0xe6860100 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = evt2irq(0x0E80),
++              .flags  = IORESOURCE_IRQ,
++      },
++      [2] = {
++              .start  = evt2irq(0x0EA0),
++              .flags  = IORESOURCE_IRQ,
++      },
++      [3] = {
++              .start  = evt2irq(0x0EC0),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device sdhi1_device = {
++      .name           = "sh_mobile_sdhi",
++      .id             = 1,
++      .dev            = {
++              .platform_data  = &sdhi1_info,
++      },
++      .num_resources  = ARRAY_SIZE(sdhi1_resources),
++      .resource       = sdhi1_resources,
++};
++
+ /* I2C */
+ static struct i2c_board_info i2c0_devices[] = {
+       {
+@@ -619,6 +657,32 @@ static void __init eva_init(void)
+       gpio_request(GPIO_PORT176, NULL);
+       gpio_direction_output(GPIO_PORT176, 1);
++      /*
++       * We can switch CON8/CON14 by SW1.5,
++       * but it needs after DBGMD_SELECT_B
++       */
++      gpio_request(GPIO_PORT6, NULL);
++      gpio_direction_input(GPIO_PORT6);
++      if (gpio_get_value(GPIO_PORT6)) {
++              /* CON14 enable */
++      } else {
++              /* CON8 (SDHI1) enable */
++              gpio_request(GPIO_FN_SDHI1_CLK, NULL);
++              gpio_request(GPIO_FN_SDHI1_CMD, NULL);
++              gpio_request(GPIO_FN_SDHI1_D0,  NULL);
++              gpio_request(GPIO_FN_SDHI1_D1,  NULL);
++              gpio_request(GPIO_FN_SDHI1_D2,  NULL);
++              gpio_request(GPIO_FN_SDHI1_D3,  NULL);
++              gpio_request(GPIO_FN_SDHI1_CD,  NULL);
++              gpio_request(GPIO_FN_SDHI1_WP,  NULL);
++
++              gpio_request(GPIO_PORT16, NULL); /* SDSLOT2_PON */
++              gpio_direction_output(GPIO_PORT16, 1);
++
++              platform_device_register(&sdhi1_device);
++      }
++
++
+ #ifdef CONFIG_CACHE_L2X0
+       /* Early BRESP enable, Shared attribute override enable, 32K*8way */
+       l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch b/patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch
new file mode 100644 (file)
index 0000000..fe15b6a
--- /dev/null
@@ -0,0 +1,108 @@
+From 0d4e5e39563404cb97b24a37388535b6c54ac90d Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:09:42 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: add MMCIF support
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 0a4266bb22774bb0b6390d2633a151d996a14e77)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 57 ++++++++++++++++++++++++++
+ 1 file changed, 57 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 5f62428..0cfaec5 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -33,6 +33,7 @@
+ #include <linux/usb/renesas_usbhs.h>
+ #include <linux/mfd/tmio.h>
+ #include <linux/mmc/host.h>
++#include <linux/mmc/sh_mmcif.h>
+ #include <linux/mmc/sh_mobile_sdhi.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+@@ -492,6 +493,44 @@ static struct platform_device sdhi1_device = {
+       .resource       = sdhi1_resources,
+ };
++/* MMCIF */
++static struct sh_mmcif_plat_data sh_mmcif_plat = {
++      .sup_pclk       = 0,
++      .ocr            = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
++      .caps           = MMC_CAP_4_BIT_DATA |
++                        MMC_CAP_8_BIT_DATA |
++                        MMC_CAP_NONREMOVABLE,
++};
++
++static struct resource sh_mmcif_resources[] = {
++      [0] = {
++              .name   = "MMCIF",
++              .start  = 0xe6bd0000,
++              .end    = 0xe6bd0100 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              /* MMC ERR */
++              .start  = evt2irq(0x1AC0),
++              .flags  = IORESOURCE_IRQ,
++      },
++      [2] = {
++              /* MMC NOR */
++              .start  = evt2irq(0x1AE0),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device sh_mmcif_device = {
++      .name           = "sh_mmcif",
++      .id             = -1,
++      .dev            = {
++              .platform_data  = &sh_mmcif_plat,
++      },
++      .num_resources  = ARRAY_SIZE(sh_mmcif_resources),
++      .resource       = sh_mmcif_resources,
++};
++
+ /* I2C */
+ static struct i2c_board_info i2c0_devices[] = {
+       {
+@@ -508,6 +547,7 @@ static struct platform_device *eva_devices[] __initdata = {
+       &gpio_keys_device,
+       &sh_eth_device,
+       &sdhi0_device,
++      &sh_mmcif_device,
+ };
+ static void __init eva_clock_init(void)
+@@ -649,6 +689,23 @@ static void __init eva_init(void)
+       /* we can use GPIO_FN_IRQ31_PORT167 here for SDHI0 CD irq */
+       /*
++       * MMCIF
++       *
++       * Here doesn't care SW1.4 status,
++       * since CON2 is not mounted.
++       */
++      gpio_request(GPIO_FN_MMC1_CLK_PORT103,  NULL);
++      gpio_request(GPIO_FN_MMC1_CMD_PORT104,  NULL);
++      gpio_request(GPIO_FN_MMC1_D0_PORT149,   NULL);
++      gpio_request(GPIO_FN_MMC1_D1_PORT148,   NULL);
++      gpio_request(GPIO_FN_MMC1_D2_PORT147,   NULL);
++      gpio_request(GPIO_FN_MMC1_D3_PORT146,   NULL);
++      gpio_request(GPIO_FN_MMC1_D4_PORT145,   NULL);
++      gpio_request(GPIO_FN_MMC1_D5_PORT144,   NULL);
++      gpio_request(GPIO_FN_MMC1_D6_PORT143,   NULL);
++      gpio_request(GPIO_FN_MMC1_D7_PORT142,   NULL);
++
++      /*
+        * CAUTION
+        *
+        * DBGMD/LCDC0/FSIA MUX
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch b/patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch
new file mode 100644 (file)
index 0000000..90555bd
--- /dev/null
@@ -0,0 +1,47 @@
+From 3d1f581e9dbb224b5f0543883cc3e86876c8e5fe Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 24 Apr 2012 02:10:05 -0700
+Subject: ARM: mach-shmobile: r8a7740: reserve DMA memory for the frame buffer
+
+The default 2MB size of DMA coherent memory isn't enough for allocate
+frame buffer memory.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 3841e6f561af717478b253ce1dcba7bff9e9f890)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/setup-r8a7740.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 34a1548..ec4eb49 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -18,6 +18,7 @@
+  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  */
+ #include <linux/delay.h>
++#include <linux/dma-mapping.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/io.h>
+@@ -60,6 +61,12 @@ static struct map_desc r8a7740_io_desc[] __initdata = {
+ void __init r8a7740_map_io(void)
+ {
+       iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
++
++      /*
++       * DMA memory at 0xff200000 - 0xffdfffff. The default 2MB size isn't
++       * enough to allocate the frame buffer memory.
++       */
++      init_consistent_dma_size(12 << 20);
+ }
+ /* SCIFA0 */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch b/patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch
new file mode 100644 (file)
index 0000000..1205439
--- /dev/null
@@ -0,0 +1,64 @@
+From c1d7a1d9c12959dea7cc4f0552e6b7985afeb186 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 6 May 2012 22:58:41 -0700
+Subject: ARM: mach-shmobile: clock-r8a7740: add sh-eth clock
+
+armadillo800eva board is using sh-eth, but clock-r8a7740 didn't care it.
+This clock was enabled by boot-loader.
+This patch fix it up.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 9c18f238c1ec36b9912b5b36ae24e0c221179044)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 1 +
+ arch/arm/mach-shmobile/clock-r8a7740.c         | 3 +++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 0cfaec5..e750ea6 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -321,6 +321,7 @@ static struct resource sh_eth_resources[] = {
+ static struct platform_device sh_eth_device = {
+       .name = "sh-eth",
++      .id = -1,
+       .dev = {
+               .platform_data = &sh_eth_platdata,
+       },
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index 81b54a6..26eea5f 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -352,6 +352,7 @@ enum {
+       MSTP329, MSTP328, MSTP323, MSTP320,
+       MSTP314, MSTP313, MSTP312,
++      MSTP309,
+       MSTP416, MSTP415, MSTP407, MSTP406,
+@@ -382,6 +383,7 @@ static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 14, 0), /* SDHI0 */
+       [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 13, 0), /* SDHI1 */
+       [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 12, 0), /* MMC */
++      [MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3,  9, 0), /* GEther */
+       [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 16, 0), /* USBHOST */
+       [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 15, 0), /* SDHI2 */
+@@ -447,6 +449,7 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("sh_mobile_sdhi.0",       &mstp_clks[MSTP314]),
+       CLKDEV_DEV_ID("sh_mobile_sdhi.1",       &mstp_clks[MSTP313]),
+       CLKDEV_DEV_ID("sh_mmcif",               &mstp_clks[MSTP312]),
++      CLKDEV_DEV_ID("sh-eth",                 &mstp_clks[MSTP309]),
+       CLKDEV_DEV_ID("sh_mobile_sdhi.2",       &mstp_clks[MSTP415]),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch b/patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch
new file mode 100644 (file)
index 0000000..0fdb8e8
--- /dev/null
@@ -0,0 +1,87 @@
+From b578e0342552c51f1d81de4d730bf5325f52b48a Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Wed, 25 Apr 2012 20:57:13 -0700
+Subject: ARM: mach-shmobile: armadillo800eva: defconfig update
+
+This patch enable USBFunc/SHDI/MMCIF,
+remove debug settings,
+and cleanuped by c2330e286f68f1c408b4aa6515ba49d57f05beae script
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 9183857d503f915ee05abb6e03cea7253dcbace6)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/configs/armadillo800eva_defconfig | 25 ++++++++++++-------------
+ 1 file changed, 12 insertions(+), 13 deletions(-)
+
+diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
+index 0d20749..ddc9fe6 100644
+--- a/arch/arm/configs/armadillo800eva_defconfig
++++ b/arch/arm/configs/armadillo800eva_defconfig
+@@ -10,7 +10,6 @@ CONFIG_LOG_BUF_SHIFT=16
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_SYSFS_DEPRECATED_V2=y
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+-CONFIG_KALLSYMS_ALL=y
+ CONFIG_SLAB=y
+ CONFIG_MODULES=y
+ CONFIG_MODULE_UNLOAD=y
+@@ -63,6 +62,7 @@ CONFIG_BLK_DEV_DM=y
+ CONFIG_NETDEVICES=y
+ # CONFIG_NET_VENDOR_BROADCOM is not set
+ # CONFIG_NET_VENDOR_CHELSIO is not set
++# CONFIG_NET_VENDOR_CIRRUS is not set
+ # CONFIG_NET_VENDOR_FARADAY is not set
+ # CONFIG_NET_VENDOR_INTEL is not set
+ # CONFIG_NET_VENDOR_MARVELL is not set
+@@ -70,6 +70,7 @@ CONFIG_NETDEVICES=y
+ # CONFIG_NET_VENDOR_NATSEMI is not set
+ CONFIG_SH_ETH=y
+ # CONFIG_NET_VENDOR_SEEQ is not set
++# CONFIG_NET_VENDOR_SMSC is not set
+ # CONFIG_NET_VENDOR_STMICRO is not set
+ # CONFIG_WLAN is not set
+ # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+@@ -106,7 +107,15 @@ CONFIG_SND=y
+ CONFIG_SND_SOC=y
+ CONFIG_SND_SOC_SH4_FSI=y
+ # CONFIG_HID_SUPPORT is not set
+-# CONFIG_USB_SUPPORT is not set
++CONFIG_USB=y
++# CONFIG_USB_DEVICE_CLASS is not set
++CONFIG_USB_RENESAS_USBHS=y
++CONFIG_USB_GADGET=y
++CONFIG_USB_RENESAS_USBHS_UDC=y
++CONFIG_USB_ETH=m
++CONFIG_MMC=y
++CONFIG_MMC_SDHI=y
++CONFIG_MMC_SH_MMCIF=y
+ CONFIG_UIO=y
+ CONFIG_UIO_PDRV_GENIRQ=y
+ # CONFIG_DNOTIFY is not set
+@@ -124,17 +133,7 @@ CONFIG_NLS_CODEPAGE_437=y
+ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_ENABLE_WARN_DEPRECATED is not set
+ # CONFIG_ENABLE_MUST_CHECK is not set
+-CONFIG_MAGIC_SYSRQ=y
+-CONFIG_DEBUG_SECTION_MISMATCH=y
+-CONFIG_DEBUG_KERNEL=y
+-CONFIG_LOCKUP_DETECTOR=y
+-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+-# CONFIG_DETECT_HUNG_TASK is not set
+-# CONFIG_SCHED_DEBUG is not set
+-CONFIG_DEBUG_KMEMLEAK=y
+-CONFIG_DEBUG_SPINLOCK=y
+-CONFIG_DEBUG_INFO=y
+-# CONFIG_FTRACE is not set
++# CONFIG_ARM_UNWIND is not set
+ CONFIG_CRYPTO=y
+ CONFIG_CRYPTO_CBC=y
+ CONFIG_CRYPTO_MD5=y
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch b/patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch
new file mode 100644 (file)
index 0000000..6050a90
--- /dev/null
@@ -0,0 +1,88 @@
+From e8f0e8b7d350aad665d17ffe656edaa2c2dda533 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Mon, 14 May 2012 19:54:41 +0900
+Subject: ARM: mach-shmobile: Use DT_MACHINE for armadillo 800 eva
+
+Use DT_MACHINE_START() on the r8a7740 based armadillo 800 eva board.
+
+Also include a tiny DTS file to describe the board and update the
+Kconfig dependencies to select CONFIG_USE_OF.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit e6bf705911a0b64c589b6c408a316e7d465acbbd)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/boot/dts/r8a7740-armadillo800eva.dts  | 22 ++++++++++++++++++++++
+ arch/arm/mach-shmobile/Kconfig                 |  1 +
+ arch/arm/mach-shmobile/board-armadillo800eva.c |  8 +++++++-
+ 3 files changed, 30 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/boot/dts/r8a7740-armadillo800eva.dts
+
+diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
+new file mode 100644
+index 0000000..a7505a9
+--- /dev/null
++++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
+@@ -0,0 +1,22 @@
++/*
++ * Device Tree Source for the armadillo 800 eva board
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2.  This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++/dts-v1/;
++/include/ "skeleton.dtsi"
++
++/ {
++      model = "armadillo 800 eva";
++      compatible = "renesas,armadillo800eva";
++
++      memory {
++              device_type = "memory";
++              reg = <0x40000000 0x20000000>;
++      };
++};
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index 799e996..da57dde 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -99,6 +99,7 @@ config MACH_ARMADILLO800EVA
+       bool "Armadillo-800 EVA board"
+       depends on ARCH_R8A7740
+       select ARCH_REQUIRE_GPIOLIB
++      select USE_OF
+ config MACH_MARZEN
+       bool "MARZEN board"
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index e750ea6..9e37026 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -768,11 +768,17 @@ static void __init eva_add_early_devices(void)
+       shmobile_timer.init = eva_earlytimer_init;
+ }
+-MACHINE_START(ARMADILLO800EVA, "armadillo800eva")
++static const char *eva_boards_compat_dt[] __initdata = {
++      "renesas,armadillo800eva",
++      NULL,
++};
++
++DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
+       .map_io         = r8a7740_map_io,
+       .init_early     = eva_add_early_devices,
+       .init_irq       = r8a7740_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
+       .init_machine   = eva_init,
+       .timer          = &shmobile_timer,
++      .dt_compat      = eva_boards_compat_dt,
+ MACHINE_END
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch b/patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch
new file mode 100644 (file)
index 0000000..d84ba6b
--- /dev/null
@@ -0,0 +1,82 @@
+From 86c25d5111c1edb9ca3cc28eaa0abd387250959a Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:35:15 -0700
+Subject: ARM: shmobile: r8a7740: add HDMI interrupt support
+
+It is required from sh_mobile_hdmi driver.
+This patch is based on v1.0 manual
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 7d7136cabcad632a81cd568a9c1135db276fe0f2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/intc-r8a7740.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c
+index 09c42af..9a69a31 100644
+--- a/arch/arm/mach-shmobile/intc-r8a7740.c
++++ b/arch/arm/mach-shmobile/intc-r8a7740.c
+@@ -71,10 +71,12 @@ enum {
+       DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
+       DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
+       SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM,
++      HDMI,
+       USBH_INT, USBH_OHCI, USBH_EHCI, USBH_PME, USBH_BIND,
+       RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF,
+       SPU2_0, SPU2_1,
+       FSI, FMSI,
++      HDMI_SSS, HDMI_KEY,
+       IPMMU,
+       AP_ARM_CTIIRQ, AP_ARM_PMURQ,
+       MFIS2,
+@@ -182,6 +184,7 @@ static struct intc_vect intca_vectors[] __initdata = {
+       INTC_VECT(USBH_EHCI,            0x1580),
+       INTC_VECT(USBH_PME,             0x15A0),
+       INTC_VECT(USBH_BIND,            0x15C0),
++      INTC_VECT(HDMI,                 0x1700),
+       INTC_VECT(RSPI_OVRF,            0x1780),
+       INTC_VECT(RSPI_SPTEF,           0x17A0),
+       INTC_VECT(RSPI_SPRF,            0x17C0),
+@@ -189,6 +192,8 @@ static struct intc_vect intca_vectors[] __initdata = {
+       INTC_VECT(SPU2_1,               0x1820),
+       INTC_VECT(FSI,                  0x1840),
+       INTC_VECT(FMSI,                 0x1860),
++      INTC_VECT(HDMI_SSS,             0x18A0),
++      INTC_VECT(HDMI_KEY,             0x18C0),
+       INTC_VECT(IPMMU,                0x1920),
+       INTC_VECT(AP_ARM_CTIIRQ,        0x1980),
+       INTC_VECT(AP_ARM_PMURQ,         0x19A0),
+@@ -304,11 +309,11 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = {
+           USBH_EHCI, USBH_PME, USBH_BIND, 0 } },
+         /* IMR3A3 / IMCR3A3 */
+       { /* IMR4A3 / IMCR4A3 */ 0xe6950090, 0xe69500d0, 8,
+-        { 0, 0, 0, 0,
++        { HDMI, 0, 0, 0,
+           RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, 0 } },
+       { /* IMR5A3 / IMCR5A3 */ 0xe6950094, 0xe69500d4, 8,
+         { SPU2_0, SPU2_1, FSI, FMSI,
+-          0, 0, 0, 0 } },
++          0, HDMI_SSS, HDMI_KEY, 0 } },
+       { /* IMR6A3 / IMCR6A3 */ 0xe6950098, 0xe69500d8, 8,
+         { 0, IPMMU, 0, 0,
+           AP_ARM_CTIIRQ, AP_ARM_PMURQ, 0, 0 } },
+@@ -353,10 +358,10 @@ static struct intc_prio_reg intca_prio_registers[] __initdata = {
+       { 0xe6950014, 0, 16, 4, /* IPRFA3 */ { USBH2, 0, 0, 0 } },
+                               /* IPRGA3 */
+                               /* IPRHA3 */
+-                              /* IPRIA3 */
++      { 0xe6950020, 0, 16, 4, /* IPRIA3 */ { HDMI, 0, 0, 0 } },
+       { 0xe6950024, 0, 16, 4, /* IPRJA3 */ { RSPI, 0, 0, 0 } },
+       { 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } },
+-                              /* IPRLA3 */
++      { 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, HDMI_SSS, HDMI_KEY, 0 } },
+       { 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU, 0, 0, 0 } },
+       { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
+       { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch b/patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch
new file mode 100644 (file)
index 0000000..707d43a
--- /dev/null
@@ -0,0 +1,146 @@
+From 86a946d62d5993f9f8bff6db6445a0a12893665d Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:35:36 -0700
+Subject: ARM: shmobile: r8a7740: add HDMI clock support
+
+It is required from sh_mobile_hdmi driver.
+This patch is based on v1.0 manual
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit c6750acb3b54c77c011045467770d5143be749ee)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 84 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 84 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index 26eea5f..b095343 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -54,6 +54,7 @@
+ #define MSTPSR2               0xe6150040
+ #define MSTPSR3               0xe6150048
+ #define MSTPSR4               0xe615004c
++#define HDMICKCR      0xe6150094
+ #define SMSTPCR0      0xe6150130
+ #define SMSTPCR1      0xe6150134
+ #define SMSTPCR2      0xe6150138
+@@ -313,6 +314,79 @@ static struct clk_div4_table div4_table = {
+       .kick = div4_kick,
+ };
++/* DIV6 reparent */
++enum {
++      DIV6_HDMI,
++      DIV6_REPARENT_NR,
++};
++
++static struct clk *hdmi_parent[] = {
++      [0] = &pllc1_div2_clk,
++      [1] = &system_clk,
++      [2] = &dv_clk
++};
++
++static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
++      [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
++                                    hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
++};
++
++/* HDMI1/2 clock */
++static unsigned long hdmi12_recalc(struct clk *clk)
++{
++      u32 val = __raw_readl(HDMICKCR);
++      int shift = (int)clk->priv;
++
++      val >>= shift;
++      val &= 0x3;
++
++      return clk->parent->rate / (1 << val);
++};
++
++static int hdmi12_set_rate(struct clk *clk, unsigned long rate)
++{
++      u32 val, mask;
++      int i, shift;
++
++      for (i = 0; i < 3; i++)
++              if (rate == clk->parent->rate / (1 << i))
++                      goto find;
++      return -ENODEV;
++
++find:
++      shift = (int)clk->priv;
++
++      val = __raw_readl(HDMICKCR);
++      mask = ~(0x3 << shift);
++      val = (val & mask) | i << shift;
++      __raw_writel(val, HDMICKCR);
++
++      return 0;
++};
++
++static struct sh_clk_ops hdmi12_clk_ops = {
++      .recalc         = hdmi12_recalc,
++      .set_rate       = hdmi12_set_rate,
++};
++
++static struct clk hdmi1_clk = {
++      .ops            = &hdmi12_clk_ops,
++      .priv           = (void *)9,
++      .parent         = &div6_reparent_clks[DIV6_HDMI],  /* late install */
++};
++
++static struct clk hdmi2_clk = {
++      .ops            = &hdmi12_clk_ops,
++      .priv           = (void *)11,
++      .parent         = &div6_reparent_clks[DIV6_HDMI], /* late install */
++};
++
++static struct clk *late_main_clks[] = {
++      &hdmi1_clk,
++      &hdmi2_clk,
++};
++
++/* MSTP */
+ enum {
+       DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
+       DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
+@@ -408,6 +482,8 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_CON_ID("pllc1_clk",              &pllc1_clk),
+       CLKDEV_CON_ID("pllc1_div2_clk",         &pllc1_div2_clk),
+       CLKDEV_CON_ID("usb24s",                 &usb24s_clk),
++      CLKDEV_CON_ID("hdmi1",                  &hdmi1_clk),
++      CLKDEV_CON_ID("hdmi2",                  &hdmi2_clk),
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("i_clk",                  &div4_clks[DIV4_I]),
+@@ -459,6 +535,7 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_ICK_ID("phy",    "renesas_usbhs",        &mstp_clks[MSTP406]),
+       CLKDEV_ICK_ID("pci",    "renesas_usbhs",        &div4_clks[DIV4_USBP]),
+       CLKDEV_ICK_ID("usb24",  "renesas_usbhs",        &usb24_clk),
++      CLKDEV_ICK_ID("ick",    "sh-mobile-hdmi",       &div6_reparent_clks[DIV6_HDMI]),
+ };
+ void __init r8a7740_clock_init(u8 md_ck)
+@@ -495,8 +572,15 @@ void __init r8a7740_clock_init(u8 md_ck)
+               ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+       if (!ret)
++              ret = sh_clk_div6_reparent_register(div6_reparent_clks,
++                                                  DIV6_REPARENT_NR);
++
++      if (!ret)
+               ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
++      for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
++              ret = clk_register(late_main_clks[k]);
++
+       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+       if (!ret)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch b/patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch
new file mode 100644 (file)
index 0000000..8619f0d
--- /dev/null
@@ -0,0 +1,76 @@
+From 77cd6be2b59e2839e6c2b8cab77a480e092aedec Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:35:58 -0700
+Subject: ARM: shmobile: r8a7740: add HDMI GPIO support
+
+In order to enable HDMI GPIO selection from platform board,
+this patch adds its interface to GPIO framework.
+
+This patch is based on v1.0 manual
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit e2dcd461a7ba0c3deb44336136ea784c8b972292)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/r8a7740.h | 4 ++++
+ arch/arm/mach-shmobile/pfc-r8a7740.c          | 9 +++++++++
+ 2 files changed, 13 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index 9d447ab..2764846 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -565,6 +565,10 @@ enum {
+       GPIO_FN_RESETP_PULLUP,
+       GPIO_FN_RESETP_PLAIN,
++      /* HDMI */
++      GPIO_FN_HDMI_HPD,
++      GPIO_FN_HDMI_CEC,
++
+       /* SDENC */
+       GPIO_FN_SDENC_CPG,
+       GPIO_FN_SDENC_DV_CLKI,
+diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
+index 670fe18..0dda816 100644
+--- a/arch/arm/mach-shmobile/pfc-r8a7740.c
++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
+@@ -560,6 +560,9 @@ enum {
+       /* SDENC */
+       SDENC_CPG_MARK,         SDENC_DV_CLKI_MARK,
++      /* HDMI */
++      HDMI_HPD_MARK, HDMI_CEC_MARK,
++
+       /* DEBUG */
+       EDEBGREQ_PULLUP_MARK,   /* for JTAG */
+       EDEBGREQ_PULLDOWN_MARK,
+@@ -1620,9 +1623,11 @@ static pinmux_enum_t pinmux_data[] = {
+       /* Port210 */
+       PINMUX_DATA(IRQ9_PORT210_MARK,          PORT210_FN0,    MSEL1CR_9_1),
++      PINMUX_DATA(HDMI_HPD_MARK,              PORT210_FN1),
+       /* Port211 */
+       PINMUX_DATA(IRQ16_PORT211_MARK,         PORT211_FN0,    MSEL1CR_16_1),
++      PINMUX_DATA(HDMI_CEC_MARK,              PORT211_FN1),
+       /* LCDC select */
+       PINMUX_DATA(LCDC0_SELECT_MARK,                          MSEL3CR_6_0),
+@@ -2097,6 +2102,10 @@ static struct pinmux_gpio pinmux_gpios[] = {
+       GPIO_FN(SDENC_CPG),
+       GPIO_FN(SDENC_DV_CLKI),
++      /* HDMI */
++      GPIO_FN(HDMI_HPD),
++      GPIO_FN(HDMI_CEC),
++
+       /* SYSC */
+       GPIO_FN(RESETP_PULLUP),
+       GPIO_FN(RESETP_PLAIN),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch b/patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch
new file mode 100644 (file)
index 0000000..ac9838b
--- /dev/null
@@ -0,0 +1,34 @@
+From acd1ae033a03a0c6356e68d9d17427afb0f53eb0 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:36:21 -0700
+Subject: ARM: shmobile: r8a7740: add MERAM work-around
+
+r8a7740 chip has lasting errata on MERAM buffer, and this patch adds
+its work-around on setup-r8a7740.c
+It solved CEU/VIO6C/2D-DMAC/VCP1/VPU5F/JPU/DISP memroy access error.
+
+But MERAM driver can't control this issue,
+since this work-around requires access to non-MERAM register address.
+So, This it will be called as board specific code at this point.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit d49679e5928709bce8937dce396458b139c4b34d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -587,6 +587,7 @@ static void __init eva_init(void)
+       eva_clock_init();
+       r8a7740_pinmux_init();
++      r8a7740_meram_workaround();
+       /* SCIFA1 */
+       gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
diff --git a/patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch b/patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch
new file mode 100644 (file)
index 0000000..8c3989b
--- /dev/null
@@ -0,0 +1,101 @@
+From 5484e5aba2cd92f69af04090ab0f4e018175df69 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:36:39 -0700
+Subject: ARM: shmobile: r8a7740: add CEU clock support
+
+It is required from sh_mobile_ceu_camera driver.
+This patch is based on v1.0 manual
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit ad9f1721c15b84f1a2e45a8a03f1ff7c86c2829b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index b095343..ce0930a 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -43,6 +43,8 @@
+ /* CPG registers */
+ #define FRQCRA                0xe6150000
+ #define FRQCRB                0xe6150004
++#define VCLKCR1               0xE6150008
++#define VCLKCR2               0xE615000c
+ #define FRQCRC                0xe61500e0
+ #define PLLC01CR      0xe6150028
+@@ -317,6 +319,7 @@ static struct clk_div4_table div4_table = {
+ /* DIV6 reparent */
+ enum {
+       DIV6_HDMI,
++      DIV6_VCLK1, DIV6_VCLK2,
+       DIV6_REPARENT_NR,
+ };
+@@ -326,9 +329,21 @@ static struct clk *hdmi_parent[] = {
+       [2] = &dv_clk
+ };
++static struct clk *vclk_parents[8] = {
++      [0] = &pllc1_div2_clk,
++      [2] = &dv_clk,
++      [3] = &usb24s_clk,
++      [4] = &extal1_div2_clk,
++      [5] = &extalr_clk,
++};
++
+ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
+       [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
+                                     hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
++      [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0,
++                                     vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
++      [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
++                                     vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
+ };
+ /* HDMI1/2 clock */
+@@ -417,7 +432,7 @@ static struct clk div6_clks[DIV6_NR] = {
+ };
+ enum {
+-      MSTP125,
++      MSTP128, MSTP127, MSTP125,
+       MSTP116, MSTP111, MSTP100, MSTP117,
+       MSTP230,
+@@ -434,6 +449,8 @@ enum {
+ };
+ static struct clk mstp_clks[MSTP_NR] = {
++      [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S],   SMSTPCR1, 28, 0), /* CEU21 */
++      [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S],   SMSTPCR1, 27, 0), /* CEU20 */
+       [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
+       [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B],   SMSTPCR1, 17, 0), /* LCDC1 */
+       [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
+@@ -484,6 +501,8 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_CON_ID("usb24s",                 &usb24s_clk),
+       CLKDEV_CON_ID("hdmi1",                  &hdmi1_clk),
+       CLKDEV_CON_ID("hdmi2",                  &hdmi2_clk),
++      CLKDEV_CON_ID("video1",                 &div6_reparent_clks[DIV6_VCLK1]),
++      CLKDEV_CON_ID("video2",                 &div6_reparent_clks[DIV6_VCLK2]),
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("i_clk",                  &div4_clks[DIV4_I]),
+@@ -506,6 +525,8 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("i2c-sh_mobile.0",        &mstp_clks[MSTP116]),
+       CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1",    &mstp_clks[MSTP117]),
+       CLKDEV_DEV_ID("sh_tmu.0",               &mstp_clks[MSTP125]),
++      CLKDEV_DEV_ID("sh_mobile_ceu.0",        &mstp_clks[MSTP127]),
++      CLKDEV_DEV_ID("sh_mobile_ceu.1",        &mstp_clks[MSTP128]),
+       CLKDEV_DEV_ID("sh-sci.4",               &mstp_clks[MSTP200]),
+       CLKDEV_DEV_ID("sh-sci.3",               &mstp_clks[MSTP201]),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch b/patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch
new file mode 100644 (file)
index 0000000..f4e6143
--- /dev/null
@@ -0,0 +1,125 @@
+From 3380d7910c8f2625a74337bd1a3f1d81bc146c73 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:36:58 -0700
+Subject: ARM: shmobile: r8a7740: add FSI parent clock support
+
+r8a7740 FSI can select its parent clock,
+and its selection is dependent on platform board.
+
+In order to enable FSI parent selection from platform board,
+this patch adds its interface to clock framework.
+
+This patch is based on v1.0 manual
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 69efac9a8bc6d479bc4c339ae4ac4d353460def6)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index ce0930a..7b9e4ab 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -46,6 +46,7 @@
+ #define VCLKCR1               0xE6150008
+ #define VCLKCR2               0xE615000c
+ #define FRQCRC                0xe61500e0
++#define FSIACKCR      0xe6150018
+ #define PLLC01CR      0xe6150028
+ #define SUBCKCR               0xe6150080
+@@ -56,6 +57,7 @@
+ #define MSTPSR2               0xe6150040
+ #define MSTPSR3               0xe6150048
+ #define MSTPSR4               0xe615004c
++#define FSIBCKCR      0xe6150090
+ #define HDMICKCR      0xe6150094
+ #define SMSTPCR0      0xe6150130
+ #define SMSTPCR1      0xe6150134
+@@ -274,6 +276,13 @@ static struct clk usb24_clk = {
+       .parent         = &usb24s_clk,
+ };
++/* External FSIACK/FSIBCK clock */
++static struct clk fsiack_clk = {
++};
++
++static struct clk fsibck_clk = {
++};
++
+ struct clk *main_clks[] = {
+       &extalr_clk,
+       &extal1_clk,
+@@ -291,6 +300,8 @@ struct clk *main_clks[] = {
+       &pllc1_div2_clk,
+       &usb24s_clk,
+       &usb24_clk,
++      &fsiack_clk,
++      &fsibck_clk,
+ };
+ static void div4_kick(struct clk *clk)
+@@ -320,6 +331,7 @@ static struct clk_div4_table div4_table = {
+ enum {
+       DIV6_HDMI,
+       DIV6_VCLK1, DIV6_VCLK2,
++      DIV6_FSIA, DIV6_FSIB,
+       DIV6_REPARENT_NR,
+ };
+@@ -337,6 +349,16 @@ static struct clk *vclk_parents[8] = {
+       [5] = &extalr_clk,
+ };
++static struct clk *fsia_parents[] = {
++      [0] = &pllc1_div2_clk,
++      [1] = &fsiack_clk, /* external clock */
++};
++
++static struct clk *fsib_parents[] = {
++      [0] = &pllc1_div2_clk,
++      [1] = &fsibck_clk, /* external clock */
++};
++
+ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
+       [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
+                                     hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
+@@ -344,6 +366,10 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
+                                      vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
+       [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
+                                      vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
++      [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
++                                    fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2),
++      [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
++                                    fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
+ };
+ /* HDMI1/2 clock */
+@@ -503,6 +529,8 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_CON_ID("hdmi2",                  &hdmi2_clk),
+       CLKDEV_CON_ID("video1",                 &div6_reparent_clks[DIV6_VCLK1]),
+       CLKDEV_CON_ID("video2",                 &div6_reparent_clks[DIV6_VCLK2]),
++      CLKDEV_CON_ID("fsiack",                 &fsiack_clk),
++      CLKDEV_CON_ID("fsibck",                 &fsibck_clk),
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("i_clk",                  &div4_clks[DIV4_I]),
+@@ -557,6 +585,9 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_ICK_ID("pci",    "renesas_usbhs",        &div4_clks[DIV4_USBP]),
+       CLKDEV_ICK_ID("usb24",  "renesas_usbhs",        &usb24_clk),
+       CLKDEV_ICK_ID("ick",    "sh-mobile-hdmi",       &div6_reparent_clks[DIV6_HDMI]),
++
++      CLKDEV_ICK_ID("icka", "sh_fsi2",        &div6_reparent_clks[DIV6_FSIA]),
++      CLKDEV_ICK_ID("ickb", "sh_fsi2",        &div6_reparent_clks[DIV6_FSIB]),
+ };
+ void __init r8a7740_clock_init(u8 md_ck)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch b/patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch
new file mode 100644 (file)
index 0000000..ddaab4f
--- /dev/null
@@ -0,0 +1,97 @@
+From ead2de820556aa2682e1505f691a5207365d4e69 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:37:16 -0700
+Subject: ARM: shmobile: r8a7740: add FSI-B (for HDMI) GPIO support
+
+In order to enable FSI-B selection from platform board,
+this patch adds its interface to GPIO framework.
+
+This patch is based on v1.0 manual
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 147d1ffdc21d067f0084f0911dbf1eee57e3d76b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/r8a7740.h |  5 ++++-
+ arch/arm/mach-shmobile/pfc-r8a7740.c          | 11 +++++++++--
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index 2764846..6468fcc 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -139,7 +139,7 @@ enum {
+       GPIO_FN_DBGMD10,        GPIO_FN_DBGMD11,        GPIO_FN_DBGMD20,
+       GPIO_FN_DBGMD21,
+-      /* FSI */
++      /* FSI-A */
+       GPIO_FN_FSIAISLD_PORT0,         /* FSIAISLD Port 0/5 */
+       GPIO_FN_FSIAISLD_PORT5,
+       GPIO_FN_FSIASPDIF_PORT9,        /* FSIASPDIF Port 9/18 */
+@@ -150,6 +150,9 @@ enum {
+       GPIO_FN_FSIACK,         GPIO_FN_FSIAILR,
+       GPIO_FN_FSIAIBT,
++      /* FSI-B */
++      GPIO_FN_FSIBCK,
++
+       /* FMSI */
+       GPIO_FN_FMSISLD_PORT1, /* FMSISLD Port 1/6 */
+       GPIO_FN_FMSISLD_PORT6,
+diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
+index 0dda816..03def0f 100644
+--- a/arch/arm/mach-shmobile/pfc-r8a7740.c
++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
+@@ -169,7 +169,7 @@ enum {
+       DBGMD10_MARK,   DBGMD11_MARK,   DBGMD20_MARK,
+       DBGMD21_MARK,
+-      /* FSI */
++      /* FSI-A */
+       FSIAISLD_PORT0_MARK,    /* FSIAISLD Port 0/5 */
+       FSIAISLD_PORT5_MARK,
+       FSIASPDIF_PORT9_MARK,   /* FSIASPDIF Port 9/18 */
+@@ -178,6 +178,9 @@ enum {
+       FSIAOBT_MARK,   FSIAOSLD_MARK,  FSIAOMC_MARK,
+       FSIACK_MARK,    FSIAILR_MARK,   FSIAIBT_MARK,
++      /* FSI-B */
++      FSIBCK_MARK,
++
+       /* FMSI */
+       FMSISLD_PORT1_MARK, /* FMSISLD Port 1/6 */
+       FMSISLD_PORT6_MARK,
+@@ -774,6 +777,7 @@ static pinmux_enum_t pinmux_data[] = {
+       /* Port11 */
+       PINMUX_DATA(FSIACK_MARK,                PORT11_FN1),
++      PINMUX_DATA(FSIBCK_MARK,                PORT11_FN2),
+       PINMUX_DATA(IRQ2_PORT11_MARK,           PORT11_FN0,     MSEL1CR_2_0),
+       /* Port12 */
+@@ -1696,7 +1700,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
+       GPIO_FN(DBGMD10),       GPIO_FN(DBGMD11),       GPIO_FN(DBGMD20),
+       GPIO_FN(DBGMD21),
+-      /* FSI */
++      /* FSI-A */
+       GPIO_FN(FSIAISLD_PORT0),        /* FSIAISLD Port 0/5 */
+       GPIO_FN(FSIAISLD_PORT5),
+       GPIO_FN(FSIASPDIF_PORT9),       /* FSIASPDIF Port 9/18 */
+@@ -1705,6 +1709,9 @@ static struct pinmux_gpio pinmux_gpios[] = {
+       GPIO_FN(FSIAOBT),       GPIO_FN(FSIAOSLD),      GPIO_FN(FSIAOMC),
+       GPIO_FN(FSIACK),        GPIO_FN(FSIAILR),       GPIO_FN(FSIAIBT),
++      /* FSI-B */
++      GPIO_FN(FSIBCK),
++
+       /* FMSI */
+       GPIO_FN(FMSISLD_PORT1), /* FMSISLD Port 1/6 */
+       GPIO_FN(FMSISLD_PORT6),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch b/patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch
new file mode 100644 (file)
index 0000000..731d6c1
--- /dev/null
@@ -0,0 +1,197 @@
+From e92cdf42dfe94be35bc251b5eaa9a0db2c8679e9 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:39:11 -0700
+Subject: ARM: shmobile: armadillo800eva: enable HDMI
+
+This patch enable HDMI support on CON3.
+And removed unnecessary CONFIG_SYSFS_DEPRECATED_xxx config.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 910c14d0b8f121df420a878cbd973ffa7d549393)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/configs/armadillo800eva_defconfig     |  10 +--
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 100 +++++++++++++++++++++++++
+ 2 files changed, 101 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
+index ddc9fe6..f6ebdde 100644
+--- a/arch/arm/configs/armadillo800eva_defconfig
++++ b/arch/arm/configs/armadillo800eva_defconfig
+@@ -5,10 +5,7 @@ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=16
+ # CONFIG_UTS_NS is not set
+ # CONFIG_IPC_NS is not set
+-# CONFIG_USER_NS is not set
+ # CONFIG_PID_NS is not set
+-CONFIG_SYSFS_DEPRECATED=y
+-CONFIG_SYSFS_DEPRECATED_V2=y
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_SLAB=y
+ CONFIG_MODULES=y
+@@ -90,25 +87,21 @@ CONFIG_I2C=y
+ CONFIG_I2C_SH_MOBILE=y
+ # CONFIG_HWMON is not set
+ CONFIG_FB=y
+-CONFIG_FB_MODE_HELPERS=y
+ CONFIG_FB_SH_MOBILE_LCDC=y
++CONFIG_FB_SH_MOBILE_HDMI=y
+ CONFIG_LCD_CLASS_DEVICE=y
+ CONFIG_FRAMEBUFFER_CONSOLE=y
+ CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+ CONFIG_LOGO=y
+ # CONFIG_LOGO_LINUX_MONO is not set
+ # CONFIG_LOGO_LINUX_VGA16 is not set
+-CONFIG_SOUND=y
+-CONFIG_SND=y
+ # CONFIG_SND_SUPPORT_OLD_API is not set
+ # CONFIG_SND_VERBOSE_PROCFS is not set
+ # CONFIG_SND_DRIVERS is not set
+ # CONFIG_SND_ARM is not set
+-CONFIG_SND_SOC=y
+ CONFIG_SND_SOC_SH4_FSI=y
+ # CONFIG_HID_SUPPORT is not set
+ CONFIG_USB=y
+-# CONFIG_USB_DEVICE_CLASS is not set
+ CONFIG_USB_RENESAS_USBHS=y
+ CONFIG_USB_GADGET=y
+ CONFIG_USB_RENESAS_USBHS_UDC=y
+@@ -124,7 +117,6 @@ CONFIG_VFAT_FS=y
+ CONFIG_TMPFS=y
+ # CONFIG_MISC_FILESYSTEMS is not set
+ CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+ CONFIG_NFS_V3_ACL=y
+ CONFIG_NFS_V4=y
+ CONFIG_NFS_V4_1=y
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 6e6839d..4e6893f 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -45,6 +45,7 @@
+ #include <asm/hardware/cache-l2x0.h>
+ #include <mach/r8a7740.h>
+ #include <video/sh_mobile_lcdc.h>
++#include <video/sh_mobile_hdmi.h>
+ /*
+  * CON1               Camera Module
+@@ -384,6 +385,103 @@ static struct platform_device lcdc0_device = {
+       },
+ };
++/*
++ * LCDC1/HDMI
++ */
++static struct sh_mobile_hdmi_info hdmi_info = {
++      .flags          = HDMI_OUTPUT_PUSH_PULL |
++                        HDMI_OUTPUT_POLARITY_HI |
++                        HDMI_32BIT_REG |
++                        HDMI_HAS_HTOP1 |
++                        HDMI_SND_SRC_SPDIF,
++};
++
++static struct resource hdmi_resources[] = {
++      [0] = {
++              .name   = "HDMI",
++              .start  = 0xe6be0000,
++              .end    = 0xe6be03ff,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = evt2irq(0x1700),
++              .flags  = IORESOURCE_IRQ,
++      },
++      [2] = {
++              .name   = "HDMI emma3pf",
++              .start  = 0xe6be4000,
++              .end    = 0xe6be43ff,
++              .flags  = IORESOURCE_MEM,
++      },
++};
++
++static struct platform_device hdmi_device = {
++      .name           = "sh-mobile-hdmi",
++      .num_resources  = ARRAY_SIZE(hdmi_resources),
++      .resource       = hdmi_resources,
++      .id             = -1,
++      .dev    = {
++              .platform_data  = &hdmi_info,
++      },
++};
++
++static const struct fb_videomode lcdc1_mode = {
++      .name           = "HDMI 720p",
++      .xres           = 1280,
++      .yres           = 720,
++      .pixclock       = 13468,
++      .left_margin    = 220,
++      .right_margin   = 110,
++      .hsync_len      = 40,
++      .upper_margin   = 20,
++      .lower_margin   = 5,
++      .vsync_len      = 5,
++      .refresh        = 60,
++      .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
++};
++
++static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
++      .clock_source   = LCDC_CLK_PERIPHERAL, /* HDMI clock */
++      .ch[0] = {
++              .chan                   = LCDC_CHAN_MAINLCD,
++              .fourcc                 = V4L2_PIX_FMT_RGB565,
++              .interface_type         = RGB24,
++              .clock_divider          = 1,
++              .flags                  = LCDC_FLAGS_DWPOL,
++              .lcd_modes              = &lcdc1_mode,
++              .num_modes              = 1,
++              .tx_dev                 = &hdmi_device,
++              .panel_cfg = {
++                      .width  = 1280,
++                      .height = 720,
++              },
++      },
++};
++
++static struct resource hdmi_lcdc_resources[] = {
++      [0] = {
++              .name   = "LCDC1",
++              .start  = 0xfe944000,
++              .end    = 0xfe948000 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = intcs_evt2irq(0x1780),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device hdmi_lcdc_device = {
++      .name           = "sh_mobile_lcdc_fb",
++      .num_resources  = ARRAY_SIZE(hdmi_lcdc_resources),
++      .resource       = hdmi_lcdc_resources,
++      .id             = 1,
++      .dev    = {
++              .platform_data  = &hdmi_lcdc_info,
++              .coherent_dma_mask = ~0,
++      },
++};
++
+ /* GPIO KEY */
+ #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+@@ -549,6 +647,8 @@ static struct platform_device *eva_devices[] __initdata = {
+       &sh_eth_device,
+       &sdhi0_device,
+       &sh_mmcif_device,
++      &hdmi_device,
++      &hdmi_lcdc_device,
+ };
+ static void __init eva_clock_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch b/patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch
new file mode 100644 (file)
index 0000000..5854c1f
--- /dev/null
@@ -0,0 +1,35 @@
+From e942f8cdf5f982742f6bc8cb49fd546bb828ffce Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 20 Jun 2012 12:53:25 +0200
+Subject: ARM: mach-shmobile: armadillo800eva: Use late init machine hook
+
+Since commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111 ("ARM: shmobile:
+use machine specific hook for late init") suspend and CPU idle are not
+initialized automatically anymore. Set shmobile_init_late() as the
+machine late init hook to initialize them.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 37f971b68009b8fadd322130787d693137302925)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 4e6893f..bbf5ccff 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -880,6 +880,7 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva")
+       .init_irq       = r8a7740_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
+       .init_machine   = eva_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+       .dt_compat      = eva_boards_compat_dt,
+ MACHINE_END
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch b/patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch
new file mode 100644 (file)
index 0000000..28a60b6
--- /dev/null
@@ -0,0 +1,192 @@
+From c7934751659fc8d58c97d51edc6fdb5af8307330 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:40:07 -0700
+Subject: ARM: shmobile: armadillo800eva: enable camera
+
+This patch enable camera support on CON1
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 3760e79450f48e31fde2b2dd49c5ab6a685c3ea8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/configs/armadillo800eva_defconfig     |  10 +++
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 111 ++++++++++++++++++++++++-
+ 2 files changed, 120 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
+index f6ebdde..df1ce54 100644
+--- a/arch/arm/configs/armadillo800eva_defconfig
++++ b/arch/arm/configs/armadillo800eva_defconfig
+@@ -86,6 +86,16 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
+ CONFIG_I2C=y
+ CONFIG_I2C_SH_MOBILE=y
+ # CONFIG_HWMON is not set
++CONFIG_MEDIA_SUPPORT=y
++CONFIG_VIDEO_DEV=y
++# CONFIG_RC_CORE is not set
++# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
++# CONFIG_V4L_USB_DRIVERS is not set
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_SOC_CAMERA=y
++CONFIG_SOC_CAMERA_MT9T112=y
++CONFIG_VIDEO_SH_MOBILE_CEU=y
++# CONFIG_RADIO_ADAPTERS is not set
+ CONFIG_FB=y
+ CONFIG_FB_SH_MOBILE_LCDC=y
+ CONFIG_FB_SH_MOBILE_HDMI=y
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index bbf5ccff..a513ebe 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -37,13 +37,16 @@
+ #include <linux/mmc/sh_mobile_sdhi.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
++#include <mach/r8a7740.h>
++#include <media/mt9t112.h>
++#include <media/sh_mobile_ceu.h>
++#include <media/soc_camera.h>
+ #include <asm/page.h>
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/time.h>
+ #include <asm/hardware/cache-l2x0.h>
+-#include <mach/r8a7740.h>
+ #include <video/sh_mobile_lcdc.h>
+ #include <video/sh_mobile_hdmi.h>
+@@ -630,6 +633,87 @@ static struct platform_device sh_mmcif_device = {
+       .resource       = sh_mmcif_resources,
+ };
++/* Camera */
++static int mt9t111_power(struct device *dev, int mode)
++{
++      struct clk *mclk = clk_get(NULL, "video1");
++
++      if (IS_ERR(mclk)) {
++              dev_err(dev, "can't get video1 clock\n");
++              return -EINVAL;
++      }
++
++      if (mode) {
++              /* video1 (= CON1 camera) expect 24MHz */
++              clk_set_rate(mclk, clk_round_rate(mclk, 24000000));
++              clk_enable(mclk);
++              gpio_direction_output(GPIO_PORT158, 1);
++      } else {
++              gpio_direction_output(GPIO_PORT158, 0);
++              clk_disable(mclk);
++      }
++
++      clk_put(mclk);
++
++      return 0;
++}
++
++static struct i2c_board_info i2c_camera_mt9t111 = {
++      I2C_BOARD_INFO("mt9t112", 0x3d),
++};
++
++static struct mt9t112_camera_info mt9t111_info = {
++      .divider = { 16, 0, 0, 7, 0, 10, 14, 7, 7 },
++};
++
++static struct soc_camera_link mt9t111_link = {
++      .i2c_adapter_id = 0,
++      .bus_id         = 0,
++      .board_info     = &i2c_camera_mt9t111,
++      .power          = mt9t111_power,
++      .priv           = &mt9t111_info,
++};
++
++static struct platform_device camera_device = {
++      .name   = "soc-camera-pdrv",
++      .id     = 0,
++      .dev    = {
++              .platform_data = &mt9t111_link,
++      },
++};
++
++/* CEU0 */
++static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
++      .flags = SH_CEU_FLAG_LOWER_8BIT,
++};
++
++static struct resource ceu0_resources[] = {
++      [0] = {
++              .name   = "CEU",
++              .start  = 0xfe910000,
++              .end    = 0xfe91009f,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = intcs_evt2irq(0x0500),
++              .flags  = IORESOURCE_IRQ,
++      },
++      [2] = {
++              /* place holder for contiguous memory */
++      },
++};
++
++static struct platform_device ceu0_device = {
++      .name           = "sh_mobile_ceu",
++      .id             = 0,
++      .num_resources  = ARRAY_SIZE(ceu0_resources),
++      .resource       = ceu0_resources,
++      .dev    = {
++              .platform_data          = &sh_mobile_ceu0_info,
++              .coherent_dma_mask      = 0xffffffff,
++      },
++};
++
+ /* I2C */
+ static struct i2c_board_info i2c0_devices[] = {
+       {
+@@ -649,6 +733,8 @@ static struct platform_device *eva_devices[] __initdata = {
+       &sh_mmcif_device,
+       &hdmi_device,
+       &hdmi_lcdc_device,
++      &camera_device,
++      &ceu0_device,
+ };
+ static void __init eva_clock_init(void)
+@@ -807,6 +893,29 @@ static void __init eva_init(void)
+       gpio_request(GPIO_FN_MMC1_D6_PORT143,   NULL);
+       gpio_request(GPIO_FN_MMC1_D7_PORT142,   NULL);
++      /* CEU0 */
++      gpio_request(GPIO_FN_VIO0_D7,           NULL);
++      gpio_request(GPIO_FN_VIO0_D6,           NULL);
++      gpio_request(GPIO_FN_VIO0_D5,           NULL);
++      gpio_request(GPIO_FN_VIO0_D4,           NULL);
++      gpio_request(GPIO_FN_VIO0_D3,           NULL);
++      gpio_request(GPIO_FN_VIO0_D2,           NULL);
++      gpio_request(GPIO_FN_VIO0_D1,           NULL);
++      gpio_request(GPIO_FN_VIO0_D0,           NULL);
++      gpio_request(GPIO_FN_VIO0_CLK,          NULL);
++      gpio_request(GPIO_FN_VIO0_HD,           NULL);
++      gpio_request(GPIO_FN_VIO0_VD,           NULL);
++      gpio_request(GPIO_FN_VIO0_FIELD,        NULL);
++      gpio_request(GPIO_FN_VIO_CKO,           NULL);
++
++      /* CON1/CON15 Camera */
++      gpio_request(GPIO_PORT173, NULL); /* STANDBY */
++      gpio_request(GPIO_PORT172, NULL); /* RST */
++      gpio_request(GPIO_PORT158, NULL); /* CAM_PON */
++      gpio_direction_output(GPIO_PORT173, 0);
++      gpio_direction_output(GPIO_PORT172, 1);
++      gpio_direction_output(GPIO_PORT158, 0); /* see mt9t111_power() */
++
+       /*
+        * CAUTION
+        *
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch b/patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch
new file mode 100644 (file)
index 0000000..5f28f1e
--- /dev/null
@@ -0,0 +1,299 @@
+From 0e0018e5c4b1d2d6c6fe9d67a8c5916752884589 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:36:49 -0700
+Subject: ARM: shmobile: r8a7740: add DMAEngine support for FSI
+
+Current shdmac can support FSI DMAC on r8a7740.
+This support reduce CPU duty when sound was playback.
+
+This patch is based on v1.0 manual
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 643c3307bbbe7e80c6693376137971fbdcbe1c82)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c        |   8 +-
+ arch/arm/mach-shmobile/include/mach/r8a7740.h |   8 ++
+ arch/arm/mach-shmobile/setup-r8a7740.c        | 198 ++++++++++++++++++++++++++
+ 3 files changed, 213 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index 7b9e4ab..39b1311 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -463,6 +463,7 @@ enum {
+       MSTP230,
+       MSTP222,
++      MSTP218, MSTP217, MSTP216,
+       MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+       MSTP329, MSTP328, MSTP323, MSTP320,
+@@ -485,6 +486,9 @@ static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */
+       [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */
++      [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 18, 0), /* DMAC1 */
++      [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 17, 0), /* DMAC2 */
++      [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 16, 0), /* DMAC3 */
+       [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2,  7, 0), /* SCIFA5 */
+       [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2,  6, 0), /* SCIFB */
+       [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2,  4, 0), /* SCIFA0 */
+@@ -563,7 +567,9 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("sh-sci.0",               &mstp_clks[MSTP204]),
+       CLKDEV_DEV_ID("sh-sci.8",               &mstp_clks[MSTP206]),
+       CLKDEV_DEV_ID("sh-sci.5",               &mstp_clks[MSTP207]),
+-
++      CLKDEV_DEV_ID("sh-dma-engine.2",        &mstp_clks[MSTP216]),
++      CLKDEV_DEV_ID("sh-dma-engine.1",        &mstp_clks[MSTP217]),
++      CLKDEV_DEV_ID("sh-dma-engine.0",        &mstp_clks[MSTP218]),
+       CLKDEV_DEV_ID("sh-sci.7",               &mstp_clks[MSTP222]),
+       CLKDEV_DEV_ID("sh-sci.6",               &mstp_clks[MSTP230]),
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index 6468fcc..f71507b 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -588,4 +588,12 @@ enum {
+       GPIO_FN_TRACEAUD_FROM_MEMC,
+ };
++/* DMA slave IDs */
++enum {
++      SHDMA_SLAVE_INVALID,
++      SHDMA_SLAVE_FSIA_RX,
++      SHDMA_SLAVE_FSIA_TX,
++      SHDMA_SLAVE_FSIB_TX,
++};
++
+ #endif /* __ASM_R8A7740_H__ */
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 366311b..516a7ec 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -24,7 +24,9 @@
+ #include <linux/io.h>
+ #include <linux/platform_device.h>
+ #include <linux/serial_sci.h>
++#include <linux/sh_dma.h>
+ #include <linux/sh_timer.h>
++#include <linux/dma-mapping.h>
+ #include <mach/r8a7740.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+@@ -276,6 +278,199 @@ static struct platform_device *r8a7740_early_devices[] __initdata = {
+       &cmt10_device,
+ };
++/* DMA */
++enum {
++      XMIT_SZ_8BIT            = 0,
++      XMIT_SZ_16BIT           = 1,
++      XMIT_SZ_32BIT           = 2,
++      XMIT_SZ_64BIT           = 7,
++      XMIT_SZ_128BIT          = 3,
++      XMIT_SZ_256BIT          = 4,
++      XMIT_SZ_512BIT          = 5,
++};
++
++/* log2(size / 8) - used to calculate number of transfers */
++#define TS_SHIFT {                    \
++      [XMIT_SZ_8BIT]          = 0,    \
++      [XMIT_SZ_16BIT]         = 1,    \
++      [XMIT_SZ_32BIT]         = 2,    \
++      [XMIT_SZ_64BIT]         = 3,    \
++      [XMIT_SZ_128BIT]        = 4,    \
++      [XMIT_SZ_256BIT]        = 5,    \
++      [XMIT_SZ_512BIT]        = 6,    \
++}
++
++#define TS_INDEX2VAL(i) ((((i) & 0x3) << 3) | (((i) & 0xc) << (20 - 2)))
++#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
++#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
++
++static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
++      {
++              .slave_id       = SHDMA_SLAVE_FSIA_TX,
++              .addr           = 0xfe1f0024,
++              .chcr           = CHCR_TX(XMIT_SZ_32BIT),
++              .mid_rid        = 0xb1,
++      }, {
++              .slave_id       = SHDMA_SLAVE_FSIA_RX,
++              .addr           = 0xfe1f0020,
++              .chcr           = CHCR_RX(XMIT_SZ_32BIT),
++              .mid_rid        = 0xb2,
++      }, {
++              .slave_id       = SHDMA_SLAVE_FSIB_TX,
++              .addr           = 0xfe1f0064,
++              .chcr           = CHCR_TX(XMIT_SZ_32BIT),
++              .mid_rid        = 0xb5,
++      },
++};
++
++#define DMA_CHANNEL(a, b, c)                  \
++{                                             \
++      .offset         = a,                    \
++      .dmars          = b,                    \
++      .dmars_bit      = c,                    \
++      .chclr_offset   = (0x220 - 0x20) + a    \
++}
++
++static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
++      DMA_CHANNEL(0x00, 0, 0),
++      DMA_CHANNEL(0x10, 0, 8),
++      DMA_CHANNEL(0x20, 4, 0),
++      DMA_CHANNEL(0x30, 4, 8),
++      DMA_CHANNEL(0x50, 8, 0),
++      DMA_CHANNEL(0x60, 8, 8),
++};
++
++static const unsigned int ts_shift[] = TS_SHIFT;
++
++static struct sh_dmae_pdata dma_platform_data = {
++      .slave          = r8a7740_dmae_slaves,
++      .slave_num      = ARRAY_SIZE(r8a7740_dmae_slaves),
++      .channel        = r8a7740_dmae_channels,
++      .channel_num    = ARRAY_SIZE(r8a7740_dmae_channels),
++      .ts_low_shift   = 3,
++      .ts_low_mask    = 0x18,
++      .ts_high_shift  = (20 - 2),
++      .ts_high_mask   = 0x00300000,
++      .ts_shift       = ts_shift,
++      .ts_shift_num   = ARRAY_SIZE(ts_shift),
++      .dmaor_init     = DMAOR_DME,
++      .chclr_present  = 1,
++};
++
++/* Resource order important! */
++static struct resource r8a7740_dmae0_resources[] = {
++      {
++              /* Channel registers and DMAOR */
++              .start  = 0xfe008020,
++              .end    = 0xfe00828f,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              /* DMARSx */
++              .start  = 0xfe009000,
++              .end    = 0xfe00900b,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              .name   = "error_irq",
++              .start  = evt2irq(0x20c0),
++              .end    = evt2irq(0x20c0),
++              .flags  = IORESOURCE_IRQ,
++      },
++      {
++              /* IRQ for channels 0-5 */
++              .start  = evt2irq(0x2000),
++              .end    = evt2irq(0x20a0),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++/* Resource order important! */
++static struct resource r8a7740_dmae1_resources[] = {
++      {
++              /* Channel registers and DMAOR */
++              .start  = 0xfe018020,
++              .end    = 0xfe01828f,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              /* DMARSx */
++              .start  = 0xfe019000,
++              .end    = 0xfe01900b,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              .name   = "error_irq",
++              .start  = evt2irq(0x21c0),
++              .end    = evt2irq(0x21c0),
++              .flags  = IORESOURCE_IRQ,
++      },
++      {
++              /* IRQ for channels 0-5 */
++              .start  = evt2irq(0x2100),
++              .end    = evt2irq(0x21a0),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++/* Resource order important! */
++static struct resource r8a7740_dmae2_resources[] = {
++      {
++              /* Channel registers and DMAOR */
++              .start  = 0xfe028020,
++              .end    = 0xfe02828f,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              /* DMARSx */
++              .start  = 0xfe029000,
++              .end    = 0xfe02900b,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              .name   = "error_irq",
++              .start  = evt2irq(0x22c0),
++              .end    = evt2irq(0x22c0),
++              .flags  = IORESOURCE_IRQ,
++      },
++      {
++              /* IRQ for channels 0-5 */
++              .start  = evt2irq(0x2200),
++              .end    = evt2irq(0x22a0),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device dma0_device = {
++      .name           = "sh-dma-engine",
++      .id             = 0,
++      .resource       = r8a7740_dmae0_resources,
++      .num_resources  = ARRAY_SIZE(r8a7740_dmae0_resources),
++      .dev            = {
++              .platform_data  = &dma_platform_data,
++      },
++};
++
++static struct platform_device dma1_device = {
++      .name           = "sh-dma-engine",
++      .id             = 1,
++      .resource       = r8a7740_dmae1_resources,
++      .num_resources  = ARRAY_SIZE(r8a7740_dmae1_resources),
++      .dev            = {
++              .platform_data  = &dma_platform_data,
++      },
++};
++
++static struct platform_device dma2_device = {
++      .name           = "sh-dma-engine",
++      .id             = 2,
++      .resource       = r8a7740_dmae2_resources,
++      .num_resources  = ARRAY_SIZE(r8a7740_dmae2_resources),
++      .dev            = {
++              .platform_data  = &dma_platform_data,
++      },
++};
++
+ /* I2C */
+ static struct resource i2c0_resources[] = {
+       [0] = {
+@@ -322,6 +517,9 @@ static struct platform_device i2c1_device = {
+ static struct platform_device *r8a7740_late_devices[] __initdata = {
+       &i2c0_device,
+       &i2c1_device,
++      &dma0_device,
++      &dma1_device,
++      &dma2_device,
+ };
+ /*
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch b/patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch
new file mode 100644 (file)
index 0000000..c76b22f
--- /dev/null
@@ -0,0 +1,80 @@
+From b96167a50df2468ba7f7eb96fab0bec5e0ee7106 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:37:00 -0700
+Subject: ARM: shmobile: r8a7740: add DMAEngine support for SDHI
+
+Current shdmac can support SDHI DMAC on r8a7740.
+This support reduce CPU duty when SDHI access.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit cb76eb812ee03187da3b46e190895b55019d2133)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/r8a7740.h |  6 ++++++
+ arch/arm/mach-shmobile/setup-r8a7740.c        | 30 +++++++++++++++++++++++++++
+ 2 files changed, 36 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index f71507b..0f14ce8 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -591,6 +591,12 @@ enum {
+ /* DMA slave IDs */
+ enum {
+       SHDMA_SLAVE_INVALID,
++      SHDMA_SLAVE_SDHI0_RX,
++      SHDMA_SLAVE_SDHI0_TX,
++      SHDMA_SLAVE_SDHI1_RX,
++      SHDMA_SLAVE_SDHI1_TX,
++      SHDMA_SLAVE_SDHI2_RX,
++      SHDMA_SLAVE_SDHI2_TX,
+       SHDMA_SLAVE_FSIA_RX,
+       SHDMA_SLAVE_FSIA_TX,
+       SHDMA_SLAVE_FSIB_TX,
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 516a7ec..320c43a 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -306,6 +306,36 @@ enum {
+ static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
+       {
++              .slave_id       = SHDMA_SLAVE_SDHI0_TX,
++              .addr           = 0xe6850030,
++              .chcr           = CHCR_TX(XMIT_SZ_16BIT),
++              .mid_rid        = 0xc1,
++      }, {
++              .slave_id       = SHDMA_SLAVE_SDHI0_RX,
++              .addr           = 0xe6850030,
++              .chcr           = CHCR_RX(XMIT_SZ_16BIT),
++              .mid_rid        = 0xc2,
++      }, {
++              .slave_id       = SHDMA_SLAVE_SDHI1_TX,
++              .addr           = 0xe6860030,
++              .chcr           = CHCR_TX(XMIT_SZ_16BIT),
++              .mid_rid        = 0xc9,
++      }, {
++              .slave_id       = SHDMA_SLAVE_SDHI1_RX,
++              .addr           = 0xe6860030,
++              .chcr           = CHCR_RX(XMIT_SZ_16BIT),
++              .mid_rid        = 0xca,
++      }, {
++              .slave_id       = SHDMA_SLAVE_SDHI2_TX,
++              .addr           = 0xe6870030,
++              .chcr           = CHCR_TX(XMIT_SZ_16BIT),
++              .mid_rid        = 0xcd,
++      }, {
++              .slave_id       = SHDMA_SLAVE_SDHI2_RX,
++              .addr           = 0xe6870030,
++              .chcr           = CHCR_RX(XMIT_SZ_16BIT),
++              .mid_rid        = 0xce,
++      }, {
+               .slave_id       = SHDMA_SLAVE_FSIA_TX,
+               .addr           = 0xfe1f0024,
+               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch b/patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch
new file mode 100644 (file)
index 0000000..4384aca
--- /dev/null
@@ -0,0 +1,170 @@
+From 59ea669a42f7a0fa16df6d769a6843d3060b64f2 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:37:10 -0700
+Subject: ARM: shmobile: r8a7740: add DMAEngine support for USB
+
+Current shdmac can support USB DMAC on r8a7740.
+This support reduce CPU duty when USB access.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit dbf382e556931aa75b2d7970d64661544d6c327c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c        |  4 +-
+ arch/arm/mach-shmobile/include/mach/r8a7740.h |  2 +
+ arch/arm/mach-shmobile/setup-r8a7740.c        | 87 +++++++++++++++++++++++++++
+ 3 files changed, 92 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index 39b1311..daf3eac 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -463,7 +463,7 @@ enum {
+       MSTP230,
+       MSTP222,
+-      MSTP218, MSTP217, MSTP216,
++      MSTP218, MSTP217, MSTP216, MSTP214,
+       MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+       MSTP329, MSTP328, MSTP323, MSTP320,
+@@ -489,6 +489,7 @@ static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 18, 0), /* DMAC1 */
+       [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 17, 0), /* DMAC2 */
+       [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 16, 0), /* DMAC3 */
++      [MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 14, 0), /* USBDMAC */
+       [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2,  7, 0), /* SCIFA5 */
+       [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2,  6, 0), /* SCIFB */
+       [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2,  4, 0), /* SCIFA0 */
+@@ -567,6 +568,7 @@ static struct clk_lookup lookups[] = {
+       CLKDEV_DEV_ID("sh-sci.0",               &mstp_clks[MSTP204]),
+       CLKDEV_DEV_ID("sh-sci.8",               &mstp_clks[MSTP206]),
+       CLKDEV_DEV_ID("sh-sci.5",               &mstp_clks[MSTP207]),
++      CLKDEV_DEV_ID("sh-dma-engine.3",        &mstp_clks[MSTP214]),
+       CLKDEV_DEV_ID("sh-dma-engine.2",        &mstp_clks[MSTP216]),
+       CLKDEV_DEV_ID("sh-dma-engine.1",        &mstp_clks[MSTP217]),
+       CLKDEV_DEV_ID("sh-dma-engine.0",        &mstp_clks[MSTP218]),
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index 0f14ce8..8bd7b9c 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -600,6 +600,8 @@ enum {
+       SHDMA_SLAVE_FSIA_RX,
+       SHDMA_SLAVE_FSIA_TX,
+       SHDMA_SLAVE_FSIB_TX,
++      SHDMA_SLAVE_USBHS_TX,
++      SHDMA_SLAVE_USBHS_RX,
+ };
+ #endif /* __ASM_R8A7740_H__ */
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 320c43a..5e84609 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -501,6 +501,92 @@ static struct platform_device dma2_device = {
+       },
+ };
++/* USB-DMAC */
++/* Transmit sizes and respective CHCR register values */
++enum {
++      USBTS_XMIT_SZ_8BYTE             = 0,
++      USBTS_XMIT_SZ_16BYTE            = 1,
++      USBTS_XMIT_SZ_32BYTE            = 2,
++};
++
++/* log2(size / 8) - used to calculate number of transfers */
++static const unsigned int dma_usbts_shift[] = {
++      [USBTS_XMIT_SZ_8BYTE]   = 3,
++      [USBTS_XMIT_SZ_16BYTE]  = 4,
++      [USBTS_XMIT_SZ_32BYTE]  = 5,
++};
++
++static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
++      {
++              .offset = 0,
++      }, {
++              .offset = 0x20,
++      },
++};
++
++#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
++
++static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = {
++      {
++              .slave_id       = SHDMA_SLAVE_USBHS_TX,
++              .chcr           = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
++      }, {
++              .slave_id       = SHDMA_SLAVE_USBHS_RX,
++              .chcr           = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
++      },
++};
++
++static struct sh_dmae_pdata usb_dma_platform_data = {
++      .slave          = r8a7740_usb_dma_slaves,
++      .slave_num      = ARRAY_SIZE(r8a7740_usb_dma_slaves),
++      .channel        = r8a7740_usb_dma_channels,
++      .channel_num    = ARRAY_SIZE(r8a7740_usb_dma_channels),
++      .ts_low_shift   = 6,
++      .ts_low_mask    = 0xc0,
++      .ts_high_shift  = 0,
++      .ts_high_mask   = 0,
++      .ts_shift       = dma_usbts_shift,
++      .ts_shift_num   = ARRAY_SIZE(dma_usbts_shift),
++      .dmaor_init     = DMAOR_DME,
++      .chcr_offset    = 0x14,
++      .chcr_ie_bit    = 1 << 5,
++      .dmaor_is_32bit = 1,
++      .needs_tend_set = 1,
++      .no_dmars       = 1,
++      .slave_only     = 1,
++};
++
++static struct resource r8a7740_usb_dma_resources[] = {
++      {
++              /* Channel registers and DMAOR */
++              .start  = 0xe68a0020,
++              .end    = 0xe68a0064 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              /* VCR/SWR/DMICR */
++              .start  = 0xe68a0000,
++              .end    = 0xe68a0014 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      {
++              /* IRQ for channels */
++              .start  = evt2irq(0x0a00),
++              .end    = evt2irq(0x0a00),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device usb_dma_device = {
++      .name           = "sh-dma-engine",
++      .id             = 3,
++      .resource       = r8a7740_usb_dma_resources,
++      .num_resources  = ARRAY_SIZE(r8a7740_usb_dma_resources),
++      .dev            = {
++              .platform_data  = &usb_dma_platform_data,
++      },
++};
++
+ /* I2C */
+ static struct resource i2c0_resources[] = {
+       [0] = {
+@@ -550,6 +636,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = {
+       &dma0_device,
+       &dma1_device,
+       &dma2_device,
++      &usb_dma_device,
+ };
+ /*
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch b/patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch
new file mode 100644 (file)
index 0000000..8233c22
--- /dev/null
@@ -0,0 +1,139 @@
+From 5fa62ea250079de3ea68853067d0935524c3e766 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:43:10 -0700
+Subject: ARM: shmobile: use common DMAEngine definitions on r8a7740
+
+This patch switch over to use common DMAEngine definitions,
+and reduced a waste of code.
+
+It is easy to understand if sh_dmae_pdata / sh_dmae_slave_config
+settings are used defined value instead of direct value.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit d7de938f3da618b1592427f625e150c0a68b9ecb)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/setup-r8a7740.c | 64 ++++++----------------------------
+ 1 file changed, 11 insertions(+), 53 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 5e84609..48d7bbf 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -27,6 +27,7 @@
+ #include <linux/sh_dma.h>
+ #include <linux/sh_timer.h>
+ #include <linux/dma-mapping.h>
++#include <mach/dma-register.h>
+ #include <mach/r8a7740.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+@@ -279,31 +280,6 @@ static struct platform_device *r8a7740_early_devices[] __initdata = {
+ };
+ /* DMA */
+-enum {
+-      XMIT_SZ_8BIT            = 0,
+-      XMIT_SZ_16BIT           = 1,
+-      XMIT_SZ_32BIT           = 2,
+-      XMIT_SZ_64BIT           = 7,
+-      XMIT_SZ_128BIT          = 3,
+-      XMIT_SZ_256BIT          = 4,
+-      XMIT_SZ_512BIT          = 5,
+-};
+-
+-/* log2(size / 8) - used to calculate number of transfers */
+-#define TS_SHIFT {                    \
+-      [XMIT_SZ_8BIT]          = 0,    \
+-      [XMIT_SZ_16BIT]         = 1,    \
+-      [XMIT_SZ_32BIT]         = 2,    \
+-      [XMIT_SZ_64BIT]         = 3,    \
+-      [XMIT_SZ_128BIT]        = 4,    \
+-      [XMIT_SZ_256BIT]        = 5,    \
+-      [XMIT_SZ_512BIT]        = 6,    \
+-}
+-
+-#define TS_INDEX2VAL(i) ((((i) & 0x3) << 3) | (((i) & 0xc) << (20 - 2)))
+-#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
+-#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
+-
+ static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = {
+       {
+               .slave_id       = SHDMA_SLAVE_SDHI0_TX,
+@@ -370,19 +346,17 @@ static const struct sh_dmae_channel r8a7740_dmae_channels[] = {
+       DMA_CHANNEL(0x60, 8, 8),
+ };
+-static const unsigned int ts_shift[] = TS_SHIFT;
+-
+ static struct sh_dmae_pdata dma_platform_data = {
+       .slave          = r8a7740_dmae_slaves,
+       .slave_num      = ARRAY_SIZE(r8a7740_dmae_slaves),
+       .channel        = r8a7740_dmae_channels,
+       .channel_num    = ARRAY_SIZE(r8a7740_dmae_channels),
+-      .ts_low_shift   = 3,
+-      .ts_low_mask    = 0x18,
+-      .ts_high_shift  = (20 - 2),
+-      .ts_high_mask   = 0x00300000,
+-      .ts_shift       = ts_shift,
+-      .ts_shift_num   = ARRAY_SIZE(ts_shift),
++      .ts_low_shift   = TS_LOW_SHIFT,
++      .ts_low_mask    = TS_LOW_BIT << TS_LOW_SHIFT,
++      .ts_high_shift  = TS_HI_SHIFT,
++      .ts_high_mask   = TS_HI_BIT << TS_HI_SHIFT,
++      .ts_shift       = dma_ts_shift,
++      .ts_shift_num   = ARRAY_SIZE(dma_ts_shift),
+       .dmaor_init     = DMAOR_DME,
+       .chclr_present  = 1,
+ };
+@@ -502,20 +476,6 @@ static struct platform_device dma2_device = {
+ };
+ /* USB-DMAC */
+-/* Transmit sizes and respective CHCR register values */
+-enum {
+-      USBTS_XMIT_SZ_8BYTE             = 0,
+-      USBTS_XMIT_SZ_16BYTE            = 1,
+-      USBTS_XMIT_SZ_32BYTE            = 2,
+-};
+-
+-/* log2(size / 8) - used to calculate number of transfers */
+-static const unsigned int dma_usbts_shift[] = {
+-      [USBTS_XMIT_SZ_8BYTE]   = 3,
+-      [USBTS_XMIT_SZ_16BYTE]  = 4,
+-      [USBTS_XMIT_SZ_32BYTE]  = 5,
+-};
+-
+ static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
+       {
+               .offset = 0,
+@@ -524,8 +484,6 @@ static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = {
+       },
+ };
+-#define USBTS_INDEX2VAL(i) (((i) & 3) << 6)
+-
+ static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = {
+       {
+               .slave_id       = SHDMA_SLAVE_USBHS_TX,
+@@ -541,10 +499,10 @@ static struct sh_dmae_pdata usb_dma_platform_data = {
+       .slave_num      = ARRAY_SIZE(r8a7740_usb_dma_slaves),
+       .channel        = r8a7740_usb_dma_channels,
+       .channel_num    = ARRAY_SIZE(r8a7740_usb_dma_channels),
+-      .ts_low_shift   = 6,
+-      .ts_low_mask    = 0xc0,
+-      .ts_high_shift  = 0,
+-      .ts_high_mask   = 0,
++      .ts_low_shift   = USBTS_LOW_SHIFT,
++      .ts_low_mask    = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
++      .ts_high_shift  = USBTS_HI_SHIFT,
++      .ts_high_mask   = USBTS_HI_BIT << USBTS_HI_SHIFT,
+       .ts_shift       = dma_usbts_shift,
+       .ts_shift_num   = ARRAY_SIZE(dma_usbts_shift),
+       .dmaor_init     = DMAOR_DME,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch b/patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch
new file mode 100644 (file)
index 0000000..b62ac18
--- /dev/null
@@ -0,0 +1,184 @@
+From 2b0c07b75a3b421285bae10961bf20e0011839b6 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:32:50 -0700
+Subject: ARM: shmobile: armadillo800eva: enable FSI-WM8978 sound
+
+This patch enable sound support on CON11
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 5389bf719f87101339f292256392bff5ae926917)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Kconfig                 |  1 +
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 99 ++++++++++++++++++++++++++
+ 2 files changed, 100 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index da57dde..c74b74a 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -100,6 +100,7 @@ config MACH_ARMADILLO800EVA
+       depends on ARCH_R8A7740
+       select ARCH_REQUIRE_GPIOLIB
+       select USE_OF
++      select SND_SOC_WM8978 if SND_SIMPLE_CARD
+ config MACH_MARZEN
+       bool "MARZEN board"
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index a513ebe..afe7860 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -49,6 +49,8 @@
+ #include <asm/hardware/cache-l2x0.h>
+ #include <video/sh_mobile_lcdc.h>
+ #include <video/sh_mobile_hdmi.h>
++#include <sound/sh_fsi.h>
++#include <sound/simple_card.h>
+ /*
+  * CON1               Camera Module
+@@ -112,6 +114,28 @@
+  */
+ /*
++ * FSI-WM8978
++ *
++ * this command is required when playback.
++ *
++ * # amixer set "Headphone" 50
++ */
++
++/*
++ * FIXME !!
++ *
++ * gpio_no_direction
++ *
++ * current gpio frame work doesn't have
++ * the method to control only pull up/down/free.
++ * this function should be replaced by correct gpio function
++ */
++static void __init gpio_no_direction(u32 addr)
++{
++      __raw_writeb(0x00, addr);
++}
++
++/*
+  * USB function
+  *
+  * When you use USB Function,
+@@ -714,12 +738,71 @@ static struct platform_device ceu0_device = {
+       },
+ };
++/* FSI */
++static struct sh_fsi_platform_info fsi_info = {
++      /* FSI-WM8978 */
++      .port_a = {
++      },
++};
++
++static struct resource fsi_resources[] = {
++      [0] = {
++              .name   = "FSI",
++              .start  = 0xfe1f0000,
++              .end    = 0xfe1f8400 - 1,
++              .flags  = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start  = evt2irq(0x1840),
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct platform_device fsi_device = {
++      .name           = "sh_fsi2",
++      .id             = -1,
++      .num_resources  = ARRAY_SIZE(fsi_resources),
++      .resource       = fsi_resources,
++      .dev    = {
++              .platform_data  = &fsi_info,
++      },
++};
++
++/* FSI-WM8978 */
++static struct asoc_simple_dai_init_info fsi_wm8978_init_info = {
++      .fmt            = SND_SOC_DAIFMT_I2S,
++      .codec_daifmt   = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF,
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBS_CFS,
++      .sysclk         = 12288000,
++};
++
++static struct asoc_simple_card_info fsi_wm8978_info = {
++      .name           = "wm8978",
++      .card           = "FSI2A-WM8978",
++      .cpu_dai        = "fsia-dai",
++      .codec          = "wm8978.0-001a",
++      .platform       = "sh_fsi2",
++      .codec_dai      = "wm8978-hifi",
++      .init           = &fsi_wm8978_init_info,
++};
++
++static struct platform_device fsi_wm8978_device = {
++      .name   = "asoc-simple-card",
++      .id     = 0,
++      .dev    = {
++              .platform_data  = &fsi_wm8978_info,
++      },
++};
++
+ /* I2C */
+ static struct i2c_board_info i2c0_devices[] = {
+       {
+               I2C_BOARD_INFO("st1232-ts", 0x55),
+               .irq = evt2irq(0x0340),
+       },
++      {
++              I2C_BOARD_INFO("wm8978", 0x1a),
++      },
+ };
+ /*
+@@ -735,6 +818,8 @@ static struct platform_device *eva_devices[] __initdata = {
+       &hdmi_lcdc_device,
+       &camera_device,
+       &ceu0_device,
++      &fsi_device,
++      &fsi_wm8978_device,
+ };
+ static void __init eva_clock_init(void)
+@@ -768,6 +853,8 @@ clock_error:
+ /*
+  * board init
+  */
++#define GPIO_PORT7CR  0xe6050007
++#define GPIO_PORT8CR  0xe6050008
+ static void __init eva_init(void)
+ {
+       eva_clock_init();
+@@ -916,6 +1003,18 @@ static void __init eva_init(void)
+       gpio_direction_output(GPIO_PORT172, 1);
+       gpio_direction_output(GPIO_PORT158, 0); /* see mt9t111_power() */
++      /* FSI-WM8978 */
++      gpio_request(GPIO_FN_FSIAIBT,           NULL);
++      gpio_request(GPIO_FN_FSIAILR,           NULL);
++      gpio_request(GPIO_FN_FSIAOMC,           NULL);
++      gpio_request(GPIO_FN_FSIAOSLD,          NULL);
++      gpio_request(GPIO_FN_FSIAISLD_PORT5,    NULL);
++
++      gpio_request(GPIO_PORT7, NULL);
++      gpio_request(GPIO_PORT8, NULL);
++      gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */
++      gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */
++
+       /*
+        * CAUTION
+        *
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch b/patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch
new file mode 100644 (file)
index 0000000..120c315
--- /dev/null
@@ -0,0 +1,176 @@
+From 850c6f996ee51eddf540325ec5c892073dbc2567 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:33:04 -0700
+Subject: ARM: shmobile: armadillo800eva: enable FSI-HDMI sound
+
+This patch enable HDMI sound support on CON3
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 0676c05e57c6e37fc9f985a8f6ea2883e5b2cbda)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 82 +++++++++++++++++++++++++-
+ 1 file changed, 79 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index afe7860..df5fd2c 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -739,10 +739,42 @@ static struct platform_device ceu0_device = {
+ };
+ /* FSI */
++static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
++{
++      struct clk *fsib;
++      int ret;
++
++      /* it support 48KHz only */
++      if (48000 != rate)
++              return -EINVAL;
++
++      fsib = clk_get(dev, "ickb");
++      if (IS_ERR(fsib))
++              return -EINVAL;
++
++      if (enable) {
++              ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
++              clk_enable(fsib);
++      } else {
++              ret = 0;
++              clk_disable(fsib);
++      }
++
++      clk_put(fsib);
++
++      return ret;
++}
++
+ static struct sh_fsi_platform_info fsi_info = {
+       /* FSI-WM8978 */
+       .port_a = {
+       },
++      /* FSI-HDMI */
++      .port_b = {
++              .flags          = SH_FSI_FMT_SPDIF |
++                                SH_FSI_ENABLE_STREAM_MODE,
++              .set_rate       = fsi_hdmi_set_rate,
++      }
+ };
+ static struct resource fsi_resources[] = {
+@@ -794,6 +826,29 @@ static struct platform_device fsi_wm8978_device = {
+       },
+ };
++/* FSI-HDMI */
++static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = {
++      .cpu_daifmt     = SND_SOC_DAIFMT_CBM_CFM,
++};
++
++static struct asoc_simple_card_info fsi2_hdmi_info = {
++      .name           = "HDMI",
++      .card           = "FSI2B-HDMI",
++      .cpu_dai        = "fsib-dai",
++      .codec          = "sh-mobile-hdmi",
++      .platform       = "sh_fsi2",
++      .codec_dai      = "sh_mobile_hdmi-hifi",
++      .init           = &fsi2_hdmi_init_info,
++};
++
++static struct platform_device fsi_hdmi_device = {
++      .name   = "asoc-simple-card",
++      .id     = 1,
++      .dev    = {
++              .platform_data  = &fsi2_hdmi_info,
++      },
++};
++
+ /* I2C */
+ static struct i2c_board_info i2c0_devices[] = {
+       {
+@@ -819,6 +874,7 @@ static struct platform_device *eva_devices[] __initdata = {
+       &camera_device,
+       &ceu0_device,
+       &fsi_device,
++      &fsi_hdmi_device,
+       &fsi_wm8978_device,
+ };
+@@ -827,10 +883,14 @@ static void __init eva_clock_init(void)
+       struct clk *system      = clk_get(NULL, "system_clk");
+       struct clk *xtal1       = clk_get(NULL, "extal1");
+       struct clk *usb24s      = clk_get(NULL, "usb24s");
++      struct clk *fsibck      = clk_get(NULL, "fsibck");
++      struct clk *fsib        = clk_get(&fsi_device.dev, "ickb");
+       if (IS_ERR(system)      ||
+           IS_ERR(xtal1)       ||
+-          IS_ERR(usb24s)) {
++          IS_ERR(usb24s)      ||
++          IS_ERR(fsibck)      ||
++          IS_ERR(fsib)) {
+               pr_err("armadillo800eva board clock init failed\n");
+               goto clock_error;
+       }
+@@ -841,6 +901,11 @@ static void __init eva_clock_init(void)
+       /* usb24s use extal1 (= system) clock (= 24MHz) */
+       clk_set_parent(usb24s, system);
++      /* FSIBCK is 12.288MHz, and it is parent of FSI-B */
++      clk_set_parent(fsib, fsibck);
++      clk_set_rate(fsibck, 12288000);
++      clk_set_rate(fsib,   12288000);
++
+ clock_error:
+       if (!IS_ERR(system))
+               clk_put(system);
+@@ -848,6 +913,10 @@ clock_error:
+               clk_put(xtal1);
+       if (!IS_ERR(usb24s))
+               clk_put(usb24s);
++      if (!IS_ERR(fsibck))
++              clk_put(fsibck);
++      if (!IS_ERR(fsib))
++              clk_put(fsib);
+ }
+ /*
+@@ -857,8 +926,6 @@ clock_error:
+ #define GPIO_PORT8CR  0xe6050008
+ static void __init eva_init(void)
+ {
+-      eva_clock_init();
+-
+       r8a7740_pinmux_init();
+       r8a7740_meram_workaround();
+@@ -1015,6 +1082,13 @@ static void __init eva_init(void)
+       gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */
+       gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */
++      /* FSI-HDMI */
++      gpio_request(GPIO_FN_FSIBCK,            NULL);
++
++      /* HDMI */
++      gpio_request(GPIO_FN_HDMI_HPD,          NULL);
++      gpio_request(GPIO_FN_HDMI_CEC,          NULL);
++
+       /*
+        * CAUTION
+        *
+@@ -1061,6 +1135,8 @@ static void __init eva_init(void)
+       platform_add_devices(eva_devices,
+                            ARRAY_SIZE(eva_devices));
++
++      eva_clock_init();
+ }
+ static void __init eva_earlytimer_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch b/patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch
new file mode 100644 (file)
index 0000000..e2c925f
--- /dev/null
@@ -0,0 +1,54 @@
+From 95f8bc86715253ac6371cf581049a13a0a1d94eb Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:37:20 -0700
+Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on FSI
+
+It is possible to reduce CPU load if FSI playback used DMAEngine.
+This patch enabled it.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit dc7dd5841f714c3bc3f358cb126ba4432947e854)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/configs/armadillo800eva_defconfig     | 2 ++
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 2 ++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
+index df1ce54..16bbb3f 100644
+--- a/arch/arm/configs/armadillo800eva_defconfig
++++ b/arch/arm/configs/armadillo800eva_defconfig
+@@ -119,6 +119,8 @@ CONFIG_USB_ETH=m
+ CONFIG_MMC=y
+ CONFIG_MMC_SDHI=y
+ CONFIG_MMC_SH_MMCIF=y
++CONFIG_DMADEVICES=y
++CONFIG_SH_DMAE=y
+ CONFIG_UIO=y
+ CONFIG_UIO_PDRV_GENIRQ=y
+ # CONFIG_DNOTIFY is not set
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index df5fd2c..032e04d 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -768,12 +768,14 @@ static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
+ static struct sh_fsi_platform_info fsi_info = {
+       /* FSI-WM8978 */
+       .port_a = {
++              .tx_id = SHDMA_SLAVE_FSIA_TX,
+       },
+       /* FSI-HDMI */
+       .port_b = {
+               .flags          = SH_FSI_FMT_SPDIF |
+                                 SH_FSI_ENABLE_STREAM_MODE,
+               .set_rate       = fsi_hdmi_set_rate,
++              .tx_id          = SHDMA_SLAVE_FSIB_TX,
+       }
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch b/patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch
new file mode 100644 (file)
index 0000000..7b80c65
--- /dev/null
@@ -0,0 +1,43 @@
+From 67c3e7eb10a9da8600072c0b2292287dafe97219 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:37:38 -0700
+Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on SDHI
+
+It is possible to reduce CPU load if SDHI used DMAEngine.
+This patch enabled it.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 95798e350dde44920a021a7e7e720a3be15e8220)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 032e04d..54bf618 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -543,6 +543,8 @@ static struct platform_device gpio_keys_device = {
+  */
+ #define IRQ31 evt2irq(0x33E0)
+ static struct sh_mobile_sdhi_info sdhi0_info = {
++      .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
++      .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
+       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\
+                         MMC_CAP_NEEDS_POLL,
+       .tmio_ocr_mask  = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+@@ -583,6 +585,8 @@ static struct platform_device sdhi0_device = {
+ /* SDHI1 */
+ static struct sh_mobile_sdhi_info sdhi1_info = {
++      .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
++      .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
+       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+       .tmio_ocr_mask  = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch b/patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch
new file mode 100644 (file)
index 0000000..27ccbe4
--- /dev/null
@@ -0,0 +1,34 @@
+From ad78daa637449523d9cdfd7b28f5ea0150ac349a Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:37:47 -0700
+Subject: ARM: shmobile: armadillo800eva: enable DMAEngine on USB
+
+It is possible to reduce CPU load if USB used DMAEngine.
+This patch enabled it.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit f7e566fa26b7d34514d5ba7b8b4464934be8ff2c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 54bf618..539f1cf 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -297,6 +297,8 @@ static struct usbhsf_private usbhsf_private = {
+               .driver_param = {
+                       .buswait_bwait          = 5,
+                       .detection_delay        = 5,
++                      .d0_rx_id       = SHDMA_SLAVE_USBHS_RX,
++                      .d1_tx_id       = SHDMA_SLAVE_USBHS_TX,
+               },
+       }
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch b/patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch
new file mode 100644 (file)
index 0000000..897c432
--- /dev/null
@@ -0,0 +1,60 @@
+From 2d6b318376b8c20432ed164d31b047a74c6d5215 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:41:45 -0700
+Subject: ARM: shmobile: use common extra gpio functions on armadillo800eva
+
+This patch switch over to use common extra gpio method,
+and reduced a waste of code on SH-ARM.
+
+But these functions should be replaced by correct
+gpio function in the future.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit a01366b4b5cc669633d1cf6ee327c85a5406ef5f)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 18 ++----------------
+ 1 file changed, 2 insertions(+), 16 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 539f1cf..a4fd71a 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -122,20 +122,6 @@
+  */
+ /*
+- * FIXME !!
+- *
+- * gpio_no_direction
+- *
+- * current gpio frame work doesn't have
+- * the method to control only pull up/down/free.
+- * this function should be replaced by correct gpio function
+- */
+-static void __init gpio_no_direction(u32 addr)
+-{
+-      __raw_writeb(0x00, addr);
+-}
+-
+-/*
+  * USB function
+  *
+  * When you use USB Function,
+@@ -1087,8 +1073,8 @@ static void __init eva_init(void)
+       gpio_request(GPIO_PORT7, NULL);
+       gpio_request(GPIO_PORT8, NULL);
+-      gpio_no_direction(GPIO_PORT7CR); /* FSIAOBT needs no direction */
+-      gpio_no_direction(GPIO_PORT8CR); /* FSIAOLR needs no direction */
++      gpio_direction_none(GPIO_PORT7CR); /* FSIAOBT needs no direction */
++      gpio_direction_none(GPIO_PORT8CR); /* FSIAOLR needs no direction */
+       /* FSI-HDMI */
+       gpio_request(GPIO_FN_FSIBCK,            NULL);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch b/patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch
new file mode 100644 (file)
index 0000000..2024d81
--- /dev/null
@@ -0,0 +1,61 @@
+From 6a9259faadbdfcb18a8f2ee78d414ae7194a2b10 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Fri, 29 Jun 2012 08:33:11 +0200
+Subject: ARM: mach-shmobile: add fixed voltage regulators to armadillo800eva
+
+On armadillo800eva provide a 3.3V supply for its SD/MMC-card interfaces.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit f65ad7e36cbae24f05ea2314ad63e9dd23294c60)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index a4fd71a..7c77f07 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -28,6 +28,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/gpio.h>
+ #include <linux/gpio_keys.h>
++#include <linux/regulator/fixed.h>
++#include <linux/regulator/machine.h>
+ #include <linux/sh_eth.h>
+ #include <linux/videodev2.h>
+ #include <linux/usb/renesas_usbhs.h>
+@@ -520,6 +522,17 @@ static struct platform_device gpio_keys_device = {
+       },
+ };
++/* Fixed 3.3V regulator to be used by SDHI0, SDHI1, MMCIF */
++static struct regulator_consumer_supply fixed3v3_power_consumers[] =
++{
++      REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
++      REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
++      REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
++      REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
++      REGULATOR_SUPPLY("vmmc", "sh_mmcif"),
++      REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
++};
++
+ /* SDHI0 */
+ /*
+  * FIXME
+@@ -920,6 +933,9 @@ clock_error:
+ #define GPIO_PORT8CR  0xe6050008
+ static void __init eva_init(void)
+ {
++      regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
++                                   ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
++
+       r8a7740_pinmux_init();
+       r8a7740_meram_workaround();
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch b/patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch
new file mode 100644 (file)
index 0000000..0b7bb32
--- /dev/null
@@ -0,0 +1,107 @@
+From 34b7faf5447e1eefc86e43779a132ad8e8cf5c32 Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Date: Wed, 27 Jun 2012 09:59:00 +0900
+Subject: ARM: mach-shmobile: Convert sh_clk_mstp32_register to
+ sh_clk_mstp_register
+
+sh_clk_mstp32_register is deprecated. This convert to sh_clk_mstp_register.
+
+Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 64e9de2f854fb5d08d255b24568c60b090f2603a)
+
+Conflicts:
+       arch/arm/mach-shmobile/clock-r8a7740.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/clock-r8a7740.c | 2 +-
+ arch/arm/mach-shmobile/clock-r8a7779.c | 2 +-
+ arch/arm/mach-shmobile/clock-sh7367.c  | 2 +-
+ arch/arm/mach-shmobile/clock-sh7372.c  | 2 +-
+ arch/arm/mach-shmobile/clock-sh7377.c  | 2 +-
+ arch/arm/mach-shmobile/clock-sh73a0.c  | 2 +-
+ 6 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
+index daf3eac..ad5fccc 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7740.c
++++ b/arch/arm/mach-shmobile/clock-r8a7740.c
+@@ -636,7 +636,7 @@ void __init r8a7740_clock_init(u8 md_ck)
+                                                   DIV6_REPARENT_NR);
+       if (!ret)
+-              ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
++              ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+       for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
+               ret = clk_register(late_main_clks[k]);
+diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
+index 7d6e9fe..339c62c 100644
+--- a/arch/arm/mach-shmobile/clock-r8a7779.c
++++ b/arch/arm/mach-shmobile/clock-r8a7779.c
+@@ -162,7 +162,7 @@ void __init r8a7779_clock_init(void)
+               ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+       if (!ret)
+-              ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
++              ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+       for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
+               ret = clk_register(late_main_clks[k]);
+diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
+index 006e7b5..162b791 100644
+--- a/arch/arm/mach-shmobile/clock-sh7367.c
++++ b/arch/arm/mach-shmobile/clock-sh7367.c
+@@ -344,7 +344,7 @@ void __init sh7367_clock_init(void)
+               ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+       if (!ret)
+-              ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
++              ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
+index 94d1f88..5a2894b 100644
+--- a/arch/arm/mach-shmobile/clock-sh7372.c
++++ b/arch/arm/mach-shmobile/clock-sh7372.c
+@@ -704,7 +704,7 @@ void __init sh7372_clock_init(void)
+               ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);
+       if (!ret)
+-              ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
++              ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+       for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
+               ret = clk_register(late_main_clks[k]);
+diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c
+index 0798a15..85f2a3e 100644
+--- a/arch/arm/mach-shmobile/clock-sh7377.c
++++ b/arch/arm/mach-shmobile/clock-sh7377.c
+@@ -355,7 +355,7 @@ void __init sh7377_clock_init(void)
+               ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+       if (!ret)
+-              ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
++              ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
+index 472d1f5..f6788be 100644
+--- a/arch/arm/mach-shmobile/clock-sh73a0.c
++++ b/arch/arm/mach-shmobile/clock-sh73a0.c
+@@ -612,7 +612,7 @@ void __init sh73a0_clock_init(void)
+               ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
+       if (!ret)
+-              ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
++              ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+       for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
+               ret = clk_register(late_main_clks[k]);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch b/patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch
new file mode 100644 (file)
index 0000000..f609f35
--- /dev/null
@@ -0,0 +1,45 @@
+From e52c21c95e6ce158bd78d4b0d3b55fb4350beb4a Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:25:24 -0700
+Subject: ARM: shmobile: r8a7740: fixup: MSEL1CR 7bit control
+
+MSEL1CR 7bit selects IRQ7 source pin which was
+VBUS pin or A21/MSIOF0_RSYNC/MSIOF1_TSYNC pin.
+But current pfc-r8a7740 MSEL1CR 7bit setting was wrong.
+This patch fix it up
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 444c5ed8d746140cd8f5591f708e5f1f84a9876e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/pfc-r8a7740.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
+index 03def0f..ce9e7fa 100644
+--- a/arch/arm/mach-shmobile/pfc-r8a7740.c
++++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
+@@ -1261,7 +1261,7 @@ static pinmux_enum_t pinmux_data[] = {
+       PINMUX_DATA(A21_MARK,                   PORT120_FN1),
+       PINMUX_DATA(MSIOF0_RSYNC_MARK,          PORT120_FN2),
+       PINMUX_DATA(MSIOF1_TSYNC_PORT120_MARK,  PORT120_FN3,    MSEL4CR_10_0),
+-      PINMUX_DATA(IRQ7_PORT120_MARK,          PORT120_FN0,    MSEL1CR_7_0),
++      PINMUX_DATA(IRQ7_PORT120_MARK,          PORT120_FN0,    MSEL1CR_7_1),
+       /* Port121 */
+       PINMUX_DATA(A20_MARK,                   PORT121_FN1),
+@@ -1623,7 +1623,7 @@ static pinmux_enum_t pinmux_data[] = {
+       /* Port209 */
+       PINMUX_DATA(VBUS_MARK,                  PORT209_FN1),
+-      PINMUX_DATA(IRQ7_PORT209_MARK,          PORT209_FN0,    MSEL1CR_7_1),
++      PINMUX_DATA(IRQ7_PORT209_MARK,          PORT209_FN0,    MSEL1CR_7_0),
+       /* Port210 */
+       PINMUX_DATA(IRQ9_PORT210_MARK,          PORT210_FN0,    MSEL1CR_9_1),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch b/patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch
new file mode 100644 (file)
index 0000000..be5eee6
--- /dev/null
@@ -0,0 +1,122 @@
+From cfbc3351777b8b9160e410b3f1dfdb2558214b1a Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:25:58 -0700
+Subject: ARM: shmobile: r8a7740: add A4S pm domain support
+
+This patch adds basic A4S pm domain support.
+Now, below devices can be controled by PM
+
+Common-SHwy, Common-HPB, BSC, MFI, MMFROM, HS-SHwy,
+SYS-HPB, INTCA, DBSC, DDRPHY (Logic),
+ATAPI, GbEther, AXI-bus
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 8459293c27bcd13aabacb7ee8097f6818f2ceedb)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Makefile               |  1 +
+ arch/arm/mach-shmobile/include/mach/r8a7740.h |  6 ++++++
+ arch/arm/mach-shmobile/pm-r8a7740.c           | 30 +++++++++++++++++++++++++++
+ arch/arm/mach-shmobile/setup-r8a7740.c        |  5 +++++
+ 4 files changed, 42 insertions(+)
+ create mode 100644 arch/arm/mach-shmobile/pm-r8a7740.c
+
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index b39033b..7804bd1 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -39,6 +39,7 @@ obj-$(CONFIG_SUSPEND)                += suspend.o
+ obj-$(CONFIG_CPU_IDLE)                += cpuidle.o
+ obj-$(CONFIG_ARCH_SHMOBILE)   += pm-rmobile.o
+ obj-$(CONFIG_ARCH_SH7372)     += pm-sh7372.o sleep-sh7372.o
++obj-$(CONFIG_ARCH_R8A7740)    += pm-r8a7740.o
+ obj-$(CONFIG_ARCH_R8A7779)    += pm-r8a7779.o
+ # Board objects
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index 8bd7b9c..e8c87e9 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -19,6 +19,8 @@
+ #ifndef __ASM_R8A7740_H__
+ #define __ASM_R8A7740_H__
++#include <mach/pm-rmobile.h>
++
+ /*
+  * MD_CKx pin
+  */
+@@ -604,4 +606,8 @@ enum {
+       SHDMA_SLAVE_USBHS_RX,
+ };
++#ifdef CONFIG_PM
++extern struct rmobile_pm_domain r8a7740_pd_a4s;
++#endif /* CONFIG_PM */
++
+ #endif /* __ASM_R8A7740_H__ */
+diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
+new file mode 100644
+index 0000000..d2fe815
+--- /dev/null
++++ b/arch/arm/mach-shmobile/pm-r8a7740.c
+@@ -0,0 +1,30 @@
++/*
++ * r8a7740 power management support
++ *
++ * Copyright (C) 2012  Renesas Solutions Corp.
++ * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <mach/pm-rmobile.h>
++
++#ifdef CONFIG_PM
++static int r8a7740_pd_a4s_suspend(void)
++{
++      /*
++       * The A4S domain contains the CPU core and therefore it should
++       * only be turned off if the CPU is in use.
++       */
++      return -EBUSY;
++}
++
++struct rmobile_pm_domain r8a7740_pd_a4s = {
++      .genpd.name     = "A4S",
++      .bit_shift      = 10,
++      .gov            = &pm_domain_always_on_gov,
++      .no_debug       = true,
++      .suspend        = r8a7740_pd_a4s_suspend,
++};
++#endif /* CONFIG_PM */
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 48d7bbf..c37ad75 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -29,6 +29,7 @@
+ #include <linux/dma-mapping.h>
+ #include <mach/dma-register.h>
+ #include <mach/r8a7740.h>
++#include <mach/pm-rmobile.h>
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+ #include <asm/mach-types.h>
+@@ -671,6 +672,10 @@ void __init r8a7740_add_standard_devices(void)
+       r8a7740_i2c_workaround(&i2c0_device);
+       r8a7740_i2c_workaround(&i2c1_device);
++      /* PM domain */
++      rmobile_init_pm_domain(&r8a7740_pd_a4s);
++
++      /* add devices */
+       platform_add_devices(r8a7740_early_devices,
+                           ARRAY_SIZE(r8a7740_early_devices));
+       platform_add_devices(r8a7740_late_devices,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch b/patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch
new file mode 100644 (file)
index 0000000..3a6b491
--- /dev/null
@@ -0,0 +1,107 @@
+From 12c6836de664df0456e3d827b605ef1bf4bb323a Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:26:31 -0700
+Subject: ARM: shmobile: r8a7740: add A3SP pm domain support
+
+This patch adds basic A3SP pm domain support.
+Now, below devices can be controled by PM
+
+DMAC1/2/3, IPMMU, DDM, FLCTL, SYS-HPB, BBIF1, MSIOF1/2,
+SCIFA,SCIFB, IIC1, IrDA, USBH, USBDMAC, SDHI0/1/2, TPU,
+DREQPAK (Sys),  MMCIF, RSPI, SIM, USBF
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 802a5639aa7041b27cb865d3be289cd8afe3387b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/r8a7740.h |  1 +
+ arch/arm/mach-shmobile/pm-r8a7740.c           | 19 +++++++++++++++++++
+ arch/arm/mach-shmobile/setup-r8a7740.c        | 16 ++++++++++++++++
+ 3 files changed, 36 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index e8c87e9..a5691cf 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -608,6 +608,7 @@ enum {
+ #ifdef CONFIG_PM
+ extern struct rmobile_pm_domain r8a7740_pd_a4s;
++extern struct rmobile_pm_domain r8a7740_pd_a3sp;
+ #endif /* CONFIG_PM */
+ #endif /* __ASM_R8A7740_H__ */
+diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
+index d2fe815..de7c621 100644
+--- a/arch/arm/mach-shmobile/pm-r8a7740.c
++++ b/arch/arm/mach-shmobile/pm-r8a7740.c
+@@ -8,6 +8,7 @@
+  * License.  See the file "COPYING" in the main directory of this archive
+  * for more details.
+  */
++#include <linux/console.h>
+ #include <mach/pm-rmobile.h>
+ #ifdef CONFIG_PM
+@@ -27,4 +28,22 @@ struct rmobile_pm_domain r8a7740_pd_a4s = {
+       .no_debug       = true,
+       .suspend        = r8a7740_pd_a4s_suspend,
+ };
++
++static int r8a7740_pd_a3sp_suspend(void)
++{
++      /*
++       * Serial consoles make use of SCIF hardware located in A3SP,
++       * keep such power domain on if "no_console_suspend" is set.
++       */
++      return console_suspend_enabled ? 0 : -EBUSY;
++}
++
++struct rmobile_pm_domain r8a7740_pd_a3sp = {
++      .genpd.name     = "A3SP",
++      .bit_shift      = 11,
++      .gov            = &pm_domain_always_on_gov,
++      .no_debug       = true,
++      .suspend        = r8a7740_pd_a3sp_suspend,
++};
++
+ #endif /* CONFIG_PM */
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index c37ad75..59c79412 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -674,12 +674,28 @@ void __init r8a7740_add_standard_devices(void)
+       /* PM domain */
+       rmobile_init_pm_domain(&r8a7740_pd_a4s);
++      rmobile_init_pm_domain(&r8a7740_pd_a3sp);
++
++      rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp);
+       /* add devices */
+       platform_add_devices(r8a7740_early_devices,
+                           ARRAY_SIZE(r8a7740_early_devices));
+       platform_add_devices(r8a7740_late_devices,
+                            ARRAY_SIZE(r8a7740_late_devices));
++
++      /* add devices to PM domain  */
++
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif0_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif1_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif2_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif3_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif4_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif5_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif6_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scif7_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &scifb_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a3sp,  &i2c1_device);
+ }
+ static void __init r8a7740_earlytimer_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch b/patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch
new file mode 100644 (file)
index 0000000..b3b936d
--- /dev/null
@@ -0,0 +1,63 @@
+From ffd8b73a5eead1c3d0361edd426cd5560a853b6c Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:26:53 -0700
+Subject: ARM: shmobile: r8a7740: add A4LC pm domain support
+
+This patch adds basic A4LC pm domain support.
+Now, below devices can be controled by PM
+
+MERAM, LCDC, VOU, ICBS, SDENC-Link
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit a330ce3cdaba5202051edf8ae69482e15fdc9db5)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/r8a7740.h | 1 +
+ arch/arm/mach-shmobile/pm-r8a7740.c           | 5 +++++
+ arch/arm/mach-shmobile/setup-r8a7740.c        | 1 +
+ 3 files changed, 7 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+index a5691cf..7143147 100644
+--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
++++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
+@@ -609,6 +609,7 @@ enum {
+ #ifdef CONFIG_PM
+ extern struct rmobile_pm_domain r8a7740_pd_a4s;
+ extern struct rmobile_pm_domain r8a7740_pd_a3sp;
++extern struct rmobile_pm_domain r8a7740_pd_a4lc;
+ #endif /* CONFIG_PM */
+ #endif /* __ASM_R8A7740_H__ */
+diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
+index de7c621..893504d 100644
+--- a/arch/arm/mach-shmobile/pm-r8a7740.c
++++ b/arch/arm/mach-shmobile/pm-r8a7740.c
+@@ -46,4 +46,9 @@ struct rmobile_pm_domain r8a7740_pd_a3sp = {
+       .suspend        = r8a7740_pd_a3sp_suspend,
+ };
++struct rmobile_pm_domain r8a7740_pd_a4lc = {
++      .genpd.name     = "A4LC",
++      .bit_shift      = 1,
++};
++
+ #endif /* CONFIG_PM */
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 59c79412..c006d8d 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -675,6 +675,7 @@ void __init r8a7740_add_standard_devices(void)
+       /* PM domain */
+       rmobile_init_pm_domain(&r8a7740_pd_a4s);
+       rmobile_init_pm_domain(&r8a7740_pd_a3sp);
++      rmobile_init_pm_domain(&r8a7740_pd_a4lc);
+       rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch b/patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch
new file mode 100644 (file)
index 0000000..05a8453
--- /dev/null
@@ -0,0 +1,130 @@
+From a15b184d2c262c2133a1573ae9516633fdaf6f60 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:27:14 -0700
+Subject: ARM: shmobile: armadillo800eva: USB Func enables external IRQ mode
+
+We can control renesas_usbhs driver as 2 way which are
+autonomy mode and external IRQ trigger mode.
+
+Autonomy mode is very easy settings for platform,
+but it required USB power domain always ON,
+since its connection/disconnection IRQ come from it.
+
+If platform uses external IRQ trigger mode,
+USB power domain can be OFF, since its
+connection/disconnection IRQ come from external IRQ.
+
+This patch enable external IRQ mode.
+Now it is possible to add USB support on A4SP domain.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit d483b983a5efaa101714186a8485a5fd4de42fba)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 46 +++++++++++++++++++++-----
+ 1 file changed, 38 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 7c77f07..5002f64 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -133,14 +133,8 @@
+  * These are a little bit complex.
+  * see
+  *    usbhsf_power_ctrl()
+- *
+- * CAUTION
+- *
+- * It uses autonomy mode for USB hotplug at this point
+- * (= usbhs_private.platform_callback.get_vbus is NULL),
+- * since we don't know what's happen on PM control
+- * on this workaround.
+  */
++#define IRQ7          evt2irq(0x02e0)
+ #define USBCR1                0xe605810a
+ #define USBH          0xC6700000
+ #define USBH_USBCTR   0x10834
+@@ -220,6 +214,20 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
+       }
+ }
++static int usbhsf_get_vbus(struct platform_device *pdev)
++{
++      return gpio_get_value(GPIO_PORT209);
++}
++
++static irqreturn_t usbhsf_interrupt(int irq, void *data)
++{
++      struct platform_device *pdev = data;
++
++      renesas_usbhs_call_notify_hotplug(pdev);
++
++      return IRQ_HANDLED;
++}
++
+ static void usbhsf_hardware_exit(struct platform_device *pdev)
+ {
+       struct usbhsf_private *priv = usbhsf_get_priv(pdev);
+@@ -243,11 +251,14 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
+       priv->host      = NULL;
+       priv->func      = NULL;
+       priv->usbh_base = NULL;
++
++      free_irq(IRQ7, pdev);
+ }
+ static int usbhsf_hardware_init(struct platform_device *pdev)
+ {
+       struct usbhsf_private *priv = usbhsf_get_priv(pdev);
++      int ret;
+       priv->phy       = clk_get(&pdev->dev, "phy");
+       priv->usb24     = clk_get(&pdev->dev, "usb24");
+@@ -267,6 +278,14 @@ static int usbhsf_hardware_init(struct platform_device *pdev)
+               return -EIO;
+       }
++      ret = request_irq(IRQ7, usbhsf_interrupt, IRQF_TRIGGER_NONE,
++                        dev_name(&pdev->dev), pdev);
++      if (ret) {
++              dev_err(&pdev->dev, "request_irq err\n");
++              return ret;
++      }
++      irq_set_irq_type(IRQ7, IRQ_TYPE_EDGE_BOTH);
++
+       /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */
+       clk_set_rate(priv->usb24,
+                    clk_get_rate(clk_get_parent(priv->usb24)));
+@@ -278,6 +297,7 @@ static struct usbhsf_private usbhsf_private = {
+       .info = {
+               .platform_callback = {
+                       .get_id         = usbhsf_get_id,
++                      .get_vbus       = usbhsf_get_vbus,
+                       .hardware_init  = usbhsf_hardware_init,
+                       .hardware_exit  = usbhsf_hardware_exit,
+                       .power_ctrl     = usbhsf_power_ctrl,
+@@ -1018,7 +1038,17 @@ static void __init eva_init(void)
+               /* USB Host */
+       } else {
+               /* USB Func */
+-              gpio_request(GPIO_FN_VBUS, NULL);
++              /*
++               * A1 chip has 2 IRQ7 pin and it was controled by MSEL register.
++               * OTOH, usbhs interrupt needs its value (HI/LOW) to decide
++               * USB connection/disconnection (usbhsf_get_vbus()).
++               * This means we needs to select GPIO_FN_IRQ7_PORT209 first,
++               * and select GPIO_PORT209 here
++               */
++              gpio_request(GPIO_FN_IRQ7_PORT209, NULL);
++              gpio_request(GPIO_PORT209, NULL);
++              gpio_direction_input(GPIO_PORT209);
++
+               platform_device_register(&usbhsf_device);
+       }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch b/patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch
new file mode 100644 (file)
index 0000000..77f0990
--- /dev/null
@@ -0,0 +1,35 @@
+From ac8b41bd50ebd214726fffdac141ee4d37d3fb40 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:27:37 -0700
+Subject: ARM: shmobile: armadillo800eva: A4LC domain includes LCDC
+
+It is possible to control LCDC under A4LC domain to reduce power.
+This patch enable it.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 1000076a88d58acf77d8fa8bf5d2567425b8ea1b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 5002f64..101242a 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -1177,6 +1177,9 @@ static void __init eva_init(void)
+                            ARRAY_SIZE(eva_devices));
+       eva_clock_init();
++
++      rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device);
++      rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device);
+ }
+ static void __init eva_earlytimer_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch b/patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch
new file mode 100644 (file)
index 0000000..03ae976
--- /dev/null
@@ -0,0 +1,55 @@
+From 481b82720f5d1da8062da229cecc6ccfd875fb68 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Thu, 5 Jul 2012 01:28:00 -0700
+Subject: ARM: shmobile: armadillo800eva: A3SP domain includes USB
+
+Because USB Func is controlled by external IRQ mode,
+it is possible to control USB under A3SP domain to reduce power.
+This patch enables it.
+
+Armadillo800eva board switchs USB Host/Func by SW1.6,
+So, the device to adds into domain is selected on this patch.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 0f54788d8b4f7aa8d74b0a5a0ad706bcc216b3c7)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 101242a..cf10f92 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -953,6 +953,8 @@ clock_error:
+ #define GPIO_PORT8CR  0xe6050008
+ static void __init eva_init(void)
+ {
++      struct platform_device *usb = NULL;
++
+       regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
+                                    ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+@@ -1050,6 +1052,7 @@ static void __init eva_init(void)
+               gpio_direction_input(GPIO_PORT209);
+               platform_device_register(&usbhsf_device);
++              usb = &usbhsf_device;
+       }
+       /* SDHI0 */
+@@ -1180,6 +1183,8 @@ static void __init eva_init(void)
+       rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device);
+       rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device);
++      if (usb)
++              rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb);
+ }
+ static void __init eva_earlytimer_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch b/patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch
new file mode 100644 (file)
index 0000000..d3e0e1c
--- /dev/null
@@ -0,0 +1,118 @@
+From db4818fde4a8b81acde03834936d131a21c4ae4f Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Fri, 6 Jul 2012 17:08:07 +0900
+Subject: ARM: mach-shmobile: r8a7740 generic board support via DT
+
+Add generic DT board support for the r8a7740 SoC.
+
+SCIF serial ports and timers are kept as regular
+platform devices. Other on-chip and on-board devices
+should be configured via the device tree.
+
+At this point there is no interrupt controller support
+in place but such code will be added over time when
+proper IRQ domain support has been added to INTC.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 755d57b2229bd8cfa1d553c0b6878f2096f55ec3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/boot/dts/r8a7740.dtsi         | 21 +++++++++++++++
+ arch/arm/mach-shmobile/setup-r8a7740.c | 47 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 68 insertions(+)
+ create mode 100644 arch/arm/boot/dts/r8a7740.dtsi
+
+diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
+new file mode 100644
+index 0000000..798fa35
+--- /dev/null
++++ b/arch/arm/boot/dts/r8a7740.dtsi
+@@ -0,0 +1,21 @@
++/*
++ * Device Tree Source for the r8a7740 SoC
++ *
++ * Copyright (C) 2012 Renesas Solutions Corp.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2.  This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++/include/ "skeleton.dtsi"
++
++/ {
++      compatible = "renesas,r8a7740";
++
++      cpus {
++              cpu@0 {
++                      compatible = "arm,cortex-a9";
++              };
++      };
++};
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index c006d8d..78948a9 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -23,6 +23,7 @@
+ #include <linux/init.h>
+ #include <linux/io.h>
+ #include <linux/platform_device.h>
++#include <linux/of_platform.h>
+ #include <linux/serial_sci.h>
+ #include <linux/sh_dma.h>
+ #include <linux/sh_timer.h>
+@@ -716,3 +717,49 @@ void __init r8a7740_add_early_devices(void)
+       /* override timer setup with soc-specific code */
+       shmobile_timer.init = r8a7740_earlytimer_init;
+ }
++
++#ifdef CONFIG_USE_OF
++
++void __init r8a7740_add_early_devices_dt(void)
++{
++      shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */
++
++      early_platform_add_devices(r8a7740_early_devices,
++                                 ARRAY_SIZE(r8a7740_early_devices));
++
++      /* setup early console here as well */
++      shmobile_setup_console();
++}
++
++static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = {
++      { }
++};
++
++void __init r8a7740_add_standard_devices_dt(void)
++{
++      /* clocks are setup late during boot in the case of DT */
++      r8a7740_clock_init(0);
++
++      platform_add_devices(r8a7740_early_devices,
++                          ARRAY_SIZE(r8a7740_early_devices));
++
++      of_platform_populate(NULL, of_default_bus_match_table,
++                           r8a7740_auxdata_lookup, NULL);
++}
++
++static const char *r8a7740_boards_compat_dt[] __initdata = {
++      "renesas,r8a7740",
++      NULL,
++};
++
++DT_MACHINE_START(SH7372_DT, "Generic R8A7740 (Flattened Device Tree)")
++      .map_io         = r8a7740_map_io,
++      .init_early     = r8a7740_add_early_devices_dt,
++      .init_irq       = r8a7740_init_irq,
++      .handle_irq     = shmobile_handle_irq_intc,
++      .init_machine   = r8a7740_add_standard_devices_dt,
++      .timer          = &shmobile_timer,
++      .dt_compat      = r8a7740_boards_compat_dt,
++MACHINE_END
++
++#endif /* CONFIG_USE_OF */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch b/patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch
new file mode 100644 (file)
index 0000000..3b6f056
--- /dev/null
@@ -0,0 +1,43 @@
+From 8a8dced180f83f64ff5d6098281f27053df630ad Mon Sep 17 00:00:00 2001
+From: Simon Horman <horms@verge.net.au>
+Date: Fri, 6 Jul 2012 20:08:15 +0900
+Subject: ARM: mach-shmobile: armadillo800eva: defconfig Allow use of armhf
+ userspace
+
+This allows use a Debian armhf usespace
+as well as the existing ability to use a Debian armel userspace.
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 70523b4e57cb6eeb1da7c8ebf19df855221825ad)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/configs/armadillo800eva_defconfig | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
+index 16bbb3f..7d87184 100644
+--- a/arch/arm/configs/armadillo800eva_defconfig
++++ b/arch/arm/configs/armadillo800eva_defconfig
+@@ -18,7 +18,7 @@ CONFIG_ARCH_SHMOBILE=y
+ CONFIG_ARCH_R8A7740=y
+ CONFIG_MACH_ARMADILLO800EVA=y
+ # CONFIG_SH_TIMER_TMU is not set
+-# CONFIG_ARM_THUMB is not set
++CONFIG_ARM_THUMB=y
+ CONFIG_CPU_BPREDICT_DISABLE=y
+ # CONFIG_CACHE_L2X0 is not set
+ CONFIG_ARM_ERRATA_430973=y
+@@ -36,6 +36,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
+ CONFIG_CMDLINE_FORCE=y
+ CONFIG_KEXEC=y
++CONFIG_VFP=y
+ # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+ # CONFIG_SUSPEND is not set
+ CONFIG_NET=y
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch b/patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch
new file mode 100644 (file)
index 0000000..8184e72
--- /dev/null
@@ -0,0 +1,40 @@
+From fdfc19ff5c71ac77f6cc8781402dd92452e4e053 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 24 Jul 2012 15:26:08 +0200
+Subject: ARM: mach-shmobile: armadillo800eva: Fix GPIO buttons descriptions
+
+The GPIO buttons are named SW3, SW4, SW5 and SW6 on the board
+silkscreen. Update the buttons descriptions accordingly.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+(cherry picked from commit 2d85b9494d10501f20ebf043f8d599e45736d78f)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index cf10f92..a002504 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -523,10 +523,10 @@ static struct platform_device hdmi_lcdc_device = {
+ #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+ static struct gpio_keys_button gpio_buttons[] = {
+-      GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW1"),
+-      GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW2"),
+-      GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW3"),
+-      GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW4"),
++      GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW3"),
++      GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW4"),
++      GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW5"),
++      GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW6"),
+ };
+ static struct gpio_keys_platform_data gpio_key_info = {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch b/patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch
new file mode 100644 (file)
index 0000000..3e9c99c
--- /dev/null
@@ -0,0 +1,37 @@
+From 10ee1d677c8fa257269f2c5e062525035b866a61 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 24 Jul 2012 15:26:09 +0200
+Subject: ARM: mach-shmobile: armadillo800eva: Enable power button as wakeup
+ source
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+(cherry picked from commit 5c1d2d16772e2d7d4e2e8da99a92d6f50b9102f0)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index a002504..65cb793 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -520,10 +520,11 @@ static struct platform_device hdmi_lcdc_device = {
+ };
+ /* GPIO KEY */
+-#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
++#define GPIO_KEY(c, g, d, ...) \
++      { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
+ static struct gpio_keys_button gpio_buttons[] = {
+-      GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW3"),
++      GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW3", .wakeup = 1),
+       GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW4"),
+       GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW5"),
+       GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW6"),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch b/patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch
new file mode 100644 (file)
index 0000000..58ffe1c
--- /dev/null
@@ -0,0 +1,43 @@
+From 974462b8ff3fbb6468b94d52690a5707b2ccb955 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Wed, 8 Aug 2012 23:03:07 -0700
+Subject: ARM: shmobile: armadillo800eva: fixup: sound card detection order
+
+Since armadillo800eva has 2 sound cards,
+and had reversed deferred probe order issue,
+it was purposely registered in reverse order.
+
+But it was solved by
+1d29cfa57471a5e4b8a7c2a7433eeba170d3ad92
+(driver core: fixup reversed deferred probe order)
+
+armadillo800eva board is expecting that
+FSI-WM8978 is the 1st, and FSI-HDMI is the 2nd sound card.
+This patch fixes it up
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+(cherry picked from commit ee3c843d0fc21c68ced93b982b5731178a24df68)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-armadillo800eva.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
+index 65cb793..453a6e5 100644
+--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
++++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
+@@ -902,8 +902,8 @@ static struct platform_device *eva_devices[] __initdata = {
+       &camera_device,
+       &ceu0_device,
+       &fsi_device,
+-      &fsi_hdmi_device,
+       &fsi_wm8978_device,
++      &fsi_hdmi_device,
+ };
+ static void __init eva_clock_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch b/patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch
new file mode 100644 (file)
index 0000000..b53acd6
--- /dev/null
@@ -0,0 +1,39 @@
+From 1b5f7629ee098b784f2b8e2ee49d03d90e01f811 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Sun, 2 Sep 2012 23:06:52 -0700
+Subject: ARM: shmobile: armadillo800eva: enable rw rootfs mount
+
+armadillo800eva default boot loader is "hermit",
+and it's tag->u.core.flags has flag when kernel boots.
+Because of this, ${LINUX}/arch/arm/kernel/setup.c :: parse_tag_core()
+didn't remove MS_RDONLY flag from root_mountflags.
+Thus, the rootfs is mounted as "readonly".
+This patch adds "rw" kernel parameter,
+and enable read/write mounts for rootfs
+
+Cc: Masahiro Nakai <nakai@atmark-techno.com>
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+(cherry picked from commit 28e515878f8896b33c325ff9767cb0237210fb4c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/configs/armadillo800eva_defconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
+index 7d87184..90610c7 100644
+--- a/arch/arm/configs/armadillo800eva_defconfig
++++ b/arch/arm/configs/armadillo800eva_defconfig
+@@ -33,7 +33,7 @@ CONFIG_AEABI=y
+ CONFIG_FORCE_MAX_ZONEORDER=13
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
++CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw"
+ CONFIG_CMDLINE_FORCE=y
+ CONFIG_KEXEC=y
+ CONFIG_VFP=y
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch b/patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch
new file mode 100644 (file)
index 0000000..f043fca
--- /dev/null
@@ -0,0 +1,154 @@
+From aa9210ec33e000900e3ad25d7b98c7897027b1f2 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Wed, 11 Apr 2012 12:05:50 +0900
+Subject: sh: clkfwk: Support variable size accesses for MSTP clocks.
+
+The bulk of the MSTP users require 32-bit access, but this isn't the case
+for some of the SH-2A parts, so add in some basic infrastructure to let
+the CPU define its required access size in preparation.
+
+Requested-by: Phil Edworthy <phil.edworthy@renesas.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 4d6ddb08acc48368c5b7ac431f9d00db7227d2ed)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c   | 38 +++++++++++++++++++++++++++-----------
+ include/linux/sh_clk.h | 34 +++++++++++++++++++++++++++++++---
+ 2 files changed, 58 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 91b6d52..6cbda48 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -2,6 +2,7 @@
+  * Helper routines for SuperH Clock Pulse Generator blocks (CPG).
+  *
+  *  Copyright (C) 2010  Magnus Damm
++ *  Copyright (C) 2010 - 2012  Paul Mundt
+  *
+  * This file is subject to the terms and conditions of the GNU General Public
+  * License.  See the file "COPYING" in the main directory of this archive
+@@ -13,26 +14,41 @@
+ #include <linux/io.h>
+ #include <linux/sh_clk.h>
+-static int sh_clk_mstp32_enable(struct clk *clk)
++static int sh_clk_mstp_enable(struct clk *clk)
+ {
+-      iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+-                clk->mapped_reg);
++      if (clk->flags & CLK_ENABLE_REG_8BIT)
++              iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit),
++                       clk->mapped_reg);
++      else if (clk->flags & CLK_ENABLE_REG_16BIT)
++              iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit),
++                        clk->mapped_reg);
++      else
++              iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
++                        clk->mapped_reg);
++
+       return 0;
+ }
+-static void sh_clk_mstp32_disable(struct clk *clk)
++static void sh_clk_mstp_disable(struct clk *clk)
+ {
+-      iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+-                clk->mapped_reg);
++      if (clk->flags & CLK_ENABLE_REG_8BIT)
++              iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit),
++                       clk->mapped_reg);
++      else if (clk->flags & CLK_ENABLE_REG_16BIT)
++              iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit),
++                        clk->mapped_reg);
++      else
++              iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
++                        clk->mapped_reg);
+ }
+-static struct sh_clk_ops sh_clk_mstp32_clk_ops = {
+-      .enable         = sh_clk_mstp32_enable,
+-      .disable        = sh_clk_mstp32_disable,
++static struct sh_clk_ops sh_clk_mstp_clk_ops = {
++      .enable         = sh_clk_mstp_enable,
++      .disable        = sh_clk_mstp_disable,
+       .recalc         = followparent_recalc,
+ };
+-int __init sh_clk_mstp32_register(struct clk *clks, int nr)
++int __init sh_clk_mstp_register(struct clk *clks, int nr)
+ {
+       struct clk *clkp;
+       int ret = 0;
+@@ -40,7 +56,7 @@ int __init sh_clk_mstp32_register(struct clk *clks, int nr)
+       for (k = 0; !ret && (k < nr); k++) {
+               clkp = clks + k;
+-              clkp->ops = &sh_clk_mstp32_clk_ops;
++              clkp->ops = &sh_clk_mstp_clk_ops;
+               ret |= clk_register(clkp);
+       }
+diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
+index 0a9d8f2..c513b73 100644
+--- a/include/linux/sh_clk.h
++++ b/include/linux/sh_clk.h
+@@ -59,7 +59,15 @@ struct clk {
+       unsigned int            nr_freqs;
+ };
+-#define CLK_ENABLE_ON_INIT    (1 << 0)
++#define CLK_ENABLE_ON_INIT    BIT(0)
++
++#define CLK_ENABLE_REG_32BIT  BIT(1)  /* default access size */
++#define CLK_ENABLE_REG_16BIT  BIT(2)
++#define CLK_ENABLE_REG_8BIT   BIT(3)
++
++#define CLK_ENABLE_REG_MASK   (CLK_ENABLE_REG_32BIT | \
++                               CLK_ENABLE_REG_16BIT | \
++                               CLK_ENABLE_REG_8BIT)
+ /* drivers/sh/clk.c */
+ unsigned long followparent_recalc(struct clk *);
+@@ -102,7 +110,7 @@ long clk_round_parent(struct clk *clk, unsigned long target,
+                     unsigned long *best_freq, unsigned long *parent_freq,
+                     unsigned int div_min, unsigned int div_max);
+-#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags)      \
++#define SH_CLK_MSTP(_parent, _enable_reg, _enable_bit, _flags)                \
+ {                                                                     \
+       .parent         = _parent,                                      \
+       .enable_reg     = (void __iomem *)_enable_reg,                  \
+@@ -110,7 +118,27 @@ long clk_round_parent(struct clk *clk, unsigned long target,
+       .flags          = _flags,                                       \
+ }
+-int sh_clk_mstp32_register(struct clk *clks, int nr);
++#define SH_CLK_MSTP32(_p, _r, _b, _f)                                 \
++      SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_32BIT)
++
++#define SH_CLK_MSTP16(_p, _r, _b, _f)                                 \
++      SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_16BIT)
++
++#define SH_CLK_MSTP8(_p, _r, _b, _f)                                  \
++      SH_CLK_MSTP(_p, _r, _b, _f | CLK_ENABLE_REG_8BIT)
++
++int sh_clk_mstp_register(struct clk *clks, int nr);
++
++/*
++ * MSTP registration never really cared about access size, despite the
++ * original enable/disable pairs assuming a 32-bit access. Clocks are
++ * responsible for defining their access sizes either directly or via the
++ * clock definition wrappers.
++ */
++static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
++{
++      return sh_clk_mstp_register(clks, nr);
++}
+ #define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags)       \
+ {                                                             \
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch b/patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch
new file mode 100644 (file)
index 0000000..5d1fac6
--- /dev/null
@@ -0,0 +1,202 @@
+From 5a1639b2287a62e965e2355c68ef52da597b9a3c Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Thu, 12 Apr 2012 19:50:40 +0900
+Subject: sh: clkfwk: Support variable size accesses for div4/div6 clocks.
+
+This follows the MSTP clock change and implements variable access size
+support for the rest of the CPG clocks, too. Upcoming SH-2A support has
+need of this for 16-bit div4 clocks, while others will follow.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 104fa61a7dd83197160d5cafedc0e94ad9cd7fcc)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c | 71 +++++++++++++++++++++++++++-------------------------
+ 1 file changed, 37 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 6cbda48..f0d015d 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -14,32 +14,35 @@
+ #include <linux/io.h>
+ #include <linux/sh_clk.h>
+-static int sh_clk_mstp_enable(struct clk *clk)
++static unsigned int sh_clk_read(struct clk *clk)
+ {
+       if (clk->flags & CLK_ENABLE_REG_8BIT)
+-              iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit),
+-                       clk->mapped_reg);
++              return ioread8(clk->mapped_reg);
+       else if (clk->flags & CLK_ENABLE_REG_16BIT)
+-              iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit),
+-                        clk->mapped_reg);
+-      else
+-              iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+-                        clk->mapped_reg);
++              return ioread16(clk->mapped_reg);
+-      return 0;
++      return ioread32(clk->mapped_reg);
+ }
+-static void sh_clk_mstp_disable(struct clk *clk)
++static void sh_clk_write(int value, struct clk *clk)
+ {
+       if (clk->flags & CLK_ENABLE_REG_8BIT)
+-              iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit),
+-                       clk->mapped_reg);
++              iowrite8(value, clk->mapped_reg);
+       else if (clk->flags & CLK_ENABLE_REG_16BIT)
+-              iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit),
+-                        clk->mapped_reg);
++              iowrite16(value, clk->mapped_reg);
+       else
+-              iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+-                        clk->mapped_reg);
++              iowrite32(value, clk->mapped_reg);
++}
++
++static int sh_clk_mstp_enable(struct clk *clk)
++{
++      sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk);
++      return 0;
++}
++
++static void sh_clk_mstp_disable(struct clk *clk)
++{
++      sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk);
+ }
+ static struct sh_clk_ops sh_clk_mstp_clk_ops = {
+@@ -88,7 +91,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, NULL);
+-      idx = ioread32(clk->mapped_reg) & 0x003f;
++      idx = sh_clk_read(clk) & 0x003f;
+       return clk->freq_table[idx].frequency;
+ }
+@@ -114,10 +117,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+       if (ret < 0)
+               return ret;
+-      value = ioread32(clk->mapped_reg) &
++      value = sh_clk_read(clk) &
+               ~(((1 << clk->src_width) - 1) << clk->src_shift);
+-      iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
++      sh_clk_write(value | (i << clk->src_shift), clk);
+       /* Rebuild the frequency table */
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+@@ -135,10 +138,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
+       if (idx < 0)
+               return idx;
+-      value = ioread32(clk->mapped_reg);
++      value = sh_clk_read(clk);
+       value &= ~0x3f;
+       value |= idx;
+-      iowrite32(value, clk->mapped_reg);
++      sh_clk_write(value, clk);
+       return 0;
+ }
+@@ -149,9 +152,9 @@ static int sh_clk_div6_enable(struct clk *clk)
+       ret = sh_clk_div6_set_rate(clk, clk->rate);
+       if (ret == 0) {
+-              value = ioread32(clk->mapped_reg);
++              value = sh_clk_read(clk);
+               value &= ~0x100; /* clear stop bit to enable clock */
+-              iowrite32(value, clk->mapped_reg);
++              sh_clk_write(value, clk);
+       }
+       return ret;
+ }
+@@ -160,10 +163,10 @@ static void sh_clk_div6_disable(struct clk *clk)
+ {
+       unsigned long value;
+-      value = ioread32(clk->mapped_reg);
++      value = sh_clk_read(clk);
+       value |= 0x100; /* stop clock */
+       value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
+-      iowrite32(value, clk->mapped_reg);
++      sh_clk_write(value, clk);
+ }
+ static struct sh_clk_ops sh_clk_div6_clk_ops = {
+@@ -198,7 +201,7 @@ static int __init sh_clk_init_parent(struct clk *clk)
+               return -EINVAL;
+       }
+-      val  = (ioread32(clk->mapped_reg) >> clk->src_shift);
++      val  = (sh_clk_read(clk) >> clk->src_shift);
+       val &= (1 << clk->src_width) - 1;
+       if (val >= clk->parent_num) {
+@@ -268,7 +271,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, &clk->arch_flags);
+-      idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
++      idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f;
+       return clk->freq_table[idx].frequency;
+ }
+@@ -286,15 +289,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+        */
+       if (parent->flags & CLK_ENABLE_ON_INIT)
+-              value = ioread32(clk->mapped_reg) & ~(1 << 7);
++              value = sh_clk_read(clk) & ~(1 << 7);
+       else
+-              value = ioread32(clk->mapped_reg) | (1 << 7);
++              value = sh_clk_read(clk) | (1 << 7);
+       ret = clk_reparent(clk, parent);
+       if (ret < 0)
+               return ret;
+-      iowrite32(value, clk->mapped_reg);
++      sh_clk_write(value, clk);
+       /* Rebiuld the frequency table */
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+@@ -311,10 +314,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
+       if (idx < 0)
+               return idx;
+-      value = ioread32(clk->mapped_reg);
++      value = sh_clk_read(clk);
+       value &= ~(0xf << clk->enable_bit);
+       value |= (idx << clk->enable_bit);
+-      iowrite32(value, clk->mapped_reg);
++      sh_clk_write(value, clk);
+       if (d4t->kick)
+               d4t->kick(clk);
+@@ -324,13 +327,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
+ static int sh_clk_div4_enable(struct clk *clk)
+ {
+-      iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
++      sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
+       return 0;
+ }
+ static void sh_clk_div4_disable(struct clk *clk)
+ {
+-      iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
++      sh_clk_write(sh_clk_read(clk) | (1 << 8), clk);
+ }
+ static struct sh_clk_ops sh_clk_div4_clk_ops = {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch b/patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch
new file mode 100644 (file)
index 0000000..c7a6b9b
--- /dev/null
@@ -0,0 +1,169 @@
+From cd33eef0c195fa40494a8115aa1202bdaed860a0 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 14:59:26 +0900
+Subject: sh: clkfwk: Move to common clk_div_table accessors for div4/div6.
+
+This plugs in a generic clk_div_table, based on the div4 version. div6 is
+then adopted to use it for encapsulating its div table, which permits us
+to start div6/4 unification, as well as preparation for other div types.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit a60977a51333a8108f0574aa26094d66b7fedf34)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c   | 46 +++++++++++++++++++++++++++++++++++-----------
+ include/linux/sh_clk.h |  5 +++--
+ 2 files changed, 38 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index f0d015d..9dea329 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -71,6 +71,22 @@ static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
+       return clk_rate_table_round(clk, clk->freq_table, rate);
+ }
++/*
++ * Div/mult table lookup helpers
++ */
++static inline struct clk_div_table *clk_to_div_table(struct clk *clk)
++{
++      return clk->priv;
++}
++
++static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
++{
++      return clk_to_div_table(clk)->div_mult_table;
++}
++
++/*
++ * div6 support
++ */
+ static int sh_clk_div6_divisors[64] = {
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+@@ -78,14 +94,18 @@ static int sh_clk_div6_divisors[64] = {
+       49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
+ };
+-static struct clk_div_mult_table sh_clk_div6_table = {
++static struct clk_div_mult_table div6_div_mult_table = {
+       .divisors = sh_clk_div6_divisors,
+       .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
+ };
++static struct clk_div_table sh_clk_div6_table = {
++      .div_mult_table = &div6_div_mult_table,
++};
++
+ static unsigned long sh_clk_div6_recalc(struct clk *clk)
+ {
+-      struct clk_div_mult_table *table = &sh_clk_div6_table;
++      struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+       unsigned int idx;
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+@@ -98,7 +118,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
+ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+ {
+-      struct clk_div_mult_table *table = &sh_clk_div6_table;
++      struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+       u32 value;
+       int ret, i;
+@@ -223,7 +243,8 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
+ {
+       struct clk *clkp;
+       void *freq_table;
+-      int nr_divs = sh_clk_div6_table.nr_divisors;
++      struct clk_div_table *table = &sh_clk_div6_table;
++      int nr_divs = table->div_mult_table->nr_divisors;
+       int freq_table_size = sizeof(struct cpufreq_frequency_table);
+       int ret = 0;
+       int k;
+@@ -239,6 +260,7 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
+               clkp = clks + k;
+               clkp->ops = ops;
++              clkp->priv = table;
+               clkp->freq_table = freq_table + (k * freq_table_size);
+               clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
+               ret = clk_register(clkp);
+@@ -262,10 +284,12 @@ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
+                                       &sh_clk_div6_reparent_clk_ops);
+ }
++/*
++ * div4 support
++ */
+ static unsigned long sh_clk_div4_recalc(struct clk *clk)
+ {
+-      struct clk_div4_table *d4t = clk->priv;
+-      struct clk_div_mult_table *table = d4t->div_mult_table;
++      struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+       unsigned int idx;
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+@@ -278,8 +302,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
+ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+ {
+-      struct clk_div4_table *d4t = clk->priv;
+-      struct clk_div_mult_table *table = d4t->div_mult_table;
++      struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+       u32 value;
+       int ret;
+@@ -308,7 +331,7 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
+ {
+-      struct clk_div4_table *d4t = clk->priv;
++      struct clk_div_table *dt = clk_to_div_table(clk);
+       unsigned long value;
+       int idx = clk_rate_table_find(clk, clk->freq_table, rate);
+       if (idx < 0)
+@@ -319,8 +342,9 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
+       value |= (idx << clk->enable_bit);
+       sh_clk_write(value, clk);
+-      if (d4t->kick)
+-              d4t->kick(clk);
++      /* XXX: Should use a post-change notifier */
++      if (dt->kick)
++              dt->kick(clk);
+       return 0;
+ }
+diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
+index c513b73..706b803 100644
+--- a/include/linux/sh_clk.h
++++ b/include/linux/sh_clk.h
+@@ -18,7 +18,6 @@ struct clk_mapping {
+       struct kref             ref;
+ };
+-
+ struct sh_clk_ops {
+ #ifdef CONFIG_SH_CLK_CPG_LEGACY
+       void (*init)(struct clk *clk);
+@@ -149,11 +148,13 @@ static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
+       .flags = _flags,                                        \
+ }
+-struct clk_div4_table {
++struct clk_div_table {
+       struct clk_div_mult_table *div_mult_table;
+       void (*kick)(struct clk *clk);
+ };
++#define clk_div4_table clk_div_table
++
+ int sh_clk_div4_register(struct clk *clks, int nr,
+                        struct clk_div4_table *table);
+ int sh_clk_div4_enable_register(struct clk *clks, int nr,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch b/patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch
new file mode 100644 (file)
index 0000000..f8629fb
--- /dev/null
@@ -0,0 +1,117 @@
+From a0643bdb2770016b5930f9cbe5dee7a36e6951fc Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 15:21:43 +0900
+Subject: sh: clkfwk: Introduce a div_mask for variable div types.
+
+This plugs in a div_mask for the clock and sets it up for the existing
+div6/4 cases. This will make it possible to support other div types, as
+well as share more div6/4 infrastructure.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 1111cc1e8080b5ff46f5b945acb2f99d6176b2d1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c   | 10 +++++-----
+ include/linux/sh_clk.h |  8 ++++++++
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 9dea329..9386bd2 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -111,7 +111,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, NULL);
+-      idx = sh_clk_read(clk) & 0x003f;
++      idx = sh_clk_read(clk) & clk->div_mask;
+       return clk->freq_table[idx].frequency;
+ }
+@@ -159,7 +159,7 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
+               return idx;
+       value = sh_clk_read(clk);
+-      value &= ~0x3f;
++      value &= ~clk->div_mask;
+       value |= idx;
+       sh_clk_write(value, clk);
+       return 0;
+@@ -185,7 +185,7 @@ static void sh_clk_div6_disable(struct clk *clk)
+       value = sh_clk_read(clk);
+       value |= 0x100; /* stop clock */
+-      value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
++      value |= clk->div_mask; /* VDIV bits must be non-zero, overwrite divider */
+       sh_clk_write(value, clk);
+ }
+@@ -295,7 +295,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, &clk->arch_flags);
+-      idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f;
++      idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
+       return clk->freq_table[idx].frequency;
+ }
+@@ -338,7 +338,7 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
+               return idx;
+       value = sh_clk_read(clk);
+-      value &= ~(0xf << clk->enable_bit);
++      value &= ~(clk->div_mask << clk->enable_bit);
+       value |= (idx << clk->enable_bit);
+       sh_clk_write(value, clk);
+diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
+index 706b803..d540b81 100644
+--- a/include/linux/sh_clk.h
++++ b/include/linux/sh_clk.h
+@@ -30,6 +30,10 @@ struct sh_clk_ops {
+       long (*round_rate)(struct clk *clk, unsigned long rate);
+ };
++#define SH_CLK_DIV_MSK(div)   ((1 << (div)) - 1)
++#define SH_CLK_DIV4_MSK               SH_CLK_DIV_MSK(4)
++#define SH_CLK_DIV6_MSK               SH_CLK_DIV_MSK(6)
++
+ struct clk {
+       struct list_head        node;
+       struct clk              *parent;
+@@ -51,6 +55,7 @@ struct clk {
+       unsigned int            enable_bit;
+       void __iomem            *mapped_reg;
++      unsigned int            div_mask;
+       unsigned long           arch_flags;
+       void                    *priv;
+       struct clk_mapping      *mapping;
+@@ -145,6 +150,7 @@ static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
+       .enable_reg = (void __iomem *)_reg,                     \
+       .enable_bit = _shift,                                   \
+       .arch_flags = _div_bitmap,                              \
++      .div_mask = SH_CLK_DIV4_MSK,                            \
+       .flags = _flags,                                        \
+ }
+@@ -167,6 +173,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
+ {                                                             \
+       .enable_reg = (void __iomem *)_reg,                     \
+       .flags = _flags,                                        \
++      .div_mask = SH_CLK_DIV6_MSK,                            \
+       .parent_table = _parents,                               \
+       .parent_num = _num_parents,                             \
+       .src_shift = _src_shift,                                \
+@@ -177,6 +184,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
+ {                                                             \
+       .parent         = _parent,                              \
+       .enable_reg     = (void __iomem *)_reg,                 \
++      .div_mask       = SH_CLK_DIV6_MSK,                      \
+       .flags          = _flags,                               \
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch b/patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch
new file mode 100644 (file)
index 0000000..beb1b9b
--- /dev/null
@@ -0,0 +1,167 @@
+From 4a3185214cc3715feff6d802b0df478e7e61901e Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 15:26:01 +0900
+Subject: sh: clkfwk: Use shared sh_clk_div_recalc().
+
+This generalizes the div4 recalc routine for use by div6 and others, then
+makes it the default.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 75f5f8a56e0fdf6d32b3ae9c44c10bc0acd3857c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c   | 62 +++++++++++++++++++++-----------------------------
+ include/linux/sh_clk.h |  2 ++
+ 2 files changed, 28 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 9386bd2..84aeeb8 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -66,11 +66,6 @@ int __init sh_clk_mstp_register(struct clk *clks, int nr)
+       return ret;
+ }
+-static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
+-{
+-      return clk_rate_table_round(clk, clk->freq_table, rate);
+-}
+-
+ /*
+  * Div/mult table lookup helpers
+  */
+@@ -85,6 +80,27 @@ static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
+ }
+ /*
++ * Common div ops
++ */
++static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
++{
++      return clk_rate_table_round(clk, clk->freq_table, rate);
++}
++
++static unsigned long sh_clk_div_recalc(struct clk *clk)
++{
++      struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
++      unsigned int idx;
++
++      clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
++                           table, clk->arch_flags ? &clk->arch_flags : NULL);
++
++      idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
++
++      return clk->freq_table[idx].frequency;
++}
++
++/*
+  * div6 support
+  */
+ static int sh_clk_div6_divisors[64] = {
+@@ -103,19 +119,6 @@ static struct clk_div_table sh_clk_div6_table = {
+       .div_mult_table = &div6_div_mult_table,
+ };
+-static unsigned long sh_clk_div6_recalc(struct clk *clk)
+-{
+-      struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+-      unsigned int idx;
+-
+-      clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+-                           table, NULL);
+-
+-      idx = sh_clk_read(clk) & clk->div_mask;
+-
+-      return clk->freq_table[idx].frequency;
+-}
+-
+ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+ {
+       struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+@@ -190,7 +193,7 @@ static void sh_clk_div6_disable(struct clk *clk)
+ }
+ static struct sh_clk_ops sh_clk_div6_clk_ops = {
+-      .recalc         = sh_clk_div6_recalc,
++      .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+       .set_rate       = sh_clk_div6_set_rate,
+       .enable         = sh_clk_div6_enable,
+@@ -198,7 +201,7 @@ static struct sh_clk_ops sh_clk_div6_clk_ops = {
+ };
+ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
+-      .recalc         = sh_clk_div6_recalc,
++      .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+       .set_rate       = sh_clk_div6_set_rate,
+       .enable         = sh_clk_div6_enable,
+@@ -287,19 +290,6 @@ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
+ /*
+  * div4 support
+  */
+-static unsigned long sh_clk_div4_recalc(struct clk *clk)
+-{
+-      struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+-      unsigned int idx;
+-
+-      clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+-                           table, &clk->arch_flags);
+-
+-      idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
+-
+-      return clk->freq_table[idx].frequency;
+-}
+-
+ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+ {
+       struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+@@ -361,13 +351,13 @@ static void sh_clk_div4_disable(struct clk *clk)
+ }
+ static struct sh_clk_ops sh_clk_div4_clk_ops = {
+-      .recalc         = sh_clk_div4_recalc,
++      .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div4_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+ };
+ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
+-      .recalc         = sh_clk_div4_recalc,
++      .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div4_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+       .enable         = sh_clk_div4_enable,
+@@ -375,7 +365,7 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
+ };
+ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
+-      .recalc         = sh_clk_div4_recalc,
++      .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div4_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+       .enable         = sh_clk_div4_enable,
+diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
+index d540b81..35a04f1 100644
+--- a/include/linux/sh_clk.h
++++ b/include/linux/sh_clk.h
+@@ -172,6 +172,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
+                       _num_parents, _src_shift, _src_width)   \
+ {                                                             \
+       .enable_reg = (void __iomem *)_reg,                     \
++      .enable_bit = 0, /* unused */                           \
+       .flags = _flags,                                        \
+       .div_mask = SH_CLK_DIV6_MSK,                            \
+       .parent_table = _parents,                               \
+@@ -184,6 +185,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
+ {                                                             \
+       .parent         = _parent,                              \
+       .enable_reg     = (void __iomem *)_reg,                 \
++      .enable_bit     = 0,    /* unused */                    \
+       .div_mask       = SH_CLK_DIV6_MSK,                      \
+       .flags          = _flags,                               \
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch b/patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch
new file mode 100644 (file)
index 0000000..49ad18a
--- /dev/null
@@ -0,0 +1,151 @@
+From df94ddc15bc18c4fd96707fce2b3983e6f013f83 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 15:52:10 +0900
+Subject: sh: clkfwk: Use shared sh_clk_div_set_rate()
+
+Follows the sh_clk_div_recalc() change.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 0fa22168e00106797f28b2655aaefd0d16a6e67b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c | 70 +++++++++++++++++++++-------------------------------
+ 1 file changed, 28 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 84aeeb8..29ee5f7 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -100,6 +100,28 @@ static unsigned long sh_clk_div_recalc(struct clk *clk)
+       return clk->freq_table[idx].frequency;
+ }
++static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
++{
++      struct clk_div_table *dt = clk_to_div_table(clk);
++      unsigned long value;
++      int idx;
++
++      idx = clk_rate_table_find(clk, clk->freq_table, rate);
++      if (idx < 0)
++              return idx;
++
++      value = sh_clk_read(clk);
++      value &= ~(clk->div_mask << clk->enable_bit);
++      value |= (idx << clk->enable_bit);
++      sh_clk_write(value, clk);
++
++      /* XXX: Should use a post-change notifier */
++      if (dt->kick)
++              dt->kick(clk);
++
++      return 0;
++}
++
+ /*
+  * div6 support
+  */
+@@ -152,28 +174,12 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+       return 0;
+ }
+-static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
+-{
+-      unsigned long value;
+-      int idx;
+-
+-      idx = clk_rate_table_find(clk, clk->freq_table, rate);
+-      if (idx < 0)
+-              return idx;
+-
+-      value = sh_clk_read(clk);
+-      value &= ~clk->div_mask;
+-      value |= idx;
+-      sh_clk_write(value, clk);
+-      return 0;
+-}
+-
+ static int sh_clk_div6_enable(struct clk *clk)
+ {
+       unsigned long value;
+       int ret;
+-      ret = sh_clk_div6_set_rate(clk, clk->rate);
++      ret = sh_clk_div_set_rate(clk, clk->rate);
+       if (ret == 0) {
+               value = sh_clk_read(clk);
+               value &= ~0x100; /* clear stop bit to enable clock */
+@@ -195,7 +201,7 @@ static void sh_clk_div6_disable(struct clk *clk)
+ static struct sh_clk_ops sh_clk_div6_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+-      .set_rate       = sh_clk_div6_set_rate,
++      .set_rate       = sh_clk_div_set_rate,
+       .enable         = sh_clk_div6_enable,
+       .disable        = sh_clk_div6_disable,
+ };
+@@ -203,7 +209,7 @@ static struct sh_clk_ops sh_clk_div6_clk_ops = {
+ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+-      .set_rate       = sh_clk_div6_set_rate,
++      .set_rate       = sh_clk_div_set_rate,
+       .enable         = sh_clk_div6_enable,
+       .disable        = sh_clk_div6_disable,
+       .set_parent     = sh_clk_div6_set_parent,
+@@ -319,26 +325,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+       return 0;
+ }
+-static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
+-{
+-      struct clk_div_table *dt = clk_to_div_table(clk);
+-      unsigned long value;
+-      int idx = clk_rate_table_find(clk, clk->freq_table, rate);
+-      if (idx < 0)
+-              return idx;
+-
+-      value = sh_clk_read(clk);
+-      value &= ~(clk->div_mask << clk->enable_bit);
+-      value |= (idx << clk->enable_bit);
+-      sh_clk_write(value, clk);
+-
+-      /* XXX: Should use a post-change notifier */
+-      if (dt->kick)
+-              dt->kick(clk);
+-
+-      return 0;
+-}
+-
+ static int sh_clk_div4_enable(struct clk *clk)
+ {
+       sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
+@@ -352,13 +338,13 @@ static void sh_clk_div4_disable(struct clk *clk)
+ static struct sh_clk_ops sh_clk_div4_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+-      .set_rate       = sh_clk_div4_set_rate,
++      .set_rate       = sh_clk_div_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+ };
+ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+-      .set_rate       = sh_clk_div4_set_rate,
++      .set_rate       = sh_clk_div_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+       .enable         = sh_clk_div4_enable,
+       .disable        = sh_clk_div4_disable,
+@@ -366,7 +352,7 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
+ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+-      .set_rate       = sh_clk_div4_set_rate,
++      .set_rate       = sh_clk_div_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+       .enable         = sh_clk_div4_enable,
+       .disable        = sh_clk_div4_disable,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch b/patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch
new file mode 100644 (file)
index 0000000..420a1b4
--- /dev/null
@@ -0,0 +1,186 @@
+From c4dd62f54d65dfd226383c7c2aab74d9b33e71f5 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 16:34:48 +0900
+Subject: sh: clkfwk: Use shared sh_clk_div_enable/disable().
+
+This introduces a new flag for clocks that need to have their divisor
+ratio set back to their initial mask at disable time to prevent
+interactivity problems with the clock stop bit (presently div6 only).
+With this in place it's possible to handle the corner case on top of the
+div4 op without any particular need for leaving things split out.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 764f4e4e33d18cde4dcaf8a0d860b749c6d6d08b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c   | 77 ++++++++++++++++++++++----------------------------
+ include/linux/sh_clk.h |  6 ++--
+ 2 files changed, 38 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 29ee5f7..06537f2 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -14,6 +14,8 @@
+ #include <linux/io.h>
+ #include <linux/sh_clk.h>
++#define CPG_CKSTP_BIT BIT(8)
++
+ static unsigned int sh_clk_read(struct clk *clk)
+ {
+       if (clk->flags & CLK_ENABLE_REG_8BIT)
+@@ -122,6 +124,30 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
+       return 0;
+ }
++static int sh_clk_div_enable(struct clk *clk)
++{
++      sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
++      return 0;
++}
++
++static void sh_clk_div_disable(struct clk *clk)
++{
++      unsigned int val;
++
++      val = sh_clk_read(clk);
++      val |= CPG_CKSTP_BIT;
++
++      /*
++       * div6 clocks require the divisor field to be non-zero or the
++       * above CKSTP toggle silently fails. Ensure that the divisor
++       * array is reset to its initial state on disable.
++       */
++      if (clk->flags & CLK_MASK_DIV_ON_DISABLE)
++              val |= clk->div_mask;
++
++      sh_clk_write(val, clk);
++}
++
+ /*
+  * div6 support
+  */
+@@ -174,44 +200,20 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+       return 0;
+ }
+-static int sh_clk_div6_enable(struct clk *clk)
+-{
+-      unsigned long value;
+-      int ret;
+-
+-      ret = sh_clk_div_set_rate(clk, clk->rate);
+-      if (ret == 0) {
+-              value = sh_clk_read(clk);
+-              value &= ~0x100; /* clear stop bit to enable clock */
+-              sh_clk_write(value, clk);
+-      }
+-      return ret;
+-}
+-
+-static void sh_clk_div6_disable(struct clk *clk)
+-{
+-      unsigned long value;
+-
+-      value = sh_clk_read(clk);
+-      value |= 0x100; /* stop clock */
+-      value |= clk->div_mask; /* VDIV bits must be non-zero, overwrite divider */
+-      sh_clk_write(value, clk);
+-}
+-
+ static struct sh_clk_ops sh_clk_div6_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+       .set_rate       = sh_clk_div_set_rate,
+-      .enable         = sh_clk_div6_enable,
+-      .disable        = sh_clk_div6_disable,
++      .enable         = sh_clk_div_enable,
++      .disable        = sh_clk_div_disable,
+ };
+ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+       .set_rate       = sh_clk_div_set_rate,
+-      .enable         = sh_clk_div6_enable,
+-      .disable        = sh_clk_div6_disable,
++      .enable         = sh_clk_div_enable,
++      .disable        = sh_clk_div_disable,
+       .set_parent     = sh_clk_div6_set_parent,
+ };
+@@ -325,17 +327,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+       return 0;
+ }
+-static int sh_clk_div4_enable(struct clk *clk)
+-{
+-      sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
+-      return 0;
+-}
+-
+-static void sh_clk_div4_disable(struct clk *clk)
+-{
+-      sh_clk_write(sh_clk_read(clk) | (1 << 8), clk);
+-}
+-
+ static struct sh_clk_ops sh_clk_div4_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div_set_rate,
+@@ -346,16 +337,16 @@ static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+-      .enable         = sh_clk_div4_enable,
+-      .disable        = sh_clk_div4_disable,
++      .enable         = sh_clk_div_enable,
++      .disable        = sh_clk_div_disable,
+ };
+ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+-      .enable         = sh_clk_div4_enable,
+-      .disable        = sh_clk_div4_disable,
++      .enable         = sh_clk_div_enable,
++      .disable        = sh_clk_div_disable,
+       .set_parent     = sh_clk_div4_set_parent,
+ };
+diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
+index 35a04f1..5091091 100644
+--- a/include/linux/sh_clk.h
++++ b/include/linux/sh_clk.h
+@@ -69,6 +69,8 @@ struct clk {
+ #define CLK_ENABLE_REG_16BIT  BIT(2)
+ #define CLK_ENABLE_REG_8BIT   BIT(3)
++#define CLK_MASK_DIV_ON_DISABLE       BIT(4)
++
+ #define CLK_ENABLE_REG_MASK   (CLK_ENABLE_REG_32BIT | \
+                                CLK_ENABLE_REG_16BIT | \
+                                CLK_ENABLE_REG_8BIT)
+@@ -173,7 +175,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
+ {                                                             \
+       .enable_reg = (void __iomem *)_reg,                     \
+       .enable_bit = 0, /* unused */                           \
+-      .flags = _flags,                                        \
++      .flags = _flags | CLK_MASK_DIV_ON_DISABLE,              \
+       .div_mask = SH_CLK_DIV6_MSK,                            \
+       .parent_table = _parents,                               \
+       .parent_num = _num_parents,                             \
+@@ -187,7 +189,7 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
+       .enable_reg     = (void __iomem *)_reg,                 \
+       .enable_bit     = 0,    /* unused */                    \
+       .div_mask       = SH_CLK_DIV6_MSK,                      \
+-      .flags          = _flags,                               \
++      .flags          = _flags | CLK_MASK_DIV_ON_DISABLE,     \
+ }
+ int sh_clk_div6_register(struct clk *clks, int nr);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch b/patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch
new file mode 100644 (file)
index 0000000..581bf9a
--- /dev/null
@@ -0,0 +1,106 @@
+From d50dd1ccae270ab558c081c9a7697137a92afdce Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 16:43:42 +0900
+Subject: sh: clkfwk: Consolidate div6/div4 clk_ops definitions.
+
+Everything with the exception of the _reparent ops are now shared, so
+switch everything over to common types.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit e3c87607731e1a8937567e92a52eedee1bec622d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c | 42 +++++++++++++++++-------------------------
+ 1 file changed, 17 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 06537f2..eeaec79 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -148,6 +148,20 @@ static void sh_clk_div_disable(struct clk *clk)
+       sh_clk_write(val, clk);
+ }
++static struct sh_clk_ops sh_clk_div_clk_ops = {
++      .recalc         = sh_clk_div_recalc,
++      .set_rate       = sh_clk_div_set_rate,
++      .round_rate     = sh_clk_div_round_rate,
++};
++
++static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
++      .recalc         = sh_clk_div_recalc,
++      .set_rate       = sh_clk_div_set_rate,
++      .round_rate     = sh_clk_div_round_rate,
++      .enable         = sh_clk_div_enable,
++      .disable        = sh_clk_div_disable,
++};
++
+ /*
+  * div6 support
+  */
+@@ -200,14 +214,6 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+       return 0;
+ }
+-static struct sh_clk_ops sh_clk_div6_clk_ops = {
+-      .recalc         = sh_clk_div_recalc,
+-      .round_rate     = sh_clk_div_round_rate,
+-      .set_rate       = sh_clk_div_set_rate,
+-      .enable         = sh_clk_div_enable,
+-      .disable        = sh_clk_div_disable,
+-};
+-
+ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+@@ -286,7 +292,7 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
+ int __init sh_clk_div6_register(struct clk *clks, int nr)
+ {
+-      return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
++      return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops);
+ }
+ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
+@@ -327,20 +333,6 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+       return 0;
+ }
+-static struct sh_clk_ops sh_clk_div4_clk_ops = {
+-      .recalc         = sh_clk_div_recalc,
+-      .set_rate       = sh_clk_div_set_rate,
+-      .round_rate     = sh_clk_div_round_rate,
+-};
+-
+-static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
+-      .recalc         = sh_clk_div_recalc,
+-      .set_rate       = sh_clk_div_set_rate,
+-      .round_rate     = sh_clk_div_round_rate,
+-      .enable         = sh_clk_div_enable,
+-      .disable        = sh_clk_div_disable,
+-};
+-
+ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div_set_rate,
+@@ -385,14 +377,14 @@ static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
+ int __init sh_clk_div4_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+ {
+-      return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
++      return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
+ }
+ int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+ {
+       return sh_clk_div4_register_ops(clks, nr, table,
+-                                      &sh_clk_div4_enable_clk_ops);
++                                      &sh_clk_div_enable_clk_ops);
+ }
+ int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch b/patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch
new file mode 100644 (file)
index 0000000..bb9f3ea
--- /dev/null
@@ -0,0 +1,245 @@
+From 14bb73c341fd8f669c5c48c59811c8e27f3fefce Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 16:55:05 +0900
+Subject: sh: clkfwk: Consolidate div clk registration helper.
+
+This consolidates the div6/4 versions of the clk registration wrapper.
+The existing wrappers with their own sh_clk_ops are maintained for API
+compatability, though in the future it should be possible to be rid of
+them entirely.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 609d7558f232e583a31951c65a6ee43d81c65720)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/clk/cpg.c | 182 +++++++++++++++++++++------------------------------
+ 1 file changed, 75 insertions(+), 107 deletions(-)
+
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index eeaec79..07e9fb4 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -162,6 +162,72 @@ static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
+       .disable        = sh_clk_div_disable,
+ };
++static int __init sh_clk_init_parent(struct clk *clk)
++{
++      u32 val;
++
++      if (clk->parent)
++              return 0;
++
++      if (!clk->parent_table || !clk->parent_num)
++              return 0;
++
++      if (!clk->src_width) {
++              pr_err("sh_clk_init_parent: cannot select parent clock\n");
++              return -EINVAL;
++      }
++
++      val  = (sh_clk_read(clk) >> clk->src_shift);
++      val &= (1 << clk->src_width) - 1;
++
++      if (val >= clk->parent_num) {
++              pr_err("sh_clk_init_parent: parent table size failed\n");
++              return -EINVAL;
++      }
++
++      clk_reparent(clk, clk->parent_table[val]);
++      if (!clk->parent) {
++              pr_err("sh_clk_init_parent: unable to set parent");
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int __init sh_clk_div_register_ops(struct clk *clks, int nr,
++                      struct clk_div_table *table, struct sh_clk_ops *ops)
++{
++      struct clk *clkp;
++      void *freq_table;
++      int nr_divs = table->div_mult_table->nr_divisors;
++      int freq_table_size = sizeof(struct cpufreq_frequency_table);
++      int ret = 0;
++      int k;
++
++      freq_table_size *= (nr_divs + 1);
++      freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
++      if (!freq_table) {
++              pr_err("%s: unable to alloc memory\n", __func__);
++              return -ENOMEM;
++      }
++
++      for (k = 0; !ret && (k < nr); k++) {
++              clkp = clks + k;
++
++              clkp->ops = ops;
++              clkp->priv = table;
++
++              clkp->freq_table = freq_table + (k * freq_table_size);
++              clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
++
++              ret = clk_register(clkp);
++              if (ret == 0)
++                      ret = sh_clk_init_parent(clkp);
++      }
++
++      return ret;
++}
++
+ /*
+  * div6 support
+  */
+@@ -223,82 +289,16 @@ static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
+       .set_parent     = sh_clk_div6_set_parent,
+ };
+-static int __init sh_clk_init_parent(struct clk *clk)
+-{
+-      u32 val;
+-
+-      if (clk->parent)
+-              return 0;
+-
+-      if (!clk->parent_table || !clk->parent_num)
+-              return 0;
+-
+-      if (!clk->src_width) {
+-              pr_err("sh_clk_init_parent: cannot select parent clock\n");
+-              return -EINVAL;
+-      }
+-
+-      val  = (sh_clk_read(clk) >> clk->src_shift);
+-      val &= (1 << clk->src_width) - 1;
+-
+-      if (val >= clk->parent_num) {
+-              pr_err("sh_clk_init_parent: parent table size failed\n");
+-              return -EINVAL;
+-      }
+-
+-      clk_reparent(clk, clk->parent_table[val]);
+-      if (!clk->parent) {
+-              pr_err("sh_clk_init_parent: unable to set parent");
+-              return -EINVAL;
+-      }
+-
+-      return 0;
+-}
+-
+-static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
+-                                         struct sh_clk_ops *ops)
+-{
+-      struct clk *clkp;
+-      void *freq_table;
+-      struct clk_div_table *table = &sh_clk_div6_table;
+-      int nr_divs = table->div_mult_table->nr_divisors;
+-      int freq_table_size = sizeof(struct cpufreq_frequency_table);
+-      int ret = 0;
+-      int k;
+-
+-      freq_table_size *= (nr_divs + 1);
+-      freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
+-      if (!freq_table) {
+-              pr_err("sh_clk_div6_register: unable to alloc memory\n");
+-              return -ENOMEM;
+-      }
+-
+-      for (k = 0; !ret && (k < nr); k++) {
+-              clkp = clks + k;
+-
+-              clkp->ops = ops;
+-              clkp->priv = table;
+-              clkp->freq_table = freq_table + (k * freq_table_size);
+-              clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
+-              ret = clk_register(clkp);
+-              if (ret < 0)
+-                      break;
+-
+-              ret = sh_clk_init_parent(clkp);
+-      }
+-
+-      return ret;
+-}
+-
+ int __init sh_clk_div6_register(struct clk *clks, int nr)
+ {
+-      return sh_clk_div6_register_ops(clks, nr, &sh_clk_div_enable_clk_ops);
++      return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
++                                     &sh_clk_div_enable_clk_ops);
+ }
+ int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
+ {
+-      return sh_clk_div6_register_ops(clks, nr,
+-                                      &sh_clk_div6_reparent_clk_ops);
++      return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
++                                     &sh_clk_div6_reparent_clk_ops);
+ }
+ /*
+@@ -342,54 +342,22 @@ static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
+       .set_parent     = sh_clk_div4_set_parent,
+ };
+-static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
+-                      struct clk_div4_table *table, struct sh_clk_ops *ops)
+-{
+-      struct clk *clkp;
+-      void *freq_table;
+-      int nr_divs = table->div_mult_table->nr_divisors;
+-      int freq_table_size = sizeof(struct cpufreq_frequency_table);
+-      int ret = 0;
+-      int k;
+-
+-      freq_table_size *= (nr_divs + 1);
+-      freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
+-      if (!freq_table) {
+-              pr_err("sh_clk_div4_register: unable to alloc memory\n");
+-              return -ENOMEM;
+-      }
+-
+-      for (k = 0; !ret && (k < nr); k++) {
+-              clkp = clks + k;
+-
+-              clkp->ops = ops;
+-              clkp->priv = table;
+-
+-              clkp->freq_table = freq_table + (k * freq_table_size);
+-              clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
+-
+-              ret = clk_register(clkp);
+-      }
+-
+-      return ret;
+-}
+-
+ int __init sh_clk_div4_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+ {
+-      return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
++      return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
+ }
+ int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+ {
+-      return sh_clk_div4_register_ops(clks, nr, table,
+-                                      &sh_clk_div_enable_clk_ops);
++      return sh_clk_div_register_ops(clks, nr, table,
++                                     &sh_clk_div_enable_clk_ops);
+ }
+ int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+ {
+-      return sh_clk_div4_register_ops(clks, nr, table,
+-                                      &sh_clk_div4_reparent_clk_ops);
++      return sh_clk_div_register_ops(clks, nr, table,
++                                     &sh_clk_div4_reparent_clk_ops);
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch b/patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch
new file mode 100644 (file)
index 0000000..1a0d512
--- /dev/null
@@ -0,0 +1,128 @@
+From 0ee607349ba34cf8cdb94370c297faed58f64e39 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Sat, 19 May 2012 15:11:41 +0900
+Subject: irqdomain: Support removal of IRQ domains.
+
+Now that IRQ domains are being used by modules it's necessary to support
+removing them, too. This adds a new irq_domain_remove() routine for doing
+the bulk of the heavy lifting. It's left as an exercise to the caller to
+ensure all mappings have been appropriatey disposed of before attempting
+to remove the domain.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit 58ee99ada293b5ed971a023304fcfbc1a0ccdb1c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/irqdomain.h |  4 +++-
+ kernel/irq/irqdomain.c    | 61 +++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 62 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
+index c65740d..a796dbf 100644
+--- a/include/linux/irqdomain.h
++++ b/include/linux/irqdomain.h
+@@ -141,10 +141,12 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
+       return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops,
+                                    host_data);
+ }
++
++extern void irq_domain_remove(struct irq_domain *host);
++
+ extern struct irq_domain *irq_find_host(struct device_node *node);
+ extern void irq_set_default_host(struct irq_domain *host);
+-
+ extern unsigned int irq_create_mapping(struct irq_domain *host,
+                                      irq_hw_number_t hwirq);
+ extern void irq_dispose_mapping(unsigned int virq);
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 0e0ba5f..9cae0b2 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -56,6 +56,12 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
+       return domain;
+ }
++static void irq_domain_free(struct irq_domain *domain)
++{
++      of_node_put(domain->of_node);
++      kfree(domain);
++}
++
+ static void irq_domain_add(struct irq_domain *domain)
+ {
+       mutex_lock(&irq_domain_mutex);
+@@ -65,6 +71,58 @@ static void irq_domain_add(struct irq_domain *domain)
+                domain->revmap_type, domain);
+ }
++/**
++ * irq_domain_remove() - Remove an irq domain.
++ * @domain: domain to remove
++ *
++ * This routine is used to remove an irq domain. The caller must ensure
++ * that all mappings within the domain have been disposed of prior to
++ * use, depending on the revmap type.
++ */
++void irq_domain_remove(struct irq_domain *domain)
++{
++      mutex_lock(&irq_domain_mutex);
++
++      switch (domain->revmap_type) {
++      case IRQ_DOMAIN_MAP_LEGACY:
++              /*
++               * Legacy domains don't manage their own irq_desc
++               * allocations, we expect the caller to handle irq_desc
++               * freeing on their own.
++               */
++              break;
++      case IRQ_DOMAIN_MAP_TREE:
++              /*
++               * radix_tree_delete() takes care of destroying the root
++               * node when all entries are removed. Shout if there are
++               * any mappings left.
++               */
++              WARN_ON(domain->revmap_data.tree.height);
++              break;
++      case IRQ_DOMAIN_MAP_LINEAR:
++              kfree(domain->revmap_data.linear.revmap);
++              domain->revmap_data.linear.size = 0;
++              break;
++      case IRQ_DOMAIN_MAP_NOMAP:
++              break;
++      }
++
++      list_del(&domain->link);
++
++      /*
++       * If the going away domain is the default one, reset it.
++       */
++      if (unlikely(irq_default_domain == domain))
++              irq_set_default_host(NULL);
++
++      mutex_unlock(&irq_domain_mutex);
++
++      pr_debug("irq: Removed domain of type %d @0x%p\n",
++               domain->revmap_type, domain);
++
++      irq_domain_free(domain);
++}
++
+ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
+                                            irq_hw_number_t hwirq)
+ {
+@@ -117,8 +175,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
+               if (WARN_ON(!irq_data || irq_data->domain)) {
+                       mutex_unlock(&irq_domain_mutex);
+-                      of_node_put(domain->of_node);
+-                      kfree(domain);
++                      irq_domain_free(domain);
+                       return NULL;
+               }
+       }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch b/patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch
new file mode 100644 (file)
index 0000000..4489c8e
--- /dev/null
@@ -0,0 +1,109 @@
+From fd54923383b7dee6af8b53a91d2c6768d2726d77 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Sat, 19 May 2012 15:11:42 +0900
+Subject: irqdomain: Export remaining public API symbols.
+
+modules making use of irq domains at the very least need access to the
+add/remove/lookup routines, though there's nothing preventing them from
+using the remainder of the public API, either.
+
+The current set of exports seem primarily geared at DT-enabled platforms
+using DT-backed IRQ domains, where many of the API accesses are hidden
+away in OF code. The non-DT cases need to do most of this on their own.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit ecd84eb20a08841197d6bbda5961dcf5f4e424fc)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 9cae0b2..01d4a0d 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -122,6 +122,7 @@ void irq_domain_remove(struct irq_domain *domain)
+       irq_domain_free(domain);
+ }
++EXPORT_SYMBOL_GPL(irq_domain_remove);
+ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
+                                            irq_hw_number_t hwirq)
+@@ -209,6 +210,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
+       irq_domain_add(domain);
+       return domain;
+ }
++EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
+ /**
+  * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
+@@ -238,6 +240,7 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
+       irq_domain_add(domain);
+       return domain;
+ }
++EXPORT_SYMBOL_GPL(irq_domain_add_linear);
+ struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
+                                        unsigned int max_irq,
+@@ -252,6 +255,7 @@ struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
+       }
+       return domain;
+ }
++EXPORT_SYMBOL_GPL(irq_domain_add_nomap);
+ /**
+  * irq_domain_add_tree()
+@@ -273,6 +277,7 @@ struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
+       }
+       return domain;
+ }
++EXPORT_SYMBOL_GPL(irq_domain_add_tree);
+ /**
+  * irq_find_host() - Locates a domain for a given device node
+@@ -320,6 +325,7 @@ void irq_set_default_host(struct irq_domain *domain)
+       irq_default_domain = domain;
+ }
++EXPORT_SYMBOL_GPL(irq_set_default_host);
+ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
+                           irq_hw_number_t hwirq)
+@@ -378,6 +384,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
+       return virq;
+ }
++EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
+ /**
+  * irq_create_mapping() - Map a hardware interrupt into linux irq space
+@@ -617,6 +624,7 @@ unsigned int irq_radix_revmap_lookup(struct irq_domain *domain,
+        */
+       return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);
+ }
++EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup);
+ /**
+  * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping.
+@@ -641,6 +649,7 @@ void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq,
+               mutex_unlock(&revmap_trees_mutex);
+       }
+ }
++EXPORT_SYMBOL_GPL(irq_radix_revmap_insert);
+ /**
+  * irq_linear_revmap() - Find a linux irq from a hw irq number.
+@@ -674,6 +683,7 @@ unsigned int irq_linear_revmap(struct irq_domain *domain,
+       return revmap[hwirq];
+ }
++EXPORT_SYMBOL_GPL(irq_linear_revmap);
+ #ifdef CONFIG_IRQ_DOMAIN_DEBUG
+ static int virq_debug_show(struct seq_file *m, void *private)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch b/patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch
new file mode 100644 (file)
index 0000000..17332a5
--- /dev/null
@@ -0,0 +1,38 @@
+From 5cfad4570d46fe50c16ce73dcf3f2d6bf76f2b33 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Sat, 19 May 2012 15:11:43 +0900
+Subject: irqdomain: Make irq_domain_simple_map() static.
+
+Presently irq_domain_simple_map() isn't labelled as static, but there's
+no definition for it in the public irqdomain header either. At present
+all in-tree ->map users have meaningful work to do, and all others are
+using irq_domain_simple_ops directly. Make it static for now, as it can
+always be exported and added to the public API later.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit 5c5806e50b9fd4ca435acdf0eceddda64da9be5b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 01d4a0d..92e06442 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -758,8 +758,8 @@ static int __init irq_debugfs_init(void)
+ __initcall(irq_debugfs_init);
+ #endif /* CONFIG_IRQ_DOMAIN_DEBUG */
+-int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
+-                        irq_hw_number_t hwirq)
++static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
++                               irq_hw_number_t hwirq)
+ {
+       return 0;
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch b/patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch
new file mode 100644 (file)
index 0000000..ad6a35b
--- /dev/null
@@ -0,0 +1,35 @@
+From 4eb9577004521127daa39444ae35279e8f07eccd Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Sat, 19 May 2012 15:11:45 +0900
+Subject: irqdomain: Kill off duplicate definitions.
+
+Presently irqdomain.h has duplicate definitions for irq_find_host() and
+irq_set_default_host(), presumably from merge damage. Kill off the
+duplicates.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit cb5557bec9f14d05204a9014ae1b23aca8b04f1d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/irqdomain.h | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
+index a796dbf..5abb533 100644
+--- a/include/linux/irqdomain.h
++++ b/include/linux/irqdomain.h
+@@ -144,9 +144,6 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
+ extern void irq_domain_remove(struct irq_domain *host);
+-extern struct irq_domain *irq_find_host(struct device_node *node);
+-extern void irq_set_default_host(struct irq_domain *host);
+-
+ extern unsigned int irq_create_mapping(struct irq_domain *host,
+                                      irq_hw_number_t hwirq);
+ extern void irq_dispose_mapping(unsigned int virq);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch b/patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch
new file mode 100644 (file)
index 0000000..8211a87
--- /dev/null
@@ -0,0 +1,142 @@
+From acccf0bbf24e13673a3d5d76e49f389d736d4882 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Sat, 19 May 2012 15:11:47 +0900
+Subject: irqdomain: trivial pr_fmt conversion.
+
+Convert to pr_fmt before things start to get out of hand and some
+janitors start getting overly excited.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit 54a9058860f2b7ed8d2fe5bf7be19bb901866dc2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 32 +++++++++++++++++---------------
+ 1 file changed, 17 insertions(+), 15 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 92e06442..9a6e8a8 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -1,3 +1,5 @@
++#define pr_fmt(fmt)  "irq: " fmt
++
+ #include <linux/debugfs.h>
+ #include <linux/hardirq.h>
+ #include <linux/interrupt.h>
+@@ -67,7 +69,7 @@ static void irq_domain_add(struct irq_domain *domain)
+       mutex_lock(&irq_domain_mutex);
+       list_add(&domain->link, &irq_domain_list);
+       mutex_unlock(&irq_domain_mutex);
+-      pr_debug("irq: Allocated domain of type %d @0x%p\n",
++      pr_debug("Allocated domain of type %d @0x%p\n",
+                domain->revmap_type, domain);
+ }
+@@ -117,7 +119,7 @@ void irq_domain_remove(struct irq_domain *domain)
+       mutex_unlock(&irq_domain_mutex);
+-      pr_debug("irq: Removed domain of type %d @0x%p\n",
++      pr_debug("Removed domain of type %d @0x%p\n",
+                domain->revmap_type, domain);
+       irq_domain_free(domain);
+@@ -321,7 +323,7 @@ EXPORT_SYMBOL_GPL(irq_find_host);
+  */
+ void irq_set_default_host(struct irq_domain *domain)
+ {
+-      pr_debug("irq: Default domain set to @0x%p\n", domain);
++      pr_debug("Default domain set to @0x%p\n", domain);
+       irq_default_domain = domain;
+ }
+@@ -335,7 +337,7 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
+       irq_data->hwirq = hwirq;
+       irq_data->domain = domain;
+       if (domain->ops->map(domain, virq, hwirq)) {
+-              pr_debug("irq: -> mapping failed, freeing\n");
++              pr_debug("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
+               irq_data->domain = NULL;
+               irq_data->hwirq = 0;
+               return -1;
+@@ -366,7 +368,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
+       virq = irq_alloc_desc_from(1, 0);
+       if (!virq) {
+-              pr_debug("irq: create_direct virq allocation failed\n");
++              pr_debug("create_direct virq allocation failed\n");
+               return 0;
+       }
+       if (virq >= domain->revmap_data.nomap.max_irq) {
+@@ -375,7 +377,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
+               irq_free_desc(virq);
+               return 0;
+       }
+-      pr_debug("irq: create_direct obtained virq %d\n", virq);
++      pr_debug("create_direct obtained virq %d\n", virq);
+       if (irq_setup_virq(domain, virq, virq)) {
+               irq_free_desc(virq);
+@@ -402,23 +404,23 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+       unsigned int hint;
+       int virq;
+-      pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
++      pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
+       /* Look for default domain if nececssary */
+       if (domain == NULL)
+               domain = irq_default_domain;
+       if (domain == NULL) {
+-              printk(KERN_WARNING "irq_create_mapping called for"
+-                     " NULL domain, hwirq=%lx\n", hwirq);
++              pr_warning("irq_create_mapping called for"
++                         " NULL domain, hwirq=%lx\n", hwirq);
+               WARN_ON(1);
+               return 0;
+       }
+-      pr_debug("irq: -> using domain @%p\n", domain);
++      pr_debug("-> using domain @%p\n", domain);
+       /* Check if mapping already exists */
+       virq = irq_find_mapping(domain, hwirq);
+       if (virq) {
+-              pr_debug("irq: -> existing mapping on virq %d\n", virq);
++              pr_debug("-> existing mapping on virq %d\n", virq);
+               return virq;
+       }
+@@ -434,7 +436,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+       if (virq <= 0)
+               virq = irq_alloc_desc_from(1, 0);
+       if (virq <= 0) {
+-              pr_debug("irq: -> virq allocation failed\n");
++              pr_debug("-> virq allocation failed\n");
+               return 0;
+       }
+@@ -444,7 +446,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+               return 0;
+       }
+-      pr_debug("irq: irq %lu on domain %s mapped to virtual irq %u\n",
++      pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
+               hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);
+       return virq;
+@@ -473,8 +475,8 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
+               if (intsize > 0)
+                       return intspec[0];
+ #endif
+-              printk(KERN_WARNING "irq: no irq domain found for %s !\n",
+-                     controller->full_name);
++              pr_warning("no irq domain found for %s !\n",
++                         controller->full_name);
+               return 0;
+       }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch b/patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch
new file mode 100644 (file)
index 0000000..c58ba42
--- /dev/null
@@ -0,0 +1,29 @@
+From b1308eaacaa94b41421129c2cd44b69e4e83f2de Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Date: Sat, 19 May 2012 12:15:35 +0100
+Subject: irqdomain: Document size parameter of irq_domain_add_linear()
+
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit a87487e687ceafdc696b8cb1fb27e37cc463586b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 9a6e8a8..41c1564 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -217,6 +217,7 @@ EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
+ /**
+  * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
+  * @of_node: pointer to interrupt controller's device tree node.
++ * @size: Number of interrupts in the domain.
+  * @ops: map/unmap domain callbacks
+  * @host_data: Controller private data pointer
+  */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch b/patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch
new file mode 100644 (file)
index 0000000..24847e4
--- /dev/null
@@ -0,0 +1,232 @@
+From e572a45ad1741b29429e38cfd2be60e23e1ebc57 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Fri, 15 Jun 2012 11:50:25 -0600
+Subject: devicetree: add helper inline for retrieving a node's full name
+
+The pattern (np ? np->full_name : "<none>") is rather common in the
+kernel, but can also make for quite long lines.  This patch adds a new
+inline function, of_node_full_name() so that the test for a valid node
+pointer doesn't need to be open coded at all call sites.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Rob Herring <rob.herring@calxeda.com>
+(cherry picked from commit 74a7f08448adea6cb47cd9b260c98ff168117e92)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/microblaze/pci/pci-common.c       |  6 ++----
+ arch/powerpc/kernel/pci-common.c       |  6 ++----
+ arch/powerpc/kernel/vio.c              |  5 ++---
+ arch/powerpc/platforms/cell/iommu.c    |  3 +--
+ arch/powerpc/platforms/pseries/iommu.c |  2 +-
+ arch/sparc/kernel/of_device_64.c       |  2 +-
+ drivers/of/base.c                      |  2 +-
+ drivers/of/irq.c                       |  2 +-
+ include/linux/of.h                     | 10 ++++++++++
+ kernel/irq/irqdomain.c                 |  8 ++++----
+ 10 files changed, 25 insertions(+), 21 deletions(-)
+
+diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
+index d10403d..162b4e5 100644
+--- a/arch/microblaze/pci/pci-common.c
++++ b/arch/microblaze/pci/pci-common.c
+@@ -249,8 +249,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
+       } else {
+               pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+                        oirq.size, oirq.specifier[0], oirq.specifier[1],
+-                       oirq.controller ? oirq.controller->full_name :
+-                       "<default>");
++                       of_node_full_name(oirq.controller));
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+@@ -1492,8 +1491,7 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose)
+       struct pci_bus *bus;
+       struct device_node *node = hose->dn;
+-      pr_debug("PCI: Scanning PHB %s\n",
+-               node ? node->full_name : "<NO NAME>");
++      pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
+       pcibios_setup_phb_resources(hose, &resources);
+diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
+index 8e78e93..886c254 100644
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -248,8 +248,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
+       } else {
+               pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+                        oirq.size, oirq.specifier[0], oirq.specifier[1],
+-                       oirq.controller ? oirq.controller->full_name :
+-                       "<default>");
++                       of_node_full_name(oirq.controller));
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+@@ -1628,8 +1627,7 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
+       struct device_node *node = hose->dn;
+       int mode;
+-      pr_debug("PCI: Scanning PHB %s\n",
+-               node ? node->full_name : "<NO NAME>");
++      pr_debug("PCI: Scanning PHB %s\n", of_node_full_name(node));
+       /* Get some IO space for the new PHB */
+       pcibios_setup_phb_io_space(hose);
+diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
+index a3a9990..ea6081a 100644
+--- a/arch/powerpc/kernel/vio.c
++++ b/arch/powerpc/kernel/vio.c
+@@ -1193,8 +1193,7 @@ static void __devinit vio_dev_release(struct device *dev)
+       struct iommu_table *tbl = get_iommu_table_base(dev);
+       if (tbl)
+-              iommu_free_table(tbl, dev->of_node ?
+-                      dev->of_node->full_name : dev_name(dev));
++              iommu_free_table(tbl, of_node_full_name(dev->of_node));
+       of_node_put(dev->of_node);
+       kfree(to_vio_dev(dev));
+ }
+@@ -1330,7 +1329,7 @@ static ssize_t devspec_show(struct device *dev,
+ {
+       struct device_node *of_node = dev->of_node;
+-      return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
++      return sprintf(buf, "%s\n", of_node_full_name(of_node));
+ }
+ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
+index b9f509a..b673200 100644
+--- a/arch/powerpc/platforms/cell/iommu.c
++++ b/arch/powerpc/platforms/cell/iommu.c
+@@ -552,8 +552,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
+       iommu = cell_iommu_for_node(dev_to_node(dev));
+       if (iommu == NULL || list_empty(&iommu->windows)) {
+               printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n",
+-                     dev->of_node ? dev->of_node->full_name : "?",
+-                     dev_to_node(dev));
++                     of_node_full_name(dev->of_node), dev_to_node(dev));
+               return NULL;
+       }
+       window = list_entry(iommu->windows.next, struct iommu_window, list);
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index 2d311c0..6b58a39 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -1051,7 +1051,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
+       if (!pdn || !PCI_DN(pdn)) {
+               printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
+                      "no DMA window found for pci dev=%s dn=%s\n",
+-                               pci_name(dev), dn? dn->full_name : "<null>");
++                               pci_name(dev), of_node_full_name(dn));
+               return;
+       }
+       pr_debug("  parent is %s\n", pdn->full_name);
+diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c
+index 7a3be6f..7bbdc26 100644
+--- a/arch/sparc/kernel/of_device_64.c
++++ b/arch/sparc/kernel/of_device_64.c
+@@ -580,7 +580,7 @@ static unsigned int __init build_one_device_irq(struct platform_device *op,
+                               printk("%s: Apply [%s:%x] imap --> [%s:%x]\n",
+                                      op->dev.of_node->full_name,
+                                      pp->full_name, this_orig_irq,
+-                                     (iret ? iret->full_name : "NULL"), irq);
++                                     of_node_full_name(iret), irq);
+                       if (!iret)
+                               break;
+diff --git a/drivers/of/base.c b/drivers/of/base.c
+index 5806449..6271c2e 100644
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -1173,7 +1173,7 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+       ap->stem[stem_len] = 0;
+       list_add_tail(&ap->link, &aliases_lookup);
+       pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+-               ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
++               ap->alias, ap->stem, ap->id, of_node_full_name(np));
+ }
+ /**
+diff --git a/drivers/of/irq.c b/drivers/of/irq.c
+index 9cf0060..ff8ab7b 100644
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -255,7 +255,7 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
+       skiplevel:
+               /* Iterate again with new parent */
+-              pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>");
++              pr_debug(" -> new parent: %s\n", of_node_full_name(newpar));
+               of_node_put(ipar);
+               ipar = newpar;
+               newpar = NULL;
+diff --git a/include/linux/of.h b/include/linux/of.h
+index fa7fb1d..284d117 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -163,6 +163,11 @@ static inline int of_node_to_nid(struct device_node *np) { return -1; }
+ #define of_node_to_nid of_node_to_nid
+ #endif
++static inline const char* of_node_full_name(struct device_node *np)
++{
++      return np ? np->full_name : "<no-node>";
++}
++
+ extern struct device_node *of_find_node_by_name(struct device_node *from,
+       const char *name);
+ #define for_each_node_by_name(dn, name) \
+@@ -261,6 +266,11 @@ extern void of_detach_node(struct device_node *);
+ #define of_match_ptr(_ptr)    (_ptr)
+ #else /* CONFIG_OF */
++static inline const char* of_node_full_name(struct device_node *np)
++{
++      return "<no-node>";
++}
++
+ static inline bool of_have_populated_dt(void)
+ {
+       return false;
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 41c1564..38c5eb8 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -448,7 +448,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+       }
+       pr_debug("irq %lu on domain %s mapped to virtual irq %u\n",
+-              hwirq, domain->of_node ? domain->of_node->full_name : "null", virq);
++              hwirq, of_node_full_name(domain->of_node), virq);
+       return virq;
+ }
+@@ -477,7 +477,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
+                       return intspec[0];
+ #endif
+               pr_warning("no irq domain found for %s !\n",
+-                         controller->full_name);
++                         of_node_full_name(controller));
+               return 0;
+       }
+@@ -725,8 +725,8 @@ static int virq_debug_show(struct seq_file *m, void *private)
+                       data = irq_desc_get_chip_data(desc);
+                       seq_printf(m, data ? "0x%p  " : "  %p  ", data);
+-                      if (desc->irq_data.domain && desc->irq_data.domain->of_node)
+-                              p = desc->irq_data.domain->of_node->full_name;
++                      if (desc->irq_data.domain)
++                              p = of_node_full_name(desc->irq_data.domain->of_node);
+                       else
+                               p = none;
+                       seq_printf(m, "%s\n", p);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch b/patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch
new file mode 100644 (file)
index 0000000..099c368
--- /dev/null
@@ -0,0 +1,132 @@
+From 249521995c6f0647ab54b64f89103ba3389edfea Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Sun, 3 Jun 2012 22:04:34 -0700
+Subject: irqdomain: Simple NUMA awareness.
+
+While common irqdesc allocation is node aware, the irqdomain code is not.
+
+Presently we observe a number of regressions/inconsistencies on
+NUMA-capable platforms:
+
+- Platforms using irqdomains with legacy mappings, where the
+  irq_descs are allocated node-local and the irqdomain data
+  structure is not.
+
+- Drivers implementing irqdomains will lose node locality
+  regardless of the underlying struct device's node id.
+
+This plugs in NUMA node id proliferation across the various allocation
+callsites by way of_node_to_nid() node lookup. While of_node_to_nid()
+does the right thing for OF-capable platforms it doesn't presently handle
+the non-DT case. This is trivially dealt with by simply wraping in to
+numa_node_id() unconditionally.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit 5ca4db61e859526b2dbee3bcea3626d3de49a0b2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/of.h     | 15 ++++++++++-----
+ kernel/irq/irqdomain.c | 13 ++++++++-----
+ 2 files changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/include/linux/of.h b/include/linux/of.h
+index 284d117..e24c5cc 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -21,6 +21,7 @@
+ #include <linux/kref.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/spinlock.h>
++#include <linux/topology.h>
+ #include <asm/byteorder.h>
+ #include <asm/errno.h>
+@@ -158,11 +159,6 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
+ #define OF_BAD_ADDR   ((u64)-1)
+-#ifndef of_node_to_nid
+-static inline int of_node_to_nid(struct device_node *np) { return -1; }
+-#define of_node_to_nid of_node_to_nid
+-#endif
+-
+ static inline const char* of_node_full_name(struct device_node *np)
+ {
+       return np ? np->full_name : "<no-node>";
+@@ -361,6 +357,15 @@ static inline int of_machine_is_compatible(const char *compat)
+ #define of_match_node(_matches, _node)        NULL
+ #endif /* CONFIG_OF */
++#ifndef of_node_to_nid
++static inline int of_node_to_nid(struct device_node *np)
++{
++      return numa_node_id();
++}
++
++#define of_node_to_nid of_node_to_nid
++#endif
++
+ /**
+  * of_property_read_bool - Findfrom a property
+  * @np:               device node from which the property value is to be read.
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 38c5eb8..79ae0eb 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -10,6 +10,7 @@
+ #include <linux/mutex.h>
+ #include <linux/of.h>
+ #include <linux/of_address.h>
++#include <linux/topology.h>
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+ #include <linux/smp.h>
+@@ -45,7 +46,8 @@ static struct irq_domain *irq_domain_alloc(struct device_node *of_node,
+ {
+       struct irq_domain *domain;
+-      domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++      domain = kzalloc_node(sizeof(*domain), GFP_KERNEL,
++                            of_node_to_nid(of_node));
+       if (WARN_ON(!domain))
+               return NULL;
+@@ -229,7 +231,8 @@ struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
+       struct irq_domain *domain;
+       unsigned int *revmap;
+-      revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL);
++      revmap = kzalloc_node(sizeof(*revmap) * size, GFP_KERNEL,
++                            of_node_to_nid(of_node));
+       if (WARN_ON(!revmap))
+               return NULL;
+@@ -367,7 +370,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
+       BUG_ON(domain == NULL);
+       WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP);
+-      virq = irq_alloc_desc_from(1, 0);
++      virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
+       if (!virq) {
+               pr_debug("create_direct virq allocation failed\n");
+               return 0;
+@@ -433,9 +436,9 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+       hint = hwirq % nr_irqs;
+       if (hint == 0)
+               hint++;
+-      virq = irq_alloc_desc_from(hint, 0);
++      virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node));
+       if (virq <= 0)
+-              virq = irq_alloc_desc_from(1, 0);
++              virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
+       if (virq <= 0) {
+               pr_debug("-> virq allocation failed\n");
+               return 0;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch b/patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch
new file mode 100644 (file)
index 0000000..4e41912
--- /dev/null
@@ -0,0 +1,39 @@
+From e023d517b8a6bdbb4083914ec6519fa6486d437d Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 3 Jun 2012 22:04:35 -0700
+Subject: irqdomain: Remove unnecessary test for IRQ_DOMAIN_MAP_LEGACY
+
+Where irq_domain_associate() is called in irq_create_mapping, there is
+no need to test for IRQ_DOMAIN_MAP_LEGACY because it is already tested
+for earlier in the routine.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>
+
+(cherry picked from commit 732557047128e5c200c3590efba39f10ac46bcb2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 79ae0eb..b1f774c 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -445,8 +445,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+       }
+       if (irq_setup_virq(domain, virq, hwirq)) {
+-              if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY)
+-                      irq_free_desc(virq);
++              irq_free_desc(virq);
+               return 0;
+       }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch b/patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch
new file mode 100644 (file)
index 0000000..6cb797b
--- /dev/null
@@ -0,0 +1,69 @@
+From 421754810bdf0283c6f75bffdc96a0795bdf340d Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 3 Jun 2012 22:04:39 -0700
+Subject: irqdomain: Make ops->map hook optional
+
+There isn't a really compelling reason to force ->map to be populated,
+so allow it to be left unset.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>
+(cherry picked from commit aed98048bd1c83469d96932c1901e867d9ba519a)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index b1f774c..d3968e9 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -205,7 +205,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
+                * one can then use irq_create_mapping() to
+                * explicitly change them
+                */
+-              ops->map(domain, irq, hwirq);
++              if (ops->map)
++                      ops->map(domain, irq, hwirq);
+               /* Clear norequest flags */
+               irq_clear_status_flags(irq, IRQ_NOREQUEST);
+@@ -340,8 +341,8 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
+       irq_data->hwirq = hwirq;
+       irq_data->domain = domain;
+-      if (domain->ops->map(domain, virq, hwirq)) {
+-              pr_debug("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
++      if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
++              pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
+               irq_data->domain = NULL;
+               irq_data->hwirq = 0;
+               return -1;
+@@ -763,12 +764,6 @@ static int __init irq_debugfs_init(void)
+ __initcall(irq_debugfs_init);
+ #endif /* CONFIG_IRQ_DOMAIN_DEBUG */
+-static int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
+-                               irq_hw_number_t hwirq)
+-{
+-      return 0;
+-}
+-
+ /**
+  * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings
+  *
+@@ -831,7 +826,6 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d,
+ EXPORT_SYMBOL_GPL(irq_domain_xlate_onetwocell);
+ const struct irq_domain_ops irq_domain_simple_ops = {
+-      .map = irq_domain_simple_map,
+       .xlate = irq_domain_xlate_onetwocell,
+ };
+ EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch b/patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch
new file mode 100644 (file)
index 0000000..e395c3d
--- /dev/null
@@ -0,0 +1,109 @@
+From c9055637ff0ca4029e5bf18053b65172b27f63b0 Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Date: Thu, 5 Jul 2012 12:19:19 +0100
+Subject: irq_domain: Standardise legacy/linear domain selection
+
+A large proportion of interrupt controllers that support legacy mappings
+do so because non-DT systems need to use fixed IRQ numbers when registering
+devices via buses but can otherwise use a linear mapping. The interrupt
+controller itself typically is not affected by the mapping used and best
+practice is to use a linear mapping where possible so drivers frequently
+select at runtime depending on if a legacy range has been allocated to
+them.
+
+Standardise this behaviour by providing irq_domain_register_simple() which
+will allocate a linear mapping unless a positive first_irq is provided in
+which case it will fall back to a legacy mapping. This helps make best
+practice for irq_domain adoption clearer.
+
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit 781d0f46d81e2c26c70649903b503bcfe817efc8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ Documentation/IRQ-domain.txt |  5 +++++
+ include/linux/irqdomain.h    |  5 +++++
+ kernel/irq/irqdomain.c       | 30 ++++++++++++++++++++++++++++++
+ 3 files changed, 40 insertions(+)
+
+diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt
+index 27dcaab..1401cec 100644
+--- a/Documentation/IRQ-domain.txt
++++ b/Documentation/IRQ-domain.txt
+@@ -93,6 +93,7 @@ Linux IRQ number into the hardware.
+ Most drivers cannot use this mapping.
+ ==== Legacy ====
++irq_domain_add_simple()
+ irq_domain_add_legacy()
+ irq_domain_add_legacy_isa()
+@@ -115,3 +116,7 @@ The legacy map should only be used if fixed IRQ mappings must be
+ supported.  For example, ISA controllers would use the legacy map for
+ mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ
+ numbers.
++
++Most users of legacy mappings should use irq_domain_add_simple() which
++will use a legacy domain only if an IRQ range is supplied by the
++system and will otherwise use a linear domain mapping.
+diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
+index 5abb533..17b60be 100644
+--- a/include/linux/irqdomain.h
++++ b/include/linux/irqdomain.h
+@@ -112,6 +112,11 @@ struct irq_domain {
+ };
+ #ifdef CONFIG_IRQ_DOMAIN
++struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
++                                       unsigned int size,
++                                       unsigned int first_irq,
++                                       const struct irq_domain_ops *ops,
++                                       void *host_data);
+ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
+                                        unsigned int size,
+                                        unsigned int first_irq,
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index d3968e9..0c51958 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -140,6 +140,36 @@ static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain,
+ }
+ /**
++ * irq_domain_add_simple() - Allocate and register a simple irq_domain.
++ * @of_node: pointer to interrupt controller's device tree node.
++ * @size: total number of irqs in mapping
++ * @first_irq: first number of irq block assigned to the domain
++ * @ops: map/unmap domain callbacks
++ * @host_data: Controller private data pointer
++ *
++ * Allocates a legacy irq_domain if irq_base is positive or a linear
++ * domain otherwise.
++ *
++ * This is intended to implement the expected behaviour for most
++ * interrupt controllers which is that a linear mapping should
++ * normally be used unless the system requires a legacy mapping in
++ * order to support supplying interrupt numbers during non-DT
++ * registration of devices.
++ */
++struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
++                                       unsigned int size,
++                                       unsigned int first_irq,
++                                       const struct irq_domain_ops *ops,
++                                       void *host_data)
++{
++      if (first_irq > 0)
++              return irq_domain_add_legacy(of_node, size, first_irq, 0,
++                                           ops, host_data);
++      else
++              return irq_domain_add_linear(of_node, size, ops, host_data);
++}
++
++/**
+  * irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain.
+  * @of_node: pointer to interrupt controller's device tree node.
+  * @size: total number of irqs in legacy mapping
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch b/patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch
new file mode 100644 (file)
index 0000000..fa0ed49
--- /dev/null
@@ -0,0 +1,32 @@
+From 709c8d22171cc90cc30e4528312bcc0e31b870b2 Mon Sep 17 00:00:00 2001
+From: Dong Aisheng <dong.aisheng@linaro.org>
+Date: Wed, 20 Jun 2012 17:00:30 +0800
+Subject: irq_domain: correct a minor wrong comment for linear revmap
+
+The revmap type should be linear for irq_domain_add_linear function.
+
+Signed-off-by: Dong Aisheng <dong.aisheng@linaro.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit 22076c7712be29a602de45b1c573f31adbd428a9)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 0c51958..622fdf4 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -248,7 +248,7 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
+ EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
+ /**
+- * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain.
++ * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain.
+  * @of_node: pointer to interrupt controller's device tree node.
+  * @size: Number of interrupts in the domain.
+  * @ops: map/unmap domain callbacks
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch b/patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch
new file mode 100644 (file)
index 0000000..639979c
--- /dev/null
@@ -0,0 +1,63 @@
+From 077e92f0d6cc5991a052116eb8d66539dd49a995 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 3 Jun 2012 22:04:36 -0700
+Subject: irqdomain: Always update revmap when setting up a virq
+
+At irq_setup_virq() time all of the data needed to update the reverse
+map is available, but the current code ignores it and relies upon the
+slow path to insert revmap records.  This patch adds revmap updating
+to the setup path so the slow path will no longer be necessary.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>
+(cherry picked from commit 2a71a1a9da40dfbd5b23d4312aa1641385581f4a)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/powerpc/sysdev/xics/xics-common.c |  3 ---
+ kernel/irq/irqdomain.c                 | 12 ++++++++++++
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
+index cd1d18d..9049d9f 100644
+--- a/arch/powerpc/sysdev/xics/xics-common.c
++++ b/arch/powerpc/sysdev/xics/xics-common.c
+@@ -329,9 +329,6 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq,
+       pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
+-      /* Insert the interrupt mapping into the radix tree for fast lookup */
+-      irq_radix_revmap_insert(xics_host, virq, hw);
+-
+       /* They aren't all level sensitive but we just don't really know */
+       irq_set_status_flags(virq, IRQ_LEVEL);
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 622fdf4..648177c 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -378,6 +378,18 @@ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
+               return -1;
+       }
++      switch (domain->revmap_type) {
++      case IRQ_DOMAIN_MAP_LINEAR:
++              if (hwirq < domain->revmap_data.linear.size)
++                      domain->revmap_data.linear.revmap[hwirq] = virq;
++              break;
++      case IRQ_DOMAIN_MAP_TREE:
++              mutex_lock(&revmap_trees_mutex);
++              irq_radix_revmap_insert(domain, virq, hwirq);
++              mutex_unlock(&revmap_trees_mutex);
++              break;
++      }
++
+       irq_clear_status_flags(virq, IRQ_NOREQUEST);
+       return 0;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch b/patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch
new file mode 100644 (file)
index 0000000..e3a482d
--- /dev/null
@@ -0,0 +1,125 @@
+From d3a8f8cf4ad2e5416f53db8963f3ff153feec161 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 3 Jun 2012 22:04:35 -0700
+Subject: irqdomain: Split disassociating code into separate function
+
+This patch moves the irq disassociation code out into a separate
+function in preparation to extend irq_setup_virq to handle multiple
+irqs and rename it for use by interrupt controller drivers.  The new
+function will be used by irq_setup_virq() in its error path.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>
+(cherry picked from commit 913af2070731bfc1bd39bb35c5cd2fd66f5eff12)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 75 +++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 47 insertions(+), 28 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 648177c..091732c 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -364,6 +364,52 @@ void irq_set_default_host(struct irq_domain *domain)
+ }
+ EXPORT_SYMBOL_GPL(irq_set_default_host);
++static void irq_domain_disassociate_many(struct irq_domain *domain,
++                                       unsigned int irq_base, int count)
++{
++      /*
++       * disassociate in reverse order;
++       * not strictly necessary, but nice for unwinding
++       */
++      while (count--) {
++              int irq = irq_base + count;
++              struct irq_data *irq_data = irq_get_irq_data(irq);
++              irq_hw_number_t hwirq = irq_data->hwirq;
++
++              if (WARN_ON(!irq_data || irq_data->domain != domain))
++                      continue;
++
++              irq_set_status_flags(irq, IRQ_NOREQUEST);
++
++              /* remove chip and handler */
++              irq_set_chip_and_handler(irq, NULL, NULL);
++
++              /* Make sure it's completed */
++              synchronize_irq(irq);
++
++              /* Tell the PIC about it */
++              if (domain->ops->unmap)
++                      domain->ops->unmap(domain, irq);
++              smp_mb();
++
++              irq_data->domain = NULL;
++              irq_data->hwirq = 0;
++
++              /* Clear reverse map */
++              switch(domain->revmap_type) {
++              case IRQ_DOMAIN_MAP_LINEAR:
++                      if (hwirq < domain->revmap_data.linear.size)
++                              domain->revmap_data.linear.revmap[hwirq] = 0;
++                      break;
++              case IRQ_DOMAIN_MAP_TREE:
++                      mutex_lock(&revmap_trees_mutex);
++                      radix_tree_delete(&domain->revmap_data.tree, hwirq);
++                      mutex_unlock(&revmap_trees_mutex);
++                      break;
++              }
++      }
++}
++
+ static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
+                           irq_hw_number_t hwirq)
+ {
+@@ -556,7 +602,6 @@ void irq_dispose_mapping(unsigned int virq)
+ {
+       struct irq_data *irq_data = irq_get_irq_data(virq);
+       struct irq_domain *domain;
+-      irq_hw_number_t hwirq;
+       if (!virq || !irq_data)
+               return;
+@@ -569,33 +614,7 @@ void irq_dispose_mapping(unsigned int virq)
+       if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
+               return;
+-      irq_set_status_flags(virq, IRQ_NOREQUEST);
+-
+-      /* remove chip and handler */
+-      irq_set_chip_and_handler(virq, NULL, NULL);
+-
+-      /* Make sure it's completed */
+-      synchronize_irq(virq);
+-
+-      /* Tell the PIC about it */
+-      if (domain->ops->unmap)
+-              domain->ops->unmap(domain, virq);
+-      smp_mb();
+-
+-      /* Clear reverse map */
+-      hwirq = irq_data->hwirq;
+-      switch(domain->revmap_type) {
+-      case IRQ_DOMAIN_MAP_LINEAR:
+-              if (hwirq < domain->revmap_data.linear.size)
+-                      domain->revmap_data.linear.revmap[hwirq] = 0;
+-              break;
+-      case IRQ_DOMAIN_MAP_TREE:
+-              mutex_lock(&revmap_trees_mutex);
+-              radix_tree_delete(&domain->revmap_data.tree, hwirq);
+-              mutex_unlock(&revmap_trees_mutex);
+-              break;
+-      }
+-
++      irq_domain_disassociate_many(domain, virq, 1);
+       irq_free_desc(virq);
+ }
+ EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch b/patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch
new file mode 100644 (file)
index 0000000..f9f8697
--- /dev/null
@@ -0,0 +1,239 @@
+From 5f4e2248df9a3128a3e81755f87b12dd211ead30 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 17 Jun 2012 16:17:04 -0600
+Subject: irqdomain: Support for static IRQ mapping and association.
+
+This adds a new strict mapping API for supporting creation of linux IRQs
+at existing positions within the domain. The new routines are as follows:
+
+For dynamic allocation and insertion to specified ranges:
+
+       - irq_create_identity_mapping()
+       - irq_create_strict_mappings()
+
+These will allocate and associate a range of linux IRQs at the specified
+location. This can be used by controllers that have their own static linux IRQ
+definitions to map a hwirq range to, as well as for platforms that wish to
+establish 1:1 identity mapping between linux and hwirq space.
+
+For insertion to specified ranges by platforms that do their own irq_desc
+management:
+
+       - irq_domain_associate()
+       - irq_domain_associate_many()
+
+These in turn call back in to the domain's ->map() routine, for further
+processing by the platform. Disassociation of IRQs get handled through
+irq_dispose_mapping() as normal.
+
+With these in place it should be possible to begin migration of legacy IRQ
+domains to linear ones, without requiring special handling for static vs
+dynamic IRQ definitions in DT vs non-DT paths. This also makes it possible
+for domains with static mappings to adopt whichever tree model best fits
+their needs, rather than simply restricting them to linear revmaps.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+[grant.likely: Reorganized irq_domain_associate{,_many} to have all logic in one place]
+[grant.likely: Add error checking for unallocated irq_descs at associate time]
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>(cherry picked from commit 98aa468e045a0091a7c34d9f5205a629634fabf4)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/irqdomain.h |  19 ++++++++
+ kernel/irq/irqdomain.c    | 113 ++++++++++++++++++++++++++++++++++++----------
+ 2 files changed, 107 insertions(+), 25 deletions(-)
+
+diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
+index 17b60be..eab8a0e 100644
+--- a/include/linux/irqdomain.h
++++ b/include/linux/irqdomain.h
+@@ -149,12 +149,31 @@ static inline struct irq_domain *irq_domain_add_legacy_isa(
+ extern void irq_domain_remove(struct irq_domain *host);
++extern int irq_domain_associate_many(struct irq_domain *domain,
++                                   unsigned int irq_base,
++                                   irq_hw_number_t hwirq_base, int count);
++static inline int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
++                                      irq_hw_number_t hwirq)
++{
++      return irq_domain_associate_many(domain, irq, hwirq, 1);
++}
++
+ extern unsigned int irq_create_mapping(struct irq_domain *host,
+                                      irq_hw_number_t hwirq);
+ extern void irq_dispose_mapping(unsigned int virq);
+ extern unsigned int irq_find_mapping(struct irq_domain *host,
+                                    irq_hw_number_t hwirq);
+ extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
++extern int irq_create_strict_mappings(struct irq_domain *domain,
++                                    unsigned int irq_base,
++                                    irq_hw_number_t hwirq_base, int count);
++
++static inline int irq_create_identity_mapping(struct irq_domain *host,
++                                            irq_hw_number_t hwirq)
++{
++      return irq_create_strict_mappings(host, hwirq, hwirq, 1);
++}
++
+ extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq,
+                                   irq_hw_number_t hwirq);
+ extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host,
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 091732c..a07d924 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -410,36 +410,61 @@ static void irq_domain_disassociate_many(struct irq_domain *domain,
+       }
+ }
+-static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
+-                          irq_hw_number_t hwirq)
++int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
++                            irq_hw_number_t hwirq_base, int count)
+ {
+-      struct irq_data *irq_data = irq_get_irq_data(virq);
++      unsigned int virq = irq_base;
++      irq_hw_number_t hwirq = hwirq_base;
++      int i;
+-      irq_data->hwirq = hwirq;
+-      irq_data->domain = domain;
+-      if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
+-              pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
+-              irq_data->domain = NULL;
+-              irq_data->hwirq = 0;
+-              return -1;
+-      }
++      pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
++              of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
+-      switch (domain->revmap_type) {
+-      case IRQ_DOMAIN_MAP_LINEAR:
+-              if (hwirq < domain->revmap_data.linear.size)
+-                      domain->revmap_data.linear.revmap[hwirq] = virq;
+-              break;
+-      case IRQ_DOMAIN_MAP_TREE:
+-              mutex_lock(&revmap_trees_mutex);
+-              irq_radix_revmap_insert(domain, virq, hwirq);
+-              mutex_unlock(&revmap_trees_mutex);
+-              break;
+-      }
++      for (i = 0; i < count; i++) {
++              struct irq_data *irq_data = irq_get_irq_data(virq + i);
++
++              if (WARN(!irq_data, "error: irq_desc not allocated; "
++                       "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
++                      return -EINVAL;
++              if (WARN(irq_data->domain, "error: irq_desc already associated; "
++                       "irq=%i hwirq=0x%x\n", virq + i, (int)hwirq + i))
++                      return -EINVAL;
++      };
++
++      for (i = 0; i < count; i++, virq++, hwirq++) {
++              struct irq_data *irq_data = irq_get_irq_data(virq);
++
++              irq_data->hwirq = hwirq;
++              irq_data->domain = domain;
++              if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
++                      pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
++                      irq_data->domain = NULL;
++                      irq_data->hwirq = 0;
++                      goto err_unmap;
++              }
++
++              switch (domain->revmap_type) {
++              case IRQ_DOMAIN_MAP_LINEAR:
++                      if (hwirq < domain->revmap_data.linear.size)
++                              domain->revmap_data.linear.revmap[hwirq] = virq;
++                      break;
++              case IRQ_DOMAIN_MAP_TREE:
++                      mutex_lock(&revmap_trees_mutex);
++                      irq_radix_revmap_insert(domain, virq, hwirq);
++                      mutex_unlock(&revmap_trees_mutex);
++                      break;
++              }
+-      irq_clear_status_flags(virq, IRQ_NOREQUEST);
++              irq_clear_status_flags(virq, IRQ_NOREQUEST);
++      }
+       return 0;
++
++ err_unmap:
++      irq_domain_disassociate_many(domain, irq_base, i);
++      return -EINVAL;
+ }
++EXPORT_SYMBOL_GPL(irq_domain_associate_many);
+ /**
+  * irq_create_direct_mapping() - Allocate an irq for direct mapping
+@@ -472,7 +497,7 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
+       }
+       pr_debug("create_direct obtained virq %d\n", virq);
+-      if (irq_setup_virq(domain, virq, virq)) {
++      if (irq_domain_associate(domain, virq, virq)) {
+               irq_free_desc(virq);
+               return 0;
+       }
+@@ -533,7 +558,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+               return 0;
+       }
+-      if (irq_setup_virq(domain, virq, hwirq)) {
++      if (irq_domain_associate(domain, virq, hwirq)) {
+               irq_free_desc(virq);
+               return 0;
+       }
+@@ -545,6 +570,44 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
+ }
+ EXPORT_SYMBOL_GPL(irq_create_mapping);
++/**
++ * irq_create_strict_mappings() - Map a range of hw irqs to fixed linux irqs
++ * @domain: domain owning the interrupt range
++ * @irq_base: beginning of linux IRQ range
++ * @hwirq_base: beginning of hardware IRQ range
++ * @count: Number of interrupts to map
++ *
++ * This routine is used for allocating and mapping a range of hardware
++ * irqs to linux irqs where the linux irq numbers are at pre-defined
++ * locations. For use by controllers that already have static mappings
++ * to insert in to the domain.
++ *
++ * Non-linear users can use irq_create_identity_mapping() for IRQ-at-a-time
++ * domain insertion.
++ *
++ * 0 is returned upon success, while any failure to establish a static
++ * mapping is treated as an error.
++ */
++int irq_create_strict_mappings(struct irq_domain *domain, unsigned int irq_base,
++                             irq_hw_number_t hwirq_base, int count)
++{
++      int ret;
++
++      ret = irq_alloc_descs(irq_base, irq_base, count,
++                            of_node_to_nid(domain->of_node));
++      if (unlikely(ret < 0))
++              return ret;
++
++      ret = irq_domain_associate_many(domain, irq_base, hwirq_base, count);
++      if (unlikely(ret < 0)) {
++              irq_free_descs(irq_base, count);
++              return ret;
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
++
+ unsigned int irq_create_of_mapping(struct device_node *controller,
+                                  const u32 *intspec, unsigned int intsize)
+ {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch b/patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch
new file mode 100644 (file)
index 0000000..e4d1ae3
--- /dev/null
@@ -0,0 +1,146 @@
+From 5b89c7072aeb8b3f6f16a675fafb342c2dd3e1b6 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 3 Jun 2012 22:04:37 -0700
+Subject: irqdomain: Eliminate dedicated radix lookup functions
+
+In preparation to remove the slow revmap path, eliminate the public
+radix revmap lookup functions.  This simplifies the code and makes the
+slowpath removal patch a lot simpler.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>
+(cherry picked from commit d6b0d1f7058f7cf818138cd7fd116dca3f3576d9)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/powerpc/sysdev/xics/icp-hv.c     |  2 +-
+ arch/powerpc/sysdev/xics/icp-native.c |  2 +-
+ include/linux/irqdomain.h             |  4 ---
+ kernel/irq/irqdomain.c                | 60 +----------------------------------
+ 4 files changed, 3 insertions(+), 65 deletions(-)
+
+diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
+index 762c5ca..df0fc58 100644
+--- a/arch/powerpc/sysdev/xics/icp-hv.c
++++ b/arch/powerpc/sysdev/xics/icp-hv.c
+@@ -115,7 +115,7 @@ static unsigned int icp_hv_get_irq(void)
+       if (vec == XICS_IRQ_SPURIOUS)
+               return NO_IRQ;
+-      irq = irq_radix_revmap_lookup(xics_host, vec);
++      irq = irq_find_mapping(xics_host, vec);
+       if (likely(irq != NO_IRQ)) {
+               xics_push_cppr(vec);
+               return irq;
+diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
+index 4c79b6f..48861d3 100644
+--- a/arch/powerpc/sysdev/xics/icp-native.c
++++ b/arch/powerpc/sysdev/xics/icp-native.c
+@@ -119,7 +119,7 @@ static unsigned int icp_native_get_irq(void)
+       if (vec == XICS_IRQ_SPURIOUS)
+               return NO_IRQ;
+-      irq = irq_radix_revmap_lookup(xics_host, vec);
++      irq = irq_find_mapping(xics_host, vec);
+       if (likely(irq != NO_IRQ)) {
+               xics_push_cppr(vec);
+               return irq;
+diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
+index eab8a0e..0d5b17b 100644
+--- a/include/linux/irqdomain.h
++++ b/include/linux/irqdomain.h
+@@ -174,10 +174,6 @@ static inline int irq_create_identity_mapping(struct irq_domain *host,
+       return irq_create_strict_mappings(host, hwirq, hwirq, 1);
+ }
+-extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq,
+-                                  irq_hw_number_t hwirq);
+-extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host,
+-                                          irq_hw_number_t hwirq);
+ extern unsigned int irq_linear_revmap(struct irq_domain *host,
+                                     irq_hw_number_t hwirq);
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index a07d924..f540bb1 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -450,7 +450,7 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
+                       break;
+               case IRQ_DOMAIN_MAP_TREE:
+                       mutex_lock(&revmap_trees_mutex);
+-                      irq_radix_revmap_insert(domain, virq, hwirq);
++                      radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data);
+                       mutex_unlock(&revmap_trees_mutex);
+                       break;
+               }
+@@ -724,64 +724,6 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
+ EXPORT_SYMBOL_GPL(irq_find_mapping);
+ /**
+- * irq_radix_revmap_lookup() - Find a linux irq from a hw irq number.
+- * @domain: domain owning this hardware interrupt
+- * @hwirq: hardware irq number in that domain space
+- *
+- * This is a fast path, for use by irq controller code that uses radix tree
+- * revmaps
+- */
+-unsigned int irq_radix_revmap_lookup(struct irq_domain *domain,
+-                                   irq_hw_number_t hwirq)
+-{
+-      struct irq_data *irq_data;
+-
+-      if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_TREE))
+-              return irq_find_mapping(domain, hwirq);
+-
+-      /*
+-       * Freeing an irq can delete nodes along the path to
+-       * do the lookup via call_rcu.
+-       */
+-      rcu_read_lock();
+-      irq_data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
+-      rcu_read_unlock();
+-
+-      /*
+-       * If found in radix tree, then fine.
+-       * Else fallback to linear lookup - this should not happen in practice
+-       * as it means that we failed to insert the node in the radix tree.
+-       */
+-      return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);
+-}
+-EXPORT_SYMBOL_GPL(irq_radix_revmap_lookup);
+-
+-/**
+- * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping.
+- * @domain: domain owning this hardware interrupt
+- * @virq: linux irq number
+- * @hwirq: hardware irq number in that domain space
+- *
+- * This is for use by irq controllers that use a radix tree reverse
+- * mapping for fast lookup.
+- */
+-void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq,
+-                           irq_hw_number_t hwirq)
+-{
+-      struct irq_data *irq_data = irq_get_irq_data(virq);
+-
+-      if (WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_TREE))
+-              return;
+-
+-      if (virq) {
+-              mutex_lock(&revmap_trees_mutex);
+-              radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data);
+-              mutex_unlock(&revmap_trees_mutex);
+-      }
+-}
+-EXPORT_SYMBOL_GPL(irq_radix_revmap_insert);
+-
+-/**
+  * irq_linear_revmap() - Find a linux irq from a hw irq number.
+  * @domain: domain owning this hardware interrupt
+  * @hwirq: hardware irq number in that domain space
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch b/patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch
new file mode 100644 (file)
index 0000000..6aa1f06
--- /dev/null
@@ -0,0 +1,39 @@
+From 669724cfa76709814c46bac8ba50f1a52d15ffd7 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 3 Jun 2012 22:04:38 -0700
+Subject: irqdomain: Fix irq_create_direct_mapping() to test irq_domain type.
+
+irq_create_direct_mapping can only be used with the NOMAP type.  Make
+the function test to ensure it is passed the correct type of
+irq_domain.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Rob Herring <rob.herring@calxeda.com>
+(cherry picked from commit 9844a5524ec532aee826c35e3031637c7fc8287b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index f540bb1..c0e638b 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -481,8 +481,8 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
+       if (domain == NULL)
+               domain = irq_default_domain;
+-      BUG_ON(domain == NULL);
+-      WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP);
++      if (WARN_ON(!domain || domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP))
++              return 0;
+       virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
+       if (!virq) {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch b/patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch
new file mode 100644 (file)
index 0000000..d416e80
--- /dev/null
@@ -0,0 +1,142 @@
+From 026250e1fad07349b34213260492cecee3b32eae Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Sun, 3 Jun 2012 22:04:39 -0700
+Subject: irqdomain: eliminate slow-path revmap lookups
+
+With the current state of irq_domain, the reverse map is always updated
+when new IRQs get mapped.  This means that the irq_find_mapping() function
+can be simplified to execute the revmap lookup functions unconditionally
+
+This patch adds lookup functions for the revmaps that don't yet have one
+and removes the slow path lookup code path.
+
+v8: Broke out unrelated changes into separate patches.  Rebased on Paul's irq
+    association patches.
+v7: Rebased to irqdomain/next for v3.4 and applied before the removal of 'hint'
+v6: Remove the slow path entirely.  The only place where the slow path
+    could get called is for a linear mapping if the hwirq number is larger
+    than the linear revmap size.  There shouldn't be any interrupt
+    controllers that do that.
+v5: rewrite to not use a ->revmap() callback.  It is simpler, smaller,
+    safer and faster to open code each of the revmap lookups directly into
+    irq_find_mapping() via a switch statement.
+v4: Fix build failure on incorrect variable reference.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Milton Miller <miltonm@bga.com>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: Rob Herring <rob.herring@calxeda.com>
+(cherry picked from commit 4c0946c47463defa681b83294383dc996d255bb7)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 65 +++++++++++++++++++-------------------------------
+ 1 file changed, 25 insertions(+), 40 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index c0e638b..170724a 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -686,16 +686,11 @@ EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+  * irq_find_mapping() - Find a linux irq from an hw irq number.
+  * @domain: domain owning this hardware interrupt
+  * @hwirq: hardware irq number in that domain space
+- *
+- * This is a slow path, for use by generic code. It's expected that an
+- * irq controller implementation directly calls the appropriate low level
+- * mapping function.
+  */
+ unsigned int irq_find_mapping(struct irq_domain *domain,
+                             irq_hw_number_t hwirq)
+ {
+-      unsigned int i;
+-      unsigned int hint = hwirq % nr_irqs;
++      struct irq_data *data;
+       /* Look for default domain if nececssary */
+       if (domain == NULL)
+@@ -703,22 +698,25 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
+       if (domain == NULL)
+               return 0;
+-      /* legacy -> bail early */
+-      if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
++      switch (domain->revmap_type) {
++      case IRQ_DOMAIN_MAP_LEGACY:
+               return irq_domain_legacy_revmap(domain, hwirq);
+-
+-      /* Slow path does a linear search of the map */
+-      if (hint == 0)
+-              hint = 1;
+-      i = hint;
+-      do {
+-              struct irq_data *data = irq_get_irq_data(i);
++      case IRQ_DOMAIN_MAP_LINEAR:
++              return irq_linear_revmap(domain, hwirq);
++      case IRQ_DOMAIN_MAP_TREE:
++              rcu_read_lock();
++              data = radix_tree_lookup(&domain->revmap_data.tree, hwirq);
++              rcu_read_unlock();
++              if (data)
++                      return data->irq;
++              break;
++      case IRQ_DOMAIN_MAP_NOMAP:
++              data = irq_get_irq_data(hwirq);
+               if (data && (data->domain == domain) && (data->hwirq == hwirq))
+-                      return i;
+-              i++;
+-              if (i >= nr_irqs)
+-                      i = 1;
+-      } while(i != hint);
++                      return hwirq;
++              break;
++      }
++
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(irq_find_mapping);
+@@ -728,32 +726,19 @@ EXPORT_SYMBOL_GPL(irq_find_mapping);
+  * @domain: domain owning this hardware interrupt
+  * @hwirq: hardware irq number in that domain space
+  *
+- * This is a fast path, for use by irq controller code that uses linear
+- * revmaps. It does fallback to the slow path if the revmap doesn't exist
+- * yet and will create the revmap entry with appropriate locking
++ * This is a fast path that can be called directly by irq controller code to
++ * save a handful of instructions.
+  */
+ unsigned int irq_linear_revmap(struct irq_domain *domain,
+                              irq_hw_number_t hwirq)
+ {
+-      unsigned int *revmap;
++      BUG_ON(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR);
+-      if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR))
+-              return irq_find_mapping(domain, hwirq);
+-
+-      /* Check revmap bounds */
+-      if (unlikely(hwirq >= domain->revmap_data.linear.size))
+-              return irq_find_mapping(domain, hwirq);
+-
+-      /* Check if revmap was allocated */
+-      revmap = domain->revmap_data.linear.revmap;
+-      if (unlikely(revmap == NULL))
+-              return irq_find_mapping(domain, hwirq);
+-
+-      /* Fill up revmap with slow path if no mapping found */
+-      if (unlikely(!revmap[hwirq]))
+-              revmap[hwirq] = irq_find_mapping(domain, hwirq);
++      /* Check revmap bounds; complain if exceeded */
++      if (WARN_ON(hwirq >= domain->revmap_data.linear.size))
++              return 0;
+-      return revmap[hwirq];
++      return domain->revmap_data.linear.revmap[hwirq];
+ }
+ EXPORT_SYMBOL_GPL(irq_linear_revmap);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch b/patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch
new file mode 100644 (file)
index 0000000..feaa1b5
--- /dev/null
@@ -0,0 +1,56 @@
+From 6a3157b4d4a0df782066f610807c4288ed52ec43 Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Date: Fri, 20 Jul 2012 10:33:19 +0100
+Subject: irqdomain: Improve diagnostics when a domain mapping fails
+
+When the map operation fails log the error code we get and add a WARN_ON()
+so we get a backtrace (which should help work out which interrupt is the
+source of the issue).
+
+Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+(cherry picked from commit f5a1ad057e6da5d0fc9c5677ff44797d193d3e62)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ kernel/irq/irqdomain.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 170724a..49a7772 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -415,7 +415,7 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
+ {
+       unsigned int virq = irq_base;
+       irq_hw_number_t hwirq = hwirq_base;
+-      int i;
++      int i, ret;
+       pr_debug("%s(%s, irqbase=%i, hwbase=%i, count=%i)\n", __func__,
+               of_node_full_name(domain->of_node), irq_base, (int)hwirq_base, count);
+@@ -436,11 +436,16 @@ int irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base,
+               irq_data->hwirq = hwirq;
+               irq_data->domain = domain;
+-              if (domain->ops->map && domain->ops->map(domain, virq, hwirq)) {
+-                      pr_err("irq-%i==>hwirq-0x%lx mapping failed\n", virq, hwirq);
+-                      irq_data->domain = NULL;
+-                      irq_data->hwirq = 0;
+-                      goto err_unmap;
++              if (domain->ops->map) {
++                      ret = domain->ops->map(domain, virq, hwirq);
++                      if (ret != 0) {
++                              pr_err("irq-%i==>hwirq-0x%lx mapping failed: %d\n",
++                                     virq, hwirq, ret);
++                              WARN_ON(1);
++                              irq_data->domain = NULL;
++                              irq_data->hwirq = 0;
++                              goto err_unmap;
++                      }
+               }
+               switch (domain->revmap_type) {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch b/patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch
new file mode 100644 (file)
index 0000000..755bc2e
--- /dev/null
@@ -0,0 +1,83 @@
+From f2f3cb0fe8263325798302e1b431e38cf4e153e8 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 28 Mar 2012 19:22:46 +0900
+Subject: ARM: mach-shmobile: Introduce INTC_IRQ_PINS_16H
+
+Add INTC_IRQ_PINS_16H to allow broken out support of the
+the high 16 external interrupt pins. On SoCs with 32 external
+interrupt pins the interrupt vectors for the low 16 and the
+high 16 interrupt pins are sparesly populated. The low 16 are
+at 0x0200 and high 16 are at 0x3200 which with current macros
+results in a separation of 384 linux interrupts. This sparse
+population makes it unsuitable with a single IRQ domain to
+cover the full IRQ range, so this macro breaks out the 32 pins
+into two separate 16 bit controllers to allow two independent
+INTC instances with two separate IRQ domains.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit d7e7e4ffc64f700e876a9f3b2727febaa2041221)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/intc.h | 44 ++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/intc.h b/arch/arm/mach-shmobile/include/mach/intc.h
+index 8b22258..a5603c7 100644
+--- a/arch/arm/mach-shmobile/include/mach/intc.h
++++ b/arch/arm/mach-shmobile/include/mach/intc.h
+@@ -142,6 +142,50 @@ static struct intc_desc p ## _desc __initdata = {                 \
+                            p ## _sense_registers, p ## _ack_registers) \
+ }
++#define INTC_IRQ_PINS_16H(p, base, vect, str)                         \
++                                                                      \
++static struct resource p ## _resources[] __initdata = {                       \
++      [0] = {                                                         \
++              .start  = base,                                         \
++              .end    = base + 0x64,                                  \
++              .flags  = IORESOURCE_MEM,                               \
++      },                                                              \
++};                                                                    \
++                                                                      \
++enum {                                                                        \
++      p ## _UNUSED = 0,                                               \
++      INTC_IRQ_PINS_ENUM_16H(p),                                      \
++};                                                                    \
++                                                                      \
++static struct intc_vect p ## _vectors[] __initdata = {                        \
++      INTC_IRQ_PINS_VECT_16H(p, vect),                                \
++};                                                                    \
++                                                                      \
++static struct intc_mask_reg p ## _mask_registers[] __initdata = {     \
++      INTC_IRQ_PINS_MASK_16H(p, base),                                \
++};                                                                    \
++                                                                      \
++static struct intc_prio_reg p ## _prio_registers[] __initdata = {     \
++      INTC_IRQ_PINS_PRIO_16H(p, base),                                \
++};                                                                    \
++                                                                      \
++static struct intc_sense_reg p ## _sense_registers[] __initdata = {   \
++      INTC_IRQ_PINS_SENSE_16H(p, base),                               \
++};                                                                    \
++                                                                      \
++static struct intc_mask_reg p ## _ack_registers[] __initdata = {      \
++      INTC_IRQ_PINS_ACK_16H(p, base),                                 \
++};                                                                    \
++                                                                      \
++static struct intc_desc p ## _desc __initdata = {                     \
++      .name = str,                                                    \
++      .resource = p ## _resources,                                    \
++      .num_resources = ARRAY_SIZE(p ## _resources),                   \
++      .hw = INTC_HW_DESC(p ## _vectors, NULL,                         \
++                           p ## _mask_registers, p ## _prio_registers, \
++                           p ## _sense_registers, p ## _ack_registers) \
++}
++
+ #define INTC_IRQ_PINS_32(p, base, vect, str)                          \
+                                                                       \
+ static struct resource p ## _resources[] __initdata = {                       \
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch b/patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch
new file mode 100644 (file)
index 0000000..9387903
--- /dev/null
@@ -0,0 +1,72 @@
+From cba1bcc0a91c91fb5b503e6a718801a0eca41b3f Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Tue, 22 May 2012 19:07:55 +0900
+Subject: sh: intc: Kill off special reservation interface.
+
+At present reserving the IRLs in the IRQ bitmap in addition to the
+dropping of the legacy IRQ pre-allocation prevent IRL IRQs from being
+allocated for the x3proto board.
+
+The only reason to permit reservations was to lock down possible hardware
+vectors prior to dynamic IRQ scanning, but this doesn't matter much given
+that the hardware controller configuration is sorted before we get around
+to doing any dynamic IRQ allocation anyways. Beyond that, all of the
+tables are __init annotated, so quite a bit more work would need to be
+done to support reconfiguring things like IRL controllers on the fly,
+much more than would ever make it worth the hassle.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 5f19f14fed7786652b9617c633db101d26a42251)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/sh/kernel/cpu/sh4a/setup-shx3.c | 3 ---
+ drivers/sh/intc/dynamic.c            | 8 --------
+ include/linux/sh_intc.h              | 1 -
+ 3 files changed, 12 deletions(-)
+
+diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+index bb20880..674531e 100644
+--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
++++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+@@ -484,9 +484,6 @@ void __init plat_irq_setup_pins(int mode)
+ void __init plat_irq_setup(void)
+ {
+-      reserve_intc_vectors(vectors_irq, ARRAY_SIZE(vectors_irq));
+-      reserve_intc_vectors(vectors_irl, ARRAY_SIZE(vectors_irl));
+-
+       register_intc_controller(&intc_desc);
+ }
+diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
+index 5fea1ee..14eb01e 100644
+--- a/drivers/sh/intc/dynamic.c
++++ b/drivers/sh/intc/dynamic.c
+@@ -55,11 +55,3 @@ void destroy_irq(unsigned int irq)
+ {
+       irq_free_desc(irq);
+ }
+-
+-void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs)
+-{
+-      int i;
+-
+-      for (i = 0; i < nr_vecs; i++)
+-              irq_reserve_irq(evt2irq(vectors[i].vect));
+-}
+diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
+index 6aed080..3238328 100644
+--- a/include/linux/sh_intc.h
++++ b/include/linux/sh_intc.h
+@@ -133,7 +133,6 @@ struct intc_desc symbol __initdata = {                                     \
+ }
+ int register_intc_controller(struct intc_desc *desc);
+-void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs);
+ int intc_set_priority(unsigned int irq, unsigned int prio);
+ int intc_irq_lookup(const char *chipname, intc_enum enum_id);
+ void intc_finalize(void);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch b/patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch
new file mode 100644 (file)
index 0000000..55c10a8
--- /dev/null
@@ -0,0 +1,41 @@
+From 42251498a3ddced1d93aae4fc44936663d7079a5 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Thu, 24 May 2012 19:24:18 +0900
+Subject: sh: intc: Allocate subgroup virq backing desc directly.
+
+This switches to using irq_alloc_desc() directly for subgroup IRQs.
+We still need to call activate_irq() on these in order to make them
+requestable, at least up until these get moved in to their own irq
+domain..
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 123df01e8e046d6065089e1bff29aa3fc48d4420)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/intc/virq.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c
+index 93cec21..f30ac93 100644
+--- a/drivers/sh/intc/virq.c
++++ b/drivers/sh/intc/virq.c
+@@ -219,12 +219,14 @@ restart:
+               if (radix_tree_deref_retry(entry))
+                       goto restart;
+-              irq = create_irq();
++              irq = irq_alloc_desc(numa_node_id());
+               if (unlikely(irq < 0)) {
+                       pr_err("no more free IRQs, bailing..\n");
+                       break;
+               }
++              activate_irq(irq);
++
+               pr_info("Setting up a chained VIRQ from %d -> %d\n",
+                       irq, entry->pirq);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0032-sh-intc-initial-irqdomain-support.patch b/patches.marzen/0032-sh-intc-initial-irqdomain-support.patch
new file mode 100644 (file)
index 0000000..be492d9
--- /dev/null
@@ -0,0 +1,195 @@
+From 53b1c0647bb113f4c1edfdfc8c40b7bf8f258628 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Wed, 1 Aug 2012 17:13:46 +0900
+Subject: sh: intc: initial irqdomain support.
+
+Trivial support for irq domains, using either a linear map or radix tree
+depending on the vector layout.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 1d6a21b0a672fb29b01ccf397d478e0541e17716)
+
+Conflicts:
+       drivers/sh/intc/Makefile
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/intc/Kconfig     |  4 +++
+ drivers/sh/intc/Makefile    |  2 +-
+ drivers/sh/intc/core.c      | 11 +++++---
+ drivers/sh/intc/internals.h |  5 ++++
+ drivers/sh/intc/irqdomain.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 85 insertions(+), 5 deletions(-)
+ create mode 100644 drivers/sh/intc/irqdomain.c
+
+diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig
+index c88cbcc..a305731 100644
+--- a/drivers/sh/intc/Kconfig
++++ b/drivers/sh/intc/Kconfig
+@@ -1,3 +1,7 @@
++config SH_INTC
++      def_bool y
++      select IRQ_DOMAIN
++
+ comment "Interrupt controller options"
+ config INTC_USERIMASK
+diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile
+index bb5df86..44cf2cd 100644
+--- a/drivers/sh/intc/Makefile
++++ b/drivers/sh/intc/Makefile
+@@ -1,4 +1,4 @@
+-obj-y         := access.o chip.o core.o dynamic.o handle.o virq.o
++obj-y         := access.o chip.o core.o dynamic.o handle.o irqdomain.o virq.o
+ obj-$(CONFIG_INTC_BALANCING)          += balancing.o
+ obj-$(CONFIG_INTC_USERIMASK)          += userimask.o
+diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
+index 7e562cc..2374468 100644
+--- a/drivers/sh/intc/core.c
++++ b/drivers/sh/intc/core.c
+@@ -25,6 +25,7 @@
+ #include <linux/stat.h>
+ #include <linux/interrupt.h>
+ #include <linux/sh_intc.h>
++#include <linux/irqdomain.h>
+ #include <linux/device.h>
+ #include <linux/syscore_ops.h>
+ #include <linux/list.h>
+@@ -310,6 +311,8 @@ int __init register_intc_controller(struct intc_desc *desc)
+       BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
++      intc_irq_domain_init(d, hw);
++
+       /* register the vectors one by one */
+       for (i = 0; i < hw->nr_vectors; i++) {
+               struct intc_vect *vect = hw->vectors + i;
+@@ -319,8 +322,8 @@ int __init register_intc_controller(struct intc_desc *desc)
+               if (!vect->enum_id)
+                       continue;
+-              res = irq_alloc_desc_at(irq, numa_node_id());
+-              if (res != irq && res != -EEXIST) {
++              res = irq_create_identity_mapping(d->domain, irq);
++              if (unlikely(res)) {
+                       pr_err("can't get irq_desc for %d\n", irq);
+                       continue;
+               }
+@@ -340,8 +343,8 @@ int __init register_intc_controller(struct intc_desc *desc)
+                        * IRQ support, each vector still needs to have
+                        * its own backing irq_desc.
+                        */
+-                      res = irq_alloc_desc_at(irq2, numa_node_id());
+-                      if (res != irq2 && res != -EEXIST) {
++                      res = irq_create_identity_mapping(d->domain, irq2);
++                      if (unlikely(res)) {
+                               pr_err("can't get irq_desc for %d\n", irq2);
+                               continue;
+                       }
+diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h
+index f034a97..7dff08e 100644
+--- a/drivers/sh/intc/internals.h
++++ b/drivers/sh/intc/internals.h
+@@ -1,5 +1,6 @@
+ #include <linux/sh_intc.h>
+ #include <linux/irq.h>
++#include <linux/irqdomain.h>
+ #include <linux/list.h>
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+@@ -66,6 +67,7 @@ struct intc_desc_int {
+       unsigned int nr_sense;
+       struct intc_window *window;
+       unsigned int nr_windows;
++      struct irq_domain *domain;
+       struct irq_chip chip;
+       bool skip_suspend;
+ };
+@@ -187,6 +189,9 @@ unsigned long intc_get_ack_handle(unsigned int irq);
+ void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d,
+                             intc_enum enum_id, int enable);
++/* irqdomain.c */
++void intc_irq_domain_init(struct intc_desc_int *d, struct intc_hw_desc *hw);
++
+ /* virq.c */
+ void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d);
+ void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d);
+diff --git a/drivers/sh/intc/irqdomain.c b/drivers/sh/intc/irqdomain.c
+new file mode 100644
+index 0000000..3968f1c
+--- /dev/null
++++ b/drivers/sh/intc/irqdomain.c
+@@ -0,0 +1,68 @@
++/*
++ * IRQ domain support for SH INTC subsystem
++ *
++ * Copyright (C) 2012  Paul Mundt
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#define pr_fmt(fmt) "intc: " fmt
++
++#include <linux/irqdomain.h>
++#include <linux/sh_intc.h>
++#include <linux/export.h>
++#include "internals.h"
++
++/**
++ * intc_irq_domain_evt_xlate() - Generic xlate for vectored IRQs.
++ *
++ * This takes care of exception vector to hwirq translation through
++ * by way of evt2irq() translation.
++ *
++ * Note: For platforms that use a flat vector space without INTEVT this
++ * basically just mimics irq_domain_xlate_onecell() by way of a nopped
++ * out evt2irq() implementation.
++ */
++static int intc_evt_xlate(struct irq_domain *d, struct device_node *ctrlr,
++                        const u32 *intspec, unsigned int intsize,
++                        unsigned long *out_hwirq, unsigned int *out_type)
++{
++      if (WARN_ON(intsize < 1))
++              return -EINVAL;
++
++      *out_hwirq = evt2irq(intspec[0]);
++      *out_type = IRQ_TYPE_NONE;
++
++      return 0;
++}
++
++static const struct irq_domain_ops intc_evt_ops = {
++      .xlate          = intc_evt_xlate,
++};
++
++void __init intc_irq_domain_init(struct intc_desc_int *d,
++                               struct intc_hw_desc *hw)
++{
++      unsigned int irq_base, irq_end;
++
++      /*
++       * Quick linear revmap check
++       */
++      irq_base = evt2irq(hw->vectors[0].vect);
++      irq_end = evt2irq(hw->vectors[hw->nr_vectors - 1].vect);
++
++      /*
++       * Linear domains have a hard-wired assertion that IRQs start at
++       * 0 in order to make some performance optimizations. Lamely
++       * restrict the linear case to these conditions here, taking the
++       * tree penalty for linear cases with non-zero hwirq bases.
++       */
++      if (irq_base == 0 && irq_end == (irq_base + hw->nr_vectors - 1))
++              d->domain = irq_domain_add_linear(NULL, hw->nr_vectors,
++                                                &intc_evt_ops, NULL);
++      else
++              d->domain = irq_domain_add_tree(NULL, &intc_evt_ops, NULL);
++
++      BUG_ON(!d->domain);
++}
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch b/patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch
new file mode 100644 (file)
index 0000000..9a4f461
--- /dev/null
@@ -0,0 +1,76 @@
+From f4c7cdd9100a1141390e3cea9c3ef8a104c420ae Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Thu, 9 Aug 2012 12:59:40 +0900
+Subject: sh: intc: Handle domain association for sparseirq pre-allocated
+ vectors.
+
+Presently it's assumed that the irqdomain code handles the irq_desc
+allocation for us, but this isn't necessarily the case when we've
+pre-allocated IRQs via sparseirq. Previously we had a -EEXIST check in
+the code that attempted to trap these cases and simply update them
+in-place, but this behaviour was inadvertently lost in the transition to
+irqdomains.
+
+This simply restores the previous behaviour, first attempting to let the
+irqdomain core fetch the allocation for us, and falling back to an
+in-place domain association in the extant IRQ case. Fixes up regressions
+on platforms that pre-allocate legacy IRQs (specifically ARM-based
+SH-Mobile platforms, as SH stopped pre-allocating vectors some time ago).
+
+Reported-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 1026023705b0baa2b37df2a0d1da0022fc7b985e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/intc/core.c | 27 +++++++++++++++++++++++----
+ 1 file changed, 23 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
+index 2374468..32c26d7 100644
+--- a/drivers/sh/intc/core.c
++++ b/drivers/sh/intc/core.c
+@@ -324,8 +324,16 @@ int __init register_intc_controller(struct intc_desc *desc)
+               res = irq_create_identity_mapping(d->domain, irq);
+               if (unlikely(res)) {
+-                      pr_err("can't get irq_desc for %d\n", irq);
+-                      continue;
++                      if (res == -EEXIST) {
++                              res = irq_domain_associate(d->domain, irq, irq);
++                              if (unlikely(res)) {
++                                      pr_err("domain association failure\n");
++                                      continue;
++                              }
++                      } else {
++                              pr_err("can't identity map IRQ %d\n", irq);
++                              continue;
++                      }
+               }
+               intc_irq_xlate_set(irq, vect->enum_id, d);
+@@ -345,8 +353,19 @@ int __init register_intc_controller(struct intc_desc *desc)
+                        */
+                       res = irq_create_identity_mapping(d->domain, irq2);
+                       if (unlikely(res)) {
+-                              pr_err("can't get irq_desc for %d\n", irq2);
+-                              continue;
++                              if (res == -EEXIST) {
++                                      res = irq_domain_associate(d->domain,
++                                                                 irq, irq);
++                                      if (unlikely(res)) {
++                                              pr_err("domain association "
++                                                     "failure\n");
++                                              continue;
++                                      }
++                              } else {
++                                      pr_err("can't identity map IRQ %d\n",
++                                             irq);
++                                      continue;
++                              }
+                       }
+                       vect2->enum_id = 0;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch b/patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch
new file mode 100644 (file)
index 0000000..adc6c6e
--- /dev/null
@@ -0,0 +1,32 @@
+From e36191f0adc5ef8bafb24f3612367b5648ee279a Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Mon, 20 Aug 2012 14:51:50 +0900
+Subject: sh: intc: Fix up multi-evt irq association.
+
+In the multi-evt case we were accidentally associating the parent IRQ,
+fix this up.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit d4b7c5db429fbfd3c79120b27ccf66d583606b57)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/sh/intc/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
+index 32c26d7..8f32a13 100644
+--- a/drivers/sh/intc/core.c
++++ b/drivers/sh/intc/core.c
+@@ -355,7 +355,7 @@ int __init register_intc_controller(struct intc_desc *desc)
+                       if (unlikely(res)) {
+                               if (res == -EEXIST) {
+                                       res = irq_domain_associate(d->domain,
+-                                                                 irq, irq);
++                                                                 irq2, irq2);
+                                       if (unlikely(res)) {
+                                               pr_err("domain association "
+                                                      "failure\n");
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch b/patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch
new file mode 100644 (file)
index 0000000..3ab4273
--- /dev/null
@@ -0,0 +1,70 @@
+From faa2b6a185dbc63fb27624543fb4e6dc3498eb90 Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 28 Mar 2012 19:22:30 +0900
+Subject: ARM: mach-shmobile: Introduce shmobile_setup_delay()
+
+Add the function shmobile_setup_delay() to let platforms
+configure their maximum loops per jiffy delay. With this
+jiffies calculation done the dependency on early timer
+is removed.
+
+In the future this allows us to assign timers
+using the regular driver model via the device tree.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 0f2c9f20e4e339de30cfd5613dfa9505e7b9c58b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/common.h |  2 ++
+ arch/arm/mach-shmobile/timer.c               | 17 +++++++++++++++++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
+index c85e6ec..ff5f12f 100644
+--- a/arch/arm/mach-shmobile/include/mach/common.h
++++ b/arch/arm/mach-shmobile/include/mach/common.h
+@@ -3,6 +3,8 @@
+ extern void shmobile_earlytimer_init(void);
+ extern struct sys_timer shmobile_timer;
++extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
++                               unsigned int mult, unsigned int div);
+ struct twd_local_timer;
+ extern void shmobile_setup_console(void);
+ extern void shmobile_secondary_vector(void);
+diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
+index 8b79e79..cba39d8 100644
+--- a/arch/arm/mach-shmobile/timer.c
++++ b/arch/arm/mach-shmobile/timer.c
+@@ -19,9 +19,26 @@
+  *
+  */
+ #include <linux/platform_device.h>
++#include <linux/delay.h>
+ #include <asm/mach/time.h>
+ #include <asm/smp_twd.h>
++void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
++                               unsigned int mult, unsigned int div)
++{
++      /* calculate a worst-case loops-per-jiffy value
++       * based on maximum cpu core mhz setting and the
++       * __delay() implementation in arch/arm/lib/delay.S
++       *
++       * this will result in a longer delay than expected
++       * when the cpu core runs on lower frequencies.
++       */
++
++      unsigned int value = (1000000 * mult) / (HZ * div);
++
++      lpj_fine = max_cpu_core_mhz * value;
++}
++
+ static void __init shmobile_late_time_init(void)
+ {
+       /*
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch b/patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch
new file mode 100644 (file)
index 0000000..f2a1a78
--- /dev/null
@@ -0,0 +1,43 @@
+From 08bdac8dff053868074871b3bc6318d6d95d476e Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Wed, 28 Mar 2012 19:22:54 +0900
+Subject: ARM: mach-shmobile: Use 0x3400 as INTCS vector offset
+
+Update mach-shmobile to use 0x3400 as INTCS_VECT_BASE.
+
+Since the ARM architecture a little while back added support
+for 10 bit irqs we can now undo the previously merged commit
+9b7c23adb350a108737a993c9c781463c1439dc6 and use 0x3400 as
+INTCS vector base.
+
+This change is necessary to avoid overlapping of interrupt
+ranges so separate IRQ domains can be used for different INTC
+instances. Without this fix the vectors used by various INTC
+instances are overlapping on for instance sh7372 which works
+at the moment but breaks upcoming IRQ domain support.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 1ee8299a9ec1ce5137a044c7768293007b9a3267)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/irqs.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
+index 4e686cc2..06a5da3 100644
+--- a/arch/arm/mach-shmobile/include/mach/irqs.h
++++ b/arch/arm/mach-shmobile/include/mach/irqs.h
+@@ -7,7 +7,7 @@
+ #define gic_spi(nr)           ((nr) + 32)
+ /* INTCS */
+-#define INTCS_VECT_BASE               0x2200
++#define INTCS_VECT_BASE               0x3400
+ #define INTCS_VECT(n, vect)   INTC_VECT((n), INTCS_VECT_BASE + (vect))
+ #define intcs_evt2irq(evt)    evt2irq(INTCS_VECT_BASE + (evt))
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch b/patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch
new file mode 100644 (file)
index 0000000..5ced9d5
--- /dev/null
@@ -0,0 +1,55 @@
+From 8635adab79f5f8e8287e93cc19442556cab55d06 Mon Sep 17 00:00:00 2001
+From: Shawn Guo <shawn.guo@linaro.org>
+Date: Wed, 25 Apr 2012 22:24:44 +0800
+Subject: ARM: provide a late_initcall hook for platform initialization
+
+This allows platforms to set up things that need to be done at
+late_initcall time.
+
+Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
+Tested-by: Robert Lee <rob.lee@linaro.org>
+Tested-by: Stephen Warren <swarren@wwwdotorg.org>
+Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com>
+Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
+(cherry picked from commit 90de41375ccf8373c0a39d04547f3e3c65d90ec0)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/include/asm/mach/arch.h | 1 +
+ arch/arm/kernel/setup.c          | 8 ++++++++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
+index d7692ca..0b1c94b 100644
+--- a/arch/arm/include/asm/mach/arch.h
++++ b/arch/arm/include/asm/mach/arch.h
+@@ -43,6 +43,7 @@ struct machine_desc {
+       void                    (*init_irq)(void);
+       struct sys_timer        *timer;         /* system tick timer    */
+       void                    (*init_machine)(void);
++      void                    (*init_late)(void);
+ #ifdef CONFIG_MULTI_IRQ_HANDLER
+       void                    (*handle_irq)(struct pt_regs *);
+ #endif
+diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
+index ebfac78..549f036 100644
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -800,6 +800,14 @@ static int __init customize_machine(void)
+ }
+ arch_initcall(customize_machine);
++static int __init init_machine_late(void)
++{
++      if (machine_desc->init_late)
++              machine_desc->init_late();
++      return 0;
++}
++late_initcall(init_machine_late);
++
+ #ifdef CONFIG_KEXEC
+ static inline unsigned long long get_total_mem(void)
+ {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch b/patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch
new file mode 100644 (file)
index 0000000..695b5f9
--- /dev/null
@@ -0,0 +1,219 @@
+From 7f963c76f63cde6c48ce88a3b6a964b316e6d8ed Mon Sep 17 00:00:00 2001
+From: Shawn Guo <shawn.guo@linaro.org>
+Date: Thu, 26 Apr 2012 21:58:41 +0800
+Subject: ARM: shmobile: use machine specific hook for late init
+
+Cc: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
+Acked-by: Magnus Damm <damm@opensource.se>
+Acked-by: "Rafael J. Wysocki" <rjw@sisk.pl>
+(cherry picked from commit 21cc1b7ede3cf456cf1d51f8a906093261f7c111)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/Makefile              |  2 +-
+ arch/arm/mach-shmobile/board-ag5evm.c        |  1 +
+ arch/arm/mach-shmobile/board-ap4evb.c        |  1 +
+ arch/arm/mach-shmobile/board-bonito.c        |  1 +
+ arch/arm/mach-shmobile/board-g3evm.c         |  1 +
+ arch/arm/mach-shmobile/board-g4evm.c         |  1 +
+ arch/arm/mach-shmobile/board-kota2.c         |  1 +
+ arch/arm/mach-shmobile/board-mackerel.c      |  1 +
+ arch/arm/mach-shmobile/board-marzen.c        |  1 +
+ arch/arm/mach-shmobile/common.c              | 24 ++++++++++++++++++++++++
+ arch/arm/mach-shmobile/cpuidle.c             |  3 +--
+ arch/arm/mach-shmobile/include/mach/common.h | 14 ++++++++++++++
+ arch/arm/mach-shmobile/suspend.c             |  3 +--
+ 13 files changed, 49 insertions(+), 5 deletions(-)
+ create mode 100644 arch/arm/mach-shmobile/common.c
+
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index e7c2590..93d62fb 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -3,7 +3,7 @@
+ #
+ # Common objects
+-obj-y                         := timer.o console.o clock.o
++obj-y                         := timer.o console.o clock.o common.o
+ # CPU objects
+ obj-$(CONFIG_ARCH_SH7367)     += setup-sh7367.o clock-sh7367.o intc-sh7367.o
+diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
+index 0891ec6..5a6f22f 100644
+--- a/arch/arm/mach-shmobile/board-ag5evm.c
++++ b/arch/arm/mach-shmobile/board-ag5evm.c
+@@ -580,5 +580,6 @@ MACHINE_START(AG5EVM, "ag5evm")
+       .init_irq       = sh73a0_init_irq,
+       .handle_irq     = gic_handle_irq,
+       .init_machine   = ag5evm_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
+index b56dde2..522866d 100644
+--- a/arch/arm/mach-shmobile/board-ap4evb.c
++++ b/arch/arm/mach-shmobile/board-ap4evb.c
+@@ -1440,5 +1440,6 @@ MACHINE_START(AP4EVB, "ap4evb")
+       .init_irq       = sh7372_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
+       .init_machine   = ap4evb_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
+index 81fd95f..e6b1fd3 100644
+--- a/arch/arm/mach-shmobile/board-bonito.c
++++ b/arch/arm/mach-shmobile/board-bonito.c
+@@ -500,5 +500,6 @@ MACHINE_START(BONITO, "bonito")
+       .init_irq       = r8a7740_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
+       .init_machine   = bonito_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
+index 39b6cf8..796fa00 100644
+--- a/arch/arm/mach-shmobile/board-g3evm.c
++++ b/arch/arm/mach-shmobile/board-g3evm.c
+@@ -338,5 +338,6 @@ MACHINE_START(G3EVM, "g3evm")
+       .init_irq       = sh7367_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
+       .init_machine   = g3evm_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
+index 0e5a39c..f125732 100644
+--- a/arch/arm/mach-shmobile/board-g4evm.c
++++ b/arch/arm/mach-shmobile/board-g4evm.c
+@@ -381,5 +381,6 @@ MACHINE_START(G4EVM, "g4evm")
+       .init_irq       = sh7377_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
+       .init_machine   = g4evm_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
+index 200dcd4..f60f1b2 100644
+--- a/arch/arm/mach-shmobile/board-kota2.c
++++ b/arch/arm/mach-shmobile/board-kota2.c
+@@ -521,5 +521,6 @@ MACHINE_START(KOTA2, "kota2")
+       .init_irq       = sh73a0_init_irq,
+       .handle_irq     = gic_handle_irq,
+       .init_machine   = kota2_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
+index 8c6202b..656d351 100644
+--- a/arch/arm/mach-shmobile/board-mackerel.c
++++ b/arch/arm/mach-shmobile/board-mackerel.c
+@@ -1605,5 +1605,6 @@ MACHINE_START(MACKEREL, "mackerel")
+       .init_irq       = sh7372_init_irq,
+       .handle_irq     = shmobile_handle_irq_intc,
+       .init_machine   = mackerel_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
+index ef0e13b..14de378 100644
+--- a/arch/arm/mach-shmobile/board-marzen.c
++++ b/arch/arm/mach-shmobile/board-marzen.c
+@@ -98,5 +98,6 @@ MACHINE_START(MARZEN, "marzen")
+       .init_irq       = r8a7779_init_irq,
+       .handle_irq     = gic_handle_irq,
+       .init_machine   = marzen_init,
++      .init_late      = shmobile_init_late,
+       .timer          = &shmobile_timer,
+ MACHINE_END
+diff --git a/arch/arm/mach-shmobile/common.c b/arch/arm/mach-shmobile/common.c
+new file mode 100644
+index 0000000..608aba9
+--- /dev/null
++++ b/arch/arm/mach-shmobile/common.c
+@@ -0,0 +1,24 @@
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ *
++ */
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <mach/common.h>
++
++void __init shmobile_init_late(void)
++{
++      shmobile_suspend_init();
++      shmobile_cpuidle_init();
++}
+diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
+index 7e65591..7b541e9 100644
+--- a/arch/arm/mach-shmobile/cpuidle.c
++++ b/arch/arm/mach-shmobile/cpuidle.c
+@@ -46,7 +46,7 @@ static struct cpuidle_driver shmobile_cpuidle_driver = {
+ void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
+-static int shmobile_cpuidle_init(void)
++int shmobile_cpuidle_init(void)
+ {
+       struct cpuidle_device *dev = &shmobile_cpuidle_dev;
+       struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
+@@ -65,4 +65,3 @@ static int shmobile_cpuidle_init(void)
+       return 0;
+ }
+-late_initcall(shmobile_cpuidle_init);
+diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
+index ff5f12f..01e2bc0 100644
+--- a/arch/arm/mach-shmobile/include/mach/common.h
++++ b/arch/arm/mach-shmobile/include/mach/common.h
+@@ -85,4 +85,18 @@ extern int r8a7779_boot_secondary(unsigned int cpu);
+ extern void r8a7779_smp_prepare_cpus(void);
+ extern void r8a7779_register_twd(void);
++extern void shmobile_init_late(void);
++
++#ifdef CONFIG_SUSPEND
++int shmobile_suspend_init(void);
++#else
++static inline int shmobile_suspend_init(void) { return 0; }
++#endif
++
++#ifdef CONFIG_CPU_IDLE
++int shmobile_cpuidle_init(void);
++#else
++static inline int shmobile_cpuidle_init(void) { return 0; }
++#endif
++
+ #endif /* __ARCH_MACH_COMMON_H */
+diff --git a/arch/arm/mach-shmobile/suspend.c b/arch/arm/mach-shmobile/suspend.c
+index 4d1b86a..47d83f7 100644
+--- a/arch/arm/mach-shmobile/suspend.c
++++ b/arch/arm/mach-shmobile/suspend.c
+@@ -39,9 +39,8 @@ struct platform_suspend_ops shmobile_suspend_ops = {
+       .valid          = suspend_valid_only_mem,
+ };
+-static int __init shmobile_suspend_init(void)
++int __init shmobile_suspend_init(void)
+ {
+       suspend_set_ops(&shmobile_suspend_ops);
+       return 0;
+ }
+-late_initcall(shmobile_suspend_init);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch b/patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch
new file mode 100644 (file)
index 0000000..0bd9433
--- /dev/null
@@ -0,0 +1,46 @@
+From d85b38a67ee3f87c9ac4d814d091f6bacd77745a Mon Sep 17 00:00:00 2001
+From: Magnus Damm <damm@opensource.se>
+Date: Thu, 10 May 2012 00:37:48 +0200
+Subject: ARM / mach-shmobile: Use preset_lpj with calibrate_delay()
+
+Update the mach-shmobile shared delay calibration code for late
+timers. All existing in-tree non-DT socs are however using early
+timers today and they are unaffected by this change.
+
+The patch modifies shmobile_setup_delay() from using lpj_fine
+to preset_lpj. This change allows us to preset the worst case
+loops-per-jiffy value to all CPU cores on the system.
+
+The old code which made use of lpj_fine did not affect the
+secondary CPU cores which made it impossible to boot on SMP
+without early timers.
+
+Needed for SMP SoCs using late timers like EMEV2 or any other
+mach-shmobile SMP SoC that makes use of late timers via DT.
+
+Signed-off-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 173bf69a7af142e0325fa514954f6eeb2d20cc1d)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/timer.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
+index cba39d8..a689197 100644
+--- a/arch/arm/mach-shmobile/timer.c
++++ b/arch/arm/mach-shmobile/timer.c
+@@ -36,7 +36,8 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
+       unsigned int value = (1000000 * mult) / (HZ * div);
+-      lpj_fine = max_cpu_core_mhz * value;
++      if (!preset_lpj)
++              preset_lpj = max_cpu_core_mhz * value;
+ }
+ static void __init shmobile_late_time_init(void)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch b/patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch
new file mode 100644 (file)
index 0000000..9ccc16d
--- /dev/null
@@ -0,0 +1,72 @@
+From 357b31146983e768c408a833731f6b5c614286df Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Tue, 12 Jun 2012 02:36:21 -0700
+Subject: ARM: shmobile: r8a7740: add MERAM work-around
+
+r8a7740 chip has lasting errata on MERAM buffer, and this patch adds
+its work-around on setup-r8a7740.c
+It solved CEU/VIO6C/2D-DMAC/VCP1/VPU5F/JPU/DISP memroy access error.
+
+But MERAM driver can't control this issue,
+since this work-around requires access to non-MERAM register address.
+So, This it will be called as board specific code at this point.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit d49679e5928709bce8937dce396458b139c4b34d)
+
+Conflicts:
+       arch/arm/mach-shmobile/board-armadillo800eva.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/common.h |  1 +
+ arch/arm/mach-shmobile/setup-r8a7740.c       | 18 ++++++++++++++++++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
+index 01e2bc0..45e61da 100644
+--- a/arch/arm/mach-shmobile/include/mach/common.h
++++ b/arch/arm/mach-shmobile/include/mach/common.h
+@@ -77,6 +77,7 @@ extern void r8a7779_add_standard_devices(void);
+ extern void r8a7779_clock_init(void);
+ extern void r8a7779_pinmux_init(void);
+ extern void r8a7779_pm_init(void);
++extern void r8a7740_meram_workaround(void);
+ extern unsigned int r8a7779_get_core_count(void);
+ extern int r8a7779_platform_cpu_kill(unsigned int cpu);
+diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
+index 14edb5c..4ba8721 100644
+--- a/arch/arm/mach-shmobile/setup-r8a7740.c
++++ b/arch/arm/mach-shmobile/setup-r8a7740.c
+@@ -317,6 +317,24 @@ static struct platform_device *r8a7740_late_devices[] __initdata = {
+       &i2c1_device,
+ };
++/*
++ * r8a7740 chip has lasting errata on MERAM buffer.
++ * this is work-around for it.
++ * see
++ *    "Media RAM (MERAM)" on r8a7740 documentation
++ */
++#define MEBUFCNTR     0xFE950098
++void r8a7740_meram_workaround(void)
++{
++      void __iomem *reg;
++
++      reg = ioremap_nocache(MEBUFCNTR, 4);
++      if (reg) {
++              iowrite32(0x01600164, reg);
++              iounmap(reg);
++      }
++}
++
+ #define ICCR  0x0004
+ #define ICSTART       0x0070
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch b/patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch
new file mode 100644 (file)
index 0000000..3c63f44
--- /dev/null
@@ -0,0 +1,73 @@
+From 2a3e278e5c92a6143bc2a57f5c2d5093e26f4208 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Mon, 25 Jun 2012 03:41:09 -0700
+Subject: ARM: shmobile: add common extra gpio functions
+
+Current gpio frame work doesn't have the method to control
+just pull up/down/free, but some SH-ARM boards need such kind of operation.
+This patch adds common extra gpio functions for SH-ARM.
+
+But these functions should be replaced by correct
+gpio function in the future.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 4f3d7f65e9d541566c87de2af2d3b066bae78116)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/include/mach/gpio.h | 32 ++++++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h
+index de795b4..844507d 100644
+--- a/arch/arm/mach-shmobile/include/mach/gpio.h
++++ b/arch/arm/mach-shmobile/include/mach/gpio.h
+@@ -13,6 +13,7 @@
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/sh_pfc.h>
++#include <linux/io.h>
+ #ifdef CONFIG_GPIOLIB
+@@ -27,4 +28,35 @@ static inline int irq_to_gpio(unsigned int irq)
+ #endif /* CONFIG_GPIOLIB */
++/*
++ * FIXME !!
++ *
++ * current gpio frame work doesn't have
++ * the method to control only pull up/down/free.
++ * this function should be replaced by correct gpio function
++ */
++static inline void __init gpio_direction_none(u32 addr)
++{
++      __raw_writeb(0x00, addr);
++}
++
++static inline void __init gpio_request_pullup(u32 addr)
++{
++      u8 data = __raw_readb(addr);
++
++      data &= 0x0F;
++      data |= 0xC0;
++      __raw_writeb(data, addr);
++}
++
++static inline void __init gpio_request_pulldown(u32 addr)
++{
++      u8 data = __raw_readb(addr);
++
++      data &= 0x0F;
++      data |= 0xA0;
++
++      __raw_writeb(data, addr);
++}
++
+ #endif /* __ASM_ARCH_GPIO_H */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch b/patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch
new file mode 100644 (file)
index 0000000..161d66a
--- /dev/null
@@ -0,0 +1,55 @@
+From 585b51f2c85ca9c6523a2fca74cc9c6beae3a00a Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 27 Jun 2012 00:32:32 +0200
+Subject: ARM: mach-shmobile: add fixed voltage regulators to marzen
+
+On marzen provide a dummy regulator for the smsc911x driver.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit b354e2272ac6fddd19cfd5732bda23974f7b4ee6)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-marzen.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
+index 14de378..3a528cf 100644
+--- a/arch/arm/mach-shmobile/board-marzen.c
++++ b/arch/arm/mach-shmobile/board-marzen.c
+@@ -27,6 +27,8 @@
+ #include <linux/io.h>
+ #include <linux/gpio.h>
+ #include <linux/dma-mapping.h>
++#include <linux/regulator/fixed.h>
++#include <linux/regulator/machine.h>
+ #include <linux/smsc911x.h>
+ #include <mach/hardware.h>
+ #include <mach/r8a7779.h>
+@@ -37,6 +39,12 @@
+ #include <asm/hardware/gic.h>
+ #include <asm/traps.h>
++/* Dummy supplies, where voltage doesn't matter */
++static struct regulator_consumer_supply dummy_supplies[] = {
++      REGULATOR_SUPPLY("vddvario", "smsc911x"),
++      REGULATOR_SUPPLY("vdd33a", "smsc911x"),
++};
++
+ /* SMSC LAN89218 */
+ static struct resource smsc911x_resources[] = {
+       [0] = {
+@@ -73,6 +81,8 @@ static struct platform_device *marzen_devices[] __initdata = {
+ static void __init marzen_init(void)
+ {
++      regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
++
+       r8a7779_pinmux_init();
+       /* SCIF2 (CN18: DEBUG0) */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch b/patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch
new file mode 100644 (file)
index 0000000..ceb74d7
--- /dev/null
@@ -0,0 +1,33 @@
+From b7bf36d36b723ef18c515a031fb762d72ce06c38 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Wed, 29 Aug 2012 18:58:01 -0700
+Subject: ARM: shmobile: marzen: fixup smsc911x id for regulator
+
+dummy_supplies for smsc911x are registered as "smsc911x".
+smsc911x driver needs id = -1
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Simon Horman <horms@verge.net.au>
+(cherry picked from commit 497dcf6fc355f0734faf851662b6957386715d24)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/board-marzen.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
+index 3a528cf..fcf5a47 100644
+--- a/arch/arm/mach-shmobile/board-marzen.c
++++ b/arch/arm/mach-shmobile/board-marzen.c
+@@ -67,7 +67,7 @@ static struct smsc911x_platform_config smsc911x_platdata = {
+ static struct platform_device eth_device = {
+       .name           = "smsc911x",
+-      .id             = 0,
++      .id             = -1,
+       .dev  = {
+               .platform_data = &smsc911x_platdata,
+       },
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch b/patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch
new file mode 100644 (file)
index 0000000..5cfb754
--- /dev/null
@@ -0,0 +1,46 @@
+From d84794f3aa3f4214afb08fa52df3ad592965ddba Mon Sep 17 00:00:00 2001
+From: Phil Edworthy <phil.edworthy@renesas.com>
+Date: Sat, 23 Jun 2012 01:12:09 +0200
+Subject: ARM: shmobile: r8a7779: Route all interrupts to ARM
+
+Without this, the interrupts for I2C, VIN, GPIO, SDHC, HSCIF and
+HPB-DMAC are sent to the SH processor.
+
+Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+(cherry picked from commit 86f887c105b909a2cea7b06f2136d66b3438b038)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ arch/arm/mach-shmobile/intc-r8a7779.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
+index 550b23d..f04fad4 100644
+--- a/arch/arm/mach-shmobile/intc-r8a7779.c
++++ b/arch/arm/mach-shmobile/intc-r8a7779.c
+@@ -35,6 +35,9 @@
+ #define INT2SMSKCR3 0xfe7822ac
+ #define INT2SMSKCR4 0xfe7822b0
++#define INT2NTSR0 0xfe700060
++#define INT2NTSR1 0xfe700064
++
+ static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
+ {
+       return 0; /* always allow wakeup */
+@@ -49,6 +52,10 @@ void __init r8a7779_init_irq(void)
+       gic_init(0, 29, gic_dist_base, gic_cpu_base);
+       gic_arch_extn.irq_set_wake = r8a7779_set_wake;
++      /* route all interrupts to ARM */
++      __raw_writel(0xffffffff, INT2NTSR0);
++      __raw_writel(0x3fffffff, INT2NTSR1);
++
+       /* unmask all known interrupts in INTCS2 */
+       __raw_writel(0xfffffff0, INT2SMSKCR0);
+       __raw_writel(0xfff7ffff, INT2SMSKCR1);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch b/patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch
new file mode 100644 (file)
index 0000000..ec873b0
--- /dev/null
@@ -0,0 +1,52 @@
+From 35d53ddd33da54b2ac40aa2b73e93832f9f72c28 Mon Sep 17 00:00:00 2001
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Date: Wed, 25 Apr 2012 20:50:53 +0200
+Subject: dmaengine: Fixup dmaengine_prep_slave_single() to be actually useful
+
+dmaengine_prep_slave_single() is a helper function which is supposed to be used
+to prepare a transfer of a single contingous buffer. Currently the function
+takes a pointer to such a buffer from which it builds a scatterlist and passes
+it on to device_prep_slave_sg. The dmaengine framework requires that any
+scatterlist that is passed to device_prep_slave_sg is mapped and it may not be
+unmapped until the DMA operation has completed. This is not the here and any use
+of dmaengine_prep_slave_single() will lead to undefined behaviour (Most likely a
+system crash).
+
+This patch changes dmaengine_prep_slave_single() to take a dma_addr_t instead of
+a pointer to a buffer and moves the responsibility of mapping and unmapping the
+buffer up to the caller.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 922ee08baad2052d0759f100e026d49798c51fef)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/dmaengine.h | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index f9a2e5e..d3fec58 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -615,11 +615,13 @@ static inline int dmaengine_slave_config(struct dma_chan *chan,
+ }
+ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
+-      struct dma_chan *chan, void *buf, size_t len,
++      struct dma_chan *chan, dma_addr_t buf, size_t len,
+       enum dma_transfer_direction dir, unsigned long flags)
+ {
+       struct scatterlist sg;
+-      sg_init_one(&sg, buf, len);
++      sg_init_table(&sg, 1);
++      sg_dma_address(&sg) = buf;
++      sg_dma_len(&sg) = len;
+       return chan->device->device_prep_slave_sg(chan, &sg, 1,
+                                                 dir, flags, NULL);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch b/patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch
new file mode 100644 (file)
index 0000000..ce43120
--- /dev/null
@@ -0,0 +1,47 @@
+From a41ee881d86159d8d44d481f10c3288bdbc38a47 Mon Sep 17 00:00:00 2001
+From: Laxman Dewangan <ldewangan@nvidia.com>
+Date: Wed, 6 Jun 2012 10:55:26 +0530
+Subject: dma: dmaengine: add slave req id in slave_config
+
+The DMA controller like Nvidia's Tegra Dma controller
+supports the different slave requestor id from different slave.
+This need to be configure in dma controller to handle the request
+properly.
+
+Adding the slave-id in the slave configuration so that information
+can be passed from client when configuring for slave.
+
+Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 4fd1e324b7b5f80bd521b58593ada74ef89e80c4)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/dmaengine.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index d3fec58..2fad917 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -338,6 +338,9 @@ enum dma_slave_buswidth {
+  * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill
+  * with 'true' if peripheral should be flow controller. Direction will be
+  * selected at Runtime.
++ * @slave_id: Slave requester id. Only valid for slave channels. The dma
++ * slave peripheral will have unique id as dma requester which need to be
++ * pass as slave config.
+  *
+  * This struct is passed in as configuration data to a DMA engine
+  * in order to set up a certain channel for DMA transport at runtime.
+@@ -365,6 +368,7 @@ struct dma_slave_config {
+       u32 src_maxburst;
+       u32 dst_maxburst;
+       bool device_fc;
++      unsigned int slave_id;
+ };
+ static inline const char *dma_chan_name(struct dma_chan *chan)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch b/patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch
new file mode 100644 (file)
index 0000000..aaf2660
--- /dev/null
@@ -0,0 +1,42 @@
+From c5e667d5b33e041c7dff155e548083c2a176c31a Mon Sep 17 00:00:00 2001
+From: Lars-Peter Clausen <lars@metafoo.de>
+Date: Mon, 11 Jun 2012 20:11:40 +0200
+Subject: dmaengine: Add wrapper for device_tx_status callback
+
+This patch adds a small inline wrapper for the devivce_tx_status callback of a
+dma device. This makes the source code of users of this function a bit more
+compact and a bit more legible.
+
+E.g.:
+-status = chan->device->device_tx_status(chan, cookie, &state)
++status = dmaengine_tx_status(chan, cookie, &state)
+
+Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 3052cc2c92f11875d111d5b7b9b3ad535b3128b9)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/dmaengine.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index 2fad917..d1d6ef2 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -662,6 +662,12 @@ static inline int dmaengine_resume(struct dma_chan *chan)
+       return dmaengine_device_control(chan, DMA_RESUME, 0);
+ }
++static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan,
++      dma_cookie_t cookie, struct dma_tx_state *state)
++{
++      return chan->device->device_tx_status(chan, cookie, state);
++}
++
+ static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc)
+ {
+       return desc->tx_submit(desc);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch b/patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch
new file mode 100644 (file)
index 0000000..062ec15
--- /dev/null
@@ -0,0 +1,66 @@
+From 35a2e575d9dbacd1fdd88ca6c032d9c87de43622 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Mon, 2 Jul 2012 22:30:53 +0200
+Subject: dma: move shdma driver to an own directory
+
+The shdma driver is going to be split into multiple files. To make this more
+convenient move it to an own directory.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit e95be94b8c25220aca09ed78c176f9b55a1482c8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/Makefile         | 2 +-
+ drivers/dma/sh/Makefile      | 1 +
+ drivers/dma/{ => sh}/shdma.c | 2 +-
+ drivers/dma/{ => sh}/shdma.h | 0
+ 4 files changed, 3 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/dma/sh/Makefile
+ rename drivers/dma/{ => sh}/shdma.c (99%)
+ rename drivers/dma/{ => sh}/shdma.h (100%)
+
+diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
+index 86b795b..59c10e5 100644
+--- a/drivers/dma/Makefile
++++ b/drivers/dma/Makefile
+@@ -14,7 +14,7 @@ obj-$(CONFIG_DW_DMAC) += dw_dmac.o
+ obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
+ obj-$(CONFIG_MX3_IPU) += ipu/
+ obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
+-obj-$(CONFIG_SH_DMAE) += shdma.o
++obj-$(CONFIG_SH_DMAE) += sh/
+ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
+ obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
+ obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
+diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile
+new file mode 100644
+index 0000000..ad4981a
+--- /dev/null
++++ b/drivers/dma/sh/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_SH_DMAE) += shdma.o
+diff --git a/drivers/dma/shdma.c b/drivers/dma/sh/shdma.c
+similarity index 99%
+rename from drivers/dma/shdma.c
+rename to drivers/dma/sh/shdma.c
+index 19d7a8d..8ab4a1f 100644
+--- a/drivers/dma/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -31,7 +31,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/rculist.h>
+-#include "dmaengine.h"
++#include "../dmaengine.h"
+ #include "shdma.h"
+ /* DMA descriptor control */
+diff --git a/drivers/dma/shdma.h b/drivers/dma/sh/shdma.h
+similarity index 100%
+rename from drivers/dma/shdma.h
+rename to drivers/dma/sh/shdma.h
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch b/patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch
new file mode 100644 (file)
index 0000000..9907b4f
--- /dev/null
@@ -0,0 +1,1036 @@
+From cb331142a15a186173bb23463c591780e82f0a67 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:13 +0200
+Subject: dmaengine: add an shdma-base library
+
+This patch extracts code from shdma.c, that does not directly deal with
+hardware implementation details and can be re-used with diverse DMA
+controller variants, found on SH-based SoCs.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 9a7b8e002e331d0599127f16613c32f425a14f2c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/sh/Makefile     |   1 +
+ drivers/dma/sh/shdma-base.c | 868 ++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/shdma-base.h  | 123 +++++++
+ 3 files changed, 992 insertions(+)
+ create mode 100644 drivers/dma/sh/shdma-base.c
+ create mode 100644 include/linux/shdma-base.h
+
+diff --git a/drivers/dma/sh/Makefile b/drivers/dma/sh/Makefile
+index ad4981a..54ae957 100644
+--- a/drivers/dma/sh/Makefile
++++ b/drivers/dma/sh/Makefile
+@@ -1 +1,2 @@
++obj-$(CONFIG_SH_DMAE) += shdma-base.o
+ obj-$(CONFIG_SH_DMAE) += shdma.o
+diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
+new file mode 100644
+index 0000000..ff060d0
+--- /dev/null
++++ b/drivers/dma/sh/shdma-base.c
+@@ -0,0 +1,868 @@
++/*
++ * Dmaengine driver base library for DMA controllers, found on SH-based SoCs
++ *
++ * extracted from shdma.c
++ *
++ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
++ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
++ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
++ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/delay.h>
++#include <linux/shdma-base.h>
++#include <linux/dmaengine.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/pm_runtime.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++
++#include "../dmaengine.h"
++
++/* DMA descriptor control */
++enum shdma_desc_status {
++      DESC_IDLE,
++      DESC_PREPARED,
++      DESC_SUBMITTED,
++      DESC_COMPLETED, /* completed, have to call callback */
++      DESC_WAITING,   /* callback called, waiting for ack / re-submit */
++};
++
++#define NR_DESCS_PER_CHANNEL 32
++
++#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
++#define to_shdma_dev(d) container_of(d, struct shdma_dev, dma_dev)
++
++/*
++ * For slave DMA we assume, that there is a finite number of DMA slaves in the
++ * system, and that each such slave can only use a finite number of channels.
++ * We use slave channel IDs to make sure, that no such slave channel ID is
++ * allocated more than once.
++ */
++static unsigned int slave_num = 256;
++module_param(slave_num, uint, 0444);
++
++/* A bitmask with slave_num bits */
++static unsigned long *shdma_slave_used;
++
++/* Called under spin_lock_irq(&schan->chan_lock") */
++static void shdma_chan_xfer_ld_queue(struct shdma_chan *schan)
++{
++      struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
++      const struct shdma_ops *ops = sdev->ops;
++      struct shdma_desc *sdesc;
++
++      /* DMA work check */
++      if (ops->channel_busy(schan))
++              return;
++
++      /* Find the first not transferred descriptor */
++      list_for_each_entry(sdesc, &schan->ld_queue, node)
++              if (sdesc->mark == DESC_SUBMITTED) {
++                      ops->start_xfer(schan, sdesc);
++                      break;
++              }
++}
++
++static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
++{
++      struct shdma_desc *chunk, *c, *desc =
++              container_of(tx, struct shdma_desc, async_tx),
++              *last = desc;
++      struct shdma_chan *schan = to_shdma_chan(tx->chan);
++      struct shdma_slave *slave = tx->chan->private;
++      dma_async_tx_callback callback = tx->callback;
++      dma_cookie_t cookie;
++      bool power_up;
++
++      spin_lock_irq(&schan->chan_lock);
++
++      power_up = list_empty(&schan->ld_queue);
++
++      cookie = dma_cookie_assign(tx);
++
++      /* Mark all chunks of this descriptor as submitted, move to the queue */
++      list_for_each_entry_safe(chunk, c, desc->node.prev, node) {
++              /*
++               * All chunks are on the global ld_free, so, we have to find
++               * the end of the chain ourselves
++               */
++              if (chunk != desc && (chunk->mark == DESC_IDLE ||
++                                    chunk->async_tx.cookie > 0 ||
++                                    chunk->async_tx.cookie == -EBUSY ||
++                                    &chunk->node == &schan->ld_free))
++                      break;
++              chunk->mark = DESC_SUBMITTED;
++              /* Callback goes to the last chunk */
++              chunk->async_tx.callback = NULL;
++              chunk->cookie = cookie;
++              list_move_tail(&chunk->node, &schan->ld_queue);
++              last = chunk;
++
++              dev_dbg(schan->dev, "submit #%d@%p on %d\n",
++                      tx->cookie, &last->async_tx, schan->id);
++      }
++
++      last->async_tx.callback = callback;
++      last->async_tx.callback_param = tx->callback_param;
++
++      if (power_up) {
++              int ret;
++              schan->pm_state = SHDMA_PM_BUSY;
++
++              ret = pm_runtime_get(schan->dev);
++
++              spin_unlock_irq(&schan->chan_lock);
++              if (ret < 0)
++                      dev_err(schan->dev, "%s(): GET = %d\n", __func__, ret);
++
++              pm_runtime_barrier(schan->dev);
++
++              spin_lock_irq(&schan->chan_lock);
++
++              /* Have we been reset, while waiting? */
++              if (schan->pm_state != SHDMA_PM_ESTABLISHED) {
++                      struct shdma_dev *sdev =
++                              to_shdma_dev(schan->dma_chan.device);
++                      const struct shdma_ops *ops = sdev->ops;
++                      dev_dbg(schan->dev, "Bring up channel %d\n",
++                              schan->id);
++                      /*
++                       * TODO: .xfer_setup() might fail on some platforms.
++                       * Make it int then, on error remove chunks from the
++                       * queue again
++                       */
++                      ops->setup_xfer(schan, slave);
++
++                      if (schan->pm_state == SHDMA_PM_PENDING)
++                              shdma_chan_xfer_ld_queue(schan);
++                      schan->pm_state = SHDMA_PM_ESTABLISHED;
++              }
++      } else {
++              /*
++               * Tell .device_issue_pending() not to run the queue, interrupts
++               * will do it anyway
++               */
++              schan->pm_state = SHDMA_PM_PENDING;
++      }
++
++      spin_unlock_irq(&schan->chan_lock);
++
++      return cookie;
++}
++
++/* Called with desc_lock held */
++static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
++{
++      struct shdma_desc *sdesc;
++
++      list_for_each_entry(sdesc, &schan->ld_free, node)
++              if (sdesc->mark != DESC_PREPARED) {
++                      BUG_ON(sdesc->mark != DESC_IDLE);
++                      list_del(&sdesc->node);
++                      return sdesc;
++              }
++
++      return NULL;
++}
++
++static int shdma_alloc_chan_resources(struct dma_chan *chan)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++      struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
++      const struct shdma_ops *ops = sdev->ops;
++      struct shdma_desc *desc;
++      struct shdma_slave *slave = chan->private;
++      int ret, i;
++
++      /*
++       * This relies on the guarantee from dmaengine that alloc_chan_resources
++       * never runs concurrently with itself or free_chan_resources.
++       */
++      if (slave) {
++              if (slave->slave_id >= slave_num) {
++                      ret = -EINVAL;
++                      goto evalid;
++              }
++
++              if (test_and_set_bit(slave->slave_id, shdma_slave_used)) {
++                      ret = -EBUSY;
++                      goto etestused;
++              }
++
++              ret = ops->set_slave(schan, slave);
++              if (ret < 0)
++                      goto esetslave;
++      }
++
++      schan->desc = kcalloc(NR_DESCS_PER_CHANNEL,
++                            sdev->desc_size, GFP_KERNEL);
++      if (!schan->desc) {
++              ret = -ENOMEM;
++              goto edescalloc;
++      }
++      schan->desc_num = NR_DESCS_PER_CHANNEL;
++
++      for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
++              desc = ops->embedded_desc(schan->desc, i);
++              dma_async_tx_descriptor_init(&desc->async_tx,
++                                           &schan->dma_chan);
++              desc->async_tx.tx_submit = shdma_tx_submit;
++              desc->mark = DESC_IDLE;
++
++              list_add(&desc->node, &schan->ld_free);
++      }
++
++      return NR_DESCS_PER_CHANNEL;
++
++edescalloc:
++      if (slave)
++esetslave:
++              clear_bit(slave->slave_id, shdma_slave_used);
++etestused:
++evalid:
++      chan->private = NULL;
++      return ret;
++}
++
++static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all)
++{
++      struct shdma_desc *desc, *_desc;
++      /* Is the "exposed" head of a chain acked? */
++      bool head_acked = false;
++      dma_cookie_t cookie = 0;
++      dma_async_tx_callback callback = NULL;
++      void *param = NULL;
++      unsigned long flags;
++
++      spin_lock_irqsave(&schan->chan_lock, flags);
++      list_for_each_entry_safe(desc, _desc, &schan->ld_queue, node) {
++              struct dma_async_tx_descriptor *tx = &desc->async_tx;
++
++              BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie);
++              BUG_ON(desc->mark != DESC_SUBMITTED &&
++                     desc->mark != DESC_COMPLETED &&
++                     desc->mark != DESC_WAITING);
++
++              /*
++               * queue is ordered, and we use this loop to (1) clean up all
++               * completed descriptors, and to (2) update descriptor flags of
++               * any chunks in a (partially) completed chain
++               */
++              if (!all && desc->mark == DESC_SUBMITTED &&
++                  desc->cookie != cookie)
++                      break;
++
++              if (tx->cookie > 0)
++                      cookie = tx->cookie;
++
++              if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
++                      if (schan->dma_chan.completed_cookie != desc->cookie - 1)
++                              dev_dbg(schan->dev,
++                                      "Completing cookie %d, expected %d\n",
++                                      desc->cookie,
++                                      schan->dma_chan.completed_cookie + 1);
++                      schan->dma_chan.completed_cookie = desc->cookie;
++              }
++
++              /* Call callback on the last chunk */
++              if (desc->mark == DESC_COMPLETED && tx->callback) {
++                      desc->mark = DESC_WAITING;
++                      callback = tx->callback;
++                      param = tx->callback_param;
++                      dev_dbg(schan->dev, "descriptor #%d@%p on %d callback\n",
++                              tx->cookie, tx, schan->id);
++                      BUG_ON(desc->chunks != 1);
++                      break;
++              }
++
++              if (tx->cookie > 0 || tx->cookie == -EBUSY) {
++                      if (desc->mark == DESC_COMPLETED) {
++                              BUG_ON(tx->cookie < 0);
++                              desc->mark = DESC_WAITING;
++                      }
++                      head_acked = async_tx_test_ack(tx);
++              } else {
++                      switch (desc->mark) {
++                      case DESC_COMPLETED:
++                              desc->mark = DESC_WAITING;
++                              /* Fall through */
++                      case DESC_WAITING:
++                              if (head_acked)
++                                      async_tx_ack(&desc->async_tx);
++                      }
++              }
++
++              dev_dbg(schan->dev, "descriptor %p #%d completed.\n",
++                      tx, tx->cookie);
++
++              if (((desc->mark == DESC_COMPLETED ||
++                    desc->mark == DESC_WAITING) &&
++                   async_tx_test_ack(&desc->async_tx)) || all) {
++                      /* Remove from ld_queue list */
++                      desc->mark = DESC_IDLE;
++
++                      list_move(&desc->node, &schan->ld_free);
++
++                      if (list_empty(&schan->ld_queue)) {
++                              dev_dbg(schan->dev, "Bring down channel %d\n", schan->id);
++                              pm_runtime_put(schan->dev);
++                              schan->pm_state = SHDMA_PM_ESTABLISHED;
++                      }
++              }
++      }
++
++      if (all && !callback)
++              /*
++               * Terminating and the loop completed normally: forgive
++               * uncompleted cookies
++               */
++              schan->dma_chan.completed_cookie = schan->dma_chan.cookie;
++
++      spin_unlock_irqrestore(&schan->chan_lock, flags);
++
++      if (callback)
++              callback(param);
++
++      return callback;
++}
++
++/*
++ * shdma_chan_ld_cleanup - Clean up link descriptors
++ *
++ * Clean up the ld_queue of DMA channel.
++ */
++static void shdma_chan_ld_cleanup(struct shdma_chan *schan, bool all)
++{
++      while (__ld_cleanup(schan, all))
++              ;
++}
++
++/*
++ * shdma_free_chan_resources - Free all resources of the channel.
++ */
++static void shdma_free_chan_resources(struct dma_chan *chan)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++      struct shdma_dev *sdev = to_shdma_dev(chan->device);
++      const struct shdma_ops *ops = sdev->ops;
++      LIST_HEAD(list);
++
++      /* Protect against ISR */
++      spin_lock_irq(&schan->chan_lock);
++      ops->halt_channel(schan);
++      spin_unlock_irq(&schan->chan_lock);
++
++      /* Now no new interrupts will occur */
++
++      /* Prepared and not submitted descriptors can still be on the queue */
++      if (!list_empty(&schan->ld_queue))
++              shdma_chan_ld_cleanup(schan, true);
++
++      if (chan->private) {
++              /* The caller is holding dma_list_mutex */
++              struct shdma_slave *slave = chan->private;
++              clear_bit(slave->slave_id, shdma_slave_used);
++              chan->private = NULL;
++      }
++
++      spin_lock_irq(&schan->chan_lock);
++
++      list_splice_init(&schan->ld_free, &list);
++      schan->desc_num = 0;
++
++      spin_unlock_irq(&schan->chan_lock);
++
++      kfree(schan->desc);
++}
++
++/**
++ * shdma_add_desc - get, set up and return one transfer descriptor
++ * @schan:    DMA channel
++ * @flags:    DMA transfer flags
++ * @dst:      destination DMA address, incremented when direction equals
++ *            DMA_DEV_TO_MEM or DMA_MEM_TO_MEM
++ * @src:      source DMA address, incremented when direction equals
++ *            DMA_MEM_TO_DEV or DMA_MEM_TO_MEM
++ * @len:      DMA transfer length
++ * @first:    if NULL, set to the current descriptor and cookie set to -EBUSY
++ * @direction:        needed for slave DMA to decide which address to keep constant,
++ *            equals DMA_MEM_TO_MEM for MEMCPY
++ * Returns 0 or an error
++ * Locks: called with desc_lock held
++ */
++static struct shdma_desc *shdma_add_desc(struct shdma_chan *schan,
++      unsigned long flags, dma_addr_t *dst, dma_addr_t *src, size_t *len,
++      struct shdma_desc **first, enum dma_transfer_direction direction)
++{
++      struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
++      const struct shdma_ops *ops = sdev->ops;
++      struct shdma_desc *new;
++      size_t copy_size = *len;
++
++      if (!copy_size)
++              return NULL;
++
++      /* Allocate the link descriptor from the free list */
++      new = shdma_get_desc(schan);
++      if (!new) {
++              dev_err(schan->dev, "No free link descriptor available\n");
++              return NULL;
++      }
++
++      ops->desc_setup(schan, new, *src, *dst, &copy_size);
++
++      if (!*first) {
++              /* First desc */
++              new->async_tx.cookie = -EBUSY;
++              *first = new;
++      } else {
++              /* Other desc - invisible to the user */
++              new->async_tx.cookie = -EINVAL;
++      }
++
++      dev_dbg(schan->dev,
++              "chaining (%u/%u)@%x -> %x with %p, cookie %d\n",
++              copy_size, *len, *src, *dst, &new->async_tx,
++              new->async_tx.cookie);
++
++      new->mark = DESC_PREPARED;
++      new->async_tx.flags = flags;
++      new->direction = direction;
++
++      *len -= copy_size;
++      if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
++              *src += copy_size;
++      if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM)
++              *dst += copy_size;
++
++      return new;
++}
++
++/*
++ * shdma_prep_sg - prepare transfer descriptors from an SG list
++ *
++ * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also
++ * converted to scatter-gather to guarantee consistent locking and a correct
++ * list manipulation. For slave DMA direction carries the usual meaning, and,
++ * logically, the SG list is RAM and the addr variable contains slave address,
++ * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM
++ * and the SG list contains only one element and points at the source buffer.
++ */
++static struct dma_async_tx_descriptor *shdma_prep_sg(struct shdma_chan *schan,
++      struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
++      enum dma_transfer_direction direction, unsigned long flags)
++{
++      struct scatterlist *sg;
++      struct shdma_desc *first = NULL, *new = NULL /* compiler... */;
++      LIST_HEAD(tx_list);
++      int chunks = 0;
++      unsigned long irq_flags;
++      int i;
++
++      for_each_sg(sgl, sg, sg_len, i)
++              chunks += DIV_ROUND_UP(sg_dma_len(sg), schan->max_xfer_len);
++
++      /* Have to lock the whole loop to protect against concurrent release */
++      spin_lock_irqsave(&schan->chan_lock, irq_flags);
++
++      /*
++       * Chaining:
++       * first descriptor is what user is dealing with in all API calls, its
++       *      cookie is at first set to -EBUSY, at tx-submit to a positive
++       *      number
++       * if more than one chunk is needed further chunks have cookie = -EINVAL
++       * the last chunk, if not equal to the first, has cookie = -ENOSPC
++       * all chunks are linked onto the tx_list head with their .node heads
++       *      only during this function, then they are immediately spliced
++       *      back onto the free list in form of a chain
++       */
++      for_each_sg(sgl, sg, sg_len, i) {
++              dma_addr_t sg_addr = sg_dma_address(sg);
++              size_t len = sg_dma_len(sg);
++
++              if (!len)
++                      goto err_get_desc;
++
++              do {
++                      dev_dbg(schan->dev, "Add SG #%d@%p[%d], dma %llx\n",
++                              i, sg, len, (unsigned long long)sg_addr);
++
++                      if (direction == DMA_DEV_TO_MEM)
++                              new = shdma_add_desc(schan, flags,
++                                              &sg_addr, addr, &len, &first,
++                                              direction);
++                      else
++                              new = shdma_add_desc(schan, flags,
++                                              addr, &sg_addr, &len, &first,
++                                              direction);
++                      if (!new)
++                              goto err_get_desc;
++
++                      new->chunks = chunks--;
++                      list_add_tail(&new->node, &tx_list);
++              } while (len);
++      }
++
++      if (new != first)
++              new->async_tx.cookie = -ENOSPC;
++
++      /* Put them back on the free list, so, they don't get lost */
++      list_splice_tail(&tx_list, &schan->ld_free);
++
++      spin_unlock_irqrestore(&schan->chan_lock, irq_flags);
++
++      return &first->async_tx;
++
++err_get_desc:
++      list_for_each_entry(new, &tx_list, node)
++              new->mark = DESC_IDLE;
++      list_splice(&tx_list, &schan->ld_free);
++
++      spin_unlock_irqrestore(&schan->chan_lock, irq_flags);
++
++      return NULL;
++}
++
++static struct dma_async_tx_descriptor *shdma_prep_memcpy(
++      struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
++      size_t len, unsigned long flags)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++      struct scatterlist sg;
++
++      if (!chan || !len)
++              return NULL;
++
++      BUG_ON(!schan->desc_num);
++
++      sg_init_table(&sg, 1);
++      sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len,
++                  offset_in_page(dma_src));
++      sg_dma_address(&sg) = dma_src;
++      sg_dma_len(&sg) = len;
++
++      return shdma_prep_sg(schan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM, flags);
++}
++
++static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
++      struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
++      enum dma_transfer_direction direction, unsigned long flags, void *context)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++      struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
++      const struct shdma_ops *ops = sdev->ops;
++      struct shdma_slave *slave = chan->private;
++      dma_addr_t slave_addr;
++
++      if (!chan)
++              return NULL;
++
++      BUG_ON(!schan->desc_num);
++
++      /* Someone calling slave DMA on a generic channel? */
++      if (!slave || !sg_len) {
++              dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n",
++                       __func__, slave, sg_len, slave ? slave->slave_id : -1);
++              return NULL;
++      }
++
++      slave_addr = ops->slave_addr(schan);
++
++      return shdma_prep_sg(schan, sgl, sg_len, &slave_addr,
++                            direction, flags);
++}
++
++static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
++                        unsigned long arg)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++      struct shdma_dev *sdev = to_shdma_dev(chan->device);
++      const struct shdma_ops *ops = sdev->ops;
++      unsigned long flags;
++
++      /* Only supports DMA_TERMINATE_ALL */
++      if (cmd != DMA_TERMINATE_ALL)
++              return -ENXIO;
++
++      if (!chan)
++              return -EINVAL;
++
++      spin_lock_irqsave(&schan->chan_lock, flags);
++
++      ops->halt_channel(schan);
++
++      spin_unlock_irqrestore(&schan->chan_lock, flags);
++
++      shdma_chan_ld_cleanup(schan, true);
++
++      return 0;
++}
++
++static void shdma_issue_pending(struct dma_chan *chan)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++
++      spin_lock_irq(&schan->chan_lock);
++      if (schan->pm_state == SHDMA_PM_ESTABLISHED)
++              shdma_chan_xfer_ld_queue(schan);
++      else
++              schan->pm_state = SHDMA_PM_PENDING;
++      spin_unlock_irq(&schan->chan_lock);
++}
++
++static enum dma_status shdma_tx_status(struct dma_chan *chan,
++                                      dma_cookie_t cookie,
++                                      struct dma_tx_state *txstate)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++      enum dma_status status;
++      unsigned long flags;
++
++      shdma_chan_ld_cleanup(schan, false);
++
++      spin_lock_irqsave(&schan->chan_lock, flags);
++
++      status = dma_cookie_status(chan, cookie, txstate);
++
++      /*
++       * If we don't find cookie on the queue, it has been aborted and we have
++       * to report error
++       */
++      if (status != DMA_SUCCESS) {
++              struct shdma_desc *sdesc;
++              status = DMA_ERROR;
++              list_for_each_entry(sdesc, &schan->ld_queue, node)
++                      if (sdesc->cookie == cookie) {
++                              status = DMA_IN_PROGRESS;
++                              break;
++                      }
++      }
++
++      spin_unlock_irqrestore(&schan->chan_lock, flags);
++
++      return status;
++}
++
++/* Called from error IRQ or NMI */
++bool shdma_reset(struct shdma_dev *sdev)
++{
++      const struct shdma_ops *ops = sdev->ops;
++      struct shdma_chan *schan;
++      unsigned int handled = 0;
++      int i;
++
++      /* Reset all channels */
++      shdma_for_each_chan(schan, sdev, i) {
++              struct shdma_desc *sdesc;
++              LIST_HEAD(dl);
++
++              if (!schan)
++                      continue;
++
++              spin_lock(&schan->chan_lock);
++
++              /* Stop the channel */
++              ops->halt_channel(schan);
++
++              list_splice_init(&schan->ld_queue, &dl);
++
++              if (!list_empty(&dl)) {
++                      dev_dbg(schan->dev, "Bring down channel %d\n", schan->id);
++                      pm_runtime_put(schan->dev);
++              }
++              schan->pm_state = SHDMA_PM_ESTABLISHED;
++
++              spin_unlock(&schan->chan_lock);
++
++              /* Complete all  */
++              list_for_each_entry(sdesc, &dl, node) {
++                      struct dma_async_tx_descriptor *tx = &sdesc->async_tx;
++                      sdesc->mark = DESC_IDLE;
++                      if (tx->callback)
++                              tx->callback(tx->callback_param);
++              }
++
++              spin_lock(&schan->chan_lock);
++              list_splice(&dl, &schan->ld_free);
++              spin_unlock(&schan->chan_lock);
++
++              handled++;
++      }
++
++      return !!handled;
++}
++EXPORT_SYMBOL(shdma_reset);
++
++static irqreturn_t chan_irq(int irq, void *dev)
++{
++      struct shdma_chan *schan = dev;
++      const struct shdma_ops *ops =
++              to_shdma_dev(schan->dma_chan.device)->ops;
++      irqreturn_t ret;
++
++      spin_lock(&schan->chan_lock);
++
++      ret = ops->chan_irq(schan, irq) ? IRQ_WAKE_THREAD : IRQ_NONE;
++
++      spin_unlock(&schan->chan_lock);
++
++      return ret;
++}
++
++static irqreturn_t chan_irqt(int irq, void *dev)
++{
++      struct shdma_chan *schan = dev;
++      const struct shdma_ops *ops =
++              to_shdma_dev(schan->dma_chan.device)->ops;
++      struct shdma_desc *sdesc;
++
++      spin_lock_irq(&schan->chan_lock);
++      list_for_each_entry(sdesc, &schan->ld_queue, node) {
++              if (sdesc->mark == DESC_SUBMITTED &&
++                  ops->desc_completed(schan, sdesc)) {
++                      dev_dbg(schan->dev, "done #%d@%p\n",
++                              sdesc->async_tx.cookie, &sdesc->async_tx);
++                      sdesc->mark = DESC_COMPLETED;
++                      break;
++              }
++      }
++      /* Next desc */
++      shdma_chan_xfer_ld_queue(schan);
++      spin_unlock_irq(&schan->chan_lock);
++
++      shdma_chan_ld_cleanup(schan, false);
++
++      return IRQ_HANDLED;
++}
++
++int shdma_request_irq(struct shdma_chan *schan, int irq,
++                         unsigned long flags, const char *name)
++{
++      int ret = request_threaded_irq(irq, chan_irq, chan_irqt,
++                                     flags, name, schan);
++
++      schan->irq = ret < 0 ? ret : irq;
++
++      return ret;
++}
++EXPORT_SYMBOL(shdma_request_irq);
++
++void shdma_free_irq(struct shdma_chan *schan)
++{
++      if (schan->irq >= 0)
++              free_irq(schan->irq, schan);
++}
++EXPORT_SYMBOL(shdma_free_irq);
++
++void shdma_chan_probe(struct shdma_dev *sdev,
++                         struct shdma_chan *schan, int id)
++{
++      schan->pm_state = SHDMA_PM_ESTABLISHED;
++
++      /* reference struct dma_device */
++      schan->dma_chan.device = &sdev->dma_dev;
++      dma_cookie_init(&schan->dma_chan);
++
++      schan->dev = sdev->dma_dev.dev;
++      schan->id = id;
++
++      if (!schan->max_xfer_len)
++              schan->max_xfer_len = PAGE_SIZE;
++
++      spin_lock_init(&schan->chan_lock);
++
++      /* Init descripter manage list */
++      INIT_LIST_HEAD(&schan->ld_queue);
++      INIT_LIST_HEAD(&schan->ld_free);
++
++      /* Add the channel to DMA device channel list */
++      list_add_tail(&schan->dma_chan.device_node,
++                      &sdev->dma_dev.channels);
++      sdev->schan[sdev->dma_dev.chancnt++] = schan;
++}
++EXPORT_SYMBOL(shdma_chan_probe);
++
++void shdma_chan_remove(struct shdma_chan *schan)
++{
++      list_del(&schan->dma_chan.device_node);
++}
++EXPORT_SYMBOL(shdma_chan_remove);
++
++int shdma_init(struct device *dev, struct shdma_dev *sdev,
++                  int chan_num)
++{
++      struct dma_device *dma_dev = &sdev->dma_dev;
++
++      /*
++       * Require all call-backs for now, they can trivially be made optional
++       * later as required
++       */
++      if (!sdev->ops ||
++          !sdev->desc_size ||
++          !sdev->ops->embedded_desc ||
++          !sdev->ops->start_xfer ||
++          !sdev->ops->setup_xfer ||
++          !sdev->ops->set_slave ||
++          !sdev->ops->desc_setup ||
++          !sdev->ops->slave_addr ||
++          !sdev->ops->channel_busy ||
++          !sdev->ops->halt_channel ||
++          !sdev->ops->desc_completed)
++              return -EINVAL;
++
++      sdev->schan = kcalloc(chan_num, sizeof(*sdev->schan), GFP_KERNEL);
++      if (!sdev->schan)
++              return -ENOMEM;
++
++      INIT_LIST_HEAD(&dma_dev->channels);
++
++      /* Common and MEMCPY operations */
++      dma_dev->device_alloc_chan_resources
++              = shdma_alloc_chan_resources;
++      dma_dev->device_free_chan_resources = shdma_free_chan_resources;
++      dma_dev->device_prep_dma_memcpy = shdma_prep_memcpy;
++      dma_dev->device_tx_status = shdma_tx_status;
++      dma_dev->device_issue_pending = shdma_issue_pending;
++
++      /* Compulsory for DMA_SLAVE fields */
++      dma_dev->device_prep_slave_sg = shdma_prep_slave_sg;
++      dma_dev->device_control = shdma_control;
++
++      dma_dev->dev = dev;
++
++      return 0;
++}
++EXPORT_SYMBOL(shdma_init);
++
++void shdma_cleanup(struct shdma_dev *sdev)
++{
++      kfree(sdev->schan);
++}
++EXPORT_SYMBOL(shdma_cleanup);
++
++static int __init shdma_enter(void)
++{
++      shdma_slave_used = kzalloc(DIV_ROUND_UP(slave_num, BITS_PER_LONG) *
++                                  sizeof(long), GFP_KERNEL);
++      if (!shdma_slave_used)
++              return -ENOMEM;
++      return 0;
++}
++module_init(shdma_enter);
++
++static void __exit shdma_exit(void)
++{
++      kfree(shdma_slave_used);
++}
++module_exit(shdma_exit);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("SH-DMA driver base library");
++MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
+new file mode 100644
+index 0000000..83efd13
+--- /dev/null
++++ b/include/linux/shdma-base.h
+@@ -0,0 +1,123 @@
++/*
++ * Dmaengine driver base library for DMA controllers, found on SH-based SoCs
++ *
++ * extracted from shdma.c and headers
++ *
++ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
++ * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
++ * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
++ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of version 2 of the GNU General Public License as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef SHDMA_BASE_H
++#define SHDMA_BASE_H
++
++#include <linux/dmaengine.h>
++#include <linux/interrupt.h>
++#include <linux/list.h>
++#include <linux/types.h>
++
++/**
++ * shdma_pm_state - DMA channel PM state
++ * SHDMA_PM_ESTABLISHED:      either idle or during data transfer
++ * SHDMA_PM_BUSY:             during the transfer preparation, when we have to
++ *                            drop the lock temporarily
++ * SHDMA_PM_PENDING:  transfers pending
++ */
++enum shdma_pm_state {
++      SHDMA_PM_ESTABLISHED,
++      SHDMA_PM_BUSY,
++      SHDMA_PM_PENDING,
++};
++
++struct device;
++
++/*
++ * Drivers, using this library are expected to embed struct shdma_dev,
++ * struct shdma_chan, struct shdma_desc, and struct shdma_slave
++ * in their respective device, channel, descriptor and slave objects.
++ */
++
++struct shdma_slave {
++      unsigned int slave_id;
++};
++
++struct shdma_desc {
++      struct list_head node;
++      struct dma_async_tx_descriptor async_tx;
++      enum dma_transfer_direction direction;
++      dma_cookie_t cookie;
++      int chunks;
++      int mark;
++};
++
++struct shdma_chan {
++      spinlock_t chan_lock;           /* Channel operation lock */
++      struct list_head ld_queue;      /* Link descriptors queue */
++      struct list_head ld_free;       /* Free link descriptors */
++      struct dma_chan dma_chan;       /* DMA channel */
++      struct device *dev;             /* Channel device */
++      void *desc;                     /* buffer for descriptor array */
++      int desc_num;                   /* desc count */
++      size_t max_xfer_len;            /* max transfer length */
++      int id;                         /* Raw id of this channel */
++      int irq;                        /* Channel IRQ */
++      enum shdma_pm_state pm_state;
++};
++
++/**
++ * struct shdma_ops - simple DMA driver operations
++ * desc_completed:    return true, if this is the descriptor, that just has
++ *                    completed (atomic)
++ * halt_channel:      stop DMA channel operation (atomic)
++ * channel_busy:      return true, if the channel is busy (atomic)
++ * slave_addr:                return slave DMA address
++ * desc_setup:                set up the hardware specific descriptor portion (atomic)
++ * set_slave:         bind channel to a slave
++ * setup_xfer:                configure channel hardware for operation (atomic)
++ * start_xfer:                start the DMA transfer (atomic)
++ * embedded_desc:     return Nth struct shdma_desc pointer from the
++ *                    descriptor array
++ * chan_irq:          process channel IRQ, return true if a transfer has
++ *                    completed (atomic)
++ */
++struct shdma_ops {
++      bool (*desc_completed)(struct shdma_chan *, struct shdma_desc *);
++      void (*halt_channel)(struct shdma_chan *);
++      bool (*channel_busy)(struct shdma_chan *);
++      dma_addr_t (*slave_addr)(struct shdma_chan *);
++      int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
++                        dma_addr_t, dma_addr_t, size_t *);
++      int (*set_slave)(struct shdma_chan *, struct shdma_slave *);
++      void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *);
++      void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
++      struct shdma_desc *(*embedded_desc)(void *, int);
++      bool (*chan_irq)(struct shdma_chan *, int);
++};
++
++struct shdma_dev {
++      struct dma_device dma_dev;
++      struct shdma_chan **schan;
++      const struct shdma_ops *ops;
++      size_t desc_size;
++};
++
++#define shdma_for_each_chan(c, d, i) for (i = 0, c = (d)->schan[0]; \
++                              i < (d)->dma_dev.chancnt; c = (d)->schan[++i])
++
++int shdma_request_irq(struct shdma_chan *, int,
++                         unsigned long, const char *);
++void shdma_free_irq(struct shdma_chan *);
++bool shdma_reset(struct shdma_dev *sdev);
++void shdma_chan_probe(struct shdma_dev *sdev,
++                         struct shdma_chan *schan, int id);
++void shdma_chan_remove(struct shdma_chan *schan);
++int shdma_init(struct device *dev, struct shdma_dev *sdev,
++                  int chan_num);
++void shdma_cleanup(struct shdma_dev *sdev);
++
++#endif
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch b/patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch
new file mode 100644 (file)
index 0000000..c035e94
--- /dev/null
@@ -0,0 +1,44 @@
+From ede599a5d672322a39cf12cc4fdb59fe67898908 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:14 +0200
+Subject: dma: shdma: prepare for conversion to the shdma base library
+
+By placing an anonymous union at the top of struct sh_dmae_slave we can
+transparently prepare all device and client drivers for the upcoming
+shdma-base conversion.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 5902c9a7a2a9c2520af54af1ba7a9c7831664a17)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/sh_dma.h | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
+index 425450b..e081e8e 100644
+--- a/include/linux/sh_dma.h
++++ b/include/linux/sh_dma.h
+@@ -10,12 +10,16 @@
+ #ifndef SH_DMA_H
+ #define SH_DMA_H
+-#include <linux/list.h>
+ #include <linux/dmaengine.h>
++#include <linux/list.h>
++#include <linux/shdma-base.h>
+ /* Used by slave DMA clients to request DMA to/from a specific peripheral */
+ struct sh_dmae_slave {
+-      unsigned int                    slave_id; /* Set by the platform */
++      union {
++              unsigned int            slave_id; /* Set by the platform */
++              struct shdma_slave      shdma_slave;
++      };
+       struct device                   *dma_dev; /* Set by the platform */
+       const struct sh_dmae_slave_config       *config;  /* Set by the driver */
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch b/patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch
new file mode 100644 (file)
index 0000000..bba8d95
--- /dev/null
@@ -0,0 +1,30 @@
+From 6381d33c361574132c3152d0cfa56278a67d40f7 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:20 +0200
+Subject: ASoC: fsi: prepare for conversion to the shdma base library
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Liam Girdwood <lrg@ti.com>
+Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit b8373147ed3ca01a968d81f22688f2836a9aeb6b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ sound/soc/sh/fsi.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/sh/fsi.c
++++ b/sound/soc/sh/fsi.c
+@@ -1533,8 +1533,8 @@ static void fsi_handler_init(struct fsi_
+       fsi->capture.priv       = fsi;
+       if (fsi->info->tx_id) {
+-              fsi->playback.slave.slave_id    = fsi->info->tx_id;
+-              fsi->playback.handler           = &fsi_dma_push_handler;
++              fsi->playback.slave.shdma_slave.slave_id = fsi->info->tx_id;
++              fsi->playback.handler = &fsi_dma_push_handler;
+       }
+ }
diff --git a/patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch b/patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch
new file mode 100644 (file)
index 0000000..4a3b49d
--- /dev/null
@@ -0,0 +1,55 @@
+From a840c360c6d890060307ee970d8630f9bf812af1 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:19 +0200
+Subject: usb: renesas_usbhs: prepare for conversion to the shdma base library
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit f19b7e0db7744dd1ed6052cc58a90b74a29772b8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/usb/renesas_usbhs/fifo.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
+index 6ec7f83..fc597a4 100644
+--- a/drivers/usb/renesas_usbhs/fifo.c
++++ b/drivers/usb/renesas_usbhs/fifo.c
+@@ -994,7 +994,7 @@ static bool usbhsf_dma_filter(struct dma_chan *chan, void *param)
+        *
+        * usbhs doesn't recognize id = 0 as valid DMA
+        */
+-      if (0 == slave->slave_id)
++      if (0 == slave->shdma_slave.slave_id)
+               return false;
+       chan->private = slave;
+@@ -1173,8 +1173,8 @@ int usbhs_fifo_probe(struct usbhs_priv *priv)
+       fifo->port      = D0FIFO;
+       fifo->sel       = D0FIFOSEL;
+       fifo->ctr       = D0FIFOCTR;
+-      fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id);
+-      fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id);
++      fifo->tx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d0_tx_id);
++      fifo->rx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d0_rx_id);
+       /* D1FIFO */
+       fifo = usbhsf_get_d1fifo(priv);
+@@ -1182,8 +1182,8 @@ int usbhs_fifo_probe(struct usbhs_priv *priv)
+       fifo->port      = D1FIFO;
+       fifo->sel       = D1FIFOSEL;
+       fifo->ctr       = D1FIFOCTR;
+-      fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id);
+-      fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id);
++      fifo->tx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d1_tx_id);
++      fifo->rx_slave.shdma_slave.slave_id     = usbhs_get_dparam(priv, d1_rx_id);
+       return 0;
+ }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch b/patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch
new file mode 100644 (file)
index 0000000..674d548
--- /dev/null
@@ -0,0 +1,1561 @@
+From 67976cd109fc26028e9fbcede6badbf236d865e8 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:21 +0200
+Subject: dma: shdma: convert to the shdma base library
+
+The shdma base library has originally been extracted from the shdma driver,
+which now can be converted to actually use it.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit ce3a1ab74264b860450709e4bd0dcfc2d0bfc7f8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/sh/shdma.c | 1122 ++++++++++++------------------------------------
+ drivers/dma/sh/shdma.h |   44 +-
+ include/linux/sh_dma.h |   33 +-
+ 3 files changed, 302 insertions(+), 897 deletions(-)
+
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index 8ab4a1f..c393b35 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -3,6 +3,7 @@
+  *
+  * base is drivers/dma/flsdma.c
+  *
++ * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+  * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
+  * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
+  * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+@@ -34,18 +35,12 @@
+ #include "../dmaengine.h"
+ #include "shdma.h"
+-/* DMA descriptor control */
+-enum sh_dmae_desc_status {
+-      DESC_IDLE,
+-      DESC_PREPARED,
+-      DESC_SUBMITTED,
+-      DESC_COMPLETED, /* completed, have to call callback */
+-      DESC_WAITING,   /* callback called, waiting for ack / re-submit */
+-};
++#define SH_DMAE_DRV_NAME "sh-dma-engine"
+-#define NR_DESCS_PER_CHANNEL 32
+ /* Default MEMCPY transfer size = 2^2 = 4 bytes */
+ #define LOG2_DEFAULT_XFER_SIZE        2
++#define SH_DMA_SLAVE_NUMBER 256
++#define SH_DMA_TCR_MAX (16 * 1024 * 1024 - 1)
+ /*
+  * Used for write-side mutual exclusion for the global device list,
+@@ -54,18 +49,12 @@ enum sh_dmae_desc_status {
+ static DEFINE_SPINLOCK(sh_dmae_lock);
+ static LIST_HEAD(sh_dmae_devices);
+-/* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
+-static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
+-
+-static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
+-static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
+-
+ static void chclr_write(struct sh_dmae_chan *sh_dc, u32 data)
+ {
+       struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+       __raw_writel(data, shdev->chan_reg +
+-                   shdev->pdata->channel[sh_dc->id].chclr_offset);
++                   shdev->pdata->channel[sh_dc->shdma_chan.id].chclr_offset);
+ }
+ static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
+@@ -155,11 +144,11 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
+       spin_unlock_irqrestore(&sh_dmae_lock, flags);
+       if (dmaor & (DMAOR_AE | DMAOR_NMIF)) {
+-              dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n");
++              dev_warn(shdev->shdma_dev.dma_dev.dev, "Can't initialize DMAOR.\n");
+               return -EIO;
+       }
+       if (shdev->pdata->dmaor_init & ~dmaor)
+-              dev_warn(shdev->common.dev,
++              dev_warn(shdev->shdma_dev.dma_dev.dev,
+                        "DMAOR=0x%x hasn't latched the initial value 0x%x.\n",
+                        dmaor, shdev->pdata->dmaor_init);
+       return 0;
+@@ -224,15 +213,6 @@ static void dmae_start(struct sh_dmae_chan *sh_chan)
+       chcr_write(sh_chan, chcr & ~CHCR_TE);
+ }
+-static void dmae_halt(struct sh_dmae_chan *sh_chan)
+-{
+-      struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+-      u32 chcr = chcr_read(sh_chan);
+-
+-      chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit);
+-      chcr_write(sh_chan, chcr);
+-}
+-
+ static void dmae_init(struct sh_dmae_chan *sh_chan)
+ {
+       /*
+@@ -261,7 +241,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
+ {
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+       struct sh_dmae_pdata *pdata = shdev->pdata;
+-      const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
++      const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->shdma_chan.id];
+       u16 __iomem *addr = shdev->dmars;
+       unsigned int shift = chan_pdata->dmars_bit;
+@@ -282,706 +262,142 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
+       return 0;
+ }
+-static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
++static void sh_dmae_start_xfer(struct shdma_chan *schan,
++                             struct shdma_desc *sdesc)
+ {
+-      struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
+-      struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan);
+-      struct sh_dmae_slave *param = tx->chan->private;
+-      dma_async_tx_callback callback = tx->callback;
+-      dma_cookie_t cookie;
+-      bool power_up;
+-
+-      spin_lock_irq(&sh_chan->desc_lock);
+-
+-      if (list_empty(&sh_chan->ld_queue))
+-              power_up = true;
+-      else
+-              power_up = false;
+-
+-      cookie = dma_cookie_assign(tx);
+-
+-      /* Mark all chunks of this descriptor as submitted, move to the queue */
+-      list_for_each_entry_safe(chunk, c, desc->node.prev, node) {
+-              /*
+-               * All chunks are on the global ld_free, so, we have to find
+-               * the end of the chain ourselves
+-               */
+-              if (chunk != desc && (chunk->mark == DESC_IDLE ||
+-                                    chunk->async_tx.cookie > 0 ||
+-                                    chunk->async_tx.cookie == -EBUSY ||
+-                                    &chunk->node == &sh_chan->ld_free))
+-                      break;
+-              chunk->mark = DESC_SUBMITTED;
+-              /* Callback goes to the last chunk */
+-              chunk->async_tx.callback = NULL;
+-              chunk->cookie = cookie;
+-              list_move_tail(&chunk->node, &sh_chan->ld_queue);
+-              last = chunk;
+-      }
+-
+-      last->async_tx.callback = callback;
+-      last->async_tx.callback_param = tx->callback_param;
+-
+-      dev_dbg(sh_chan->dev, "submit #%d@%p on %d: %x[%d] -> %x\n",
+-              tx->cookie, &last->async_tx, sh_chan->id,
+-              desc->hw.sar, desc->hw.tcr, desc->hw.dar);
+-
+-      if (power_up) {
+-              sh_chan->pm_state = DMAE_PM_BUSY;
+-
+-              pm_runtime_get(sh_chan->dev);
+-
+-              spin_unlock_irq(&sh_chan->desc_lock);
+-
+-              pm_runtime_barrier(sh_chan->dev);
+-
+-              spin_lock_irq(&sh_chan->desc_lock);
+-
+-              /* Have we been reset, while waiting? */
+-              if (sh_chan->pm_state != DMAE_PM_ESTABLISHED) {
+-                      dev_dbg(sh_chan->dev, "Bring up channel %d\n",
+-                              sh_chan->id);
+-                      if (param) {
+-                              const struct sh_dmae_slave_config *cfg =
+-                                      param->config;
+-
+-                              dmae_set_dmars(sh_chan, cfg->mid_rid);
+-                              dmae_set_chcr(sh_chan, cfg->chcr);
+-                      } else {
+-                              dmae_init(sh_chan);
+-                      }
+-
+-                      if (sh_chan->pm_state == DMAE_PM_PENDING)
+-                              sh_chan_xfer_ld_queue(sh_chan);
+-                      sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+-              }
+-      } else {
+-              sh_chan->pm_state = DMAE_PM_PENDING;
+-      }
+-
+-      spin_unlock_irq(&sh_chan->desc_lock);
+-
+-      return cookie;
++      struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
++                                                  shdma_chan);
++      struct sh_dmae_desc *sh_desc = container_of(sdesc,
++                                      struct sh_dmae_desc, shdma_desc);
++      dev_dbg(sh_chan->shdma_chan.dev, "Queue #%d to %d: %u@%x -> %x\n",
++              sdesc->async_tx.cookie, sh_chan->shdma_chan.id,
++              sh_desc->hw.tcr, sh_desc->hw.sar, sh_desc->hw.dar);
++      /* Get the ld start address from ld_queue */
++      dmae_set_reg(sh_chan, &sh_desc->hw);
++      dmae_start(sh_chan);
+ }
+-/* Called with desc_lock held */
+-static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan)
++static bool sh_dmae_channel_busy(struct shdma_chan *schan)
+ {
+-      struct sh_desc *desc;
+-
+-      list_for_each_entry(desc, &sh_chan->ld_free, node)
+-              if (desc->mark != DESC_PREPARED) {
+-                      BUG_ON(desc->mark != DESC_IDLE);
+-                      list_del(&desc->node);
+-                      return desc;
+-              }
+-
+-      return NULL;
++      struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
++                                                  shdma_chan);
++      return dmae_is_busy(sh_chan);
+ }
+-static const struct sh_dmae_slave_config *sh_dmae_find_slave(
+-      struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param)
++static void sh_dmae_setup_xfer(struct shdma_chan *schan,
++                             struct shdma_slave *sslave)
+ {
+-      struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+-      struct sh_dmae_pdata *pdata = shdev->pdata;
+-      int i;
++      struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
++                                                  shdma_chan);
+-      if (param->slave_id >= SH_DMA_SLAVE_NUMBER)
+-              return NULL;
+-
+-      for (i = 0; i < pdata->slave_num; i++)
+-              if (pdata->slave[i].slave_id == param->slave_id)
+-                      return pdata->slave + i;
+-
+-      return NULL;
+-}
+-
+-static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
+-{
+-      struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+-      struct sh_desc *desc;
+-      struct sh_dmae_slave *param = chan->private;
+-      int ret;
++      if (sslave) {
++              struct sh_dmae_slave *slave = container_of(sslave,
++                                      struct sh_dmae_slave, shdma_slave);
++              const struct sh_dmae_slave_config *cfg =
++                      slave->config;
+-      /*
+-       * This relies on the guarantee from dmaengine that alloc_chan_resources
+-       * never runs concurrently with itself or free_chan_resources.
+-       */
+-      if (param) {
+-              const struct sh_dmae_slave_config *cfg;
+-
+-              cfg = sh_dmae_find_slave(sh_chan, param);
+-              if (!cfg) {
+-                      ret = -EINVAL;
+-                      goto efindslave;
+-              }
+-
+-              if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) {
+-                      ret = -EBUSY;
+-                      goto etestused;
+-              }
+-
+-              param->config = cfg;
+-      }
+-
+-      while (sh_chan->descs_allocated < NR_DESCS_PER_CHANNEL) {
+-              desc = kzalloc(sizeof(struct sh_desc), GFP_KERNEL);
+-              if (!desc)
+-                      break;
+-              dma_async_tx_descriptor_init(&desc->async_tx,
+-                                      &sh_chan->common);
+-              desc->async_tx.tx_submit = sh_dmae_tx_submit;
+-              desc->mark = DESC_IDLE;
+-
+-              list_add(&desc->node, &sh_chan->ld_free);
+-              sh_chan->descs_allocated++;
+-      }
+-
+-      if (!sh_chan->descs_allocated) {
+-              ret = -ENOMEM;
+-              goto edescalloc;
+-      }
+-
+-      return sh_chan->descs_allocated;
+-
+-edescalloc:
+-      if (param)
+-              clear_bit(param->slave_id, sh_dmae_slave_used);
+-etestused:
+-efindslave:
+-      chan->private = NULL;
+-      return ret;
+-}
+-
+-/*
+- * sh_dma_free_chan_resources - Free all resources of the channel.
+- */
+-static void sh_dmae_free_chan_resources(struct dma_chan *chan)
+-{
+-      struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+-      struct sh_desc *desc, *_desc;
+-      LIST_HEAD(list);
+-
+-      /* Protect against ISR */
+-      spin_lock_irq(&sh_chan->desc_lock);
+-      dmae_halt(sh_chan);
+-      spin_unlock_irq(&sh_chan->desc_lock);
+-
+-      /* Now no new interrupts will occur */
+-
+-      /* Prepared and not submitted descriptors can still be on the queue */
+-      if (!list_empty(&sh_chan->ld_queue))
+-              sh_dmae_chan_ld_cleanup(sh_chan, true);
+-
+-      if (chan->private) {
+-              /* The caller is holding dma_list_mutex */
+-              struct sh_dmae_slave *param = chan->private;
+-              clear_bit(param->slave_id, sh_dmae_slave_used);
+-              chan->private = NULL;
+-      }
+-
+-      spin_lock_irq(&sh_chan->desc_lock);
+-
+-      list_splice_init(&sh_chan->ld_free, &list);
+-      sh_chan->descs_allocated = 0;
+-
+-      spin_unlock_irq(&sh_chan->desc_lock);
+-
+-      list_for_each_entry_safe(desc, _desc, &list, node)
+-              kfree(desc);
+-}
+-
+-/**
+- * sh_dmae_add_desc - get, set up and return one transfer descriptor
+- * @sh_chan:  DMA channel
+- * @flags:    DMA transfer flags
+- * @dest:     destination DMA address, incremented when direction equals
+- *            DMA_DEV_TO_MEM
+- * @src:      source DMA address, incremented when direction equals
+- *            DMA_MEM_TO_DEV
+- * @len:      DMA transfer length
+- * @first:    if NULL, set to the current descriptor and cookie set to -EBUSY
+- * @direction:        needed for slave DMA to decide which address to keep constant,
+- *            equals DMA_MEM_TO_MEM for MEMCPY
+- * Returns 0 or an error
+- * Locks: called with desc_lock held
+- */
+-static struct sh_desc *sh_dmae_add_desc(struct sh_dmae_chan *sh_chan,
+-      unsigned long flags, dma_addr_t *dest, dma_addr_t *src, size_t *len,
+-      struct sh_desc **first, enum dma_transfer_direction direction)
+-{
+-      struct sh_desc *new;
+-      size_t copy_size;
+-
+-      if (!*len)
+-              return NULL;
+-
+-      /* Allocate the link descriptor from the free list */
+-      new = sh_dmae_get_desc(sh_chan);
+-      if (!new) {
+-              dev_err(sh_chan->dev, "No free link descriptor available\n");
+-              return NULL;
+-      }
+-
+-      copy_size = min(*len, (size_t)SH_DMA_TCR_MAX + 1);
+-
+-      new->hw.sar = *src;
+-      new->hw.dar = *dest;
+-      new->hw.tcr = copy_size;
+-
+-      if (!*first) {
+-              /* First desc */
+-              new->async_tx.cookie = -EBUSY;
+-              *first = new;
++              dmae_set_dmars(sh_chan, cfg->mid_rid);
++              dmae_set_chcr(sh_chan, cfg->chcr);
+       } else {
+-              /* Other desc - invisible to the user */
+-              new->async_tx.cookie = -EINVAL;
++              dmae_init(sh_chan);
+       }
+-
+-      dev_dbg(sh_chan->dev,
+-              "chaining (%u/%u)@%x -> %x with %p, cookie %d, shift %d\n",
+-              copy_size, *len, *src, *dest, &new->async_tx,
+-              new->async_tx.cookie, sh_chan->xmit_shift);
+-
+-      new->mark = DESC_PREPARED;
+-      new->async_tx.flags = flags;
+-      new->direction = direction;
+-
+-      *len -= copy_size;
+-      if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
+-              *src += copy_size;
+-      if (direction == DMA_MEM_TO_MEM || direction == DMA_DEV_TO_MEM)
+-              *dest += copy_size;
+-
+-      return new;
+ }
+-/*
+- * sh_dmae_prep_sg - prepare transfer descriptors from an SG list
+- *
+- * Common routine for public (MEMCPY) and slave DMA. The MEMCPY case is also
+- * converted to scatter-gather to guarantee consistent locking and a correct
+- * list manipulation. For slave DMA direction carries the usual meaning, and,
+- * logically, the SG list is RAM and the addr variable contains slave address,
+- * e.g., the FIFO I/O register. For MEMCPY direction equals DMA_MEM_TO_MEM
+- * and the SG list contains only one element and points at the source buffer.
+- */
+-static struct dma_async_tx_descriptor *sh_dmae_prep_sg(struct sh_dmae_chan *sh_chan,
+-      struct scatterlist *sgl, unsigned int sg_len, dma_addr_t *addr,
+-      enum dma_transfer_direction direction, unsigned long flags)
++static const struct sh_dmae_slave_config *dmae_find_slave(
++      struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *slave)
+ {
+-      struct scatterlist *sg;
+-      struct sh_desc *first = NULL, *new = NULL /* compiler... */;
+-      LIST_HEAD(tx_list);
+-      int chunks = 0;
+-      unsigned long irq_flags;
++      struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
++      struct sh_dmae_pdata *pdata = shdev->pdata;
++      const struct sh_dmae_slave_config *cfg;
+       int i;
+-      if (!sg_len)
++      if (slave->shdma_slave.slave_id >= SH_DMA_SLAVE_NUMBER)
+               return NULL;
+-      for_each_sg(sgl, sg, sg_len, i)
+-              chunks += (sg_dma_len(sg) + SH_DMA_TCR_MAX) /
+-                      (SH_DMA_TCR_MAX + 1);
+-
+-      /* Have to lock the whole loop to protect against concurrent release */
+-      spin_lock_irqsave(&sh_chan->desc_lock, irq_flags);
+-
+-      /*
+-       * Chaining:
+-       * first descriptor is what user is dealing with in all API calls, its
+-       *      cookie is at first set to -EBUSY, at tx-submit to a positive
+-       *      number
+-       * if more than one chunk is needed further chunks have cookie = -EINVAL
+-       * the last chunk, if not equal to the first, has cookie = -ENOSPC
+-       * all chunks are linked onto the tx_list head with their .node heads
+-       *      only during this function, then they are immediately spliced
+-       *      back onto the free list in form of a chain
+-       */
+-      for_each_sg(sgl, sg, sg_len, i) {
+-              dma_addr_t sg_addr = sg_dma_address(sg);
+-              size_t len = sg_dma_len(sg);
+-
+-              if (!len)
+-                      goto err_get_desc;
+-
+-              do {
+-                      dev_dbg(sh_chan->dev, "Add SG #%d@%p[%d], dma %llx\n",
+-                              i, sg, len, (unsigned long long)sg_addr);
+-
+-                      if (direction == DMA_DEV_TO_MEM)
+-                              new = sh_dmae_add_desc(sh_chan, flags,
+-                                              &sg_addr, addr, &len, &first,
+-                                              direction);
+-                      else
+-                              new = sh_dmae_add_desc(sh_chan, flags,
+-                                              addr, &sg_addr, &len, &first,
+-                                              direction);
+-                      if (!new)
+-                              goto err_get_desc;
+-
+-                      new->chunks = chunks--;
+-                      list_add_tail(&new->node, &tx_list);
+-              } while (len);
+-      }
+-
+-      if (new != first)
+-              new->async_tx.cookie = -ENOSPC;
+-
+-      /* Put them back on the free list, so, they don't get lost */
+-      list_splice_tail(&tx_list, &sh_chan->ld_free);
+-
+-      spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
+-
+-      return &first->async_tx;
+-
+-err_get_desc:
+-      list_for_each_entry(new, &tx_list, node)
+-              new->mark = DESC_IDLE;
+-      list_splice(&tx_list, &sh_chan->ld_free);
+-
+-      spin_unlock_irqrestore(&sh_chan->desc_lock, irq_flags);
++      for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
++              if (cfg->slave_id == slave->shdma_slave.slave_id)
++                      return cfg;
+       return NULL;
+ }
+-static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy(
+-      struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
+-      size_t len, unsigned long flags)
++static int sh_dmae_set_slave(struct shdma_chan *schan,
++                           struct shdma_slave *sslave)
+ {
+-      struct sh_dmae_chan *sh_chan;
+-      struct scatterlist sg;
+-
+-      if (!chan || !len)
+-              return NULL;
+-
+-      sh_chan = to_sh_chan(chan);
+-
+-      sg_init_table(&sg, 1);
+-      sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_src)), len,
+-                  offset_in_page(dma_src));
+-      sg_dma_address(&sg) = dma_src;
+-      sg_dma_len(&sg) = len;
+-
+-      return sh_dmae_prep_sg(sh_chan, &sg, 1, &dma_dest, DMA_MEM_TO_MEM,
+-                             flags);
+-}
+-
+-static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg(
+-      struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
+-      enum dma_transfer_direction direction, unsigned long flags,
+-      void *context)
+-{
+-      struct sh_dmae_slave *param;
+-      struct sh_dmae_chan *sh_chan;
+-      dma_addr_t slave_addr;
+-
+-      if (!chan)
+-              return NULL;
+-
+-      sh_chan = to_sh_chan(chan);
+-      param = chan->private;
+-
+-      /* Someone calling slave DMA on a public channel? */
+-      if (!param || !sg_len) {
+-              dev_warn(sh_chan->dev, "%s: bad parameter: %p, %d, %d\n",
+-                       __func__, param, sg_len, param ? param->slave_id : -1);
+-              return NULL;
+-      }
+-
+-      slave_addr = param->config->addr;
+-
+-      /*
+-       * if (param != NULL), this is a successfully requested slave channel,
+-       * therefore param->config != NULL too.
+-       */
+-      return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr,
+-                             direction, flags);
+-}
+-
+-static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+-                         unsigned long arg)
+-{
+-      struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+-      unsigned long flags;
+-
+-      /* Only supports DMA_TERMINATE_ALL */
+-      if (cmd != DMA_TERMINATE_ALL)
+-              return -ENXIO;
+-
+-      if (!chan)
+-              return -EINVAL;
+-
+-      spin_lock_irqsave(&sh_chan->desc_lock, flags);
+-      dmae_halt(sh_chan);
+-
+-      if (!list_empty(&sh_chan->ld_queue)) {
+-              /* Record partial transfer */
+-              struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
+-                                                struct sh_desc, node);
+-              desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
+-                      sh_chan->xmit_shift;
+-      }
+-      spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
++      struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
++                                                  shdma_chan);
++      struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave,
++                                                 shdma_slave);
++      const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave);
++      if (!cfg)
++              return -ENODEV;
+-      sh_dmae_chan_ld_cleanup(sh_chan, true);
++      slave->config = cfg;
+       return 0;
+ }
+-static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
++static void dmae_halt(struct sh_dmae_chan *sh_chan)
+ {
+-      struct sh_desc *desc, *_desc;
+-      /* Is the "exposed" head of a chain acked? */
+-      bool head_acked = false;
+-      dma_cookie_t cookie = 0;
+-      dma_async_tx_callback callback = NULL;
+-      void *param = NULL;
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&sh_chan->desc_lock, flags);
+-      list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) {
+-              struct dma_async_tx_descriptor *tx = &desc->async_tx;
+-
+-              BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie);
+-              BUG_ON(desc->mark != DESC_SUBMITTED &&
+-                     desc->mark != DESC_COMPLETED &&
+-                     desc->mark != DESC_WAITING);
+-
+-              /*
+-               * queue is ordered, and we use this loop to (1) clean up all
+-               * completed descriptors, and to (2) update descriptor flags of
+-               * any chunks in a (partially) completed chain
+-               */
+-              if (!all && desc->mark == DESC_SUBMITTED &&
+-                  desc->cookie != cookie)
+-                      break;
+-
+-              if (tx->cookie > 0)
+-                      cookie = tx->cookie;
+-
+-              if (desc->mark == DESC_COMPLETED && desc->chunks == 1) {
+-                      if (sh_chan->common.completed_cookie != desc->cookie - 1)
+-                              dev_dbg(sh_chan->dev,
+-                                      "Completing cookie %d, expected %d\n",
+-                                      desc->cookie,
+-                                      sh_chan->common.completed_cookie + 1);
+-                      sh_chan->common.completed_cookie = desc->cookie;
+-              }
+-
+-              /* Call callback on the last chunk */
+-              if (desc->mark == DESC_COMPLETED && tx->callback) {
+-                      desc->mark = DESC_WAITING;
+-                      callback = tx->callback;
+-                      param = tx->callback_param;
+-                      dev_dbg(sh_chan->dev, "descriptor #%d@%p on %d callback\n",
+-                              tx->cookie, tx, sh_chan->id);
+-                      BUG_ON(desc->chunks != 1);
+-                      break;
+-              }
+-
+-              if (tx->cookie > 0 || tx->cookie == -EBUSY) {
+-                      if (desc->mark == DESC_COMPLETED) {
+-                              BUG_ON(tx->cookie < 0);
+-                              desc->mark = DESC_WAITING;
+-                      }
+-                      head_acked = async_tx_test_ack(tx);
+-              } else {
+-                      switch (desc->mark) {
+-                      case DESC_COMPLETED:
+-                              desc->mark = DESC_WAITING;
+-                              /* Fall through */
+-                      case DESC_WAITING:
+-                              if (head_acked)
+-                                      async_tx_ack(&desc->async_tx);
+-                      }
+-              }
+-
+-              dev_dbg(sh_chan->dev, "descriptor %p #%d completed.\n",
+-                      tx, tx->cookie);
+-
+-              if (((desc->mark == DESC_COMPLETED ||
+-                    desc->mark == DESC_WAITING) &&
+-                   async_tx_test_ack(&desc->async_tx)) || all) {
+-                      /* Remove from ld_queue list */
+-                      desc->mark = DESC_IDLE;
+-
+-                      list_move(&desc->node, &sh_chan->ld_free);
+-
+-                      if (list_empty(&sh_chan->ld_queue)) {
+-                              dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+-                              pm_runtime_put(sh_chan->dev);
+-                      }
+-              }
+-      }
+-
+-      if (all && !callback)
+-              /*
+-               * Terminating and the loop completed normally: forgive
+-               * uncompleted cookies
+-               */
+-              sh_chan->common.completed_cookie = sh_chan->common.cookie;
+-
+-      spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
+-
+-      if (callback)
+-              callback(param);
++      struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
++      u32 chcr = chcr_read(sh_chan);
+-      return callback;
++      chcr &= ~(CHCR_DE | CHCR_TE | shdev->chcr_ie_bit);
++      chcr_write(sh_chan, chcr);
+ }
+-/*
+- * sh_chan_ld_cleanup - Clean up link descriptors
+- *
+- * This function cleans up the ld_queue of DMA channel.
+- */
+-static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
++static int sh_dmae_desc_setup(struct shdma_chan *schan,
++                            struct shdma_desc *sdesc,
++                            dma_addr_t src, dma_addr_t dst, size_t *len)
+ {
+-      while (__ld_cleanup(sh_chan, all))
+-              ;
+-}
++      struct sh_dmae_desc *sh_desc = container_of(sdesc,
++                                      struct sh_dmae_desc, shdma_desc);
+-/* Called under spin_lock_irq(&sh_chan->desc_lock) */
+-static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
+-{
+-      struct sh_desc *desc;
++      if (*len > schan->max_xfer_len)
++              *len = schan->max_xfer_len;
+-      /* DMA work check */
+-      if (dmae_is_busy(sh_chan))
+-              return;
+-
+-      /* Find the first not transferred descriptor */
+-      list_for_each_entry(desc, &sh_chan->ld_queue, node)
+-              if (desc->mark == DESC_SUBMITTED) {
+-                      dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
+-                              desc->async_tx.cookie, sh_chan->id,
+-                              desc->hw.tcr, desc->hw.sar, desc->hw.dar);
+-                      /* Get the ld start address from ld_queue */
+-                      dmae_set_reg(sh_chan, &desc->hw);
+-                      dmae_start(sh_chan);
+-                      break;
+-              }
+-}
++      sh_desc->hw.sar = src;
++      sh_desc->hw.dar = dst;
++      sh_desc->hw.tcr = *len;
+-static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan)
+-{
+-      struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+-
+-      spin_lock_irq(&sh_chan->desc_lock);
+-      if (sh_chan->pm_state == DMAE_PM_ESTABLISHED)
+-              sh_chan_xfer_ld_queue(sh_chan);
+-      else
+-              sh_chan->pm_state = DMAE_PM_PENDING;
+-      spin_unlock_irq(&sh_chan->desc_lock);
++      return 0;
+ }
+-static enum dma_status sh_dmae_tx_status(struct dma_chan *chan,
+-                                      dma_cookie_t cookie,
+-                                      struct dma_tx_state *txstate)
++static void sh_dmae_halt(struct shdma_chan *schan)
+ {
+-      struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
+-      enum dma_status status;
+-      unsigned long flags;
+-
+-      sh_dmae_chan_ld_cleanup(sh_chan, false);
+-
+-      spin_lock_irqsave(&sh_chan->desc_lock, flags);
+-
+-      status = dma_cookie_status(chan, cookie, txstate);
+-
+-      /*
+-       * If we don't find cookie on the queue, it has been aborted and we have
+-       * to report error
+-       */
+-      if (status != DMA_SUCCESS) {
+-              struct sh_desc *desc;
+-              status = DMA_ERROR;
+-              list_for_each_entry(desc, &sh_chan->ld_queue, node)
+-                      if (desc->cookie == cookie) {
+-                              status = DMA_IN_PROGRESS;
+-                              break;
+-                      }
+-      }
+-
+-      spin_unlock_irqrestore(&sh_chan->desc_lock, flags);
+-
+-      return status;
++      struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
++                                                  shdma_chan);
++      dmae_halt(sh_chan);
+ }
+-static irqreturn_t sh_dmae_interrupt(int irq, void *data)
++static bool sh_dmae_chan_irq(struct shdma_chan *schan, int irq)
+ {
+-      irqreturn_t ret = IRQ_NONE;
+-      struct sh_dmae_chan *sh_chan = data;
+-      u32 chcr;
+-
+-      spin_lock(&sh_chan->desc_lock);
+-
+-      chcr = chcr_read(sh_chan);
++      struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
++                                                  shdma_chan);
+-      if (chcr & CHCR_TE) {
+-              /* DMA stop */
+-              dmae_halt(sh_chan);
+-
+-              ret = IRQ_HANDLED;
+-              tasklet_schedule(&sh_chan->tasklet);
+-      }
++      if (!(chcr_read(sh_chan) & CHCR_TE))
++              return false;
+-      spin_unlock(&sh_chan->desc_lock);
++      /* DMA stop */
++      dmae_halt(sh_chan);
+-      return ret;
++      return true;
+ }
+ /* Called from error IRQ or NMI */
+ static bool sh_dmae_reset(struct sh_dmae_device *shdev)
+ {
+-      unsigned int handled = 0;
+-      int i;
++      bool ret;
+       /* halt the dma controller */
+       sh_dmae_ctl_stop(shdev);
+       /* We cannot detect, which channel caused the error, have to reset all */
+-      for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) {
+-              struct sh_dmae_chan *sh_chan = shdev->chan[i];
+-              struct sh_desc *desc;
+-              LIST_HEAD(dl);
+-
+-              if (!sh_chan)
+-                      continue;
+-
+-              spin_lock(&sh_chan->desc_lock);
+-
+-              /* Stop the channel */
+-              dmae_halt(sh_chan);
+-
+-              list_splice_init(&sh_chan->ld_queue, &dl);
+-
+-              if (!list_empty(&dl)) {
+-                      dev_dbg(sh_chan->dev, "Bring down channel %d\n", sh_chan->id);
+-                      pm_runtime_put(sh_chan->dev);
+-              }
+-              sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+-
+-              spin_unlock(&sh_chan->desc_lock);
+-
+-              /* Complete all  */
+-              list_for_each_entry(desc, &dl, node) {
+-                      struct dma_async_tx_descriptor *tx = &desc->async_tx;
+-                      desc->mark = DESC_IDLE;
+-                      if (tx->callback)
+-                              tx->callback(tx->callback_param);
+-              }
+-
+-              spin_lock(&sh_chan->desc_lock);
+-              list_splice(&dl, &sh_chan->ld_free);
+-              spin_unlock(&sh_chan->desc_lock);
+-
+-              handled++;
+-      }
++      ret = shdma_reset(&shdev->shdma_dev);
+       sh_dmae_rst(shdev);
+-      return !!handled;
++      return ret;
+ }
+ static irqreturn_t sh_dmae_err(int irq, void *data)
+@@ -991,35 +407,24 @@ static irqreturn_t sh_dmae_err(int irq, void *data)
+       if (!(dmaor_read(shdev) & DMAOR_AE))
+               return IRQ_NONE;
+-      sh_dmae_reset(data);
++      sh_dmae_reset(shdev);
+       return IRQ_HANDLED;
+ }
+-static void dmae_do_tasklet(unsigned long data)
++static bool sh_dmae_desc_completed(struct shdma_chan *schan,
++                                 struct shdma_desc *sdesc)
+ {
+-      struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
+-      struct sh_desc *desc;
++      struct sh_dmae_chan *sh_chan = container_of(schan,
++                                      struct sh_dmae_chan, shdma_chan);
++      struct sh_dmae_desc *sh_desc = container_of(sdesc,
++                                      struct sh_dmae_desc, shdma_desc);
+       u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
+       u32 dar_buf = sh_dmae_readl(sh_chan, DAR);
+-      spin_lock_irq(&sh_chan->desc_lock);
+-      list_for_each_entry(desc, &sh_chan->ld_queue, node) {
+-              if (desc->mark == DESC_SUBMITTED &&
+-                  ((desc->direction == DMA_DEV_TO_MEM &&
+-                    (desc->hw.dar + desc->hw.tcr) == dar_buf) ||
+-                   (desc->hw.sar + desc->hw.tcr) == sar_buf)) {
+-                      dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n",
+-                              desc->async_tx.cookie, &desc->async_tx,
+-                              desc->hw.dar);
+-                      desc->mark = DESC_COMPLETED;
+-                      break;
+-              }
+-      }
+-      /* Next desc */
+-      sh_chan_xfer_ld_queue(sh_chan);
+-      spin_unlock_irq(&sh_chan->desc_lock);
+-
+-      sh_dmae_chan_ld_cleanup(sh_chan, false);
++      return  (sdesc->direction == DMA_DEV_TO_MEM &&
++               (sh_desc->hw.dar + sh_desc->hw.tcr) == dar_buf) ||
++              (sdesc->direction != DMA_DEV_TO_MEM &&
++               (sh_desc->hw.sar + sh_desc->hw.tcr) == sar_buf);
+ }
+ static bool sh_dmae_nmi_notify(struct sh_dmae_device *shdev)
+@@ -1073,97 +478,174 @@ static struct notifier_block sh_dmae_nmi_notifier __read_mostly = {
+ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
+                                       int irq, unsigned long flags)
+ {
+-      int err;
+       const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
+-      struct platform_device *pdev = to_platform_device(shdev->common.dev);
+-      struct sh_dmae_chan *new_sh_chan;
++      struct shdma_dev *sdev = &shdev->shdma_dev;
++      struct platform_device *pdev = to_platform_device(sdev->dma_dev.dev);
++      struct sh_dmae_chan *sh_chan;
++      struct shdma_chan *schan;
++      int err;
+-      /* alloc channel */
+-      new_sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL);
+-      if (!new_sh_chan) {
+-              dev_err(shdev->common.dev,
++      sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL);
++      if (!sh_chan) {
++              dev_err(sdev->dma_dev.dev,
+                       "No free memory for allocating dma channels!\n");
+               return -ENOMEM;
+       }
+-      new_sh_chan->pm_state = DMAE_PM_ESTABLISHED;
+-
+-      /* reference struct dma_device */
+-      new_sh_chan->common.device = &shdev->common;
+-      dma_cookie_init(&new_sh_chan->common);
++      schan = &sh_chan->shdma_chan;
++      schan->max_xfer_len = SH_DMA_TCR_MAX + 1;
+-      new_sh_chan->dev = shdev->common.dev;
+-      new_sh_chan->id = id;
+-      new_sh_chan->irq = irq;
+-      new_sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32);
++      shdma_chan_probe(sdev, schan, id);
+-      /* Init DMA tasklet */
+-      tasklet_init(&new_sh_chan->tasklet, dmae_do_tasklet,
+-                      (unsigned long)new_sh_chan);
+-
+-      spin_lock_init(&new_sh_chan->desc_lock);
+-
+-      /* Init descripter manage list */
+-      INIT_LIST_HEAD(&new_sh_chan->ld_queue);
+-      INIT_LIST_HEAD(&new_sh_chan->ld_free);
+-
+-      /* Add the channel to DMA device channel list */
+-      list_add_tail(&new_sh_chan->common.device_node,
+-                      &shdev->common.channels);
+-      shdev->common.chancnt++;
++      sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32);
++      /* set up channel irq */
+       if (pdev->id >= 0)
+-              snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
+-                       "sh-dmae%d.%d", pdev->id, new_sh_chan->id);
++              snprintf(sh_chan->dev_id, sizeof(sh_chan->dev_id),
++                       "sh-dmae%d.%d", pdev->id, id);
+       else
+-              snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
+-                       "sh-dma%d", new_sh_chan->id);
++              snprintf(sh_chan->dev_id, sizeof(sh_chan->dev_id),
++                       "sh-dma%d", id);
+-      /* set up channel irq */
+-      err = request_irq(irq, &sh_dmae_interrupt, flags,
+-                        new_sh_chan->dev_id, new_sh_chan);
++      err = shdma_request_irq(schan, irq, flags, sh_chan->dev_id);
+       if (err) {
+-              dev_err(shdev->common.dev, "DMA channel %d request_irq error "
+-                      "with return %d\n", id, err);
++              dev_err(sdev->dma_dev.dev,
++                      "DMA channel %d request_irq error %d\n",
++                      id, err);
+               goto err_no_irq;
+       }
+-      shdev->chan[id] = new_sh_chan;
++      shdev->chan[id] = sh_chan;
+       return 0;
+ err_no_irq:
+       /* remove from dmaengine device node */
+-      list_del(&new_sh_chan->common.device_node);
+-      kfree(new_sh_chan);
++      shdma_chan_remove(schan);
++      kfree(sh_chan);
+       return err;
+ }
+ static void sh_dmae_chan_remove(struct sh_dmae_device *shdev)
+ {
++      struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev;
++      struct shdma_chan *schan;
+       int i;
+-      for (i = shdev->common.chancnt - 1 ; i >= 0 ; i--) {
+-              if (shdev->chan[i]) {
+-                      struct sh_dmae_chan *sh_chan = shdev->chan[i];
++      shdma_for_each_chan(schan, &shdev->shdma_dev, i) {
++              struct sh_dmae_chan *sh_chan = container_of(schan,
++                                      struct sh_dmae_chan, shdma_chan);
++              BUG_ON(!schan);
+-                      free_irq(sh_chan->irq, sh_chan);
++              shdma_free_irq(&sh_chan->shdma_chan);
+-                      list_del(&sh_chan->common.device_node);
+-                      kfree(sh_chan);
+-                      shdev->chan[i] = NULL;
++              shdma_chan_remove(schan);
++              kfree(sh_chan);
++      }
++      dma_dev->chancnt = 0;
++}
++
++static void sh_dmae_shutdown(struct platform_device *pdev)
++{
++      struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
++      sh_dmae_ctl_stop(shdev);
++}
++
++static int sh_dmae_runtime_suspend(struct device *dev)
++{
++      return 0;
++}
++
++static int sh_dmae_runtime_resume(struct device *dev)
++{
++      struct sh_dmae_device *shdev = dev_get_drvdata(dev);
++
++      return sh_dmae_rst(shdev);
++}
++
++#ifdef CONFIG_PM
++static int sh_dmae_suspend(struct device *dev)
++{
++      return 0;
++}
++
++static int sh_dmae_resume(struct device *dev)
++{
++      struct sh_dmae_device *shdev = dev_get_drvdata(dev);
++      int i, ret;
++
++      ret = sh_dmae_rst(shdev);
++      if (ret < 0)
++              dev_err(dev, "Failed to reset!\n");
++
++      for (i = 0; i < shdev->pdata->channel_num; i++) {
++              struct sh_dmae_chan *sh_chan = shdev->chan[i];
++              struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private;
++
++              if (!sh_chan->shdma_chan.desc_num)
++                      continue;
++
++              if (param) {
++                      const struct sh_dmae_slave_config *cfg = param->config;
++                      dmae_set_dmars(sh_chan, cfg->mid_rid);
++                      dmae_set_chcr(sh_chan, cfg->chcr);
++              } else {
++                      dmae_init(sh_chan);
+               }
+       }
+-      shdev->common.chancnt = 0;
++
++      return 0;
+ }
++#else
++#define sh_dmae_suspend NULL
++#define sh_dmae_resume NULL
++#endif
+-static int __init sh_dmae_probe(struct platform_device *pdev)
++const struct dev_pm_ops sh_dmae_pm = {
++      .suspend                = sh_dmae_suspend,
++      .resume                 = sh_dmae_resume,
++      .runtime_suspend        = sh_dmae_runtime_suspend,
++      .runtime_resume         = sh_dmae_runtime_resume,
++};
++
++static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
++{
++      struct sh_dmae_slave *param = schan->dma_chan.private;
++
++      /*
++       * Implicit BUG_ON(!param)
++       * if (param != NULL), this is a successfully requested slave channel,
++       * therefore param->config != NULL too.
++       */
++      return param->config->addr;
++}
++
++static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
++{
++      return &((struct sh_dmae_desc *)buf)[i].shdma_desc;
++}
++
++static const struct shdma_ops sh_dmae_shdma_ops = {
++      .desc_completed = sh_dmae_desc_completed,
++      .halt_channel = sh_dmae_halt,
++      .channel_busy = sh_dmae_channel_busy,
++      .slave_addr = sh_dmae_slave_addr,
++      .desc_setup = sh_dmae_desc_setup,
++      .set_slave = sh_dmae_set_slave,
++      .setup_xfer = sh_dmae_setup_xfer,
++      .start_xfer = sh_dmae_start_xfer,
++      .embedded_desc = sh_dmae_embedded_desc,
++      .chan_irq = sh_dmae_chan_irq,
++};
++
++static int __devinit sh_dmae_probe(struct platform_device *pdev)
+ {
+       struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
+       unsigned long irqflags = IRQF_DISABLED,
+-              chan_flag[SH_DMAC_MAX_CHANNELS] = {};
+-      int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
++              chan_flag[SH_DMAE_MAX_CHANNELS] = {};
++      int errirq, chan_irq[SH_DMAE_MAX_CHANNELS];
+       int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
+       struct sh_dmae_device *shdev;
++      struct dma_device *dma_dev;
+       struct resource *chan, *dmars, *errirq_res, *chanirq_res;
+       /* get platform data */
+@@ -1211,6 +693,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+               goto ealloc;
+       }
++      dma_dev = &shdev->shdma_dev.dma_dev;
++
+       shdev->chan_reg = ioremap(chan->start, resource_size(chan));
+       if (!shdev->chan_reg)
+               goto emapchan;
+@@ -1220,8 +704,23 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+                       goto emapdmars;
+       }
++      if (!pdata->slave_only)
++              dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
++      if (pdata->slave && pdata->slave_num)
++              dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
++
++      /* Default transfer size of 32 bytes requires 32-byte alignment */
++      dma_dev->copy_align = LOG2_DEFAULT_XFER_SIZE;
++
++      shdev->shdma_dev.ops = &sh_dmae_shdma_ops;
++      shdev->shdma_dev.desc_size = sizeof(struct sh_dmae_desc);
++      err = shdma_init(&pdev->dev, &shdev->shdma_dev,
++                            pdata->channel_num);
++      if (err < 0)
++              goto eshdma;
++
+       /* platform data */
+-      shdev->pdata = pdata;
++      shdev->pdata = pdev->dev.platform_data;
+       if (pdata->chcr_offset)
+               shdev->chcr_offset = pdata->chcr_offset;
+@@ -1235,10 +734,10 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+       platform_set_drvdata(pdev, shdev);
+-      shdev->common.dev = &pdev->dev;
+-
+       pm_runtime_enable(&pdev->dev);
+-      pm_runtime_get_sync(&pdev->dev);
++      err = pm_runtime_get_sync(&pdev->dev);
++      if (err < 0)
++              dev_err(&pdev->dev, "%s(): GET = %d\n", __func__, err);
+       spin_lock_irq(&sh_dmae_lock);
+       list_add_tail_rcu(&shdev->node, &sh_dmae_devices);
+@@ -1249,27 +748,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+       if (err)
+               goto rst_err;
+-      INIT_LIST_HEAD(&shdev->common.channels);
+-
+-      if (!pdata->slave_only)
+-              dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
+-      if (pdata->slave && pdata->slave_num)
+-              dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
+-
+-      shdev->common.device_alloc_chan_resources
+-              = sh_dmae_alloc_chan_resources;
+-      shdev->common.device_free_chan_resources = sh_dmae_free_chan_resources;
+-      shdev->common.device_prep_dma_memcpy = sh_dmae_prep_memcpy;
+-      shdev->common.device_tx_status = sh_dmae_tx_status;
+-      shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending;
+-
+-      /* Compulsory for DMA_SLAVE fields */
+-      shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
+-      shdev->common.device_control = sh_dmae_control;
+-
+-      /* Default transfer size of 32 bytes requires 32-byte alignment */
+-      shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
+-
+ #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
+       chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+@@ -1301,7 +779,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+           !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
+               /* Special case - all multiplexed */
+               for (; irq_cnt < pdata->channel_num; irq_cnt++) {
+-                      if (irq_cnt < SH_DMAC_MAX_CHANNELS) {
++                      if (irq_cnt < SH_DMAE_MAX_CHANNELS) {
+                               chan_irq[irq_cnt] = chanirq_res->start;
+                               chan_flag[irq_cnt] = IRQF_SHARED;
+                       } else {
+@@ -1312,7 +790,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+       } else {
+               do {
+                       for (i = chanirq_res->start; i <= chanirq_res->end; i++) {
+-                              if (irq_cnt >= SH_DMAC_MAX_CHANNELS) {
++                              if (irq_cnt >= SH_DMAE_MAX_CHANNELS) {
+                                       irq_cap = 1;
+                                       break;
+                               }
+@@ -1328,7 +806,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+                               chan_irq[irq_cnt++] = i;
+                       }
+-                      if (irq_cnt >= SH_DMAC_MAX_CHANNELS)
++                      if (irq_cnt >= SH_DMAE_MAX_CHANNELS)
+                               break;
+                       chanirq_res = platform_get_resource(pdev,
+@@ -1346,14 +824,19 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
+       if (irq_cap)
+               dev_notice(&pdev->dev, "Attempting to register %d DMA "
+                          "channels when a maximum of %d are supported.\n",
+-                         pdata->channel_num, SH_DMAC_MAX_CHANNELS);
++                         pdata->channel_num, SH_DMAE_MAX_CHANNELS);
+       pm_runtime_put(&pdev->dev);
+-      dma_async_device_register(&shdev->common);
++      err = dma_async_device_register(&shdev->shdma_dev.dma_dev);
++      if (err < 0)
++              goto edmadevreg;
+       return err;
++edmadevreg:
++      pm_runtime_get(&pdev->dev);
++
+ chan_probe_err:
+       sh_dmae_chan_remove(shdev);
+@@ -1369,10 +852,11 @@ rst_err:
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
++      platform_set_drvdata(pdev, NULL);
++      shdma_cleanup(&shdev->shdma_dev);
++eshdma:
+       if (dmars)
+               iounmap(shdev->dmars);
+-
+-      platform_set_drvdata(pdev, NULL);
+ emapdmars:
+       iounmap(shdev->chan_reg);
+       synchronize_rcu();
+@@ -1387,13 +871,14 @@ ermrdmars:
+       return err;
+ }
+-static int __exit sh_dmae_remove(struct platform_device *pdev)
++static int __devexit sh_dmae_remove(struct platform_device *pdev)
+ {
+       struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
++      struct dma_device *dma_dev = &shdev->shdma_dev.dma_dev;
+       struct resource *res;
+       int errirq = platform_get_irq(pdev, 0);
+-      dma_async_device_unregister(&shdev->common);
++      dma_async_device_unregister(dma_dev);
+       if (errirq > 0)
+               free_irq(errirq, shdev);
+@@ -1402,11 +887,11 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
+       list_del_rcu(&shdev->node);
+       spin_unlock_irq(&sh_dmae_lock);
+-      /* channel data remove */
+-      sh_dmae_chan_remove(shdev);
+-
+       pm_runtime_disable(&pdev->dev);
++      sh_dmae_chan_remove(shdev);
++      shdma_cleanup(&shdev->shdma_dev);
++
+       if (shdev->dmars)
+               iounmap(shdev->dmars);
+       iounmap(shdev->chan_reg);
+@@ -1426,77 +911,14 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
+       return 0;
+ }
+-static void sh_dmae_shutdown(struct platform_device *pdev)
+-{
+-      struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
+-      sh_dmae_ctl_stop(shdev);
+-}
+-
+-static int sh_dmae_runtime_suspend(struct device *dev)
+-{
+-      return 0;
+-}
+-
+-static int sh_dmae_runtime_resume(struct device *dev)
+-{
+-      struct sh_dmae_device *shdev = dev_get_drvdata(dev);
+-
+-      return sh_dmae_rst(shdev);
+-}
+-
+-#ifdef CONFIG_PM
+-static int sh_dmae_suspend(struct device *dev)
+-{
+-      return 0;
+-}
+-
+-static int sh_dmae_resume(struct device *dev)
+-{
+-      struct sh_dmae_device *shdev = dev_get_drvdata(dev);
+-      int i, ret;
+-
+-      ret = sh_dmae_rst(shdev);
+-      if (ret < 0)
+-              dev_err(dev, "Failed to reset!\n");
+-
+-      for (i = 0; i < shdev->pdata->channel_num; i++) {
+-              struct sh_dmae_chan *sh_chan = shdev->chan[i];
+-              struct sh_dmae_slave *param = sh_chan->common.private;
+-
+-              if (!sh_chan->descs_allocated)
+-                      continue;
+-
+-              if (param) {
+-                      const struct sh_dmae_slave_config *cfg = param->config;
+-                      dmae_set_dmars(sh_chan, cfg->mid_rid);
+-                      dmae_set_chcr(sh_chan, cfg->chcr);
+-              } else {
+-                      dmae_init(sh_chan);
+-              }
+-      }
+-
+-      return 0;
+-}
+-#else
+-#define sh_dmae_suspend NULL
+-#define sh_dmae_resume NULL
+-#endif
+-
+-const struct dev_pm_ops sh_dmae_pm = {
+-      .suspend                = sh_dmae_suspend,
+-      .resume                 = sh_dmae_resume,
+-      .runtime_suspend        = sh_dmae_runtime_suspend,
+-      .runtime_resume         = sh_dmae_runtime_resume,
+-};
+-
+ static struct platform_driver sh_dmae_driver = {
+-      .remove         = __exit_p(sh_dmae_remove),
+-      .shutdown       = sh_dmae_shutdown,
+-      .driver = {
++      .driver         = {
+               .owner  = THIS_MODULE,
+-              .name   = "sh-dma-engine",
+               .pm     = &sh_dmae_pm,
++              .name   = SH_DMAE_DRV_NAME,
+       },
++      .remove         = __devexit_p(sh_dmae_remove),
++      .shutdown       = sh_dmae_shutdown,
+ };
+ static int __init sh_dmae_init(void)
+@@ -1521,4 +943,4 @@ module_exit(sh_dmae_exit);
+ MODULE_AUTHOR("Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>");
+ MODULE_DESCRIPTION("Renesas SH DMA Engine driver");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:sh-dma-engine");
++MODULE_ALIAS("platform:" SH_DMAE_DRV_NAME);
+diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
+index 0b1d2c1..840e47d 100644
+--- a/drivers/dma/sh/shdma.h
++++ b/drivers/dma/sh/shdma.h
+@@ -13,42 +13,27 @@
+ #ifndef __DMA_SHDMA_H
+ #define __DMA_SHDMA_H
++#include <linux/shdma-base.h>
+ #include <linux/dmaengine.h>
+ #include <linux/interrupt.h>
+ #include <linux/list.h>
+-#define SH_DMAC_MAX_CHANNELS 20
+-#define SH_DMA_SLAVE_NUMBER 256
+-#define SH_DMA_TCR_MAX 0x00FFFFFF     /* 16MB */
++#define SH_DMAE_MAX_CHANNELS 20
++#define SH_DMAE_TCR_MAX 0x00FFFFFF    /* 16MB */
+ struct device;
+-enum dmae_pm_state {
+-      DMAE_PM_ESTABLISHED,
+-      DMAE_PM_BUSY,
+-      DMAE_PM_PENDING,
+-};
+-
+ struct sh_dmae_chan {
+-      spinlock_t desc_lock;           /* Descriptor operation lock */
+-      struct list_head ld_queue;      /* Link descriptors queue */
+-      struct list_head ld_free;       /* Link descriptors free */
+-      struct dma_chan common;         /* DMA common channel */
+-      struct device *dev;             /* Channel device */
+-      struct tasklet_struct tasklet;  /* Tasklet */
+-      int descs_allocated;            /* desc count */
++      struct shdma_chan shdma_chan;
+       int xmit_shift;                 /* log_2(bytes_per_xfer) */
+-      int irq;
+-      int id;                         /* Raw id of this channel */
+       u32 __iomem *base;
+       char dev_id[16];                /* unique name per DMAC of channel */
+       int pm_error;
+-      enum dmae_pm_state pm_state;
+ };
+ struct sh_dmae_device {
+-      struct dma_device common;
+-      struct sh_dmae_chan *chan[SH_DMAC_MAX_CHANNELS];
++      struct shdma_dev shdma_dev;
++      struct sh_dmae_chan *chan[SH_DMAE_MAX_CHANNELS];
+       struct sh_dmae_pdata *pdata;
+       struct list_head node;
+       u32 __iomem *chan_reg;
+@@ -57,10 +42,21 @@ struct sh_dmae_device {
+       u32 chcr_ie_bit;
+ };
+-#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)
++struct sh_dmae_regs {
++      u32 sar; /* SAR / source address */
++      u32 dar; /* DAR / destination address */
++      u32 tcr; /* TCR / transfer count */
++};
++
++struct sh_dmae_desc {
++      struct sh_dmae_regs hw;
++      struct shdma_desc shdma_desc;
++};
++
++#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, shdma_chan)
+ #define to_sh_desc(lh) container_of(lh, struct sh_desc, node)
+ #define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx)
+-#define to_sh_dev(chan) container_of(chan->common.device,\
+-                                   struct sh_dmae_device, common)
++#define to_sh_dev(chan) container_of(chan->shdma_chan.dma_chan.device,\
++                                   struct sh_dmae_device, shdma_dev.dma_dev)
+ #endif        /* __DMA_SHDMA_H */
+diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
+index e081e8e..7c8ca41 100644
+--- a/include/linux/sh_dma.h
++++ b/include/linux/sh_dma.h
+@@ -13,34 +13,21 @@
+ #include <linux/dmaengine.h>
+ #include <linux/list.h>
+ #include <linux/shdma-base.h>
++#include <linux/types.h>
++
++struct device;
+ /* Used by slave DMA clients to request DMA to/from a specific peripheral */
+ struct sh_dmae_slave {
+-      union {
+-              unsigned int            slave_id; /* Set by the platform */
+-              struct shdma_slave      shdma_slave;
+-      };
+-      struct device                   *dma_dev; /* Set by the platform */
+-      const struct sh_dmae_slave_config       *config;  /* Set by the driver */
+-};
+-
+-struct sh_dmae_regs {
+-      u32 sar; /* SAR / source address */
+-      u32 dar; /* DAR / destination address */
+-      u32 tcr; /* TCR / transfer count */
+-};
+-
+-struct sh_desc {
+-      struct sh_dmae_regs hw;
+-      struct list_head node;
+-      struct dma_async_tx_descriptor async_tx;
+-      enum dma_transfer_direction direction;
+-      dma_cookie_t cookie;
+-      size_t partial;
+-      int chunks;
+-      int mark;
++      struct shdma_slave              shdma_slave;    /* Set by the platform */
++      struct device                   *dma_dev;       /* Set by the platform */
++      const struct sh_dmae_slave_config *config;      /* Set by the driver */
+ };
++/*
++ * Supplied by platforms to specify, how a DMA channel has to be configured for
++ * a certain peripheral
++ */
+ struct sh_dmae_slave_config {
+       unsigned int                    slave_id;
+       dma_addr_t                      addr;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch b/patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch
new file mode 100644 (file)
index 0000000..4e64c5a
--- /dev/null
@@ -0,0 +1,183 @@
+From a2071a25b2853b85f682b5a37d87faa4659141c6 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 5 Jul 2012 12:29:40 +0200
+Subject: dmaengine: shdma: prepare to stop using struct dma_chan::private
+
+Using struct dma_chan::private is deprecated. To update the shdma driver to
+stop using it we first have to eliminate internal runtime uses of it. After
+that we will also be able to stop using it for channel configuration.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit ecf90fbbdc66cde6f5fa25d88541112b9baac459)
+
+Conflicts:
+       drivers/dma/sh/shdma.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/sh/shdma-base.c |  9 +++++----
+ drivers/dma/sh/shdma.c      | 24 ++++++++++--------------
+ drivers/dma/sh/shdma.h      |  2 ++
+ include/linux/sh_dma.h      |  2 --
+ include/linux/shdma-base.h  |  1 +
+ 5 files changed, 18 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
+index ff060d0..f75ebfa 100644
+--- a/drivers/dma/sh/shdma-base.c
++++ b/drivers/dma/sh/shdma-base.c
+@@ -76,7 +76,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
+               container_of(tx, struct shdma_desc, async_tx),
+               *last = desc;
+       struct shdma_chan *schan = to_shdma_chan(tx->chan);
+-      struct shdma_slave *slave = tx->chan->private;
++      struct shdma_slave *slave = schan->slave;
+       dma_async_tx_callback callback = tx->callback;
+       dma_cookie_t cookie;
+       bool power_up;
+@@ -208,6 +208,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
+               goto edescalloc;
+       }
+       schan->desc_num = NR_DESCS_PER_CHANNEL;
++      schan->slave = slave;
+       for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
+               desc = ops->embedded_desc(schan->desc, i);
+@@ -365,9 +366,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
+       if (!list_empty(&schan->ld_queue))
+               shdma_chan_ld_cleanup(schan, true);
+-      if (chan->private) {
++      if (schan->slave) {
+               /* The caller is holding dma_list_mutex */
+-              struct shdma_slave *slave = chan->private;
++              struct shdma_slave *slave = schan->slave;
+               clear_bit(slave->slave_id, shdma_slave_used);
+               chan->private = NULL;
+       }
+@@ -558,7 +559,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
+       struct shdma_chan *schan = to_shdma_chan(chan);
+       struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+       const struct shdma_ops *ops = sdev->ops;
+-      struct shdma_slave *slave = chan->private;
++      struct shdma_slave *slave = schan->slave;
+       dma_addr_t slave_addr;
+       if (!chan)
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index c393b35..305e77a 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -291,10 +291,8 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
+                                                   shdma_chan);
+       if (sslave) {
+-              struct sh_dmae_slave *slave = container_of(sslave,
+-                                      struct sh_dmae_slave, shdma_slave);
+               const struct sh_dmae_slave_config *cfg =
+-                      slave->config;
++                      sh_chan->config;
+               dmae_set_dmars(sh_chan, cfg->mid_rid);
+               dmae_set_chcr(sh_chan, cfg->chcr);
+@@ -326,13 +324,11 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
+ {
+       struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
+                                                   shdma_chan);
+-      struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave,
+-                                                 shdma_slave);
+       const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave);
+       if (!cfg)
+               return -ENODEV;
+-      slave->config = cfg;
++      sh_chan->config = cfg;
+       return 0;
+ }
+@@ -579,13 +575,12 @@ static int sh_dmae_resume(struct device *dev)
+       for (i = 0; i < shdev->pdata->channel_num; i++) {
+               struct sh_dmae_chan *sh_chan = shdev->chan[i];
+-              struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private;
+               if (!sh_chan->shdma_chan.desc_num)
+                       continue;
+-              if (param) {
+-                      const struct sh_dmae_slave_config *cfg = param->config;
++              if (sh_chan->shdma_chan.slave) {
++                      const struct sh_dmae_slave_config *cfg = sh_chan->config;
+                       dmae_set_dmars(sh_chan, cfg->mid_rid);
+                       dmae_set_chcr(sh_chan, cfg->chcr);
+               } else {
+@@ -609,14 +604,15 @@ const struct dev_pm_ops sh_dmae_pm = {
+ static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
+ {
+-      struct sh_dmae_slave *param = schan->dma_chan.private;
++      struct sh_dmae_chan *sh_chan = container_of(schan,
++                                      struct sh_dmae_chan, shdma_chan);
+       /*
+-       * Implicit BUG_ON(!param)
+-       * if (param != NULL), this is a successfully requested slave channel,
+-       * therefore param->config != NULL too.
++       * Implicit BUG_ON(!sh_chan->config)
++       * This is an exclusive slave DMA operation, may only be called after a
++       * successful slave configuration.
+        */
+-      return param->config->addr;
++      return sh_chan->config->addr;
+ }
+ static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
+diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
+index 840e47d..9314e93 100644
+--- a/drivers/dma/sh/shdma.h
++++ b/drivers/dma/sh/shdma.h
+@@ -13,6 +13,7 @@
+ #ifndef __DMA_SHDMA_H
+ #define __DMA_SHDMA_H
++#include <linux/sh_dma.h>
+ #include <linux/shdma-base.h>
+ #include <linux/dmaengine.h>
+ #include <linux/interrupt.h>
+@@ -25,6 +26,7 @@ struct device;
+ struct sh_dmae_chan {
+       struct shdma_chan shdma_chan;
++      const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
+       int xmit_shift;                 /* log_2(bytes_per_xfer) */
+       u32 __iomem *base;
+       char dev_id[16];                /* unique name per DMAC of channel */
+diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
+index 7c8ca41..a79f10a 100644
+--- a/include/linux/sh_dma.h
++++ b/include/linux/sh_dma.h
+@@ -20,8 +20,6 @@ struct device;
+ /* Used by slave DMA clients to request DMA to/from a specific peripheral */
+ struct sh_dmae_slave {
+       struct shdma_slave              shdma_slave;    /* Set by the platform */
+-      struct device                   *dma_dev;       /* Set by the platform */
+-      const struct sh_dmae_slave_config *config;      /* Set by the driver */
+ };
+ /*
+diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
+index 83efd13..c3a19e9 100644
+--- a/include/linux/shdma-base.h
++++ b/include/linux/shdma-base.h
+@@ -66,6 +66,7 @@ struct shdma_chan {
+       size_t max_xfer_len;            /* max transfer length */
+       int id;                         /* Raw id of this channel */
+       int irq;                        /* Channel IRQ */
++      struct shdma_slave *slave;      /* Client data for slave DMA */
+       enum shdma_pm_state pm_state;
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch b/patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch
new file mode 100644 (file)
index 0000000..96374c2
--- /dev/null
@@ -0,0 +1,58 @@
+From fc5aa8d8ebed522f219c9a368306cbe41fe75ca9 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 5 Jul 2012 12:29:37 +0200
+Subject: dmaengine: shdma: (cosmetic) simplify a static function
+
+dmae_find_slave() needs only the slave_id field from the slave object, no
+need to pass the pointer to the object, pass the slave_id directly.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 341f4dc5dcecbf60f038055db177845b9af480ed)
+
+Conflicts:
+       drivers/dma/sh/shdma.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/sh/shdma.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index 305e77a..9f0a2e5 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -302,18 +302,18 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
+ }
+ static const struct sh_dmae_slave_config *dmae_find_slave(
+-      struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *slave)
++      struct sh_dmae_chan *sh_chan, unsigned int slave_id)
+ {
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+       struct sh_dmae_pdata *pdata = shdev->pdata;
+       const struct sh_dmae_slave_config *cfg;
+       int i;
+-      if (slave->shdma_slave.slave_id >= SH_DMA_SLAVE_NUMBER)
++      if (slave_id >= SH_DMA_SLAVE_NUMBER)
+               return NULL;
+       for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
+-              if (cfg->slave_id == slave->shdma_slave.slave_id)
++              if (cfg->slave_id == slave_id)
+                       return cfg;
+       return NULL;
+@@ -324,7 +324,7 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
+ {
+       struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
+                                                   shdma_chan);
+-      const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave);
++      const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
+       if (!cfg)
+               return -ENODEV;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch b/patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch
new file mode 100644 (file)
index 0000000..d7aba34
--- /dev/null
@@ -0,0 +1,220 @@
+From 994962e925ac52b6a5c870d02f537c5e3dd535ca Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 5 Jul 2012 12:29:41 +0200
+Subject: dma: sh: use an integer slave ID to improve API compatibility
+
+Initially struct shdma_slave has been introduced with the only member - an
+unsigned slave ID - to describe common properties of DMA slaves in an
+extensible way. However, experience shows, that a slave ID is indeed the
+only parameter, needed to identify DMA slaves. This is also, what is used
+by the core dmaengine API in struct dma_slave_config. We switch to using
+the slave_id directly, instead of passing a pointer to struct shdma_slave
+to improve compatibility with the core. We also make the slave_id signed
+for easier error checking.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit c2cdb7e4d16394fc51dc5c2c5b3e7c3733bdfaac)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/sh/shdma-base.c | 25 +++++++++++++------------
+ drivers/dma/sh/shdma.c      | 12 ++++++------
+ include/linux/sh_dma.h      |  8 ++++----
+ include/linux/shdma-base.h  |  8 ++++----
+ 4 files changed, 27 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
+index f75ebfa..73db282 100644
+--- a/drivers/dma/sh/shdma-base.c
++++ b/drivers/dma/sh/shdma-base.c
+@@ -76,7 +76,6 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
+               container_of(tx, struct shdma_desc, async_tx),
+               *last = desc;
+       struct shdma_chan *schan = to_shdma_chan(tx->chan);
+-      struct shdma_slave *slave = schan->slave;
+       dma_async_tx_callback callback = tx->callback;
+       dma_cookie_t cookie;
+       bool power_up;
+@@ -138,7 +137,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
+                        * Make it int then, on error remove chunks from the
+                        * queue again
+                        */
+-                      ops->setup_xfer(schan, slave);
++                      ops->setup_xfer(schan, schan->slave_id);
+                       if (schan->pm_state == SHDMA_PM_PENDING)
+                               shdma_chan_xfer_ld_queue(schan);
+@@ -186,7 +185,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
+        * never runs concurrently with itself or free_chan_resources.
+        */
+       if (slave) {
+-              if (slave->slave_id >= slave_num) {
++              if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
+                       ret = -EINVAL;
+                       goto evalid;
+               }
+@@ -196,9 +195,13 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
+                       goto etestused;
+               }
+-              ret = ops->set_slave(schan, slave);
++              ret = ops->set_slave(schan, slave->slave_id);
+               if (ret < 0)
+                       goto esetslave;
++
++              schan->slave_id = slave->slave_id;
++      } else {
++              schan->slave_id = -EINVAL;
+       }
+       schan->desc = kcalloc(NR_DESCS_PER_CHANNEL,
+@@ -208,7 +211,6 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
+               goto edescalloc;
+       }
+       schan->desc_num = NR_DESCS_PER_CHANNEL;
+-      schan->slave = slave;
+       for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
+               desc = ops->embedded_desc(schan->desc, i);
+@@ -366,10 +368,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
+       if (!list_empty(&schan->ld_queue))
+               shdma_chan_ld_cleanup(schan, true);
+-      if (schan->slave) {
++      if (schan->slave_id >= 0) {
+               /* The caller is holding dma_list_mutex */
+-              struct shdma_slave *slave = schan->slave;
+-              clear_bit(slave->slave_id, shdma_slave_used);
++              clear_bit(schan->slave_id, shdma_slave_used);
+               chan->private = NULL;
+       }
+@@ -559,7 +560,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
+       struct shdma_chan *schan = to_shdma_chan(chan);
+       struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+       const struct shdma_ops *ops = sdev->ops;
+-      struct shdma_slave *slave = schan->slave;
++      int slave_id = schan->slave_id;
+       dma_addr_t slave_addr;
+       if (!chan)
+@@ -568,9 +569,9 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
+       BUG_ON(!schan->desc_num);
+       /* Someone calling slave DMA on a generic channel? */
+-      if (!slave || !sg_len) {
+-              dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n",
+-                       __func__, slave, sg_len, slave ? slave->slave_id : -1);
++      if (slave_id < 0 || !sg_len) {
++              dev_warn(schan->dev, "%s: bad parameter: len=%d, id=%d\n",
++                       __func__, sg_len, slave_id);
+               return NULL;
+       }
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index 9f0a2e5..9a10d8b 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -285,12 +285,12 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan)
+ }
+ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
+-                             struct shdma_slave *sslave)
++                             int slave_id)
+ {
+       struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
+                                                   shdma_chan);
+-      if (sslave) {
++      if (slave_id >= 0) {
+               const struct sh_dmae_slave_config *cfg =
+                       sh_chan->config;
+@@ -302,7 +302,7 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
+ }
+ static const struct sh_dmae_slave_config *dmae_find_slave(
+-      struct sh_dmae_chan *sh_chan, unsigned int slave_id)
++      struct sh_dmae_chan *sh_chan, int slave_id)
+ {
+       struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
+       struct sh_dmae_pdata *pdata = shdev->pdata;
+@@ -320,11 +320,11 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
+ }
+ static int sh_dmae_set_slave(struct shdma_chan *schan,
+-                           struct shdma_slave *sslave)
++                           int slave_id)
+ {
+       struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
+                                                   shdma_chan);
+-      const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
++      const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave_id);
+       if (!cfg)
+               return -ENODEV;
+@@ -579,7 +579,7 @@ static int sh_dmae_resume(struct device *dev)
+               if (!sh_chan->shdma_chan.desc_num)
+                       continue;
+-              if (sh_chan->shdma_chan.slave) {
++              if (sh_chan->shdma_chan.slave_id >= 0) {
+                       const struct sh_dmae_slave_config *cfg = sh_chan->config;
+                       dmae_set_dmars(sh_chan, cfg->mid_rid);
+                       dmae_set_chcr(sh_chan, cfg->chcr);
+diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
+index a79f10a..4e83f3e 100644
+--- a/include/linux/sh_dma.h
++++ b/include/linux/sh_dma.h
+@@ -27,10 +27,10 @@ struct sh_dmae_slave {
+  * a certain peripheral
+  */
+ struct sh_dmae_slave_config {
+-      unsigned int                    slave_id;
+-      dma_addr_t                      addr;
+-      u32                             chcr;
+-      char                            mid_rid;
++      int             slave_id;
++      dma_addr_t      addr;
++      u32             chcr;
++      char            mid_rid;
+ };
+ struct sh_dmae_channel {
+diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
+index c3a19e9..6263ad2 100644
+--- a/include/linux/shdma-base.h
++++ b/include/linux/shdma-base.h
+@@ -43,7 +43,7 @@ struct device;
+  */
+ struct shdma_slave {
+-      unsigned int slave_id;
++      int slave_id;
+ };
+ struct shdma_desc {
+@@ -66,7 +66,7 @@ struct shdma_chan {
+       size_t max_xfer_len;            /* max transfer length */
+       int id;                         /* Raw id of this channel */
+       int irq;                        /* Channel IRQ */
+-      struct shdma_slave *slave;      /* Client data for slave DMA */
++      int slave_id;                   /* Client ID for slave DMA */
+       enum shdma_pm_state pm_state;
+ };
+@@ -93,8 +93,8 @@ struct shdma_ops {
+       dma_addr_t (*slave_addr)(struct shdma_chan *);
+       int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
+                         dma_addr_t, dma_addr_t, size_t *);
+-      int (*set_slave)(struct shdma_chan *, struct shdma_slave *);
+-      void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *);
++      int (*set_slave)(struct shdma_chan *, int);
++      void (*setup_xfer)(struct shdma_chan *, int);
+       void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
+       struct shdma_desc *(*embedded_desc)(void *, int);
+       bool (*chan_irq)(struct shdma_chan *, int);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch b/patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch
new file mode 100644 (file)
index 0000000..b1aa4af
--- /dev/null
@@ -0,0 +1,231 @@
+From 3f976e575c229dad477f66090af9286700b35b3e Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 5 Jul 2012 12:29:42 +0200
+Subject: dma: sh: provide a migration path for slave drivers to stop using
+ .private
+
+This patch extends the sh dmaengine driver to support the preferred channel
+selection and configuration method, instead of using the "private" field
+from struct dma_chan. We add a standard filter function to be used by
+slave drivers instead of implementing their own ones, and add support for
+the DMA_SLAVE_CONFIG control operation, which must accompany the new
+channel selection method. We still support the legacy .private channel
+allocation method to cater for a smooth driver migration.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+[applied a trvial checkpath fix]
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 1ff8df4f5388ad66bd7d0199b5839a2e3345c055)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/sh/shdma-base.c | 114 ++++++++++++++++++++++++++++++++++----------
+ drivers/dma/sh/shdma.c      |   5 +-
+ include/linux/sh_dma.h      |   2 +
+ include/linux/shdma-base.h  |   2 +-
+ 4 files changed, 95 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
+index 73db282..27f5c78 100644
+--- a/drivers/dma/sh/shdma-base.c
++++ b/drivers/dma/sh/shdma-base.c
+@@ -171,6 +171,65 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
+       return NULL;
+ }
++static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
++{
++      struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
++      const struct shdma_ops *ops = sdev->ops;
++      int ret;
++
++      if (slave_id < 0 || slave_id >= slave_num)
++              return -EINVAL;
++
++      if (test_and_set_bit(slave_id, shdma_slave_used))
++              return -EBUSY;
++
++      ret = ops->set_slave(schan, slave_id, false);
++      if (ret < 0) {
++              clear_bit(slave_id, shdma_slave_used);
++              return ret;
++      }
++
++      schan->slave_id = slave_id;
++
++      return 0;
++}
++
++/*
++ * This is the standard shdma filter function to be used as a replacement to the
++ * "old" method, using the .private pointer. If for some reason you allocate a
++ * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
++ * parameter. If this filter is used, the slave driver, after calling
++ * dma_request_channel(), will also have to call dmaengine_slave_config() with
++ * .slave_id, .direction, and either .src_addr or .dst_addr set.
++ * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
++ * capability! If this becomes a requirement, hardware glue drivers, using this
++ * services would have to provide their own filters, which first would check
++ * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
++ * this, and only then, in case of a match, call this common filter.
++ */
++bool shdma_chan_filter(struct dma_chan *chan, void *arg)
++{
++      struct shdma_chan *schan = to_shdma_chan(chan);
++      struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
++      const struct shdma_ops *ops = sdev->ops;
++      int slave_id = (int)arg;
++      int ret;
++
++      if (slave_id < 0)
++              /* No slave requested - arbitrary channel */
++              return true;
++
++      if (slave_id >= slave_num)
++              return false;
++
++      ret = ops->set_slave(schan, slave_id, true);
++      if (ret < 0)
++              return false;
++
++      return true;
++}
++EXPORT_SYMBOL(shdma_chan_filter);
++
+ static int shdma_alloc_chan_resources(struct dma_chan *chan)
+ {
+       struct shdma_chan *schan = to_shdma_chan(chan);
+@@ -185,21 +244,10 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
+        * never runs concurrently with itself or free_chan_resources.
+        */
+       if (slave) {
+-              if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
+-                      ret = -EINVAL;
+-                      goto evalid;
+-              }
+-
+-              if (test_and_set_bit(slave->slave_id, shdma_slave_used)) {
+-                      ret = -EBUSY;
+-                      goto etestused;
+-              }
+-
+-              ret = ops->set_slave(schan, slave->slave_id);
++              /* Legacy mode: .private is set in filter */
++              ret = shdma_setup_slave(schan, slave->slave_id);
+               if (ret < 0)
+                       goto esetslave;
+-
+-              schan->slave_id = slave->slave_id;
+       } else {
+               schan->slave_id = -EINVAL;
+       }
+@@ -228,8 +276,6 @@ edescalloc:
+       if (slave)
+ esetslave:
+               clear_bit(slave->slave_id, shdma_slave_used);
+-etestused:
+-evalid:
+       chan->private = NULL;
+       return ret;
+ }
+@@ -587,22 +633,40 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+       struct shdma_chan *schan = to_shdma_chan(chan);
+       struct shdma_dev *sdev = to_shdma_dev(chan->device);
+       const struct shdma_ops *ops = sdev->ops;
++      struct dma_slave_config *config;
+       unsigned long flags;
+-
+-      /* Only supports DMA_TERMINATE_ALL */
+-      if (cmd != DMA_TERMINATE_ALL)
+-              return -ENXIO;
++      int ret;
+       if (!chan)
+               return -EINVAL;
+-      spin_lock_irqsave(&schan->chan_lock, flags);
+-
+-      ops->halt_channel(schan);
+-
+-      spin_unlock_irqrestore(&schan->chan_lock, flags);
++      switch (cmd) {
++      case DMA_TERMINATE_ALL:
++              spin_lock_irqsave(&schan->chan_lock, flags);
++              ops->halt_channel(schan);
++              spin_unlock_irqrestore(&schan->chan_lock, flags);
+-      shdma_chan_ld_cleanup(schan, true);
++              shdma_chan_ld_cleanup(schan, true);
++              break;
++      case DMA_SLAVE_CONFIG:
++              /*
++               * So far only .slave_id is used, but the slave drivers are
++               * encouraged to also set a transfer direction and an address.
++               */
++              if (!arg)
++                      return -EINVAL;
++              /*
++               * We could lock this, but you shouldn't be configuring the
++               * channel, while using it...
++               */
++              config = (struct dma_slave_config *)arg;
++              ret = shdma_setup_slave(schan, config->slave_id);
++              if (ret < 0)
++                      return ret;
++              break;
++      default:
++              return -ENXIO;
++      }
+       return 0;
+ }
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index 9a10d8b..027c9be 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -320,7 +320,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
+ }
+ static int sh_dmae_set_slave(struct shdma_chan *schan,
+-                           int slave_id)
++                           int slave_id, bool try)
+ {
+       struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
+                                                   shdma_chan);
+@@ -328,7 +328,8 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
+       if (!cfg)
+               return -ENODEV;
+-      sh_chan->config = cfg;
++      if (!try)
++              sh_chan->config = cfg;
+       return 0;
+ }
+diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
+index 4e83f3e..b64d6be 100644
+--- a/include/linux/sh_dma.h
++++ b/include/linux/sh_dma.h
+@@ -99,4 +99,6 @@ struct sh_dmae_pdata {
+ #define CHCR_TE       0x00000002
+ #define CHCR_IE       0x00000004
++bool shdma_chan_filter(struct dma_chan *chan, void *arg);
++
+ #endif
+diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
+index 6263ad2..93f9821 100644
+--- a/include/linux/shdma-base.h
++++ b/include/linux/shdma-base.h
+@@ -93,7 +93,7 @@ struct shdma_ops {
+       dma_addr_t (*slave_addr)(struct shdma_chan *);
+       int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
+                         dma_addr_t, dma_addr_t, size_t *);
+-      int (*set_slave)(struct shdma_chan *, int);
++      int (*set_slave)(struct shdma_chan *, int, bool);
+       void (*setup_xfer)(struct shdma_chan *, int);
+       void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
+       struct shdma_desc *(*embedded_desc)(void *, int);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch b/patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch
new file mode 100644 (file)
index 0000000..8352cb6
--- /dev/null
@@ -0,0 +1,101 @@
+From b1cb8efea85092e5441a428691a36d9fec40ca0f Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Mon, 30 Jul 2012 21:28:27 +0200
+Subject: dmaengine: shdma: restore partial transfer calculation
+
+The recent shdma driver split has mistakenly removed support for partial
+DMA transfer size calculation on forced termination. This patch restores
+it.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Acked-by: Vinod Koul <vinod.koul@linux.intel.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 4f46f8ac80416b0e8fd3aba6a0d842205fb29140)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/dma/sh/shdma-base.c |  9 +++++++++
+ drivers/dma/sh/shdma.c      | 12 ++++++++++++
+ include/linux/shdma-base.h  |  2 ++
+ 3 files changed, 23 insertions(+)
+
+diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
+index 27f5c78..f4cd946 100644
+--- a/drivers/dma/sh/shdma-base.c
++++ b/drivers/dma/sh/shdma-base.c
+@@ -483,6 +483,7 @@ static struct shdma_desc *shdma_add_desc(struct shdma_chan *schan,
+       new->mark = DESC_PREPARED;
+       new->async_tx.flags = flags;
+       new->direction = direction;
++      new->partial = 0;
+       *len -= copy_size;
+       if (direction == DMA_MEM_TO_MEM || direction == DMA_MEM_TO_DEV)
+@@ -644,6 +645,14 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+       case DMA_TERMINATE_ALL:
+               spin_lock_irqsave(&schan->chan_lock, flags);
+               ops->halt_channel(schan);
++
++              if (ops->get_partial && !list_empty(&schan->ld_queue)) {
++                      /* Record partial transfer */
++                      struct shdma_desc *desc = list_first_entry(&schan->ld_queue,
++                                              struct shdma_desc, node);
++                      desc->partial = ops->get_partial(schan, desc);
++              }
++
+               spin_unlock_irqrestore(&schan->chan_lock, flags);
+               shdma_chan_ld_cleanup(schan, true);
+diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
+index 027c9be..f41bcc5 100644
+--- a/drivers/dma/sh/shdma.c
++++ b/drivers/dma/sh/shdma.c
+@@ -381,6 +381,17 @@ static bool sh_dmae_chan_irq(struct shdma_chan *schan, int irq)
+       return true;
+ }
++static size_t sh_dmae_get_partial(struct shdma_chan *schan,
++                                struct shdma_desc *sdesc)
++{
++      struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
++                                                  shdma_chan);
++      struct sh_dmae_desc *sh_desc = container_of(sdesc,
++                                      struct sh_dmae_desc, shdma_desc);
++      return (sh_desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
++              sh_chan->xmit_shift;
++}
++
+ /* Called from error IRQ or NMI */
+ static bool sh_dmae_reset(struct sh_dmae_device *shdev)
+ {
+@@ -632,6 +643,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
+       .start_xfer = sh_dmae_start_xfer,
+       .embedded_desc = sh_dmae_embedded_desc,
+       .chan_irq = sh_dmae_chan_irq,
++      .get_partial = sh_dmae_get_partial,
+ };
+ static int __devinit sh_dmae_probe(struct platform_device *pdev)
+diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
+index 93f9821..a3728bf 100644
+--- a/include/linux/shdma-base.h
++++ b/include/linux/shdma-base.h
+@@ -50,6 +50,7 @@ struct shdma_desc {
+       struct list_head node;
+       struct dma_async_tx_descriptor async_tx;
+       enum dma_transfer_direction direction;
++      size_t partial;
+       dma_cookie_t cookie;
+       int chunks;
+       int mark;
+@@ -98,6 +99,7 @@ struct shdma_ops {
+       void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
+       struct shdma_desc *(*embedded_desc)(void *, int);
+       bool (*chan_irq)(struct shdma_chan *, int);
++      size_t (*get_partial)(struct shdma_chan *, struct shdma_desc *);
+ };
+ struct shdma_dev {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch b/patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch
new file mode 100644 (file)
index 0000000..0b342dd
--- /dev/null
@@ -0,0 +1,77 @@
+From f51d4dcccbe271ab892444ddb9821b2e8b976c04 Mon Sep 17 00:00:00 2001
+From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com>
+Date: Fri, 6 Apr 2012 09:59:14 +0900
+Subject: serial: sh-sci: modify sci_break_ctl()
+
+SCIF modules which have SCSPTR can output the break signal. Now that we
+have a way of determining port features/capabilities, add trivial break
+control via SCSPTR support. Tested on sh7757lcr.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit bbb4ce50f3169b08764f9965fd5b9655646d545a)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/sh-sci.c | 30 ++++++++++++++++++++++++++----
+ include/linux/serial_sci.h  |  2 ++
+ 2 files changed, 28 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index 3158e17..3e471fc 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -1564,10 +1564,32 @@ static void sci_enable_ms(struct uart_port *port)
+ static void sci_break_ctl(struct uart_port *port, int break_state)
+ {
+-      /*
+-       * Not supported by hardware. Most parts couple break and rx
+-       * interrupts together, with break detection always enabled.
+-       */
++      struct sci_port *s = to_sci_port(port);
++      unsigned short scscr, scsptr;
++
++      switch (s->cfg->regtype) {
++      case SCIx_SH4_SCIF_REGTYPE:
++              scsptr = serial_port_in(port, SCSPTR);
++              scscr = serial_port_in(port, SCSCR);
++
++              if (break_state == -1) {
++                      scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
++                      scscr &= ~SCSCR_TE;
++              } else {
++                      scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO;
++                      scscr |= SCSCR_TE;
++              }
++
++              serial_port_out(port, SCSPTR, scsptr);
++              serial_port_out(port, SCSCR, scscr);
++              break;
++      default:
++              /*
++               * Not supported by hardware. Most parts couple break and rx
++               * interrupts together, with break detection always enabled.
++               */
++              break;
++      }
+ }
+ #ifdef CONFIG_SERIAL_SH_SCI_DMA
+diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
+index 7877907..eb763ad 100644
+--- a/include/linux/serial_sci.h
++++ b/include/linux/serial_sci.h
+@@ -52,6 +52,8 @@ enum {
+ /* SCSPTR, optional */
+ #define SCSPTR_RTSIO  (1 << 7)
+ #define SCSPTR_CTSIO  (1 << 5)
++#define SCSPTR_SPB2IO (1 << 1)
++#define SCSPTR_SPB2DT (1 << 0)
+ /* Offsets into the sci_port->irqs array */
+ enum {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch b/patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch
new file mode 100644 (file)
index 0000000..807ce53
--- /dev/null
@@ -0,0 +1,77 @@
+From 771d21f0510973f1da8789ad877a0fa806aa1ec7 Mon Sep 17 00:00:00 2001
+From: "Shimoda, Yoshihiro" <yoshihiro.shimoda.uh@renesas.com>
+Date: Thu, 12 Apr 2012 19:19:21 +0900
+Subject: serial: sh-sci: Update break_ctl handling for all SCSPTR-capable
+ regtypes.
+
+This updates the earlier break_ctl support regardless of regtype so long
+as the requisite SCSPTR exists. This is the same approach used by
+sci_init_pins() for providing a generic solution now that we're able to
+detect register capabilities on a per-port basis.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit a4e02f6d83d4fcdb13bcaba76878fc5ea0da9911)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/sh-sci.c | 36 ++++++++++++++++++------------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index 3e471fc..be31d85 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -1565,31 +1565,31 @@ static void sci_enable_ms(struct uart_port *port)
+ static void sci_break_ctl(struct uart_port *port, int break_state)
+ {
+       struct sci_port *s = to_sci_port(port);
++      struct plat_sci_reg *reg = sci_regmap[s->cfg->regtype] + SCSPTR;
+       unsigned short scscr, scsptr;
+-      switch (s->cfg->regtype) {
+-      case SCIx_SH4_SCIF_REGTYPE:
+-              scsptr = serial_port_in(port, SCSPTR);
+-              scscr = serial_port_in(port, SCSCR);
+-
+-              if (break_state == -1) {
+-                      scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
+-                      scscr &= ~SCSCR_TE;
+-              } else {
+-                      scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO;
+-                      scscr |= SCSCR_TE;
+-              }
+-
+-              serial_port_out(port, SCSPTR, scsptr);
+-              serial_port_out(port, SCSCR, scscr);
+-              break;
+-      default:
++      /* check wheter the port has SCSPTR */
++      if (!reg->size) {
+               /*
+                * Not supported by hardware. Most parts couple break and rx
+                * interrupts together, with break detection always enabled.
+                */
+-              break;
++              return;
+       }
++
++      scsptr = serial_port_in(port, SCSPTR);
++      scscr = serial_port_in(port, SCSCR);
++
++      if (break_state == -1) {
++              scsptr = (scsptr | SCSPTR_SPB2IO) & ~SCSPTR_SPB2DT;
++              scscr &= ~SCSCR_TE;
++      } else {
++              scsptr = (scsptr | SCSPTR_SPB2DT) & ~SCSPTR_SPB2IO;
++              scscr |= SCSCR_TE;
++      }
++
++      serial_port_out(port, SCSPTR, scsptr);
++      serial_port_out(port, SCSCR, scscr);
+ }
+ #ifdef CONFIG_SERIAL_SH_SCI_DMA
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch b/patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch
new file mode 100644 (file)
index 0000000..990a00f
--- /dev/null
@@ -0,0 +1,63 @@
+From 0491f004737edadd928f7d46f5e9f0f8f5f054e0 Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 18 May 2012 18:21:06 +0900
+Subject: serial: sh-sci: Fix for port types without BRI interrupts.
+
+In doing the evt2irq() + muxed vector conversion for various port types
+it became apparent that some of the legacy port types will presently
+error out due to the irq requesting logic attempting to acquire the
+non-existent BRI IRQ. This adds some sanity checks to the request/free
+path to ensure that non-existence of a source in itself is not an error.
+
+This should restore functionality for legacy PORT_SCI ports.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 0e8963de1fe95e7fbc30c79c1dbc7cb1ea0cf699)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/sh-sci.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index be31d85..4604153 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -1052,9 +1052,17 @@ static int sci_request_irq(struct sci_port *port)
+               if (SCIx_IRQ_IS_MUXED(port)) {
+                       i = SCIx_MUX_IRQ;
+                       irq = up->irq;
+-              } else
++              } else {
+                       irq = port->cfg->irqs[i];
++                      /*
++                       * Certain port types won't support all of the
++                       * available interrupt sources.
++                       */
++                      if (unlikely(!irq))
++                              continue;
++              }
++
+               desc = sci_irq_desc + i;
+               port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s",
+                                           dev_name(up->dev), desc->desc);
+@@ -1094,6 +1102,15 @@ static void sci_free_irq(struct sci_port *port)
+        * IRQ first.
+        */
+       for (i = 0; i < SCIx_NR_IRQS; i++) {
++              unsigned int irq = port->cfg->irqs[i];
++
++              /*
++               * Certain port types won't support all of the available
++               * interrupt sources.
++               */
++              if (unlikely(!irq))
++                      continue;
++
+               free_irq(port->cfg->irqs[i], port);
+               kfree(port->irqstr[i]);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch b/patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch
new file mode 100644 (file)
index 0000000..fc41e2d
--- /dev/null
@@ -0,0 +1,102 @@
+From 61760a1e6363eeb42b29b76176e3ec4ac837753b Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 13 Jun 2012 00:28:23 +0200
+Subject: serial: sh-sci: Fix probe error paths
+
+When probing fails, the driver must not try to cleanup resources that
+have not been initialized. Fix this.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 6dae14216c85eea13db7b12c469475c5d30e5499)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/sh-sci.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index 4604153..27df2ad 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -2179,6 +2179,16 @@ static int __devinit sci_init_single(struct platform_device *dev,
+       return 0;
+ }
++static void sci_cleanup_single(struct sci_port *port)
++{
++      sci_free_gpios(port);
++
++      clk_put(port->iclk);
++      clk_put(port->fclk);
++
++      pm_runtime_disable(port->port.dev);
++}
++
+ #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+ static void serial_console_putchar(struct uart_port *port, int ch)
+ {
+@@ -2360,14 +2370,10 @@ static int sci_remove(struct platform_device *dev)
+       cpufreq_unregister_notifier(&port->freq_transition,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
+-      sci_free_gpios(port);
+-
+       uart_remove_one_port(&sci_uart_driver, &port->port);
+-      clk_put(port->iclk);
+-      clk_put(port->fclk);
++      sci_cleanup_single(port);
+-      pm_runtime_disable(&dev->dev);
+       return 0;
+ }
+@@ -2392,7 +2398,13 @@ static int __devinit sci_probe_single(struct platform_device *dev,
+       if (ret)
+               return ret;
+-      return uart_add_one_port(&sci_uart_driver, &sciport->port);
++      ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
++      if (ret) {
++              sci_cleanup_single(sciport);
++              return ret;
++      }
++
++      return 0;
+ }
+ static int __devinit sci_probe(struct platform_device *dev)
+@@ -2413,24 +2425,22 @@ static int __devinit sci_probe(struct platform_device *dev)
+       ret = sci_probe_single(dev, dev->id, p, sp);
+       if (ret)
+-              goto err_unreg;
++              return ret;
+       sp->freq_transition.notifier_call = sci_notifier;
+       ret = cpufreq_register_notifier(&sp->freq_transition,
+                                       CPUFREQ_TRANSITION_NOTIFIER);
+-      if (unlikely(ret < 0))
+-              goto err_unreg;
++      if (unlikely(ret < 0)) {
++              sci_cleanup_single(sp);
++              return ret;
++      }
+ #ifdef CONFIG_SH_STANDARD_BIOS
+       sh_bios_gdb_detach();
+ #endif
+       return 0;
+-
+-err_unreg:
+-      sci_remove(dev);
+-      return ret;
+ }
+ static int sci_suspend(struct device *dev)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch b/patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch
new file mode 100644 (file)
index 0000000..7ca587c
--- /dev/null
@@ -0,0 +1,39 @@
+From e78402772bb6c357710275ae6958fd9eaab70036 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Wed, 13 Jun 2012 00:28:24 +0200
+Subject: serial: sh-sci: Make probe fail for ports that exceed the maximum
+ count
+
+The driver supports a maximum number of ports configurable at compile
+time. Make sure the probe() method fails when registering a port that
+exceeds the maximum instead of returning success without registering the
+port.
+
+This fixes a crash at system suspend time, when the driver tried to
+suspend a non-registered port using the UART core.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit b6c5ef6f6d3e46d6200b141c30ac000a11b851df)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/sh-sci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index 27df2ad..1bd9163 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -2391,7 +2391,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
+                          index+1, SCI_NPORTS);
+               dev_notice(&dev->dev, "Consider bumping "
+                          "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
+-              return 0;
++              return -EINVAL;
+       }
+       ret = sci_init_single(dev, sciport, index, p);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch b/patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch
new file mode 100644 (file)
index 0000000..75ad2f3
--- /dev/null
@@ -0,0 +1,53 @@
+From d9a397f8913cef21e0cc251856d5e3e709d057f8 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:17 +0200
+Subject: serial: sh-sci: prepare for conversion to the shdma base library
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Alan Cox <alan@linux.intel.com>
+Acked-by: Paul Mundt <lethal@linux-sh.org>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit d6fa5a4e7ab605370fd6c982782f84ef2e6660e7)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/sh-sci.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index 1bd9163..d4d8c94 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -1615,9 +1615,9 @@ static bool filter(struct dma_chan *chan, void *slave)
+       struct sh_dmae_slave *param = slave;
+       dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
+-              param->slave_id);
++              param->shdma_slave.slave_id);
+-      chan->private = param;
++      chan->private = &param->shdma_slave;
+       return true;
+ }
+@@ -1656,7 +1656,7 @@ static void sci_request_dma(struct uart_port *port)
+       param = &s->param_tx;
+       /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
+-      param->slave_id = s->cfg->dma_slave_tx;
++      param->shdma_slave.slave_id = s->cfg->dma_slave_tx;
+       s->cookie_tx = -EINVAL;
+       chan = dma_request_channel(mask, filter, param);
+@@ -1684,7 +1684,7 @@ static void sci_request_dma(struct uart_port *port)
+       param = &s->param_rx;
+       /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
+-      param->slave_id = s->cfg->dma_slave_rx;
++      param->shdma_slave.slave_id = s->cfg->dma_slave_rx;
+       chan = dma_request_channel(mask, filter, param);
+       dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch b/patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch
new file mode 100644 (file)
index 0000000..543dee3
--- /dev/null
@@ -0,0 +1,51 @@
+From 3e91d8139916610c1a34ff1359fb866b2bc82bab Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Mon, 30 Jul 2012 21:28:47 +0200
+Subject: serial: sh-sci: fix compilation breakage, when DMA is enabled
+
+A recent commit:
+
+commit d6fa5a4e7ab605370fd6c982782f84ef2e6660e7
+Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+    serial: sh-sci: prepare for conversion to the shdma base library
+
+is not sufficient to update the sh-sci driver to the new shdma driver
+layout. This caused compilation breakage, when CONFIG_SERIAL_SH_SCI_DMA
+is enabled. This patch trivially fixes the problem by updating the DMA
+descriptor manipulation code.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit 4dc4c51675c137c30838425ecc8d471ff5eb138b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/tty/serial/sh-sci.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
+index d4d8c94..9be296c 100644
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -25,6 +25,7 @@
+ #include <linux/module.h>
+ #include <linux/errno.h>
++#include <linux/sh_dma.h>
+ #include <linux/timer.h>
+ #include <linux/interrupt.h>
+ #include <linux/tty.h>
+@@ -1410,8 +1411,8 @@ static void work_fn_rx(struct work_struct *work)
+               /* Handle incomplete DMA receive */
+               struct tty_struct *tty = port->state->port.tty;
+               struct dma_chan *chan = s->chan_rx;
+-              struct sh_desc *sh_desc = container_of(desc, struct sh_desc,
+-                                                     async_tx);
++              struct shdma_desc *sh_desc = container_of(desc,
++                                      struct shdma_desc, async_tx);
+               unsigned long flags;
+               int count;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch b/patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch
new file mode 100644 (file)
index 0000000..5c96ddc
--- /dev/null
@@ -0,0 +1,53 @@
+From 925ce819e01d210634e6108067368107fe17fd8c Mon Sep 17 00:00:00 2001
+From: Lee Jones <lee.jones@linaro.org>
+Date: Tue, 29 May 2012 18:47:37 +0000
+Subject: net/smsc911x: Repair broken failure paths
+
+Current failure paths attempt to free resources which we failed to request
+and disable resources which we failed to enable ones. This leads to kernel
+oops/panic. This patch does some simple re-ordering to prevent this from
+happening.
+
+Cc: netdev@vger.kernel.org
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 2e1d4a065a77d076a679df22a4eddbc7e33cad98)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/smsc/smsc911x.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
+index cd3defb..245c700 100644
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -2389,11 +2389,11 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
+       retval = smsc911x_request_resources(pdev);
+       if (retval)
+-              goto out_return_resources;
++              goto out_request_resources_fail;
+       retval = smsc911x_enable_resources(pdev);
+       if (retval)
+-              goto out_disable_resources;
++              goto out_enable_resources_fail;
+       if (pdata->ioaddr == NULL) {
+               SMSC_WARN(pdata, probe, "Error smsc911x base address invalid");
+@@ -2500,8 +2500,9 @@ out_free_irq:
+       free_irq(dev->irq, dev);
+ out_disable_resources:
+       (void)smsc911x_disable_resources(pdev);
+-out_return_resources:
++out_enable_resources_fail:
+       smsc911x_free_resources(pdev);
++out_request_resources_fail:
+       platform_set_drvdata(pdev, NULL);
+       iounmap(pdata->ioaddr);
+       free_netdev(dev);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch b/patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch
new file mode 100644 (file)
index 0000000..b80d5b0
--- /dev/null
@@ -0,0 +1,70 @@
+From 89b2c2592f45401b0862a70a6d71e4c81274c1a3 Mon Sep 17 00:00:00 2001
+From: Matthias Brugger <mbrugger@iseebcn.com>
+Date: Fri, 22 Jun 2012 01:10:15 +0000
+Subject: smsc911x.c: encapsulate enable irq calls
+
+We encapsulate enbale irq functionality in a function call.
+As on probe the interrupts will be disabled twice, we delete
+one.
+
+Signed-off-by: Matthias Brugger <mbrugger@iseebcn.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 8e27628ecf883b9e5825103e40e6f86bf8225f1a)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/net/ethernet/smsc/smsc911x.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
+index 245c700..759e9b4 100644
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -1442,6 +1442,14 @@ smsc911x_set_hw_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6])
+       smsc911x_mac_write(pdata, ADDRL, mac_low32);
+ }
++static void smsc911x_disable_irq_chip(struct net_device *dev)
++{
++      struct smsc911x_data *pdata = netdev_priv(dev);
++
++      smsc911x_reg_write(pdata, INT_EN, 0);
++      smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
++}
++
+ static int smsc911x_open(struct net_device *dev)
+ {
+       struct smsc911x_data *pdata = netdev_priv(dev);
+@@ -1494,8 +1502,7 @@ static int smsc911x_open(struct net_device *dev)
+       spin_unlock_irq(&pdata->mac_lock);
+       /* Initialise irqs, but leave all sources disabled */
+-      smsc911x_reg_write(pdata, INT_EN, 0);
+-      smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
++      smsc911x_disable_irq_chip(dev);
+       /* Set interrupt deassertion to 100uS */
+       intcfg = ((10 << 24) | INT_CFG_IRQ_EN_);
+@@ -2214,9 +2221,6 @@ static int __devinit smsc911x_init(struct net_device *dev)
+       if (smsc911x_soft_reset(pdata))
+               return -ENODEV;
+-      /* Disable all interrupt sources until we bring the device up */
+-      smsc911x_reg_write(pdata, INT_EN, 0);
+-
+       ether_setup(dev);
+       dev->flags |= IFF_MULTICAST;
+       netif_napi_add(dev, &pdata->napi, smsc911x_poll, SMSC_NAPI_WEIGHT);
+@@ -2433,8 +2437,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
+       smsc911x_reg_write(pdata, INT_CFG, intcfg);
+       /* Ensure interrupts are globally disabled before connecting ISR */
+-      smsc911x_reg_write(pdata, INT_EN, 0);
+-      smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
++      smsc911x_disable_irq_chip(dev);
+       retval = request_irq(dev->irq, smsc911x_irqhandler,
+                            irq_flags | IRQF_SHARED, dev->name, dev);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch b/patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch
new file mode 100644 (file)
index 0000000..d7ad043
--- /dev/null
@@ -0,0 +1,47 @@
+From 3dc719e07177476e63995abda41f8d86f7c6056d Mon Sep 17 00:00:00 2001
+From: Paul Mundt <lethal@linux-sh.org>
+Date: Fri, 25 May 2012 13:39:09 +0900
+Subject: clocksource: sh_tmu: Convert timer lock to raw spinlock.
+
+Signed-off-by: Paul Mundt <lethal@linux-sh.org>
+(cherry picked from commit c2225a57e596a308424e59abc7e864f866fe4493)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/clocksource/sh_tmu.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
+index 97f54b6..852b3f1 100644
+--- a/drivers/clocksource/sh_tmu.c
++++ b/drivers/clocksource/sh_tmu.c
+@@ -45,7 +45,7 @@ struct sh_tmu_priv {
+       struct clocksource cs;
+ };
+-static DEFINE_SPINLOCK(sh_tmu_lock);
++static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
+ #define TSTR -1 /* shared register */
+ #define TCOR  0 /* channel register */
+@@ -95,7 +95,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
+       unsigned long flags, value;
+       /* start stop register shared by multiple timer channels */
+-      spin_lock_irqsave(&sh_tmu_lock, flags);
++      raw_spin_lock_irqsave(&sh_tmu_lock, flags);
+       value = sh_tmu_read(p, TSTR);
+       if (start)
+@@ -104,7 +104,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
+               value &= ~(1 << cfg->timer_bit);
+       sh_tmu_write(p, TSTR, value);
+-      spin_unlock_irqrestore(&sh_tmu_lock, flags);
++      raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
+ }
+ static int sh_tmu_enable(struct sh_tmu_priv *p)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch b/patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch
new file mode 100644 (file)
index 0000000..792f032
--- /dev/null
@@ -0,0 +1,52 @@
+From 611af69d5a747a3c8d6268a006dd0d913257fe02 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 19:10:35 +0200
+Subject: mmc: tmio: use MMC opcode defines instead of numbers
+
+mmc.h defines macros for most frequently used MMC opcodes. Use them instead
+of hard-coded numbers.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 0f506a96693d8ad4aeccbd98dbd54a3c7357cfa8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 9a7996a..0ad3917 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -36,6 +36,7 @@
+ #include <linux/mfd/tmio.h>
+ #include <linux/mmc/cd-gpio.h>
+ #include <linux/mmc/host.h>
++#include <linux/mmc/mmc.h>
+ #include <linux/mmc/tmio.h>
+ #include <linux/module.h>
+ #include <linux/pagemap.h>
+@@ -305,8 +306,8 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
+       int c = cmd->opcode;
+       u32 irq_mask = TMIO_MASK_CMD;
+-      /* Command 12 is handled by hardware */
+-      if (cmd->opcode == 12 && !cmd->arg) {
++      /* CMD12 is handled by hardware */
++      if (cmd->opcode == MMC_STOP_TRANSMISSION && !cmd->arg) {
+               sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
+               return 0;
+       }
+@@ -449,7 +450,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
+       }
+       if (stop) {
+-              if (stop->opcode == 12 && !stop->arg)
++              if (stop->opcode == MMC_STOP_TRANSMISSION && !stop->arg)
+                       sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
+               else
+                       BUG();
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch b/patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch
new file mode 100644 (file)
index 0000000..325a3c1
--- /dev/null
@@ -0,0 +1,43 @@
+From a43c0fe8cb2e7a3312b979c3b1fe1ab5b762994a Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 10 Jul 2012 22:54:11 -0400
+Subject: mmc: cd-gpio: pass IRQF_ONESHOT to request_threaded_irq()
+
+Fix a boot regression on Mackerel boards with sh_mobile_sdhi
+in existing kernels causing:
+
+genirq: Threaded irq requested with handler=NULL and !ONESHOT for irq XXX
+
+caused by 1c6c6952 (genirq: Reject bogus threaded irq requests).
+
+This is backported from Guennadi's patch:
+"mmc: extend and rename cd-gpio helpers to handle more slot GPIO functions"
+
+Reported-by: Rafael J. Wysocki <rjw@sisk.pl>
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 623b51fc8642fd3c795fa9903be3adaa537ad9c5)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/core/cd-gpio.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
+index f13e38d..8f5dc08 100644
+--- a/drivers/mmc/core/cd-gpio.c
++++ b/drivers/mmc/core/cd-gpio.c
+@@ -50,8 +50,8 @@ int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio)
+               goto egpioreq;
+       ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
+-                                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+-                                 cd->label, host);
++                                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
++                                 IRQF_ONESHOT, cd->label, host);
+       if (ret < 0)
+               goto eirqreq;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch b/patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch
new file mode 100644 (file)
index 0000000..7a17b5a
--- /dev/null
@@ -0,0 +1,199 @@
+From 06a2252e0baf7bc5e4dd3b8c31898edcc838b518 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Mon, 30 Apr 2012 23:31:57 +0200
+Subject: mmc: extend and rename cd-gpio helpers to handle more slot GPIO
+ functions
+
+GPIOs can be used in MMC/SD-card slots not only for hotplug detection, but
+also to implement the write-protection pin. Rename cd-gpio helpers to
+slot-gpio to make addition of further slot GPIO functions possible.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit fd0ea65d3e675e479e022b6cfc9ebe1864c76afc)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/core/Makefile                    |  2 +-
+ drivers/mmc/core/{cd-gpio.c => slot-gpio.c}  | 48 ++++++++++++++--------------
+ drivers/mmc/host/tmio_mmc_pio.c              |  6 ++--
+ include/linux/mmc/{cd-gpio.h => slot-gpio.h} |  8 ++---
+ 4 files changed, 32 insertions(+), 32 deletions(-)
+ rename drivers/mmc/core/{cd-gpio.c => slot-gpio.c} (53%)
+ rename include/linux/mmc/{cd-gpio.h => slot-gpio.h} (68%)
+
+diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
+index dca4428..38ed210 100644
+--- a/drivers/mmc/core/Makefile
++++ b/drivers/mmc/core/Makefile
+@@ -7,6 +7,6 @@ mmc_core-y                     := core.o bus.o host.o \
+                                  mmc.o mmc_ops.o sd.o sd_ops.o \
+                                  sdio.o sdio_ops.o sdio_bus.o \
+                                  sdio_cis.o sdio_io.o sdio_irq.o \
+-                                 quirks.o cd-gpio.o
++                                 quirks.o slot-gpio.o
+ mmc_core-$(CONFIG_DEBUG_FS)   += debugfs.o
+diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/slot-gpio.c
+similarity index 53%
+rename from drivers/mmc/core/cd-gpio.c
+rename to drivers/mmc/core/slot-gpio.c
+index 8f5dc08..9796710 100644
+--- a/drivers/mmc/core/cd-gpio.c
++++ b/drivers/mmc/core/slot-gpio.c
+@@ -12,72 +12,72 @@
+ #include <linux/gpio.h>
+ #include <linux/interrupt.h>
+ #include <linux/jiffies.h>
+-#include <linux/mmc/cd-gpio.h>
+ #include <linux/mmc/host.h>
++#include <linux/mmc/slot-gpio.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+-struct mmc_cd_gpio {
+-      unsigned int gpio;
+-      char label[0];
++struct mmc_gpio {
++      unsigned int cd_gpio;
++      char cd_label[0];
+ };
+-static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
++static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
+ {
+       /* Schedule a card detection after a debounce timeout */
+       mmc_detect_change(dev_id, msecs_to_jiffies(100));
+       return IRQ_HANDLED;
+ }
+-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio)
++int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+ {
+       size_t len = strlen(dev_name(host->parent)) + 4;
+-      struct mmc_cd_gpio *cd;
++      struct mmc_gpio *ctx;
+       int irq = gpio_to_irq(gpio);
+       int ret;
+       if (irq < 0)
+               return irq;
+-      cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
+-      if (!cd)
++      ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
++      if (!ctx)
+               return -ENOMEM;
+-      snprintf(cd->label, len, "%s cd", dev_name(host->parent));
++      snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
+-      ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label);
++      ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
+       if (ret < 0)
+               goto egpioreq;
+-      ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
+-                                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+-                                 IRQF_ONESHOT, cd->label, host);
++      ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
++                      IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
++                      ctx->cd_label, host);
+       if (ret < 0)
+               goto eirqreq;
+-      cd->gpio = gpio;
++      ctx->cd_gpio = gpio;
+       host->hotplug.irq = irq;
+-      host->hotplug.handler_priv = cd;
++      host->hotplug.handler_priv = ctx;
+       return 0;
+ eirqreq:
+       gpio_free(gpio);
+ egpioreq:
+-      kfree(cd);
++      kfree(ctx);
+       return ret;
+ }
+-EXPORT_SYMBOL(mmc_cd_gpio_request);
++EXPORT_SYMBOL(mmc_gpio_request_cd);
+-void mmc_cd_gpio_free(struct mmc_host *host)
++void mmc_gpio_free_cd(struct mmc_host *host)
+ {
+-      struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
++      struct mmc_gpio *ctx = host->hotplug.handler_priv;
+-      if (!cd)
++      if (!ctx)
+               return;
+       free_irq(host->hotplug.irq, host);
+-      gpio_free(cd->gpio);
+-      kfree(cd);
++      gpio_free(ctx->cd_gpio);
++      kfree(ctx);
+ }
+-EXPORT_SYMBOL(mmc_cd_gpio_free);
++EXPORT_SYMBOL(mmc_gpio_free_cd);
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 0ad3917..7ffc489 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -34,9 +34,9 @@
+ #include <linux/io.h>
+ #include <linux/irq.h>
+ #include <linux/mfd/tmio.h>
+-#include <linux/mmc/cd-gpio.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/mmc.h>
++#include <linux/mmc/slot-gpio.h>
+ #include <linux/mmc/tmio.h>
+ #include <linux/module.h>
+ #include <linux/pagemap.h>
+@@ -977,7 +977,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+       tmio_mmc_enable_mmc_irqs(_host, irq_mask);
+       if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
+-              ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio);
++              ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
+               if (ret < 0) {
+                       tmio_mmc_host_remove(_host);
+                       return ret;
+@@ -1009,7 +1009,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
+                * This means we can miss a card-eject, but this is anyway
+                * possible, because of delayed processing of hotplug events.
+                */
+-              mmc_cd_gpio_free(mmc);
++              mmc_gpio_free_cd(mmc);
+       if (!host->native_hotplug)
+               pm_runtime_get_sync(&pdev->dev);
+diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/slot-gpio.h
+similarity index 68%
+rename from include/linux/mmc/cd-gpio.h
+rename to include/linux/mmc/slot-gpio.h
+index cefaba0..edfaa32 100644
+--- a/include/linux/mmc/cd-gpio.h
++++ b/include/linux/mmc/slot-gpio.h
+@@ -8,11 +8,11 @@
+  * published by the Free Software Foundation.
+  */
+-#ifndef MMC_CD_GPIO_H
+-#define MMC_CD_GPIO_H
++#ifndef MMC_SLOT_GPIO_H
++#define MMC_SLOT_GPIO_H
+ struct mmc_host;
+-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio);
+-void mmc_cd_gpio_free(struct mmc_host *host);
++int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
++void mmc_gpio_free_cd(struct mmc_host *host);
+ #endif
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch b/patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch
new file mode 100644 (file)
index 0000000..a3be21c
--- /dev/null
@@ -0,0 +1,66 @@
+From b1c9b658ce7354835934388f45df16bfd25a37fc Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 12 Jun 2012 23:29:35 +0200
+Subject: mmc: tmio: Don't access hardware registers after stopping clocks
+
+The tmio_mmc_set_ios() function configures the MMC power, clock and bus
+width. When the mmc core requests the driver to power off the card, we
+inform runtime PM, that the controller can be suspended. This can lead
+to the MSTP clock being turned off.
+
+Writing to any 16-bit hardware registers with the MSTP clock off leads
+to timeouts and errors being printed to the kernel log. This can occur
+both when stopping the MMC clock and when configuring the bus width.
+
+To fix this, stop the MMC clock before calling put_runtime_pm(), and
+skip bus width configuration when power is off.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Tested-by: Simon Horman <horms@verge.net.au>
+Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 6de707f200f73af7a58b58b3a5b956cff7b6e228)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 7ffc489..4f26edf 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -811,19 +811,21 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+               if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
+                       host->set_pwr(host->pdev, 0);
+               if (host->power) {
++                      tmio_mmc_clk_stop(host);
+                       host->power = false;
+                       pm_runtime_put(dev);
+               }
+-              tmio_mmc_clk_stop(host);
+       }
+-      switch (ios->bus_width) {
+-      case MMC_BUS_WIDTH_1:
+-              sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
+-      break;
+-      case MMC_BUS_WIDTH_4:
+-              sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
+-      break;
++      if (host->power) {
++              switch (ios->bus_width) {
++              case MMC_BUS_WIDTH_1:
++                      sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
++              break;
++              case MMC_BUS_WIDTH_4:
++                      sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
++              break;
++              }
+       }
+       /* Let things settle. delay taken from winCE driver */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch b/patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch
new file mode 100644 (file)
index 0000000..0ccb9cd
--- /dev/null
@@ -0,0 +1,60 @@
+From 13b6cca29fb687ec7821001eb9bc38ba8a6270a1 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 19:10:30 +0200
+Subject: mmc: tmio: don't needlessly enable interrupts during probing
+
+We don't have to force-enable MMC interrupts in our .probe() method,
+mmc_add_host() will trigger card detection, that will enable all the
+necessary interrupts.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit e0337cc8b02fcb3f725746735db84d6d1b6b9196)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 4f26edf..4318c1a 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -951,6 +951,17 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+       _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK);
+       tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
++
++      /* Unmask the IRQs we want to know about */
++      if (!_host->chan_rx)
++              irq_mask |= TMIO_MASK_READOP;
++      if (!_host->chan_tx)
++              irq_mask |= TMIO_MASK_WRITEOP;
++      if (!_host->native_hotplug)
++              irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
++
++      _host->sdcard_irq_mask &= ~irq_mask;
++
+       if (pdata->flags & TMIO_MMC_SDIO_IRQ)
+               tmio_mmc_enable_sdio_irq(mmc, 0);
+@@ -968,16 +979,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+       dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
+-      /* Unmask the IRQs we want to know about */
+-      if (!_host->chan_rx)
+-              irq_mask |= TMIO_MASK_READOP;
+-      if (!_host->chan_tx)
+-              irq_mask |= TMIO_MASK_WRITEOP;
+-      if (!_host->native_hotplug)
+-              irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
+-
+-      tmio_mmc_enable_mmc_irqs(_host, irq_mask);
+-
+       if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
+               ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
+               if (ret < 0) {
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch b/patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch
new file mode 100644 (file)
index 0000000..a5ee720
--- /dev/null
@@ -0,0 +1,66 @@
+From 9000384872b9fb65e1fb9b7042da31d2d4023c7b Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 19:10:32 +0200
+Subject: mmc: sdhi: implement tmio-mmc clock enable-update and disable
+ callbacks
+
+Instead of delivering one static clock frequency value, read from the
+hardware during probing, enable the tmio-mmc driver to re-read the
+frequency dynamically.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 56c492879318f43b1a7911675ff30fb0ede123b5)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mobile_sdhi.c | 24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index 934b68e..d8b167c 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -39,6 +39,27 @@ struct sh_mobile_sdhi {
+       struct tmio_mmc_dma dma_priv;
+ };
++static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f)
++{
++      struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
++      struct tmio_mmc_host *host = mmc_priv(mmc);
++      struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
++      int ret = clk_enable(priv->clk);
++      if (ret < 0)
++              return ret;
++
++      *f = clk_get_rate(priv->clk);
++      return 0;
++}
++
++static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
++{
++      struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
++      struct tmio_mmc_host *host = mmc_priv(mmc);
++      struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
++      clk_disable(priv->clk);
++}
++
+ static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
+ {
+       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+@@ -132,9 +153,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+               goto eclkget;
+       }
+-      mmc_data->hclk = clk_get_rate(priv->clk);
+       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
+       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
++      mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
++      mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
+       mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
+       if (p) {
+               mmc_data->flags = p->tmio_flags;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch b/patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch
new file mode 100644 (file)
index 0000000..bf6f327
--- /dev/null
@@ -0,0 +1,120 @@
+From 2351d645d302b589c88ca21a2ea3198fd7bfa752 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 19:10:31 +0200
+Subject: mmc: tmio: add callbacks to enable-update and disable the interface
+ clock
+
+Every time the clock is enabled after possibly being disabled, we have
+to re-read its frequency and update our configuration.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 8c102a964655b1a8df41b1f9e2355657471a45e3)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 35 ++++++++++++++++++++++++++++++++---
+ include/linux/mfd/tmio.h        |  3 +++
+ 2 files changed, 35 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 4318c1a..c6c0334 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -752,6 +752,22 @@ fail:
+       mmc_request_done(mmc, mrq);
+ }
++static int tmio_mmc_clk_update(struct mmc_host *mmc)
++{
++      struct tmio_mmc_host *host = mmc_priv(mmc);
++      struct tmio_mmc_data *pdata = host->pdata;
++      int ret;
++
++      if (!pdata->clk_enable)
++              return -ENOTSUPP;
++
++      ret = pdata->clk_enable(host->pdev, &mmc->f_max);
++      if (!ret)
++              mmc->f_min = mmc->f_max / 512;
++
++      return ret;
++}
++
+ /* Set MMC clock / power.
+  * Note: This controller uses a simple divider scheme therefore it cannot
+  * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
+@@ -798,6 +814,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+        */
+       if (ios->power_mode == MMC_POWER_ON && ios->clock) {
+               if (!host->power) {
++                      tmio_mmc_clk_update(mmc);
+                       pm_runtime_get_sync(dev);
+                       host->power = true;
+               }
+@@ -811,9 +828,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+               if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
+                       host->set_pwr(host->pdev, 0);
+               if (host->power) {
++                      struct tmio_mmc_data *pdata = host->pdata;
+                       tmio_mmc_clk_stop(host);
+                       host->power = false;
+                       pm_runtime_put(dev);
++                      if (pdata->clk_disable)
++                              pdata->clk_disable(host->pdev);
+               }
+       }
+@@ -907,8 +927,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+       mmc->ops = &tmio_mmc_ops;
+       mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
+-      mmc->f_max = pdata->hclk;
+-      mmc->f_min = mmc->f_max / 512;
+       mmc->max_segs = 32;
+       mmc->max_blk_size = 512;
+       mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
+@@ -930,6 +948,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+       if (ret < 0)
+               goto pm_disable;
++      if (tmio_mmc_clk_update(mmc) < 0) {
++              mmc->f_max = pdata->hclk;
++              mmc->f_min = mmc->f_max / 512;
++      }
++
+       /*
+        * There are 4 different scenarios for the card detection:
+        *  1) an external gpio irq handles the cd (best for power savings)
+@@ -975,7 +998,13 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+       /* See if we also get DMA */
+       tmio_mmc_request_dma(_host, pdata);
+-      mmc_add_host(mmc);
++      ret = mmc_add_host(mmc);
++      if (pdata->clk_disable)
++              pdata->clk_disable(pdev);
++      if (ret < 0) {
++              tmio_mmc_host_remove(_host);
++              return ret;
++      }
+       dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
+diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
+index f5171db..b332c4c 100644
+--- a/include/linux/mfd/tmio.h
++++ b/include/linux/mfd/tmio.h
+@@ -110,6 +110,9 @@ struct tmio_mmc_data {
+       void (*set_clk_div)(struct platform_device *host, int state);
+       int (*get_cd)(struct platform_device *host);
+       int (*write16_hook)(struct tmio_mmc_host *host, int addr);
++      /* clock management callbacks */
++      int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
++      void (*clk_disable)(struct platform_device *pdev);
+ };
+ /*
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch b/patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch
new file mode 100644 (file)
index 0000000..dba509b
--- /dev/null
@@ -0,0 +1,62 @@
+From 399a8f308acebcabaa5c10f336668cd3f73ac273 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 19:10:34 +0200
+Subject: mmc: sdhi: do not install dummy callbacks
+
+Currently the SDHI glue for the TMIO MMC driver installs dummy .get_cd() and
+.set_pwr() callbacks even if the platform didn't supply them. This is not
+necessary, since the TMIO MMC driver itself checks for NULL callbacks. This
+is also dubious if the platform provides a regulator for SD-card power
+switching. It is better to only install those callbacks, if they are really
+provided by the platform.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 71da63e767c393c0ebbd3c65df428df0ce42a16c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mobile_sdhi.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index d8b167c..42f07fa 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -64,18 +64,14 @@ static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
+ {
+       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+-      if (p && p->set_pwr)
+-              p->set_pwr(pdev, state);
++      p->set_pwr(pdev, state);
+ }
+ static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
+ {
+       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+-      if (p && p->get_cd)
+-              return p->get_cd(pdev);
+-      else
+-              return -ENOSYS;
++      return p->get_cd(pdev);
+ }
+ static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
+@@ -153,8 +149,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+               goto eclkget;
+       }
+-      mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
+-      mmc_data->get_cd = sh_mobile_sdhi_get_cd;
++      if (p->set_pwr)
++              mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
++      if (p->get_cd)
++              mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+       mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
+       mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
+       mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch b/patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch
new file mode 100644 (file)
index 0000000..983f2ae
--- /dev/null
@@ -0,0 +1,112 @@
+From 23b39f743c1d33128add46201409eb6709b10a4f Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 02:28:43 -0400
+Subject: mmc: add a function to get regulators, supplying card's power
+
+Add a function to get regulators, supplying card's Vdd and Vccq on a
+specific host. If a Vdd supplying regulator is found, the function checks,
+whether a valid OCR mask can be obtained from it. The Vccq regulator is
+optional. A failure to get it is not fatal.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit e137788dd115dd9d21759a768dba5fff9685e587)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/core/core.c  | 23 +++++++++++++++++++++++
+ include/linux/mmc/host.h | 16 ++++++++++++++--
+ 2 files changed, 37 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
+index ba821fe..1db77e7 100644
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -1012,6 +1012,29 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
+ }
+ EXPORT_SYMBOL(mmc_regulator_set_ocr);
++int mmc_regulator_get_supply(struct mmc_host *mmc)
++{
++      struct device *dev = mmc_dev(mmc);
++      struct regulator *supply;
++      int ret;
++
++      supply = devm_regulator_get(dev, "vmmc");
++      mmc->supply.vmmc = supply;
++      mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc");
++
++      if (IS_ERR(supply))
++              return PTR_ERR(supply);
++
++      ret = mmc_regulator_get_ocrmask(supply);
++      if (ret > 0)
++              mmc->ocr_avail = ret;
++      else
++              dev_warn(mmc_dev(mmc), "Failed getting OCR mask: %d\n", ret);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
++
+ #endif /* CONFIG_REGULATOR */
+ /*
+diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
+index 0707d22..9deb725 100644
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -155,6 +155,13 @@ struct mmc_hotplug {
+       void *handler_priv;
+ };
++struct regulator;
++
++struct mmc_supply {
++      struct regulator *vmmc;         /* Card power supply */
++      struct regulator *vqmmc;        /* Optional Vccq supply */
++};
++
+ struct mmc_host {
+       struct device           *parent;
+       struct device           class_dev;
+@@ -309,6 +316,7 @@ struct mmc_host {
+ #ifdef CONFIG_REGULATOR
+       bool                    regulator_enabled; /* regulator state */
+ #endif
++      struct mmc_supply       supply;
+       struct dentry           *debugfs_root;
+@@ -357,13 +365,12 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
+       wake_up_process(host->sdio_irq_thread);
+ }
+-struct regulator;
+-
+ #ifdef CONFIG_REGULATOR
+ int mmc_regulator_get_ocrmask(struct regulator *supply);
+ int mmc_regulator_set_ocr(struct mmc_host *mmc,
+                       struct regulator *supply,
+                       unsigned short vdd_bit);
++int mmc_regulator_get_supply(struct mmc_host *mmc);
+ #else
+ static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
+ {
+@@ -376,6 +383,11 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
+ {
+       return 0;
+ }
++
++static inline int mmc_regulator_get_supply(struct mmc_host *mmc)
++{
++      return 0;
++}
+ #endif
+ int mmc_card_awake(struct mmc_host *host);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0078-mmc-tmio-add-regulator-support.patch b/patches.marzen/0078-mmc-tmio-add-regulator-support.patch
new file mode 100644 (file)
index 0000000..7c18978
--- /dev/null
@@ -0,0 +1,95 @@
+From 2f82c1eaa54c5b6eb2d1bc04cd04add57ca9ad05 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 19:10:33 +0200
+Subject: mmc: tmio: add regulator support
+
+Currently the TMIO MMC driver derives the OCR mask from the platform data
+and uses a platform callback to turn card power on and off. This patch adds
+regulator support to the driver.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Liam Girdwood <lrg@ti.com>
+Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit b958a67c6bbe0a886bebc618aac7a059cdbab418)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 37 +++++++++++++++++++++++++++++--------
+ 1 file changed, 29 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index c6c0334..b5c32b4 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -768,6 +768,18 @@ static int tmio_mmc_clk_update(struct mmc_host *mmc)
+       return ret;
+ }
++static void tmio_mmc_set_power(struct tmio_mmc_host *host, struct mmc_ios *ios)
++{
++      struct mmc_host *mmc = host->mmc;
++
++      if (host->set_pwr)
++              host->set_pwr(host->pdev, ios->power_mode != MMC_POWER_OFF);
++      if (!IS_ERR(mmc->supply.vmmc))
++              /* Errors ignored... */
++              mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
++                                    ios->power_mode ? ios->vdd : 0);
++}
++
+ /* Set MMC clock / power.
+  * Note: This controller uses a simple divider scheme therefore it cannot
+  * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
+@@ -820,13 +832,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+               }
+               tmio_mmc_set_clock(host, ios->clock);
+               /* power up SD bus */
+-              if (host->set_pwr)
+-                      host->set_pwr(host->pdev, 1);
++              tmio_mmc_set_power(host, ios);
+               /* start bus clock */
+               tmio_mmc_clk_start(host);
+       } else if (ios->power_mode != MMC_POWER_UP) {
+-              if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
+-                      host->set_pwr(host->pdev, 0);
++              if (ios->power_mode == MMC_POWER_OFF)
++                      tmio_mmc_set_power(host, ios);
+               if (host->power) {
+                       struct tmio_mmc_data *pdata = host->pdata;
+                       tmio_mmc_clk_stop(host);
+@@ -888,6 +899,19 @@ static const struct mmc_host_ops tmio_mmc_ops = {
+       .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
+ };
++static void tmio_mmc_init_ocr(struct tmio_mmc_host *host)
++{
++      struct tmio_mmc_data *pdata = host->pdata;
++      struct mmc_host *mmc = host->mmc;
++
++      mmc_regulator_get_supply(mmc);
++
++      if (!mmc->ocr_avail)
++              mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34;
++      else if (pdata->ocr_mask)
++              dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
++}
++
+ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+                                 struct platform_device *pdev,
+                                 struct tmio_mmc_data *pdata)
+@@ -933,10 +957,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+               mmc->max_segs;
+       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+       mmc->max_seg_size = mmc->max_req_size;
+-      if (pdata->ocr_mask)
+-              mmc->ocr_avail = pdata->ocr_mask;
+-      else
+-              mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++      tmio_mmc_init_ocr(_host);
+       _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
+                                 mmc->caps & MMC_CAP_NEEDS_POLL ||
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch b/patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch
new file mode 100644 (file)
index 0000000..e7c85da
--- /dev/null
@@ -0,0 +1,29 @@
+From edc14a6a575b9ed664f5618b40bb720801514acc Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 20 Jun 2012 19:10:36 +0200
+Subject: mmc: tmio: remove a duplicated comment line
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 944640d0fffb2ee2961a24c3747b1fc87c4157a8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index b5c32b4..b204012f 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -984,7 +984,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+        *  While we increment the runtime PM counter for all scenarios when
+        *  the mmc core activates us by calling an appropriate set_ios(), we
+        *  must additionally ensure that in case 2) the tmio mmc hardware stays
+-       *  additionally ensure that in case 2) the tmio mmc hardware stays
+        *  powered on during runtime for the card detection to work.
+        */
+       if (_host->native_hotplug)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0080-mmc-tmio-support-caps2-flags.patch b/patches.marzen/0080-mmc-tmio-support-caps2-flags.patch
new file mode 100644 (file)
index 0000000..ce76873
--- /dev/null
@@ -0,0 +1,45 @@
+From 84ff72e8bc8a05f00821fa782bda46ba105ce831 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 23 May 2012 10:44:37 +0200
+Subject: mmc: tmio: support caps2 flags
+
+Allow tmio mmc glue drivers to pass mmc_host::caps2 flags down to
+the mmc layer.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 02cb3221d5bb351ad9f7469453dcca7594a0fabf)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 1 +
+ include/linux/mfd/tmio.h        | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index b204012f..f8df021 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -951,6 +951,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+       mmc->ops = &tmio_mmc_ops;
+       mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
++      mmc->caps2 = pdata->capabilities2;
+       mmc->max_segs = 32;
+       mmc->max_blk_size = 512;
+       mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
+diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
+index b332c4c..d83af39 100644
+--- a/include/linux/mfd/tmio.h
++++ b/include/linux/mfd/tmio.h
+@@ -101,6 +101,7 @@ struct tmio_mmc_host;
+ struct tmio_mmc_data {
+       unsigned int                    hclk;
+       unsigned long                   capabilities;
++      unsigned long                   capabilities2;
+       unsigned long                   flags;
+       u32                             ocr_mask;       /* available voltages */
+       struct tmio_mmc_dma             *dma;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch b/patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch
new file mode 100644 (file)
index 0000000..d88c529
--- /dev/null
@@ -0,0 +1,44 @@
+From ab7669dbefddb9148fbda646fe4746a1a33f914f Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 23 May 2012 11:05:33 +0200
+Subject: mmc: sh_mobile_sdhi: support caps2 flags
+
+Let SDHI platforms specify mmc_host::caps2 flags in their platform data.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit d7d8d500bc03891c4a86da49858c46e2db256581)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mobile_sdhi.c  | 1 +
+ include/linux/mmc/sh_mobile_sdhi.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index 42f07fa..1e7c5c4 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -162,6 +162,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+                       mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
+               mmc_data->ocr_mask = p->tmio_ocr_mask;
+               mmc_data->capabilities |= p->tmio_caps;
++              mmc_data->capabilities2 |= p->tmio_caps2;
+               mmc_data->cd_gpio = p->cd_gpio;
+               if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
+diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h
+index e94e620..b65679f 100644
+--- a/include/linux/mmc/sh_mobile_sdhi.h
++++ b/include/linux/mmc/sh_mobile_sdhi.h
+@@ -23,6 +23,7 @@ struct sh_mobile_sdhi_info {
+       int dma_slave_rx;
+       unsigned long tmio_flags;
+       unsigned long tmio_caps;
++      unsigned long tmio_caps2;
+       u32 tmio_ocr_mask;      /* available MMC voltages */
+       unsigned int cd_gpio;
+       struct tmio_mmc_data *pdata;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch b/patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch
new file mode 100644 (file)
index 0000000..ee219f3
--- /dev/null
@@ -0,0 +1,121 @@
+From a19323115f3cf3e2e7f0b56ce75752ed2e682bfb Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 18:03:43 +0200
+Subject: mmc: sdhi: add OF support, make platform data optional
+
+Add primitive support for OF to the SDHI TMIO glue, which also makes it
+necessary to be able to run without platform data.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit c7bb4487a3474c03986758595fcae1cfb771b3b0)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mobile_sdhi.c | 35 +++++++++++++++++++++++------------
+ 1 file changed, 23 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index 1e7c5c4..a842939 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -21,6 +21,7 @@
+ #include <linux/kernel.h>
+ #include <linux/clk.h>
+ #include <linux/slab.h>
++#include <linux/mod_devicetable.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/mmc/host.h>
+@@ -133,12 +134,14 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+       }
+       mmc_data = &priv->mmc_data;
+-      p->pdata = mmc_data;
+-      if (p->init) {
+-              ret = p->init(pdev, &sdhi_ops);
+-              if (ret)
+-                      goto einit;
++      if (p) {
++              p->pdata = mmc_data;
++              if (p->init) {
++                      ret = p->init(pdev, &sdhi_ops);
++                      if (ret)
++                              goto einit;
++              }
+       }
+       snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
+@@ -149,10 +152,6 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+               goto eclkget;
+       }
+-      if (p->set_pwr)
+-              mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
+-      if (p->get_cd)
+-              mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+       mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
+       mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
+       mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
+@@ -164,6 +163,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+               mmc_data->capabilities |= p->tmio_caps;
+               mmc_data->capabilities2 |= p->tmio_caps2;
+               mmc_data->cd_gpio = p->cd_gpio;
++              if (p->set_pwr)
++                      mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
++              if (p->get_cd)
++                      mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+               if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
+                       priv->param_tx.slave_id = p->dma_slave_tx;
+@@ -269,7 +272,7 @@ eirq_card_detect:
+ eprobe:
+       clk_put(priv->clk);
+ eclkget:
+-      if (p->cleanup)
++      if (p && p->cleanup)
+               p->cleanup(pdev);
+ einit:
+       kfree(priv);
+@@ -284,7 +287,8 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
+       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+       int i = 0, irq;
+-      p->pdata = NULL;
++      if (p)
++              p->pdata = NULL;
+       tmio_mmc_host_remove(host);
+@@ -297,7 +301,7 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
+       clk_put(priv->clk);
+-      if (p->cleanup)
++      if (p && p->cleanup)
+               p->cleanup(pdev);
+       kfree(priv);
+@@ -312,11 +316,18 @@ static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
+       .runtime_resume = tmio_mmc_host_runtime_resume,
+ };
++static const struct of_device_id sh_mobile_sdhi_of_match[] = {
++      { .compatible = "renesas,shmobile-sdhi" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
++
+ static struct platform_driver sh_mobile_sdhi_driver = {
+       .driver         = {
+               .name   = "sh_mobile_sdhi",
+               .owner  = THIS_MODULE,
+               .pm     = &tmio_mmc_dev_pm_ops,
++              .of_match_table = sh_mobile_sdhi_of_match,
+       },
+       .probe          = sh_mobile_sdhi_probe,
+       .remove         = __devexit_p(sh_mobile_sdhi_remove),
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch b/patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch
new file mode 100644 (file)
index 0000000..03ec82d
--- /dev/null
@@ -0,0 +1,100 @@
+From 3383b414d84936e9695df242dbe081140e7b0fbd Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 15:40:15 +0200
+Subject: mmc: core: use a more generic name for slot function types and fields
+
+struct mmc_host::hotplug is becoming a generic hook for slot functions.
+Rename it accordingly.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 27410ee7e391ce650d6d0242805f080599be7ad7)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/core/host.c      |  2 ++
+ drivers/mmc/core/slot-gpio.c |  8 ++++----
+ include/linux/mmc/host.h     | 17 ++++++++++++++---
+ 3 files changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
+index 91c84c7..b8c5290 100644
+--- a/drivers/mmc/core/host.c
++++ b/drivers/mmc/core/host.c
+@@ -327,6 +327,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+       mmc_host_clk_init(host);
++      host->slot.cd_irq = -EINVAL;
++
+       spin_lock_init(&host->lock);
+       init_waitqueue_head(&host->wq);
+       INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
+index 9796710..468e5a0 100644
+--- a/drivers/mmc/core/slot-gpio.c
++++ b/drivers/mmc/core/slot-gpio.c
+@@ -56,8 +56,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+               goto eirqreq;
+       ctx->cd_gpio = gpio;
+-      host->hotplug.irq = irq;
+-      host->hotplug.handler_priv = ctx;
++      host->slot.cd_irq = irq;
++      host->slot.handler_priv = ctx;
+       return 0;
+@@ -71,12 +71,12 @@ EXPORT_SYMBOL(mmc_gpio_request_cd);
+ void mmc_gpio_free_cd(struct mmc_host *host)
+ {
+-      struct mmc_gpio *ctx = host->hotplug.handler_priv;
++      struct mmc_gpio *ctx = host->slot.handler_priv;
+       if (!ctx)
+               return;
+-      free_irq(host->hotplug.irq, host);
++      free_irq(host->slot.cd_irq, host);
+       gpio_free(ctx->cd_gpio);
+       kfree(ctx);
+ }
+diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
+index 9deb725..90b6a38 100644
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -150,8 +150,19 @@ struct mmc_async_req {
+       int (*err_check) (struct mmc_card *, struct mmc_async_req *);
+ };
+-struct mmc_hotplug {
+-      unsigned int irq;
++/**
++ * struct mmc_slot - MMC slot functions
++ *
++ * @cd_irq:           MMC/SD-card slot hotplug detection IRQ or -EINVAL
++ * @handler_priv:     MMC/SD-card slot context
++ *
++ * Some MMC/SD host controllers implement slot-functions like card and
++ * write-protect detection natively. However, a large number of controllers
++ * leave these functions to the CPU. This struct provides a hook to attach
++ * such slot-function drivers.
++ */
++struct mmc_slot {
++      int cd_irq;
+       void *handler_priv;
+ };
+@@ -297,7 +308,7 @@ struct mmc_host {
+       struct delayed_work     detect;
+       int                     detect_change;  /* card detect flag */
+-      struct mmc_hotplug      hotplug;
++      struct mmc_slot         slot;
+       const struct mmc_bus_ops *bus_ops;      /* current bus driver */
+       unsigned int            bus_refs;       /* reference counter */
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch b/patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch
new file mode 100644 (file)
index 0000000..b0886e5
--- /dev/null
@@ -0,0 +1,33 @@
+From ecce3df848ddf973eae9260a50fdd16cbb860f3f Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 15:49:52 +0200
+Subject: mmc: add two capability flags for CD and WP signal polarity
+
+To handle CD and WP SD/MMC slot pins we need generic flags to specify their
+polarity.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 5c08d7fae0815cd163a98e05c8d94fc0de77ff67)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ include/linux/mmc/host.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
+index 90b6a38..c1a03ee 100644
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -256,6 +256,8 @@ struct mmc_host {
+ #define MMC_CAP2_BROKEN_VOLTAGE       (1 << 7)        /* Use the broken voltage */
+ #define MMC_CAP2_DETECT_ON_ERR        (1 << 8)        /* On I/O err check card removal */
+ #define MMC_CAP2_HC_ERASE_SZ  (1 << 9)        /* High-capacity erase size */
++#define MMC_CAP2_CD_ACTIVE_HIGH       (1 << 10)       /* Card-detect signal active high */
++#define MMC_CAP2_RO_ACTIVE_HIGH       (1 << 11)       /* Write-protect signal active high */
+       mmc_pm_flag_t           pm_caps;        /* supported pm features */
+       unsigned int        power_notify_type;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch b/patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch
new file mode 100644 (file)
index 0000000..4005a0d
--- /dev/null
@@ -0,0 +1,141 @@
+From 2d3824e27d90f5cd81a034798596e8d6963c2b1f Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 16:27:25 +0200
+Subject: mmc: add CD GPIO polling support to slot functions
+
+A simple extension of mmc slot functions add support for CD GPIO polling
+for cases where the GPIO cannot produce interrupts, or where this is not
+desired for some reason.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit befe4048d8d20483a62636e20f3dbffebf85a1c1)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/core/slot-gpio.c  | 56 +++++++++++++++++++++++++++++++++----------
+ include/linux/mmc/slot-gpio.h |  2 ++
+ 2 files changed, 45 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
+index 468e5a0..92cba02 100644
+--- a/drivers/mmc/core/slot-gpio.c
++++ b/drivers/mmc/core/slot-gpio.c
+@@ -18,7 +18,7 @@
+ #include <linux/slab.h>
+ struct mmc_gpio {
+-      unsigned int cd_gpio;
++      int cd_gpio;
+       char cd_label[0];
+ };
+@@ -29,6 +29,18 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
+       return IRQ_HANDLED;
+ }
++int mmc_gpio_get_cd(struct mmc_host *host)
++{
++      struct mmc_gpio *ctx = host->slot.handler_priv;
++
++      if (!ctx || !gpio_is_valid(ctx->cd_gpio))
++              return -ENOSYS;
++
++      return !gpio_get_value_cansleep(ctx->cd_gpio) ^
++              !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
++}
++EXPORT_SYMBOL(mmc_gpio_get_cd);
++
+ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+ {
+       size_t len = strlen(dev_name(host->parent)) + 4;
+@@ -36,9 +48,6 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+       int irq = gpio_to_irq(gpio);
+       int ret;
+-      if (irq < 0)
+-              return irq;
+-
+       ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+@@ -49,20 +58,32 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+       if (ret < 0)
+               goto egpioreq;
+-      ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
++      /*
++       * Even if gpio_to_irq() returns a valid IRQ number, the platform might
++       * still prefer to poll, e.g., because that IRQ number is already used
++       * by another unit and cannot be shared.
++       */
++      if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL)
++              irq = -EINVAL;
++
++      if (irq >= 0) {
++              ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
+                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                       ctx->cd_label, host);
+-      if (ret < 0)
+-              goto eirqreq;
++              if (ret < 0)
++                      irq = ret;
++      }
+-      ctx->cd_gpio = gpio;
+       host->slot.cd_irq = irq;
++
++      if (irq < 0)
++              host->caps |= MMC_CAP_NEEDS_POLL;
++
++      ctx->cd_gpio = gpio;
+       host->slot.handler_priv = ctx;
+       return 0;
+-eirqreq:
+-      gpio_free(gpio);
+ egpioreq:
+       kfree(ctx);
+       return ret;
+@@ -72,12 +93,21 @@ EXPORT_SYMBOL(mmc_gpio_request_cd);
+ void mmc_gpio_free_cd(struct mmc_host *host)
+ {
+       struct mmc_gpio *ctx = host->slot.handler_priv;
++      int gpio;
+-      if (!ctx)
++      if (!ctx || !gpio_is_valid(ctx->cd_gpio))
+               return;
+-      free_irq(host->slot.cd_irq, host);
+-      gpio_free(ctx->cd_gpio);
++      if (host->slot.cd_irq >= 0) {
++              free_irq(host->slot.cd_irq, host);
++              host->slot.cd_irq = -EINVAL;
++      }
++
++      gpio = ctx->cd_gpio;
++      ctx->cd_gpio = -EINVAL;
++
++      gpio_free(gpio);
++      host->slot.handler_priv = NULL;
+       kfree(ctx);
+ }
+ EXPORT_SYMBOL(mmc_gpio_free_cd);
+diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
+index edfaa32..1a977d7 100644
+--- a/include/linux/mmc/slot-gpio.h
++++ b/include/linux/mmc/slot-gpio.h
+@@ -12,6 +12,8 @@
+ #define MMC_SLOT_GPIO_H
+ struct mmc_host;
++
++int mmc_gpio_get_cd(struct mmc_host *host);
+ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
+ void mmc_gpio_free_cd(struct mmc_host *host);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch b/patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch
new file mode 100644 (file)
index 0000000..f55688e
--- /dev/null
@@ -0,0 +1,161 @@
+From 1acb00ed4e37416f9e71be4588be8fab3e03d1ee Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 16:51:38 +0200
+Subject: mmc: core: convert slot functions to managed allocation
+
+This prepares for the addition of further slot functions.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit a7d1a1ebd8f5858a812ac3d5fbbc178b4959a63b)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/core/host.c      |  2 ++
+ drivers/mmc/core/slot-gpio.c | 51 +++++++++++++++++++++++++++++++++-----------
+ include/linux/mmc/host.h     |  3 +++
+ 3 files changed, 43 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
+index b8c5290..74cf29a 100644
+--- a/drivers/mmc/core/host.c
++++ b/drivers/mmc/core/host.c
+@@ -32,6 +32,7 @@
+ static void mmc_host_classdev_release(struct device *dev)
+ {
+       struct mmc_host *host = cls_dev_to_mmc_host(dev);
++      mutex_destroy(&host->slot.lock);
+       kfree(host);
+ }
+@@ -327,6 +328,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+       mmc_host_clk_init(host);
++      mutex_init(&host->slot.lock);
+       host->slot.cd_irq = -EINVAL;
+       spin_lock_init(&host->lock);
+diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
+index 92cba02..41689da 100644
+--- a/drivers/mmc/core/slot-gpio.c
++++ b/drivers/mmc/core/slot-gpio.c
+@@ -29,6 +29,34 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
+       return IRQ_HANDLED;
+ }
++static int mmc_gpio_alloc(struct mmc_host *host)
++{
++      size_t len = strlen(dev_name(host->parent)) + 4;
++      struct mmc_gpio *ctx;
++
++      mutex_lock(&host->slot.lock);
++
++      ctx = host->slot.handler_priv;
++      if (!ctx) {
++              /*
++               * devm_kzalloc() can be called after device_initialize(), even
++               * before device_add(), i.e., between mmc_alloc_host() and
++               * mmc_add_host()
++               */
++              ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len,
++                                 GFP_KERNEL);
++              if (ctx) {
++                      snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
++                      ctx->cd_gpio = -EINVAL;
++                      host->slot.handler_priv = ctx;
++              }
++      }
++
++      mutex_unlock(&host->slot.lock);
++
++      return ctx ? 0 : -ENOMEM;
++}
++
+ int mmc_gpio_get_cd(struct mmc_host *host)
+ {
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+@@ -43,20 +71,24 @@ EXPORT_SYMBOL(mmc_gpio_get_cd);
+ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+ {
+-      size_t len = strlen(dev_name(host->parent)) + 4;
+       struct mmc_gpio *ctx;
+       int irq = gpio_to_irq(gpio);
+       int ret;
+-      ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL);
+-      if (!ctx)
+-              return -ENOMEM;
++      ret = mmc_gpio_alloc(host);
++      if (ret < 0)
++              return ret;
+-      snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
++      ctx = host->slot.handler_priv;
+       ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
+       if (ret < 0)
+-              goto egpioreq;
++              /*
++               * don't bother freeing memory. It might still get used by other
++               * slot functions, in any case it will be freed, when the device
++               * is destroyed.
++               */
++              return ret;
+       /*
+        * Even if gpio_to_irq() returns a valid IRQ number, the platform might
+@@ -80,13 +112,8 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+               host->caps |= MMC_CAP_NEEDS_POLL;
+       ctx->cd_gpio = gpio;
+-      host->slot.handler_priv = ctx;
+       return 0;
+-
+-egpioreq:
+-      kfree(ctx);
+-      return ret;
+ }
+ EXPORT_SYMBOL(mmc_gpio_request_cd);
+@@ -107,7 +134,5 @@ void mmc_gpio_free_cd(struct mmc_host *host)
+       ctx->cd_gpio = -EINVAL;
+       gpio_free(gpio);
+-      host->slot.handler_priv = NULL;
+-      kfree(ctx);
+ }
+ EXPORT_SYMBOL(mmc_gpio_free_cd);
+diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
+index c1a03ee..65c64ee 100644
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -11,6 +11,7 @@
+ #define LINUX_MMC_HOST_H
+ #include <linux/leds.h>
++#include <linux/mutex.h>
+ #include <linux/sched.h>
+ #include <linux/device.h>
+ #include <linux/fault-inject.h>
+@@ -154,6 +155,7 @@ struct mmc_async_req {
+  * struct mmc_slot - MMC slot functions
+  *
+  * @cd_irq:           MMC/SD-card slot hotplug detection IRQ or -EINVAL
++ * @lock:             protect the @handler_priv pointer
+  * @handler_priv:     MMC/SD-card slot context
+  *
+  * Some MMC/SD host controllers implement slot-functions like card and
+@@ -163,6 +165,7 @@ struct mmc_async_req {
+  */
+ struct mmc_slot {
+       int cd_irq;
++      struct mutex lock;
+       void *handler_priv;
+ };
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch b/patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch
new file mode 100644 (file)
index 0000000..dc21d56
--- /dev/null
@@ -0,0 +1,132 @@
+From e26593f54711c1135d3d1fd0994224e9dba0dee2 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 16:59:38 +0200
+Subject: mmc: core: add WP pin handler to slot functions
+
+Card Write-Protect pin is often implemented, using a GPIO, which makes
+it simple to provide a generic handler for it.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 5aa7dad305594ea30d21e23b3036565042adf50c)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/core/slot-gpio.c  | 52 ++++++++++++++++++++++++++++++++++++++++++-
+ include/linux/mmc/slot-gpio.h |  4 ++++
+ 2 files changed, 55 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
+index 41689da..0582429 100644
+--- a/drivers/mmc/core/slot-gpio.c
++++ b/drivers/mmc/core/slot-gpio.c
+@@ -18,7 +18,9 @@
+ #include <linux/slab.h>
+ struct mmc_gpio {
++      int ro_gpio;
+       int cd_gpio;
++      char *ro_label;
+       char cd_label[0];
+ };
+@@ -43,11 +45,14 @@ static int mmc_gpio_alloc(struct mmc_host *host)
+                * before device_add(), i.e., between mmc_alloc_host() and
+                * mmc_add_host()
+                */
+-              ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len,
++              ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
+                                  GFP_KERNEL);
+               if (ctx) {
++                      ctx->ro_label = ctx->cd_label + len;
+                       snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
++                      snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
+                       ctx->cd_gpio = -EINVAL;
++                      ctx->ro_gpio = -EINVAL;
+                       host->slot.handler_priv = ctx;
+               }
+       }
+@@ -57,6 +62,18 @@ static int mmc_gpio_alloc(struct mmc_host *host)
+       return ctx ? 0 : -ENOMEM;
+ }
++int mmc_gpio_get_ro(struct mmc_host *host)
++{
++      struct mmc_gpio *ctx = host->slot.handler_priv;
++
++      if (!ctx || !gpio_is_valid(ctx->ro_gpio))
++              return -ENOSYS;
++
++      return !gpio_get_value_cansleep(ctx->ro_gpio) ^
++              !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
++}
++EXPORT_SYMBOL(mmc_gpio_get_ro);
++
+ int mmc_gpio_get_cd(struct mmc_host *host)
+ {
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+@@ -69,6 +86,24 @@ int mmc_gpio_get_cd(struct mmc_host *host)
+ }
+ EXPORT_SYMBOL(mmc_gpio_get_cd);
++int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
++{
++      struct mmc_gpio *ctx;
++      int ret;
++
++      if (!gpio_is_valid(gpio))
++              return -EINVAL;
++
++      ret = mmc_gpio_alloc(host);
++      if (ret < 0)
++              return ret;
++
++      ctx = host->slot.handler_priv;
++
++      return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
++}
++EXPORT_SYMBOL(mmc_gpio_request_ro);
++
+ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+ {
+       struct mmc_gpio *ctx;
+@@ -117,6 +152,21 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+ }
+ EXPORT_SYMBOL(mmc_gpio_request_cd);
++void mmc_gpio_free_ro(struct mmc_host *host)
++{
++      struct mmc_gpio *ctx = host->slot.handler_priv;
++      int gpio;
++
++      if (!ctx || !gpio_is_valid(ctx->ro_gpio))
++              return;
++
++      gpio = ctx->ro_gpio;
++      ctx->ro_gpio = -EINVAL;
++
++      gpio_free(gpio);
++}
++EXPORT_SYMBOL(mmc_gpio_free_ro);
++
+ void mmc_gpio_free_cd(struct mmc_host *host)
+ {
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
+index 1a977d7..7d88d27 100644
+--- a/include/linux/mmc/slot-gpio.h
++++ b/include/linux/mmc/slot-gpio.h
+@@ -13,6 +13,10 @@
+ struct mmc_host;
++int mmc_gpio_get_ro(struct mmc_host *host);
++int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
++void mmc_gpio_free_ro(struct mmc_host *host);
++
+ int mmc_gpio_get_cd(struct mmc_host *host);
+ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
+ void mmc_gpio_free_cd(struct mmc_host *host);
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch b/patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch
new file mode 100644 (file)
index 0000000..6520920
--- /dev/null
@@ -0,0 +1,45 @@
+From faee1eb43fa5fa4ab009588d46a5e5b4da3be529 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 17:11:56 +0200
+Subject: mmc: tmio: use generic GPIO CD and WP handlers
+
+The tmio-mmc driver is already using the generic GPIO CD handler in IRQ
+mode. This patch adds support for CD polling mode and also checks for
+availability of a WP GPIO.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 3071cafb7f6f9cbb52b1b7eb308c8b45cae0dcf8)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/tmio_mmc_pio.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index f8df021..0d8a9bb 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -875,6 +875,9 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
+ {
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct tmio_mmc_data *pdata = host->pdata;
++      int ret = mmc_gpio_get_ro(mmc);
++      if (ret >= 0)
++              return ret;
+       return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
+                (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
+@@ -884,6 +887,9 @@ static int tmio_mmc_get_cd(struct mmc_host *mmc)
+ {
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct tmio_mmc_data *pdata = host->pdata;
++      int ret = mmc_gpio_get_cd(mmc);
++      if (ret >= 0)
++              return ret;
+       if (!pdata->get_cd)
+               return -ENOSYS;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch b/patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch
new file mode 100644 (file)
index 0000000..3486d84
--- /dev/null
@@ -0,0 +1,37 @@
+From e4f6cf57b801d98e400bc52f4c3eb372b7703feb Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:16 +0200
+Subject: mmc: sh_mobile_sdhi: prepare for conversion to the shdma base library
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Chris Ball <cjb@laptop.org>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit c471270d7a4161a8f1794202ad8338c0ec55759e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mobile_sdhi.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index a842939..0bdc146 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -169,10 +169,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+                       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+               if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
+-                      priv->param_tx.slave_id = p->dma_slave_tx;
+-                      priv->param_rx.slave_id = p->dma_slave_rx;
+-                      priv->dma_priv.chan_priv_tx = &priv->param_tx;
+-                      priv->dma_priv.chan_priv_rx = &priv->param_rx;
++                      priv->param_tx.shdma_slave.slave_id = p->dma_slave_tx;
++                      priv->param_rx.shdma_slave.slave_id = p->dma_slave_rx;
++                      priv->dma_priv.chan_priv_tx = &priv->param_tx.shdma_slave;
++                      priv->dma_priv.chan_priv_rx = &priv->param_rx.shdma_slave;
+                       priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
+                       mmc_data->dma = &priv->dma_priv;
+               }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch b/patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch
new file mode 100644 (file)
index 0000000..bfc5b79
--- /dev/null
@@ -0,0 +1,94 @@
+From 52ffe4e5679653a9bb539a438d6521768fd70e25 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Wed, 9 May 2012 17:09:15 +0200
+Subject: mmc: sh_mmcif: remove unneeded struct sh_mmcif_dma, prepare to shdma
+ conversion
+
+Now that all users have been updated to use the embedded in struct
+sh_mmcif_plat_data DMA slave IDs, struct sh_mmcif_dma is no longer needed
+and can be removed. This also makes preparation to the shdma base library
+conversion easier.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Chris Ball <cjb@laptop.org>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 916001fe33b7b4dc797f7b29ec8bc346c4369fa6)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c  | 24 ++++++++++--------------
+ include/linux/mmc/sh_mmcif.h |  8 +-------
+ 2 files changed, 11 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
+index 724b35e..9e3b9b1 100644
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -385,31 +385,27 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
+       host->dma_active = false;
+       /* We can only either use DMA for both Tx and Rx or not use it at all */
+-      if (pdata->dma) {
+-              dev_warn(&host->pd->dev,
+-                       "Update your platform to use embedded DMA slave IDs\n");
+-              tx = &pdata->dma->chan_priv_tx;
+-              rx = &pdata->dma->chan_priv_rx;
+-      } else {
+-              tx = &host->dma_slave_tx;
+-              tx->slave_id = pdata->slave_id_tx;
+-              rx = &host->dma_slave_rx;
+-              rx->slave_id = pdata->slave_id_rx;
+-      }
+-      if (tx->slave_id > 0 && rx->slave_id > 0) {
++      tx = &host->dma_slave_tx;
++      tx->shdma_slave.slave_id = pdata->slave_id_tx;
++      rx = &host->dma_slave_rx;
++      rx->shdma_slave.slave_id = pdata->slave_id_rx;
++
++      if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) {
+               dma_cap_mask_t mask;
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+-              host->chan_tx = dma_request_channel(mask, sh_mmcif_filter, tx);
++              host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
++                                                  &tx->shdma_slave);
+               dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
+                       host->chan_tx);
+               if (!host->chan_tx)
+                       return;
+-              host->chan_rx = dma_request_channel(mask, sh_mmcif_filter, rx);
++              host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
++                                                  &rx->shdma_slave);
+               dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
+                       host->chan_rx);
+diff --git a/include/linux/mmc/sh_mmcif.h b/include/linux/mmc/sh_mmcif.h
+index 05f0e3d..c37956c 100644
+--- a/include/linux/mmc/sh_mmcif.h
++++ b/include/linux/mmc/sh_mmcif.h
+@@ -32,17 +32,11 @@
+  * 1111 : Peripheral clock (sup_pclk set '1')
+  */
+-struct sh_mmcif_dma {
+-      struct sh_dmae_slave chan_priv_tx;
+-      struct sh_dmae_slave chan_priv_rx;
+-};
+-
+ struct sh_mmcif_plat_data {
+       void (*set_pwr)(struct platform_device *pdev, int state);
+       void (*down_pwr)(struct platform_device *pdev);
+       int (*get_cd)(struct platform_device *pdef);
+-      struct sh_mmcif_dma     *dma;           /* Deprecated. Instead */
+-      unsigned int            slave_id_tx;    /* use embedded slave_id_[tr]x */
++      unsigned int            slave_id_tx;    /* embedded slave_id_[tr]x */
+       unsigned int            slave_id_rx;
+       u8                      sup_pclk;       /* 1 :SH7757, 0: SH7724/SH7372 */
+       unsigned long           caps;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch b/patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch
new file mode 100644 (file)
index 0000000..02bbc7d
--- /dev/null
@@ -0,0 +1,138 @@
+From e528d448bb2c6e6b4c1ea80b809ffdc734806290 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 5 Jul 2012 12:29:43 +0200
+Subject: mmc: sh_mmcif: switch to the new DMA channel allocation and
+ configuration
+
+Using the "private" field from struct dma_chan is deprecated. The sh
+dmaengine driver now also supports the preferred DMA channel allocation
+and configuration method, using a standard filter function and a channel
+configuration operation. This patch updates sh_mmcif to use this new
+method.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Cc: Chris Ball <cjb@laptop.org>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+(cherry picked from commit 0e79f9ae1610c15f5e5959c39d7c39071619de97)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c | 82 ++++++++++++++++++++++++++-------------------
+ 1 file changed, 47 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
+index 9e3b9b1..0f07d28 100644
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -211,8 +211,6 @@ struct sh_mmcif_host {
+       struct mmc_host *mmc;
+       struct mmc_request *mrq;
+       struct platform_device *pd;
+-      struct sh_dmae_slave dma_slave_tx;
+-      struct sh_dmae_slave dma_slave_rx;
+       struct clk *hclk;
+       unsigned int clk;
+       int bus_width;
+@@ -371,52 +369,66 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
+               desc, cookie);
+ }
+-static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
+-{
+-      dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
+-      chan->private = arg;
+-      return true;
+-}
+-
+ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
+                                struct sh_mmcif_plat_data *pdata)
+ {
+-      struct sh_dmae_slave *tx, *rx;
++      struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);
++      struct dma_slave_config cfg;
++      dma_cap_mask_t mask;
++      int ret;
++
+       host->dma_active = false;
++      if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
++              return;
++
+       /* We can only either use DMA for both Tx and Rx or not use it at all */
+-      tx = &host->dma_slave_tx;
+-      tx->shdma_slave.slave_id = pdata->slave_id_tx;
+-      rx = &host->dma_slave_rx;
+-      rx->shdma_slave.slave_id = pdata->slave_id_rx;
++      dma_cap_zero(mask);
++      dma_cap_set(DMA_SLAVE, mask);
++
++      host->chan_tx = dma_request_channel(mask, shdma_chan_filter,
++                                          (void *)pdata->slave_id_tx);
++      dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
++              host->chan_tx);
+-      if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) {
+-              dma_cap_mask_t mask;
++      if (!host->chan_tx)
++              return;
+-              dma_cap_zero(mask);
+-              dma_cap_set(DMA_SLAVE, mask);
++      cfg.slave_id = pdata->slave_id_tx;
++      cfg.direction = DMA_MEM_TO_DEV;
++      cfg.dst_addr = res->start + MMCIF_CE_DATA;
++      cfg.src_addr = 0;
++      ret = dmaengine_slave_config(host->chan_tx, &cfg);
++      if (ret < 0)
++              goto ecfgtx;
+-              host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
+-                                                  &tx->shdma_slave);
+-              dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
+-                      host->chan_tx);
++      host->chan_rx = dma_request_channel(mask, shdma_chan_filter,
++                                          (void *)pdata->slave_id_rx);
++      dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
++              host->chan_rx);
+-              if (!host->chan_tx)
+-                      return;
++      if (!host->chan_rx)
++              goto erqrx;
+-              host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
+-                                                  &rx->shdma_slave);
+-              dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
+-                      host->chan_rx);
++      cfg.slave_id = pdata->slave_id_rx;
++      cfg.direction = DMA_DEV_TO_MEM;
++      cfg.dst_addr = 0;
++      cfg.src_addr = res->start + MMCIF_CE_DATA;
++      ret = dmaengine_slave_config(host->chan_rx, &cfg);
++      if (ret < 0)
++              goto ecfgrx;
+-              if (!host->chan_rx) {
+-                      dma_release_channel(host->chan_tx);
+-                      host->chan_tx = NULL;
+-                      return;
+-              }
++      init_completion(&host->dma_complete);
+-              init_completion(&host->dma_complete);
+-      }
++      return;
++
++ecfgrx:
++      dma_release_channel(host->chan_rx);
++      host->chan_rx = NULL;
++erqrx:
++ecfgtx:
++      dma_release_channel(host->chan_tx);
++      host->chan_tx = NULL;
+ }
+ static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch b/patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch
new file mode 100644 (file)
index 0000000..ca047a2
--- /dev/null
@@ -0,0 +1,53 @@
+From a582cd28240bd5aca4462da1dacd8dd8e9ee0dbc Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Date: Tue, 12 Jun 2012 22:56:09 +0200
+Subject: mmc: sh_mmcif: Support MMC_SLEEP_AWAKE command
+
+The MMC_SLEEP_AWAKE and SD_IO_SEND_OP_COND commands share the same
+opcode. SD_IO_SEND_OP_COND isn't supported by the SH MMCIF, but
+MMC_SLEEP_AWAKE is. Discriminate between the two commands using the
+command flags, and reject SD_IO_SEND_OP_COND only.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 7541ca98477862e2e9988c6c2ceadbdccefa9d77)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
+index 0f07d28..1eb23a7 100644
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -900,21 +900,15 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
+       switch (mrq->cmd->opcode) {
+       /* MMCIF does not support SD/SDIO command */
+-      case SD_IO_SEND_OP_COND:
++      case MMC_SLEEP_AWAKE: /* = SD_IO_SEND_OP_COND (5) */
++      case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
++              if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR)
++                      break;
+       case MMC_APP_CMD:
+               host->state = STATE_IDLE;
+               mrq->cmd->error = -ETIMEDOUT;
+               mmc_request_done(mmc, mrq);
+               return;
+-      case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
+-              if (!mrq->data) {
+-                      /* send_if_cond cmd (not support) */
+-                      host->state = STATE_IDLE;
+-                      mrq->cmd->error = -ETIMEDOUT;
+-                      mmc_request_done(mmc, mrq);
+-                      return;
+-              }
+-              break;
+       default:
+               break;
+       }
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch b/patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch
new file mode 100644 (file)
index 0000000..e752b05
--- /dev/null
@@ -0,0 +1,126 @@
+From 31a4301b36511da303ad36da908f462f057f0e73 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 19 Apr 2012 16:15:52 +0200
+Subject: mmc: sh_mmcif: simplify and use meaningful label names in
+ error-handling
+
+A check for NULL platform data can be conveniently made in the very
+beginning of probing. Replace numbered error-handling labels in .probe()
+with meaningful names to make any future reorganisation simpler.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit e1aae2eb3f7c446a2680a3a0ccd05aa50521b4e2)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c |   41 ++++++++++++++++++++---------------------
+ 1 file changed, 20 insertions(+), 21 deletions(-)
+
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -1253,11 +1253,16 @@ static int __devinit sh_mmcif_probe(stru
+       int ret = 0, irq[2];
+       struct mmc_host *mmc;
+       struct sh_mmcif_host *host;
+-      struct sh_mmcif_plat_data *pd;
++      struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
+       struct resource *res;
+       void __iomem *reg;
+       char clk_name[8];
++      if (!pd) {
++              dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
++              return -ENXIO;
++      }
++
+       irq[0] = platform_get_irq(pdev, 0);
+       irq[1] = platform_get_irq(pdev, 1);
+       if (irq[0] < 0 || irq[1] < 0) {
+@@ -1274,16 +1279,11 @@ static int __devinit sh_mmcif_probe(stru
+               dev_err(&pdev->dev, "ioremap error.\n");
+               return -ENOMEM;
+       }
+-      pd = pdev->dev.platform_data;
+-      if (!pd) {
+-              dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
+-              ret = -ENXIO;
+-              goto clean_up;
+-      }
++
+       mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+-              goto clean_up;
++              goto ealloch;
+       }
+       host            = mmc_priv(mmc);
+       host->mmc       = mmc;
+@@ -1295,7 +1295,7 @@ static int __devinit sh_mmcif_probe(stru
+       if (IS_ERR(host->hclk)) {
+               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+               ret = PTR_ERR(host->hclk);
+-              goto clean_up1;
++              goto eclkget;
+       }
+       clk_enable(host->hclk);
+       host->clk = clk_get_rate(host->hclk);
+@@ -1325,7 +1325,7 @@ static int __devinit sh_mmcif_probe(stru
+       ret = pm_runtime_resume(&pdev->dev);
+       if (ret < 0)
+-              goto clean_up2;
++              goto eresume;
+       INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
+@@ -1334,17 +1334,17 @@ static int __devinit sh_mmcif_probe(stru
+       ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
+       if (ret) {
+               dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
+-              goto clean_up3;
++              goto ereqirq0;
+       }
+       ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
+       if (ret) {
+               dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
+-              goto clean_up4;
++              goto ereqirq1;
+       }
+       ret = mmc_add_host(mmc);
+       if (ret < 0)
+-              goto clean_up5;
++              goto emmcaddh;
+       dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
+@@ -1353,20 +1353,19 @@ static int __devinit sh_mmcif_probe(stru
+               sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
+       return ret;
+-clean_up5:
++emmcaddh:
+       free_irq(irq[1], host);
+-clean_up4:
++ereqirq1:
+       free_irq(irq[0], host);
+-clean_up3:
++ereqirq0:
+       pm_runtime_suspend(&pdev->dev);
+-clean_up2:
++eresume:
+       pm_runtime_disable(&pdev->dev);
+       clk_disable(host->hclk);
+-clean_up1:
++eclkget:
+       mmc_free_host(mmc);
+-clean_up:
+-      if (reg)
+-              iounmap(reg);
++ealloch:
++      iounmap(reg);
+       return ret;
+ }
diff --git a/patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch b/patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch
new file mode 100644 (file)
index 0000000..a0a25c6
--- /dev/null
@@ -0,0 +1,160 @@
+From f504bc8e96b3633271ee5e623c35e026a6db62e7 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 19 Apr 2012 18:02:05 +0200
+Subject: mmc: sh_mmcif: fix clock management
+
+Regardless of whether the MMC bus clock is the same as the PM clock on
+this specific interface, it has to be managed separately. Its proper
+management should also include enabling and disabling of the clock,
+whenever the interface is becoming active or going idle respectively.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit b289174ff70a591545a054d52ae081a75a73f085)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c |   46 ++++++++++++++++++++++----------------------
+ 1 file changed, 23 insertions(+), 23 deletions(-)
+
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -950,6 +950,7 @@ static void sh_mmcif_set_ios(struct mmc_
+               }
+               if (host->power) {
+                       pm_runtime_put(&host->pd->dev);
++                      clk_disable(host->hclk);
+                       host->power = false;
+                       if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
+                               p->down_pwr(host->pd);
+@@ -962,6 +963,7 @@ static void sh_mmcif_set_ios(struct mmc_
+               if (!host->power) {
+                       if (p->set_pwr)
+                               p->set_pwr(host->pd, ios->power_mode);
++                      clk_enable(host->hclk);
+                       pm_runtime_get_sync(&host->pd->dev);
+                       host->power = true;
+                       sh_mmcif_sync_reset(host);
+@@ -1290,22 +1292,11 @@ static int __devinit sh_mmcif_probe(stru
+       host->addr      = reg;
+       host->timeout   = 1000;
+-      snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
+-      host->hclk = clk_get(&pdev->dev, clk_name);
+-      if (IS_ERR(host->hclk)) {
+-              dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+-              ret = PTR_ERR(host->hclk);
+-              goto eclkget;
+-      }
+-      clk_enable(host->hclk);
+-      host->clk = clk_get_rate(host->hclk);
+       host->pd = pdev;
+       spin_lock_init(&host->lock);
+       mmc->ops = &sh_mmcif_ops;
+-      mmc->f_max = host->clk / 2;
+-      mmc->f_min = host->clk / 512;
+       if (pd->ocr)
+               mmc->ocr_avail = pd->ocr;
+       mmc->caps = MMC_CAP_MMC_HIGHSPEED;
+@@ -1317,18 +1308,30 @@ static int __devinit sh_mmcif_probe(stru
+       mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
+       mmc->max_seg_size = mmc->max_req_size;
+-      sh_mmcif_sync_reset(host);
+       platform_set_drvdata(pdev, host);
+       pm_runtime_enable(&pdev->dev);
+       host->power = false;
++      snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
++      host->hclk = clk_get(&pdev->dev, clk_name);
++      if (IS_ERR(host->hclk)) {
++              ret = PTR_ERR(host->hclk);
++              dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
++              goto eclkget;
++      }
++      clk_enable(host->hclk);
++      host->clk = clk_get_rate(host->hclk);
++      mmc->f_max = host->clk / 2;
++      mmc->f_min = host->clk / 512;
++
+       ret = pm_runtime_resume(&pdev->dev);
+       if (ret < 0)
+               goto eresume;
+       INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
++      sh_mmcif_sync_reset(host);
+       sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
+       ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
+@@ -1342,6 +1345,7 @@ static int __devinit sh_mmcif_probe(stru
+               goto ereqirq1;
+       }
++      clk_disable(host->hclk);
+       ret = mmc_add_host(mmc);
+       if (ret < 0)
+               goto emmcaddh;
+@@ -1360,9 +1364,10 @@ ereqirq1:
+ ereqirq0:
+       pm_runtime_suspend(&pdev->dev);
+ eresume:
+-      pm_runtime_disable(&pdev->dev);
+       clk_disable(host->hclk);
++      clk_put(host->hclk);
+ eclkget:
++      pm_runtime_disable(&pdev->dev);
+       mmc_free_host(mmc);
+ ealloch:
+       iounmap(reg);
+@@ -1375,6 +1380,7 @@ static int __devexit sh_mmcif_remove(str
+       int irq[2];
+       host->dying = true;
++      clk_enable(host->hclk);
+       pm_runtime_get_sync(&pdev->dev);
+       dev_pm_qos_hide_latency_limit(&pdev->dev);
+@@ -1400,9 +1406,9 @@ static int __devexit sh_mmcif_remove(str
+       platform_set_drvdata(pdev, NULL);
+-      clk_disable(host->hclk);
+       mmc_free_host(host->mmc);
+       pm_runtime_put_sync(&pdev->dev);
++      clk_disable(host->hclk);
+       pm_runtime_disable(&pdev->dev);
+       return 0;
+@@ -1411,24 +1417,18 @@ static int __devexit sh_mmcif_remove(str
+ #ifdef CONFIG_PM
+ static int sh_mmcif_suspend(struct device *dev)
+ {
+-      struct platform_device *pdev = to_platform_device(dev);
+-      struct sh_mmcif_host *host = platform_get_drvdata(pdev);
++      struct sh_mmcif_host *host = dev_get_drvdata(dev);
+       int ret = mmc_suspend_host(host->mmc);
+-      if (!ret) {
++      if (!ret)
+               sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
+-              clk_disable(host->hclk);
+-      }
+       return ret;
+ }
+ static int sh_mmcif_resume(struct device *dev)
+ {
+-      struct platform_device *pdev = to_platform_device(dev);
+-      struct sh_mmcif_host *host = platform_get_drvdata(pdev);
+-
+-      clk_enable(host->hclk);
++      struct sh_mmcif_host *host = dev_get_drvdata(dev);
+       return mmc_resume_host(host->mmc);
+ }
diff --git a/patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch b/patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch
new file mode 100644 (file)
index 0000000..4752592
--- /dev/null
@@ -0,0 +1,73 @@
+From 417f01ebd88111d61e507af5d9cab347ffa41861 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 19 Apr 2012 18:02:50 +0200
+Subject: mmc: sh_mmcif: re-read the clock frequency every time it is turned on
+
+With aggressive clock gating the clock can be disabled during interface
+inactivity. During this time its frequency can be changed by another its
+user. Therefore when the interface is activated again and the clock is
+re-enabled, its frequency has to be re-read.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit a6609267107ecc5598b79aa353036c1f57e7257e)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c |   23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -918,6 +918,19 @@ static void sh_mmcif_request(struct mmc_
+       sh_mmcif_start_cmd(host, mrq);
+ }
++static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
++{
++      int ret = clk_enable(host->hclk);
++
++      if (!ret) {
++              host->clk = clk_get_rate(host->hclk);
++              host->mmc->f_max = host->clk / 2;
++              host->mmc->f_min = host->clk / 512;
++      }
++
++      return ret;
++}
++
+ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ {
+       struct sh_mmcif_host *host = mmc_priv(mmc);
+@@ -963,7 +976,7 @@ static void sh_mmcif_set_ios(struct mmc_
+               if (!host->power) {
+                       if (p->set_pwr)
+                               p->set_pwr(host->pd, ios->power_mode);
+-                      clk_enable(host->hclk);
++                      sh_mmcif_clk_update(host);
+                       pm_runtime_get_sync(&host->pd->dev);
+                       host->power = true;
+                       sh_mmcif_sync_reset(host);
+@@ -1320,10 +1333,9 @@ static int __devinit sh_mmcif_probe(stru
+               dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
+               goto eclkget;
+       }
+-      clk_enable(host->hclk);
+-      host->clk = clk_get_rate(host->hclk);
+-      mmc->f_max = host->clk / 2;
+-      mmc->f_min = host->clk / 512;
++      ret = sh_mmcif_clk_update(host);
++      if (ret < 0)
++              goto eclkupdate;
+       ret = pm_runtime_resume(&pdev->dev);
+       if (ret < 0)
+@@ -1365,6 +1377,7 @@ ereqirq0:
+       pm_runtime_suspend(&pdev->dev);
+ eresume:
+       clk_disable(host->hclk);
++eclkupdate:
+       clk_put(host->hclk);
+ eclkget:
+       pm_runtime_disable(&pdev->dev);
diff --git a/patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch b/patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch
new file mode 100644 (file)
index 0000000..f30f701
--- /dev/null
@@ -0,0 +1,39 @@
+From 57a9e156b943508dc6ee4ac85e43d90f0888985f Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Fri, 20 Apr 2012 09:01:05 +0200
+Subject: mmc: sh_mmcif: remove redundant .down_pwr() callback
+
+From the original version of sh_mmcif the .set_pwr() callback has only been
+used to turn the card's power on, and the .down_pwr() callback has been
+used to turn it off. .set_pwr() can be used for both these tasks, which is
+also how it is implemented by the only user of this API: the SH7724 ecovec
+board.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit e2ee996eaad64c149cb7cfd344789c7e0c1577dc)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
+index 29d908a..10c5fcd 100644
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -965,8 +965,8 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+                       pm_runtime_put(&host->pd->dev);
+                       clk_disable(host->hclk);
+                       host->power = false;
+-                      if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
+-                              p->down_pwr(host->pd);
++                      if (p->set_pwr && ios->power_mode == MMC_POWER_OFF)
++                              p->set_pwr(host->pd, 0);
+               }
+               host->state = STATE_IDLE;
+               return;
+-- 
+1.8.0.197.g5a90748
+
diff --git a/patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch b/patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch
new file mode 100644 (file)
index 0000000..ccdff8e
--- /dev/null
@@ -0,0 +1,108 @@
+From d573e549e130bfe6200b70a36ab44767943b52a2 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Fri, 20 Apr 2012 18:27:13 +0200
+Subject: mmc: sh_mmcif: add regulator support
+
+Add regulator support to the sh_mmcif driver, but also preserve the current
+power-callback.
+
+Also note, that the card power is not switched off during clock gating
+periods, hence there's no need to power it on every time the card is
+re-activated.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
+Reviewed-by: Simon Horman <horms@verge.net.au>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit 7d17baa05da6a2e64ee15011cdf4319bd3e0ff61)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c |   38 +++++++++++++++++++++++++++++++-------
+ 1 file changed, 31 insertions(+), 7 deletions(-)
+
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -931,10 +931,22 @@ static int sh_mmcif_clk_update(struct sh
+       return ret;
+ }
++static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
++{
++      struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
++      struct mmc_host *mmc = host->mmc;
++
++      if (pd->set_pwr)
++              pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
++      if (!IS_ERR(mmc->supply.vmmc))
++              /* Errors ignored... */
++              mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
++                                    ios->power_mode ? ios->vdd : 0);
++}
++
+ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ {
+       struct sh_mmcif_host *host = mmc_priv(mmc);
+-      struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
+       unsigned long flags;
+       spin_lock_irqsave(&host->lock, flags);
+@@ -952,6 +964,7 @@ static void sh_mmcif_set_ios(struct mmc_
+                       sh_mmcif_request_dma(host, host->pd->dev.platform_data);
+                       host->card_present = true;
+               }
++              sh_mmcif_set_power(host, ios);
+       } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
+               /* clock stop */
+               sh_mmcif_clock_control(host, 0);
+@@ -965,8 +978,8 @@ static void sh_mmcif_set_ios(struct mmc_
+                       pm_runtime_put(&host->pd->dev);
+                       clk_disable(host->hclk);
+                       host->power = false;
+-                      if (p->set_pwr && ios->power_mode == MMC_POWER_OFF)
+-                              p->set_pwr(host->pd, 0);
++                      if (ios->power_mode == MMC_POWER_OFF)
++                              sh_mmcif_set_power(host, ios);
+               }
+               host->state = STATE_IDLE;
+               return;
+@@ -974,8 +987,6 @@ static void sh_mmcif_set_ios(struct mmc_
+       if (ios->clock) {
+               if (!host->power) {
+-                      if (p->set_pwr)
+-                              p->set_pwr(host->pd, ios->power_mode);
+                       sh_mmcif_clk_update(host);
+                       pm_runtime_get_sync(&host->pd->dev);
+                       host->power = true;
+@@ -1263,6 +1274,19 @@ static void mmcif_timeout_work(struct wo
+       mmc_request_done(host->mmc, mrq);
+ }
++static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
++{
++      struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
++      struct mmc_host *mmc = host->mmc;
++
++      mmc_regulator_get_supply(mmc);
++
++      if (!mmc->ocr_avail)
++              mmc->ocr_avail = pd->ocr;
++      else if (pd->ocr)
++              dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
++}
++
+ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
+ {
+       int ret = 0, irq[2];
+@@ -1310,8 +1334,8 @@ static int __devinit sh_mmcif_probe(stru
+       spin_lock_init(&host->lock);
+       mmc->ops = &sh_mmcif_ops;
+-      if (pd->ocr)
+-              mmc->ocr_avail = pd->ocr;
++      sh_mmcif_init_ocr(host);
++
+       mmc->caps = MMC_CAP_MMC_HIGHSPEED;
+       if (pd->caps)
+               mmc->caps |= pd->caps;
diff --git a/patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch b/patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch
new file mode 100644 (file)
index 0000000..6d3bd01
--- /dev/null
@@ -0,0 +1,127 @@
+From 7feedc26deff116af14317bfba8356724b71a362 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Tue, 1 May 2012 18:18:16 +0200
+Subject: mmc: sh-mmcif: add OF support, make platform data optional
+
+Add primitive OF support to the sh-mmcif driver, which also makes it
+necessary to be able to run without platform data.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit bf68a812f06ca40bccfa2e792055141f2c3948c7)
+
+Conflicts:
+       drivers/mmc/host/sh_mmcif.c
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c |   29 ++++++++++++++++++++---------
+ 1 file changed, 20 insertions(+), 9 deletions(-)
+
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -54,6 +54,7 @@
+ #include <linux/mmc/mmc.h>
+ #include <linux/mmc/sdio.h>
+ #include <linux/mmc/sh_mmcif.h>
++#include <linux/mod_devicetable.h>
+ #include <linux/pagemap.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_qos.h>
+@@ -379,6 +380,9 @@ static void sh_mmcif_request_dma(struct
+       host->dma_active = false;
++      if (!pdata)
++              return;
++
+       if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+               return;
+@@ -452,13 +456,14 @@ static void sh_mmcif_release_dma(struct
+ static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
+ {
+       struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
++      bool sup_pclk = p ? p->sup_pclk : false;
+       sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
+       sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR);
+       if (!clk)
+               return;
+-      if (p->sup_pclk && clk == host->clk)
++      if (sup_pclk && clk == host->clk)
+               sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
+       else
+               sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
+@@ -936,7 +941,7 @@ static void sh_mmcif_set_power(struct sh
+       struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
+       struct mmc_host *mmc = host->mmc;
+-      if (pd->set_pwr)
++      if (pd && pd->set_pwr)
+               pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
+       if (!IS_ERR(mmc->supply.vmmc))
+               /* Errors ignored... */
+@@ -1004,7 +1009,7 @@ static int sh_mmcif_get_cd(struct mmc_ho
+       struct sh_mmcif_host *host = mmc_priv(mmc);
+       struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
+-      if (!p->get_cd)
++      if (!p || !p->get_cd)
+               return -ENOSYS;
+       else
+               return p->get_cd(host->pd);
+@@ -1281,6 +1286,9 @@ static void sh_mmcif_init_ocr(struct sh_
+       mmc_regulator_get_supply(mmc);
++      if (!pd)
++              return;
++
+       if (!mmc->ocr_avail)
+               mmc->ocr_avail = pd->ocr;
+       else if (pd->ocr)
+@@ -1297,11 +1305,6 @@ static int __devinit sh_mmcif_probe(stru
+       void __iomem *reg;
+       char clk_name[8];
+-      if (!pd) {
+-              dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
+-              return -ENXIO;
+-      }
+-
+       irq[0] = platform_get_irq(pdev, 0);
+       irq[1] = platform_get_irq(pdev, 1);
+       if (irq[0] < 0 || irq[1] < 0) {
+@@ -1337,7 +1340,7 @@ static int __devinit sh_mmcif_probe(stru
+       sh_mmcif_init_ocr(host);
+       mmc->caps = MMC_CAP_MMC_HIGHSPEED;
+-      if (pd->caps)
++      if (pd && pd->caps)
+               mmc->caps |= pd->caps;
+       mmc->max_segs = 32;
+       mmc->max_blk_size = 512;
+@@ -1474,6 +1477,12 @@ static int sh_mmcif_resume(struct device
+ #define sh_mmcif_resume               NULL
+ #endif        /* CONFIG_PM */
++static const struct of_device_id mmcif_of_match[] = {
++      { .compatible = "renesas,sh-mmcif" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, mmcif_of_match);
++
+ static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
+       .suspend = sh_mmcif_suspend,
+       .resume = sh_mmcif_resume,
+@@ -1485,6 +1494,8 @@ static struct platform_driver sh_mmcif_d
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .pm     = &sh_mmcif_dev_pm_ops,
++              .owner  = THIS_MODULE,
++              .of_match_table = mmcif_of_match,
+       },
+ };
diff --git a/patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch b/patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch
new file mode 100644 (file)
index 0000000..613690c
--- /dev/null
@@ -0,0 +1,92 @@
+From 4156a922e2e32baccd17cb76ba388cecb1790299 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 14 Jun 2012 14:24:35 +0200
+Subject: mmc: sh_mmcif: support generic card-detection
+
+Extend the sh_mmcif driver to support GPIO card detection, provided by the
+slot function module. The original .get_cd() platform callback is also
+preserved for now.
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+(cherry picked from commit e480606ad43bb72fd82a9bd99cdcf21829a6e9c0)
+
+Signed-off-by: Simon Horman <horms@verge.net.au>
+---
+ drivers/mmc/host/sh_mmcif.c  |   18 ++++++++++++++++++
+ include/linux/mmc/sh_mmcif.h |    2 ++
+ 2 files changed, 20 insertions(+)
+
+--- a/drivers/mmc/host/sh_mmcif.c
++++ b/drivers/mmc/host/sh_mmcif.c
+@@ -54,6 +54,7 @@
+ #include <linux/mmc/mmc.h>
+ #include <linux/mmc/sdio.h>
+ #include <linux/mmc/sh_mmcif.h>
++#include <linux/mmc/slot-gpio.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/pagemap.h>
+ #include <linux/platform_device.h>
+@@ -1008,6 +1009,10 @@ static int sh_mmcif_get_cd(struct mmc_ho
+ {
+       struct sh_mmcif_host *host = mmc_priv(mmc);
+       struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
++      int ret = mmc_gpio_get_cd(mmc);
++
++      if (ret >= 0)
++              return ret;
+       if (!p || !p->get_cd)
+               return -ENOSYS;
+@@ -1384,6 +1389,12 @@ static int __devinit sh_mmcif_probe(stru
+               goto ereqirq1;
+       }
++      if (pd && pd->use_cd_gpio) {
++              ret = mmc_gpio_request_cd(mmc, pd->cd_gpio);
++              if (ret < 0)
++                      goto erqcd;
++      }
++
+       clk_disable(host->hclk);
+       ret = mmc_add_host(mmc);
+       if (ret < 0)
+@@ -1397,6 +1408,9 @@ static int __devinit sh_mmcif_probe(stru
+       return ret;
+ emmcaddh:
++      if (pd && pd->use_cd_gpio)
++              mmc_gpio_free_cd(mmc);
++erqcd:
+       free_irq(irq[1], host);
+ ereqirq1:
+       free_irq(irq[0], host);
+@@ -1417,6 +1431,7 @@ ealloch:
+ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
+ {
+       struct sh_mmcif_host *host = platform_get_drvdata(pdev);
++      struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
+       int irq[2];
+       host->dying = true;
+@@ -1425,6 +1440,9 @@ static int __devexit sh_mmcif_remove(str
+       dev_pm_qos_hide_latency_limit(&pdev->dev);
++      if (pd && pd->use_cd_gpio)
++              mmc_gpio_free_cd(host->mmc);
++
+       mmc_remove_host(host->mmc);
+       sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
+--- a/include/linux/mmc/sh_mmcif.h
++++ b/include/linux/mmc/sh_mmcif.h
+@@ -38,6 +38,8 @@ struct sh_mmcif_plat_data {
+       int (*get_cd)(struct platform_device *pdef);
+       unsigned int            slave_id_tx;    /* embedded slave_id_[tr]x */
+       unsigned int            slave_id_rx;
++      bool                    use_cd_gpio : 1;
++      unsigned int            cd_gpio;
+       u8                      sup_pclk;       /* 1 :SH7757, 0: SH7724/SH7372 */
+       unsigned long           caps;
+       u32                     ocr;
diff --git a/series b/series
index d0618c18210e5e0cbc3b1856c85376e5d94fe9d7..4f3b0d3a2439d392458e5f65b8cd6e446bb74b60 100644 (file)
--- a/series
+++ b/series
@@ -81,3 +81,211 @@ patches.pramfs/16-pramfs-ioctl-operations.patch
 patches.pramfs/17-pramfs-makefile-and-kconfig.patch
 
 
+patches.marzen/0001-sh-clkfwk-Support-variable-size-accesses-for-MSTP-cl.patch
+patches.marzen/0002-sh-clkfwk-Support-variable-size-accesses-for-div4-di.patch
+patches.marzen/0003-sh-clkfwk-Move-to-common-clk_div_table-accessors-for.patch
+patches.marzen/0004-sh-clkfwk-Introduce-a-div_mask-for-variable-div-type.patch
+patches.marzen/0005-sh-clkfwk-Use-shared-sh_clk_div_recalc.patch
+patches.marzen/0006-sh-clkfwk-Use-shared-sh_clk_div_set_rate.patch
+patches.marzen/0007-sh-clkfwk-Use-shared-sh_clk_div_enable-disable.patch
+patches.marzen/0008-sh-clkfwk-Consolidate-div6-div4-clk_ops-definitions.patch
+patches.marzen/0009-sh-clkfwk-Consolidate-div-clk-registration-helper.patch
+patches.marzen/0010-irqdomain-Support-removal-of-IRQ-domains.patch
+patches.marzen/0011-irqdomain-Export-remaining-public-API-symbols.patch
+patches.marzen/0012-irqdomain-Make-irq_domain_simple_map-static.patch
+patches.marzen/0013-irqdomain-Kill-off-duplicate-definitions.patch
+patches.marzen/0014-irqdomain-trivial-pr_fmt-conversion.patch
+patches.marzen/0015-irqdomain-Document-size-parameter-of-irq_domain_add_.patch
+patches.marzen/0016-devicetree-add-helper-inline-for-retrieving-a-node-s.patch
+patches.marzen/0017-irqdomain-Simple-NUMA-awareness.patch
+patches.marzen/0018-irqdomain-Remove-unnecessary-test-for-IRQ_DOMAIN_MAP.patch
+patches.marzen/0019-irqdomain-Make-ops-map-hook-optional.patch
+patches.marzen/0020-irq_domain-Standardise-legacy-linear-domain-selectio.patch
+patches.marzen/0021-irq_domain-correct-a-minor-wrong-comment-for-linear-.patch
+patches.marzen/0022-irqdomain-Always-update-revmap-when-setting-up-a-vir.patch
+patches.marzen/0023-irqdomain-Split-disassociating-code-into-separate-fu.patch
+patches.marzen/0024-irqdomain-Support-for-static-IRQ-mapping-and-associa.patch
+patches.marzen/0025-irqdomain-Eliminate-dedicated-radix-lookup-functions.patch
+patches.marzen/0026-irqdomain-Fix-irq_create_direct_mapping-to-test-irq_.patch
+patches.marzen/0027-irqdomain-eliminate-slow-path-revmap-lookups.patch
+patches.marzen/0028-irqdomain-Improve-diagnostics-when-a-domain-mapping-.patch
+patches.marzen/0029-ARM-mach-shmobile-Introduce-INTC_IRQ_PINS_16H.patch
+patches.marzen/0030-sh-intc-Kill-off-special-reservation-interface.patch
+patches.marzen/0031-sh-intc-Allocate-subgroup-virq-backing-desc-directly.patch
+patches.marzen/0032-sh-intc-initial-irqdomain-support.patch
+patches.marzen/0033-sh-intc-Handle-domain-association-for-sparseirq-pre-.patch
+patches.marzen/0034-sh-intc-Fix-up-multi-evt-irq-association.patch
+patches.marzen/0035-ARM-mach-shmobile-Introduce-shmobile_setup_delay.patch
+patches.marzen/0036-ARM-mach-shmobile-Use-0x3400-as-INTCS-vector-offset.patch
+patches.marzen/0037-ARM-provide-a-late_initcall-hook-for-platform-initia.patch
+patches.marzen/0038-ARM-shmobile-use-machine-specific-hook-for-late-init.patch
+patches.marzen/0039-ARM-mach-shmobile-Use-preset_lpj-with-calibrate_dela.patch
+patches.marzen/0040-ARM-shmobile-r8a7740-add-MERAM-work-around.patch
+patches.marzen/0041-ARM-shmobile-add-common-extra-gpio-functions.patch
+patches.marzen/0042-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ma.patch
+patches.marzen/0043-ARM-shmobile-marzen-fixup-smsc911x-id-for-regulator.patch
+patches.marzen/0044-ARM-shmobile-r8a7779-Route-all-interrupts-to-ARM.patch
+patches.marzen/0045-dmaengine-Fixup-dmaengine_prep_slave_single-to-be-ac.patch
+patches.marzen/0046-dma-dmaengine-add-slave-req-id-in-slave_config.patch
+patches.marzen/0047-dmaengine-Add-wrapper-for-device_tx_status-callback.patch
+patches.marzen/0048-dma-move-shdma-driver-to-an-own-directory.patch
+patches.marzen/0049-dmaengine-add-an-shdma-base-library.patch
+patches.marzen/0050-dma-shdma-prepare-for-conversion-to-the-shdma-base-l.patch
+patches.marzen/0051-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch
+patches.marzen/0052-usb-renesas_usbhs-prepare-for-conversion-to-the-shdm.patch
+patches.marzen/0053-dma-shdma-convert-to-the-shdma-base-library.patch
+patches.marzen/0054-dmaengine-shdma-prepare-to-stop-using-struct-dma_cha.patch
+patches.marzen/0055-dmaengine-shdma-cosmetic-simplify-a-static-function.patch
+patches.marzen/0056-dma-sh-use-an-integer-slave-ID-to-improve-API-compat.patch
+patches.marzen/0057-dma-sh-provide-a-migration-path-for-slave-drivers-to.patch
+patches.marzen/0058-dmaengine-shdma-restore-partial-transfer-calculation.patch
+patches.marzen/0059-serial-sh-sci-modify-sci_break_ctl.patch
+patches.marzen/0060-serial-sh-sci-Update-break_ctl-handling-for-all-SCSP.patch
+patches.marzen/0061-serial-sh-sci-Fix-for-port-types-without-BRI-interru.patch
+patches.marzen/0062-serial-sh-sci-Fix-probe-error-paths.patch
+patches.marzen/0063-serial-sh-sci-Make-probe-fail-for-ports-that-exceed-.patch
+patches.marzen/0064-serial-sh-sci-prepare-for-conversion-to-the-shdma-ba.patch
+patches.marzen/0065-serial-sh-sci-fix-compilation-breakage-when-DMA-is-e.patch
+patches.marzen/0066-net-smsc911x-Repair-broken-failure-paths.patch
+patches.marzen/0067-smsc911x.c-encapsulate-enable-irq-calls.patch
+patches.marzen/0068-clocksource-sh_tmu-Convert-timer-lock-to-raw-spinloc.patch
+patches.marzen/0069-mmc-tmio-use-MMC-opcode-defines-instead-of-numbers.patch
+patches.marzen/0070-mmc-cd-gpio-pass-IRQF_ONESHOT-to-request_threaded_ir.patch
+patches.marzen/0071-mmc-extend-and-rename-cd-gpio-helpers-to-handle-more.patch
+patches.marzen/0072-mmc-tmio-Don-t-access-hardware-registers-after-stopp.patch
+patches.marzen/0073-mmc-tmio-don-t-needlessly-enable-interrupts-during-p.patch
+patches.marzen/0074-mmc-sdhi-implement-tmio-mmc-clock-enable-update-and-.patch
+patches.marzen/0075-mmc-tmio-add-callbacks-to-enable-update-and-disable-.patch
+patches.marzen/0076-mmc-sdhi-do-not-install-dummy-callbacks.patch
+patches.marzen/0077-mmc-add-a-function-to-get-regulators-supplying-card-.patch
+patches.marzen/0078-mmc-tmio-add-regulator-support.patch
+patches.marzen/0079-mmc-tmio-remove-a-duplicated-comment-line.patch
+patches.marzen/0080-mmc-tmio-support-caps2-flags.patch
+patches.marzen/0081-mmc-sh_mobile_sdhi-support-caps2-flags.patch
+patches.marzen/0082-mmc-sdhi-add-OF-support-make-platform-data-optional.patch
+patches.marzen/0083-mmc-core-use-a-more-generic-name-for-slot-function-t.patch
+patches.marzen/0084-mmc-add-two-capability-flags-for-CD-and-WP-signal-po.patch
+patches.marzen/0085-mmc-add-CD-GPIO-polling-support-to-slot-functions.patch
+patches.marzen/0086-mmc-core-convert-slot-functions-to-managed-allocatio.patch
+patches.marzen/0087-mmc-core-add-WP-pin-handler-to-slot-functions.patch
+patches.marzen/0088-mmc-tmio-use-generic-GPIO-CD-and-WP-handlers.patch
+patches.marzen/0089-mmc-sh_mobile_sdhi-prepare-for-conversion-to-the-shd.patch
+patches.marzen/0090-mmc-sh_mmcif-remove-unneeded-struct-sh_mmcif_dma-pre.patch
+patches.marzen/0091-mmc-sh_mmcif-switch-to-the-new-DMA-channel-allocatio.patch
+patches.marzen/0092-mmc-sh_mmcif-Support-MMC_SLEEP_AWAKE-command.patch
+patches.marzen/0093-mmc-sh_mmcif-simplify-and-use-meaningful-label-names.patch
+patches.marzen/0094-mmc-sh_mmcif-fix-clock-management.patch
+patches.marzen/0095-mmc-sh_mmcif-re-read-the-clock-frequency-every-time-.patch
+patches.marzen/0096-mmc-sh_mmcif-remove-redundant-.down_pwr-callback.patch
+patches.marzen/0097-mmc-sh_mmcif-add-regulator-support.patch
+patches.marzen/0098-mmc-sh-mmcif-add-OF-support-make-platform-data-optio.patch
+patches.marzen/0099-mmc-sh_mmcif-support-generic-card-detection.patch
+
+
+patches.armadillo800/0001-ARM-shmobile-add-common-DMAEngine-definitions.patch
+patches.armadillo800/0002-ARM-shmobile-soc-core-add-R-mobile-PM-domain-common-.patch
+patches.armadillo800/0003-media-V4L2-sh_mobile_ceu-manage-lower-8bit-bus.patch
+patches.armadillo800/0004-regulator-support-multiple-dummy-fixed-regulators.patch
+patches.armadillo800/0005-regulator-extend-the-fixed-dummy-voltage-regulator-t.patch
+patches.armadillo800/0006-Input-gpio_keys-remove-useless-reinitialization-of-p.patch
+patches.armadillo800/0007-Input-st1232-add-device-tree-support.patch
+patches.armadillo800/0008-Input-st1232-switch-to-using-SIMPLE_DEV_PM_OPS.patch
+patches.armadillo800/0009-net-sh_eth-add-support-R8A7740.patch
+patches.armadillo800/0010-net-sh_eth-fix-the-rxdesc-pointer-when-rx-descriptor.patch
+patches.armadillo800/0011-net-sh_eth-fix-the-condition-to-fix-the-cur_tx-dirty.patch
+patches.armadillo800/0012-net-sh-eth-Add-support-selecting-MII-function-for-SH.patch
+patches.armadillo800/0013-net-sh-eth-Check-return-value-of-sh_eth_reset-when-c.patch
+patches.armadillo800/0014-net-sh_eth-remove-unnecessary-function.patch
+patches.armadillo800/0015-net-sh_eth-remove-unnecessary-members-definitions.patch
+patches.armadillo800/0016-net-sh_eth-fix-up-the-buffer-pointers.patch
+patches.armadillo800/0017-net-sh_eth-add-support-for-set_ringparam-get_ringpar.patch
+patches.armadillo800/0018-net-sh_eth-Add-eth-support-for-R8A7779-device.patch
+patches.armadillo800/0019-ASoC-add-generic-simple-card-support.patch
+patches.armadillo800/0020-ASoC-sh-fsi-use-simple-card-instead-of-fsi-ak4642.patch
+patches.armadillo800/0021-ASoC-sh-fsi-use-simple-card-instead-of-fsi-hdmi.patch
+patches.armadillo800/0022-ASoC-sh-fsi-use-simple-card-instead-of-fsi-da7210.patch
+patches.armadillo800/0023-ASoC-sh-fsi-use-register-field-macro-name-on-IN-OUT_.patch
+patches.armadillo800/0024-ASoC-sh-fsi-add-fsi_version-and-removed-meaningless-.patch
+patches.armadillo800/0025-ASoC-sh-fsi-use-same-format-for-IN-OUT.patch
+patches.armadillo800/0026-ASoC-sh-fsi-call-fsi_hw_startup-shutdown-from-fsi_da.patch
+patches.armadillo800/0027-ASoC-sh-fsi-enable-chip-specific-data-transfer-mode.patch
+patches.armadillo800/0028-ASoC-fsi-bugfix-enable-master-clock-control-on-DMA-s.patch
+patches.armadillo800/0029-ASoC-fsi-bugfix-correct-dma-area.patch
+patches.armadillo800/0030-ASoC-fsi-bugfix-ensure-dma-is-terminated.patch
+patches.armadillo800/0031-ASoC-fsi-use-dmaengine-helper-functions.patch
+patches.armadillo800/0032-ASoC-fsi-use-PIO-handler-if-DMA-handler-was-invalid.patch
+#patches.armadillo800/0033-ASoC-fsi-prepare-for-conversion-to-the-shdma-base-li.patch
+patches.armadillo800/0034-fbdev-sh_mobile_hdmi-add-hdmi_bit_set-function.patch
+patches.armadillo800/0035-fbdev-sh_mobile_hdmi-add-interrupt-output-option.patch
+patches.armadillo800/0036-fbdev-sh_mobile_hdmi-32bit-register-access-support.patch
+patches.armadillo800/0037-fbdev-sh_mobile_hdmi-add-HDMI-Control-Register-suppo.patch
+patches.armadillo800/0038-fbdev-sh_mipi_dsi-fix-a-section-mismatch.patch
+patches.armadillo800/0039-fbdev-sh_mobile_lcdc-Constify-sh_mobile_lcdc_fix-str.patch
+patches.armadillo800/0040-fbdev-sh_mobile_lcdc-Rename-fb-operation-handlers-wi.patch
+patches.armadillo800/0041-fbdev-sh_mobile_lcdc-Implement-overlays-support.patch
+patches.armadillo800/0042-sh_mobile_meram-Rename-operations-to-cache_-alloc-fr.patch
+patches.armadillo800/0043-sh_mobile_meram-Use-direct-function-calls-for-the-pu.patch
+patches.armadillo800/0044-sh_mobile_meram-Add-direct-MERAM-allocation-API.patch
+patches.armadillo800/0045-fbdev-sh_mobile_lcdc-Destroy-mutex-at-remove-time.patch
+patches.armadillo800/0046-fbdev-sh_mobile_lcdc-Fix-line-pitch-computation.patch
+patches.armadillo800/0047-fbdev-sh_mobile_lcdc-Use-channel-configuration-to-in.patch
+patches.armadillo800/0048-fbdev-sh_mobile_lcdc-Support-horizontal-panning.patch
+patches.armadillo800/0049-fbdev-sh_mobile_lcdc-Fix-overlay-registers-update-du.patch
+patches.armadillo800/0050-fbdev-sh_mobile_lcdc-Fix-pan-offset-computation-in-Y.patch
+patches.armadillo800/0051-fbdev-sh_mobile_lcdc-Fix-vertical-panning-step.patch
+patches.armadillo800/0052-ARM-mach-shmobile-r8a7740-add-gpio_irq-support.patch
+patches.armadillo800/0053-ARM-mach-shmobile-r8a7740-cleanup-I2C-workaround-met.patch
+patches.armadillo800/0054-ARM-mach-shmobile-clock-r8a7740-add-FSI-clock.patch
+patches.armadillo800/0055-ARM-mach-shmobile-clock-r8a7740-add-USB-clock.patch
+patches.armadillo800/0056-ARM-mach-shmobile-clock-r8a7740-add-SDHI-clock.patch
+patches.armadillo800/0057-ARM-mach-shmobile-clock-r8a7740-add-MMCIF-clock.patch
+patches.armadillo800/0058-ARM-mach-shmobile-clock-r8a7740-use-followparent_rec.patch
+patches.armadillo800/0059-ARM-mach-shmobile-add-armadillo800eva-board-support.patch
+patches.armadillo800/0060-ARM-mach-shmobile-armadillo800eva-add-defconfig.patch
+patches.armadillo800/0061-ARM-mach-shmobile-armadillo800eva-add-support-LCDC0.patch
+patches.armadillo800/0062-ARM-mach-shmobile-armadillo800eva-add-support-gpio_k.patch
+patches.armadillo800/0063-ARM-mach-shmobile-armadillo800eva-add-support-sh_eth.patch
+patches.armadillo800/0064-ARM-mach-shmobile-armadillo800eva-add-support-ST1232.patch
+patches.armadillo800/0065-ARM-mach-shmobile-armadillo800eva-add-USB-function-s.patch
+patches.armadillo800/0066-ARM-mach-shmobile-armadillo800eva-add-SDHI0-support.patch
+patches.armadillo800/0067-ARM-mach-shmobile-armadillo800eva-add-SDHI1-support.patch
+patches.armadillo800/0068-ARM-mach-shmobile-armadillo800eva-add-MMCIF-support.patch
+patches.armadillo800/0069-ARM-mach-shmobile-r8a7740-reserve-DMA-memory-for-the.patch
+patches.armadillo800/0070-ARM-mach-shmobile-clock-r8a7740-add-sh-eth-clock.patch
+patches.armadillo800/0071-ARM-mach-shmobile-armadillo800eva-defconfig-update.patch
+patches.armadillo800/0072-ARM-mach-shmobile-Use-DT_MACHINE-for-armadillo-800-e.patch
+patches.armadillo800/0073-ARM-shmobile-r8a7740-add-HDMI-interrupt-support.patch
+patches.armadillo800/0074-ARM-shmobile-r8a7740-add-HDMI-clock-support.patch
+patches.armadillo800/0075-ARM-shmobile-r8a7740-add-HDMI-GPIO-support.patch
+patches.armadillo800/0076-ARM-shmobile-r8a7740-add-MERAM-work-around.patch
+patches.armadillo800/0077-ARM-shmobile-r8a7740-add-CEU-clock-support.patch
+patches.armadillo800/0078-ARM-shmobile-r8a7740-add-FSI-parent-clock-support.patch
+patches.armadillo800/0079-ARM-shmobile-r8a7740-add-FSI-B-for-HDMI-GPIO-support.patch
+patches.armadillo800/0080-ARM-shmobile-armadillo800eva-enable-HDMI.patch
+patches.armadillo800/0081-ARM-mach-shmobile-armadillo800eva-Use-late-init-mach.patch
+patches.armadillo800/0082-ARM-shmobile-armadillo800eva-enable-camera.patch
+patches.armadillo800/0083-ARM-shmobile-r8a7740-add-DMAEngine-support-for-FSI.patch
+patches.armadillo800/0084-ARM-shmobile-r8a7740-add-DMAEngine-support-for-SDHI.patch
+patches.armadillo800/0085-ARM-shmobile-r8a7740-add-DMAEngine-support-for-USB.patch
+patches.armadillo800/0086-ARM-shmobile-use-common-DMAEngine-definitions-on-r8a.patch
+patches.armadillo800/0087-ARM-shmobile-armadillo800eva-enable-FSI-WM8978-sound.patch
+patches.armadillo800/0088-ARM-shmobile-armadillo800eva-enable-FSI-HDMI-sound.patch
+patches.armadillo800/0089-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-FSI.patch
+patches.armadillo800/0090-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-SDH.patch
+patches.armadillo800/0091-ARM-shmobile-armadillo800eva-enable-DMAEngine-on-USB.patch
+patches.armadillo800/0092-ARM-shmobile-use-common-extra-gpio-functions-on-arma.patch
+patches.armadillo800/0093-ARM-mach-shmobile-add-fixed-voltage-regulators-to-ar.patch
+patches.armadillo800/0094-ARM-mach-shmobile-Convert-sh_clk_mstp32_register-to-.patch
+patches.armadillo800/0095-ARM-shmobile-r8a7740-fixup-MSEL1CR-7bit-control.patch
+patches.armadillo800/0096-ARM-shmobile-r8a7740-add-A4S-pm-domain-support.patch
+patches.armadillo800/0097-ARM-shmobile-r8a7740-add-A3SP-pm-domain-support.patch
+patches.armadillo800/0098-ARM-shmobile-r8a7740-add-A4LC-pm-domain-support.patch
+patches.armadillo800/0099-ARM-shmobile-armadillo800eva-USB-Func-enables-extern.patch
+patches.armadillo800/0100-ARM-shmobile-armadillo800eva-A4LC-domain-includes-LC.patch
+patches.armadillo800/0101-ARM-shmobile-armadillo800eva-A3SP-domain-includes-US.patch
+patches.armadillo800/0102-ARM-mach-shmobile-r8a7740-generic-board-support-via-.patch
+patches.armadillo800/0103-ARM-mach-shmobile-armadillo800eva-defconfig-Allow-us.patch
+patches.armadillo800/0104-ARM-mach-shmobile-armadillo800eva-Fix-GPIO-buttons-d.patch
+patches.armadillo800/0105-ARM-mach-shmobile-armadillo800eva-Enable-power-butto.patch
+patches.armadillo800/0106-ARM-shmobile-armadillo800eva-fixup-sound-card-detect.patch
+patches.armadillo800/0107-ARM-shmobile-armadillo800eva-enable-rw-rootfs-mount.patch