From 8edf8c56a8e4c67adca72270b24e55f34f8b01ab Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Thu, 15 Nov 2018 14:43:32 +0100 Subject: [PATCH] [sunxi-dev] Adjusted patchset. Tested on H3, H5, A64, A83T, H6, ... focused only on basic features such as dvfs, hdmi, ... Kernel sources are switched to @megous and many patches were taken from @anarsoul branch, mostly regarding Pinebook/A64 which will take some time to get upstream. It's a mess which will be eventually sorted out or merged up. --- config/boards/orangepipc2.conf | 4 +- config/boards/orangepiprime.conf | 4 +- config/kernel/linux-sunxi-dev.config | 22 +- config/kernel/linux-sunxi64-dev.config | 24 +- config/sources/sun50iw6.conf | 24 +- config/sources/sunxi64_common.inc | 9 +- config/sources/sunxi_common.inc | 8 +- lib/debootstrap-ng.sh | 9 + patch/kernel/sunxi-dev-h6/add-1.8ghz.patch | 17 - .../add-overlay-compilation-support.patch | 125 - .../add_configfs_overlay_for_v4.18.x.patch | 326 - ...rd-0001-orangepi-one-plus-add-device.patch | 275 - ...board-0002-orangepi-lite2-add-device.patch | 287 - .../board-h6-add-mmc1-pins-oplite2.patch | 19 - .../board-h6-add-rtc-osc32k-out.patch | 35 - .../general-packaging-4.17-dev.patch | 221 - .../0000-axp-adjustements.patch.disabled | 229 + .../sunxi-dev/0000-remove-old-ths-node.patch | 24 + ...odec-Initial-implementation.patch.disabled | 346 + .../sunxi-dev/0000-unlock-h5-dvfs.patch | 46 + ...llwinner-a64-enable-Wi-Fi-for-Pine64.patch | 52 + ...4-allwinner-a64-add-Mali-device-node.patch | 72 + ...-sun8i-support-RGMII-modes-with-PHY-.patch | 35 + ...a64-disable-the-RTL8211E-internal-RX.patch | 35 + ...gem-cma-Export-with-handle-allocator.patch | 50 + .../0006-drm-sun4i-Add-GEM-allocator.patch | 102 + ...d-sopine-HDMI-sound-and-WiFi-support.patch | 96 + ...n50i-a64-pine64-add-HDMI-audio-nodes.patch | 39 + ...te-the-Allwinner-GPADC-device-tree-b.patch | 95 + ...adc-iio-rename-A33-specified-registe.patch | 56 + ...adc-iio-rework-sampling-start-end-co.patch | 237 + ...adc-iio-rework-support-clocks-and-re.patch | 168 + ...adc-iio-rework-support-multible-sens.patch | 186 + ...adc-iio-rework-support-nvmem-calibra.patch | 166 + ...adc-iio-rework-add-interrupt-support.patch | 253 + ...adc-iio-add-support-for-H3-thermal-s.patch | 67 + ...adc-iio-add-support-for-A83T-thermal.patch | 75 + ...-h5-add-support-for-the-thermal-sens.patch | 39 + ...-add-support-for-the-thermal-sensor-.patch | 30 + ...-dts-sun8i-h3-add-thermal-zone-to-H3.patch | 36 + ...h3-enable-H3-sid-controller.patch.disabled | 34 + ...pport-for-the-thermal-senso.patch.disabled | 38 + ...3t-add-thermal-zone-to-A83T.patch.disabled | 46 + ...config-enable-A80-A64-and-H5-for-THS.patch | 26 + ...adc-iio-add-support-for-H5-thermal-s.patch | 79 + ...adc-iio-add-support-for-A80-thermal-.patch | 86 + ...adc-iio-add-support-for-A64-thermal-.patch | 87 + ...ner-h5-add-support-for-the-thermal-s.patch | 30 + ...s-allwinner-h5-add-termal-zone-to-H5.patch | 43 + ...0-add-support-for-the-thermal-sensor.patch | 42 + ...ts-sun9i-a80-add-thermal-zone-to-A80.patch | 54 + patch/kernel/sunxi-dev/0034-dts-a64-ths.patch | 62 + ...-mux-and-pll-notifiers-for-A64-CPU-c.patch | 73 + ...ignore-zero-samples-to-avoid-force-p.patch | 31 + .../kernel/sunxi-dev/0037-a64-dvfs-wip.patch | 251 + ...0038-ARM-dts-add-gpu-node-to-exynos4.patch | 64 + ...switch-delay-property-for-mali-utgar.patch | 29 + .../0042-drm-lima-add-lima-uapi-header.patch | 215 + ...-lima-add-mali-4xx-GPU-hardware-regs.patch | 325 + .../0044-drm-lima-add-lima-core-driver.patch | 573 + ...45-drm-lima-add-GPU-device-functions.patch | 573 + ...6-drm-lima-add-PMU-related-functions.patch | 144 + ...0047-drm-lima-add-L2-cache-functions.patch | 158 + ...48-drm-lima-add-GP-related-functions.patch | 358 + ...49-drm-lima-add-PP-related-functions.patch | 487 + ...0-drm-lima-add-MMU-related-functions.patch | 218 + ...-drm-lima-add-BCAST-related-function.patch | 131 + ...-drm-lima-add-DLBU-related-functions.patch | 142 + ...add-GPU-virtual-memory-space-handing.patch | 414 + ...drm-lima-add-TTM-subsystem-functions.patch | 481 + ...drm-lima-add-buffer-object-functions.patch | 235 + ...6-drm-lima-add-GEM-related-functions.patch | 530 + ...lima-add-GEM-Prime-related-functions.patch | 126 + ...ima-add-GPU-schedule-using-DRM_SCHED.patch | 651 + ...m-lima-add-context-related-functions.patch | 222 + ...60-drm-lima-add-makefile-and-kconfig.patch | 83 + ...PDX-identifiers-and-change-copyright.patch | 1115 ++ .../0062-drm-lima-lima_reg.h-use-BIT.patch | 306 + ...-drm-lima-add-IRQF_SHARED-for-GP-irq.patch | 30 + ...-Kconfig-only-depend-on-ARM-or-ARM64.patch | 30 + ...drm-lima-add-comments-for-lima_reg.h.patch | 31 + ...m-lima-wait-bo-fence-before-bo-close.patch | 114 + ...067-drm-lima-refine-lima_gem_sync_bo.patch | 125 + ...ll-be-freed-when-lima_sched_free_job.patch | 25 + ...m-alloc-buffer-with-multi-page-table.patch | 189 + ...-lima-clear-vm-page-table-when-alloc.patch | 35 + ...te-SPDX-header-to-match-kernel-rules.patch | 514 + ...fourcc-add-ARM-tiled-format-modifier.patch | 33 + ...-drm-lima-add-DRM_LIMA_GEM_MOD-ioctl.patch | 172 + ...DOs-for-pll-mipi-and-add-min-max-rat.patch | 58 + ...pine-baseboard-enable-HS200-for-eMMC.patch | 25 + ...6-drm-lima-remove-depend-on-ARM-arch.patch | 63 + .../0077-drm-lima-port-to-4.18-kernel.patch | 27 + ...an-choose-not-to-use-dlbu-on-mali450.patch | 309 + ...rkaround-for-dw_hdmi-v1.32a.patch.disabled | 58 + ...e-error-message-about-failure-to-all.patch | 26 + ...-Workaround-for-Allwinner-A64-timer-.patch | 178 + ...nner-a64-Enable-A64-timer-workaround.patch | 30 + ...-maximum-rate-constraint-to-NM-PLLs.patch} | 20 + ...5-Add-max.-rate-constraint-to-pll-v.patch} | 27 + ...ust-MP-clock-parent-rate-when-allowe.patch | 107 + ...g-Use-u64-for-calculation-of-NM-rate.patch | 74 + ...ass-drm_encoder-into-sun4i_tcon0_mod.patch | 66 + ...ename-Dithering-related-register-mac.patch | 59 + ...dd-dithering-support-for-RGB565-RGB6.patch | 132 + ...revent-tcon-panel-dereference-if-nul.patch | 34 + ...-a64-Add-minimal-rate-for-video-PLLs.patch | 84 + ...-Add-max.-rate-constraint-to-video-P.patch | 90 + ...lay-Add-compatible-for-A64-DE2-displ.patch | 52 + ...drm-sun4i-Add-support-for-A64-mixers.patch | 62 + ...i-Add-support-for-A64-display-engine.patch | 33 + ...-display-Add-compatible-for-A64-HDMI.patch | 33 + ...k-sun50i-a64-ccu-Add-PLL_VIDEO0-macr.patch | 49 + ...s-allwinner-a64-Add-display-pipeline.patch | 221 + ...i-drm-add-HDMI-VCC-supply-property-f.patch | 33 + ...d-support-for-HDMI-voltage-regulator.patch | 87 + ...ner-a64-Enable-HDMI-output-on-A64-bo.patch | 364 + ...r-supply-axp20x-add-AXP813-AC-power-.patch | 42 + ...r-supply-axp20x-add-AXP803-power-bin.patch | 43 + ...-gpio-axp209-add-AXP803-GPIO-binding.patch | 38 + ...ings-iio-adc-add-AXP803-ADC-bindings.patch | 37 + ...s-axp81x-add-AC-power-supply-subnode.patch | 34 + ...ner-axp803-add-AC-and-battery-power-.patch | 63 + ...ner-a64-sopine-baseboard-enable-powe.patch | 39 + ...ner-a64-pinebook-enable-power-suppli.patch | 35 + ...dd-AC-power-supply-driver-for-AXP813.patch | 179 + ...-Add-AC-power-supply-cell-for-AXP813.patch | 41 + ...xp20x-Add-supported-cells-for-AXP803.patch | 49 + ...ove-code-from-startup-shutdown-hooks.patch | 117 + ...Add-compatibility-with-A64-codec-I2S.patch | 80 + ...codec-Don-t-hardcode-BCLK-LRCK-ratio.patch | 79 + ...-analog-split-regmap-code-into-separ.patch | 283 + ...Add-bindings-for-Allwinner-A64-codec.patch | 40 + ...ew-driver-for-Allwinner-A64-codec-s-.patch | 505 + ...-the-sun8i-codec-driver-to-be-built-.patch | 31 + ...ner-a64-add-nodes-necessary-for-anal.patch | 99 + ...ner-a64-enable-sound-on-Pine64-and-S.patch | 120 + ...lwinner-a64-enable-sound-on-Pinebook.patch | 86 + ...nable-dithering-on-tcon0-is-there-s-.patch | 58 + ...a-to-work-with-drm-scheduler-changes.patch | 46 + ...125-drm-lima-Fix-lima-cache-creation.patch | 56 + ...ANA78xx-driver-to-analogix-subdirect.patch | 100 + ...-some-definitions-of-ANX78xx-to-dedi.patch | 1005 + ...act-some-Analogix-I2C-DP-common-code.patch | 403 + ...d-ANX6345-DP-eDP-transmitter-binding.patch | 64 + ...-bridge-Add-Analogix-anx6345-support.patch | 981 + ...winner-a64-add-pinmux-for-RGB666-LCD.patch | 37 + ...a64-enable-ANX6345-bridge-on-Pineboo.patch | 84 + ...a64-enable-ANX6345-bridge-on-TERES-I.patch | 87 + ...d-5-tolerance-to-dot-clock-frequency.patch | 58 + ...ble-so-said-LDOs-for-A64-SoC-s-pll-m.patch | 43 + .../sunxi-dev/0136-hdmi-audio-fixup.patch | 24 + .../sunxi-dev/0137-Pinebook-HDMI-audio.patch | 39 + ...e-SND_SUNXI_ADDA_PR_REGMAP-to-SND_SU.patch | 36 + ...or-broken-local-ext-feature.patch.disabled | 54 + ...-Add-support-for-reset-GPIO.patch.disabled | 57 + ...oth-Add-rtl8723bs-bluetooth.patch.disabled | 57 + ...ort-for-binding-RTL8723BS-w.patch.disabled | 68 + ...d-support-for-the-RTL8723CS.patch.disabled | 311 + ...nable-Bluetooth-On-Pinebook.patch.disabled | 44 + ...-enable-Bluetooth-On-Pine64.patch.disabled | 40 + ...e-Bluetooth-On-SoPine-baseb.patch.disabled | 45 + ...ard-a10-lime-a10-add-240-mhz-cpufreq.patch | 12 - ...dts-allwinner-a64-Add-L2-cache-nodes.patch | 27 +- ...s-allwinner-a64-Olinuxino-enable-USB.patch | 7 +- ...ress-some-stability-issues.patch.disabled} | 0 .../board-olinuxino-A64-add-eMMC.patch | 8 +- ...port-for-allwinner-CSI-with-tiny-fix.patch | 2225 --- .../sunxi-dev/dvfs-regulator-opi-pc.patch | 36 - .../dvfs-regulator-update-sy8106a.patch | 48 - .../general-a64-enable-fsl-timer-errata.patch | 12 - .../general-add-HDMI-sound-nodes-DT.patch | 55 - ...eral-arm64-add-proc-cpuinfo-entries.patch} | 0 .../need-to-check}/a64-DT-DVFS.patch | 0 .../need-to-check}/a64-DVFS-cpu-supply.patch | 0 .../need-to-check}/a64-pll_cpux-test.patch | 0 .../add-mtd-spi-nor-dts.patch.disabled | 0 .../add-overlay-compilation-support.patch | 0 .../need-to-check}/add-spi-flash-pc2.patch | 0 .../need-to-check}/add-sun50i-ths.patch | 0 .../need-to-check}/add-sunxi64-overlays.patch | 0 .../need-to-check}/add-sy8106a-driver.patch | 0 .../add_BergMicro_flashes_to_SPI-NOR.patch | 0 .../add_configfs_overlay_for_v4.10.x.patch | 0 .../add_nanopim1plus2_dts.patch | 0 ...add_proc_cpuinfo_entries_for_v4.10.x.patch | 0 .../need-to-check}/add_sun50i_a64_spi.patch | 0 .../need-to-check}/badd-nanopineoplus2.patch | 0 .../need-to-check}/bash_to_afterinstall.patch | 0 .../disable-reg_dc1sw-pine64.patch.disabled | 0 .../dvfs-regulator-opi-2.patch | 0 .../dvfs-regulator-opi-pc2.patch | 0 .../dvfs-regulator-prime.patch | 0 .../enable-fsl-timer-errata.patch | 0 .../fix-i2c2-reg-property.patch | 0 .../fix-pinebook-backlight.patch | 0 .../fix-zeroplus2-mmc0-cd-polarity.patch | 0 .../scripts-dtc-import-updates.patch | 0 .../set-default-target-to-Image.patch | 0 .../spidev-remove-warnings.patch | 0 patch/kernel/sunxi-dev/patch-4.19.1-2.patch | 15435 ++++++++++++++++ ...s-21-sun4i-gpadc-iio-add-split-sun8i.patch | 30 - ...hs-22-sun4i-gpadc-iio-add-H3-support.patch | 392 - ...i-gpadc-iio-add-H3-thermal-sensor-DT.patch | 28 - ...4i-gpadc-iio-add-H3-CPU-thermal-zone.patch | 93 - ...-gpadc-iio-workaround-for-raw-0-read.patch | 34 - ...6-sun4i-gpadc-iio-add-h5-a64-support.patch | 153 - .../ths-27-sun4i-gpadc-iio-add-h5-DT.patch | 28 - ...hs-49-add-h5-cpu-opp-table.patch.disabled} | 0 ...50-add-h5-opp-table-to-cpu.patch.disabled} | 0 ...-add-realtek-8189es-kconfig-makefile.patch | 0 .../wifi-3002-add-realtek-8189es.patch | 11 +- ...-add-realtek-8723cs-kconfig-makefile.patch | 0 .../wifi-4002-add-realtek-8723cs.patch | 11 +- .../sunxi-dev/wifi-add-realtek-8189fs.patch | 8 +- ..._DMA_block_memory_allocation_to_2048.patch | 13 - ...ing-4.x-DEV-with-postinstall-scripts.patch | 197 - 217 files changed, 36176 insertions(+), 4728 deletions(-) delete mode 100644 patch/kernel/sunxi-dev-h6/add-1.8ghz.patch delete mode 100644 patch/kernel/sunxi-dev-h6/add-overlay-compilation-support.patch delete mode 100644 patch/kernel/sunxi-dev-h6/add_configfs_overlay_for_v4.18.x.patch delete mode 100644 patch/kernel/sunxi-dev-h6/board-0001-orangepi-one-plus-add-device.patch delete mode 100644 patch/kernel/sunxi-dev-h6/board-0002-orangepi-lite2-add-device.patch delete mode 100644 patch/kernel/sunxi-dev-h6/board-h6-add-mmc1-pins-oplite2.patch delete mode 100644 patch/kernel/sunxi-dev-h6/board-h6-add-rtc-osc32k-out.patch delete mode 100644 patch/kernel/sunxi-dev-h6/general-packaging-4.17-dev.patch create mode 100644 patch/kernel/sunxi-dev/0000-axp-adjustements.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0000-remove-old-ths-node.patch create mode 100644 patch/kernel/sunxi-dev/0000-sound-soc-ac100-codec-Initial-implementation.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0000-unlock-h5-dvfs.patch create mode 100644 patch/kernel/sunxi-dev/0001-arm64-allwinner-a64-enable-Wi-Fi-for-Pine64.patch create mode 100644 patch/kernel/sunxi-dev/0002-arm64-allwinner-a64-add-Mali-device-node.patch create mode 100644 patch/kernel/sunxi-dev/0003-net-stmmac-dwmac-sun8i-support-RGMII-modes-with-PHY-.patch create mode 100644 patch/kernel/sunxi-dev/0004-arm64-allwinner-a64-disable-the-RTL8211E-internal-RX.patch create mode 100644 patch/kernel/sunxi-dev/0005-drm-gem-cma-Export-with-handle-allocator.patch create mode 100644 patch/kernel/sunxi-dev/0006-drm-sun4i-Add-GEM-allocator.patch create mode 100644 patch/kernel/sunxi-dev/0007-Add-sopine-HDMI-sound-and-WiFi-support.patch create mode 100644 patch/kernel/sunxi-dev/0008-arm64-dts-sun50i-a64-pine64-add-HDMI-audio-nodes.patch create mode 100644 patch/kernel/sunxi-dev/0009-dt-bindings-update-the-Allwinner-GPADC-device-tree-b.patch create mode 100644 patch/kernel/sunxi-dev/0011-iio-adc-sun4i-gpadc-iio-rename-A33-specified-registe.patch create mode 100644 patch/kernel/sunxi-dev/0012-iio-adc-sun4i-gpadc-iio-rework-sampling-start-end-co.patch create mode 100644 patch/kernel/sunxi-dev/0013-iio-adc-sun4i-gpadc-iio-rework-support-clocks-and-re.patch create mode 100644 patch/kernel/sunxi-dev/0014-iio-adc-sun4i-gpadc-iio-rework-support-multible-sens.patch create mode 100644 patch/kernel/sunxi-dev/0015-iio-adc-sun4i-gpadc-iio-rework-support-nvmem-calibra.patch create mode 100644 patch/kernel/sunxi-dev/0016-iio-adc-sun4i-gpadc-iio-rework-add-interrupt-support.patch create mode 100644 patch/kernel/sunxi-dev/0017-iio-adc-sun4i-gpadc-iio-add-support-for-H3-thermal-s.patch create mode 100644 patch/kernel/sunxi-dev/0018-iio-adc-sun4i-gpadc-iio-add-support-for-A83T-thermal.patch create mode 100644 patch/kernel/sunxi-dev/0019-arm-dts-sunxi-h3-h5-add-support-for-the-thermal-sens.patch create mode 100644 patch/kernel/sunxi-dev/0020-arm-dts-sun8i-h3-add-support-for-the-thermal-sensor-.patch create mode 100644 patch/kernel/sunxi-dev/0021-arm-dts-sun8i-h3-add-thermal-zone-to-H3.patch create mode 100644 patch/kernel/sunxi-dev/0022-arm-dts-sun8i-h3-enable-H3-sid-controller.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0023-arm-dts-sun8i-a83t-add-support-for-the-thermal-senso.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0024-arm-dts-sun8i-a83t-add-thermal-zone-to-A83T.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0026-iio-adc-Kconfig-enable-A80-A64-and-H5-for-THS.patch create mode 100644 patch/kernel/sunxi-dev/0027-iio-adc-sun4i-gpadc-iio-add-support-for-H5-thermal-s.patch create mode 100644 patch/kernel/sunxi-dev/0028-iio-adc-sun4i-gpadc-iio-add-support-for-A80-thermal-.patch create mode 100644 patch/kernel/sunxi-dev/0029-iio-adc-sun4i-gpadc-iio-add-support-for-A64-thermal-.patch create mode 100644 patch/kernel/sunxi-dev/0030-arm64-dts-allwinner-h5-add-support-for-the-thermal-s.patch create mode 100644 patch/kernel/sunxi-dev/0031-arm64-dts-allwinner-h5-add-termal-zone-to-H5.patch create mode 100644 patch/kernel/sunxi-dev/0032-arm-dts-sun9i-a80-add-support-for-the-thermal-sensor.patch create mode 100644 patch/kernel/sunxi-dev/0033-arm-dts-sun9i-a80-add-thermal-zone-to-A80.patch create mode 100644 patch/kernel/sunxi-dev/0034-dts-a64-ths.patch create mode 100644 patch/kernel/sunxi-dev/0035-clk-sunxi-ng-add-mux-and-pll-notifiers-for-A64-CPU-c.patch create mode 100644 patch/kernel/sunxi-dev/0036-sun4i-gpadc-iio-ignore-zero-samples-to-avoid-force-p.patch create mode 100644 patch/kernel/sunxi-dev/0037-a64-dvfs-wip.patch create mode 100644 patch/kernel/sunxi-dev/0038-ARM-dts-add-gpu-node-to-exynos4.patch create mode 100644 patch/kernel/sunxi-dev/0039-dt-bindings-add-switch-delay-property-for-mali-utgar.patch create mode 100644 patch/kernel/sunxi-dev/0042-drm-lima-add-lima-uapi-header.patch create mode 100644 patch/kernel/sunxi-dev/0043-drm-lima-add-mali-4xx-GPU-hardware-regs.patch create mode 100644 patch/kernel/sunxi-dev/0044-drm-lima-add-lima-core-driver.patch create mode 100644 patch/kernel/sunxi-dev/0045-drm-lima-add-GPU-device-functions.patch create mode 100644 patch/kernel/sunxi-dev/0046-drm-lima-add-PMU-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0047-drm-lima-add-L2-cache-functions.patch create mode 100644 patch/kernel/sunxi-dev/0048-drm-lima-add-GP-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0049-drm-lima-add-PP-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0050-drm-lima-add-MMU-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0051-drm-lima-add-BCAST-related-function.patch create mode 100644 patch/kernel/sunxi-dev/0052-drm-lima-add-DLBU-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0053-drm-lima-add-GPU-virtual-memory-space-handing.patch create mode 100644 patch/kernel/sunxi-dev/0054-drm-lima-add-TTM-subsystem-functions.patch create mode 100644 patch/kernel/sunxi-dev/0055-drm-lima-add-buffer-object-functions.patch create mode 100644 patch/kernel/sunxi-dev/0056-drm-lima-add-GEM-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0057-drm-lima-add-GEM-Prime-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0058-drm-lima-add-GPU-schedule-using-DRM_SCHED.patch create mode 100644 patch/kernel/sunxi-dev/0059-drm-lima-add-context-related-functions.patch create mode 100644 patch/kernel/sunxi-dev/0060-drm-lima-add-makefile-and-kconfig.patch create mode 100644 patch/kernel/sunxi-dev/0061-drm-lima-use-SPDX-identifiers-and-change-copyright.patch create mode 100644 patch/kernel/sunxi-dev/0062-drm-lima-lima_reg.h-use-BIT.patch create mode 100644 patch/kernel/sunxi-dev/0063-drm-lima-add-IRQF_SHARED-for-GP-irq.patch create mode 100644 patch/kernel/sunxi-dev/0064-drm-lima-Kconfig-only-depend-on-ARM-or-ARM64.patch create mode 100644 patch/kernel/sunxi-dev/0065-drm-lima-add-comments-for-lima_reg.h.patch create mode 100644 patch/kernel/sunxi-dev/0066-drm-lima-wait-bo-fence-before-bo-close.patch create mode 100644 patch/kernel/sunxi-dev/0067-drm-lima-refine-lima_gem_sync_bo.patch create mode 100644 patch/kernel/sunxi-dev/0068-drm-lima-vm-will-be-freed-when-lima_sched_free_job.patch create mode 100644 patch/kernel/sunxi-dev/0069-drm-lima-vm-alloc-buffer-with-multi-page-table.patch create mode 100644 patch/kernel/sunxi-dev/0070-drm-lima-clear-vm-page-table-when-alloc.patch create mode 100644 patch/kernel/sunxi-dev/0071-drm-lima-update-SPDX-header-to-match-kernel-rules.patch create mode 100644 patch/kernel/sunxi-dev/0072-drm-fourcc-add-ARM-tiled-format-modifier.patch create mode 100644 patch/kernel/sunxi-dev/0073-drm-lima-add-DRM_LIMA_GEM_MOD-ioctl.patch create mode 100644 patch/kernel/sunxi-dev/0074-a64-ccu-enable-LDOs-for-pll-mipi-and-add-min-max-rat.patch create mode 100644 patch/kernel/sunxi-dev/0075-sopine-baseboard-enable-HS200-for-eMMC.patch create mode 100644 patch/kernel/sunxi-dev/0076-drm-lima-remove-depend-on-ARM-arch.patch create mode 100644 patch/kernel/sunxi-dev/0077-drm-lima-port-to-4.18-kernel.patch create mode 100644 patch/kernel/sunxi-dev/0078-drm-lima-user-can-choose-not-to-use-dlbu-on-mali450.patch create mode 100644 patch/kernel/sunxi-dev/0079-drm-bridge-Add-audio-workaround-for-dw_hdmi-v1.32a.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0080-rtl8723bs-disable-error-message-about-failure-to-all.patch create mode 100644 patch/kernel/sunxi-dev/0081-arm64-arch_timer-Workaround-for-Allwinner-A64-timer-.patch create mode 100644 patch/kernel/sunxi-dev/0082-arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch rename patch/kernel/sunxi-dev/{board-a83t-1-5-clk-sunxi-ng-Add-maximum-rate-constraint-to-NM-PLLs.patch => 0083-clk-sunxi-ng-Add-maximum-rate-constraint-to-NM-PLLs.patch} (74%) rename patch/kernel/sunxi-dev/{board-a83t-2-5-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-video.patch => 0084-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-v.patch} (57%) create mode 100644 patch/kernel/sunxi-dev/0085-clk-sunxi-ng-Adjust-MP-clock-parent-rate-when-allowe.patch create mode 100644 patch/kernel/sunxi-dev/0086-clk-sunxi-ng-Use-u64-for-calculation-of-NM-rate.patch create mode 100644 patch/kernel/sunxi-dev/0087-drm-sun4i-tcon-Pass-drm_encoder-into-sun4i_tcon0_mod.patch create mode 100644 patch/kernel/sunxi-dev/0088-drm-sun4i-tcon-Rename-Dithering-related-register-mac.patch create mode 100644 patch/kernel/sunxi-dev/0089-drm-sun4i-tcon-Add-dithering-support-for-RGB565-RGB6.patch create mode 100644 patch/kernel/sunxi-dev/0090-drm-sun4i-tcon-prevent-tcon-panel-dereference-if-nul.patch create mode 100644 patch/kernel/sunxi-dev/0091-clk-sunxi-ng-a64-Add-minimal-rate-for-video-PLLs.patch create mode 100644 patch/kernel/sunxi-dev/0092-clk-sunxi-ng-a64-Add-max.-rate-constraint-to-video-P.patch create mode 100644 patch/kernel/sunxi-dev/0093-dt-bindings-display-Add-compatible-for-A64-DE2-displ.patch create mode 100644 patch/kernel/sunxi-dev/0094-drm-sun4i-Add-support-for-A64-mixers.patch create mode 100644 patch/kernel/sunxi-dev/0095-drm-sun4i-Add-support-for-A64-display-engine.patch create mode 100644 patch/kernel/sunxi-dev/0096-dt-bindings-display-Add-compatible-for-A64-HDMI.patch create mode 100644 patch/kernel/sunxi-dev/0097-dt-bindings-clock-sun50i-a64-ccu-Add-PLL_VIDEO0-macr.patch create mode 100644 patch/kernel/sunxi-dev/0098-arm64-dts-allwinner-a64-Add-display-pipeline.patch create mode 100644 patch/kernel/sunxi-dev/0099-dt-bindings-sun4i-drm-add-HDMI-VCC-supply-property-f.patch create mode 100644 patch/kernel/sunxi-dev/0100-drm-sun4i-Add-support-for-HDMI-voltage-regulator.patch create mode 100644 patch/kernel/sunxi-dev/0101-arm64-dts-allwinner-a64-Enable-HDMI-output-on-A64-bo.patch create mode 100644 patch/kernel/sunxi-dev/0102-dt-bindings-power-supply-axp20x-add-AXP813-AC-power-.patch create mode 100644 patch/kernel/sunxi-dev/0103-dt-bindings-power-supply-axp20x-add-AXP803-power-bin.patch create mode 100644 patch/kernel/sunxi-dev/0104-dt-bindings-gpio-gpio-axp209-add-AXP803-GPIO-binding.patch create mode 100644 patch/kernel/sunxi-dev/0105-dt-bindings-iio-adc-add-AXP803-ADC-bindings.patch create mode 100644 patch/kernel/sunxi-dev/0106-ARM-dts-axp81x-add-AC-power-supply-subnode.patch create mode 100644 patch/kernel/sunxi-dev/0107-arm64-dts-allwinner-axp803-add-AC-and-battery-power-.patch create mode 100644 patch/kernel/sunxi-dev/0108-arm64-dts-allwinner-a64-sopine-baseboard-enable-powe.patch create mode 100644 patch/kernel/sunxi-dev/0109-arm64-dts-allwinner-a64-pinebook-enable-power-suppli.patch create mode 100644 patch/kernel/sunxi-dev/0110-power-supply-add-AC-power-supply-driver-for-AXP813.patch create mode 100644 patch/kernel/sunxi-dev/0111-mfd-axp20x-Add-AC-power-supply-cell-for-AXP813.patch create mode 100644 patch/kernel/sunxi-dev/0112-mfd-axp20x-Add-supported-cells-for-AXP803.patch create mode 100644 patch/kernel/sunxi-dev/0113-ASoC-sun4i-i2s-move-code-from-startup-shutdown-hooks.patch create mode 100644 patch/kernel/sunxi-dev/0114-ASoC-sun4i-i2s-Add-compatibility-with-A64-codec-I2S.patch create mode 100644 patch/kernel/sunxi-dev/0115-ASoC-sun8i-codec-Don-t-hardcode-BCLK-LRCK-ratio.patch create mode 100644 patch/kernel/sunxi-dev/0116-ASoC-sun8i-codec-analog-split-regmap-code-into-separ.patch create mode 100644 patch/kernel/sunxi-dev/0117-ASoC-dt-binding-Add-bindings-for-Allwinner-A64-codec.patch create mode 100644 patch/kernel/sunxi-dev/0118-ASoC-sunxi-Add-new-driver-for-Allwinner-A64-codec-s-.patch create mode 100644 patch/kernel/sunxi-dev/0119-ASoC-sunxi-allow-the-sun8i-codec-driver-to-be-built-.patch create mode 100644 patch/kernel/sunxi-dev/0120-arm64-dts-allwinner-a64-add-nodes-necessary-for-anal.patch create mode 100644 patch/kernel/sunxi-dev/0121-arm64-dts-allwinner-a64-enable-sound-on-Pine64-and-S.patch create mode 100644 patch/kernel/sunxi-dev/0122-arm64-dts-allwinner-a64-enable-sound-on-Pinebook.patch create mode 100644 patch/kernel/sunxi-dev/0123-drm-sun4i-tcon-enable-dithering-on-tcon0-is-there-s-.patch create mode 100644 patch/kernel/sunxi-dev/0124-drm-lima-Fix-Lima-to-work-with-drm-scheduler-changes.patch create mode 100644 patch/kernel/sunxi-dev/0125-drm-lima-Fix-lima-cache-creation.patch create mode 100644 patch/kernel/sunxi-dev/0126-drm-bridge-move-ANA78xx-driver-to-analogix-subdirect.patch create mode 100644 patch/kernel/sunxi-dev/0127-drm-bridge-split-some-definitions-of-ANX78xx-to-dedi.patch create mode 100644 patch/kernel/sunxi-dev/0128-drm-bridge-extract-some-Analogix-I2C-DP-common-code.patch create mode 100644 patch/kernel/sunxi-dev/0129-dt-bindings-Add-ANX6345-DP-eDP-transmitter-binding.patch create mode 100644 patch/kernel/sunxi-dev/0130-drm-bridge-Add-Analogix-anx6345-support.patch create mode 100644 patch/kernel/sunxi-dev/0131-arm64-allwinner-a64-add-pinmux-for-RGB666-LCD.patch create mode 100644 patch/kernel/sunxi-dev/0132-arm64-allwinner-a64-enable-ANX6345-bridge-on-Pineboo.patch create mode 100644 patch/kernel/sunxi-dev/0133-arm64-allwinner-a64-enable-ANX6345-bridge-on-TERES-I.patch create mode 100644 patch/kernel/sunxi-dev/0134-drm-sun4i-rgb-Add-5-tolerance-to-dot-clock-frequency.patch create mode 100644 patch/kernel/sunxi-dev/0135-clk-sunxi-ng-enable-so-said-LDOs-for-A64-SoC-s-pll-m.patch create mode 100644 patch/kernel/sunxi-dev/0136-hdmi-audio-fixup.patch create mode 100644 patch/kernel/sunxi-dev/0137-Pinebook-HDMI-audio.patch create mode 100644 patch/kernel/sunxi-dev/0138-ASoC-sunxi-rename-SND_SUNXI_ADDA_PR_REGMAP-to-SND_SU.patch create mode 100644 patch/kernel/sunxi-dev/0139-Bluetooth-Add-new-quirk-for-broken-local-ext-feature.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0140-Bluetooth-hci_h5-Add-support-for-reset-GPIO.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0141-dt-bindings-net-bluetooth-Add-rtl8723bs-bluetooth.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0142-Bluetooth-hci_h5-Add-support-for-binding-RTL8723BS-w.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0143-Bluetooth-btrtl-add-support-for-the-RTL8723CS.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0144-arm64-allwinner-a64-enable-Bluetooth-On-Pinebook.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0145-arm64-allwinner-a64-enable-Bluetooth-On-Pine64.patch.disabled create mode 100644 patch/kernel/sunxi-dev/0146-arm64-allwinner-a64-enable-Bluetooth-On-SoPine-baseb.patch.disabled delete mode 100644 patch/kernel/sunxi-dev/board-a10-lime-a10-add-240-mhz-cpufreq.patch rename patch/kernel/sunxi-dev/{board-h3-address-some-stability-issues.patch => board-h3-address-some-stability-issues.patch.disabled} (100%) delete mode 100644 patch/kernel/sunxi-dev/camera-add-support-for-allwinner-CSI-with-tiny-fix.patch delete mode 100644 patch/kernel/sunxi-dev/dvfs-regulator-opi-pc.patch delete mode 100644 patch/kernel/sunxi-dev/dvfs-regulator-update-sy8106a.patch delete mode 100644 patch/kernel/sunxi-dev/general-a64-enable-fsl-timer-errata.patch delete mode 100644 patch/kernel/sunxi-dev/general-add-HDMI-sound-nodes-DT.patch rename patch/kernel/sunxi-dev/{general-add-proc-cpuinfo-entries.patch => general-arm64-add-proc-cpuinfo-entries.patch} (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/a64-DT-DVFS.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/a64-DVFS-cpu-supply.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/a64-pll_cpux-test.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add-mtd-spi-nor-dts.patch.disabled (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add-overlay-compilation-support.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add-spi-flash-pc2.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add-sun50i-ths.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add-sunxi64-overlays.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add-sy8106a-driver.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add_BergMicro_flashes_to_SPI-NOR.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add_configfs_overlay_for_v4.10.x.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add_nanopim1plus2_dts.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add_proc_cpuinfo_entries_for_v4.10.x.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/add_sun50i_a64_spi.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/badd-nanopineoplus2.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/bash_to_afterinstall.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/disable-reg_dc1sw-pine64.patch.disabled (100%) rename patch/kernel/sunxi-dev/{ => need-to-check}/dvfs-regulator-opi-2.patch (100%) rename patch/kernel/sunxi-dev/{ => need-to-check}/dvfs-regulator-opi-pc2.patch (100%) rename patch/kernel/sunxi-dev/{ => need-to-check}/dvfs-regulator-prime.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/enable-fsl-timer-errata.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/fix-i2c2-reg-property.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/fix-pinebook-backlight.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/fix-zeroplus2-mmc0-cd-polarity.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/scripts-dtc-import-updates.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/set-default-target-to-Image.patch (100%) rename patch/kernel/{sunxi64-dev => sunxi-dev/need-to-check}/spidev-remove-warnings.patch (100%) create mode 100644 patch/kernel/sunxi-dev/patch-4.19.1-2.patch delete mode 100644 patch/kernel/sunxi-dev/ths-21-sun4i-gpadc-iio-add-split-sun8i.patch delete mode 100644 patch/kernel/sunxi-dev/ths-22-sun4i-gpadc-iio-add-H3-support.patch delete mode 100644 patch/kernel/sunxi-dev/ths-23-sun4i-gpadc-iio-add-H3-thermal-sensor-DT.patch delete mode 100644 patch/kernel/sunxi-dev/ths-24-sun4i-gpadc-iio-add-H3-CPU-thermal-zone.patch delete mode 100644 patch/kernel/sunxi-dev/ths-25-sun4i-gpadc-iio-workaround-for-raw-0-read.patch delete mode 100644 patch/kernel/sunxi-dev/ths-26-sun4i-gpadc-iio-add-h5-a64-support.patch delete mode 100644 patch/kernel/sunxi-dev/ths-27-sun4i-gpadc-iio-add-h5-DT.patch rename patch/kernel/sunxi-dev/{ths-49-add-h5-cpu-opp-table.patch => ths-49-add-h5-cpu-opp-table.patch.disabled} (100%) rename patch/kernel/sunxi-dev/{ths-50-add-h5-opp-table-to-cpu.patch => ths-50-add-h5-opp-table-to-cpu.patch.disabled} (100%) rename patch/kernel/sunxi-dev/{wireless_need_adjustement_for_4.19_TBD => }/wifi-3001-add-realtek-8189es-kconfig-makefile.patch (100%) rename patch/kernel/sunxi-dev/{wireless_need_adjustement_for_4.19_TBD => }/wifi-3002-add-realtek-8189es.patch (98%) rename patch/kernel/sunxi-dev/{wireless_need_adjustement_for_4.19_TBD => }/wifi-4001-add-realtek-8723cs-kconfig-makefile.patch (100%) rename patch/kernel/sunxi-dev/{wireless_need_adjustement_for_4.19_TBD => }/wifi-4002-add-realtek-8723cs.patch (99%) delete mode 100644 patch/kernel/sunxi64-dev/arm64_increasing_DMA_block_memory_allocation_to_2048.patch delete mode 100644 patch/kernel/sunxi64-dev/packaging-4.x-DEV-with-postinstall-scripts.patch diff --git a/config/boards/orangepipc2.conf b/config/boards/orangepipc2.conf index faa517e3d..d6216fb2b 100644 --- a/config/boards/orangepipc2.conf +++ b/config/boards/orangepipc2.conf @@ -4,8 +4,8 @@ BOARDFAMILY="sun50iw2" BOOTCONFIG="orangepi_pc2_defconfig" MODULES="" MODULES_NEXT="" -CPUMIN="408000" -CPUMAX="1296000" +CPUMIN="120000" +CPUMAX="1400000" # KERNEL_TARGET="next,dev" CLI_TARGET="stretch,bionic:next" diff --git a/config/boards/orangepiprime.conf b/config/boards/orangepiprime.conf index 9946c539f..317621e9f 100644 --- a/config/boards/orangepiprime.conf +++ b/config/boards/orangepiprime.conf @@ -4,8 +4,8 @@ BOARDFAMILY="sun50iw2" BOOTCONFIG="orangepi_prime_defconfig" MODULES="" MODULES_NEXT="" -CPUMIN="408000" -CPUMAX="1296000" +CPUMIN="120000" +CPUMAX="1400000" # KERNEL_TARGET="next,dev" CLI_TARGET="stretch:next" diff --git a/config/kernel/linux-sunxi-dev.config b/config/kernel/linux-sunxi-dev.config index 5162bb0ed..f2ba6028a 100644 --- a/config/kernel/linux-sunxi-dev.config +++ b/config/kernel/linux-sunxi-dev.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.19.1 Kernel Configuration +# Linux/arm 4.19.2 Kernel Configuration # # @@ -569,7 +569,6 @@ CONFIG_CRYPTO_GHASH_ARM_CE=m # CONFIG_CRYPTO_CRCT10DIF_ARM_CE is not set # CONFIG_CRYPTO_CRC32_ARM_CE is not set # CONFIG_CRYPTO_CHACHA20_NEON is not set -# CONFIG_CRYPTO_SPECK_NEON is not set CONFIG_VIRTUALIZATION=y # CONFIG_VHOST_NET is not set # CONFIG_VHOST_SCSI is not set @@ -771,6 +770,8 @@ CONFIG_NET_KEY=y # CONFIG_NET_KEY_MIGRATE is not set # CONFIG_XDP_SOCKETS is not set CONFIG_INET=y +CONFIG_WIREGUARD=m +# CONFIG_WIREGUARD_DEBUG is not set CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_FIB_TRIE_STATS=y @@ -3098,6 +3099,7 @@ CONFIG_CLOCK_THERMAL=y # ACPI INT340X thermal drivers # CONFIG_SUN50I_H6_THS=m +CONFIG_SUN8I_THS=m CONFIG_GENERIC_ADC_THERMAL=m CONFIG_WATCHDOG=y CONFIG_WATCHDOG_CORE=y @@ -3723,6 +3725,7 @@ CONFIG_VIDEO_RJ54N1=m # CONFIG_VIDEO_SMIAPP is not set CONFIG_VIDEO_ET8EK8=m # CONFIG_VIDEO_S5C73M3 is not set +CONFIG_VIDEO_HM5065=m # # Flash devices @@ -3993,8 +3996,10 @@ CONFIG_DRM_FBDEV_EMULATION=y CONFIG_DRM_FBDEV_OVERALLOC=100 CONFIG_DRM_LOAD_EDID_FIRMWARE=y # CONFIG_DRM_DP_CEC is not set +CONFIG_DRM_TTM=m CONFIG_DRM_GEM_CMA_HELPER=y CONFIG_DRM_KMS_CMA_HELPER=y +CONFIG_DRM_SCHED=m # # I2C encoder or helper chips @@ -4063,7 +4068,6 @@ CONFIG_DRM_PANEL_BRIDGE=y # # Display Interface Bridges # -# CONFIG_DRM_ANALOGIX_ANX78XX is not set # CONFIG_DRM_CDNS_DSI is not set # CONFIG_DRM_DUMB_VGA_DAC is not set # CONFIG_DRM_LVDS_ENCODER is not set @@ -4076,6 +4080,9 @@ CONFIG_DRM_PANEL_BRIDGE=y # CONFIG_DRM_THINE_THC63LVD1024 is not set # CONFIG_DRM_TOSHIBA_TC358767 is not set # CONFIG_DRM_TI_TFP410 is not set +CONFIG_DRM_ANALOGIX_DP_I2C=m +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +CONFIG_DRM_ANALOGIX_ANX6345=m # CONFIG_DRM_I2C_ADV7511 is not set CONFIG_DRM_DW_HDMI=y # CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set @@ -4094,6 +4101,7 @@ CONFIG_TINYDRM_MI0283QT=m # CONFIG_TINYDRM_ST7735R is not set # CONFIG_DRM_PL111 is not set # CONFIG_DRM_TVE200 is not set +CONFIG_DRM_LIMA=m # CONFIG_DRM_LEGACY is not set CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y @@ -4254,9 +4262,11 @@ CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y # CONFIG_SND_SUN4I_CODEC=m CONFIG_SND_SUN8I_CODEC=m +CONFIG_SND_AC100_CODEC=m CONFIG_SND_SUN8I_CODEC_ANALOG=m CONFIG_SND_SUN4I_I2S=m CONFIG_SND_SUN4I_SPDIF=m +CONFIG_SND_SUN8I_ADDA_PR_REGMAP=m # CONFIG_SND_SOC_XTFPGA_I2S is not set # CONFIG_ZX_TDM is not set CONFIG_SND_SOC_I2C_AND_SPI=m @@ -4879,6 +4889,7 @@ CONFIG_LEDS_REGULATOR=m CONFIG_LEDS_SYSCON=y CONFIG_LEDS_MLXREG=m CONFIG_LEDS_USER=y +CONFIG_LEDS_AXP20X=m # # LED Triggers @@ -5735,7 +5746,7 @@ CONFIG_RESET_SUNXI=y CONFIG_GENERIC_PHY=y CONFIG_PHY_SUN4I_USB=y CONFIG_PHY_SUN9I_USB=y -CONFIG_PHY_SUN50I_USB3=y +CONFIG_PHY_SUN50I_USB3=m # CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_PHY_PXA_28NM_HSIC is not set # CONFIG_PHY_PXA_28NM_USB2 is not set @@ -5764,7 +5775,7 @@ CONFIG_ARM_PMU=y # CONFIG_ANDROID is not set CONFIG_DAX=m CONFIG_NVMEM=y -CONFIG_NVMEM_SUNXI_SID=m +CONFIG_NVMEM_SUNXI_SID=y # # HW tracing support @@ -6232,7 +6243,6 @@ CONFIG_CRYPTO_CHACHA20=m CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SM4=m -CONFIG_CRYPTO_SPECK=m CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_TWOFISH_COMMON=m diff --git a/config/kernel/linux-sunxi64-dev.config b/config/kernel/linux-sunxi64-dev.config index a2a6bf670..c601ea8d0 100644 --- a/config/kernel/linux-sunxi64-dev.config +++ b/config/kernel/linux-sunxi64-dev.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.19.1 Kernel Configuration +# Linux/arm64 4.19.2 Kernel Configuration # # @@ -481,7 +481,6 @@ CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y CONFIG_CRYPTO_CHACHA20_NEON=y CONFIG_CRYPTO_AES_ARM64_BS=y -# CONFIG_CRYPTO_SPECK_NEON is not set # # General architecture-dependent options @@ -751,6 +750,8 @@ CONFIG_XFRM_IPCOMP=m CONFIG_NET_KEY=m # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y +CONFIG_WIREGUARD=m +# CONFIG_WIREGUARD_DEBUG is not set CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_FIB_TRIE_STATS=y @@ -2065,6 +2066,7 @@ CONFIG_USB_VL600=m CONFIG_USB_NET_CH9200=m CONFIG_WLAN=y CONFIG_WLAN_VENDOR_ADMTEK=y +CONFIG_RTL8189ES=m CONFIG_ATH_COMMON=m CONFIG_WLAN_VENDOR_ATH=y # CONFIG_ATH_DEBUG is not set @@ -2161,10 +2163,12 @@ CONFIG_RT2X00_LIB_LEDS=y CONFIG_WLAN_VENDOR_REALTEK=y CONFIG_RTL8187=m CONFIG_RTL8187_LEDS=y +CONFIG_RTL8189FS=m CONFIG_RTL_CARDS=m # CONFIG_RTL8192CU is not set CONFIG_RTL8XXXU=m CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_RTL8723CS=m # CONFIG_WLAN_VENDOR_RSI is not set # CONFIG_WLAN_VENDOR_ST is not set # CONFIG_WLAN_VENDOR_TI is not set @@ -2918,6 +2922,7 @@ CONFIG_THERMAL_EMULATION=y # ACPI INT340X thermal drivers # CONFIG_SUN50I_H6_THS=m +CONFIG_SUN8I_THS=m # CONFIG_QCOM_SPMI_TEMP_ALARM is not set CONFIG_GENERIC_ADC_THERMAL=m CONFIG_WATCHDOG=y @@ -2969,7 +2974,7 @@ CONFIG_BCMA_BLOCKIO=y # CONFIG_MFD_CORE=y # CONFIG_MFD_ACT8945A is not set -CONFIG_MFD_SUN4I_GPADC=m +CONFIG_MFD_SUN4I_GPADC=y # CONFIG_MFD_AS3711 is not set # CONFIG_MFD_AS3722 is not set # CONFIG_PMIC_ADP5520 is not set @@ -3641,8 +3646,10 @@ CONFIG_DRM_FBDEV_EMULATION=y CONFIG_DRM_FBDEV_OVERALLOC=100 CONFIG_DRM_LOAD_EDID_FIRMWARE=y # CONFIG_DRM_DP_CEC is not set +CONFIG_DRM_TTM=m CONFIG_DRM_GEM_CMA_HELPER=y CONFIG_DRM_KMS_CMA_HELPER=y +CONFIG_DRM_SCHED=m # # I2C encoder or helper chips @@ -3706,7 +3713,6 @@ CONFIG_DRM_PANEL_BRIDGE=y # # Display Interface Bridges # -CONFIG_DRM_ANALOGIX_ANX78XX=m CONFIG_DRM_CDNS_DSI=m # CONFIG_DRM_DUMB_VGA_DAC is not set # CONFIG_DRM_LVDS_ENCODER is not set @@ -3719,6 +3725,9 @@ CONFIG_DRM_SII9234=m CONFIG_DRM_THINE_THC63LVD1024=m # CONFIG_DRM_TOSHIBA_TC358767 is not set # CONFIG_DRM_TI_TFP410 is not set +CONFIG_DRM_ANALOGIX_DP_I2C=m +CONFIG_DRM_ANALOGIX_ANX78XX=m +CONFIG_DRM_ANALOGIX_ANX6345=m # CONFIG_DRM_I2C_ADV7511 is not set CONFIG_DRM_DW_HDMI=y CONFIG_DRM_DW_HDMI_AHB_AUDIO=m @@ -3729,6 +3738,7 @@ CONFIG_DRM_DW_HDMI_CEC=m # CONFIG_DRM_MXSFB is not set # CONFIG_DRM_TINYDRM is not set # CONFIG_DRM_PL111 is not set +CONFIG_DRM_LIMA=m # CONFIG_DRM_LEGACY is not set CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y @@ -3892,9 +3902,12 @@ CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y # Allwinner SoC Audio support # CONFIG_SND_SUN4I_CODEC=m +CONFIG_SND_SUN8I_CODEC=m CONFIG_SND_SUN8I_CODEC_ANALOG=m +CONFIG_SND_SUN50I_CODEC_ANALOG=m CONFIG_SND_SUN4I_I2S=m CONFIG_SND_SUN4I_SPDIF=m +CONFIG_SND_SUN8I_ADDA_PR_REGMAP=m # CONFIG_SND_SOC_XTFPGA_I2S is not set # CONFIG_ZX_TDM is not set CONFIG_SND_SOC_I2C_AND_SPI=m @@ -4477,6 +4490,7 @@ CONFIG_LEDS_REGULATOR=m CONFIG_LEDS_SYSCON=y CONFIG_LEDS_MLXREG=m CONFIG_LEDS_USER=y +CONFIG_LEDS_AXP20X=m # # LED Triggers @@ -4845,6 +4859,7 @@ CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y CONFIG_FSL_ERRATUM_A008585=y # CONFIG_HISILICON_ERRATUM_161010101 is not set # CONFIG_ARM64_ERRATUM_858921 is not set +CONFIG_SUN50I_A64_UNSTABLE_TIMER=y # CONFIG_ARM_TIMER_SP804 is not set CONFIG_MAILBOX=y CONFIG_ARM_MHU=y @@ -5846,7 +5861,6 @@ CONFIG_CRYPTO_CHACHA20=y # CONFIG_CRYPTO_SEED is not set CONFIG_CRYPTO_SERPENT=y CONFIG_CRYPTO_SM4=m -# CONFIG_CRYPTO_SPECK is not set # CONFIG_CRYPTO_TEA is not set CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_TWOFISH_COMMON=y diff --git a/config/sources/sun50iw6.conf b/config/sources/sun50iw6.conf index 983e3f600..5b55d19f0 100644 --- a/config/sources/sun50iw6.conf +++ b/config/sources/sun50iw6.conf @@ -5,7 +5,7 @@ OVERLAY_PREFIX='sun50i-h6' BOOTENV_FILE='sun50iw2-next.txt' [[ -z $CPUMIN ]] && CPUMIN=480000 -[[ -z $CPUMAX ]] && CPUMAX=1510000 +[[ -z $CPUMAX ]] && CPUMAX=1810000 GOVERNOR=ondemand ASOUND_STATE='asound.state.sun50iw2-dev' @@ -26,17 +26,19 @@ BOOTSCRIPT='boot-sun50i-next.cmd:boot.cmd' case $BRANCH in dev) - KERNELSOURCE='https://github.com/Icenowy/linux' - KERNELBRANCH='branch:h6-integrate-2-ugly' - KERNELDIR=$MAINLINE_KERNEL_DIR - KERNEL_USE_GCC='> 7.0' - KERNELPATCHDIR='sunxi-dev-h6' + KERNELSOURCE='https://github.com/Icenowy/linux' + KERNELBRANCH='branch:h6-integrate-2-ugly' + KERNELDIR=$MAINLINE_KERNEL_DIR + KERNEL_USE_GCC='> 7.0' + KERNELPATCHDIR='sunxi-dev-h6' + + #KERNELSOURCE=$MAINLINE_KERNEL_SOURCE + KERNELSOURCE="https://github.com/megous/linux" + #KERNELBRANCH='branch:linux-4.19.y' + KERNELBRANCH="branch:orange-pi-4.19" + KERNELPATCHDIR='sunxi-dev' + KERNELDIR=$MAINLINE_KERNEL_DIR - KERNELSOURCE=$MAINLINE_KERNEL_SOURCE - KERNELBRANCH='branch:linux-4.19.y' - KERNELDIR=$MAINLINE_KERNEL_DIR - KERNEL_USE_GCC='> 7.0' - KERNELPATCHDIR='sunxi-dev' ;; esac diff --git a/config/sources/sunxi64_common.inc b/config/sources/sunxi64_common.inc index 26be27514..7f63bb672 100644 --- a/config/sources/sunxi64_common.inc +++ b/config/sources/sunxi64_common.inc @@ -45,12 +45,13 @@ case $BRANCH in ATF_USE_GCC='> 6.3' ATF_TARGET_MAP='PLAT=sun50iw1p1 DEBUG=1 bl31;;build/sun50iw1p1/debug/bl31.bin' - KERNELSOURCE=$MAINLINE_KERNEL_SOURCE - KERNELBRANCH='branch:linux-4.19.y' + #KERNELSOURCE=$MAINLINE_KERNEL_SOURCE + KERNELSOURCE="https://github.com/megous/linux" + #KERNELBRANCH='branch:linux-4.19.y' + KERNELBRANCH="branch:orange-pi-4.19" KERNELDIR=$MAINLINE_KERNEL_DIR - KERNEL_USE_GCC='> 7.0' KERNELPATCHDIR='sunxi-dev' - + KERNEL_USE_GCC='> 7.0' ;; esac diff --git a/config/sources/sunxi_common.inc b/config/sources/sunxi_common.inc index 547a09cd5..38a2398de 100644 --- a/config/sources/sunxi_common.inc +++ b/config/sources/sunxi_common.inc @@ -36,10 +36,12 @@ case $BRANCH in dev) - KERNELSOURCE=$MAINLINE_KERNEL_SOURCE - KERNELBRANCH='branch:linux-4.19.y' + #KERNELSOURCE=$MAINLINE_KERNEL_SOURCE + KERNELSOURCE="https://github.com/megous/linux" + #KERNELBRANCH='branch:linux-4.19.y' + KERNELBRANCH="branch:orange-pi-4.19" KERNELDIR=$MAINLINE_KERNEL_DIR - + KERNELPATCHDIR='sunxi-dev' KERNEL_USE_GCC='> 7.0' ;; diff --git a/lib/debootstrap-ng.sh b/lib/debootstrap-ng.sh index 88fbd6e37..df07414ab 100644 --- a/lib/debootstrap-ng.sh +++ b/lib/debootstrap-ng.sh @@ -480,6 +480,15 @@ prepare_partitions() [[ -f $SDCARD/boot/armbianEnv.txt ]] && rm $SDCARD/boot/armbianEnv.txt fi + # if we have a headless device, set console to serial + if [[ $BUILD_DESKTOP == "no" ]]; then + if grep -lq "^console=" $SDCARD/boot/armbianEnv.txt; then + sed -i "s/console=.*/console=serial/" $SDCARD/boot/armbianEnv.txt + else + echo "console=serial" >> $SDCARD/boot/armbianEnv.txt + fi + fi + # recompile .cmd to .scr if boot.cmd exists [[ -f $SDCARD/boot/boot.cmd ]] && \ mkimage -C none -A arm -T script -d $SDCARD/boot/boot.cmd $SDCARD/boot/boot.scr > /dev/null 2>&1 diff --git a/patch/kernel/sunxi-dev-h6/add-1.8ghz.patch b/patch/kernel/sunxi-dev-h6/add-1.8ghz.patch deleted file mode 100644 index ff687e763..000000000 --- a/patch/kernel/sunxi-dev-h6/add-1.8ghz.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index d7c803c3..9ab2d1e2 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -59,6 +59,12 @@ - opp-microvolt = <1060000>; - clock-latency-ns = <244144>; /* 8 32k periods */ - }; -+ -+ opp-1800000000 { -+ opp-hz = /bits/ 64 <1800000000>; -+ opp-microvolt = <1160000>; -+ clock-latency-ns = <244144>; /* 8 32k periods */ -+ }; - }; - - cpus { diff --git a/patch/kernel/sunxi-dev-h6/add-overlay-compilation-support.patch b/patch/kernel/sunxi-dev-h6/add-overlay-compilation-support.patch deleted file mode 100644 index df39dc883..000000000 --- a/patch/kernel/sunxi-dev-h6/add-overlay-compilation-support.patch +++ /dev/null @@ -1,125 +0,0 @@ -diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 65f4e2a4..9eb2043c 100644 ---- a/arch/arm/Makefile -+++ b/arch/arm/Makefile -@@ -339,6 +339,12 @@ $(INSTALL_TARGETS): - %.dtb: | scripts - $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ - -+%.dtbo: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ -+ -+%.scr: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts ARCH=$(ARCH) $(boot)/dts/$@ -+ - PHONY += dtbs dtbs_install - - dtbs: prepare scripts -diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore -index 3c79f859..4e5c1d59 100644 ---- a/arch/arm/boot/.gitignore -+++ b/arch/arm/boot/.gitignore -@@ -3,3 +3,5 @@ zImage - xipImage - bootpImage - uImage -+*.dtb* -+*.scr -diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile -index f839ecd9..9788f16d 100644 ---- a/arch/arm64/Makefile -+++ b/arch/arm64/Makefile -@@ -121,6 +121,12 @@ zinstall install: - %.dtb: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@ - -+%.dtbo: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ -+ -+%.scr: | scripts -+ $(Q)$(MAKE) $(build)=$(boot)/dts ARCH=$(ARCH) $(boot)/dts/$@ -+ - PHONY += dtbs dtbs_install - - dtbs: prepare scripts -diff --git a/arch/arm64/boot/dts/.gitignore b/arch/arm64/boot/dts/.gitignore -index b60ed208..4bec63b6 100644 ---- a/arch/arm64/boot/dts/.gitignore -+++ b/arch/arm64/boot/dts/.gitignore -@@ -0,0 +1,2 @@ -+*.dtb* -+*.scr -diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst -index 34614a48..8a8313d6 100644 ---- a/scripts/Makefile.dtbinst -+++ b/scripts/Makefile.dtbinst -@@ -20,6 +20,9 @@ include scripts/Kbuild.include - include $(src)/Makefile - - dtbinst-files := $(sort $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS), $(dtb-))) -+dtboinst-files := $(dtbo-y) -+script-files := $(scr-y) -+readme-files := $(dtbotxt-y) - dtbinst-dirs := $(subdir-y) $(subdir-m) - - # Helper targets for Installing DTBs into the boot directory -@@ -31,10 +34,19 @@ install-dir = $(patsubst $(dtbinst_root)%,$(INSTALL_DTBS_PATH)%,$(obj)) - $(dtbinst-files): %.dtb: $(obj)/%.dtb - $(call cmd,dtb_install,$(install-dir)) - -+$(dtboinst-files): %.dtbo: $(obj)/%.dtbo -+ $(call cmd,dtb_install,$(install-dir)) -+ -+$(script-files): %.scr: $(obj)/%.scr -+ $(call cmd,dtb_install,$(install-dir)) -+ -+$(readme-files): %: $(src)/% -+ $(call cmd,dtb_install,$(install-dir)) -+ - $(dtbinst-dirs): - $(Q)$(MAKE) $(dtbinst)=$(obj)/$@ - --PHONY += $(dtbinst-files) $(dtbinst-dirs) --__dtbs_install: $(dtbinst-files) $(dtbinst-dirs) -+PHONY += $(dtbinst-files) $(dtboinst-files) $(script-files) $(readme-files) $(dtbinst-dirs) -+__dtbs_install: $(dtbinst-files) $(dtboinst-files) $(script-files) $(readme-files) $(dtbinst-dirs) - - .PHONY: $(PHONY) -diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index 58c05e5d..2b95dda9 100644 ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -278,6 +278,9 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ - # --------------------------------------------------------------------------- - DTC ?= $(objtree)/scripts/dtc/dtc - -+# Overlay support -+DTC_FLAGS += -@ -Wno-unit_address_format -Wno-simple_bus_reg -+ - # Disable noisy checks by default - ifeq ($(KBUILD_ENABLE_EXTRA_GCC_CHECKS),) - DTC_FLAGS += -Wno-unit_address_vs_reg \ -@@ -324,6 +327,23 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ - $(obj)/%.dtb: $(src)/%.dts FORCE - $(call if_changed_dep,dtc) - -+quiet_cmd_dtco = DTCO $@ -+cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \ -+ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ -+ $(DTC) -O dtb -o $@ -b 0 \ -+ -i $(dir $<) $(DTC_FLAGS) \ -+ -d $(depfile).dtc.tmp $(dtc-tmp) ; \ -+ cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) -+ -+$(obj)/%.dtbo: $(src)/%.dts FORCE -+ $(call if_changed_dep,dtco) -+ -+quiet_cmd_scr = MKIMAGE $@ -+cmd_scr = mkimage -C none -A $(ARCH) -T script -d $< $@ -+ -+$(obj)/%.scr: $(src)/%.scr-cmd FORCE -+ $(call if_changed,scr) -+ - dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) - - # Bzip2 diff --git a/patch/kernel/sunxi-dev-h6/add_configfs_overlay_for_v4.18.x.patch b/patch/kernel/sunxi-dev-h6/add_configfs_overlay_for_v4.18.x.patch deleted file mode 100644 index 5868c2741..000000000 --- a/patch/kernel/sunxi-dev-h6/add_configfs_overlay_for_v4.18.x.patch +++ /dev/null @@ -1,326 +0,0 @@ -diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig -index bc07ad3..e9da9cf 100644 ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -113,6 +113,13 @@ config OF_OVERLAY - While this option is selected automatically when needed, you can - enable it manually to improve device tree unit test coverage. - -+config OF_CONFIGFS -+ bool "Device Tree Overlay ConfigFS interface" -+ select CONFIGFS_FS -+ depends on OF_OVERLAY -+ help -+ Enable a simple user-space driven DT overlay interface. -+ - config OF_NUMA - bool - -diff --git a/drivers/of/Makefile b/drivers/of/Makefile -index d7efd9d..a06cc35 100644 ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -13,6 +13,7 @@ obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o - obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o - obj-$(CONFIG_OF_RESOLVE) += resolver.o - obj-$(CONFIG_OF_OVERLAY) += overlay.o -+obj-$(CONFIG_OF_CONFIGFS) += configfs.o - obj-$(CONFIG_OF_NUMA) += of_numa.o - - obj-$(CONFIG_OF_UNITTEST) += unittest-data/ -diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c -new file mode 100644 -index 0000000..68f889d ---- /dev/null -+++ b/drivers/of/configfs.c -@@ -0,0 +1,277 @@ -+/* -+ * Configfs entries for device-tree -+ * -+ * Copyright (C) 2013 - Pantelis Antoniou -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "of_private.h" -+ -+struct cfs_overlay_item { -+ struct config_item item; -+ -+ char path[PATH_MAX]; -+ -+ const struct firmware *fw; -+ struct device_node *overlay; -+ int ov_id; -+ -+ void *dtbo; -+ int dtbo_size; -+}; -+ -+static inline struct cfs_overlay_item *to_cfs_overlay_item( -+ struct config_item *item) -+{ -+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; -+} -+ -+static ssize_t cfs_overlay_item_path_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ return sprintf(page, "%s\n", overlay->path); -+} -+ -+static ssize_t cfs_overlay_item_path_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ const char *p = page; -+ char *s; -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy to path buffer (and make sure it's always zero terminated */ -+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); -+ overlay->path[sizeof(overlay->path) - 1] = '\0'; -+ -+ /* strip trailing newlines */ -+ s = overlay->path + strlen(overlay->path); -+ while (s > overlay->path && *--s == '\n') -+ *s = '\0'; -+ -+ pr_debug("%s: path is '%s'\n", __func__, overlay->path); -+ -+ err = request_firmware(&overlay->fw, overlay->path, NULL); -+ if (err != 0) -+ goto out_err; -+ -+ err = of_overlay_fdt_apply((void *)overlay->fw->data, -+ (u32)overlay->fw->size, &overlay->ov_id); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ -+ release_firmware(overlay->fw); -+ overlay->fw = NULL; -+ -+ overlay->path[0] = '\0'; -+ return err; -+} -+ -+static ssize_t cfs_overlay_item_status_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ return sprintf(page, "%s\n", -+ overlay->ov_id > 0 ? "applied" : "unapplied"); -+} -+ -+CONFIGFS_ATTR(cfs_overlay_item_, path); -+CONFIGFS_ATTR_RO(cfs_overlay_item_, status); -+ -+static struct configfs_attribute *cfs_overlay_attrs[] = { -+ &cfs_overlay_item_attr_path, -+ &cfs_overlay_item_attr_status, -+ NULL, -+}; -+ -+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, -+ void *buf, size_t max_count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ pr_debug("%s: buf=%p max_count=%zu\n", __func__, -+ buf, max_count); -+ -+ if (overlay->dtbo == NULL) -+ return 0; -+ -+ /* copy if buffer provided */ -+ if (buf != NULL) { -+ /* the buffer must be large enough */ -+ if (overlay->dtbo_size > max_count) -+ return -ENOSPC; -+ -+ memcpy(buf, overlay->dtbo, overlay->dtbo_size); -+ } -+ -+ return overlay->dtbo_size; -+} -+ -+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, -+ const void *buf, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy the contents */ -+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); -+ if (overlay->dtbo == NULL) -+ return -ENOMEM; -+ -+ overlay->dtbo_size = count; -+ -+ err = of_overlay_fdt_apply(overlay->dtbo, overlay->dtbo_size, -+ &overlay->ov_id); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ overlay->ov_id = 0; -+ -+ return err; -+} -+ -+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); -+ -+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { -+ &cfs_overlay_item_attr_dtbo, -+ NULL, -+}; -+ -+static void cfs_overlay_release(struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ if (overlay->ov_id > 0) -+ of_overlay_remove(&overlay->ov_id); -+ if (overlay->fw) -+ release_firmware(overlay->fw); -+ /* kfree with NULL is safe */ -+ kfree(overlay->dtbo); -+ kfree(overlay); -+} -+ -+static struct configfs_item_operations cfs_overlay_item_ops = { -+ .release = cfs_overlay_release, -+}; -+ -+static struct config_item_type cfs_overlay_type = { -+ .ct_item_ops = &cfs_overlay_item_ops, -+ .ct_attrs = cfs_overlay_attrs, -+ .ct_bin_attrs = cfs_overlay_bin_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *cfs_overlay_group_make_item( -+ struct config_group *group, const char *name) -+{ -+ struct cfs_overlay_item *overlay; -+ -+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); -+ if (!overlay) -+ return ERR_PTR(-ENOMEM); -+ -+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); -+ return &overlay->item; -+} -+ -+static void cfs_overlay_group_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ config_item_put(&overlay->item); -+} -+ -+static struct configfs_group_operations overlays_ops = { -+ .make_item = cfs_overlay_group_make_item, -+ .drop_item = cfs_overlay_group_drop_item, -+}; -+ -+static struct config_item_type overlays_type = { -+ .ct_group_ops = &overlays_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_group_operations of_cfs_ops = { -+ /* empty - we don't allow anything to be created */ -+}; -+ -+static struct config_item_type of_cfs_type = { -+ .ct_group_ops = &of_cfs_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group of_cfs_overlay_group; -+ -+static struct configfs_subsystem of_cfs_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "device-tree", -+ .ci_type = &of_cfs_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), -+}; -+ -+static int __init of_cfs_init(void) -+{ -+ int ret; -+ -+ pr_info("%s\n", __func__); -+ -+ config_group_init(&of_cfs_subsys.su_group); -+ config_group_init_type_name(&of_cfs_overlay_group, "overlays", -+ &overlays_type); -+ configfs_add_default_group(&of_cfs_overlay_group, -+ &of_cfs_subsys.su_group); -+ -+ ret = configfs_register_subsystem(&of_cfs_subsys); -+ if (ret != 0) { -+ pr_err("%s: failed to register subsys\n", __func__); -+ goto out; -+ } -+ pr_info("%s: OK\n", __func__); -+out: -+ return ret; -+} -+late_initcall(of_cfs_init); -diff --git a/drivers/of/fdt_address.c b/drivers/of/fdt_address.c -index dca8f9b..ec7e167 100644 ---- a/drivers/of/fdt_address.c -+++ b/drivers/of/fdt_address.c -@@ -161,7 +161,7 @@ static int __init fdt_translate_one(const void *blob, int parent, - * that can be mapped to a cpu physical address). This is not really specified - * that way, but this is traditionally the way IBM at least do things - */ --static u64 __init fdt_translate_address(const void *blob, int node_offset) -+u64 __init fdt_translate_address(const void *blob, int node_offset) - { - int parent, len; - const struct of_bus *bus, *pbus; diff --git a/patch/kernel/sunxi-dev-h6/board-0001-orangepi-one-plus-add-device.patch b/patch/kernel/sunxi-dev-h6/board-0001-orangepi-one-plus-add-device.patch deleted file mode 100644 index a4d51d7b4..000000000 --- a/patch/kernel/sunxi-dev-h6/board-0001-orangepi-one-plus-add-device.patch +++ /dev/null @@ -1,275 +0,0 @@ -diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile -index 3040c3074..712e1cf5f ---- a/arch/arm64/boot/dts/allwinner/Makefile -+++ b/arch/arm64/boot/dts/allwinner/Makefile -@@ -1,5 +1,6 @@ - # SPDX-License-Identifier: GPL-2.0 - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb -+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts -new file mode 100644 -index 000000000..385015396 ---- /dev/null -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-one-plus.dts -@@ -0,0 +1,258 @@ -+// SPDX-License-Identifier: (GPL-2.0+ or MIT) -+/* -+ * Copyright (c) 2018 Armbian -+ */ -+ -+/dts-v1/; -+ -+#include "sun50i-h6.dtsi" -+ -+#include -+ -+/ { -+ model = "Orange Pi One+"; -+ compatible = "xunlong,orangepi-one-plus", "allwinner,sun50i-h6"; -+ -+ aliases { -+ serial0 = &uart0; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ pwr { -+ label = "orangepi:red:pwr"; -+ gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ status { -+ label = "orangepi:green:status"; -+ gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ -+ reg_gmac_3v3: gmac-3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc-gmac-3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ startup-delay-us = <100000>; -+ enable-active-high; -+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ -+ vin-supply = <®_aldo2>; -+ }; -+ -+ reg_vcc3v3: vcc3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ reg_vcc1v8: vcc1v8 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ -+ reg_usb_vbus: vbus { -+ compatible = "regulator-fixed"; -+ regulator-name = "usb-vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ startup-delay-us = <100000>; -+ gpio = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+}; -+ -+&cpu0 { -+ cpu-supply = <®_dcdca>; -+}; -+ -+&usb2phy { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ehci3 { -+ status = "okay"; -+}; -+ -+ -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ext_rgmii_pins>; -+ phy-mode = "rgmii"; -+ phy-handle = <&ext_rgmii_phy>; -+ phy-supply = <®_gmac_3v3>; -+ allwinner,rx-delay-ps = <200>; -+ allwinner,tx-delay-ps = <200>; -+ status = "disabled"; -+}; -+ -+&dwc3 { -+ status = "okay"; -+}; -+ -+&mdio { -+ ext_rgmii_phy: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ }; -+}; -+ -+&mmc0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins>; -+ vmmc-supply = <®_vcc3v3>; -+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&ohci3 { -+ status = "okay"; -+}; -+ -+&r_i2c { -+ status = "okay"; -+ -+ axp805: pmic@36 { -+ compatible = "x-powers,axp805", "x-powers,axp806"; -+ reg = <0x36>; -+ interrupt-parent = <&r_intc>; -+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ x-powers,master-mode; -+ -+ regulators { -+ reg_aldo1: aldo1 { -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-pl"; -+ }; -+ -+ reg_aldo2: aldo2 { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-ac200"; -+ }; -+ -+ reg_aldo3: aldo3 { -+ /* This regulator is connected with CLDO1 */ -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-3v3-1"; -+ }; -+ -+ reg_bldo1: bldo1 { -+ regulator-always-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc-ddr-bias-pll"; -+ }; -+ -+ reg_bldo2: bldo2 { -+ regulator-always-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc-efuse-emmc-pcie-hdmi"; -+ }; -+ -+ reg_bldo3: bldo3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc-wifi-io"; -+ }; -+ -+ bldo4 { -+ /* unused */ -+ }; -+ -+ reg_cldo1: cldo1 { -+ /* This regulator is connected with ALDO3 */ -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-3v3-2"; -+ }; -+ -+ reg_cldo2: cldo2 { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-wifi-1"; -+ }; -+ -+ reg_cldo3: cldo3 { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-wifi-2"; -+ }; -+ -+ reg_dcdca: dcdca { -+ regulator-always-on; -+ regulator-min-microvolt = <810000>; -+ regulator-max-microvolt = <1160000>; -+ regulator-name = "vdd-cpu"; -+ }; -+ -+ reg_dcdcc: dcdcc { -+ regulator-always-on; -+ regulator-min-microvolt = <810000>; -+ regulator-max-microvolt = <1080000>; -+ regulator-name = "vdd-gpu"; -+ }; -+ -+ reg_dcdcd: dcdcd { -+ regulator-always-on; -+ regulator-min-microvolt = <960000>; -+ regulator-max-microvolt = <960000>; -+ regulator-name = "vdd-sys"; -+ }; -+ -+ reg_dcdce: dcdce { -+ regulator-always-on; -+ regulator-min-microvolt = <1400000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-name = "vcc-dram"; -+ }; -+ -+ sw { -+ /* unused */ -+ }; -+ }; -+ }; -+}; -+ -+&uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_ph_pins>; -+ status = "okay"; -+}; -+ -+&usb2otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb2phy { -+ usb0_vbus-supply = <®_usb_vbus>; -+ usb1_vbus-supply = <®_usb_vbus>; -+ status = "okay"; -+}; diff --git a/patch/kernel/sunxi-dev-h6/board-0002-orangepi-lite2-add-device.patch b/patch/kernel/sunxi-dev-h6/board-0002-orangepi-lite2-add-device.patch deleted file mode 100644 index 84ab377a4..000000000 --- a/patch/kernel/sunxi-dev-h6/board-0002-orangepi-lite2-add-device.patch +++ /dev/null @@ -1,287 +0,0 @@ -diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile -index a9797d233..4972f2901 ---- a/arch/arm64/boot/dts/allwinner/Makefile -+++ b/arch/arm64/boot/dts/allwinner/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb -+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb - dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts -new file mode 100644 -index 000000000..b9aff606e ---- /dev/null -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-lite2.dts -@@ -0,0 +1,269 @@ -+// SPDX-License-Identifier: (GPL-2.0+ or MIT) -+/* -+ * Copyright (c) 2017 Icenowy Zheng -+ */ -+ -+/dts-v1/; -+ -+#include "sun50i-h6.dtsi" -+ -+#include -+ -+/ { -+ model = "Orange Pi Lite 2"; -+ compatible = "pine64,pine-h64", "allwinner,sun50i-h6"; -+ -+ aliases { -+ serial0 = &uart0; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ pwr { -+ label = "orangepi:red:pwr"; -+ gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ status { -+ label = "orangepi:green:status"; -+ gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ -+ reg_vcc3v3: vcc3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ reg_vcc1v8: vcc1v8 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ -+ reg_usb_vbus: vbus { -+ compatible = "regulator-fixed"; -+ regulator-name = "usb-vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ startup-delay-us = <100000>; -+ gpio = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ wifi_pwrseq: wifi_pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ clocks = <&rtc 1>; -+ clock-names = "ext_clock"; -+ reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */ -+ post-power-on-delay-ms = <200>; -+ }; -+}; -+ -+&cpu0 { -+ cpu-supply = <®_dcdca>; -+}; -+ -+&dwc3 { -+ status = "okay"; -+}; -+ -+&ehci0 { -+ status = "okay"; -+}; -+ -+&ehci3 { -+ status = "okay"; -+}; -+ -+&mmc0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins>; -+ vmmc-supply = <®_vcc3v3>; -+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ -+&mmc1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc1_pins>; -+ vmmc-supply = <®_cldo2>; -+ vqmmc-supply = <®_bldo3>; -+ mmc-pwrseq = <&wifi_pwrseq>; -+ bus-width = <4>; -+ non-removable; -+ status = "okay"; -+ -+ ap6255: sdio_wifi@1 { -+ reg = <1>; -+ compatible = "brcm,bcm4329-fmac"; -+ interrupt-parent = <&r_pio>; -+ interrupts = <1 0 IRQ_TYPE_LEVEL_LOW>; /* PM0 */ -+ interrupt-names = "host-wake"; -+ }; -+}; -+ -+&mmc2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc2_pins>; -+ vmmc-supply = <®_vcc3v3>; -+ vqmmc-supply = <®_bldo3>; -+ non-removable; -+ cap-mmc-hw-reset; -+ status = "okay"; -+}; -+ -+&ohci0 { -+ status = "okay"; -+}; -+ -+&ohci3 { -+ status = "okay"; -+}; -+ -+&r_i2c { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&r_i2c_pins>; -+ status = "okay"; -+ -+ axp805: pmic@36 { -+ compatible = "x-powers,axp805", "x-powers,axp806"; -+ reg = <0x36>; -+ interrupt-parent = <&r_intc>; -+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ x-powers,self-working-mode; -+ -+ regulators { -+ reg_aldo1: aldo1 { -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-pl"; -+ }; -+ -+ reg_aldo2: aldo2 { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-ac200"; -+ }; -+ -+ reg_aldo3: aldo3 { -+ /* This regulator is connected with CLDO1 */ -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-3v3-1"; -+ }; -+ -+ reg_bldo1: bldo1 { -+ regulator-always-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc-ddr-bias-pll"; -+ }; -+ -+ reg_bldo2: bldo2 { -+ regulator-always-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc-efuse-emmc-pcie-hdmi"; -+ }; -+ -+ reg_bldo3: bldo3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc-wifi-io"; -+ }; -+ -+ bldo4 { -+ /* unused */ -+ }; -+ -+ reg_cldo1: cldo1 { -+ /* This regulator is connected with ALDO3 */ -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-3v3-2"; -+ }; -+ -+ reg_cldo2: cldo2 { -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-wifi-1"; -+ }; -+ -+ reg_cldo3: cldo3 { -+ regulator-always-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-wifi-2"; -+ }; -+ -+ reg_dcdca: dcdca { -+ regulator-always-on; -+ regulator-min-microvolt = <810000>; -+ regulator-max-microvolt = <1160000>; -+ regulator-name = "vdd-cpu"; -+ }; -+ -+ reg_dcdcc: dcdcc { -+ regulator-min-microvolt = <810000>; -+ regulator-max-microvolt = <1080000>; -+ regulator-name = "vdd-gpu"; -+ }; -+ -+ reg_dcdcd: dcdcd { -+ regulator-always-on; -+ regulator-min-microvolt = <960000>; -+ regulator-max-microvolt = <960000>; -+ regulator-name = "vdd-sys"; -+ }; -+ -+ reg_dcdce: dcdce { -+ regulator-always-on; -+ regulator-min-microvolt = <1400000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-name = "vcc-dram"; -+ }; -+ -+ sw { -+ /* unused */ -+ }; -+ }; -+ }; -+}; -+ -+&uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_ph_pins>; -+ status = "okay"; -+}; -+ -+&usb2otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usb2phy { -+ usb0_vbus-supply = <®_usb_vbus>; -+ usb3_vbus-supply = <®_usb_vbus>; -+ status = "okay"; -+}; -+ -+&usb3phy { -+ phy-supply = <®_usb_vbus>; -+ status = "okay"; -+}; diff --git a/patch/kernel/sunxi-dev-h6/board-h6-add-mmc1-pins-oplite2.patch b/patch/kernel/sunxi-dev-h6/board-h6-add-mmc1-pins-oplite2.patch deleted file mode 100644 index c3336f9de..000000000 --- a/patch/kernel/sunxi-dev-h6/board-h6-add-mmc1-pins-oplite2.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index bec8c4a..cd278d5 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -253,6 +253,14 @@ - bias-pull-up; - }; - -+ mmc1_pins: mmc1-pins { -+ pins = "PG0", "PG1", "PG2", "PG3", -+ "PG4", "PG5"; -+ function = "mmc1"; -+ drive-strength = <30>; -+ bias-pull-up; -+ }; -+ - mmc2_pins: mmc2-pins { - pins = "PC1", "PC4", "PC5", "PC6", - "PC7", "PC8", "PC9", "PC10", diff --git a/patch/kernel/sunxi-dev-h6/board-h6-add-rtc-osc32k-out.patch b/patch/kernel/sunxi-dev-h6/board-h6-add-rtc-osc32k-out.patch deleted file mode 100644 index 303a609a5..000000000 --- a/patch/kernel/sunxi-dev-h6/board-h6-add-rtc-osc32k-out.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -index bec8c4a..73ed36d 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi -@@ -124,6 +124,13 @@ - clock-output-names = "osc32k"; - }; - -+ ext_osc32k: ext_osc32k_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32768>; -+ clock-output-names = "ext_osc32k"; -+ }; -+ - psci { - compatible = "arm,psci-0.2"; - method = "smc"; -@@ -511,6 +526,16 @@ - #reset-cells = <1>; - }; - -+ rtc: rtc@7000000 { -+ compatible = "allwinner,sun6i-a31-rtc"; -+ reg = <0x07000000 0x54>; -+ interrupts = , -+ ; -+ clock-output-names = "rtc-osc32k", "rtc-osc32k-out"; -+ clocks = <&ext_osc32k>; -+ #clock-cells = <1>; -+ }; -+ - r_intc: interrupt-controller@7021000 { - compatible = "allwinner,sun50i-h6-r-intc", - "allwinner,sun6i-a31-r-intc"; diff --git a/patch/kernel/sunxi-dev-h6/general-packaging-4.17-dev.patch b/patch/kernel/sunxi-dev-h6/general-packaging-4.17-dev.patch deleted file mode 100644 index 58891b4d1..000000000 --- a/patch/kernel/sunxi-dev-h6/general-packaging-4.17-dev.patch +++ /dev/null @@ -1,221 +0,0 @@ -diff --git a/scripts/package/builddeb b/scripts/package/builddeb -index 90c9a8a..3c79b90 100755 ---- a/scripts/package/builddeb -+++ b/scripts/package/builddeb -@@ -29,6 +29,27 @@ create_package() { - # in case we are in a restrictive umask environment like 0077 - chmod -R a+rX "$pdir" - -+ # Create preinstall and post install script to remove dtb -+ if [[ "$1" == *dtb* ]]; then -+ echo "if [ -d /boot/dtb-$version ]; then mv /boot/dtb-$version /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/preinst -+ echo "if [ -d /boot/dtb.old ]; then rm -rf /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst -+ echo "if [ -d /boot/dtb ]; then mv /boot/dtb /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst -+ echo "exit 0" >> $pdir/DEBIAN/preinst -+ chmod 775 $pdir/DEBIAN/preinst -+ -+ echo "if [ -d /boot/dtb-$version.old ]; then rm -rf /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/postinst -+ echo "ln -sf dtb-$version /boot/dtb > /dev/null 2>&1 || mv /boot/dtb-$version /boot/dtb" >> $pdir/DEBIAN/postinst -+ echo "exit 0" >> $pdir/DEBIAN/postinst -+ chmod 775 $pdir/DEBIAN/postinst -+ fi -+ -+ # Create postinstall script for headers -+ if [[ "$1" == *headers* ]]; then -+ echo "cd /usr/src/linux-headers-$version; echo \"Compiling headers - please wait ...\"; find -type f -exec touch {} +;make -s scripts >/dev/null 2>&1" >> $pdir/DEBIAN/postinst -+ echo "exit 0" >> $pdir/DEBIAN/postinst -+ chmod 775 $pdir/DEBIAN/postinst -+ fi -+ - # Create the package - dpkg-gencontrol -p$pname -P"$pdir" - dpkg --build "$pdir" .. -@@ -39,9 +60,11 @@ tmpdir="$objtree/debian/tmp" - kernel_headers_dir="$objtree/debian/hdrtmp" - libc_headers_dir="$objtree/debian/headertmp" - dbg_dir="$objtree/debian/dbgtmp" --packagename=linux-image-$version --kernel_headers_packagename=linux-headers-$version --libc_headers_packagename=linux-libc-dev -+dtb_dir="$objtree/debian/dtbtmp" -+packagename=linux-image-dev"$LOCALVERSION" -+kernel_headers_packagename=linux-headers-dev"$LOCALVERSION" -+dtb_packagename=linux-dtb-dev"$LOCALVERSION" -+libc_headers_packagename=linux-libc-dev-dev"$LOCALVERSION" - dbg_packagename=$packagename-dbg - - if [ "$ARCH" = "um" ] ; then -@@ -52,6 +75,15 @@ fi - # XXX: have each arch Makefile export a variable of the canonical image install - # path instead - case $ARCH in -+aarch64|arm64) -+ image_name=Image -+ installed_image_path="boot/vmlinuz-$version" -+ -+ ;; -+arm*) -+ image_name=zImage -+ installed_image_path="boot/vmlinuz-$version" -+ ;; - um) - installed_image_path="usr/bin/linux-$version" - ;; -@@ -65,7 +97,9 @@ esac - BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)" - - # Setup the directory structure --rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files -+rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" $objtree/debian/files -+mkdir -m 755 -p "$dtb_dir/DEBIAN" -+mkdir -p "$dtb_dir/boot/dtb-$version" "$dtb_dir/usr/share/doc/$dtb_packagename" - mkdir -m 755 -p "$tmpdir/DEBIAN" - mkdir -p "$tmpdir/lib" "$tmpdir/boot" - mkdir -p "$kernel_headers_dir/lib/modules/$version/" -@@ -118,6 +152,11 @@ if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then - fi - fi - -+if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then -+ #mkdir -p "$tmpdir/boot/dtb" -+ INSTALL_DTBS_PATH="$dtb_dir/boot/dtb-$version" $MAKE KBUILD_SRC= dtbs_install -+fi -+ - if [ "$ARCH" != "um" ]; then - $MAKE headers_check KBUILD_SRC= - $MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr" -@@ -137,7 +176,7 @@ fi - for script in postinst postrm preinst prerm ; do - mkdir -p "$tmpdir$debhookdir/$script.d" - cat < "$tmpdir/DEBIAN/$script" --#!/bin/sh -+#!/bin/bash - - set -e - -@@ -153,9 +192,60 @@ EOF - chmod 755 "$tmpdir/DEBIAN/$script" - done - -+## -+## Create sym link to kernel image -+## -+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/postinst -+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst -+cat >> $tmpdir/DEBIAN/postinst < /dev/null 2>&1 -+ cp /boot/uImage /tmp/uImage -+ sync -+ mountpoint -q /boot || mount /boot -+ cp /tmp/uImage /boot/uImage -+ rm -f /$installed_image_path -+else -+ ln -sf $(basename $installed_image_path) /boot/$image_name || mv /$installed_image_path /boot/$image_name -+fi -+touch /boot/.next -+exit 0 -+EOT -+ -+## -+## FAT install workaround -+## -+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/preinst -+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst -+cat >> $tmpdir/DEBIAN/preinst <> $tmpdir/DEBIAN/preinst -+ - # Build kernel header package - (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles" - (cd $srctree; find arch/*/include include scripts -type f -o -type l) >> "$objtree/debian/hdrsrcfiles" -+(cd $srctree; find security/*/include -type f) >> "$objtree/debian/hdrsrcfiles" - (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles" - (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles" - if grep -q '^CONFIG_STACK_VALIDATION=y' $KCONFIG_CONFIG ; then -@@ -167,15 +257,19 @@ if grep -q '^CONFIG_GCC_PLUGINS=y' $KCONFIG_CONFIG ; then - fi - destdir=$kernel_headers_dir/usr/src/linux-headers-$version - mkdir -p "$destdir" -+(cd $destdir; patch -p1 < /tmp/headers-debian-byteshift.patch) - (cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -) - (cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -) - (cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be - ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build" - rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" - -+(cd $destdir; make M=scripts clean) -+ - if [ "$ARCH" != "um" ]; then - create_package "$kernel_headers_packagename" "$kernel_headers_dir" -- create_package "$libc_headers_packagename" "$libc_headers_dir" -+ # create_package "$libc_headers_packagename" "$libc_headers_dir" -+ create_package "$dtb_packagename" "$dtb_dir" - fi - - create_package "$packagename" "$tmpdir" -diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian -index 6adb3a1..00e12eb 100755 ---- a/scripts/package/mkdebian -+++ b/scripts/package/mkdebian -@@ -61,10 +61,12 @@ else - packageversion=$version-$revision - fi - sourcename=$KDEB_SOURCENAME --packagename=linux-image-$version --kernel_headers_packagename=linux-headers-$version -+packagename=linux-image-dev$LOCALVERSION -+kernel_headers_packagename=linux-headers-dev$LOCALVERSION -+dtb_packagename=linux-dtb-dev$LOCALVERSION - dbg_packagename=$packagename-dbg - debarch= -+image_name= - set_debarch - - if [ "$ARCH" = "um" ] ; then -@@ -168,6 +170,11 @@ Architecture: $debarch - Description: Linux kernel debugging symbols for $version - This package will come in handy if you need to debug the kernel. It provides - all the necessary debug symbols for the kernel and its modules. -+ -+Package: $dtb_packagename -+Architecture: $debarch -+Description: Linux DTB, version $version -+ This package contains device blobs from the Linux kernel, version $version - EOF - - cat < debian/rules -diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile -index f839ecd9..cd276162 100644 ---- a/arch/arm64/Makefile -+++ b/arch/arm64/Makefile -@@ -103,7 +103,7 @@ core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a - - # Default target when executing plain make - boot := arch/arm64/boot --KBUILD_IMAGE := $(boot)/Image.gz -+KBUILD_IMAGE := $(boot)/Image - KBUILD_DTBS := dtbs - - all: Image.gz $(KBUILD_DTBS) diff --git a/patch/kernel/sunxi-dev/0000-axp-adjustements.patch.disabled b/patch/kernel/sunxi-dev/0000-axp-adjustements.patch.disabled new file mode 100644 index 000000000..377e6b034 --- /dev/null +++ b/patch/kernel/sunxi-dev/0000-axp-adjustements.patch.disabled @@ -0,0 +1,229 @@ +diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig +index 44097a3e0..a0cbdbb2c 100644 +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -756,6 +756,14 @@ config LEDS_NIC78BX + To compile this driver as a module, choose M here: the module + will be called leds-nic78bx. + ++config LEDS_AXP20X ++ tristate "LED support for AXP20X-like PMICs (AXP813, ...)" ++ depends on LEDS_CLASS && MFD_AXP20X ++ help ++ This option enables support for on-chip LED drivers on ++ AXP20X-like PMICs. ++ ++ + comment "LED Triggers" + source "drivers/leds/trigger/Kconfig" + +diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile +index 420b5d2cf..a8149fb6e 100644 +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -78,6 +78,7 @@ obj-$(CONFIG_LEDS_MT6323) += leds-mt6323.o + obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o + obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o + obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o ++obj-$(CONFIG_LEDS_AXP20X) += leds-axp20x.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o +diff --git a/drivers/leds/leds-axp20x.c b/drivers/leds/leds-axp20x.c +new file mode 100644 +index 000000000..de33c1d83 +--- /dev/null ++++ b/drivers/leds/leds-axp20x.c +@@ -0,0 +1,138 @@ ++/* ++ * LED Driver for X-Powers AXP813 PMIC. ++ * ++ * Copyright(c) 2017 Ondrej Jirman ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AXP813_CHGLED_CTRL_MASK BIT(3) ++#define AXP813_CHGLED_CTRL_CHARGER BIT(3) ++#define AXP813_CHGLED_CTRL_USER 0 ++ ++#define AXP813_CHGLED_USER_STATE_MASK GENMASK(5, 4) ++#define AXP813_CHGLED_USER_STATE_OFFSET 4 ++#define AXP813_CHGLED_USER_STATE_OFF 0 ++#define AXP813_CHGLED_USER_STATE_BLINK_SLOW 1 ++#define AXP813_CHGLED_USER_STATE_BLINK_FAST 2 ++#define AXP813_CHGLED_USER_STATE_ON 3 ++ ++struct axp20x_led { ++ struct led_classdev cdev; ++ struct regmap *regmap; ++}; ++ ++static int axp20x_led_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ struct axp20x_led *led = ++ container_of(led_cdev, struct axp20x_led, cdev); ++ unsigned int val; ++ ++ val = value == LED_OFF ? AXP813_CHGLED_USER_STATE_OFF : ++ AXP813_CHGLED_USER_STATE_ON; ++ ++ return regmap_update_bits(led->regmap, AXP20X_OFF_CTRL, ++ AXP813_CHGLED_USER_STATE_MASK, ++ val << AXP813_CHGLED_USER_STATE_OFFSET); ++ ++} ++ ++static int axp20x_led_probe(struct platform_device *pdev) ++{ ++ struct axp20x_dev *axp20x; ++ struct axp20x_led *led; ++ int ret; ++ ++ if (!of_device_is_available(pdev->dev.of_node)) ++ return -ENODEV; ++ ++ axp20x = dev_get_drvdata(pdev->dev.parent); ++ if (!axp20x) ++ return -EINVAL; ++ ++ led = devm_kzalloc(&pdev->dev, ++ sizeof(struct axp20x_led), ++ GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->regmap = axp20x->regmap; ++ ++ led->cdev.name = "chgled"; ++ led->cdev.brightness_set_blocking = axp20x_led_set; ++ led->cdev.brightness = LED_OFF; ++ led->cdev.max_brightness = 1; ++ ++ ret = led_classdev_register(pdev->dev.parent, &led->cdev); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to register led %s\n", ++ led->cdev.name); ++ return ret; ++ } ++ ++ ret = regmap_update_bits(led->regmap, AXP20X_OFF_CTRL, ++ AXP813_CHGLED_CTRL_MASK, ++ AXP813_CHGLED_CTRL_USER); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to enable user cnotrol\n"); ++ } ++ ++ ret = axp20x_led_set(&led->cdev, led->cdev.brightness); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to init led %s\n", ++ led->cdev.name); ++ } ++ ++ platform_set_drvdata(pdev, led); ++ return 0; ++} ++ ++static int axp20x_led_remove(struct platform_device *pdev) ++{ ++ struct axp20x_led *led = platform_get_drvdata(pdev); ++ ++ axp20x_led_set(&led->cdev, LED_OFF); ++ ++ regmap_update_bits(led->regmap, AXP20X_OFF_CTRL, ++ AXP813_CHGLED_CTRL_MASK, ++ AXP813_CHGLED_CTRL_CHARGER); ++ ++ led_classdev_unregister(&led->cdev); ++ ++ return 0; ++} ++ ++static const struct of_device_id axp20x_leds_of_match[] = { ++ { .compatible = "x-powers,axp813-leds", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, axp20x_leds_of_match); ++ ++static struct platform_driver axp20x_led_driver = { ++ .driver = { ++ .name = "axp20x-leds", ++ .of_match_table = axp20x_leds_of_match, ++ }, ++ .probe = axp20x_led_probe, ++ .remove = axp20x_led_remove, ++}; ++ ++module_platform_driver(axp20x_led_driver); ++ ++MODULE_AUTHOR("Ondrej Jirman "); ++MODULE_DESCRIPTION("LED driver for AXP813 PMIC"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:leds-axp20x"); +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index 0be511dd9..a9bdf3cdd 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -130,6 +131,7 @@ static const struct regmap_range axp288_volatile_ranges[] = { + regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL), + regmap_reg_range(AXP288_BC_DET_STAT, AXP288_BC_DET_STAT), + regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL), ++ regmap_reg_range(AXP22X_CHRG_CTRL3, AXP22X_CHRG_CTRL3), + regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L), + regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), + regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE), +@@ -762,6 +764,16 @@ static const struct mfd_cell axp809_cells[] = { + }, + }; + ++static struct regulator_bulk_data vcc_vb = { ++ .supply = "vcc-vb", ++}; ++ ++static struct regulator_userspace_consumer_data vcc_vb_data = { ++ .name = "vcc-vb", ++ .num_supplies = 1, ++ .supplies = &vcc_vb, ++}; ++ + static const struct mfd_cell axp813_cells[] = { + { + .name = "axp221-pek", +@@ -778,6 +790,16 @@ static const struct mfd_cell axp813_cells[] = { + }, { + .name = "axp20x-battery-power-supply", + .of_compatible = "x-powers,axp813-battery-power-supply", ++ }, { ++ .name = "axp20x-usb-power-supply", ++ .of_compatible = "x-powers,axp813-usb-power-supply", ++ }, { ++ .name = "axp20x-leds", ++ .of_compatible = "x-powers,axp813-leds", ++ }, { ++ .name = "reg-userspace-consumer", ++ .platform_data = &vcc_vb_data, ++ .pdata_size = sizeof(vcc_vb_data), + }, + }; + diff --git a/patch/kernel/sunxi-dev/0000-remove-old-ths-node.patch b/patch/kernel/sunxi-dev/0000-remove-old-ths-node.patch new file mode 100644 index 000000000..ca2a2b658 --- /dev/null +++ b/patch/kernel/sunxi-dev/0000-remove-old-ths-node.patch @@ -0,0 +1,24 @@ +diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi +index 586ce53fc..e72c24470 100644 +--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi ++++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi +@@ -590,19 +590,6 @@ + }; + }; + +- ths: ths@1c25000 { +- #thermal-sensor-cells = <0>; +- compatible = "allwinner,sun8i-h3-ths"; +- reg = <0x01c25000 0x400>, +- <0x01c14234 0x4>; +- reg-names = "ths", "calibration"; +- interrupts = ; +- resets = <&ccu RST_BUS_THS>; +- reset-names = "ahb"; +- clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; +- clock-names = "ahb", "ths"; +- }; +- + timer@1c20c00 { + compatible = "allwinner,sun4i-a10-timer"; + reg = <0x01c20c00 0xa0>; diff --git a/patch/kernel/sunxi-dev/0000-sound-soc-ac100-codec-Initial-implementation.patch.disabled b/patch/kernel/sunxi-dev/0000-sound-soc-ac100-codec-Initial-implementation.patch.disabled new file mode 100644 index 000000000..5c9e8db29 --- /dev/null +++ b/patch/kernel/sunxi-dev/0000-sound-soc-ac100-codec-Initial-implementation.patch.disabled @@ -0,0 +1,346 @@ +From 6eb4890e1b83490864f18d3926182069e54a4dfb Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sun, 12 Nov 2017 23:09:14 +0100 +Subject: [PATCH] sound: soc: ac100-codec: Initial implementation + +This driver provides AC100 codec controls. + +Note: This does not yet provide anything, it's just a skeleton +for a future driver. + +Signed-off-by: Ondrej Jirman +--- + sound/soc/sunxi/Kconfig | 11 ++ + sound/soc/sunxi/Makefile | 1 + + sound/soc/sunxi/ac100-codec.c | 291 ++++++++++++++++++++++++++++++++++ + 3 files changed, 303 insertions(+) + create mode 100644 sound/soc/sunxi/ac100-codec.c + +diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig +index 22408bc2d6ec6..e276cc94a8c5e 100644 +--- a/sound/soc/sunxi/Kconfig ++++ b/sound/soc/sunxi/Kconfig +@@ -20,6 +20,17 @@ config SND_SUN8I_CODEC + + Say Y or M if you want to add sun8i digital audio codec support. + ++config SND_AC100_CODEC ++ tristate "Allwinner (X-Powers) AC100 audio codec" ++ depends on OF ++ depends on MACH_SUN8I || COMPILE_TEST ++ select REGMAP_MMIO ++ help ++ This option enables the audio codec support for Allwinner (X-Powers) ++ AC100 chip. ++ ++ Say Y or M if you want to add AC100 audio codec support. ++ + config SND_SUN8I_CODEC_ANALOG + tristate "Allwinner sun8i Codec Analog Controls Support" + depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST +diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile +index 4a9ef67386caf..83461fdbfaa2a 100644 +--- a/sound/soc/sunxi/Makefile ++++ b/sound/soc/sunxi/Makefile +@@ -4,3 +4,4 @@ obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o + obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o + obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o + obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o ++obj-$(CONFIG_SND_AC100_CODEC) += ac100-codec.o +diff --git a/sound/soc/sunxi/ac100-codec.c b/sound/soc/sunxi/ac100-codec.c +new file mode 100644 +index 0000000000000..d5438815be754 +--- /dev/null ++++ b/sound/soc/sunxi/ac100-codec.c +@@ -0,0 +1,291 @@ ++/* ++ * This driver supports the controls for X-Powers (Allwinner) ++ * AC100 audio codec. This codec is co-packaged with AXP81x PMICs. ++ * ++ * (C) Copyright 2017 Ondrej Jirman ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* ++ * Reasearch ++ * --------- ++ * ++ * Features: ++ * 2 A/D ++ * 2 D/A ++ * 2 I2S/PCM #1 and #2 ++ * 1 PCM mono #3 muxable with I2S #2 ++ * 3 mic inputs (mic #2 and #3 exclusively muxable at input) ++ * 1 line in (directly or through amp) ++ * 1 aux input ++ * all input signals mixable directly into output (bypass AD/DA) ++ * ++ * outputs: ++ * HPOUTL - headphone left ++ * HPOUTR - headphone right ++ * LINEOUT - line out differential ++ * EAROUT - earpeiece differential ++ * SPKOUT1 - SPOL left speaker differnetial ++ * SPKOUT2 - SPOR right speaker differnetial ++ * ++ * Power up: ++ * LDOIN - 1.5-3.3V external power ++ * AVCC - analog power 3V ++ * CPVDD - 1.8V ++ * VDD-IO1 - power for I2S #1 and #2 1.8/3V ++ * VDD-IO2 - power for I2S #3 1.8/3V ++ * VCC-RTC - power for RTC 1.8/3V ++ * ++ * Clocks: page 28 ++ * SYSCLK must be 24576000 Hz (48kHz) or 22579200 Hz (44.1kHz) ++ * - Source I2S1CLK/MCLK1 ++ * - If SRC# module is used SYSCLK must be generated by PLL ++ * ++ * A/D: ++ * ADC_APC_CTRL B15 B11 enable/disable A/D to save power ++ * ADC_APC_CTRL B14-12 B10-8 volume control for A/D ++ * ADC_DIG_CTRL B15 enable/disable digital A/D to save power ++ * ADDA_FS_I2S1 ADDA_FS_I2S2 - select sample rate ++ * ++ * D/A: ++ * OMIXER_DACA_CTRL B15-14 enable/disable D/A channels ++ * DAC_DIG_CTRL B15 enable/disable digital D/A ++ * ++ * Mixer: ++ * - 2 channels DAC Output mixers ++ * - inputs: ++ * - LINEINL/R ++ * - AXIL/R ++ * - MIC1P/N,MIC2P/N ++ * - Stereo DAC output ++ * - 2 channels ADC Record mixers ++ * - inputs: ++ * - LINEINL/R ++ * - AXIL/R ++ * - MIC1P/N,MIC2P/N ++ * - Stereo DAC output ++ * - Digital mixers ++ * - avaliable on: ++ * - before stereo DAC - DAC_MXR_SRC ++ * - I2S1 output - I2S1_MXR_SRC ++ * - I2S2 output - I2S2_MXR_SRC ++ * - Analogue inputs ++ * - LINEINL/R - 1 ch. mono ++ * - can be mixed into ADC record mixer or DAC output mixer ++ * - -9dB to 12dB in 1.5dB step by LINEIN_DIFF_PREG ++ * - AXIL/R - 2 ch. stereo ++ * - can be mixed into ADC record mixer or DAC output mixer ++ * - programmable volume level adj. and mute ++ * - -9dB to 12dB in 1.5dB steps by AXI_PREG ++ * - MIC1P/N - has preamp ++ * - MIC2P/N - has preamp ++ * - MIC3P/N - has preamp muxed with MIC2 (sel by ADC_SRCBST_CTRL B7) ++ * - can be mixed into ADC record mixer or DAC output mixer ++ * - preamps enable at ADC_SRCBST_CTRL B15 and B11 ++ * - preamp gain at MIC1BOOST MIC2BOOST ++ * - Analogue outputs: ++ * - HPOUTL/R, HPOUTFB - 2ch. headphones ++ * - sources output mixer or directly from DAC ++ * - sel HPOUT_CTRL B15 B14 ++ * - mute HPOUT_CTRL B13 B12 ++ * - power amp ++ * - powerdown/up HPOUT_CTRL B11 ++ * - volume HP_VOL[5:0] - 64dB range in 1dB step from 0dB to -62dB ++ * - mute by using 0 for HP_VOL[5:0] ++ * - DC offset cancellation (POP noise) HP_DCRM_EN ++ * - This bit must be set 0xf before headphone PA enabled, and this bit ++ * must be set 0x0 before headphone PA disabled. ++ * - zero cross to prevent noise/clicsk on volume change ZCROSS_EN ++ * - SPOLP/N, SPORP/N 2 ch. speakers (mono/stereo) ++ * - source for SPOLP ++ * - left output mixer or (left+right) output mixer ++ * - source for SPORP ++ * - right output mixer or (left+right) output mixer ++ * - volume 43.5dB rang in 1.5dB step from -43.5dB to 0dB ++ * - amp enable SPKOUT_CTRL B11 B7 ++ * - EAROUTP/N - 1 ch earpeice ++ * - source left DAC, right DAC, left output mixer or right output mixer ++ * - volume ERPOUT_CTRL[4:0] 43.5dB range in 1.5dB step from -43.5dB to 0dB ++ * - power amp enable ERPOUT_CTRL B5 ++ * - LINEOUTP/N - 1ch line out ++ * - source MIC1 preamp, MIC2 preamp, left output mix or right output mix ++ * - volume 10.5dB range in 1.5dB step from -4.5dB to 6dB ++ * - out buffer power up/down LOUT_CTRL B4 ++ * ++ * Jack insert detection: ++ * - HBIAS current detection ++ * - 5bit ADC sample rate 16/32/64/128Hz ++ * - HMIC_STATUS[12:8] - ADC value ++ * - 2 thresholds TH1 for plug connection, TH2 for key press ++ * - can periodically trigger interrupts during key press (HBIAS above TH2) ++ * ++ * Interrupts: ++ * - FALLING_EDGE ++ * - for: ++ * - KEYDOWN ++ * - KEYUP ++ * - PLUG_IN ++ * - PLUG_OUT ++ * - HMIC_DATA ++ * ++ * High Pass Filter: ++ * - remove DC offset, can be disabled ++ * ++ * AGC: ++ * - automatic gain control before ADC input channels ++ * - params: ++ * - attack, decay time - 32/fs to 2^15*32/fs ++ * - target gain - –1dB to –30dB relative to a full-scale signal ++ * - noise threshold - –30dB to –90dB of full-scale (mute if input below this level) ++ * - max gain 0dB to 40dB in steps of 0.5dB ++ * - hysteresis - for noise detection in terms of signal level ++ * - debounce time - hysteresis for noise det in terms of time ++ * - also provides some output flags: ++ * - noise threshold reached ++ * - current gain ++ * - agc saturated (gain could get higher for the given input, but limited by ++ * params) ++ * - adc saturated - clipping at ADC input stage ++ * ++ * DRC: ++ * - dynamic range control for digital playback path ++ * - energy filter ++ * - compressor ++ * - smooth filter ++ * - can be disabled ++ */ ++ ++#define AC100_HMIC_DATA_MASK GENMASK(12, 8) ++#define AC100_HMIC_DATA_OFF 8 ++#define AC100_HMIC_PULLOUT_PENDING BIT(4) ++#define AC100_HMIC_PLUGIN_PENDING BIT(3) ++#define AC100_HMIC_KEYUP_PENDING BIT(2) ++#define AC100_HMIC_KEYDOWN_PENDING BIT(1) ++#define AC100_HMIC_DATA_PENDING BIT(0) ++ ++struct ac100_codec { ++ struct device *dev; ++ struct regmap *regmap; ++ int irq; ++}; ++ ++static irqreturn_t ac100_codec_irq(int irq, void *data) ++{ ++ struct ac100_codec *codec = data; ++ unsigned int val = 0; ++ int ret; ++ ++ /* read status */ ++ ret = regmap_read(codec->regmap, AC100_HMIC_STATUS, &val); ++ if (ret) ++ return IRQ_HANDLED; ++ ++ if (val & AC100_HMIC_PULLOUT_PENDING) { ++ dev_info(codec->dev, "IRQ: Pull out"); ++ } ++ ++ if (val & AC100_HMIC_PLUGIN_PENDING) { ++ dev_info(codec->dev, "IRQ: Plug in"); ++ } ++ ++ if (val & AC100_HMIC_KEYUP_PENDING) { ++ dev_info(codec->dev, "IRQ: Key up"); ++ } ++ ++ if (val & AC100_HMIC_KEYDOWN_PENDING) { ++ dev_info(codec->dev, "IRQ: Key down"); ++ } ++ ++ if (val & AC100_HMIC_DATA_PENDING) { ++ dev_info(codec->dev, "IRQ: Data"); ++ } ++ ++ /* clear status */ ++ ret = regmap_write(codec->regmap, AC100_HMIC_STATUS, 0); ++ if (ret) ++ return IRQ_HANDLED; ++ ++ return IRQ_HANDLED; ++} ++ ++static int ac100_codec_probe(struct platform_device *pdev) ++{ ++ struct ac100_dev *ac100 = dev_get_drvdata(pdev->dev.parent); ++ struct ac100_codec *codec; ++ int ret; ++ ++ codec = devm_kzalloc(&pdev->dev, sizeof(*codec), GFP_KERNEL); ++ if (!codec) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, codec); ++ codec->dev = &pdev->dev; ++ codec->regmap = ac100->regmap; ++ ++ codec->irq = platform_get_irq(pdev, 0); ++ if (codec->irq < 0) { ++ dev_err(&pdev->dev, "No IRQ resource\n"); ++ return codec->irq; ++ } ++ ++ ret = devm_request_threaded_irq(&pdev->dev, codec->irq, NULL, ++ ac100_codec_irq, ++ IRQF_SHARED | IRQF_ONESHOT, ++ dev_name(&pdev->dev), codec); ++ if (ret) { ++ dev_err(&pdev->dev, "Could not request IRQ\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static int ac100_codec_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = platform_get_drvdata(pdev); ++ struct ac100_codec *codec = snd_soc_card_get_drvdata(card); ++ ++ return 0; ++} ++ ++static const struct of_device_id ac100_codec_of_match[] = { ++ { .compatible = "x-powers,ac100-codec" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, ac100_codec_of_match); ++ ++static struct platform_driver ac100_codec_driver = { ++ .driver = { ++ .name = "ac100-codec", ++ .of_match_table = ac100_codec_of_match, ++ }, ++ .probe = ac100_codec_probe, ++ .remove = ac100_codec_remove, ++}; ++module_platform_driver(ac100_codec_driver); ++ ++MODULE_DESCRIPTION("X-Powers AC100 codec driver"); ++MODULE_AUTHOR("Ondrej Jirman "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:ac100-codec"); diff --git a/patch/kernel/sunxi-dev/0000-unlock-h5-dvfs.patch b/patch/kernel/sunxi-dev/0000-unlock-h5-dvfs.patch new file mode 100644 index 000000000..d72287335 --- /dev/null +++ b/patch/kernel/sunxi-dev/0000-unlock-h5-dvfs.patch @@ -0,0 +1,46 @@ +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +index 67e2246a6..e37d779f8 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +@@ -55,7 +55,6 @@ + clocks = <&ccu CLK_CPUX>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; +- clock-frequency = <1200000000>; + #cooling-cells = <2>; + cooling-min-level = <0>; + cooling-max-level = <15>; +@@ -67,7 +66,6 @@ + reg = <1>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; +- clock-frequency = <1200000000>; + }; + + cpu@2 { +@@ -76,7 +74,6 @@ + reg = <2>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; +- clock-frequency = <1200000000>; + }; + + cpu@3 { +@@ -85,10 +82,16 @@ + reg = <3>; + enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; +- clock-frequency = <1200000000>; + }; + }; + ++ reg_cpu_fallback: reg_cpu_fallback { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd-cpux-dummy"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ }; ++ + psci { + compatible = "arm,psci-0.2"; + method = "smc"; diff --git a/patch/kernel/sunxi-dev/0001-arm64-allwinner-a64-enable-Wi-Fi-for-Pine64.patch b/patch/kernel/sunxi-dev/0001-arm64-allwinner-a64-enable-Wi-Fi-for-Pine64.patch new file mode 100644 index 000000000..1fa0916d9 --- /dev/null +++ b/patch/kernel/sunxi-dev/0001-arm64-allwinner-a64-enable-Wi-Fi-for-Pine64.patch @@ -0,0 +1,52 @@ +From a5b709a81ad9a5e2e6e4be6a696711ad7f35ad57 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 9 Feb 2017 00:18:56 +0800 +Subject: [PATCH 001/146] arm64: allwinner: a64: enable Wi-Fi for Pine64 + +The Wi-Fi modules of Pine64 is powered via DLDO4 and ELDO1 (the latter +one provides I/O voltage). + +Add device node for it. + +Signed-off-by: Icenowy Zheng +--- + .../boot/dts/allwinner/sun50i-a64-pine64.dts | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +index 1b9b92e541d2..d06b5b88f60e 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +@@ -62,6 +62,11 @@ + chosen { + stdout-path = "serial0:115200n8"; + }; ++ ++ wifi_pwrseq: wifi_pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ ++ }; + }; + + &ehci0 { +@@ -109,6 +114,17 @@ + status = "okay"; + }; + ++&mmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ vmmc-supply = <®_dldo4>; ++ vqmmc-supply = <®_eldo1>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ non-removable; ++ bus-width = <4>; ++ status = "okay"; ++}; ++ + &ohci0 { + status = "okay"; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0002-arm64-allwinner-a64-add-Mali-device-node.patch b/patch/kernel/sunxi-dev/0002-arm64-allwinner-a64-add-Mali-device-node.patch new file mode 100644 index 000000000..46077ddd4 --- /dev/null +++ b/patch/kernel/sunxi-dev/0002-arm64-allwinner-a64-add-Mali-device-node.patch @@ -0,0 +1,72 @@ +From fa666ec858630bad5d3bf2952c96460302065102 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Sat, 6 May 2017 19:29:44 +0800 +Subject: [PATCH 002/146] arm64: allwinner: a64: add Mali device node + +Signed-off-by: Icenowy Zheng +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 41 +++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index d3daf90a8715..0f69f3593975 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -157,6 +157,20 @@ + compatible = "linux,spdif-dit"; + }; + ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ cma: linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ size = <0x4000000>; ++ alignment = <0x2000>; ++ linux,cma-default; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupts = ; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "gp", ++ "gpmmu", ++ "pp0", ++ "ppmmu0", ++ "pp1", ++ "ppmmu1", ++ "pmu"; ++ clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>; ++ clock-names = "bus", "core"; ++ resets = <&ccu RST_BUS_GPU>; ++ memory-region = <&cma>; ++ ++ assigned-clocks = <&ccu CLK_GPU>; ++ assigned-clock-rates = <384000000>; ++ }; ++ + gic: interrupt-controller@1c81000 { + compatible = "arm,gic-400"; + reg = <0x01c81000 0x1000>, +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0003-net-stmmac-dwmac-sun8i-support-RGMII-modes-with-PHY-.patch b/patch/kernel/sunxi-dev/0003-net-stmmac-dwmac-sun8i-support-RGMII-modes-with-PHY-.patch new file mode 100644 index 000000000..c417b7244 --- /dev/null +++ b/patch/kernel/sunxi-dev/0003-net-stmmac-dwmac-sun8i-support-RGMII-modes-with-PHY-.patch @@ -0,0 +1,35 @@ +From 98800eeb2244387e821f4af8d21ccf2deaf18da0 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Mon, 21 Aug 2017 23:02:32 +0800 +Subject: [PATCH 003/146] net: stmmac: dwmac-sun8i: support RGMII modes with + PHY internal delay + +Some boards uses a PHY with internal delay with an Allwinner SoC. + +Support these PHY modes in the driver. + +As the driver has no configuration registers for these modes, just treat +them as ordinary RGMII. + +Signed-off-by: Icenowy Zheng +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +index f9a61f90cfbc..3c18f4a9dd6c 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -933,6 +933,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) + /* default */ + break; + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: + reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII; + break; + case PHY_INTERFACE_MODE_RMII: +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0004-arm64-allwinner-a64-disable-the-RTL8211E-internal-RX.patch b/patch/kernel/sunxi-dev/0004-arm64-allwinner-a64-disable-the-RTL8211E-internal-RX.patch new file mode 100644 index 000000000..c0de938bf --- /dev/null +++ b/patch/kernel/sunxi-dev/0004-arm64-allwinner-a64-disable-the-RTL8211E-internal-RX.patch @@ -0,0 +1,35 @@ +From e89cb84d23d2537cd1b256afdd0fe880648ee1a9 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Mon, 21 Aug 2017 23:08:08 +0800 +Subject: [PATCH 004/146] arm64: allwinner: a64: disable the RTL8211E internal + RX delay on Pine64+ + +Some Pine64+ boards have a broken RTL8211E PHY, which cannot work +reliably in 1000Base-T mode with default configuration. + +A solution is passed to Pine64, which is said to be disabling the +internal RX delay of the PHY. + +Enable the hack by set the PHY mode to RGMII-TXID. + +Signed-off-by: Icenowy Zheng +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts +index 24f1aac366d6..ed715426fffc 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts +@@ -52,7 +52,7 @@ + &emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-txid"; + phy-handle = <&ext_rgmii_phy>; + status = "okay"; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0005-drm-gem-cma-Export-with-handle-allocator.patch b/patch/kernel/sunxi-dev/0005-drm-gem-cma-Export-with-handle-allocator.patch new file mode 100644 index 000000000..b620041bd --- /dev/null +++ b/patch/kernel/sunxi-dev/0005-drm-gem-cma-Export-with-handle-allocator.patch @@ -0,0 +1,50 @@ +From ea69ff188dd5d9ac7162f05a22bf299b83a7536e Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Mon, 7 Dec 2015 09:33:28 +0100 +Subject: [PATCH 005/146] drm: gem: cma: Export with handle allocator + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/drm_gem_cma_helper.c | 3 ++- + include/drm/drm_gem_cma_helper.h | 4 ++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c +index 80a5115c3846..077c61f065d9 100644 +--- a/drivers/gpu/drm/drm_gem_cma_helper.c ++++ b/drivers/gpu/drm/drm_gem_cma_helper.c +@@ -142,7 +142,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_create); + * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative + * error code on failure. + */ +-static struct drm_gem_cma_object * ++struct drm_gem_cma_object * + drm_gem_cma_create_with_handle(struct drm_file *file_priv, + struct drm_device *drm, size_t size, + uint32_t *handle) +@@ -169,6 +169,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv, + + return cma_obj; + } ++EXPORT_SYMBOL_GPL(drm_gem_cma_create_with_handle); + + /** + * drm_gem_cma_free_object - free resources associated with a CMA GEM object +diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h +index 19777145cf8e..79f397c91517 100644 +--- a/include/drm/drm_gem_cma_helper.h ++++ b/include/drm/drm_gem_cma_helper.h +@@ -79,6 +79,10 @@ int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma); + /* allocate physical memory */ + struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, + size_t size); ++struct drm_gem_cma_object * ++drm_gem_cma_create_with_handle(struct drm_file *file_priv, ++ struct drm_device *drm, size_t size, ++ uint32_t *handle); + + extern const struct vm_operations_struct drm_gem_cma_vm_ops; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0006-drm-sun4i-Add-GEM-allocator.patch b/patch/kernel/sunxi-dev/0006-drm-sun4i-Add-GEM-allocator.patch new file mode 100644 index 000000000..509cf4a82 --- /dev/null +++ b/patch/kernel/sunxi-dev/0006-drm-sun4i-Add-GEM-allocator.patch @@ -0,0 +1,102 @@ +From b143de6aef8be007256082e0f89606b7f5e3c757 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Mon, 7 Dec 2015 09:47:34 +0100 +Subject: [PATCH 006/146] drm/sun4i: Add GEM allocator + +Signed-off-by: Maxime Ripard +--- + drivers/gpu/drm/sun4i/sun4i_drv.c | 27 +++++++++++++++++++++++++++ + include/uapi/drm/sun4i_drm.h | 29 +++++++++++++++++++++++++++++ + 2 files changed, 56 insertions(+) + create mode 100644 include/uapi/drm/sun4i_drm.h + +diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c +index 8b0cd08034e0..9f5de14fb2fe 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_drv.c ++++ b/drivers/gpu/drm/sun4i/sun4i_drv.c +@@ -22,6 +22,8 @@ + #include + #include + ++#include ++ + #include "sun4i_drv.h" + #include "sun4i_frontend.h" + #include "sun4i_framebuffer.h" +@@ -30,6 +32,27 @@ + + DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); + ++static int sun4i_gem_create_ioctl(struct drm_device *drm, void *data, ++ struct drm_file *file_priv) ++{ ++ struct drm_sun4i_gem_create *args = data; ++ struct drm_gem_cma_object *cma_obj; ++ size_t size; ++ ++ /* The Mali requires a 64 bytes alignment */ ++ size = ALIGN(args->size, 64); ++ ++ cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, size, ++ &args->handle); ++ ++ return PTR_ERR_OR_ZERO(cma_obj); ++} ++ ++static const struct drm_ioctl_desc sun4i_drv_ioctls[] = { ++ DRM_IOCTL_DEF_DRV(SUN4I_GEM_CREATE, sun4i_gem_create_ioctl, ++ DRM_UNLOCKED | DRM_AUTH), ++}; ++ + static struct drm_driver sun4i_drv_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, + +@@ -42,6 +65,10 @@ static struct drm_driver sun4i_drv_driver = { + .major = 1, + .minor = 0, + ++ /* Custom ioctls */ ++ .ioctls = sun4i_drv_ioctls, ++ .num_ioctls = ARRAY_SIZE(sun4i_drv_ioctls), ++ + /* GEM Operations */ + .dumb_create = drm_gem_cma_dumb_create, + .gem_free_object_unlocked = drm_gem_cma_free_object, +diff --git a/include/uapi/drm/sun4i_drm.h b/include/uapi/drm/sun4i_drm.h +new file mode 100644 +index 000000000000..67b9dd4ee594 +--- /dev/null ++++ b/include/uapi/drm/sun4i_drm.h +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (C) 2015 Free Electrons ++ * Copyright (C) 2015 NextThing Co ++ * ++ * Maxime Ripard ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ */ ++ ++#ifndef _UAPI_SUN4I_DRM_H_ ++#define _UAPI_SUN4I_DRM_H_ ++ ++#include ++ ++struct drm_sun4i_gem_create { ++ __u64 size; ++ __u32 flags; ++ __u32 handle; ++}; ++ ++#define DRM_SUN4I_GEM_CREATE 0x00 ++ ++#define DRM_IOCTL_SUN4I_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_SUN4I_GEM_CREATE, \ ++ struct drm_sun4i_gem_create) ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0007-Add-sopine-HDMI-sound-and-WiFi-support.patch b/patch/kernel/sunxi-dev/0007-Add-sopine-HDMI-sound-and-WiFi-support.patch new file mode 100644 index 000000000..a36bdba3a --- /dev/null +++ b/patch/kernel/sunxi-dev/0007-Add-sopine-HDMI-sound-and-WiFi-support.patch @@ -0,0 +1,96 @@ +From 87020e638ad511e0ebe9c72208d2f0192c905812 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sun, 3 Dec 2017 11:43:08 -0800 +Subject: [PATCH 007/146] Add sopine HDMI sound and WiFi support + +--- + .../allwinner/sun50i-a64-sopine-baseboard.dts | 18 ++++++++++++ + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 29 +++++++++++++++++++ + 2 files changed, 47 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +index c21f2331add6..8161895dde52 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +@@ -86,6 +86,10 @@ + status = "okay"; + }; + ++&i2s2 { ++ status = "okay"; ++}; ++ + &mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; +@@ -93,6 +97,16 @@ + }; + }; + ++&mmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ vmmc-supply = <®_dldo4>; ++ vqmmc-supply = <®_eldo1>; ++ non-removable; ++ bus-width = <4>; ++ status = "okay"; ++}; ++ + &mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; +@@ -138,6 +152,10 @@ + vcc-hdmi-supply = <®_dldo1>; + }; + ++&sound_hdmi { ++ status = "okay"; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 0f69f3593975..0b44018361cb 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -727,6 +727,35 @@ + status = "disabled"; + }; + ++ i2s2: i2s@1c22800 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun8i-h3-i2s"; ++ reg = <0x01c22800 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; ++ clock-names = "apb", "mod"; ++ dmas = <&dma 27>; ++ resets = <&ccu RST_BUS_I2S2>; ++ dma-names = "tx"; ++ status = "disabled"; ++ }; ++ ++ sound_hdmi: sound_hdmi { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "allwinner,hdmi"; ++ simple-audio-card,mclk-fs = <256>; ++ status = "disabled"; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s2>; ++ }; ++ }; ++ + rtc: rtc@1f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0008-arm64-dts-sun50i-a64-pine64-add-HDMI-audio-nodes.patch b/patch/kernel/sunxi-dev/0008-arm64-dts-sun50i-a64-pine64-add-HDMI-audio-nodes.patch new file mode 100644 index 000000000..cf4c3c14d --- /dev/null +++ b/patch/kernel/sunxi-dev/0008-arm64-dts-sun50i-a64-pine64-add-HDMI-audio-nodes.patch @@ -0,0 +1,39 @@ +From 887b96d878bb0e261bc19062dc73d193c75bc56a Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Tue, 26 Dec 2017 15:53:53 -0800 +Subject: [PATCH 008/146] arm64: dts: sun50i-a64-pine64: add HDMI audio nodes + +Signed-off-by: Vasily Khoruzhick +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +index d06b5b88f60e..8c5dd99cc9ac 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +@@ -97,6 +97,10 @@ + bias-pull-up; + }; + ++&i2s2 { ++ status = "okay"; ++}; ++ + &mdio { + ext_rmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; +@@ -254,6 +258,10 @@ + status = "disabled"; + }; + ++&sound_hdmi { ++ status = "okay"; ++}; ++ + /* On Exp and Euler connectors */ + &uart0 { + pinctrl-names = "default"; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0009-dt-bindings-update-the-Allwinner-GPADC-device-tree-b.patch b/patch/kernel/sunxi-dev/0009-dt-bindings-update-the-Allwinner-GPADC-device-tree-b.patch new file mode 100644 index 000000000..49df63b00 --- /dev/null +++ b/patch/kernel/sunxi-dev/0009-dt-bindings-update-the-Allwinner-GPADC-device-tree-b.patch @@ -0,0 +1,95 @@ +From 92e5c7876cef2b53ed3d1701169fcd93b73e0e33 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sat, 20 Jan 2018 13:25:21 +0100 +Subject: [PATCH 009/146] dt-bindings: update the Allwinner GPADC device tree + binding for H3 & A83T + +Allwinner H3 features a thermal sensor like the one in A33, but has its +register re-arranged, the clock divider moved to CCU (originally the +clock divider is in ADC) and added a pair of bus clock and reset. + +Allwinner A83T features a thermal sensor similar to the H3, the ths clock, +the bus clock and the reset was removed from the CCU. The THS in A83T +has a clock that is directly connected and runs with 24 MHz. + +Update the binding document to cover H3 and A83T. + +Signed-off-by: Philipp Rossak +--- + .../devicetree/bindings/mfd/sun4i-gpadc.txt | 50 +++++++++++++++++-- + 1 file changed, 47 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt +index 86dd8191b04c..f6b939617a6d 100644 +--- a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt ++++ b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt +@@ -4,12 +4,35 @@ The Allwinner SoCs all have an ADC that can also act as a thermal sensor + and sometimes as a touchscreen controller. + + Required properties: +- - compatible: "allwinner,sun8i-a33-ths", ++ - compatible: must contain one of the following compatibles: ++ - "allwinner,sun8i-a33-ths" ++ - "allwinner,sun8i-h3-ths" ++ - "allwinner,sun8i-a83t-ths" + - reg: mmio address range of the chip, +- - #thermal-sensor-cells: shall be 0, ++ - #thermal-sensor-cells: shall be 0 or 1, + - #io-channel-cells: shall be 0, + +-Example: ++Required properties for the following compatibles: ++ - "allwinner,sun8i-h3-ths" ++ - "allwinner,sun8i-a83t-ths" ++ - interrupts: the sampling interrupt of the ADC, ++ ++Required properties for the following compatibles: ++ - "allwinner,sun8i-h3-ths" ++ - clocks: the bus clock and the input clock of the ADC, ++ - clock-names: should be "bus" and "mod", ++ - resets: the bus reset of the ADC, ++ ++Optional properties for the following compatibles: ++ - "allwinner,sun8i-h3-ths" ++ - nvmem-cells: A phandle to the calibration data provided by a nvmem device. ++ If unspecified default values shall be used. The size should ++ be 0x4 or 0x8, depending on the amount of CDATA registers. ++ - nvmem-cell-names: Should be "calibration". ++ ++Details see: bindings/nvmem/nvmem.txt ++ ++Example for A33: + ths: ths@1c25000 { + compatible = "allwinner,sun8i-a33-ths"; + reg = <0x01c25000 0x100>; +@@ -17,6 +40,27 @@ Example: + #io-channel-cells = <0>; + }; + ++Example for H3: ++ ths: thermal-sensor@1c25000 { ++ compatible = "allwinner,sun8i-h3-ths"; ++ reg = <0x01c25000 0x400>; ++ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; ++ clock-names = "bus", "mod"; ++ resets = <&ccu RST_BUS_THS>; ++ interrupts = ; ++ #thermal-sensor-cells = <0>; ++ #io-channel-cells = <0>; ++ }; ++ ++Example for A83T: ++ ths: thermal-sensor@1f04000 { ++ compatible = "allwinner,sun8i-a83t-ths"; ++ reg = <0x01f04000 0x100>; ++ interrupts = ; ++ #thermal-sensor-cells = <1>; ++ #io-channel-cells = <0>; ++ }; ++ + sun4i, sun5i and sun6i SoCs are also supported via the older binding: + + sun4i resistive touchscreen controller +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0011-iio-adc-sun4i-gpadc-iio-rename-A33-specified-registe.patch b/patch/kernel/sunxi-dev/0011-iio-adc-sun4i-gpadc-iio-rename-A33-specified-registe.patch new file mode 100644 index 000000000..315e9fb10 --- /dev/null +++ b/patch/kernel/sunxi-dev/0011-iio-adc-sun4i-gpadc-iio-rename-A33-specified-registe.patch @@ -0,0 +1,56 @@ +From ef6a8862ab9440c5d6a73da32be83edc46e2fe94 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 14 Sep 2017 22:52:47 +0800 +Subject: [PATCH 011/146] iio: adc: sun4i-gpadc-iio: rename A33-specified + registers to contain A33 + +As the H3 SoC, which is also in sun8i line, has totally different +register map for the thermal sensor (a cut down version of GPADC), we +should rename A23/A33-specified registers to contain A33, in order to +prevent obfuscation with H3 registers. Currently these registers are +only prefixed "SUN8I", not "SUN8I_A33". + +Add "_A33" after "SUN8I" on the register names. + +Signed-off-by: Icenowy Zheng +Reviewed-by: Chen-Yu Tsai +Acked-by: Maxime Ripard +Acked-by: Lee Jones +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 2 +- + include/linux/mfd/sun4i-gpadc.h | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 04d7147e0110..03804ff9c006 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -88,7 +88,7 @@ static const struct gpadc_data sun6i_gpadc_data = { + static const struct gpadc_data sun8i_a33_gpadc_data = { + .temp_offset = -1662, + .temp_scale = 162, +- .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN, ++ .tp_mode_en = SUN8I_A33_GPADC_CTRL1_CHOP_TEMP_EN, + }; + + struct sun4i_gpadc_iio { +diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h +index 139872c2e0fe..78d31984a222 100644 +--- a/include/linux/mfd/sun4i-gpadc.h ++++ b/include/linux/mfd/sun4i-gpadc.h +@@ -38,9 +38,9 @@ + #define SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(x) (GENMASK(3, 0) & BIT(x)) + #define SUN6I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(3, 0) + +-/* TP_CTRL1 bits for sun8i SoCs */ +-#define SUN8I_GPADC_CTRL1_CHOP_TEMP_EN BIT(8) +-#define SUN8I_GPADC_CTRL1_GPADC_CALI_EN BIT(7) ++/* TP_CTRL1 bits for A33 */ ++#define SUN8I_A33_GPADC_CTRL1_CHOP_TEMP_EN BIT(8) ++#define SUN8I_A33_GPADC_CTRL1_GPADC_CALI_EN BIT(7) + + #define SUN4I_GPADC_CTRL2 0x08 + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0012-iio-adc-sun4i-gpadc-iio-rework-sampling-start-end-co.patch b/patch/kernel/sunxi-dev/0012-iio-adc-sun4i-gpadc-iio-rework-sampling-start-end-co.patch new file mode 100644 index 000000000..7f95ae2d4 --- /dev/null +++ b/patch/kernel/sunxi-dev/0012-iio-adc-sun4i-gpadc-iio-rework-sampling-start-end-co.patch @@ -0,0 +1,237 @@ +From 3de3b1512ed5905e9522a4966d238f571825ee70 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sat, 20 Jan 2018 14:03:10 +0100 +Subject: [PATCH 012/146] iio: adc: sun4i-gpadc-iio: rework: sampling start/end + code readout reg + +For adding newer sensor some basic rework of the code is necessary. + +This commit reworks the code and allows the sampling start/end code and +the position of value readout register to be altered. Later the start/end +functions will be used to configure the ths and start/stop the +sampling. + +Signed-off-by: Icenowy Zheng +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 87 ++++++++++++++++++++++++++++--- + include/linux/mfd/sun4i-gpadc.h | 19 +++++-- + 2 files changed, 94 insertions(+), 12 deletions(-) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 03804ff9c006..363936b37c5a 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -49,6 +49,18 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan) + return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan); + } + ++struct sun4i_gpadc_iio; ++ ++/* ++ * Prototypes for these functions, which enable these functions to be ++ * referenced in gpadc_data structures. ++ */ ++static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info); ++static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info); ++ ++static int sunxi_ths_sample_start(struct sun4i_gpadc_iio *info); ++static int sunxi_ths_sample_end(struct sun4i_gpadc_iio *info); ++ + struct gpadc_data { + int temp_offset; + int temp_scale; +@@ -56,6 +68,13 @@ struct gpadc_data { + unsigned int tp_adc_select; + unsigned int (*adc_chan_select)(unsigned int chan); + unsigned int adc_chan_mask; ++ unsigned int temp_data; ++ int (*sample_start)(struct sun4i_gpadc_iio *info); ++ int (*sample_end)(struct sun4i_gpadc_iio *info); ++ u32 ctrl0_map; ++ u32 ctrl2_map; ++ u32 sensor_en_map; ++ u32 filter_map; + }; + + static const struct gpadc_data sun4i_gpadc_data = { +@@ -65,6 +84,9 @@ static const struct gpadc_data sun4i_gpadc_data = { + .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, + .adc_chan_select = &sun4i_gpadc_chan_select, + .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .sample_end = sun4i_gpadc_sample_end, + }; + + static const struct gpadc_data sun5i_gpadc_data = { +@@ -74,6 +96,9 @@ static const struct gpadc_data sun5i_gpadc_data = { + .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, + .adc_chan_select = &sun4i_gpadc_chan_select, + .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .sample_end = sun4i_gpadc_sample_end, + }; + + static const struct gpadc_data sun6i_gpadc_data = { +@@ -83,12 +108,18 @@ static const struct gpadc_data sun6i_gpadc_data = { + .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, + .adc_chan_select = &sun6i_gpadc_chan_select, + .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .sample_end = sun4i_gpadc_sample_end, + }; + + static const struct gpadc_data sun8i_a33_gpadc_data = { + .temp_offset = -1662, + .temp_scale = 162, + .tp_mode_en = SUN8I_A33_GPADC_CTRL1_CHOP_TEMP_EN, ++ .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .sample_start = sun4i_gpadc_sample_start, ++ .sample_end = sun4i_gpadc_sample_end, + }; + + struct sun4i_gpadc_iio { +@@ -277,7 +308,7 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val) + if (info->no_irq) { + pm_runtime_get_sync(indio_dev->dev.parent); + +- regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); ++ regmap_read(info->regmap, info->data->temp_data, val); + + pm_runtime_mark_last_busy(indio_dev->dev.parent); + pm_runtime_put_autosuspend(indio_dev->dev.parent); +@@ -382,10 +413,8 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id) + return IRQ_HANDLED; + } + +-static int sun4i_gpadc_runtime_suspend(struct device *dev) ++static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info) + { +- struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); +- + /* Disable the ADC on IP */ + regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0); + /* Disable temperature sensor on IP */ +@@ -394,19 +423,32 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev) + return 0; + } + +-static int sun4i_gpadc_runtime_resume(struct device *dev) ++static int sunxi_ths_sample_end(struct sun4i_gpadc_iio *info) ++{ ++ /* Disable temperature sensor */ ++ regmap_write(info->regmap, SUNXI_THS_CTRL2, 0x0); ++ ++ return 0; ++} ++ ++static int sun4i_gpadc_runtime_suspend(struct device *dev) + { + struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); + ++ return info->data->sample_end(info); ++} ++ ++static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info) ++{ + /* clkin = 6MHz */ + regmap_write(info->regmap, SUN4I_GPADC_CTRL0, + SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) | + SUN4I_GPADC_CTRL0_FS_DIV(7) | +- SUN4I_GPADC_CTRL0_T_ACQ(63)); ++ SUNXI_THS_ACQ0(63)); + regmap_write(info->regmap, SUN4I_GPADC_CTRL1, info->data->tp_mode_en); + regmap_write(info->regmap, SUN4I_GPADC_CTRL3, +- SUN4I_GPADC_CTRL3_FILTER_EN | +- SUN4I_GPADC_CTRL3_FILTER_TYPE(1)); ++ SUNXI_THS_FILTER_EN | ++ SUNXI_THS_FILTER_TYPE(1)); + /* period = SUN4I_GPADC_TPR_TEMP_PERIOD * 256 * 16 / clkin; ~0.6s */ + regmap_write(info->regmap, SUN4I_GPADC_TPR, + SUN4I_GPADC_TPR_TEMP_ENABLE | +@@ -415,6 +457,35 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) + return 0; + } + ++static int sunxi_ths_sample_start(struct sun4i_gpadc_iio *info) ++{ ++ u32 value; ++ ++ if (info->data->ctrl0_map) ++ regmap_write(info->regmap, SUNXI_THS_CTRL0, ++ info->data->ctrl0_map); ++ ++ regmap_write(info->regmap, SUNXI_THS_CTRL2, ++ info->data->ctrl2_map); ++ ++ regmap_write(info->regmap, SUNXI_THS_FILTER, ++ info->data->filter_map); ++ ++ regmap_read(info->regmap, SUNXI_THS_CTRL2, &value); ++ ++ regmap_write(info->regmap, SUNXI_THS_CTRL2, ++ info->data->sensor_en_map | value); ++ ++ return 0; ++} ++ ++static int sun4i_gpadc_runtime_resume(struct device *dev) ++{ ++ struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); ++ ++ return info->data->sample_start(info); ++} ++ + static int sun4i_gpadc_get_temp(void *data, int *temp) + { + struct sun4i_gpadc_iio *info = data; +diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h +index 78d31984a222..39e096c3ddac 100644 +--- a/include/linux/mfd/sun4i-gpadc.h ++++ b/include/linux/mfd/sun4i-gpadc.h +@@ -17,7 +17,6 @@ + #define SUN4I_GPADC_CTRL0_ADC_CLK_SELECT BIT(22) + #define SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(x) ((GENMASK(1, 0) & (x)) << 20) + #define SUN4I_GPADC_CTRL0_FS_DIV(x) ((GENMASK(3, 0) & (x)) << 16) +-#define SUN4I_GPADC_CTRL0_T_ACQ(x) (GENMASK(15, 0) & (x)) + + #define SUN4I_GPADC_CTRL1 0x04 + +@@ -51,9 +50,6 @@ + + #define SUN4I_GPADC_CTRL3 0x0c + +-#define SUN4I_GPADC_CTRL3_FILTER_EN BIT(2) +-#define SUN4I_GPADC_CTRL3_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) +- + #define SUN4I_GPADC_TPR 0x18 + + #define SUN4I_GPADC_TPR_TEMP_ENABLE BIT(16) +@@ -90,6 +86,21 @@ + /* 10s delay before suspending the IP */ + #define SUN4I_GPADC_AUTOSUSPEND_DELAY 10000 + ++/* SUNXI_THS COMMON REGISTERS + DEFINES */ ++#define SUNXI_THS_CTRL0 0x00 ++#define SUNXI_THS_CTRL2 0x40 ++#define SUNXI_THS_FILTER 0x70 ++ ++#define SUNXI_THS_FILTER_EN BIT(2) ++#define SUNXI_THS_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) ++#define SUNXI_THS_ACQ0(x) (GENMASK(15, 0) & (x)) ++#define SUNXI_THS_ACQ1(x) (GENMASK(31, 16) & ((x) << 16)) ++ ++#define SUNXI_THS_TEMP_SENSE_EN0 BIT(0) ++#define SUNXI_THS_TEMP_SENSE_EN1 BIT(1) ++#define SUNXI_THS_TEMP_SENSE_EN2 BIT(2) ++#define SUNXI_THS_TEMP_SENSE_EN3 BIT(3) ++ + struct sun4i_gpadc_dev { + struct device *dev; + struct regmap *regmap; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0013-iio-adc-sun4i-gpadc-iio-rework-support-clocks-and-re.patch b/patch/kernel/sunxi-dev/0013-iio-adc-sun4i-gpadc-iio-rework-support-clocks-and-re.patch new file mode 100644 index 000000000..f58519d66 --- /dev/null +++ b/patch/kernel/sunxi-dev/0013-iio-adc-sun4i-gpadc-iio-rework-support-clocks-and-re.patch @@ -0,0 +1,168 @@ +From c2d19fecbff6a21b3ab351c7843ae27de0d10b5b Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sun, 21 Jan 2018 22:23:00 +0100 +Subject: [PATCH 013/146] iio: adc: sun4i-gpadc-iio: rework: support clocks and + reset + +For adding newer sensor some basic rework of the code is necessary. + +The SoCs after H3 has newer thermal sensor ADCs, which have two clock +inputs (bus clock and sampling clock) and a reset. The registers are +also re-arranged. + +This commit reworks the code, adds the process of the clocks and +resets. + +Signed-off-by: Philipp Rossak +Signed-off-by: Icenowy Zheng +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 80 +++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 363936b37c5a..1a80744bd472 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -22,6 +22,7 @@ + * shutdown for not being used. + */ + ++#include + #include + #include + #include +@@ -31,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -75,6 +77,9 @@ struct gpadc_data { + u32 ctrl2_map; + u32 sensor_en_map; + u32 filter_map; ++ bool has_bus_clk; ++ bool has_bus_rst; ++ bool has_mod_clk; + }; + + static const struct gpadc_data sun4i_gpadc_data = { +@@ -134,6 +139,9 @@ struct sun4i_gpadc_iio { + atomic_t ignore_temp_data_irq; + const struct gpadc_data *data; + bool no_irq; ++ struct clk *bus_clk; ++ struct clk *mod_clk; ++ struct reset_control *reset; + /* prevents concurrent reads of temperature and ADC */ + struct mutex mutex; + struct thermal_zone_device *tzd; +@@ -435,6 +443,12 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev) + { + struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); + ++ if (info->data->has_mod_clk) ++ clk_disable(info->mod_clk); ++ ++ if (info->data->has_bus_clk) ++ clk_disable(info->bus_clk); ++ + return info->data->sample_end(info); + } + +@@ -483,6 +497,12 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) + { + struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); + ++ if (info->data->has_mod_clk) ++ clk_enable(info->mod_clk); ++ ++ if (info->data->has_bus_clk) ++ clk_enable(info->bus_clk); ++ + return info->data->sample_start(info); + } + +@@ -597,10 +617,61 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, + return ret; + } + ++ if (info->data->has_bus_rst) { ++ info->reset = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(info->reset)) { ++ ret = PTR_ERR(info->reset); ++ return ret; ++ } ++ ++ ret = reset_control_deassert(info->reset); ++ if (ret) ++ return ret; ++ } ++ ++ if (info->data->has_bus_clk) { ++ info->bus_clk = devm_clk_get(&pdev->dev, "bus"); ++ if (IS_ERR(info->bus_clk)) { ++ ret = PTR_ERR(info->bus_clk); ++ goto assert_reset; ++ } ++ ++ ret = clk_prepare_enable(info->bus_clk); ++ if (ret) ++ goto assert_reset; ++ } ++ ++ if (info->data->has_mod_clk) { ++ info->mod_clk = devm_clk_get(&pdev->dev, "mod"); ++ if (IS_ERR(info->mod_clk)) { ++ ret = PTR_ERR(info->mod_clk); ++ goto disable_bus_clk; ++ } ++ ++ /* Running at 6MHz */ ++ ret = clk_set_rate(info->mod_clk, 4000000); ++ if (ret) ++ goto disable_bus_clk; ++ ++ ret = clk_prepare_enable(info->mod_clk); ++ if (ret) ++ goto disable_bus_clk; ++ } ++ + if (IS_ENABLED(CONFIG_THERMAL_OF)) + info->sensor_device = &pdev->dev; + + return 0; ++ ++disable_bus_clk: ++ if (info->data->has_bus_clk) ++ clk_disable_unprepare(info->bus_clk); ++ ++assert_reset: ++ if (info->data->has_bus_rst) ++ reset_control_assert(info->reset); ++ ++ return ret; + } + + static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, +@@ -766,6 +837,15 @@ static int sun4i_gpadc_remove(struct platform_device *pdev) + if (!info->no_irq) + iio_map_array_unregister(indio_dev); + ++ if (info->data->has_mod_clk) ++ clk_disable_unprepare(info->mod_clk); ++ ++ if (info->data->has_bus_clk) ++ clk_disable_unprepare(info->bus_clk); ++ ++ if (info->data->has_bus_rst) ++ reset_control_assert(info->reset); ++ + return 0; + } + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0014-iio-adc-sun4i-gpadc-iio-rework-support-multible-sens.patch b/patch/kernel/sunxi-dev/0014-iio-adc-sun4i-gpadc-iio-rework-support-multible-sens.patch new file mode 100644 index 000000000..d90101227 --- /dev/null +++ b/patch/kernel/sunxi-dev/0014-iio-adc-sun4i-gpadc-iio-rework-support-multible-sens.patch @@ -0,0 +1,186 @@ +From e684b6faf4b5509f852867cac4830a0274f89211 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sun, 21 Jan 2018 22:26:50 +0100 +Subject: [PATCH 014/146] iio: adc: sun4i-gpadc-iio: rework: support multible + sensors + +For adding newer sensor some basic rework of the code is necessary. + +This patch reworks the driver to be able to handle more than one +thermal sensor. Newer SoC like the A80 have 4 thermal sensors. +Because of this the maximal sensor count value was set to 4. + +The sensor_id value is set during sensor registration and is for each +registered sensor indiviual. This makes it able to differntiate the +sensors when the value is read from the register. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 36 ++++++++++++++++++++----------- + include/linux/mfd/sun4i-gpadc.h | 6 ++++++ + 2 files changed, 29 insertions(+), 13 deletions(-) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 1a80744bd472..bff06f2798e8 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -70,7 +70,7 @@ struct gpadc_data { + unsigned int tp_adc_select; + unsigned int (*adc_chan_select)(unsigned int chan); + unsigned int adc_chan_mask; +- unsigned int temp_data; ++ unsigned int temp_data[MAX_SENSOR_COUNT]; + int (*sample_start)(struct sun4i_gpadc_iio *info); + int (*sample_end)(struct sun4i_gpadc_iio *info); + u32 ctrl0_map; +@@ -80,6 +80,7 @@ struct gpadc_data { + bool has_bus_clk; + bool has_bus_rst; + bool has_mod_clk; ++ int sensor_count; + }; + + static const struct gpadc_data sun4i_gpadc_data = { +@@ -89,9 +90,10 @@ static const struct gpadc_data sun4i_gpadc_data = { + .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, + .adc_chan_select = &sun4i_gpadc_chan_select, + .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, +- .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .temp_data = {SUN4I_GPADC_TEMP_DATA, 0, 0, 0}, + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, ++ .sensor_count = 1, + }; + + static const struct gpadc_data sun5i_gpadc_data = { +@@ -101,9 +103,10 @@ static const struct gpadc_data sun5i_gpadc_data = { + .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, + .adc_chan_select = &sun4i_gpadc_chan_select, + .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, +- .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .temp_data = {SUN4I_GPADC_TEMP_DATA, 0, 0, 0}, + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, ++ .sensor_count = 1, + }; + + static const struct gpadc_data sun6i_gpadc_data = { +@@ -113,18 +116,20 @@ static const struct gpadc_data sun6i_gpadc_data = { + .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, + .adc_chan_select = &sun6i_gpadc_chan_select, + .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, +- .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .temp_data = {SUN4I_GPADC_TEMP_DATA, 0, 0, 0}, + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, ++ .sensor_count = 1, + }; + + static const struct gpadc_data sun8i_a33_gpadc_data = { + .temp_offset = -1662, + .temp_scale = 162, + .tp_mode_en = SUN8I_A33_GPADC_CTRL1_CHOP_TEMP_EN, +- .temp_data = SUN4I_GPADC_TEMP_DATA, ++ .temp_data = {SUN4I_GPADC_TEMP_DATA, 0, 0, 0}, + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, ++ .sensor_count = 1, + }; + + struct sun4i_gpadc_iio { +@@ -142,6 +147,7 @@ struct sun4i_gpadc_iio { + struct clk *bus_clk; + struct clk *mod_clk; + struct reset_control *reset; ++ int sensor_id; + /* prevents concurrent reads of temperature and ADC */ + struct mutex mutex; + struct thermal_zone_device *tzd; +@@ -309,14 +315,15 @@ static int sun4i_gpadc_adc_read(struct iio_dev *indio_dev, int channel, + return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq); + } + +-static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val) ++static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val, ++ int sensor) + { + struct sun4i_gpadc_iio *info = iio_priv(indio_dev); + + if (info->no_irq) { + pm_runtime_get_sync(indio_dev->dev.parent); + +- regmap_read(info->regmap, info->data->temp_data, val); ++ regmap_read(info->regmap, info->data->temp_data[sensor], val); + + pm_runtime_mark_last_busy(indio_dev->dev.parent); + pm_runtime_put_autosuspend(indio_dev->dev.parent); +@@ -363,7 +370,7 @@ static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev, + ret = sun4i_gpadc_adc_read(indio_dev, chan->channel, + val); + else +- ret = sun4i_gpadc_temp_read(indio_dev, val); ++ ret = sun4i_gpadc_temp_read(indio_dev, val, 0); + + if (ret) + return ret; +@@ -511,7 +518,7 @@ static int sun4i_gpadc_get_temp(void *data, int *temp) + struct sun4i_gpadc_iio *info = data; + int val, scale, offset; + +- if (sun4i_gpadc_temp_read(info->indio_dev, &val)) ++ if (sun4i_gpadc_temp_read(info->indio_dev, &val, info->sensor_id)) + return -ETIMEDOUT; + + sun4i_gpadc_temp_scale(info->indio_dev, &scale); +@@ -755,7 +762,7 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) + { + struct sun4i_gpadc_iio *info; + struct iio_dev *indio_dev; +- int ret; ++ int ret, i; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); + if (!indio_dev) +@@ -788,9 +795,12 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + + if (IS_ENABLED(CONFIG_THERMAL_OF)) { +- info->tzd = thermal_zone_of_sensor_register(info->sensor_device, +- 0, info, +- &sun4i_ts_tz_ops); ++ for (i = 0; i < info->data->sensor_count; i++) { ++ info->sensor_id = i; ++ info->tzd = thermal_zone_of_sensor_register( ++ info->sensor_device, ++ i, info, &sun4i_ts_tz_ops); ++ } + /* + * Do not fail driver probing when failing to register in + * thermal because no thermal DT node is found. +diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h +index 39e096c3ddac..40b4dd9d2405 100644 +--- a/include/linux/mfd/sun4i-gpadc.h ++++ b/include/linux/mfd/sun4i-gpadc.h +@@ -90,6 +90,10 @@ + #define SUNXI_THS_CTRL0 0x00 + #define SUNXI_THS_CTRL2 0x40 + #define SUNXI_THS_FILTER 0x70 ++#define SUNXI_THS_TDATA0 0x80 ++#define SUNXI_THS_TDATA1 0x84 ++#define SUNXI_THS_TDATA2 0x88 ++#define SUNXI_THS_TDATA3 0x8c + + #define SUNXI_THS_FILTER_EN BIT(2) + #define SUNXI_THS_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) +@@ -101,6 +105,8 @@ + #define SUNXI_THS_TEMP_SENSE_EN2 BIT(2) + #define SUNXI_THS_TEMP_SENSE_EN3 BIT(3) + ++#define MAX_SENSOR_COUNT 4 ++ + struct sun4i_gpadc_dev { + struct device *dev; + struct regmap *regmap; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0015-iio-adc-sun4i-gpadc-iio-rework-support-nvmem-calibra.patch b/patch/kernel/sunxi-dev/0015-iio-adc-sun4i-gpadc-iio-rework-support-nvmem-calibra.patch new file mode 100644 index 000000000..edb2eb8fc --- /dev/null +++ b/patch/kernel/sunxi-dev/0015-iio-adc-sun4i-gpadc-iio-rework-support-nvmem-calibra.patch @@ -0,0 +1,166 @@ +From 9bb64076c49cf41aaa252ce7b5aa24b93c322bd5 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sun, 21 Jan 2018 22:29:55 +0100 +Subject: [PATCH 015/146] iio: adc: sun4i-gpadc-iio: rework: support nvmem + calibration data + +This patch reworks the driver to support nvmem calibration cells. +The driver checks if the nvmem calibration is supported and reads out +the nvmem. At the beginning of the startup process the calibration data +is written to the related registers. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 52 +++++++++++++++++++++++++++++++ + include/linux/mfd/sun4i-gpadc.h | 2 ++ + 2 files changed, 54 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index bff06f2798e8..7b12666cdd9e 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -81,6 +82,7 @@ struct gpadc_data { + bool has_bus_rst; + bool has_mod_clk; + int sensor_count; ++ bool supports_nvmem; + }; + + static const struct gpadc_data sun4i_gpadc_data = { +@@ -94,6 +96,7 @@ static const struct gpadc_data sun4i_gpadc_data = { + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, ++ .supports_nvmem = false, + }; + + static const struct gpadc_data sun5i_gpadc_data = { +@@ -107,6 +110,7 @@ static const struct gpadc_data sun5i_gpadc_data = { + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, ++ .supports_nvmem = false, + }; + + static const struct gpadc_data sun6i_gpadc_data = { +@@ -120,6 +124,7 @@ static const struct gpadc_data sun6i_gpadc_data = { + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, ++ .supports_nvmem = false, + }; + + static const struct gpadc_data sun8i_a33_gpadc_data = { +@@ -130,6 +135,7 @@ static const struct gpadc_data sun8i_a33_gpadc_data = { + .sample_start = sun4i_gpadc_sample_start, + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, ++ .supports_nvmem = false, + }; + + struct sun4i_gpadc_iio { +@@ -148,6 +154,8 @@ struct sun4i_gpadc_iio { + struct clk *mod_clk; + struct reset_control *reset; + int sensor_id; ++ u32 calibration_data[2]; ++ bool has_calibration_data[2]; + /* prevents concurrent reads of temperature and ADC */ + struct mutex mutex; + struct thermal_zone_device *tzd; +@@ -459,6 +467,17 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev) + return info->data->sample_end(info); + } + ++static void sunxi_calibrate(struct sun4i_gpadc_iio *info) ++{ ++ if (info->has_calibration_data[0]) ++ regmap_write(info->regmap, SUNXI_THS_CDATA_0_1, ++ info->calibration_data[0]); ++ ++ if (info->has_calibration_data[1]) ++ regmap_write(info->regmap, SUNXI_THS_CDATA_2_3, ++ info->calibration_data[1]); ++} ++ + static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info) + { + /* clkin = 6MHz */ +@@ -481,6 +500,7 @@ static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info) + static int sunxi_ths_sample_start(struct sun4i_gpadc_iio *info) + { + u32 value; ++ sunxi_calibrate(info); + + if (info->data->ctrl0_map) + regmap_write(info->regmap, SUNXI_THS_CTRL0, +@@ -602,6 +622,9 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, + struct resource *mem; + void __iomem *base; + int ret; ++ struct nvmem_cell *cell; ++ ssize_t cell_size; ++ u64 *cell_data; + + info->data = of_device_get_match_data(&pdev->dev); + if (!info->data) +@@ -616,6 +639,35 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, + if (IS_ERR(base)) + return PTR_ERR(base); + ++ info->has_calibration_data[0] = false; ++ info->has_calibration_data[1] = false; ++ ++ if (!info->data->supports_nvmem) ++ goto no_nvmem; ++ ++ cell = devm_nvmem_cell_get(&pdev->dev, "calibration"); ++ if (IS_ERR(cell)) { ++ if (PTR_ERR(cell) == -EPROBE_DEFER) ++ return PTR_ERR(cell); ++ } else { ++ cell_data = (u64 *)nvmem_cell_read(cell, &cell_size); ++ devm_nvmem_cell_put(&pdev->dev, cell); ++ if (cell_size <= 4) { ++ info->has_calibration_data[0] = true; ++ info->calibration_data[0] = be32_to_cpu(cell_data[0] & ++ GENMASK(31, 0)); ++ } else if (cell_size <= 8) { ++ info->has_calibration_data[0] = true; ++ info->calibration_data[0] = be32_to_cpu(cell_data[0] & ++ GENMASK(31, 0)); ++ info->has_calibration_data[1] = true; ++ info->calibration_data[1] = be32_to_cpu( ++ (cell_data[0] >> 32) & GENMASK(31, 0)); ++ } ++ } ++ ++no_nvmem: ++ + info->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sun4i_gpadc_regmap_config); + if (IS_ERR(info->regmap)) { +diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h +index 40b4dd9d2405..c251002431bd 100644 +--- a/include/linux/mfd/sun4i-gpadc.h ++++ b/include/linux/mfd/sun4i-gpadc.h +@@ -90,6 +90,8 @@ + #define SUNXI_THS_CTRL0 0x00 + #define SUNXI_THS_CTRL2 0x40 + #define SUNXI_THS_FILTER 0x70 ++#define SUNXI_THS_CDATA_0_1 0x74 ++#define SUNXI_THS_CDATA_2_3 0x78 + #define SUNXI_THS_TDATA0 0x80 + #define SUNXI_THS_TDATA1 0x84 + #define SUNXI_THS_TDATA2 0x88 +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0016-iio-adc-sun4i-gpadc-iio-rework-add-interrupt-support.patch b/patch/kernel/sunxi-dev/0016-iio-adc-sun4i-gpadc-iio-rework-add-interrupt-support.patch new file mode 100644 index 000000000..93f26e9be --- /dev/null +++ b/patch/kernel/sunxi-dev/0016-iio-adc-sun4i-gpadc-iio-rework-add-interrupt-support.patch @@ -0,0 +1,253 @@ +From 153c005037601e2ba02f7fb36d8864194d8c98c8 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sun, 21 Jan 2018 11:20:55 +0100 +Subject: [PATCH 016/146] iio: adc: sun4i-gpadc-iio: rework: add interrupt + support + +This patch rewors the driver to support interrupts for the thermal part +of the sensor. + +This is only available for the newer sensor (currently H3 and A83T). +The interrupt will be trigerd on data available and triggers the update +for the thermal sensors. All newer sensors have different amount of +sensors and different interrupts for each device the reset of the +interrupts need to be done different + +For the newer sensors is the autosuspend disabled. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 68 ++++++++++++++++++++++++++++--- + include/linux/mfd/sun4i-gpadc.h | 33 +++++++++++++++ + 2 files changed, 95 insertions(+), 6 deletions(-) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 7b12666cdd9e..77e07f042730 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -78,11 +78,14 @@ struct gpadc_data { + u32 ctrl2_map; + u32 sensor_en_map; + u32 filter_map; ++ u32 irq_clear_map; ++ u32 irq_control_map; + bool has_bus_clk; + bool has_bus_rst; + bool has_mod_clk; + int sensor_count; + bool supports_nvmem; ++ bool support_irq; + }; + + static const struct gpadc_data sun4i_gpadc_data = { +@@ -97,6 +100,7 @@ static const struct gpadc_data sun4i_gpadc_data = { + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, + .supports_nvmem = false, ++ .support_irq = false, + }; + + static const struct gpadc_data sun5i_gpadc_data = { +@@ -111,6 +115,7 @@ static const struct gpadc_data sun5i_gpadc_data = { + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, + .supports_nvmem = false, ++ .support_irq = false, + }; + + static const struct gpadc_data sun6i_gpadc_data = { +@@ -125,6 +130,7 @@ static const struct gpadc_data sun6i_gpadc_data = { + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, + .supports_nvmem = false, ++ .support_irq = false, + }; + + static const struct gpadc_data sun8i_a33_gpadc_data = { +@@ -136,6 +142,7 @@ static const struct gpadc_data sun8i_a33_gpadc_data = { + .sample_end = sun4i_gpadc_sample_end, + .sensor_count = 1, + .supports_nvmem = false, ++ .support_irq = false, + }; + + struct sun4i_gpadc_iio { +@@ -339,6 +346,11 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val, + return 0; + } + ++ if (info->data->support_irq) { ++ regmap_read(info->regmap, info->data->temp_data[sensor], val); ++ return 0; ++ } ++ + return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq); + } + +@@ -436,6 +448,17 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static irqreturn_t sunxi_irq_thread(int irq, void *data) ++{ ++ struct sun4i_gpadc_iio *info = data; ++ ++ regmap_write(info->regmap, SUNXI_THS_STAT, info->data->irq_clear_map); ++ ++ thermal_zone_device_update(info->tzd, THERMAL_EVENT_TEMP_SAMPLE); ++ ++ return IRQ_HANDLED; ++} ++ + static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info) + { + /* Disable the ADC on IP */ +@@ -448,6 +471,8 @@ static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info) + + static int sunxi_ths_sample_end(struct sun4i_gpadc_iio *info) + { ++ /* Disable ths interrupt*/ ++ regmap_write(info->regmap, SUNXI_THS_INTC, 0x0); + /* Disable temperature sensor */ + regmap_write(info->regmap, SUNXI_THS_CTRL2, 0x0); + +@@ -509,9 +534,15 @@ static int sunxi_ths_sample_start(struct sun4i_gpadc_iio *info) + regmap_write(info->regmap, SUNXI_THS_CTRL2, + info->data->ctrl2_map); + ++ regmap_write(info->regmap, SUNXI_THS_STAT, ++ info->data->irq_clear_map); ++ + regmap_write(info->regmap, SUNXI_THS_FILTER, + info->data->filter_map); + ++ regmap_write(info->regmap, SUNXI_THS_INTC, ++ info->data->irq_control_map); ++ + regmap_read(info->regmap, SUNXI_THS_CTRL2, &value); + + regmap_write(info->regmap, SUNXI_THS_CTRL2, +@@ -625,12 +656,29 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, + struct nvmem_cell *cell; + ssize_t cell_size; + u64 *cell_data; ++ int irq; + + info->data = of_device_get_match_data(&pdev->dev); + if (!info->data) + return -ENODEV; + +- info->no_irq = true; ++ if (info->data->support_irq) { ++ /* only the new versions of ths support right now irqs */ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get IRQ: %d\n", irq); ++ return irq; ++ } ++ ++ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, ++ sunxi_irq_thread, IRQF_ONESHOT, ++ dev_name(&pdev->dev), info); ++ if (ret) ++ return ret; ++ ++ } else ++ info->no_irq = true; ++ + indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels); + indio_dev->channels = sun8i_a33_gpadc_channels; + +@@ -840,11 +888,13 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) + if (ret) + return ret; + +- pm_runtime_set_autosuspend_delay(&pdev->dev, +- SUN4I_GPADC_AUTOSUSPEND_DELAY); +- pm_runtime_use_autosuspend(&pdev->dev); +- pm_runtime_set_suspended(&pdev->dev); +- pm_runtime_enable(&pdev->dev); ++ if (!info->data->support_irq) { ++ pm_runtime_set_autosuspend_delay(&pdev->dev, ++ SUN4I_GPADC_AUTOSUSPEND_DELAY); ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_runtime_set_suspended(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); ++ } + + if (IS_ENABLED(CONFIG_THERMAL_OF)) { + for (i = 0; i < info->data->sensor_count; i++) { +@@ -865,6 +915,9 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) + } + } + ++ if (info->data->support_irq) ++ info->data->sample_start(info); ++ + ret = devm_iio_device_register(&pdev->dev, indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "could not register the device\n"); +@@ -894,6 +947,9 @@ static int sun4i_gpadc_remove(struct platform_device *pdev) + if (!IS_ENABLED(CONFIG_THERMAL_OF)) + return 0; + ++ if (info->data->support_irq) ++ info->data->sample_end(info); ++ + thermal_zone_of_sensor_unregister(info->sensor_device, info->tzd); + + if (!info->no_irq) +diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h +index c251002431bd..ab34a96a7ff3 100644 +--- a/include/linux/mfd/sun4i-gpadc.h ++++ b/include/linux/mfd/sun4i-gpadc.h +@@ -89,6 +89,8 @@ + /* SUNXI_THS COMMON REGISTERS + DEFINES */ + #define SUNXI_THS_CTRL0 0x00 + #define SUNXI_THS_CTRL2 0x40 ++#define SUNXI_THS_INTC 0x44 ++#define SUNXI_THS_STAT 0x48 + #define SUNXI_THS_FILTER 0x70 + #define SUNXI_THS_CDATA_0_1 0x74 + #define SUNXI_THS_CDATA_2_3 0x78 +@@ -107,6 +109,37 @@ + #define SUNXI_THS_TEMP_SENSE_EN2 BIT(2) + #define SUNXI_THS_TEMP_SENSE_EN3 BIT(3) + ++#define SUNXI_THS_TEMP_PERIOD(x) (GENMASK(31, 12) & ((x) << 12)) ++ ++#define SUNXI_THS_INTS_ALARM_OFF_2 BIT(14) ++#define SUNXI_THS_INTS_ALARM_OFF_1 BIT(13) ++#define SUNXI_THS_INTS_ALARM_OFF_0 BIT(12) ++#define SUNXI_THS_INTS_TDATA_IRQ_3 BIT(11) ++#define SUNXI_THS_INTS_TDATA_IRQ_2 BIT(10) ++#define SUNXI_THS_INTS_TDATA_IRQ_1 BIT(9) ++#define SUNXI_THS_INTS_TDATA_IRQ_0 BIT(8) ++#define SUNXI_THS_INTS_SHUT_INT_3 BIT(7) ++#define SUNXI_THS_INTS_SHUT_INT_2 BIT(6) ++#define SUNXI_THS_INTS_SHUT_INT_1 BIT(5) ++#define SUNXI_THS_INTS_SHUT_INT_0 BIT(4) ++#define SUNXI_THS_INTS_ALARM_INT_3 BIT(3) ++#define SUNXI_THS_INTS_ALARM_INT_2 BIT(2) ++#define SUNXI_THS_INTS_ALARM_INT_1 BIT(1) ++#define SUNXI_THS_INTS_ALARM_INT_0 BIT(0) ++ ++#define SUNXI_THS_INTC_TDATA_IRQ_EN3 BIT(11) ++#define SUNXI_THS_INTC_TDATA_IRQ_EN2 BIT(10) ++#define SUNXI_THS_INTC_TDATA_IRQ_EN1 BIT(9) ++#define SUNXI_THS_INTC_TDATA_IRQ_EN0 BIT(8) ++#define SUNXI_THS_INTC_SHUT_INT_EN3 BIT(7) ++#define SUNXI_THS_INTC_SHUT_INT_EN2 BIT(6) ++#define SUNXI_THS_INTC_SHUT_INT_EN1 BIT(5) ++#define SUNXI_THS_INTC_SHUT_INT_EN0 BIT(4) ++#define SUNXI_THS_INTC_ALARM_INT_EN3 BIT(3) ++#define SUNXI_THS_INTC_ALARM_INT_EN2 BIT(2) ++#define SUNXI_THS_INTC_ALARM_INT_EN1 BIT(1) ++#define SUNXI_THS_INTC_ALARM_INT_EN0 BIT(0) ++ + #define MAX_SENSOR_COUNT 4 + + struct sun4i_gpadc_dev { +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0017-iio-adc-sun4i-gpadc-iio-add-support-for-H3-thermal-s.patch b/patch/kernel/sunxi-dev/0017-iio-adc-sun4i-gpadc-iio-add-support-for-H3-thermal-s.patch new file mode 100644 index 000000000..5c1e56444 --- /dev/null +++ b/patch/kernel/sunxi-dev/0017-iio-adc-sun4i-gpadc-iio-add-support-for-H3-thermal-s.patch @@ -0,0 +1,67 @@ +From 1968a84bd7cfdf60b29a154e682c4239bdfe6cb7 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sun, 21 Jan 2018 23:14:09 +0100 +Subject: [PATCH 017/146] iio: adc: sun4i-gpadc-iio: add support for H3 thermal + sensor + +This patch adds support for the H3 ths sensor. + +The H3 supports interrupts. The interrupt is configured to update the +the sensor values every second. The calibration data is writen at the +begin of the init process. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 77e07f042730..f2e0ec65c53e 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -145,6 +145,31 @@ static const struct gpadc_data sun8i_a33_gpadc_data = { + .support_irq = false, + }; + ++static const struct gpadc_data sun8i_h3_ths_data = { ++ .temp_offset = -1791, ++ .temp_scale = -121, ++ .temp_data = {SUNXI_THS_TDATA0, 0, 0, 0}, ++ .sample_start = sunxi_ths_sample_start, ++ .sample_end = sunxi_ths_sample_end, ++ .has_bus_clk = true, ++ .has_bus_rst = true, ++ .has_mod_clk = true, ++ .sensor_count = 1, ++ .supports_nvmem = true, ++ .support_irq = true, ++ .ctrl0_map = SUNXI_THS_ACQ0(0xff), ++ .ctrl2_map = SUNXI_THS_ACQ1(0x3f), ++ .sensor_en_map = SUNXI_THS_TEMP_SENSE_EN0, ++ .filter_map = SUNXI_THS_FILTER_EN | ++ SUNXI_THS_FILTER_TYPE(0x2), ++ .irq_clear_map = SUNXI_THS_INTS_ALARM_INT_0 | ++ SUNXI_THS_INTS_SHUT_INT_0 | ++ SUNXI_THS_INTS_TDATA_IRQ_0 | ++ SUNXI_THS_INTS_ALARM_OFF_0, ++ .irq_control_map = SUNXI_THS_INTC_TDATA_IRQ_EN0 | ++ SUNXI_THS_TEMP_PERIOD(0x7), ++}; ++ + struct sun4i_gpadc_iio { + struct iio_dev *indio_dev; + struct completion completion; +@@ -643,6 +668,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { + .compatible = "allwinner,sun8i-a33-ths", + .data = &sun8i_a33_gpadc_data, + }, ++ { ++ .compatible = "allwinner,sun8i-h3-ths", ++ .data = &sun8i_h3_ths_data, ++ }, + { /* sentinel */ } + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0018-iio-adc-sun4i-gpadc-iio-add-support-for-A83T-thermal.patch b/patch/kernel/sunxi-dev/0018-iio-adc-sun4i-gpadc-iio-add-support-for-A83T-thermal.patch new file mode 100644 index 000000000..7e3d6cf33 --- /dev/null +++ b/patch/kernel/sunxi-dev/0018-iio-adc-sun4i-gpadc-iio-add-support-for-A83T-thermal.patch @@ -0,0 +1,75 @@ +From 20484f59a26747db157563c9ba13767c21b48efb Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sun, 21 Jan 2018 18:50:11 +0100 +Subject: [PATCH 018/146] iio: adc: sun4i-gpadc-iio: add support for A83T + thermal sensor + +This patch adds support for the A83T ths sensor. + +The A83T does not support interrupts. This seems to be broken. +The calibration data is writen at the begin of the init process. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 38 +++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index f2e0ec65c53e..b8693afcdbea 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -170,6 +170,40 @@ static const struct gpadc_data sun8i_h3_ths_data = { + SUNXI_THS_TEMP_PERIOD(0x7), + }; + ++static const struct gpadc_data sun8i_a83t_ths_data = { ++ .temp_offset = -2724, ++ .temp_scale = -70, ++ .temp_data = {SUNXI_THS_TDATA0, ++ SUNXI_THS_TDATA1, ++ SUNXI_THS_TDATA2, ++ 0}, ++ .sample_start = sunxi_ths_sample_start, ++ .sample_end = sunxi_ths_sample_end, ++ .sensor_count = 3, ++ .supports_nvmem = false, ++ .support_irq = true, ++ .ctrl0_map = SUNXI_THS_ACQ0(0x1f3), ++ .ctrl2_map = SUNXI_THS_ACQ1(0x1f3), ++ .sensor_en_map = SUNXI_THS_TEMP_SENSE_EN0 | ++ SUNXI_THS_TEMP_SENSE_EN1 | ++ SUNXI_THS_TEMP_SENSE_EN2, ++ .filter_map = SUNXI_THS_FILTER_EN | ++ SUNXI_THS_FILTER_TYPE(0x2), ++ .irq_clear_map = SUNXI_THS_INTS_ALARM_INT_0 | ++ SUNXI_THS_INTS_ALARM_INT_1 | ++ SUNXI_THS_INTS_ALARM_INT_2 | ++ SUNXI_THS_INTS_SHUT_INT_0 | ++ SUNXI_THS_INTS_SHUT_INT_1 | ++ SUNXI_THS_INTS_SHUT_INT_2 | ++ SUNXI_THS_INTS_TDATA_IRQ_0 | ++ SUNXI_THS_INTS_TDATA_IRQ_1 | ++ SUNXI_THS_INTS_TDATA_IRQ_2, ++ .irq_control_map = SUNXI_THS_INTC_TDATA_IRQ_EN0 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN1 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN2 | ++ SUNXI_THS_TEMP_PERIOD(0x257), ++}; ++ + struct sun4i_gpadc_iio { + struct iio_dev *indio_dev; + struct completion completion; +@@ -672,6 +706,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { + .compatible = "allwinner,sun8i-h3-ths", + .data = &sun8i_h3_ths_data, + }, ++ { ++ .compatible = "allwinner,sun8i-a83t-ths", ++ .data = &sun8i_a83t_ths_data, ++ }, + { /* sentinel */ } + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0019-arm-dts-sunxi-h3-h5-add-support-for-the-thermal-sens.patch b/patch/kernel/sunxi-dev/0019-arm-dts-sunxi-h3-h5-add-support-for-the-thermal-sens.patch new file mode 100644 index 000000000..9133319ea --- /dev/null +++ b/patch/kernel/sunxi-dev/0019-arm-dts-sunxi-h3-h5-add-support-for-the-thermal-sens.patch @@ -0,0 +1,39 @@ +From f1b96d20375eb192d017999740c0055f2efbf576 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Fri, 26 Jan 2018 01:01:34 +0100 +Subject: [PATCH 019/146] arm: dts: sunxi-h3-h5: add support for the thermal + sensor in H3 and H5 + +As we have gained the support for the thermal sensor in H3 and H5, +we can now add its device nodes to the device tree. The H3 and H5 share +most of its compatible. The compatible and the thermal sensor cells +will be added in an additional patch per device. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sunxi-h3-h5.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi +index fc6131315c47..8fde0f6c16e4 100644 +--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi ++++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi +@@ -488,6 +488,15 @@ + }; + }; + ++ ths: thermal-sensor@1c25000 { ++ reg = <0x01c25000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; ++ clock-names = "bus", "mod"; ++ resets = <&ccu RST_BUS_THS>; ++ #io-channel-cells = <0>; ++ }; ++ + timer@1c20c00 { + compatible = "allwinner,sun4i-a10-timer"; + reg = <0x01c20c00 0xa0>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0020-arm-dts-sun8i-h3-add-support-for-the-thermal-sensor-.patch b/patch/kernel/sunxi-dev/0020-arm-dts-sun8i-h3-add-support-for-the-thermal-sensor-.patch new file mode 100644 index 000000000..41e22f639 --- /dev/null +++ b/patch/kernel/sunxi-dev/0020-arm-dts-sun8i-h3-add-support-for-the-thermal-sensor-.patch @@ -0,0 +1,30 @@ +From e475b475fbab608b805a57c8cc083e7b3da77954 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Fri, 26 Jan 2018 01:07:15 +0100 +Subject: [PATCH 020/146] arm: dts: sun8i: h3: add support for the thermal + sensor in H3 + +This patch adds the missing compatible and the thermal sensor cells. +The H3 has one sensor. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sun8i-h3.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi +index f0096074a467..5907b54b6e1d 100644 +--- a/arch/arm/boot/dts/sun8i-h3.dtsi ++++ b/arch/arm/boot/dts/sun8i-h3.dtsi +@@ -216,3 +216,8 @@ + &pio { + compatible = "allwinner,sun8i-h3-pinctrl"; + }; ++ ++&ths { ++ compatible = "allwinner,sun8i-h3-ths"; ++ #thermal-sensor-cells = <0>; ++}; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0021-arm-dts-sun8i-h3-add-thermal-zone-to-H3.patch b/patch/kernel/sunxi-dev/0021-arm-dts-sun8i-h3-add-thermal-zone-to-H3.patch new file mode 100644 index 000000000..fb9e8788f --- /dev/null +++ b/patch/kernel/sunxi-dev/0021-arm-dts-sun8i-h3-add-thermal-zone-to-H3.patch @@ -0,0 +1,36 @@ +From 16346f511d19e20e12041076f402606b87de0b56 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Fri, 26 Jan 2018 01:10:12 +0100 +Subject: [PATCH 021/146] arm: dts: sun8i: h3: add thermal zone to H3 + +This patch adds the thermal zones to the H3. We have only one sensor and +that is placed in the cpu. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sun8i-h3.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi +index 5907b54b6e1d..d2c85be8a2d0 100644 +--- a/arch/arm/boot/dts/sun8i-h3.dtsi ++++ b/arch/arm/boot/dts/sun8i-h3.dtsi +@@ -111,6 +111,15 @@ + }; + }; + ++ thermal-zones { ++ cpu-thermal { ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 0>; ++ }; ++ }; ++ + timer { + compatible = "arm,armv7-timer"; + interrupts = , +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0022-arm-dts-sun8i-h3-enable-H3-sid-controller.patch.disabled b/patch/kernel/sunxi-dev/0022-arm-dts-sun8i-h3-enable-H3-sid-controller.patch.disabled new file mode 100644 index 000000000..0994d30f1 --- /dev/null +++ b/patch/kernel/sunxi-dev/0022-arm-dts-sun8i-h3-enable-H3-sid-controller.patch.disabled @@ -0,0 +1,34 @@ +From 328b1316b4a89f2bf9e451f3cfa41d591962c44e Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Tue, 23 Jan 2018 10:57:37 +0100 +Subject: [PATCH 022/146] arm: dts: sun8i: h3: enable H3 sid controller + +This patch enables the the sid controller in the H3. It can be used +for thermal calibration data. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sun8i-h3.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi +index d2c85be8a2d0..791a9406c671 100644 +--- a/arch/arm/boot/dts/sun8i-h3.dtsi ++++ b/arch/arm/boot/dts/sun8i-h3.dtsi +@@ -111,6 +111,13 @@ + }; + }; + ++ soc { ++ sid: eeprom@1c14000 { ++ compatible = "allwinner,sun8i-h3-sid"; ++ reg = <0x01c14000 0x400>; ++ }; ++ }; ++ + thermal-zones { + cpu-thermal { + /* milliseconds */ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0023-arm-dts-sun8i-a83t-add-support-for-the-thermal-senso.patch.disabled b/patch/kernel/sunxi-dev/0023-arm-dts-sun8i-a83t-add-support-for-the-thermal-senso.patch.disabled new file mode 100644 index 000000000..b42bb8e58 --- /dev/null +++ b/patch/kernel/sunxi-dev/0023-arm-dts-sun8i-a83t-add-support-for-the-thermal-senso.patch.disabled @@ -0,0 +1,38 @@ +From 4d9df1fab6b1601612b7b4380f83d3c4560c671e Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Fri, 26 Jan 2018 01:15:17 +0100 +Subject: [PATCH 023/146] arm: dts: sun8i: a83t: add support for the thermal + sensor in A83T + +As we have gained the support for the thermal sensor in A83T, +we can now add its device nodes to the device tree. + +The A83T seems to have a broken IRQ 31, thus we use here IRQ 41. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sun8i-a83t.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi +index 00a02b037320..6bdfcc7a1ac3 100644 +--- a/arch/arm/boot/dts/sun8i-a83t.dtsi ++++ b/arch/arm/boot/dts/sun8i-a83t.dtsi +@@ -757,6 +757,14 @@ + clocks = <&osc24M>; + }; + ++ ths: thermal-sensor@1f04000 { ++ compatible = "allwinner,sun8i-a83t-ths"; ++ reg = <0x01f04000 0x100>; ++ interrupts = ; ++ #thermal-sensor-cells = <1>; ++ #io-channel-cells = <0>; ++ }; ++ + watchdog@1c20ca0 { + compatible = "allwinner,sun6i-a31-wdt"; + reg = <0x01c20ca0 0x20>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0024-arm-dts-sun8i-a83t-add-thermal-zone-to-A83T.patch.disabled b/patch/kernel/sunxi-dev/0024-arm-dts-sun8i-a83t-add-thermal-zone-to-A83T.patch.disabled new file mode 100644 index 000000000..4d835f752 --- /dev/null +++ b/patch/kernel/sunxi-dev/0024-arm-dts-sun8i-a83t-add-thermal-zone-to-A83T.patch.disabled @@ -0,0 +1,46 @@ +From 5bcffafbbcc98a66101d02d37ba6beca3f52068e Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Fri, 26 Jan 2018 01:17:14 +0100 +Subject: [PATCH 024/146] arm: dts: sun8i: a83t: add thermal zone to A83T + +This patch adds the thermal zones to the A83T. Sensor 0 is located in the +cpu cluster 0. Sensor 1 is located in cluster 1 and Sensor 3 is located +in the gpu. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sun8i-a83t.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi +index 6bdfcc7a1ac3..ec22157419b6 100644 +--- a/arch/arm/boot/dts/sun8i-a83t.dtsi ++++ b/arch/arm/boot/dts/sun8i-a83t.dtsi +@@ -1033,4 +1033,24 @@ + #size-cells = <0>; + }; + }; ++ ++ thermal-zones { ++ cpu0_thermal: cpu0-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ thermal-sensors = <&ths 0>; ++ }; ++ ++ cpu1_thermal: cpu1-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ thermal-sensors = <&ths 1>; ++ }; ++ ++ gpu_thermal: gpu-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ thermal-sensors = <&ths 2>; ++ }; ++ }; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0026-iio-adc-Kconfig-enable-A80-A64-and-H5-for-THS.patch b/patch/kernel/sunxi-dev/0026-iio-adc-Kconfig-enable-A80-A64-and-H5-for-THS.patch new file mode 100644 index 000000000..f4b3591e8 --- /dev/null +++ b/patch/kernel/sunxi-dev/0026-iio-adc-Kconfig-enable-A80-A64-and-H5-for-THS.patch @@ -0,0 +1,26 @@ +From f79548364ea767853c5a95f1db2407219f06572a Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Wed, 24 Jan 2018 22:35:13 +0100 +Subject: [PATCH 026/146] iio: adc: Kconfig: enable A80, A64 and H5 for THS + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig +index 4a754921fb6f..c77aec60a364 100644 +--- a/drivers/iio/adc/Kconfig ++++ b/drivers/iio/adc/Kconfig +@@ -723,7 +723,7 @@ config STX104 + config SUN4I_GPADC + tristate "Support for the Allwinner SoCs GPADC" + depends on IIO +- depends on MFD_SUN4I_GPADC || MACH_SUN8I ++ depends on MFD_SUN4I_GPADC || MACH_SUN8I || MACH_SUN50I || MACH_SUN9I + depends on THERMAL || !THERMAL_OF + select REGMAP_IRQ + help +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0027-iio-adc-sun4i-gpadc-iio-add-support-for-H5-thermal-s.patch b/patch/kernel/sunxi-dev/0027-iio-adc-sun4i-gpadc-iio-add-support-for-H5-thermal-s.patch new file mode 100644 index 000000000..3171dc0ee --- /dev/null +++ b/patch/kernel/sunxi-dev/0027-iio-adc-sun4i-gpadc-iio-add-support-for-H5-thermal-s.patch @@ -0,0 +1,79 @@ +From 46f1130b5286457e519c296a4b683747deb983cb Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Wed, 24 Jan 2018 16:58:30 +0100 +Subject: [PATCH 027/146] iio: adc: sun4i-gpadc-iio: add support for H5 thermal + sensor +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds support for the H5 ths sensor. + +The H5 supports interrupts. The interrupt is configured to update +the sensor values every second. The sensor is except the scale/offset +values and an additional sensor for the gpu the same. A temperatur higer +than 70°C needs an other formula. Since the operating temperatures maximum +is 70°C this case was neglegted. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 36 +++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index b8693afcdbea..40529a197335 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -204,6 +204,38 @@ static const struct gpadc_data sun8i_a83t_ths_data = { + SUNXI_THS_TEMP_PERIOD(0x257), + }; + ++static const struct gpadc_data sun50i_h5_ths_data = { ++ .temp_offset = -1872, ++ .temp_scale = -119, ++ .temp_data = {SUNXI_THS_TDATA0, ++ SUNXI_THS_TDATA1, 0, 0}, ++ .sample_start = sunxi_ths_sample_start, ++ .sample_end = sunxi_ths_sample_end, ++ .has_bus_clk = true, ++ .has_bus_rst = true, ++ .has_mod_clk = true, ++ .sensor_count = 2, ++ .supports_nvmem = false, ++ .support_irq = true, ++ .ctrl0_map = SUNXI_THS_ACQ0(0x1f3), ++ .ctrl2_map = SUNXI_THS_ACQ1(0x1f3), ++ .sensor_en_map = SUNXI_THS_TEMP_SENSE_EN0 | ++ SUNXI_THS_TEMP_SENSE_EN1, ++ .filter_map = SUNXI_THS_FILTER_EN | ++ SUNXI_THS_FILTER_TYPE(0x2), ++ .irq_clear_map = SUNXI_THS_INTS_ALARM_INT_0 | ++ SUNXI_THS_INTS_ALARM_INT_1 | ++ SUNXI_THS_INTS_SHUT_INT_0 | ++ SUNXI_THS_INTS_SHUT_INT_1 | ++ SUNXI_THS_INTS_TDATA_IRQ_0 | ++ SUNXI_THS_INTS_TDATA_IRQ_1 | ++ SUNXI_THS_INTS_ALARM_OFF_0 | ++ SUNXI_THS_INTS_ALARM_OFF_1, ++ .irq_control_map = SUNXI_THS_INTC_TDATA_IRQ_EN0 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN1 | ++ SUNXI_THS_TEMP_PERIOD(0x3a), ++}; ++ + struct sun4i_gpadc_iio { + struct iio_dev *indio_dev; + struct completion completion; +@@ -710,6 +742,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { + .compatible = "allwinner,sun8i-a83t-ths", + .data = &sun8i_a83t_ths_data, + }, ++ { ++ .compatible = "allwinner,sun50i-h5-ths", ++ .data = &sun50i_h5_ths_data, ++ }, + { /* sentinel */ } + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0028-iio-adc-sun4i-gpadc-iio-add-support-for-A80-thermal-.patch b/patch/kernel/sunxi-dev/0028-iio-adc-sun4i-gpadc-iio-add-support-for-A80-thermal-.patch new file mode 100644 index 000000000..691443bb4 --- /dev/null +++ b/patch/kernel/sunxi-dev/0028-iio-adc-sun4i-gpadc-iio-add-support-for-A80-thermal-.patch @@ -0,0 +1,86 @@ +From 413a3bde03c061d4b5affe25ad75f4dfe6e3282b Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Wed, 24 Jan 2018 17:28:02 +0100 +Subject: [PATCH 028/146] iio: adc: sun4i-gpadc-iio: add support for A80 + thermal sensor + +This patch adds support for the A80 ths sensor. + +The A80 has 4 sensors and supports interrupts. The interrupt is configured to update +the sensor values every second. The A80 shares some registers with the +integrated GPADC. ACQ0 must be set in the GPADC register with the offset +0x00. In fact the GPADC and the THS use the same register base and also +the same clocks and resets. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 46 +++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 40529a197335..7ab175f0bd40 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -236,6 +236,48 @@ static const struct gpadc_data sun50i_h5_ths_data = { + SUNXI_THS_TEMP_PERIOD(0x3a), + }; + ++static const struct gpadc_data sun9i_a80_ths_data = { ++ .temp_offset = -2794, ++ .temp_scale = -67, ++ .temp_data = {SUNXI_THS_TDATA0, ++ SUNXI_THS_TDATA1, ++ SUNXI_THS_TDATA2, ++ SUNXI_THS_TDATA3}, ++ .sample_start = sunxi_ths_sample_start, ++ .sample_end = sunxi_ths_sample_end, ++ .has_bus_clk = true, ++ .has_bus_rst = true, ++ .has_mod_clk = true, ++ .sensor_count = 4, ++ .supports_nvmem = false, ++ .support_irq = true, ++ .ctrl0_map = SUNXI_THS_ACQ0(0x1f3), ++ .ctrl2_map = SUNXI_THS_TEMP_SENSE_EN0 | ++ SUNXI_THS_TEMP_SENSE_EN1 | ++ SUNXI_THS_TEMP_SENSE_EN2 | ++ SUNXI_THS_TEMP_SENSE_EN3 | ++ SUNXI_THS_ACQ1(0x1f3), ++ .filter_map = SUNXI_THS_FILTER_EN | ++ SUNXI_THS_FILTER_TYPE(0x2), ++ .irq_clear_map = SUNXI_THS_INTS_ALARM_INT_0 | ++ SUNXI_THS_INTS_ALARM_INT_1 | ++ SUNXI_THS_INTS_ALARM_INT_2 | ++ SUNXI_THS_INTS_ALARM_INT_3 | ++ SUNXI_THS_INTS_SHUT_INT_0 | ++ SUNXI_THS_INTS_SHUT_INT_1 | ++ SUNXI_THS_INTS_SHUT_INT_2 | ++ SUNXI_THS_INTS_SHUT_INT_3 | ++ SUNXI_THS_INTS_TDATA_IRQ_0 | ++ SUNXI_THS_INTS_TDATA_IRQ_1 | ++ SUNXI_THS_INTS_TDATA_IRQ_2 | ++ SUNXI_THS_INTS_TDATA_IRQ_3, ++ .irq_control_map = SUNXI_THS_INTC_TDATA_IRQ_EN0 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN1 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN2 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN3 | ++ SUNXI_THS_TEMP_PERIOD(0x3a), ++}; ++ + struct sun4i_gpadc_iio { + struct iio_dev *indio_dev; + struct completion completion; +@@ -746,6 +788,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { + .compatible = "allwinner,sun50i-h5-ths", + .data = &sun50i_h5_ths_data, + }, ++ { ++ .compatible = "allwinner,sun9i-a80-ths", ++ .data = &sun9i_a80_ths_data, ++ }, + { /* sentinel */ } + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0029-iio-adc-sun4i-gpadc-iio-add-support-for-A64-thermal-.patch b/patch/kernel/sunxi-dev/0029-iio-adc-sun4i-gpadc-iio-add-support-for-A64-thermal-.patch new file mode 100644 index 000000000..48df85475 --- /dev/null +++ b/patch/kernel/sunxi-dev/0029-iio-adc-sun4i-gpadc-iio-add-support-for-A64-thermal-.patch @@ -0,0 +1,87 @@ +From 5a1eb96e482c276f8bc81c18696748ecb20b3656 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Wed, 24 Jan 2018 17:41:45 +0100 +Subject: [PATCH 029/146] iio: adc: sun4i-gpadc-iio: add support for A64 + thermal sensor + +This patch adds support for the A64 ths sensor. + +The A64 supports interrupts. The interrupt is configured to update +the sensor values every second. + +Signed-off-by: Philipp Rossak +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 50 +++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index 7ab175f0bd40..fdfa01bad325 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -278,6 +278,52 @@ static const struct gpadc_data sun9i_a80_ths_data = { + SUNXI_THS_TEMP_PERIOD(0x3a), + }; + ++static const struct gpadc_data sun50i_a64_ths_data = { ++ .temp_offset = -2170, ++ .temp_scale = -117, ++ .temp_data = {SUNXI_THS_TDATA0, ++ SUNXI_THS_TDATA1, ++ SUNXI_THS_TDATA2, ++ 0}, ++ .sample_start = sunxi_ths_sample_start, ++ .sample_end = sunxi_ths_sample_end, ++ .has_bus_clk = true, ++ .has_bus_rst = true, ++ .has_mod_clk = true, ++ .sensor_count = 3, ++ .supports_nvmem = false, ++ .support_irq = true, ++ ++ /* The final sample period is calculated as follows: ++ * (THERMAL_PER + 1) * 4096 / 24MHz * 2^(FILTER_TYPE + 1) ++ * ++ * This results to about 1Hz with these settings. ++ */ ++ .ctrl0_map = SUNXI_THS_ACQ0(0xff), ++ .ctrl2_map = SUNXI_THS_TEMP_SENSE_EN0 | ++ SUNXI_THS_TEMP_SENSE_EN1 | ++ SUNXI_THS_TEMP_SENSE_EN2 | ++ SUNXI_THS_ACQ1(0x3f), ++ .filter_map = SUNXI_THS_FILTER_EN | ++ SUNXI_THS_FILTER_TYPE(0x1), ++ .irq_clear_map = SUNXI_THS_INTS_ALARM_INT_0 | ++ SUNXI_THS_INTS_ALARM_INT_1 | ++ SUNXI_THS_INTS_ALARM_INT_2 | ++ SUNXI_THS_INTS_SHUT_INT_0 | ++ SUNXI_THS_INTS_SHUT_INT_1 | ++ SUNXI_THS_INTS_SHUT_INT_2 | ++ SUNXI_THS_INTS_TDATA_IRQ_0 | ++ SUNXI_THS_INTS_TDATA_IRQ_1 | ++ SUNXI_THS_INTS_TDATA_IRQ_2 | ++ SUNXI_THS_INTS_ALARM_OFF_0 | ++ SUNXI_THS_INTS_ALARM_OFF_1 | ++ SUNXI_THS_INTS_ALARM_OFF_2, ++ .irq_control_map = SUNXI_THS_INTC_TDATA_IRQ_EN0 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN1 | ++ SUNXI_THS_INTC_TDATA_IRQ_EN2 | ++ SUNXI_THS_TEMP_PERIOD(0x7), ++}; ++ + struct sun4i_gpadc_iio { + struct iio_dev *indio_dev; + struct completion completion; +@@ -792,6 +838,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { + .compatible = "allwinner,sun9i-a80-ths", + .data = &sun9i_a80_ths_data, + }, ++ { ++ .compatible = "allwinner,sun50i-a64-ths", ++ .data = &sun50i_a64_ths_data, ++ }, + { /* sentinel */ } + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0030-arm64-dts-allwinner-h5-add-support-for-the-thermal-s.patch b/patch/kernel/sunxi-dev/0030-arm64-dts-allwinner-h5-add-support-for-the-thermal-s.patch new file mode 100644 index 000000000..6e7212c59 --- /dev/null +++ b/patch/kernel/sunxi-dev/0030-arm64-dts-allwinner-h5-add-support-for-the-thermal-s.patch @@ -0,0 +1,30 @@ +From e6e2d489bd4776f62a962ad8f511d862a1864f80 Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Fri, 26 Jan 2018 01:40:38 +0100 +Subject: [PATCH 030/146] arm64: dts: allwinner: h5: add support for the + thermal sensor in H5 + +This patch adds the missing compatible and the thermal sensor cells. +The H5 has two sensors. + +Signed-off-by: Philipp Rossak +--- + arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +index 62d646baac3c..ee12490203b8 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +@@ -129,3 +129,8 @@ + ; + compatible = "allwinner,sun50i-h5-pinctrl"; + }; ++ ++&ths { ++ compatible = "allwinner,sun50i-h5-ths"; ++ #thermal-sensor-cells = <1>; ++}; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0031-arm64-dts-allwinner-h5-add-termal-zone-to-H5.patch b/patch/kernel/sunxi-dev/0031-arm64-dts-allwinner-h5-add-termal-zone-to-H5.patch new file mode 100644 index 000000000..251937875 --- /dev/null +++ b/patch/kernel/sunxi-dev/0031-arm64-dts-allwinner-h5-add-termal-zone-to-H5.patch @@ -0,0 +1,43 @@ +From b3ec6c1e145347ad88b14fcab39080c5af9410ef Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Fri, 26 Jan 2018 01:42:16 +0100 +Subject: [PATCH 031/146] arm64: dts: allwinner: h5: add termal zone to H5 + +This patch adds the termal zones to the H5. Sensor 0 is located in the +cpu. Sensor 1 is located in the gpu. + +Signed-off-by: Philipp Rossak +--- + arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +index ee12490203b8..849c3d8a50bb 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi +@@ -81,6 +81,22 @@ + method = "smc"; + }; + ++ thermal-zones { ++ cpu-thermal { ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 0>; ++ }; ++ ++ gpu-thermal { ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 1>; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupts = +Date: Sat, 27 Jan 2018 21:30:16 +0100 +Subject: [PATCH 032/146] arm: dts: sun9i: a80: add support for the thermal + sensor in A80 + +As we have gained the support for the thermal sensor in A80, +we can now add its device nodes to the device tree. + +The clocks and the resets are shared between the GPADC and the THS +sensor. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sun9i-a80.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi +index 25591d6883ef..9411831d04aa 100644 +--- a/arch/arm/boot/dts/sun9i-a80.dtsi ++++ b/arch/arm/boot/dts/sun9i-a80.dtsi +@@ -913,6 +913,17 @@ + #reset-cells = <1>; + }; + ++ ths: thermal-sensor@6004C00 { ++ compatible = "allwinner,sun9i-a80-ths"; ++ reg = <0x06004C00 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_GPADC>, <&ccu CLK_GPADC>; ++ clock-names = "bus", "mod"; ++ resets = <&ccu RST_BUS_GPADC>; ++ #thermal-sensor-cells = <1>; ++ #io-channel-cells = <0>; ++ }; ++ + timer@6000c00 { + compatible = "allwinner,sun4i-a10-timer"; + reg = <0x06000c00 0xa0>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0033-arm-dts-sun9i-a80-add-thermal-zone-to-A80.patch b/patch/kernel/sunxi-dev/0033-arm-dts-sun9i-a80-add-thermal-zone-to-A80.patch new file mode 100644 index 000000000..fb3795176 --- /dev/null +++ b/patch/kernel/sunxi-dev/0033-arm-dts-sun9i-a80-add-thermal-zone-to-A80.patch @@ -0,0 +1,54 @@ +From 559d5cc47ffd71a47da77424e251a8d21250cabb Mon Sep 17 00:00:00 2001 +From: Philipp Rossak +Date: Sat, 27 Jan 2018 21:39:09 +0100 +Subject: [PATCH 033/146] arm: dts: sun9i: a80: add thermal zone to A80 + +This patch adds the thermal zones to the A80. + +Sensor 0 is located besides the big CPU, sensor 1 is located besides the +DRAM, sensor 2 is located besides the GPU and sensor 3 is located besides +the small CPU. + +Signed-off-by: Philipp Rossak +--- + arch/arm/boot/dts/sun9i-a80.dtsi | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi +index 9411831d04aa..6c52b33dad84 100644 +--- a/arch/arm/boot/dts/sun9i-a80.dtsi ++++ b/arch/arm/boot/dts/sun9i-a80.dtsi +@@ -1221,4 +1221,30 @@ + #size-cells = <0>; + }; + }; ++ ++ thermal-zones { ++ cpu0_thermal: cpu0-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ thermal-sensors = <&ths 0>; ++ }; ++ ++ dram_thermal: dram-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ thermal-sensors = <&ths 1>; ++ }; ++ ++ gpu_thermal: gpu-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ thermal-sensors = <&ths 2>; ++ }; ++ ++ cpu2_thermal: cpu2-thermal { ++ polling-delay-passive = <1000>; ++ polling-delay = <5000>; ++ thermal-sensors = <&ths 3>; ++ }; ++ }; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0034-dts-a64-ths.patch b/patch/kernel/sunxi-dev/0034-dts-a64-ths.patch new file mode 100644 index 000000000..6f550c3f2 --- /dev/null +++ b/patch/kernel/sunxi-dev/0034-dts-a64-ths.patch @@ -0,0 +1,62 @@ +From ff4436bd3de240a1d0796d4c6f8bd676ff0925e1 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Mon, 23 Apr 2018 23:24:41 -0700 +Subject: [PATCH 034/146] dts: a64 ths + +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 32 +++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 0b44018361cb..0eb482eb58b7 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -171,6 +171,27 @@ + }; + }; + ++ thermal-zones { ++ cpu_thermal: cpu0-thermal { ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 0>; ++ }; ++ gpu0_thermal: gpu0-thermal { ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 1>; ++ }; ++ gpu1_thermal: gpu1-thermal { ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 2>; ++ }; ++ }; ++ + timer { + compatible = "arm,armv8-timer"; + interrupts = ; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; ++ clock-names = "bus", "mod"; ++ resets = <&ccu RST_BUS_THS>; ++ #io-channel-cells = <0>; ++ #thermal-sensor-cells = <1>; ++ }; ++ + uart0: serial@1c28000 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28000 0x400>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0035-clk-sunxi-ng-add-mux-and-pll-notifiers-for-A64-CPU-c.patch b/patch/kernel/sunxi-dev/0035-clk-sunxi-ng-add-mux-and-pll-notifiers-for-A64-CPU-c.patch new file mode 100644 index 000000000..860d255ca --- /dev/null +++ b/patch/kernel/sunxi-dev/0035-clk-sunxi-ng-add-mux-and-pll-notifiers-for-A64-CPU-c.patch @@ -0,0 +1,73 @@ +From 5afd98f6db25b34a96bfc7544681dbf40896c1fd Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Sat, 23 Sep 2017 08:15:29 +0800 +Subject: [PATCH 035/146] clk: sunxi-ng: add mux and pll notifiers for A64 CPU + clock + +The A64 PLL_CPU clock has the same instability if some factor changed +without the PLL gated like other SoCs with sun6i-style CCU, e.g. A33, +H3. + +Add the mux and pll notifiers for A64 CPU clock to workaround the +problem. + +Fixes: c6a0637460c2 ("clk: sunxi-ng: Add A64 clocks") +Signed-off-by: Icenowy Zheng +--- + drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 28 ++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +index ee9c12cf3f08..1fe3c3fbc9bc 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +@@ -896,11 +896,26 @@ static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = { + .num_resets = ARRAY_SIZE(sun50i_a64_ccu_resets), + }; + ++static struct ccu_pll_nb sun50i_a64_pll_cpu_nb = { ++ .common = &pll_cpux_clk.common, ++ /* copy from pll_cpux_clk */ ++ .enable = BIT(31), ++ .lock = BIT(28), ++}; ++ ++static struct ccu_mux_nb sun50i_a64_cpu_nb = { ++ .common = &cpux_clk.common, ++ .cm = &cpux_clk.mux, ++ .delay_us = 1, /* > 8 clock cycles at 24 MHz */ ++ .bypass_index = 1, /* index of 24 MHz oscillator */ ++}; ++ + static int sun50i_a64_ccu_probe(struct platform_device *pdev) + { + struct resource *res; + void __iomem *reg; + u32 val; ++ int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg = devm_ioremap_resource(&pdev->dev, res); +@@ -914,7 +929,18 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev) + + writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); + +- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); ++ ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); ++ if (ret) ++ return ret; ++ ++ /* Gate then ungate PLL CPU after any rate changes */ ++ ccu_pll_notifier_register(&sun50i_a64_pll_cpu_nb); ++ ++ /* Reparent CPU during PLL CPU rate changes */ ++ ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, ++ &sun50i_a64_cpu_nb); ++ ++ return 0; + } + + static const struct of_device_id sun50i_a64_ccu_ids[] = { +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0036-sun4i-gpadc-iio-ignore-zero-samples-to-avoid-force-p.patch b/patch/kernel/sunxi-dev/0036-sun4i-gpadc-iio-ignore-zero-samples-to-avoid-force-p.patch new file mode 100644 index 000000000..5662af42f --- /dev/null +++ b/patch/kernel/sunxi-dev/0036-sun4i-gpadc-iio-ignore-zero-samples-to-avoid-force-p.patch @@ -0,0 +1,31 @@ +From a6b5eb09bddbd0c331f41fefa2fd2f71a2cf9455 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Tue, 24 Apr 2018 22:21:10 -0700 +Subject: [PATCH 036/146] sun4i-gpadc-iio: ignore zero samples to avoid force + poweroff when reading first sample + +Signed-off-by: Vasily Khoruzhick +--- + drivers/iio/adc/sun4i-gpadc-iio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c +index fdfa01bad325..68256e73a4d2 100644 +--- a/drivers/iio/adc/sun4i-gpadc-iio.c ++++ b/drivers/iio/adc/sun4i-gpadc-iio.c +@@ -751,6 +751,12 @@ static int sun4i_gpadc_get_temp(void *data, int *temp) + if (sun4i_gpadc_temp_read(info->indio_dev, &val, info->sensor_id)) + return -ETIMEDOUT; + ++ /* Ignore first sample which is always zero. 0 is either too ++ * cold or too hot, so we can safely ignore it ++ */ ++ if (val == 0) ++ return -ETIMEDOUT; ++ + sun4i_gpadc_temp_scale(info->indio_dev, &scale); + sun4i_gpadc_temp_offset(info->indio_dev, &offset); + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0037-a64-dvfs-wip.patch b/patch/kernel/sunxi-dev/0037-a64-dvfs-wip.patch new file mode 100644 index 000000000..a3014207e --- /dev/null +++ b/patch/kernel/sunxi-dev/0037-a64-dvfs-wip.patch @@ -0,0 +1,251 @@ +From b07dd371b1a1203a013f91da750259f7a2467fce Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Tue, 24 Apr 2018 22:21:27 -0700 +Subject: [PATCH 037/146] a64 dvfs wip + +Changed: Igor + +--- + .../boot/dts/allwinner/sun50i-a64-pine64.dts | 4 + + .../dts/allwinner/sun50i-a64-pinebook.dts | 4 + + .../allwinner/sun50i-a64-sopine-baseboard.dts | 4 + + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 111 ++++++++++++++++-- + drivers/clk/sunxi-ng/ccu-sun50i-a64.h | 1 - + include/dt-bindings/clock/sun50i-a64-ccu.h | 1 + + 6 files changed, 112 insertions(+), 13 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +index 8c5dd99cc9ac..cdf5169f2a1a 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +@@ -69,6 +69,10 @@ + }; + }; + ++&cpu0 { ++ cpu-supply = <®_dcdc2>; ++}; ++ + &ehci0 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +index 897e60cbe38d..b3698a8bb1d3 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +@@ -66,6 +66,10 @@ + }; + }; + ++&cpu0 { ++ cpu-supply = <®_dcdc2>; ++}; ++ + &ehci0 { + phys = <&usbphy 0>; + phy-names = "usb"; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +index 8161895dde52..dc728b3b5556 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +@@ -69,6 +69,10 @@ + }; + }; + ++&cpu0 { ++ cpu-supply = <®_dcdc2>; ++}; ++ + &ehci0 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 0eb482eb58b7..62b880f68d6a 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; +@@ -79,6 +80,47 @@ + }; + }; + ++ cpu0_opp_table: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-120000000 { ++ opp-hz = /bits/ 64 <120000000>; ++ opp-microvolt = <1040000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ opp-648000000 { ++ opp-hz = /bits/ 64 <648000000>; ++ opp-microvolt = <1040000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ opp-816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <1100000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ opp-912000000 { ++ opp-hz = /bits/ 64 <912000000>; ++ opp-microvolt = <1120000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ opp-960000000 { ++ opp-hz = /bits/ 64 <960000000>; ++ opp-microvolt = <1160000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ opp-1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <1200000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <1240000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -88,6 +135,10 @@ + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-names = "cpu"; ++ operating-points-v2 = <&cpu0_opp_table>; ++ #cooling-cells = <2>; + }; + + cpu1: cpu@1 { +@@ -95,6 +146,7 @@ + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu2: cpu@2 { +@@ -102,6 +154,7 @@ + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + + cpu3: cpu@3 { +@@ -109,6 +162,7 @@ + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; ++ operating-points-v2 = <&cpu0_opp_table>; + }; + }; + +@@ -173,22 +227,55 @@ + + thermal-zones { + cpu_thermal: cpu0-thermal { +- /* milliseconds */ +- polling-delay-passive = <250>; +- polling-delay = <1000>; +- thermal-sensors = <&ths 0>; ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 0>; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_alert0>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ map1 { ++ trip = <&cpu_alert1>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ trips { ++ cpu_alert0: cpu_alert0 { ++ /* milliCelsius */ ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu_alert1: cpu_alert1 { ++ /* milliCelsius */ ++ temperature = <90000>; ++ hysteresis = <2000>; ++ type = "hot"; ++ }; ++ ++ cpu_crit: cpu_crit { ++ /* milliCelsius */ ++ temperature = <110000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; + }; + gpu0_thermal: gpu0-thermal { +- /* milliseconds */ +- polling-delay-passive = <250>; +- polling-delay = <1000>; +- thermal-sensors = <&ths 1>; ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 1>; + }; + gpu1_thermal: gpu1-thermal { +- /* milliseconds */ +- polling-delay-passive = <250>; +- polling-delay = <1000>; +- thermal-sensors = <&ths 2>; ++ /* milliseconds */ ++ polling-delay-passive = <250>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 2>; + }; + }; + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h +index 061b6fbb4f95..91f79512cee4 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h +@@ -43,7 +43,6 @@ + #define CLK_PLL_HSIC 18 + #define CLK_PLL_DE 19 + #define CLK_PLL_DDR1 20 +-#define CLK_CPUX 21 + #define CLK_AXI 22 + #define CLK_APB 23 + #define CLK_AHB1 24 +diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h +index d66432c6e675..d7f42dd22663 100644 +--- a/include/dt-bindings/clock/sun50i-a64-ccu.h ++++ b/include/dt-bindings/clock/sun50i-a64-ccu.h +@@ -45,6 +45,7 @@ + + #define CLK_PLL_PERIPH0 11 + ++#define CLK_CPUX 21 + #define CLK_BUS_MIPI_DSI 28 + #define CLK_BUS_CE 29 + #define CLK_BUS_DMA 30 +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0038-ARM-dts-add-gpu-node-to-exynos4.patch b/patch/kernel/sunxi-dev/0038-ARM-dts-add-gpu-node-to-exynos4.patch new file mode 100644 index 000000000..1503b5f07 --- /dev/null +++ b/patch/kernel/sunxi-dev/0038-ARM-dts-add-gpu-node-to-exynos4.patch @@ -0,0 +1,64 @@ +From eca91d4d36d78c3176480742532b247fd3d72fe0 Mon Sep 17 00:00:00 2001 +From: Simon Shields +Date: Sat, 13 Jan 2018 14:17:26 +1100 +Subject: [PATCH 038/146] ARM: dts: add gpu node to exynos4 + +v2 (Qiang Yu): + add vender string to exynos4 mali gpu + +Based off a similar commit for the Samsung Mali driver by +Tobias Jakobi + +Signed-off-by: Simon Shields +Signed-off-by: Qiang Yu +--- + arch/arm/boot/dts/exynos4.dtsi | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi +index 6085e92ac2d7..362461657136 100644 +--- a/arch/arm/boot/dts/exynos4.dtsi ++++ b/arch/arm/boot/dts/exynos4.dtsi +@@ -730,6 +730,39 @@ + status = "disabled"; + }; + ++ gpu: gpu@13000000 { ++ compatible = "samsung,exynos4-mali", "arm,mali-400"; ++ reg = <0x13000000 0x30000>; ++ power-domains = <&pd_g3d>; ++ ++ /* ++ * Propagate VPLL output clock to SCLK_G3D and ++ * ensure that the DIV_G3D divider is 1. ++ */ ++ assigned-clocks = <&clock CLK_MOUT_G3D1>, <&clock CLK_MOUT_G3D>, ++ <&clock CLK_FOUT_VPLL>, <&clock CLK_SCLK_G3D>; ++ assigned-clock-parents = <&clock CLK_SCLK_VPLL>, ++ <&clock CLK_MOUT_G3D1>; ++ assigned-clock-rates = <0>, <0>, <160000000>, <160000000>; ++ ++ clocks = <&clock CLK_SCLK_G3D>, <&clock CLK_G3D>; ++ clock-names = "bus", "core"; ++ ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "ppmmu0", "ppmmu1", "ppmmu2", "ppmmu3", ++ "gpmmu", "pp0", "pp1", "pp2", "pp3", "gp"; ++ status = "disabled"; ++ }; ++ + tmu: tmu@100c0000 { + interrupt-parent = <&combiner>; + reg = <0x100C0000 0x100>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0039-dt-bindings-add-switch-delay-property-for-mali-utgar.patch b/patch/kernel/sunxi-dev/0039-dt-bindings-add-switch-delay-property-for-mali-utgar.patch new file mode 100644 index 000000000..bd3091916 --- /dev/null +++ b/patch/kernel/sunxi-dev/0039-dt-bindings-add-switch-delay-property-for-mali-utgar.patch @@ -0,0 +1,29 @@ +From 93a9dff30ace06dceba2a84eb709433d5e08c7bc Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Wed, 21 Mar 2018 14:58:02 +0800 +Subject: [PATCH 039/146] dt-bindings: add switch-delay property for + mali-utgard + +Signed-off-by: Qiang Yu +--- + Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt +index 63cd91176a68..3e2590162d4f 100644 +--- a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt ++++ b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt +@@ -58,6 +58,10 @@ Optional properties: + A power domain consumer specifier as defined in + Documentation/devicetree/bindings/power/power_domain.txt + ++ - switch-delay: ++ This value is the number of Mali clock cycles it takes to ++ enable the power gates and turn on the power mesh. ++ + Vendor-specific bindings + ------------------------ + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0042-drm-lima-add-lima-uapi-header.patch b/patch/kernel/sunxi-dev/0042-drm-lima-add-lima-uapi-header.patch new file mode 100644 index 000000000..6fa7b1295 --- /dev/null +++ b/patch/kernel/sunxi-dev/0042-drm-lima-add-lima-uapi-header.patch @@ -0,0 +1,215 @@ +From e59461ae51787ed4ba778ca32b6bde432552da96 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 14 May 2018 20:53:38 +0800 +Subject: [PATCH 042/146] drm/lima: add lima uapi header + +Signed-off-by: Qiang Yu +--- + include/uapi/drm/lima_drm.h | 195 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 195 insertions(+) + create mode 100644 include/uapi/drm/lima_drm.h + +diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h +new file mode 100644 +index 000000000000..9df95e46fb2c +--- /dev/null ++++ b/include/uapi/drm/lima_drm.h +@@ -0,0 +1,195 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_DRM_H__ ++#define __LIMA_DRM_H__ ++ ++#include "drm.h" ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++#define LIMA_INFO_GPU_MALI400 0x00 ++#define LIMA_INFO_GPU_MALI450 0x01 ++ ++struct drm_lima_info { ++ __u32 gpu_id; /* out */ ++ __u32 num_pp; /* out */ ++ __u64 va_start; /* out */ ++ __u64 va_end; /* out */ ++}; ++ ++struct drm_lima_gem_create { ++ __u32 size; /* in */ ++ __u32 flags; /* in */ ++ __u32 handle; /* out */ ++ __u32 pad; ++}; ++ ++struct drm_lima_gem_info { ++ __u32 handle; /* in */ ++ __u32 pad; ++ __u64 offset; /* out */ ++}; ++ ++#define LIMA_VA_OP_MAP 1 ++#define LIMA_VA_OP_UNMAP 2 ++ ++struct drm_lima_gem_va { ++ __u32 handle; /* in */ ++ __u32 op; /* in */ ++ __u32 flags; /* in */ ++ __u32 va; /* in */ ++}; ++ ++#define LIMA_SUBMIT_BO_READ 0x01 ++#define LIMA_SUBMIT_BO_WRITE 0x02 ++ ++struct drm_lima_gem_submit_bo { ++ __u32 handle; /* in */ ++ __u32 flags; /* in */ ++}; ++ ++#define LIMA_SUBMIT_DEP_FENCE 0x00 ++#define LIMA_SUBMIT_DEP_SYNC_FD 0x01 ++ ++struct drm_lima_gem_submit_dep_fence { ++ __u32 type; ++ __u32 ctx; ++ __u32 pipe; ++ __u32 seq; ++}; ++ ++struct drm_lima_gem_submit_dep_sync_fd { ++ __u32 type; ++ __u32 fd; ++}; ++ ++union drm_lima_gem_submit_dep { ++ __u32 type; ++ struct drm_lima_gem_submit_dep_fence fence; ++ struct drm_lima_gem_submit_dep_sync_fd sync_fd; ++}; ++ ++#define LIMA_GP_FRAME_REG_NUM 6 ++ ++struct drm_lima_gp_frame { ++ __u32 frame[LIMA_GP_FRAME_REG_NUM]; ++}; ++ ++#define LIMA_PP_FRAME_REG_NUM 23 ++#define LIMA_PP_WB_REG_NUM 12 ++ ++struct drm_lima_m400_pp_frame { ++ __u32 frame[LIMA_PP_FRAME_REG_NUM]; ++ __u32 num_pp; ++ __u32 wb[3 * LIMA_PP_WB_REG_NUM]; ++ __u32 plbu_array_address[4]; ++ __u32 fragment_stack_address[4]; ++}; ++ ++struct drm_lima_m450_pp_frame { ++ __u32 frame[LIMA_PP_FRAME_REG_NUM]; ++ __u32 _pad; ++ __u32 wb[3 * LIMA_PP_WB_REG_NUM]; ++ __u32 dlbu_regs[4]; ++ __u32 fragment_stack_address[8]; ++}; ++ ++#define LIMA_PIPE_GP 0x00 ++#define LIMA_PIPE_PP 0x01 ++ ++#define LIMA_SUBMIT_FLAG_EXPLICIT_FENCE (1 << 0) ++#define LIMA_SUBMIT_FLAG_SYNC_FD_OUT (1 << 1) ++ ++struct drm_lima_gem_submit_in { ++ __u32 ctx; ++ __u32 pipe; ++ __u32 nr_bos; ++ __u32 frame_size; ++ __u64 bos; ++ __u64 frame; ++ __u64 deps; ++ __u32 nr_deps; ++ __u32 flags; ++}; ++ ++struct drm_lima_gem_submit_out { ++ __u32 fence; ++ __u32 done; ++ __u32 sync_fd; ++ __u32 _pad; ++}; ++ ++union drm_lima_gem_submit { ++ struct drm_lima_gem_submit_in in; ++ struct drm_lima_gem_submit_out out; ++}; ++ ++struct drm_lima_wait_fence { ++ __u32 ctx; /* in */ ++ __u32 pipe; /* in */ ++ __u64 timeout_ns; /* in */ ++ __u32 seq; /* in */ ++ __u32 _pad; ++}; ++ ++#define LIMA_GEM_WAIT_READ 0x01 ++#define LIMA_GEM_WAIT_WRITE 0x02 ++ ++struct drm_lima_gem_wait { ++ __u32 handle; /* in */ ++ __u32 op; /* in */ ++ __u64 timeout_ns; /* in */ ++}; ++ ++#define LIMA_CTX_OP_CREATE 1 ++#define LIMA_CTX_OP_FREE 2 ++ ++struct drm_lima_ctx { ++ __u32 op; /* in */ ++ __u32 id; /* in/out */ ++}; ++ ++#define DRM_LIMA_INFO 0x00 ++#define DRM_LIMA_GEM_CREATE 0x01 ++#define DRM_LIMA_GEM_INFO 0x02 ++#define DRM_LIMA_GEM_VA 0x03 ++#define DRM_LIMA_GEM_SUBMIT 0x04 ++#define DRM_LIMA_WAIT_FENCE 0x05 ++#define DRM_LIMA_GEM_WAIT 0x06 ++#define DRM_LIMA_CTX 0x07 ++ ++#define DRM_IOCTL_LIMA_INFO DRM_IOR(DRM_COMMAND_BASE + DRM_LIMA_INFO, struct drm_lima_info) ++#define DRM_IOCTL_LIMA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GEM_CREATE, struct drm_lima_gem_create) ++#define DRM_IOCTL_LIMA_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GEM_INFO, struct drm_lima_gem_info) ++#define DRM_IOCTL_LIMA_GEM_VA DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_GEM_VA, struct drm_lima_gem_va) ++#define DRM_IOCTL_LIMA_GEM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GEM_SUBMIT, union drm_lima_gem_submit) ++#define DRM_IOCTL_LIMA_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_WAIT_FENCE, struct drm_lima_wait_fence) ++#define DRM_IOCTL_LIMA_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_GEM_WAIT, struct drm_lima_gem_wait) ++#define DRM_IOCTL_LIMA_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_CTX, struct drm_lima_ctx) ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif /* __LIMA_DRM_H__ */ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0043-drm-lima-add-mali-4xx-GPU-hardware-regs.patch b/patch/kernel/sunxi-dev/0043-drm-lima-add-mali-4xx-GPU-hardware-regs.patch new file mode 100644 index 000000000..d000d8228 --- /dev/null +++ b/patch/kernel/sunxi-dev/0043-drm-lima-add-mali-4xx-GPU-hardware-regs.patch @@ -0,0 +1,325 @@ +From 68dcb878e43a65cc7129d7a1535da3b133e0e446 Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Mon, 14 May 2018 21:14:31 +0800 +Subject: [PATCH 043/146] drm/lima: add mali 4xx GPU hardware regs + +Signed-off-by: Qiang Yu +Signed-off-by: Heiko Stuebner +--- + drivers/gpu/drm/lima/lima_regs.h | 304 +++++++++++++++++++++++++++++++ + 1 file changed, 304 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_regs.h + +diff --git a/drivers/gpu/drm/lima/lima_regs.h b/drivers/gpu/drm/lima/lima_regs.h +new file mode 100644 +index 000000000000..ea4a37d69b98 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_regs.h +@@ -0,0 +1,304 @@ ++/* ++ * Copyright (C) 2010-2017 ARM Limited. All rights reserved. ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * This program is free software and is provided to you under ++ * the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation, and any use by ++ * you of this program is subject to the terms of such GNU ++ * licence. ++ * ++ * A copy of the licence is included with the program, and ++ * can also be obtained from Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++#ifndef __LIMA_REGS_H__ ++#define __LIMA_REGS_H__ ++ ++/* PMU regs */ ++#define LIMA_PMU_POWER_UP 0x00 ++#define LIMA_PMU_POWER_DOWN 0x04 ++#define LIMA_PMU_POWER_GP0_MASK (1 << 0) ++#define LIMA_PMU_POWER_L2_MASK (1 << 1) ++#define LIMA_PMU_POWER_PP_MASK(i) (1 << (2 + i)) ++ ++/* ++ * On Mali450 each block automatically starts up its corresponding L2 ++ * and the PPs are not fully independent controllable. ++ * Instead PP0, PP1-3 and PP4-7 can be turned on or off. ++ */ ++#define LIMA450_PMU_POWER_PP0_MASK BIT(1) ++#define LIMA450_PMU_POWER_PP13_MASK BIT(2) ++#define LIMA450_PMU_POWER_PP47_MASK BIT(3) ++ ++#define LIMA_PMU_STATUS 0x08 ++#define LIMA_PMU_INT_MASK 0x0C ++#define LIMA_PMU_INT_RAWSTAT 0x10 ++#define LIMA_PMU_INT_CLEAR 0x18 ++#define LIMA_PMU_INT_CMD_MASK (1 << 0) ++#define LIMA_PMU_SW_DELAY 0x1C ++ ++/* L2 cache regs */ ++#define LIMA_L2_CACHE_SIZE 0x0004 ++#define LIMA_L2_CACHE_STATUS 0x0008 ++#define LIMA_L2_CACHE_STATUS_COMMAND_BUSY (1 << 0) ++#define LIMA_L2_CACHE_STATUS_DATA_BUSY (1 << 1) ++#define LIMA_L2_CACHE_COMMAND 0x0010 ++#define LIMA_L2_CACHE_COMMAND_CLEAR_ALL (1 << 0) ++#define LIMA_L2_CACHE_CLEAR_PAGE 0x0014 ++#define LIMA_L2_CACHE_MAX_READS 0x0018 ++#define LIMA_L2_CACHE_ENABLE 0x001C ++#define LIMA_L2_CACHE_ENABLE_ACCESS (1 << 0) ++#define LIMA_L2_CACHE_ENABLE_READ_ALLOCATE (1 << 1) ++#define LIMA_L2_CACHE_PERFCNT_SRC0 0x0020 ++#define LIMA_L2_CACHE_PERFCNT_VAL0 0x0024 ++#define LIMA_L2_CACHE_PERFCNT_SRC1 0x0028 ++#define LIMA_L2_CACHE_ERFCNT_VAL1 0x002C ++ ++/* GP regs */ ++#define LIMA_GP_VSCL_START_ADDR 0x00 ++#define LIMA_GP_VSCL_END_ADDR 0x04 ++#define LIMA_GP_PLBUCL_START_ADDR 0x08 ++#define LIMA_GP_PLBUCL_END_ADDR 0x0c ++#define LIMA_GP_PLBU_ALLOC_START_ADDR 0x10 ++#define LIMA_GP_PLBU_ALLOC_END_ADDR 0x14 ++#define LIMA_GP_CMD 0x20 ++#define LIMA_GP_CMD_START_VS (1 << 0) ++#define LIMA_GP_CMD_START_PLBU (1 << 1) ++#define LIMA_GP_CMD_UPDATE_PLBU_ALLOC (1 << 4) ++#define LIMA_GP_CMD_RESET (1 << 5) ++#define LIMA_GP_CMD_FORCE_HANG (1 << 6) ++#define LIMA_GP_CMD_STOP_BUS (1 << 9) ++#define LIMA_GP_CMD_SOFT_RESET (1 << 10) ++#define LIMA_GP_INT_RAWSTAT 0x24 ++#define LIMA_GP_INT_CLEAR 0x28 ++#define LIMA_GP_INT_MASK 0x2C ++#define LIMA_GP_INT_STAT 0x30 ++#define LIMA_GP_IRQ_VS_END_CMD_LST (1 << 0) ++#define LIMA_GP_IRQ_PLBU_END_CMD_LST (1 << 1) ++#define LIMA_GP_IRQ_PLBU_OUT_OF_MEM (1 << 2) ++#define LIMA_GP_IRQ_VS_SEM_IRQ (1 << 3) ++#define LIMA_GP_IRQ_PLBU_SEM_IRQ (1 << 4) ++#define LIMA_GP_IRQ_HANG (1 << 5) ++#define LIMA_GP_IRQ_FORCE_HANG (1 << 6) ++#define LIMA_GP_IRQ_PERF_CNT_0_LIMIT (1 << 7) ++#define LIMA_GP_IRQ_PERF_CNT_1_LIMIT (1 << 8) ++#define LIMA_GP_IRQ_WRITE_BOUND_ERR (1 << 9) ++#define LIMA_GP_IRQ_SYNC_ERROR (1 << 10) ++#define LIMA_GP_IRQ_AXI_BUS_ERROR (1 << 11) ++#define LIMA_GP_IRQ_AXI_BUS_STOPPED (1 << 12) ++#define LIMA_GP_IRQ_VS_INVALID_CMD (1 << 13) ++#define LIMA_GP_IRQ_PLB_INVALID_CMD (1 << 14) ++#define LIMA_GP_IRQ_RESET_COMPLETED (1 << 19) ++#define LIMA_GP_IRQ_SEMAPHORE_UNDERFLOW (1 << 20) ++#define LIMA_GP_IRQ_SEMAPHORE_OVERFLOW (1 << 21) ++#define LIMA_GP_IRQ_PTR_ARRAY_OUT_OF_BOUNDS (1 << 22) ++#define LIMA_GP_WRITE_BOUND_LOW 0x34 ++#define LIMA_GP_PERF_CNT_0_ENABLE 0x3C ++#define LIMA_GP_PERF_CNT_1_ENABLE 0x40 ++#define LIMA_GP_PERF_CNT_0_SRC 0x44 ++#define LIMA_GP_PERF_CNT_1_SRC 0x48 ++#define LIMA_GP_PERF_CNT_0_VALUE 0x4C ++#define LIMA_GP_PERF_CNT_1_VALUE 0x50 ++#define LIMA_GP_PERF_CNT_0_LIMIT 0x54 ++#define LIMA_GP_STATUS 0x68 ++#define LIMA_GP_STATUS_VS_ACTIVE (1 << 1) ++#define LIMA_GP_STATUS_BUS_STOPPED (1 << 2) ++#define LIMA_GP_STATUS_PLBU_ACTIVE (1 << 3) ++#define LIMA_GP_STATUS_BUS_ERROR (1 << 6) ++#define LIMA_GP_STATUS_WRITE_BOUND_ERR (1 << 8) ++#define LIMA_GP_VERSION 0x6C ++#define LIMA_GP_VSCL_START_ADDR_READ 0x80 ++#define LIMA_GP_PLBCL_START_ADDR_READ 0x84 ++#define LIMA_GP_CONTR_AXI_BUS_ERROR_STAT 0x94 ++ ++#define LIMA_GP_IRQ_MASK_ALL \ ++ ( \ ++ LIMA_GP_IRQ_VS_END_CMD_LST | \ ++ LIMA_GP_IRQ_PLBU_END_CMD_LST | \ ++ LIMA_GP_IRQ_PLBU_OUT_OF_MEM | \ ++ LIMA_GP_IRQ_VS_SEM_IRQ | \ ++ LIMA_GP_IRQ_PLBU_SEM_IRQ | \ ++ LIMA_GP_IRQ_HANG | \ ++ LIMA_GP_IRQ_FORCE_HANG | \ ++ LIMA_GP_IRQ_PERF_CNT_0_LIMIT | \ ++ LIMA_GP_IRQ_PERF_CNT_1_LIMIT | \ ++ LIMA_GP_IRQ_WRITE_BOUND_ERR | \ ++ LIMA_GP_IRQ_SYNC_ERROR | \ ++ LIMA_GP_IRQ_AXI_BUS_ERROR | \ ++ LIMA_GP_IRQ_AXI_BUS_STOPPED | \ ++ LIMA_GP_IRQ_VS_INVALID_CMD | \ ++ LIMA_GP_IRQ_PLB_INVALID_CMD | \ ++ LIMA_GP_IRQ_RESET_COMPLETED | \ ++ LIMA_GP_IRQ_SEMAPHORE_UNDERFLOW | \ ++ LIMA_GP_IRQ_SEMAPHORE_OVERFLOW | \ ++ LIMA_GP_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) ++ ++#define LIMA_GP_IRQ_MASK_ERROR \ ++ ( \ ++ LIMA_GP_IRQ_PLBU_OUT_OF_MEM | \ ++ LIMA_GP_IRQ_FORCE_HANG | \ ++ LIMA_GP_IRQ_WRITE_BOUND_ERR | \ ++ LIMA_GP_IRQ_SYNC_ERROR | \ ++ LIMA_GP_IRQ_AXI_BUS_ERROR | \ ++ LIMA_GP_IRQ_VS_INVALID_CMD | \ ++ LIMA_GP_IRQ_PLB_INVALID_CMD | \ ++ LIMA_GP_IRQ_SEMAPHORE_UNDERFLOW | \ ++ LIMA_GP_IRQ_SEMAPHORE_OVERFLOW | \ ++ LIMA_GP_IRQ_PTR_ARRAY_OUT_OF_BOUNDS) ++ ++#define LIMA_GP_IRQ_MASK_USED \ ++ ( \ ++ LIMA_GP_IRQ_VS_END_CMD_LST | \ ++ LIMA_GP_IRQ_PLBU_END_CMD_LST | \ ++ LIMA_GP_IRQ_MASK_ERROR) ++ ++/* PP regs */ ++#define LIMA_PP_FRAME 0x0000 ++#define LIMA_PP_RSW 0x0004 ++#define LIMA_PP_STACK 0x0030 ++#define LIMA_PP_STACK_SIZE 0x0034 ++#define LIMA_PP_ORIGIN_OFFSET_X 0x0040 ++#define LIMA_PP_WB(i) (0x0100 * (i + 1)) ++#define LIMA_PP_WB_SOURCE_SELECT 0x0000 ++#define LIMA_PP_WB_SOURCE_ADDR 0x0004 ++ ++#define LIMA_PP_VERSION 0x1000 ++#define LIMA_PP_CURRENT_REND_LIST_ADDR 0x1004 ++#define LIMA_PP_STATUS 0x1008 ++#define LIMA_PP_STATUS_RENDERING_ACTIVE (1 << 0) ++#define LIMA_PP_STATUS_BUS_STOPPED (1 << 4) ++#define LIMA_PP_CTRL 0x100c ++#define LIMA_PP_CTRL_STOP_BUS (1 << 0) ++#define LIMA_PP_CTRL_FLUSH_CACHES (1 << 3) ++#define LIMA_PP_CTRL_FORCE_RESET (1 << 5) ++#define LIMA_PP_CTRL_START_RENDERING (1 << 6) ++#define LIMA_PP_CTRL_SOFT_RESET (1 << 7) ++#define LIMA_PP_INT_RAWSTAT 0x1020 ++#define LIMA_PP_INT_CLEAR 0x1024 ++#define LIMA_PP_INT_MASK 0x1028 ++#define LIMA_PP_INT_STATUS 0x102c ++#define LIMA_PP_IRQ_END_OF_FRAME (1 << 0) ++#define LIMA_PP_IRQ_END_OF_TILE (1 << 1) ++#define LIMA_PP_IRQ_HANG (1 << 2) ++#define LIMA_PP_IRQ_FORCE_HANG (1 << 3) ++#define LIMA_PP_IRQ_BUS_ERROR (1 << 4) ++#define LIMA_PP_IRQ_BUS_STOP (1 << 5) ++#define LIMA_PP_IRQ_CNT_0_LIMIT (1 << 6) ++#define LIMA_PP_IRQ_CNT_1_LIMIT (1 << 7) ++#define LIMA_PP_IRQ_WRITE_BOUNDARY_ERROR (1 << 8) ++#define LIMA_PP_IRQ_INVALID_PLIST_COMMAND (1 << 9) ++#define LIMA_PP_IRQ_CALL_STACK_UNDERFLOW (1 << 10) ++#define LIMA_PP_IRQ_CALL_STACK_OVERFLOW (1 << 11) ++#define LIMA_PP_IRQ_RESET_COMPLETED (1 << 12) ++#define LIMA_PP_WRITE_BOUNDARY_LOW 0x1044 ++#define LIMA_PP_BUS_ERROR_STATUS 0x1050 ++#define LIMA_PP_PERF_CNT_0_ENABLE 0x1080 ++#define LIMA_PP_PERF_CNT_0_SRC 0x1084 ++#define LIMA_PP_PERF_CNT_0_LIMIT 0x1088 ++#define LIMA_PP_PERF_CNT_0_VALUE 0x108c ++#define LIMA_PP_PERF_CNT_1_ENABLE 0x10a0 ++#define LIMA_PP_PERF_CNT_1_SRC 0x10a4 ++#define LIMA_PP_PERF_CNT_1_LIMIT 0x10a8 ++#define LIMA_PP_PERF_CNT_1_VALUE 0x10ac ++#define LIMA_PP_PERFMON_CONTR 0x10b0 ++#define LIMA_PP_PERFMON_BASE 0x10b4 ++ ++#define LIMA_PP_IRQ_MASK_ALL \ ++ ( \ ++ LIMA_PP_IRQ_END_OF_FRAME | \ ++ LIMA_PP_IRQ_END_OF_TILE | \ ++ LIMA_PP_IRQ_HANG | \ ++ LIMA_PP_IRQ_FORCE_HANG | \ ++ LIMA_PP_IRQ_BUS_ERROR | \ ++ LIMA_PP_IRQ_BUS_STOP | \ ++ LIMA_PP_IRQ_CNT_0_LIMIT | \ ++ LIMA_PP_IRQ_CNT_1_LIMIT | \ ++ LIMA_PP_IRQ_WRITE_BOUNDARY_ERROR | \ ++ LIMA_PP_IRQ_INVALID_PLIST_COMMAND | \ ++ LIMA_PP_IRQ_CALL_STACK_UNDERFLOW | \ ++ LIMA_PP_IRQ_CALL_STACK_OVERFLOW | \ ++ LIMA_PP_IRQ_RESET_COMPLETED) ++ ++#define LIMA_PP_IRQ_MASK_ERROR \ ++ ( \ ++ LIMA_PP_IRQ_FORCE_HANG | \ ++ LIMA_PP_IRQ_BUS_ERROR | \ ++ LIMA_PP_IRQ_WRITE_BOUNDARY_ERROR | \ ++ LIMA_PP_IRQ_INVALID_PLIST_COMMAND | \ ++ LIMA_PP_IRQ_CALL_STACK_UNDERFLOW | \ ++ LIMA_PP_IRQ_CALL_STACK_OVERFLOW) ++ ++#define LIMA_PP_IRQ_MASK_USED \ ++ ( \ ++ LIMA_PP_IRQ_END_OF_FRAME | \ ++ LIMA_PP_IRQ_MASK_ERROR) ++ ++/* MMU regs */ ++#define LIMA_MMU_DTE_ADDR 0x0000 ++#define LIMA_MMU_STATUS 0x0004 ++#define LIMA_MMU_STATUS_PAGING_ENABLED (1 << 0) ++#define LIMA_MMU_STATUS_PAGE_FAULT_ACTIVE (1 << 1) ++#define LIMA_MMU_STATUS_STALL_ACTIVE (1 << 2) ++#define LIMA_MMU_STATUS_IDLE (1 << 3) ++#define LIMA_MMU_STATUS_REPLAY_BUFFER_EMPTY (1 << 4) ++#define LIMA_MMU_STATUS_PAGE_FAULT_IS_WRITE (1 << 5) ++#define LIMA_MMU_STATUS_BUS_ID(x) ((x >> 6) & 0x1F) ++#define LIMA_MMU_COMMAND 0x0008 ++#define LIMA_MMU_COMMAND_ENABLE_PAGING 0x00 ++#define LIMA_MMU_COMMAND_DISABLE_PAGING 0x01 ++#define LIMA_MMU_COMMAND_ENABLE_STALL 0x02 ++#define LIMA_MMU_COMMAND_DISABLE_STALL 0x03 ++#define LIMA_MMU_COMMAND_ZAP_CACHE 0x04 ++#define LIMA_MMU_COMMAND_PAGE_FAULT_DONE 0x05 ++#define LIMA_MMU_COMMAND_HARD_RESET 0x06 ++#define LIMA_MMU_PAGE_FAULT_ADDR 0x000C ++#define LIMA_MMU_ZAP_ONE_LINE 0x0010 ++#define LIMA_MMU_INT_RAWSTAT 0x0014 ++#define LIMA_MMU_INT_CLEAR 0x0018 ++#define LIMA_MMU_INT_MASK 0x001C ++#define LIMA_MMU_INT_PAGE_FAULT 0x01 ++#define LIMA_MMU_INT_READ_BUS_ERROR 0x02 ++#define LIMA_MMU_INT_STATUS 0x0020 ++ ++#define LIMA_VM_FLAG_PRESENT (1 << 0) ++#define LIMA_VM_FLAG_READ_PERMISSION (1 << 1) ++#define LIMA_VM_FLAG_WRITE_PERMISSION (1 << 2) ++#define LIMA_VM_FLAG_OVERRIDE_CACHE (1 << 3) ++#define LIMA_VM_FLAG_WRITE_CACHEABLE (1 << 4) ++#define LIMA_VM_FLAG_WRITE_ALLOCATE (1 << 5) ++#define LIMA_VM_FLAG_WRITE_BUFFERABLE (1 << 6) ++#define LIMA_VM_FLAG_READ_CACHEABLE (1 << 7) ++#define LIMA_VM_FLAG_READ_ALLOCATE (1 << 8) ++#define LIMA_VM_FLAG_MASK 0x1FF ++ ++#define LIMA_VM_FLAGS_CACHE ( \ ++ LIMA_VM_FLAG_PRESENT | \ ++ LIMA_VM_FLAG_READ_PERMISSION | \ ++ LIMA_VM_FLAG_WRITE_PERMISSION | \ ++ LIMA_VM_FLAG_OVERRIDE_CACHE | \ ++ LIMA_VM_FLAG_WRITE_CACHEABLE | \ ++ LIMA_VM_FLAG_WRITE_BUFFERABLE | \ ++ LIMA_VM_FLAG_READ_CACHEABLE | \ ++ LIMA_VM_FLAG_READ_ALLOCATE ) ++ ++#define LIMA_VM_FLAGS_UNCACHE ( \ ++ LIMA_VM_FLAG_PRESENT | \ ++ LIMA_VM_FLAG_READ_PERMISSION | \ ++ LIMA_VM_FLAG_WRITE_PERMISSION ) ++ ++/* DLBU regs */ ++#define LIMA_DLBU_MASTER_TLLIST_PHYS_ADDR 0x0000 ++#define LIMA_DLBU_MASTER_TLLIST_VADDR 0x0004 ++#define LIMA_DLBU_TLLIST_VBASEADDR 0x0008 ++#define LIMA_DLBU_FB_DIM 0x000C ++#define LIMA_DLBU_TLLIST_CONF 0x0010 ++#define LIMA_DLBU_START_TILE_POS 0x0014 ++#define LIMA_DLBU_PP_ENABLE_MASK 0x0018 ++ ++/* BCAST regs */ ++#define LIMA_BCAST_BROADCAST_MASK 0x0 ++#define LIMA_BCAST_INTERRUPT_MASK 0x4 ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0044-drm-lima-add-lima-core-driver.patch b/patch/kernel/sunxi-dev/0044-drm-lima-add-lima-core-driver.patch new file mode 100644 index 000000000..91ada2a2d --- /dev/null +++ b/patch/kernel/sunxi-dev/0044-drm-lima-add-lima-core-driver.patch @@ -0,0 +1,573 @@ +From 3cce83eb3e3b54e3ffc668724722736cf7a72055 Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Mon, 14 May 2018 21:32:02 +0800 +Subject: [PATCH 044/146] drm/lima: add lima core driver + +Signed-off-by: Qiang Yu +Signed-off-by: Heiko Stuebner +Signed-off-by: Erico Nunes +--- + drivers/gpu/drm/lima/lima_drv.c | 466 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_drv.h | 77 ++++++ + 2 files changed, 543 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_drv.c + create mode 100644 drivers/gpu/drm/lima/lima_drv.h + +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +new file mode 100644 +index 000000000000..4df24a6cfff3 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -0,0 +1,466 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "lima_drv.h" ++#include "lima_gem.h" ++#include "lima_gem_prime.h" ++#include "lima_vm.h" ++ ++int lima_sched_timeout_ms = 0; ++int lima_sched_max_tasks = 32; ++int lima_max_mem = -1; ++ ++MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms (0 = no timeout (default))"); ++module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444); ++ ++MODULE_PARM_DESC(sched_max_tasks, "max queued task num in a context (default 32)"); ++module_param_named(sched_max_tasks, lima_sched_max_tasks, int, 0444); ++ ++MODULE_PARM_DESC(max_mem, "Max memory size in MB can be used (<0 = auto)"); ++module_param_named(max_mem, lima_max_mem, int, 0444); ++ ++static int lima_ioctl_info(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_info *info = data; ++ struct lima_device *ldev = to_lima_dev(dev); ++ ++ switch (ldev->id) { ++ case lima_gpu_mali400: ++ info->gpu_id = LIMA_INFO_GPU_MALI400; ++ break; ++ case lima_gpu_mali450: ++ info->gpu_id = LIMA_INFO_GPU_MALI450; ++ break; ++ default: ++ return -ENODEV; ++ } ++ info->num_pp = ldev->pipe[lima_pipe_pp].num_processor; ++ info->va_start = ldev->va_start; ++ info->va_end = ldev->va_end; ++ return 0; ++} ++ ++static int lima_ioctl_gem_create(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_gem_create *args = data; ++ ++ if (args->flags) ++ return -EINVAL; ++ ++ if (args->size == 0) ++ return -EINVAL; ++ ++ return lima_gem_create_handle(dev, file, args->size, args->flags, &args->handle); ++} ++ ++static int lima_ioctl_gem_info(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_gem_info *args = data; ++ ++ return lima_gem_mmap_offset(file, args->handle, &args->offset); ++} ++ ++static int lima_ioctl_gem_va(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_gem_va *args = data; ++ ++ switch (args->op) { ++ case LIMA_VA_OP_MAP: ++ return lima_gem_va_map(file, args->handle, args->flags, args->va); ++ case LIMA_VA_OP_UNMAP: ++ return lima_gem_va_unmap(file, args->handle, args->va); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int lima_ioctl_gem_submit(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_gem_submit_in *args = data; ++ struct lima_device *ldev = to_lima_dev(dev); ++ struct lima_drm_priv *priv = file->driver_priv; ++ struct drm_lima_gem_submit_bo *bos; ++ struct ttm_validate_buffer *vbs; ++ union drm_lima_gem_submit_dep *deps = NULL; ++ struct lima_sched_pipe *pipe; ++ struct lima_sched_task *task; ++ struct lima_ctx *ctx; ++ struct lima_submit submit = {0}; ++ int err = 0, size; ++ ++ if (args->pipe >= lima_pipe_num || args->nr_bos == 0) ++ return -EINVAL; ++ ++ if (args->flags & ~(LIMA_SUBMIT_FLAG_EXPLICIT_FENCE | ++ LIMA_SUBMIT_FLAG_SYNC_FD_OUT)) ++ return -EINVAL; ++ ++ pipe = ldev->pipe + args->pipe; ++ if (args->frame_size != pipe->frame_size) ++ return -EINVAL; ++ ++ size = args->nr_bos * (sizeof(*submit.bos) + sizeof(*submit.vbs)) + ++ args->nr_deps * sizeof(*submit.deps); ++ bos = kzalloc(size, GFP_KERNEL); ++ if (!bos) ++ return -ENOMEM; ++ ++ size = args->nr_bos * sizeof(*submit.bos); ++ if (copy_from_user(bos, u64_to_user_ptr(args->bos), size)) { ++ err = -EFAULT; ++ goto out0; ++ } ++ ++ vbs = (void *)bos + size; ++ ++ if (args->nr_deps) { ++ deps = (void *)vbs + args->nr_bos * sizeof(*submit.vbs); ++ size = args->nr_deps * sizeof(*submit.deps); ++ if (copy_from_user(deps, u64_to_user_ptr(args->deps), size)) { ++ err = -EFAULT; ++ goto out0; ++ } ++ } ++ ++ task = kmem_cache_zalloc(pipe->task_slab, GFP_KERNEL); ++ if (!task) { ++ err = -ENOMEM; ++ goto out0; ++ } ++ ++ task->frame = task + 1; ++ if (copy_from_user(task->frame, u64_to_user_ptr(args->frame), args->frame_size)) { ++ err = -EFAULT; ++ goto out1; ++ } ++ ++ err = pipe->task_validate(pipe, task); ++ if (err) ++ goto out1; ++ ++ ctx = lima_ctx_get(&priv->ctx_mgr, args->ctx); ++ if (!ctx) { ++ err = -ENOENT; ++ goto out1; ++ } ++ ++ submit.pipe = args->pipe; ++ submit.bos = bos; ++ submit.vbs = vbs; ++ submit.nr_bos = args->nr_bos; ++ submit.task = task; ++ submit.ctx = ctx; ++ submit.deps = deps; ++ submit.nr_deps = args->nr_deps; ++ submit.flags = args->flags; ++ ++ err = lima_gem_submit(file, &submit); ++ if (!err) { ++ struct drm_lima_gem_submit_out *out = data; ++ out->fence = submit.fence; ++ out->done = submit.done; ++ out->sync_fd = submit.sync_fd; ++ } ++ ++ lima_ctx_put(ctx); ++out1: ++ if (err) ++ kmem_cache_free(pipe->task_slab, task); ++out0: ++ kfree(bos); ++ return err; ++} ++ ++static int lima_wait_fence(struct dma_fence *fence, u64 timeout_ns) ++{ ++ signed long ret; ++ ++ if (!timeout_ns) ++ ret = dma_fence_is_signaled(fence) ? 0 : -EBUSY; ++ else { ++ unsigned long timeout = lima_timeout_to_jiffies(timeout_ns); ++ ++ /* must use long for result check because in 64bit arch int ++ * will overflow if timeout is too large and get <0 result ++ */ ++ ret = dma_fence_wait_timeout(fence, true, timeout); ++ if (ret == 0) ++ ret = timeout ? -ETIMEDOUT : -EBUSY; ++ else if (ret > 0) ++ ret = 0; ++ } ++ ++ return ret; ++} ++ ++static int lima_ioctl_wait_fence(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_wait_fence *args = data; ++ struct lima_drm_priv *priv = file->driver_priv; ++ struct dma_fence *fence; ++ int err = 0; ++ ++ fence = lima_ctx_get_native_fence(&priv->ctx_mgr, args->ctx, ++ args->pipe, args->seq); ++ if (IS_ERR(fence)) ++ return PTR_ERR(fence); ++ ++ if (fence) { ++ err = lima_wait_fence(fence, args->timeout_ns); ++ dma_fence_put(fence); ++ } ++ ++ return err; ++} ++ ++static int lima_ioctl_gem_wait(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_gem_wait *args = data; ++ ++ if (!(args->op & (LIMA_GEM_WAIT_READ|LIMA_GEM_WAIT_WRITE))) ++ return -EINVAL; ++ ++ return lima_gem_wait(file, args->handle, args->op, args->timeout_ns); ++} ++ ++static int lima_ioctl_ctx(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_ctx *args = data; ++ struct lima_drm_priv *priv = file->driver_priv; ++ struct lima_device *ldev = to_lima_dev(dev); ++ ++ if (args->op == LIMA_CTX_OP_CREATE) ++ return lima_ctx_create(ldev, &priv->ctx_mgr, &args->id); ++ else if (args->op == LIMA_CTX_OP_FREE) ++ return lima_ctx_free(&priv->ctx_mgr, args->id); ++ ++ return -EINVAL; ++} ++ ++static int lima_drm_driver_open(struct drm_device *dev, struct drm_file *file) ++{ ++ int err; ++ struct lima_drm_priv *priv; ++ struct lima_device *ldev = to_lima_dev(dev); ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->vm = lima_vm_create(ldev); ++ if (!priv->vm) { ++ err = -ENOMEM; ++ goto err_out0; ++ } ++ ++ lima_ctx_mgr_init(&priv->ctx_mgr); ++ ++ file->driver_priv = priv; ++ return 0; ++ ++err_out0: ++ kfree(priv); ++ return err; ++} ++ ++static void lima_drm_driver_preclose(struct drm_device *dev, struct drm_file *file) ++{ ++ struct lima_drm_priv *priv = file->driver_priv; ++ ++ lima_ctx_mgr_fini(&priv->ctx_mgr); ++} ++ ++static void lima_drm_driver_postclose(struct drm_device *dev, struct drm_file *file) ++{ ++ struct lima_drm_priv *priv = file->driver_priv; ++ ++ lima_vm_put(priv->vm); ++ kfree(priv); ++} ++ ++static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = { ++ DRM_IOCTL_DEF_DRV(LIMA_INFO, lima_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_GEM_CREATE, lima_ioctl_gem_create, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_GEM_INFO, lima_ioctl_gem_info, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_GEM_VA, lima_ioctl_gem_va, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_GEM_SUBMIT, lima_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_WAIT_FENCE, lima_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT, lima_ioctl_gem_wait, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_CTX, lima_ioctl_ctx, DRM_AUTH|DRM_RENDER_ALLOW), ++}; ++ ++static const struct file_operations lima_drm_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = drm_compat_ioctl, ++#endif ++ .mmap = lima_gem_mmap, ++}; ++ ++static struct drm_driver lima_drm_driver = { ++ .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_PRIME, ++ .open = lima_drm_driver_open, ++ .preclose = lima_drm_driver_preclose, ++ .postclose = lima_drm_driver_postclose, ++ .ioctls = lima_drm_driver_ioctls, ++ .num_ioctls = ARRAY_SIZE(lima_drm_driver_ioctls), ++ .fops = &lima_drm_driver_fops, ++ .gem_free_object_unlocked = lima_gem_free_object, ++ .gem_open_object = lima_gem_object_open, ++ .gem_close_object = lima_gem_object_close, ++ .name = "lima", ++ .desc = "lima DRM", ++ .date = "20170325", ++ .major = 1, ++ .minor = 0, ++ .patchlevel = 0, ++ ++ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, ++ .gem_prime_import = drm_gem_prime_import, ++ .gem_prime_import_sg_table = lima_gem_prime_import_sg_table, ++ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, ++ .gem_prime_export = drm_gem_prime_export, ++ .gem_prime_res_obj = lima_gem_prime_res_obj, ++ .gem_prime_get_sg_table = lima_gem_prime_get_sg_table, ++}; ++ ++static int lima_pdev_probe(struct platform_device *pdev) ++{ ++ struct lima_device *ldev; ++ struct drm_device *ddev; ++ int err; ++ ++ ldev = devm_kzalloc(&pdev->dev, sizeof(*ldev), GFP_KERNEL); ++ if (!ldev) ++ return -ENOMEM; ++ ++ ldev->pdev = pdev; ++ ldev->dev = &pdev->dev; ++ ldev->id = (enum lima_gpu_id)of_device_get_match_data(&pdev->dev); ++ ++ platform_set_drvdata(pdev, ldev); ++ ++ /* Allocate and initialize the DRM device. */ ++ ddev = drm_dev_alloc(&lima_drm_driver, &pdev->dev); ++ if (IS_ERR(ddev)) ++ return PTR_ERR(ddev); ++ ++ ddev->dev_private = ldev; ++ ldev->ddev = ddev; ++ ++ err = lima_device_init(ldev); ++ if (err) { ++ dev_err(&pdev->dev, "Fatal error during GPU init\n"); ++ goto err_out0; ++ } ++ ++ /* ++ * Register the DRM device with the core and the connectors with ++ * sysfs. ++ */ ++ err = drm_dev_register(ddev, 0); ++ if (err < 0) ++ goto err_out1; ++ ++ return 0; ++ ++err_out1: ++ lima_device_fini(ldev); ++err_out0: ++ drm_dev_unref(ddev); ++ return err; ++} ++ ++static int lima_pdev_remove(struct platform_device *pdev) ++{ ++ struct lima_device *ldev = platform_get_drvdata(pdev); ++ struct drm_device *ddev = ldev->ddev; ++ ++ drm_dev_unregister(ddev); ++ lima_device_fini(ldev); ++ drm_dev_unref(ddev); ++ return 0; ++} ++ ++static const struct of_device_id dt_match[] = { ++ { .compatible = "arm,mali-400", .data = (void *)lima_gpu_mali400 }, ++ { .compatible = "arm,mali-450", .data = (void *)lima_gpu_mali450 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, dt_match); ++ ++static struct platform_driver lima_platform_driver = { ++ .probe = lima_pdev_probe, ++ .remove = lima_pdev_remove, ++ .driver = { ++ .name = "lima", ++ .of_match_table = dt_match, ++ }, ++}; ++ ++static void lima_check_module_param(void) ++{ ++ if (lima_sched_max_tasks < 4) ++ lima_sched_max_tasks = 4; ++ else ++ lima_sched_max_tasks = roundup_pow_of_two(lima_sched_max_tasks); ++ ++ if (lima_max_mem < 32) ++ lima_max_mem = -1; ++} ++ ++static int __init lima_init(void) ++{ ++ int ret; ++ ++ lima_check_module_param(); ++ ret = lima_sched_slab_init(); ++ if (ret) ++ return ret; ++ ++ ret = platform_driver_register(&lima_platform_driver); ++ if (ret) ++ lima_sched_slab_fini(); ++ ++ return ret; ++} ++module_init(lima_init); ++ ++static void __exit lima_exit(void) ++{ ++ platform_driver_unregister(&lima_platform_driver); ++ lima_sched_slab_fini(); ++} ++module_exit(lima_exit); ++ ++MODULE_AUTHOR("Lima Project Developers"); ++MODULE_DESCRIPTION("Lima DRM Driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h +new file mode 100644 +index 000000000000..2f5f51da21db +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_drv.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_DRV_H__ ++#define __LIMA_DRV_H__ ++ ++#include ++#include ++ ++#include "lima_ctx.h" ++ ++extern int lima_sched_timeout_ms; ++extern int lima_sched_max_tasks; ++extern int lima_max_mem; ++ ++struct lima_vm; ++struct lima_bo; ++struct lima_sched_task; ++ ++struct drm_lima_gem_submit_bo; ++ ++#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) ++ ++struct lima_drm_priv { ++ struct lima_vm *vm; ++ struct lima_ctx_mgr ctx_mgr; ++}; ++ ++struct lima_submit { ++ struct lima_ctx *ctx; ++ int pipe; ++ u32 flags; ++ ++ struct drm_lima_gem_submit_bo *bos; ++ struct ttm_validate_buffer *vbs; ++ u32 nr_bos; ++ ++ struct ttm_validate_buffer vm_pd_vb; ++ struct ww_acquire_ctx ticket; ++ struct list_head duplicates; ++ struct list_head validated; ++ ++ union drm_lima_gem_submit_dep *deps; ++ u32 nr_deps; ++ ++ struct lima_sched_task *task; ++ ++ uint32_t fence; ++ uint32_t done; ++ int sync_fd; ++}; ++ ++static inline struct lima_drm_priv * ++to_lima_drm_priv(struct drm_file *file) ++{ ++ return file->driver_priv; ++} ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0045-drm-lima-add-GPU-device-functions.patch b/patch/kernel/sunxi-dev/0045-drm-lima-add-GPU-device-functions.patch new file mode 100644 index 000000000..e8761b325 --- /dev/null +++ b/patch/kernel/sunxi-dev/0045-drm-lima-add-GPU-device-functions.patch @@ -0,0 +1,573 @@ +From 1656622231f4fc9ba6260ad1c0a44e574793a04c Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Mon, 14 May 2018 21:41:53 +0800 +Subject: [PATCH 045/146] drm/lima: add GPU device functions + +Signed-off-by: Qiang Yu +Signed-off-by: Simon Shields +Signed-off-by: Heiko Stuebner +--- + drivers/gpu/drm/lima/lima_device.c | 407 +++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_device.h | 136 ++++++++++ + 2 files changed, 543 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_device.c + create mode 100644 drivers/gpu/drm/lima/lima_device.h + +diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c +new file mode 100644 +index 000000000000..a6c3905a0c85 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_device.c +@@ -0,0 +1,407 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_gp.h" ++#include "lima_pp.h" ++#include "lima_mmu.h" ++#include "lima_pmu.h" ++#include "lima_l2_cache.h" ++#include "lima_dlbu.h" ++#include "lima_bcast.h" ++#include "lima_vm.h" ++ ++struct lima_ip_desc { ++ char *name; ++ char *irq_name; ++ bool must_have[lima_gpu_num]; ++ int offset[lima_gpu_num]; ++ ++ int (*init)(struct lima_ip *); ++ void (*fini)(struct lima_ip *); ++}; ++ ++#define LIMA_IP_DESC(ipname, mst0, mst1, off0, off1, func, irq) \ ++ [lima_ip_##ipname] = { \ ++ .name = #ipname, \ ++ .irq_name = irq, \ ++ .must_have = { \ ++ [lima_gpu_mali400] = mst0, \ ++ [lima_gpu_mali450] = mst1, \ ++ }, \ ++ .offset = { \ ++ [lima_gpu_mali400] = off0, \ ++ [lima_gpu_mali450] = off1, \ ++ }, \ ++ .init = lima_##func##_init, \ ++ .fini = lima_##func##_fini, \ ++ } ++ ++static struct lima_ip_desc lima_ip_desc[lima_ip_num] = { ++ LIMA_IP_DESC(pmu, false, false, 0x02000, 0x02000, pmu, "pmu"), ++ LIMA_IP_DESC(l2_cache0, true, true, 0x01000, 0x10000, l2_cache, NULL), ++ LIMA_IP_DESC(l2_cache1, false, true, -1, 0x01000, l2_cache, NULL), ++ LIMA_IP_DESC(l2_cache2, false, false, -1, 0x11000, l2_cache, NULL), ++ LIMA_IP_DESC(gp, true, true, 0x00000, 0x00000, gp, "gp"), ++ LIMA_IP_DESC(pp0, true, true, 0x08000, 0x08000, pp, "pp0"), ++ LIMA_IP_DESC(pp1, false, false, 0x0A000, 0x0A000, pp, "pp1"), ++ LIMA_IP_DESC(pp2, false, false, 0x0C000, 0x0C000, pp, "pp2"), ++ LIMA_IP_DESC(pp3, false, false, 0x0E000, 0x0E000, pp, "pp3"), ++ LIMA_IP_DESC(pp4, false, false, -1, 0x28000, pp, "pp4"), ++ LIMA_IP_DESC(pp5, false, false, -1, 0x2A000, pp, "pp5"), ++ LIMA_IP_DESC(pp6, false, false, -1, 0x2C000, pp, "pp6"), ++ LIMA_IP_DESC(pp7, false, false, -1, 0x2E000, pp, "pp7"), ++ LIMA_IP_DESC(gpmmu, true, true, 0x03000, 0x03000, mmu, "gpmmu"), ++ LIMA_IP_DESC(ppmmu0, true, true, 0x04000, 0x04000, mmu, "ppmmu0"), ++ LIMA_IP_DESC(ppmmu1, false, false, 0x05000, 0x05000, mmu, "ppmmu1"), ++ LIMA_IP_DESC(ppmmu2, false, false, 0x06000, 0x06000, mmu, "ppmmu2"), ++ LIMA_IP_DESC(ppmmu3, false, false, 0x07000, 0x07000, mmu, "ppmmu3"), ++ LIMA_IP_DESC(ppmmu4, false, false, -1, 0x1C000, mmu, "ppmmu4"), ++ LIMA_IP_DESC(ppmmu5, false, false, -1, 0x1D000, mmu, "ppmmu5"), ++ LIMA_IP_DESC(ppmmu6, false, false, -1, 0x1E000, mmu, "ppmmu6"), ++ LIMA_IP_DESC(ppmmu7, false, false, -1, 0x1F000, mmu, "ppmmu7"), ++ LIMA_IP_DESC(dlbu, false, true, -1, 0x14000, dlbu, NULL), ++ LIMA_IP_DESC(bcast, false, true, -1, 0x13000, bcast, NULL), ++ LIMA_IP_DESC(pp_bcast, false, true, -1, 0x16000, pp_bcast, "pp"), ++ LIMA_IP_DESC(ppmmu_bcast, false, true, -1, 0x15000, mmu, NULL), ++}; ++ ++const char *lima_ip_name(struct lima_ip *ip) ++{ ++ return lima_ip_desc[ip->id].name; ++} ++ ++static int lima_clk_init(struct lima_device *dev) ++{ ++ int err; ++ unsigned long bus_rate, gpu_rate; ++ ++ dev->clk_bus = devm_clk_get(dev->dev, "bus"); ++ if (IS_ERR(dev->clk_bus)) { ++ dev_err(dev->dev, "get bus clk failed %ld\n", PTR_ERR(dev->clk_bus)); ++ return PTR_ERR(dev->clk_bus); ++ } ++ ++ dev->clk_gpu = devm_clk_get(dev->dev, "core"); ++ if (IS_ERR(dev->clk_gpu)) { ++ dev_err(dev->dev, "get core clk failed %ld\n", PTR_ERR(dev->clk_gpu)); ++ return PTR_ERR(dev->clk_gpu); ++ } ++ ++ bus_rate = clk_get_rate(dev->clk_bus); ++ dev_info(dev->dev, "bus rate = %lu\n", bus_rate); ++ ++ gpu_rate = clk_get_rate(dev->clk_gpu); ++ dev_info(dev->dev, "mod rate = %lu", gpu_rate); ++ ++ if ((err = clk_prepare_enable(dev->clk_bus))) ++ return err; ++ if ((err = clk_prepare_enable(dev->clk_gpu))) ++ goto error_out0; ++ ++ dev->reset = devm_reset_control_get_optional(dev->dev, NULL); ++ if (IS_ERR(dev->reset)) { ++ err = PTR_ERR(dev->reset); ++ goto error_out1; ++ } else if (dev->reset != NULL) { ++ if ((err = reset_control_deassert(dev->reset))) ++ goto error_out1; ++ } ++ ++ return 0; ++ ++error_out1: ++ clk_disable_unprepare(dev->clk_gpu); ++error_out0: ++ clk_disable_unprepare(dev->clk_bus); ++ return err; ++} ++ ++static void lima_clk_fini(struct lima_device *dev) ++{ ++ if (dev->reset != NULL) ++ reset_control_assert(dev->reset); ++ clk_disable_unprepare(dev->clk_gpu); ++ clk_disable_unprepare(dev->clk_bus); ++} ++ ++static int lima_regulator_init(struct lima_device *dev) ++{ ++ int ret; ++ dev->regulator = devm_regulator_get_optional(dev->dev, "mali"); ++ if (IS_ERR(dev->regulator)) { ++ ret = PTR_ERR(dev->regulator); ++ dev->regulator = NULL; ++ if (ret == -ENODEV) ++ return 0; ++ dev_err(dev->dev, "failed to get regulator: %ld\n", PTR_ERR(dev->regulator)); ++ return ret; ++ } ++ ++ ret = regulator_enable(dev->regulator); ++ if (ret < 0) { ++ dev_err(dev->dev, "failed to enable regulator: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void lima_regulator_fini(struct lima_device *dev) ++{ ++ if (dev->regulator) ++ regulator_disable(dev->regulator); ++} ++ ++static int lima_init_ip(struct lima_device *dev, int index) ++{ ++ struct lima_ip_desc *desc = lima_ip_desc + index; ++ struct lima_ip *ip = dev->ip + index; ++ int offset = desc->offset[dev->id]; ++ bool must = desc->must_have[dev->id]; ++ int err; ++ ++ if (offset < 0) ++ return 0; ++ ++ ip->dev = dev; ++ ip->id = index; ++ ip->iomem = dev->iomem + offset; ++ if (desc->irq_name) { ++ err = platform_get_irq_byname(dev->pdev, desc->irq_name); ++ if (err < 0) ++ goto out; ++ ip->irq = err; ++ } ++ ++ err = desc->init(ip); ++ if (!err) { ++ ip->present = true; ++ return 0; ++ } ++ ++out: ++ return must ? err : 0; ++} ++ ++static void lima_fini_ip(struct lima_device *ldev, int index) ++{ ++ struct lima_ip_desc *desc = lima_ip_desc + index; ++ struct lima_ip *ip = ldev->ip + index; ++ ++ if (ip->present) ++ desc->fini(ip); ++} ++ ++static int lima_init_gp_pipe(struct lima_device *dev) ++{ ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; ++ int err; ++ ++ if ((err = lima_sched_pipe_init(pipe, "gp"))) ++ return err; ++ ++ pipe->l2_cache[pipe->num_l2_cache++] = dev->ip + lima_ip_l2_cache0; ++ pipe->mmu[pipe->num_mmu++] = dev->ip + lima_ip_gpmmu; ++ pipe->processor[pipe->num_processor++] = dev->ip + lima_ip_gp; ++ ++ if ((err = lima_gp_pipe_init(dev))) { ++ lima_sched_pipe_fini(pipe); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void lima_fini_gp_pipe(struct lima_device *dev) ++{ ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; ++ ++ lima_gp_pipe_fini(dev); ++ lima_sched_pipe_fini(pipe); ++} ++ ++static int lima_init_pp_pipe(struct lima_device *dev) ++{ ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ int err, i; ++ ++ if ((err = lima_sched_pipe_init(pipe, "pp"))) ++ return err; ++ ++ for (i = 0; i < LIMA_SCHED_PIPE_MAX_PROCESSOR; i++) { ++ struct lima_ip *pp = dev->ip + lima_ip_pp0 + i; ++ struct lima_ip *ppmmu = dev->ip + lima_ip_ppmmu0 + i; ++ struct lima_ip *l2_cache; ++ ++ if (dev->id == lima_gpu_mali400) ++ l2_cache = dev->ip + lima_ip_l2_cache0; ++ else ++ l2_cache = dev->ip + lima_ip_l2_cache1 + (i >> 2); ++ ++ if (pp->present && ppmmu->present && l2_cache->present) { ++ pipe->mmu[pipe->num_mmu++] = ppmmu; ++ pipe->processor[pipe->num_processor++] = pp; ++ if (!pipe->l2_cache[i >> 2]) ++ pipe->l2_cache[pipe->num_l2_cache++] = l2_cache; ++ } ++ } ++ ++ if (dev->ip[lima_ip_bcast].present) { ++ pipe->bcast_processor = dev->ip + lima_ip_pp_bcast; ++ pipe->bcast_mmu = dev->ip + lima_ip_ppmmu_bcast; ++ } ++ ++ if ((err = lima_pp_pipe_init(dev))) { ++ lima_sched_pipe_fini(pipe); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void lima_fini_pp_pipe(struct lima_device *dev) ++{ ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ ++ lima_pp_pipe_fini(dev); ++ lima_sched_pipe_fini(pipe); ++} ++ ++int lima_device_init(struct lima_device *ldev) ++{ ++ int err, i; ++ struct resource *res; ++ ++ dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32)); ++ ++ err = lima_clk_init(ldev); ++ if (err) { ++ dev_err(ldev->dev, "clk init fail %d\n", err); ++ return err; ++ } ++ ++ if ((err = lima_regulator_init(ldev))) { ++ dev_err(ldev->dev, "regulator init fail %d\n", err); ++ goto err_out0; ++ } ++ ++ err = lima_ttm_init(ldev); ++ if (err) ++ goto err_out1; ++ ++ ldev->empty_vm = lima_vm_create(ldev); ++ if (!ldev->empty_vm) { ++ err = -ENOMEM; ++ goto err_out2; ++ } ++ ++ ldev->va_start = 0; ++ if (ldev->id == lima_gpu_mali450) { ++ ldev->va_end = LIMA_VA_RESERVE_START; ++ ldev->dlbu_cpu = dma_alloc_wc( ++ ldev->dev, LIMA_PAGE_SIZE, ++ &ldev->dlbu_dma, GFP_KERNEL); ++ if (!ldev->dlbu_cpu) { ++ err = -ENOMEM; ++ goto err_out3; ++ } ++ } ++ else ++ ldev->va_end = LIMA_VA_RESERVE_END; ++ ++ res = platform_get_resource(ldev->pdev, IORESOURCE_MEM, 0); ++ ldev->iomem = devm_ioremap_resource(ldev->dev, res); ++ if (IS_ERR(ldev->iomem)) { ++ dev_err(ldev->dev, "fail to ioremap iomem\n"); ++ err = PTR_ERR(ldev->iomem); ++ goto err_out4; ++ } ++ ++ for (i = 0; i < lima_ip_num; i++) { ++ err = lima_init_ip(ldev, i); ++ if (err) ++ goto err_out5; ++ } ++ ++ err = lima_init_gp_pipe(ldev); ++ if (err) ++ goto err_out5; ++ ++ err = lima_init_pp_pipe(ldev); ++ if (err) ++ goto err_out6; ++ ++ if (ldev->id == lima_gpu_mali450) { ++ lima_dlbu_enable(ldev); ++ lima_bcast_enable(ldev); ++ } ++ ++ return 0; ++ ++err_out6: ++ lima_fini_gp_pipe(ldev); ++err_out5: ++ while (--i >= 0) ++ lima_fini_ip(ldev, i); ++err_out4: ++ if (ldev->dlbu_cpu) ++ dma_free_wc(ldev->dev, LIMA_PAGE_SIZE, ++ ldev->dlbu_cpu, ldev->dlbu_dma); ++err_out3: ++ lima_vm_put(ldev->empty_vm); ++err_out2: ++ lima_ttm_fini(ldev); ++err_out1: ++ lima_regulator_fini(ldev); ++err_out0: ++ lima_clk_fini(ldev); ++ return err; ++} ++ ++void lima_device_fini(struct lima_device *ldev) ++{ ++ int i; ++ ++ lima_fini_pp_pipe(ldev); ++ lima_fini_gp_pipe(ldev); ++ ++ for (i = lima_ip_num - 1; i >= 0; i--) ++ lima_fini_ip(ldev, i); ++ ++ if (ldev->dlbu_cpu) ++ dma_free_wc(ldev->dev, LIMA_PAGE_SIZE, ++ ldev->dlbu_cpu, ldev->dlbu_dma); ++ ++ lima_vm_put(ldev->empty_vm); ++ ++ lima_ttm_fini(ldev); ++ ++ lima_regulator_fini(ldev); ++ ++ lima_clk_fini(ldev); ++} +diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h +new file mode 100644 +index 000000000000..6c9c26b9e122 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_device.h +@@ -0,0 +1,136 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_DEVICE_H__ ++#define __LIMA_DEVICE_H__ ++ ++#include ++ ++#include "lima_sched.h" ++#include "lima_ttm.h" ++ ++enum lima_gpu_id { ++ lima_gpu_mali400 = 0, ++ lima_gpu_mali450, ++ lima_gpu_num, ++}; ++ ++enum lima_ip_id { ++ lima_ip_pmu, ++ lima_ip_gpmmu, ++ lima_ip_ppmmu0, ++ lima_ip_ppmmu1, ++ lima_ip_ppmmu2, ++ lima_ip_ppmmu3, ++ lima_ip_ppmmu4, ++ lima_ip_ppmmu5, ++ lima_ip_ppmmu6, ++ lima_ip_ppmmu7, ++ lima_ip_gp, ++ lima_ip_pp0, ++ lima_ip_pp1, ++ lima_ip_pp2, ++ lima_ip_pp3, ++ lima_ip_pp4, ++ lima_ip_pp5, ++ lima_ip_pp6, ++ lima_ip_pp7, ++ lima_ip_l2_cache0, ++ lima_ip_l2_cache1, ++ lima_ip_l2_cache2, ++ lima_ip_dlbu, ++ lima_ip_bcast, ++ lima_ip_pp_bcast, ++ lima_ip_ppmmu_bcast, ++ lima_ip_num, ++}; ++ ++struct lima_device; ++ ++struct lima_ip { ++ struct lima_device *dev; ++ enum lima_ip_id id; ++ bool present; ++ ++ void __iomem *iomem; ++ int irq; ++ ++ union { ++ /* pmu */ ++ unsigned switch_delay; ++ /* gp/pp */ ++ bool async_reset; ++ /* l2 cache */ ++ spinlock_t lock; ++ } data; ++}; ++ ++enum lima_pipe_id { ++ lima_pipe_gp, ++ lima_pipe_pp, ++ lima_pipe_num, ++}; ++ ++struct lima_device { ++ struct device *dev; ++ struct drm_device *ddev; ++ struct platform_device *pdev; ++ ++ enum lima_gpu_id id; ++ int num_pp; ++ ++ void __iomem *iomem; ++ struct clk *clk_bus; ++ struct clk *clk_gpu; ++ struct reset_control *reset; ++ struct regulator *regulator; ++ ++ struct lima_ip ip[lima_ip_num]; ++ struct lima_sched_pipe pipe[lima_pipe_num]; ++ ++ struct lima_mman mman; ++ ++ struct lima_vm *empty_vm; ++ uint64_t va_start; ++ uint64_t va_end; ++ ++ u32 *dlbu_cpu; ++ dma_addr_t dlbu_dma; ++}; ++ ++static inline struct lima_device * ++to_lima_dev(struct drm_device *dev) ++{ ++ return dev->dev_private; ++} ++ ++static inline struct lima_device * ++ttm_to_lima_dev(struct ttm_bo_device *dev) ++{ ++ return container_of(dev, struct lima_device, mman.bdev); ++} ++ ++int lima_device_init(struct lima_device *ldev); ++void lima_device_fini(struct lima_device *ldev); ++ ++const char *lima_ip_name(struct lima_ip *ip); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0046-drm-lima-add-PMU-related-functions.patch b/patch/kernel/sunxi-dev/0046-drm-lima-add-PMU-related-functions.patch new file mode 100644 index 000000000..9222ac9b7 --- /dev/null +++ b/patch/kernel/sunxi-dev/0046-drm-lima-add-PMU-related-functions.patch @@ -0,0 +1,144 @@ +From 399e0d92074e30643eee980e744b6cac64bef7a2 Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Mon, 14 May 2018 21:47:28 +0800 +Subject: [PATCH 046/146] drm/lima: add PMU related functions + +Signed-off-by: Qiang Yu +Signed-off-by: Heiko Stuebner +--- + drivers/gpu/drm/lima/lima_pmu.c | 85 +++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_pmu.h | 30 ++++++++++++ + 2 files changed, 115 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_pmu.c + create mode 100644 drivers/gpu/drm/lima/lima_pmu.h + +diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c +new file mode 100644 +index 000000000000..255a64e9f265 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_pmu.c +@@ -0,0 +1,85 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_pmu.h" ++#include "lima_regs.h" ++ ++#define pmu_write(reg, data) writel(data, ip->iomem + LIMA_PMU_##reg) ++#define pmu_read(reg) readl(ip->iomem + LIMA_PMU_##reg) ++ ++static int lima_pmu_wait_cmd(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ u32 stat, timeout; ++ ++ for (timeout = 1000000; timeout > 0; timeout--) { ++ stat = pmu_read(INT_RAWSTAT); ++ if (stat & LIMA_PMU_INT_CMD_MASK) ++ break; ++ } ++ ++ if (!timeout) { ++ dev_err(dev->dev, "timeout wait pmd cmd\n"); ++ return -ETIMEDOUT; ++ } ++ ++ pmu_write(INT_CLEAR, LIMA_PMU_INT_CMD_MASK); ++ return 0; ++} ++ ++int lima_pmu_init(struct lima_ip *ip) ++{ ++ int err; ++ u32 stat; ++ struct lima_device *dev = ip->dev; ++ struct device_node *np = dev->dev->of_node; ++ ++ /* If this value is too low, when in high GPU clk freq, ++ * GPU will be in unstable state. */ ++ if (of_property_read_u32(np, "switch-delay", &ip->data.switch_delay)) ++ ip->data.switch_delay = 0xff; ++ ++ pmu_write(INT_MASK, 0); ++ pmu_write(SW_DELAY, ip->data.switch_delay); ++ ++ /* status reg 1=off 0=on */ ++ stat = pmu_read(STATUS); ++ ++ /* power up all ip */ ++ if (stat) { ++ pmu_write(POWER_UP, stat); ++ err = lima_pmu_wait_cmd(ip); ++ if (err) ++ return err; ++ } ++ return 0; ++} ++ ++void lima_pmu_fini(struct lima_ip *ip) ++{ ++ ++} +diff --git a/drivers/gpu/drm/lima/lima_pmu.h b/drivers/gpu/drm/lima/lima_pmu.h +new file mode 100644 +index 000000000000..fb68a7059a37 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_pmu.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_PMU_H__ ++#define __LIMA_PMU_H__ ++ ++struct lima_ip; ++ ++int lima_pmu_init(struct lima_ip *ip); ++void lima_pmu_fini(struct lima_ip *ip); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0047-drm-lima-add-L2-cache-functions.patch b/patch/kernel/sunxi-dev/0047-drm-lima-add-L2-cache-functions.patch new file mode 100644 index 000000000..95e46a4a9 --- /dev/null +++ b/patch/kernel/sunxi-dev/0047-drm-lima-add-L2-cache-functions.patch @@ -0,0 +1,158 @@ +From 821cfa3044859b50d6d2f2f1fdbd1761bb53099b Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 14 May 2018 22:03:24 +0800 +Subject: [PATCH 047/146] drm/lima: add L2 cache functions + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_l2_cache.c | 98 ++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_l2_cache.h | 32 +++++++++ + 2 files changed, 130 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_l2_cache.c + create mode 100644 drivers/gpu/drm/lima/lima_l2_cache.h + +diff --git a/drivers/gpu/drm/lima/lima_l2_cache.c b/drivers/gpu/drm/lima/lima_l2_cache.c +new file mode 100644 +index 000000000000..a9b85de5c51a +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_l2_cache.c +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_l2_cache.h" ++#include "lima_regs.h" ++ ++#define l2_cache_write(reg, data) writel(data, ip->iomem + LIMA_L2_CACHE_##reg) ++#define l2_cache_read(reg) readl(ip->iomem + LIMA_L2_CACHE_##reg) ++ ++static int lima_l2_cache_wait_idle(struct lima_ip *ip) ++{ ++ int timeout; ++ struct lima_device *dev = ip->dev; ++ ++ for (timeout = 100000; timeout > 0; timeout--) { ++ if (!(l2_cache_read(STATUS) & LIMA_L2_CACHE_STATUS_COMMAND_BUSY)) ++ break; ++ } ++ if (!timeout) { ++ dev_err(dev->dev, "l2 cache wait command timeout\n"); ++ return -ETIMEDOUT; ++ } ++ return 0; ++} ++ ++int lima_l2_cache_flush(struct lima_ip *ip) ++{ ++ int ret; ++ ++ spin_lock(&ip->data.lock); ++ l2_cache_write(COMMAND, LIMA_L2_CACHE_COMMAND_CLEAR_ALL); ++ ret = lima_l2_cache_wait_idle(ip); ++ spin_unlock(&ip->data.lock); ++ return ret; ++} ++ ++int lima_l2_cache_init(struct lima_ip *ip) ++{ ++ int i, err; ++ u32 size; ++ struct lima_device *dev = ip->dev; ++ ++ /* l2_cache2 only exists when one of PP4-7 present */ ++ if (ip->id == lima_ip_l2_cache2) { ++ for (i = lima_ip_pp4; i <= lima_ip_pp7; i++) { ++ if (dev->ip[i].present) ++ break; ++ } ++ if (i > lima_ip_pp7) ++ return -ENODEV; ++ } ++ ++ spin_lock_init(&ip->data.lock); ++ ++ size = l2_cache_read(SIZE); ++ dev_info(dev->dev, "l2 cache %uK, %u-way, %ubyte cache line, %ubit external bus\n", ++ 1 << (((size >> 16) & 0xff) - 10), ++ 1 << ((size >> 8) & 0xff), ++ 1 << (size & 0xff), ++ 1 << ((size >> 24) & 0xff)); ++ ++ err = lima_l2_cache_flush(ip); ++ if (err) ++ return err; ++ ++ l2_cache_write(ENABLE, LIMA_L2_CACHE_ENABLE_ACCESS | LIMA_L2_CACHE_ENABLE_READ_ALLOCATE); ++ l2_cache_write(MAX_READS, 0x1c); ++ ++ return 0; ++} ++ ++void lima_l2_cache_fini(struct lima_ip *ip) ++{ ++ ++} +diff --git a/drivers/gpu/drm/lima/lima_l2_cache.h b/drivers/gpu/drm/lima/lima_l2_cache.h +new file mode 100644 +index 000000000000..4a35725bf38d +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_l2_cache.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_L2_CACHE_H__ ++#define __LIMA_L2_CACHE_H__ ++ ++struct lima_ip; ++ ++int lima_l2_cache_init(struct lima_ip *ip); ++void lima_l2_cache_fini(struct lima_ip *ip); ++ ++int lima_l2_cache_flush(struct lima_ip *ip); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0048-drm-lima-add-GP-related-functions.patch b/patch/kernel/sunxi-dev/0048-drm-lima-add-GP-related-functions.patch new file mode 100644 index 000000000..ae6e7692b --- /dev/null +++ b/patch/kernel/sunxi-dev/0048-drm-lima-add-GP-related-functions.patch @@ -0,0 +1,358 @@ +From ddd7da175a64f80b659132f6d9e0fac616d6bf6d Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 14 May 2018 22:05:37 +0800 +Subject: [PATCH 048/146] drm/lima: add GP related functions + +GP is a processor for OpenGL vertex shader +processing. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_gp.c | 293 +++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_gp.h | 34 ++++ + 2 files changed, 327 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_gp.c + create mode 100644 drivers/gpu/drm/lima/lima_gp.h + +diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c +new file mode 100644 +index 000000000000..8fb49986418a +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_gp.c +@@ -0,0 +1,293 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "lima_device.h" ++#include "lima_gp.h" ++#include "lima_regs.h" ++ ++#define gp_write(reg, data) writel(data, ip->iomem + LIMA_GP_##reg) ++#define gp_read(reg) readl(ip->iomem + LIMA_GP_##reg) ++ ++static irqreturn_t lima_gp_irq_handler(int irq, void *data) ++{ ++ struct lima_ip *ip = data; ++ struct lima_device *dev = ip->dev; ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; ++ u32 state = gp_read(INT_STAT); ++ u32 status = gp_read(STATUS); ++ bool done = false; ++ ++ /* for shared irq case */ ++ if (!state) ++ return IRQ_NONE; ++ ++ if (state & LIMA_GP_IRQ_MASK_ERROR) { ++ dev_err(dev->dev, "gp error irq state=%x status=%x\n", ++ state, status); ++ ++ /* mask all interrupts before hard reset */ ++ gp_write(INT_MASK, 0); ++ ++ pipe->error = true; ++ done = true; ++ } ++ else { ++ bool valid = state & (LIMA_GP_IRQ_VS_END_CMD_LST | ++ LIMA_GP_IRQ_PLBU_END_CMD_LST); ++ bool active = status & (LIMA_GP_STATUS_VS_ACTIVE | ++ LIMA_GP_STATUS_PLBU_ACTIVE); ++ done = valid && !active; ++ } ++ ++ gp_write(INT_CLEAR, state); ++ ++ if (done) ++ lima_sched_pipe_task_done(pipe); ++ ++ return IRQ_HANDLED; ++} ++ ++static void lima_gp_soft_reset_async(struct lima_ip *ip) ++{ ++ if (ip->data.async_reset) ++ return; ++ ++ gp_write(INT_MASK, 0); ++ gp_write(INT_CLEAR, LIMA_GP_IRQ_RESET_COMPLETED); ++ gp_write(CMD, LIMA_GP_CMD_SOFT_RESET); ++ ip->data.async_reset = true; ++} ++ ++static int lima_gp_soft_reset_async_wait(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int timeout; ++ ++ if (!ip->data.async_reset) ++ return 0; ++ ++ for (timeout = 1000; timeout > 0; timeout--) { ++ if (gp_read(INT_RAWSTAT) & LIMA_GP_IRQ_RESET_COMPLETED) ++ break; ++ } ++ if (!timeout) { ++ dev_err(dev->dev, "gp soft reset time out\n"); ++ return -ETIMEDOUT; ++ } ++ ++ gp_write(INT_CLEAR, LIMA_GP_IRQ_MASK_ALL); ++ gp_write(INT_MASK, LIMA_GP_IRQ_MASK_USED); ++ ++ ip->data.async_reset = false; ++ return 0; ++} ++ ++static int lima_gp_task_validate(struct lima_sched_pipe *pipe, ++ struct lima_sched_task *task) ++{ ++ struct drm_lima_gp_frame *frame = task->frame; ++ u32 *f = frame->frame; ++ (void)pipe; ++ ++ if (f[LIMA_GP_VSCL_START_ADDR >> 2] > ++ f[LIMA_GP_VSCL_END_ADDR >> 2] || ++ f[LIMA_GP_PLBUCL_START_ADDR >> 2] > ++ f[LIMA_GP_PLBUCL_END_ADDR >> 2] || ++ f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] > ++ f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]) ++ return -EINVAL; ++ ++ if (f[LIMA_GP_VSCL_START_ADDR >> 2] == ++ f[LIMA_GP_VSCL_END_ADDR >> 2] && ++ f[LIMA_GP_PLBUCL_START_ADDR >> 2] == ++ f[LIMA_GP_PLBUCL_END_ADDR >> 2]) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static void lima_gp_task_run(struct lima_sched_pipe *pipe, ++ struct lima_sched_task *task) ++{ ++ struct lima_ip *ip = pipe->processor[0]; ++ struct drm_lima_gp_frame *frame = task->frame; ++ u32 *f = frame->frame; ++ u32 cmd = 0; ++ int i; ++ ++ if (f[LIMA_GP_VSCL_START_ADDR >> 2] != ++ f[LIMA_GP_VSCL_END_ADDR >> 2]) ++ cmd |= LIMA_GP_CMD_START_VS; ++ if (f[LIMA_GP_PLBUCL_START_ADDR >> 2] != ++ f[LIMA_GP_PLBUCL_END_ADDR >> 2]) ++ cmd |= LIMA_GP_CMD_START_PLBU; ++ ++ /* before any hw ops, wait last success task async soft reset */ ++ lima_gp_soft_reset_async_wait(ip); ++ ++ for (i = 0; i < LIMA_GP_FRAME_REG_NUM; i++) ++ writel(f[i], ip->iomem + LIMA_GP_VSCL_START_ADDR + i * 4); ++ ++ gp_write(CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC); ++ gp_write(CMD, cmd); ++} ++ ++static int lima_gp_hard_reset(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int timeout; ++ ++ gp_write(PERF_CNT_0_LIMIT, 0xC0FFE000); ++ gp_write(INT_MASK, 0); ++ gp_write(CMD, LIMA_GP_CMD_RESET); ++ for (timeout = 1000; timeout > 0; timeout--) { ++ gp_write(PERF_CNT_0_LIMIT, 0xC01A0000); ++ if (gp_read(PERF_CNT_0_LIMIT) == 0xC01A0000) ++ break; ++ } ++ if (!timeout) { ++ dev_err(dev->dev, "gp hard reset timeout\n"); ++ return -ETIMEDOUT; ++ } ++ ++ gp_write(PERF_CNT_0_LIMIT, 0); ++ gp_write(INT_CLEAR, LIMA_GP_IRQ_MASK_ALL); ++ gp_write(INT_MASK, LIMA_GP_IRQ_MASK_USED); ++ return 0; ++} ++ ++static void lima_gp_task_fini(struct lima_sched_pipe *pipe) ++{ ++ lima_gp_soft_reset_async(pipe->processor[0]); ++} ++ ++static void lima_gp_task_error(struct lima_sched_pipe *pipe) ++{ ++ lima_gp_hard_reset(pipe->processor[0]); ++} ++ ++static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe) ++{ ++ lima_sched_pipe_task_done(pipe); ++} ++ ++static void lima_gp_print_version(struct lima_ip *ip) ++{ ++ u32 version, major, minor; ++ char *name; ++ ++ version = gp_read(VERSION); ++ major = (version >> 8) & 0xFF; ++ minor = version & 0xFF; ++ switch (version >> 16) { ++ case 0xA07: ++ name = "mali200"; ++ break; ++ case 0xC07: ++ name = "mali300"; ++ break; ++ case 0xB07: ++ name = "mali400"; ++ break; ++ case 0xD07: ++ name = "mali450"; ++ break; ++ default: ++ name = "unknow"; ++ break; ++ } ++ dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n", ++ lima_ip_name(ip), name, major, minor); ++} ++ ++static struct kmem_cache *lima_gp_task_slab = NULL; ++static int lima_gp_task_slab_refcnt = 0; ++ ++int lima_gp_init(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int err; ++ ++ lima_gp_print_version(ip); ++ ++ ip->data.async_reset = false; ++ lima_gp_soft_reset_async(ip); ++ err = lima_gp_soft_reset_async_wait(ip); ++ if (err) ++ return err; ++ ++ err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler, 0, ++ lima_ip_name(ip), ip); ++ if (err) { ++ dev_err(dev->dev, "gp %s fail to request irq\n", ++ lima_ip_name(ip)); ++ return err; ++ } ++ ++ return 0; ++} ++ ++void lima_gp_fini(struct lima_ip *ip) ++{ ++ ++} ++ ++int lima_gp_pipe_init(struct lima_device *dev) ++{ ++ int frame_size = sizeof(struct drm_lima_gp_frame); ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; ++ ++ if (!lima_gp_task_slab) { ++ lima_gp_task_slab = kmem_cache_create( ++ "lima_gp_task", sizeof(struct lima_sched_task) + frame_size, ++ 0, SLAB_HWCACHE_ALIGN, NULL); ++ if (!lima_gp_task_slab) ++ return -ENOMEM; ++ } ++ lima_gp_task_slab_refcnt++; ++ ++ pipe->frame_size = frame_size; ++ pipe->task_slab = lima_gp_task_slab; ++ ++ pipe->task_validate = lima_gp_task_validate; ++ pipe->task_run = lima_gp_task_run; ++ pipe->task_fini = lima_gp_task_fini; ++ pipe->task_error = lima_gp_task_error; ++ pipe->task_mmu_error = lima_gp_task_mmu_error; ++ ++ return 0; ++} ++ ++void lima_gp_pipe_fini(struct lima_device *dev) ++{ ++ if (!--lima_gp_task_slab_refcnt) { ++ kmem_cache_destroy(lima_gp_task_slab); ++ lima_gp_task_slab = NULL; ++ } ++} +diff --git a/drivers/gpu/drm/lima/lima_gp.h b/drivers/gpu/drm/lima/lima_gp.h +new file mode 100644 +index 000000000000..8354911e50ce +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_gp.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_GP_H__ ++#define __LIMA_GP_H__ ++ ++struct lima_ip; ++struct lima_device; ++ ++int lima_gp_init(struct lima_ip *ip); ++void lima_gp_fini(struct lima_ip *ip); ++ ++int lima_gp_pipe_init(struct lima_device *dev); ++void lima_gp_pipe_fini(struct lima_device *dev); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0049-drm-lima-add-PP-related-functions.patch b/patch/kernel/sunxi-dev/0049-drm-lima-add-PP-related-functions.patch new file mode 100644 index 000000000..aedea81fd --- /dev/null +++ b/patch/kernel/sunxi-dev/0049-drm-lima-add-PP-related-functions.patch @@ -0,0 +1,487 @@ +From f3a488deb6ebf451b0a1f928e5692ea3d1af4410 Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Mon, 14 May 2018 22:10:48 +0800 +Subject: [PATCH 049/146] drm/lima: add PP related functions + +PP is a processor used for OpenGL fragment shader +processing. + +Signed-off-by: Qiang Yu +Signed-off-by: Heiko Stuebner +--- + drivers/gpu/drm/lima/lima_pp.c | 418 +++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_pp.h | 37 +++ + 2 files changed, 455 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_pp.c + create mode 100644 drivers/gpu/drm/lima/lima_pp.h + +diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c +new file mode 100644 +index 000000000000..371d6b70c271 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_pp.c +@@ -0,0 +1,418 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "lima_device.h" ++#include "lima_pp.h" ++#include "lima_dlbu.h" ++#include "lima_bcast.h" ++#include "lima_vm.h" ++#include "lima_regs.h" ++ ++#define pp_write(reg, data) writel(data, ip->iomem + LIMA_PP_##reg) ++#define pp_read(reg) readl(ip->iomem + LIMA_PP_##reg) ++ ++static void lima_pp_handle_irq(struct lima_ip *ip, u32 state) ++{ ++ struct lima_device *dev = ip->dev; ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ ++ if (state & LIMA_PP_IRQ_MASK_ERROR) { ++ u32 status = pp_read(STATUS); ++ ++ dev_err(dev->dev, "pp error irq state=%x status=%x\n", ++ state, status); ++ ++ pipe->error = true; ++ ++ /* mask all interrupts before hard reset */ ++ pp_write(INT_MASK, 0); ++ } ++ ++ pp_write(INT_CLEAR, state); ++} ++ ++static irqreturn_t lima_pp_irq_handler(int irq, void *data) ++{ ++ struct lima_ip *ip = data; ++ struct lima_device *dev = ip->dev; ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ u32 state = pp_read(INT_STATUS); ++ ++ /* for shared irq case */ ++ if (!state) ++ return IRQ_NONE; ++ ++ lima_pp_handle_irq(ip, state); ++ ++ if (atomic_dec_and_test(&pipe->task)) ++ lima_sched_pipe_task_done(pipe); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t lima_pp_bcast_irq_handler(int irq, void *data) ++{ ++ int i; ++ irqreturn_t ret = IRQ_NONE; ++ struct lima_ip *pp_bcast = data; ++ struct lima_device *dev = pp_bcast->dev; ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ ++ for (i = 0; i < pipe->num_processor; i++) { ++ struct lima_ip *ip = pipe->processor[i]; ++ u32 status, state; ++ ++ if (pipe->done & (1 << i)) ++ continue; ++ ++ /* status read first in case int state change in the middle ++ * which may miss the interrupt handling */ ++ status = pp_read(STATUS); ++ state = pp_read(INT_STATUS); ++ ++ if (state) { ++ lima_pp_handle_irq(ip, state); ++ ret = IRQ_HANDLED; ++ } ++ else { ++ if (status & LIMA_PP_STATUS_RENDERING_ACTIVE) ++ continue; ++ } ++ ++ pipe->done |= (1 << i); ++ if (atomic_dec_and_test(&pipe->task)) ++ lima_sched_pipe_task_done(pipe); ++ } ++ ++ return ret; ++} ++ ++static void lima_pp_soft_reset_async(struct lima_ip *ip) ++{ ++ if (ip->data.async_reset) ++ return; ++ ++ pp_write(INT_MASK, 0); ++ pp_write(INT_RAWSTAT, LIMA_PP_IRQ_MASK_ALL); ++ pp_write(CTRL, LIMA_PP_CTRL_SOFT_RESET); ++ ip->data.async_reset = true; ++} ++ ++static int lima_pp_soft_reset_async_wait_one(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int timeout; ++ ++ for (timeout = 1000; timeout > 0; timeout--) { ++ if (!(pp_read(STATUS) & LIMA_PP_STATUS_RENDERING_ACTIVE) && ++ pp_read(INT_RAWSTAT) == LIMA_PP_IRQ_RESET_COMPLETED) ++ break; ++ } ++ if (!timeout) { ++ dev_err(dev->dev, "pp %s reset time out\n", lima_ip_name(ip)); ++ return -ETIMEDOUT; ++ } ++ ++ pp_write(INT_CLEAR, LIMA_PP_IRQ_MASK_ALL); ++ pp_write(INT_MASK, LIMA_PP_IRQ_MASK_USED); ++ return 0; ++} ++ ++static int lima_pp_soft_reset_async_wait(struct lima_ip *ip) ++{ ++ int i, err = 0; ++ ++ if (!ip->data.async_reset) ++ return 0; ++ ++ if (ip->id == lima_ip_pp_bcast) { ++ struct lima_device *dev = ip->dev; ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ for (i = 0; i < pipe->num_processor; i++) ++ err |= lima_pp_soft_reset_async_wait_one(pipe->processor[i]); ++ } ++ else ++ err = lima_pp_soft_reset_async_wait_one(ip); ++ ++ ip->data.async_reset = false; ++ return err; ++} ++ ++static void lima_pp_start_task(struct lima_ip *ip, u32 *frame, u32 *wb, ++ bool skip_stack_addr) ++{ ++ int i, j, n = 0; ++ ++ for (i = 0; i < LIMA_PP_FRAME_REG_NUM; i++) { ++ if (skip_stack_addr && i * 4 == LIMA_PP_STACK) ++ continue; ++ ++ writel(frame[i], ip->iomem + LIMA_PP_FRAME + i * 4); ++ } ++ ++ for (i = 0; i < 3; i++) { ++ for (j = 0; j < LIMA_PP_WB_REG_NUM; j++) ++ writel(wb[n++], ip->iomem + LIMA_PP_WB(i) + j * 4); ++ } ++ ++ pp_write(CTRL, LIMA_PP_CTRL_START_RENDERING); ++} ++ ++static int lima_pp_hard_reset(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int timeout; ++ ++ pp_write(PERF_CNT_0_LIMIT, 0xC0FFE000); ++ pp_write(INT_MASK, 0); ++ pp_write(CTRL, LIMA_PP_CTRL_FORCE_RESET); ++ for (timeout = 1000; timeout > 0; timeout--) { ++ pp_write(PERF_CNT_0_LIMIT, 0xC01A0000); ++ if (pp_read(PERF_CNT_0_LIMIT) == 0xC01A0000) ++ break; ++ } ++ if (!timeout) { ++ dev_err(dev->dev, "pp hard reset timeout\n"); ++ return -ETIMEDOUT; ++ } ++ ++ pp_write(PERF_CNT_0_LIMIT, 0); ++ pp_write(INT_CLEAR, LIMA_PP_IRQ_MASK_ALL); ++ pp_write(INT_MASK, LIMA_PP_IRQ_MASK_USED); ++ return 0; ++} ++ ++static void lima_pp_print_version(struct lima_ip *ip) ++{ ++ u32 version, major, minor; ++ char *name; ++ ++ version = pp_read(VERSION); ++ major = (version >> 8) & 0xFF; ++ minor = version & 0xFF; ++ switch (version >> 16) { ++ case 0xC807: ++ name = "mali200"; ++ break; ++ case 0xCE07: ++ name = "mali300"; ++ break; ++ case 0xCD07: ++ name = "mali400"; ++ break; ++ case 0xCF07: ++ name = "mali450"; ++ break; ++ default: ++ name = "unknow"; ++ break; ++ } ++ dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n", ++ lima_ip_name(ip), name, major, minor); ++} ++ ++int lima_pp_init(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int err; ++ ++ lima_pp_print_version(ip); ++ ++ ip->data.async_reset = false; ++ lima_pp_soft_reset_async(ip); ++ err = lima_pp_soft_reset_async_wait(ip); ++ if (err) ++ return err; ++ ++ err = devm_request_irq(dev->dev, ip->irq, lima_pp_irq_handler, ++ IRQF_SHARED, lima_ip_name(ip), ip); ++ if (err) { ++ dev_err(dev->dev, "pp %s fail to request irq\n", ++ lima_ip_name(ip)); ++ return err; ++ } ++ ++ return 0; ++} ++ ++void lima_pp_fini(struct lima_ip *ip) ++{ ++ ++} ++ ++int lima_pp_bcast_init(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int err; ++ ++ err = devm_request_irq(dev->dev, ip->irq, lima_pp_bcast_irq_handler, ++ IRQF_SHARED, lima_ip_name(ip), ip); ++ if (err) { ++ dev_err(dev->dev, "pp %s fail to request irq\n", ++ lima_ip_name(ip)); ++ return err; ++ } ++ ++ return 0; ++} ++ ++void lima_pp_bcast_fini(struct lima_ip *ip) ++{ ++ ++} ++ ++static int lima_pp_task_validate(struct lima_sched_pipe *pipe, ++ struct lima_sched_task *task) ++{ ++ if (!pipe->bcast_processor) { ++ struct drm_lima_m400_pp_frame *f = task->frame; ++ ++ if (f->num_pp > pipe->num_processor) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void lima_pp_task_run(struct lima_sched_pipe *pipe, ++ struct lima_sched_task *task) ++{ ++ if (pipe->bcast_processor) { ++ struct drm_lima_m450_pp_frame *frame = task->frame; ++ struct lima_device *dev = pipe->bcast_processor->dev; ++ int i; ++ ++ pipe->done = 0; ++ atomic_set(&pipe->task, pipe->num_processor); ++ ++ frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU; ++ lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs); ++ ++ lima_pp_soft_reset_async_wait(pipe->bcast_processor); ++ ++ for (i = 0; i < pipe->num_processor; i++) { ++ struct lima_ip *ip = pipe->processor[i]; ++ pp_write(STACK, frame->fragment_stack_address[i]); ++ } ++ ++ lima_pp_start_task(pipe->bcast_processor, frame->frame, ++ frame->wb, true); ++ } ++ else { ++ struct drm_lima_m400_pp_frame *frame = task->frame; ++ int i; ++ ++ atomic_set(&pipe->task, frame->num_pp); ++ ++ for (i = 0; i < frame->num_pp; i++) { ++ frame->frame[LIMA_PP_FRAME >> 2] = ++ frame->plbu_array_address[i]; ++ frame->frame[LIMA_PP_STACK >> 2] = ++ frame->fragment_stack_address[i]; ++ ++ lima_pp_soft_reset_async_wait(pipe->processor[i]); ++ ++ lima_pp_start_task(pipe->processor[i], frame->frame, ++ frame->wb, false); ++ } ++ } ++} ++ ++static void lima_pp_task_fini(struct lima_sched_pipe *pipe) ++{ ++ if (pipe->bcast_processor) ++ lima_pp_soft_reset_async(pipe->bcast_processor); ++ else { ++ int i; ++ for (i = 0; i < pipe->num_processor; i++) ++ lima_pp_soft_reset_async(pipe->processor[i]); ++ } ++} ++ ++static void lima_pp_task_error(struct lima_sched_pipe *pipe) ++{ ++ int i; ++ ++ if (pipe->bcast_processor) ++ lima_bcast_disable(pipe->bcast_processor->dev); ++ ++ for (i = 0; i < pipe->num_processor; i++) ++ lima_pp_hard_reset(pipe->processor[i]); ++ ++ if (pipe->bcast_processor) ++ lima_bcast_enable(pipe->bcast_processor->dev); ++} ++ ++static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe) ++{ ++ if (atomic_dec_and_test(&pipe->task)) ++ lima_sched_pipe_task_done(pipe); ++} ++ ++static struct kmem_cache *lima_pp_task_slab = NULL; ++static int lima_pp_task_slab_refcnt = 0; ++ ++int lima_pp_pipe_init(struct lima_device *dev) ++{ ++ int frame_size; ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ ++ if (dev->id == lima_gpu_mali400) ++ frame_size = sizeof(struct drm_lima_m400_pp_frame); ++ else ++ frame_size = sizeof(struct drm_lima_m450_pp_frame); ++ ++ if (!lima_pp_task_slab) { ++ lima_pp_task_slab = kmem_cache_create( ++ "lima_pp_task", sizeof(struct lima_sched_task) + frame_size, ++ 0, SLAB_HWCACHE_ALIGN, NULL); ++ if (!lima_pp_task_slab) ++ return -ENOMEM; ++ } ++ lima_pp_task_slab_refcnt++; ++ ++ pipe->frame_size = frame_size; ++ pipe->task_slab = lima_pp_task_slab; ++ ++ pipe->task_validate = lima_pp_task_validate; ++ pipe->task_run = lima_pp_task_run; ++ pipe->task_fini = lima_pp_task_fini; ++ pipe->task_error = lima_pp_task_error; ++ pipe->task_mmu_error = lima_pp_task_mmu_error; ++ ++ return 0; ++} ++ ++void lima_pp_pipe_fini(struct lima_device *dev) ++{ ++ if (!--lima_pp_task_slab_refcnt) { ++ kmem_cache_destroy(lima_pp_task_slab); ++ lima_pp_task_slab = NULL; ++ } ++} +diff --git a/drivers/gpu/drm/lima/lima_pp.h b/drivers/gpu/drm/lima/lima_pp.h +new file mode 100644 +index 000000000000..4bd1d9fcbcdf +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_pp.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_PP_H__ ++#define __LIMA_PP_H__ ++ ++struct lima_ip; ++struct lima_device; ++ ++int lima_pp_init(struct lima_ip *ip); ++void lima_pp_fini(struct lima_ip *ip); ++ ++int lima_pp_bcast_init(struct lima_ip *ip); ++void lima_pp_bcast_fini(struct lima_ip *ip); ++ ++int lima_pp_pipe_init(struct lima_device *dev); ++void lima_pp_pipe_fini(struct lima_device *dev); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0050-drm-lima-add-MMU-related-functions.patch b/patch/kernel/sunxi-dev/0050-drm-lima-add-MMU-related-functions.patch new file mode 100644 index 000000000..640317bcf --- /dev/null +++ b/patch/kernel/sunxi-dev/0050-drm-lima-add-MMU-related-functions.patch @@ -0,0 +1,218 @@ +From ae47294de5185d599b64565ff1ca2d47277eecec Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Mon, 14 May 2018 22:13:51 +0800 +Subject: [PATCH 050/146] drm/lima: add MMU related functions + +Signed-off-by: Qiang Yu +Signed-off-by: Marek Vasut +Signed-off-by: Heiko Stuebner +--- + drivers/gpu/drm/lima/lima_mmu.c | 154 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_mmu.h | 34 +++++++ + 2 files changed, 188 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_mmu.c + create mode 100644 drivers/gpu/drm/lima/lima_mmu.h + +diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c +new file mode 100644 +index 000000000000..22ac4db07849 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_mmu.c +@@ -0,0 +1,154 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_mmu.h" ++#include "lima_vm.h" ++#include "lima_object.h" ++#include "lima_regs.h" ++ ++#define mmu_write(reg, data) writel(data, ip->iomem + LIMA_MMU_##reg) ++#define mmu_read(reg) readl(ip->iomem + LIMA_MMU_##reg) ++ ++#define lima_mmu_send_command(command, condition) \ ++({ \ ++ int __timeout, __ret = 0; \ ++ \ ++ mmu_write(COMMAND, command); \ ++ for (__timeout = 1000; __timeout > 0; __timeout--) { \ ++ if (condition) \ ++ break; \ ++ } \ ++ if (!__timeout) { \ ++ dev_err(dev->dev, "mmu command %x timeout\n", command); \ ++ __ret = -ETIMEDOUT; \ ++ } \ ++ __ret; \ ++}) ++ ++static irqreturn_t lima_mmu_irq_handler(int irq, void *data) ++{ ++ struct lima_ip *ip = data; ++ struct lima_device *dev = ip->dev; ++ u32 status = mmu_read(INT_STATUS); ++ struct lima_sched_pipe *pipe; ++ ++ /* for shared irq case */ ++ if (!status) ++ return IRQ_NONE; ++ ++ if (status & LIMA_MMU_INT_PAGE_FAULT) { ++ u32 fault = mmu_read(PAGE_FAULT_ADDR); ++ dev_err(dev->dev, "mmu page fault at 0x%x from bus id %d of type %s on %s\n", ++ fault, LIMA_MMU_STATUS_BUS_ID(status), ++ status & LIMA_MMU_STATUS_PAGE_FAULT_IS_WRITE ? "write" : "read", ++ lima_ip_name(ip)); ++ } ++ ++ if (status & LIMA_MMU_INT_READ_BUS_ERROR) { ++ dev_err(dev->dev, "mmu %s irq bus error\n", lima_ip_name(ip)); ++ } ++ ++ /* mask all interrupts before resume */ ++ mmu_write(INT_MASK, 0); ++ mmu_write(INT_CLEAR, status); ++ ++ pipe = dev->pipe + (ip->id == lima_ip_gpmmu ? lima_pipe_gp : lima_pipe_pp); ++ lima_sched_pipe_mmu_error(pipe); ++ ++ return IRQ_HANDLED; ++} ++ ++int lima_mmu_init(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ int err; ++ ++ if (ip->id == lima_ip_ppmmu_bcast) ++ return 0; ++ ++ mmu_write(DTE_ADDR, 0xCAFEBABE); ++ if (mmu_read(DTE_ADDR) != 0xCAFEB000) { ++ dev_err(dev->dev, "mmu %s dte write test fail\n", lima_ip_name(ip)); ++ return -EIO; ++ } ++ ++ err = lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET, mmu_read(DTE_ADDR) == 0); ++ if (err) ++ return err; ++ ++ err = devm_request_irq(dev->dev, ip->irq, lima_mmu_irq_handler, ++ IRQF_SHARED, lima_ip_name(ip), ip); ++ if (err) { ++ dev_err(dev->dev, "mmu %s fail to request irq\n", lima_ip_name(ip)); ++ return err; ++ } ++ ++ mmu_write(INT_MASK, LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR); ++ mmu_write(DTE_ADDR, *lima_bo_get_pages(dev->empty_vm->pd)); ++ return lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING, ++ mmu_read(STATUS) & LIMA_MMU_STATUS_PAGING_ENABLED); ++} ++ ++void lima_mmu_fini(struct lima_ip *ip) ++{ ++ ++} ++ ++void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm) ++{ ++ struct lima_device *dev = ip->dev; ++ ++ lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_STALL, ++ mmu_read(STATUS) & LIMA_MMU_STATUS_STALL_ACTIVE); ++ ++ if (vm) ++ mmu_write(DTE_ADDR, *lima_bo_get_pages(vm->pd)); ++ ++ /* flush the TLB */ ++ mmu_write(COMMAND, LIMA_MMU_COMMAND_ZAP_CACHE); ++ ++ lima_mmu_send_command(LIMA_MMU_COMMAND_DISABLE_STALL, ++ !(mmu_read(STATUS) & LIMA_MMU_STATUS_STALL_ACTIVE)); ++} ++ ++void lima_mmu_page_fault_resume(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ u32 status = mmu_read(STATUS); ++ ++ if (status & LIMA_MMU_STATUS_PAGE_FAULT_ACTIVE) { ++ dev_info(dev->dev, "mmu resume\n"); ++ ++ mmu_write(INT_MASK, 0); ++ mmu_write(DTE_ADDR, 0xCAFEBABE); ++ lima_mmu_send_command(LIMA_MMU_COMMAND_HARD_RESET, mmu_read(DTE_ADDR) == 0); ++ mmu_write(INT_MASK, LIMA_MMU_INT_PAGE_FAULT | LIMA_MMU_INT_READ_BUS_ERROR); ++ mmu_write(DTE_ADDR, *lima_bo_get_pages(dev->empty_vm->pd)); ++ lima_mmu_send_command(LIMA_MMU_COMMAND_ENABLE_PAGING, ++ mmu_read(STATUS) & LIMA_MMU_STATUS_PAGING_ENABLED); ++ } ++} +diff --git a/drivers/gpu/drm/lima/lima_mmu.h b/drivers/gpu/drm/lima/lima_mmu.h +new file mode 100644 +index 000000000000..9930521ddfa1 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_mmu.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_MMU_H__ ++#define __LIMA_MMU_H__ ++ ++struct lima_ip; ++struct lima_vm; ++ ++int lima_mmu_init(struct lima_ip *ip); ++void lima_mmu_fini(struct lima_ip *ip); ++ ++void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm); ++void lima_mmu_page_fault_resume(struct lima_ip *ip); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0051-drm-lima-add-BCAST-related-function.patch b/patch/kernel/sunxi-dev/0051-drm-lima-add-BCAST-related-function.patch new file mode 100644 index 000000000..ad20df5e0 --- /dev/null +++ b/patch/kernel/sunxi-dev/0051-drm-lima-add-BCAST-related-function.patch @@ -0,0 +1,131 @@ +From 7fe721b0e0c72de29b4cfe9b3d6aa80a64f1603d Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 14 May 2018 22:17:43 +0800 +Subject: [PATCH 051/146] drm/lima: add BCAST related function + +BCAST is a hardware module to broadcast register +read/write for PPs. It can also merge IRQs from +different PPs into one IRQ. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_bcast.c | 65 +++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_bcast.h | 34 ++++++++++++++++ + 2 files changed, 99 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_bcast.c + create mode 100644 drivers/gpu/drm/lima/lima_bcast.h + +diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c +new file mode 100644 +index 000000000000..32012a61ea6a +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_bcast.c +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_bcast.h" ++#include "lima_regs.h" ++ ++#define bcast_write(reg, data) writel(data, ip->iomem + LIMA_BCAST_##reg) ++#define bcast_read(reg) readl(ip->iomem + LIMA_BCAST_##reg) ++ ++void lima_bcast_enable(struct lima_device *dev) ++{ ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ struct lima_ip *ip = dev->ip + lima_ip_bcast; ++ int i, mask = 0; ++ ++ for (i = 0; i < pipe->num_processor; i++) { ++ struct lima_ip *pp = pipe->processor[i]; ++ mask |= 1 << (pp->id - lima_ip_pp0); ++ } ++ ++ bcast_write(BROADCAST_MASK, (mask << 16) | mask); ++ bcast_write(INTERRUPT_MASK, mask); ++} ++ ++void lima_bcast_disable(struct lima_device *dev) ++{ ++ struct lima_ip *ip = dev->ip + lima_ip_bcast; ++ ++ bcast_write(BROADCAST_MASK, 0); ++ bcast_write(INTERRUPT_MASK, 0); ++} ++ ++int lima_bcast_init(struct lima_ip *ip) ++{ ++ return 0; ++} ++ ++void lima_bcast_fini(struct lima_ip *ip) ++{ ++ ++} ++ +diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h +new file mode 100644 +index 000000000000..abafd4f613c7 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_bcast.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __LIMA_BCAST_H__ ++#define __LIMA_BCAST_H__ ++ ++struct lima_ip; ++ ++int lima_bcast_init(struct lima_ip *ip); ++void lima_bcast_fini(struct lima_ip *ip); ++ ++void lima_bcast_enable(struct lima_device *dev); ++void lima_bcast_disable(struct lima_device *dev); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0052-drm-lima-add-DLBU-related-functions.patch b/patch/kernel/sunxi-dev/0052-drm-lima-add-DLBU-related-functions.patch new file mode 100644 index 000000000..a0c20cd19 --- /dev/null +++ b/patch/kernel/sunxi-dev/0052-drm-lima-add-DLBU-related-functions.patch @@ -0,0 +1,142 @@ +From ec275c7f186f53de7bf00ced46c8f0bbb3338e8d Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 14 May 2018 22:21:19 +0800 +Subject: [PATCH 052/146] drm/lima: add DLBU related functions + +DLBU is used to balance load among PPs. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_dlbu.c | 75 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_dlbu.h | 37 ++++++++++++++++ + 2 files changed, 112 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_dlbu.c + create mode 100644 drivers/gpu/drm/lima/lima_dlbu.h + +diff --git a/drivers/gpu/drm/lima/lima_dlbu.c b/drivers/gpu/drm/lima/lima_dlbu.c +new file mode 100644 +index 000000000000..5281dd3c0417 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_dlbu.c +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_dlbu.h" ++#include "lima_vm.h" ++#include "lima_regs.h" ++ ++#define dlbu_write(reg, data) writel(data, ip->iomem + LIMA_DLBU_##reg) ++#define dlbu_read(reg) readl(ip->iomem + LIMA_DLBU_##reg) ++ ++void lima_dlbu_enable(struct lima_device *dev) ++{ ++ struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ struct lima_ip *ip = dev->ip + lima_ip_dlbu; ++ int i, mask = 0; ++ ++ for (i = 0; i < pipe->num_processor; i++) { ++ struct lima_ip *pp = pipe->processor[i]; ++ mask |= 1 << (pp->id - lima_ip_pp0); ++ } ++ ++ dlbu_write(PP_ENABLE_MASK, mask); ++} ++ ++void lima_dlbu_disable(struct lima_device *dev) ++{ ++ struct lima_ip *ip = dev->ip + lima_ip_dlbu; ++ dlbu_write(PP_ENABLE_MASK, 0); ++} ++ ++void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg) ++{ ++ dlbu_write(TLLIST_VBASEADDR, reg[0]); ++ dlbu_write(FB_DIM, reg[1]); ++ dlbu_write(TLLIST_CONF, reg[2]); ++ dlbu_write(START_TILE_POS, reg[3]); ++} ++ ++int lima_dlbu_init(struct lima_ip *ip) ++{ ++ struct lima_device *dev = ip->dev; ++ ++ dlbu_write(MASTER_TLLIST_PHYS_ADDR, dev->dlbu_dma | 1); ++ dlbu_write(MASTER_TLLIST_VADDR, LIMA_VA_RESERVE_DLBU); ++ ++ return 0; ++} ++ ++void lima_dlbu_fini(struct lima_ip *ip) ++{ ++ ++} +diff --git a/drivers/gpu/drm/lima/lima_dlbu.h b/drivers/gpu/drm/lima/lima_dlbu.h +new file mode 100644 +index 000000000000..4521a5dda9e0 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_dlbu.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __LIMA_DLBU_H__ ++#define __LIMA_DLBU_H__ ++ ++struct lima_ip; ++struct lima_device; ++ ++void lima_dlbu_enable(struct lima_device *dev); ++void lima_dlbu_disable(struct lima_device *dev); ++ ++void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg); ++ ++int lima_dlbu_init(struct lima_ip *ip); ++void lima_dlbu_fini(struct lima_ip *ip); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0053-drm-lima-add-GPU-virtual-memory-space-handing.patch b/patch/kernel/sunxi-dev/0053-drm-lima-add-GPU-virtual-memory-space-handing.patch new file mode 100644 index 000000000..666cafcac --- /dev/null +++ b/patch/kernel/sunxi-dev/0053-drm-lima-add-GPU-virtual-memory-space-handing.patch @@ -0,0 +1,414 @@ +From 643a121d5e299aef668f8a87a7858b7f52e735d6 Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Mon, 14 May 2018 22:24:16 +0800 +Subject: [PATCH 053/146] drm/lima: add GPU virtual memory space handing + +Signed-off-by: Qiang Yu +Signed-off-by: Vasily Khoruzhick +--- + drivers/gpu/drm/lima/lima_vm.c | 312 +++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_vm.h | 73 ++++++++ + 2 files changed, 385 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_vm.c + create mode 100644 drivers/gpu/drm/lima/lima_vm.h + +diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c +new file mode 100644 +index 000000000000..00a3f6b59a33 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_vm.c +@@ -0,0 +1,312 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_vm.h" ++#include "lima_object.h" ++#include "lima_regs.h" ++ ++struct lima_bo_va_mapping { ++ struct list_head list; ++ struct rb_node rb; ++ uint32_t start; ++ uint32_t last; ++ uint32_t __subtree_last; ++}; ++ ++struct lima_bo_va { ++ struct list_head list; ++ unsigned ref_count; ++ ++ struct list_head mapping; ++ ++ struct lima_vm *vm; ++}; ++ ++#define LIMA_PDE(va) (va >> 22) ++#define LIMA_PTE(va) ((va & 0x3FFFFF) >> 12) ++ ++#define START(node) ((node)->start) ++#define LAST(node) ((node)->last) ++ ++INTERVAL_TREE_DEFINE(struct lima_bo_va_mapping, rb, uint32_t, __subtree_last, ++ START, LAST, static, lima_vm_it) ++ ++#undef START ++#undef LAST ++ ++static void lima_vm_unmap_page_table(struct lima_vm *vm, u32 start, u32 end) ++{ ++ u32 addr; ++ ++ for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) { ++ u32 pde = LIMA_PDE(addr); ++ u32 pte = LIMA_PTE(addr); ++ u32 *pt; ++ ++ pt = lima_bo_kmap(vm->pt[pde]); ++ pt[pte] = 0; ++ } ++} ++ ++static int lima_vm_map_page_table(struct lima_vm *vm, dma_addr_t *dma, ++ u32 start, u32 end) ++{ ++ u64 addr; ++ int err, i = 0; ++ ++ for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) { ++ u32 pde = LIMA_PDE(addr); ++ u32 pte = LIMA_PTE(addr); ++ u32 *pd, *pt; ++ ++ if (vm->pt[pde]) ++ pt = lima_bo_kmap(vm->pt[pde]); ++ else { ++ vm->pt[pde] = lima_bo_create( ++ vm->dev, LIMA_PAGE_SIZE, 0, ttm_bo_type_kernel, ++ NULL, vm->pd->tbo.resv); ++ if (IS_ERR(vm->pt[pde])) { ++ err = PTR_ERR(vm->pt[pde]); ++ goto err_out; ++ } ++ ++ pt = lima_bo_kmap(vm->pt[pde]); ++ if (IS_ERR(pt)) { ++ err = PTR_ERR(pt); ++ goto err_out; ++ } ++ ++ pd = lima_bo_kmap(vm->pd); ++ pd[pde] = *lima_bo_get_pages(vm->pt[pde]) | LIMA_VM_FLAG_PRESENT; ++ } ++ ++ pt[pte] = dma[i++] | LIMA_VM_FLAGS_CACHE; ++ } ++ ++ return 0; ++ ++err_out: ++ if (addr != start) ++ lima_vm_unmap_page_table(vm, start, addr - 1); ++ return err; ++} ++ ++static struct lima_bo_va * ++lima_vm_bo_find(struct lima_vm *vm, struct lima_bo *bo) ++{ ++ struct lima_bo_va *bo_va, *ret = NULL; ++ ++ list_for_each_entry(bo_va, &bo->va, list) { ++ if (bo_va->vm == vm) { ++ ret = bo_va; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++int lima_vm_bo_map(struct lima_vm *vm, struct lima_bo *bo, u32 start) ++{ ++ int err; ++ struct lima_bo_va_mapping *it, *mapping; ++ u32 end = start + bo->gem.size - 1; ++ dma_addr_t *pages_dma = lima_bo_get_pages(bo); ++ struct lima_bo_va *bo_va; ++ ++ it = lima_vm_it_iter_first(&vm->va, start, end); ++ if (it) { ++ dev_dbg(bo->gem.dev->dev, "lima vm map va overlap %x-%x %x-%x\n", ++ start, end, it->start, it->last); ++ return -EINVAL; ++ } ++ ++ mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); ++ if (!mapping) ++ return -ENOMEM; ++ mapping->start = start; ++ mapping->last = end; ++ ++ err = lima_vm_map_page_table(vm, pages_dma, start, end); ++ if (err) { ++ kfree(mapping); ++ return err; ++ } ++ ++ lima_vm_it_insert(mapping, &vm->va); ++ ++ bo_va = lima_vm_bo_find(vm, bo); ++ list_add_tail(&mapping->list, &bo_va->mapping); ++ ++ return 0; ++} ++ ++static void lima_vm_unmap(struct lima_vm *vm, ++ struct lima_bo_va_mapping *mapping) ++{ ++ lima_vm_it_remove(mapping, &vm->va); ++ ++ lima_vm_unmap_page_table(vm, mapping->start, mapping->last); ++ ++ list_del(&mapping->list); ++ kfree(mapping); ++} ++ ++int lima_vm_bo_unmap(struct lima_vm *vm, struct lima_bo *bo, u32 start) ++{ ++ struct lima_bo_va *bo_va; ++ struct lima_bo_va_mapping *mapping; ++ ++ bo_va = lima_vm_bo_find(vm, bo); ++ list_for_each_entry(mapping, &bo_va->mapping, list) { ++ if (mapping->start == start) { ++ lima_vm_unmap(vm, mapping); ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo) ++{ ++ struct lima_bo_va *bo_va; ++ ++ bo_va = lima_vm_bo_find(vm, bo); ++ if (bo_va) { ++ bo_va->ref_count++; ++ return 0; ++ } ++ ++ bo_va = kmalloc(sizeof(*bo_va), GFP_KERNEL); ++ if (!bo_va) ++ return -ENOMEM; ++ ++ bo_va->vm = vm; ++ bo_va->ref_count = 1; ++ INIT_LIST_HEAD(&bo_va->mapping); ++ list_add_tail(&bo_va->list, &bo->va); ++ return 0; ++} ++ ++int lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo) ++{ ++ struct lima_bo_va *bo_va; ++ struct lima_bo_va_mapping *mapping, *tmp; ++ ++ bo_va = lima_vm_bo_find(vm, bo); ++ if (--bo_va->ref_count > 0) ++ return 0; ++ ++ list_for_each_entry_safe(mapping, tmp, &bo_va->mapping, list) { ++ lima_vm_unmap(vm, mapping); ++ } ++ list_del(&bo_va->list); ++ kfree(bo_va); ++ return 0; ++} ++ ++struct lima_vm *lima_vm_create(struct lima_device *dev) ++{ ++ struct lima_vm *vm; ++ void *pd; ++ ++ vm = kzalloc(sizeof(*vm), GFP_KERNEL); ++ if (!vm) ++ return NULL; ++ ++ vm->dev = dev; ++ vm->va = RB_ROOT_CACHED; ++ kref_init(&vm->refcount); ++ ++ vm->pd = lima_bo_create(dev, LIMA_PAGE_SIZE, 0, ++ ttm_bo_type_kernel, NULL, NULL); ++ if (IS_ERR(vm->pd)) ++ goto err_out0; ++ ++ pd = lima_bo_kmap(vm->pd); ++ if (IS_ERR(pd)) ++ goto err_out1; ++ ++ if (dev->dlbu_cpu) { ++ int err = lima_vm_map_page_table( ++ vm, &dev->dlbu_dma, LIMA_VA_RESERVE_DLBU, ++ LIMA_VA_RESERVE_DLBU + LIMA_PAGE_SIZE - 1); ++ if (err) ++ goto err_out1; ++ } ++ ++ return vm; ++ ++err_out1: ++ lima_bo_unref(vm->pd); ++err_out0: ++ kfree(vm); ++ return NULL; ++} ++ ++void lima_vm_release(struct kref *kref) ++{ ++ struct lima_vm *vm = container_of(kref, struct lima_vm, refcount); ++ struct lima_device *dev = vm->dev; ++ int i; ++ ++ if (!RB_EMPTY_ROOT(&vm->va.rb_root)) { ++ dev_err(dev->dev, "still active bo inside vm\n"); ++ } ++ ++ for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) { ++ if (vm->pt[i]) ++ lima_bo_unref(vm->pt[i]); ++ } ++ ++ if (vm->pd) ++ lima_bo_unref(vm->pd); ++ ++ kfree(vm); ++} ++ ++void lima_vm_print(struct lima_vm *vm) ++{ ++ int i, j; ++ u32 *pd = lima_bo_kmap(vm->pd); ++ ++ /* to avoid the defined by not used warning */ ++ (void)&lima_vm_it_iter_next; ++ ++ for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) { ++ if (pd[i]) { ++ u32 *pt = lima_bo_kmap(vm->pt[i]); ++ ++ printk(KERN_INFO "lima vm pd %03x:%08x\n", i, pd[i]); ++ for (j = 0; j < LIMA_PAGE_ENT_NUM; j++) { ++ if (pt[j]) ++ printk(KERN_INFO " pt %03x:%08x\n", j, pt[j]); ++ } ++ } ++ } ++} +diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h +new file mode 100644 +index 000000000000..20506459def0 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_vm.h +@@ -0,0 +1,73 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_VM_H__ ++#define __LIMA_VM_H__ ++ ++#include ++#include ++ ++#define LIMA_PAGE_SIZE 4096 ++#define LIMA_PAGE_MASK (LIMA_PAGE_SIZE - 1) ++#define LIMA_PAGE_ENT_NUM (LIMA_PAGE_SIZE / sizeof(u32)) ++ ++#define LIMA_VA_RESERVE_START 0xFFF00000 ++#define LIMA_VA_RESERVE_DLBU LIMA_VA_RESERVE_START ++#define LIMA_VA_RESERVE_END 0x100000000 ++ ++struct lima_bo; ++struct lima_device; ++ ++struct lima_vm { ++ struct kref refcount; ++ ++ /* tree of virtual addresses mapped */ ++ struct rb_root_cached va; ++ ++ struct lima_device *dev; ++ ++ struct lima_bo *pd; ++ struct lima_bo *pt[LIMA_PAGE_ENT_NUM]; ++}; ++ ++int lima_vm_bo_map(struct lima_vm *vm, struct lima_bo *bo, u32 start); ++int lima_vm_bo_unmap(struct lima_vm *vm, struct lima_bo *bo, u32 start); ++ ++int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo); ++int lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo); ++ ++struct lima_vm *lima_vm_create(struct lima_device *dev); ++void lima_vm_release(struct kref *kref); ++ ++static inline struct lima_vm *lima_vm_get(struct lima_vm *vm) ++{ ++ kref_get(&vm->refcount); ++ return vm; ++} ++ ++static inline void lima_vm_put(struct lima_vm *vm) ++{ ++ kref_put(&vm->refcount, lima_vm_release); ++} ++ ++void lima_vm_print(struct lima_vm *vm); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0054-drm-lima-add-TTM-subsystem-functions.patch b/patch/kernel/sunxi-dev/0054-drm-lima-add-TTM-subsystem-functions.patch new file mode 100644 index 000000000..b7faced92 --- /dev/null +++ b/patch/kernel/sunxi-dev/0054-drm-lima-add-TTM-subsystem-functions.patch @@ -0,0 +1,481 @@ +From f31bbd84c9aab62a0aee72e540d9d8c9d998a958 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 14 May 2018 22:28:36 +0800 +Subject: [PATCH 054/146] drm/lima: add TTM subsystem functions + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_ttm.c | 409 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_ttm.h | 44 ++++ + 2 files changed, 453 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_ttm.c + create mode 100644 drivers/gpu/drm/lima/lima_ttm.h + +diff --git a/drivers/gpu/drm/lima/lima_ttm.c b/drivers/gpu/drm/lima/lima_ttm.c +new file mode 100644 +index 000000000000..5325f3f48ae7 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_ttm.c +@@ -0,0 +1,409 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "lima_drv.h" ++#include "lima_device.h" ++#include "lima_object.h" ++ ++ ++static int lima_ttm_mem_global_init(struct drm_global_reference *ref) ++{ ++ return ttm_mem_global_init(ref->object); ++} ++ ++static void lima_ttm_mem_global_release(struct drm_global_reference *ref) ++{ ++ ttm_mem_global_release(ref->object); ++} ++ ++static int lima_ttm_global_init(struct lima_device *dev) ++{ ++ struct drm_global_reference *global_ref; ++ int err; ++ ++ dev->mman.mem_global_referenced = false; ++ global_ref = &dev->mman.mem_global_ref; ++ global_ref->global_type = DRM_GLOBAL_TTM_MEM; ++ global_ref->size = sizeof(struct ttm_mem_global); ++ global_ref->init = &lima_ttm_mem_global_init; ++ global_ref->release = &lima_ttm_mem_global_release; ++ ++ err = drm_global_item_ref(global_ref); ++ if (err != 0) { ++ dev_err(dev->dev, "Failed setting up TTM memory accounting " ++ "subsystem.\n"); ++ return err; ++ } ++ ++ dev->mman.bo_global_ref.mem_glob = ++ dev->mman.mem_global_ref.object; ++ global_ref = &dev->mman.bo_global_ref.ref; ++ global_ref->global_type = DRM_GLOBAL_TTM_BO; ++ global_ref->size = sizeof(struct ttm_bo_global); ++ global_ref->init = &ttm_bo_global_init; ++ global_ref->release = &ttm_bo_global_release; ++ err = drm_global_item_ref(global_ref); ++ if (err != 0) { ++ dev_err(dev->dev, "Failed setting up TTM BO subsystem.\n"); ++ drm_global_item_unref(&dev->mman.mem_global_ref); ++ return err; ++ } ++ ++ dev->mman.mem_global_referenced = true; ++ return 0; ++} ++ ++static void lima_ttm_global_fini(struct lima_device *dev) ++{ ++ if (dev->mman.mem_global_referenced) { ++ drm_global_item_unref(&dev->mman.bo_global_ref.ref); ++ drm_global_item_unref(&dev->mman.mem_global_ref); ++ dev->mman.mem_global_referenced = false; ++ } ++} ++ ++struct lima_tt_mgr { ++ spinlock_t lock; ++ unsigned long available; ++}; ++ ++static int lima_ttm_bo_man_init(struct ttm_mem_type_manager *man, ++ unsigned long p_size) ++{ ++ struct lima_tt_mgr *mgr; ++ ++ mgr = kmalloc(sizeof(*mgr), GFP_KERNEL); ++ if (!mgr) ++ return -ENOMEM; ++ ++ spin_lock_init(&mgr->lock); ++ mgr->available = p_size; ++ man->priv = mgr; ++ return 0; ++} ++ ++static int lima_ttm_bo_man_takedown(struct ttm_mem_type_manager *man) ++{ ++ struct lima_tt_mgr *mgr = man->priv; ++ ++ kfree(mgr); ++ man->priv = NULL; ++ return 0; ++} ++ ++static int lima_ttm_bo_man_get_node(struct ttm_mem_type_manager *man, ++ struct ttm_buffer_object *bo, ++ const struct ttm_place *place, ++ struct ttm_mem_reg *mem) ++{ ++ struct lima_tt_mgr *mgr = man->priv; ++ ++ /* don't exceed the mem limit */ ++ spin_lock(&mgr->lock); ++ if (mgr->available < mem->num_pages) { ++ spin_unlock(&mgr->lock); ++ return 0; ++ } ++ mgr->available -= mem->num_pages; ++ spin_unlock(&mgr->lock); ++ ++ /* just fake a non-null pointer to tell caller success */ ++ mem->mm_node = (void *)1; ++ return 0; ++} ++ ++static void lima_ttm_bo_man_put_node(struct ttm_mem_type_manager *man, ++ struct ttm_mem_reg *mem) ++{ ++ struct lima_tt_mgr *mgr = man->priv; ++ ++ spin_lock(&mgr->lock); ++ mgr->available += mem->num_pages; ++ spin_unlock(&mgr->lock); ++ ++ mem->mm_node = NULL; ++} ++ ++static void lima_ttm_bo_man_debug(struct ttm_mem_type_manager *man, ++ struct drm_printer *printer) ++{ ++} ++ ++static const struct ttm_mem_type_manager_func lima_bo_manager_func = { ++ .init = lima_ttm_bo_man_init, ++ .takedown = lima_ttm_bo_man_takedown, ++ .get_node = lima_ttm_bo_man_get_node, ++ .put_node = lima_ttm_bo_man_put_node, ++ .debug = lima_ttm_bo_man_debug ++}; ++ ++static int lima_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, ++ struct ttm_mem_type_manager *man) ++{ ++ struct lima_device *dev = ttm_to_lima_dev(bdev); ++ ++ switch (type) { ++ case TTM_PL_SYSTEM: ++ /* System memory */ ++ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; ++ man->available_caching = TTM_PL_MASK_CACHING; ++ man->default_caching = TTM_PL_FLAG_CACHED; ++ break; ++ case TTM_PL_TT: ++ man->func = &lima_bo_manager_func; ++ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; ++ man->available_caching = TTM_PL_MASK_CACHING; ++ man->default_caching = TTM_PL_FLAG_CACHED; ++ break; ++ default: ++ dev_err(dev->dev, "Unsupported memory type %u\n", ++ (unsigned int)type); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int lima_ttm_backend_bind(struct ttm_tt *ttm, ++ struct ttm_mem_reg *bo_mem) ++{ ++ return 0; ++} ++ ++static int lima_ttm_backend_unbind(struct ttm_tt *ttm) ++{ ++ return 0; ++} ++ ++static void lima_ttm_backend_destroy(struct ttm_tt *ttm) ++{ ++ struct lima_ttm_tt *tt = (void *)ttm; ++ ++ ttm_dma_tt_fini(&tt->ttm); ++ kfree(tt); ++} ++ ++static struct ttm_backend_func lima_ttm_backend_func = { ++ .bind = &lima_ttm_backend_bind, ++ .unbind = &lima_ttm_backend_unbind, ++ .destroy = &lima_ttm_backend_destroy, ++}; ++ ++static struct ttm_tt *lima_ttm_tt_create(struct ttm_buffer_object *bo, ++ uint32_t page_flags) ++{ ++ struct lima_ttm_tt *tt; ++ ++ tt = kzalloc(sizeof(struct lima_ttm_tt), GFP_KERNEL); ++ if (tt == NULL) ++ return NULL; ++ ++ tt->ttm.ttm.func = &lima_ttm_backend_func; ++ ++ if (ttm_sg_tt_init(&tt->ttm, bo, page_flags)) { ++ kfree(tt); ++ return NULL; ++ } ++ ++ return &tt->ttm.ttm; ++} ++ ++static int lima_ttm_tt_populate(struct ttm_tt *ttm, ++ struct ttm_operation_ctx *ctx) ++{ ++ struct lima_device *dev = ttm_to_lima_dev(ttm->bdev); ++ struct lima_ttm_tt *tt = (void *)ttm; ++ bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); ++ ++ if (slave) { ++ drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, ++ tt->ttm.dma_address, ++ ttm->num_pages); ++ ttm->state = tt_unbound; ++ return 0; ++ } ++ ++ return ttm_populate_and_map_pages(dev->dev, &tt->ttm, ctx); ++} ++ ++static void lima_ttm_tt_unpopulate(struct ttm_tt *ttm) ++{ ++ struct lima_device *dev = ttm_to_lima_dev(ttm->bdev); ++ struct lima_ttm_tt *tt = (void *)ttm; ++ bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); ++ ++ if (slave) ++ return; ++ ++ ttm_unmap_and_unpopulate_pages(dev->dev, &tt->ttm); ++} ++ ++static int lima_invalidate_caches(struct ttm_bo_device *bdev, ++ uint32_t flags) ++{ ++ struct lima_device *dev = ttm_to_lima_dev(bdev); ++ ++ dev_err(dev->dev, "%s not implemented\n", __FUNCTION__); ++ return 0; ++} ++ ++static void lima_evict_flags(struct ttm_buffer_object *tbo, ++ struct ttm_placement *placement) ++{ ++ struct lima_bo *bo = ttm_to_lima_bo(tbo); ++ struct lima_device *dev = to_lima_dev(bo->gem.dev); ++ ++ dev_err(dev->dev, "%s not implemented\n", __FUNCTION__); ++} ++ ++static int lima_verify_access(struct ttm_buffer_object *tbo, ++ struct file *filp) ++{ ++ struct lima_bo *bo = ttm_to_lima_bo(tbo); ++ ++ return drm_vma_node_verify_access(&bo->gem.vma_node, ++ filp->private_data); ++} ++ ++static int lima_ttm_io_mem_reserve(struct ttm_bo_device *bdev, ++ struct ttm_mem_reg *mem) ++{ ++ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; ++ ++ mem->bus.addr = NULL; ++ mem->bus.offset = 0; ++ mem->bus.size = mem->num_pages << PAGE_SHIFT; ++ mem->bus.base = 0; ++ mem->bus.is_iomem = false; ++ ++ if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) ++ return -EINVAL; ++ ++ switch (mem->mem_type) { ++ case TTM_PL_SYSTEM: ++ case TTM_PL_TT: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static void lima_ttm_io_mem_free(struct ttm_bo_device *bdev, ++ struct ttm_mem_reg *mem) ++{ ++ ++} ++ ++static void lima_bo_move_notify(struct ttm_buffer_object *tbo, bool evict, ++ struct ttm_mem_reg *new_mem) ++{ ++ struct lima_bo *bo = ttm_to_lima_bo(tbo); ++ struct lima_device *dev = to_lima_dev(bo->gem.dev); ++ ++ if (evict) ++ dev_err(dev->dev, "%s not implemented\n", __FUNCTION__); ++} ++ ++static void lima_bo_swap_notify(struct ttm_buffer_object *tbo) ++{ ++ struct lima_bo *bo = ttm_to_lima_bo(tbo); ++ struct lima_device *dev = to_lima_dev(bo->gem.dev); ++ ++ dev_err(dev->dev, "%s not implemented\n", __FUNCTION__); ++} ++ ++static struct ttm_bo_driver lima_bo_driver = { ++ .ttm_tt_create = lima_ttm_tt_create, ++ .ttm_tt_populate = lima_ttm_tt_populate, ++ .ttm_tt_unpopulate = lima_ttm_tt_unpopulate, ++ .invalidate_caches = lima_invalidate_caches, ++ .init_mem_type = lima_init_mem_type, ++ .eviction_valuable = ttm_bo_eviction_valuable, ++ .evict_flags = lima_evict_flags, ++ .verify_access = lima_verify_access, ++ .io_mem_reserve = lima_ttm_io_mem_reserve, ++ .io_mem_free = lima_ttm_io_mem_free, ++ .move_notify = lima_bo_move_notify, ++ .swap_notify = lima_bo_swap_notify, ++}; ++ ++int lima_ttm_init(struct lima_device *dev) ++{ ++ int err; ++ bool need_dma32; ++ u64 gtt_size; ++ ++ err = lima_ttm_global_init(dev); ++ if (err) ++ return err; ++ ++#if defined(CONFIG_ARM) && !defined(CONFIG_ARM_LPAE) ++ need_dma32 = false; ++#else ++ need_dma32 = true; ++#endif ++ ++ err = ttm_bo_device_init(&dev->mman.bdev, ++ dev->mman.bo_global_ref.ref.object, ++ &lima_bo_driver, ++ dev->ddev->anon_inode->i_mapping, ++ DRM_FILE_PAGE_OFFSET, ++ need_dma32); ++ if (err) { ++ dev_err(dev->dev, "failed initializing buffer object " ++ "driver(%d).\n", err); ++ goto err_out0; ++ } ++ ++ if (lima_max_mem < 0) { ++ struct sysinfo si; ++ si_meminfo(&si); ++ /* TODO: better to have lower 32 mem size */ ++ gtt_size = min(((u64)si.totalram * si.mem_unit * 3/4), ++ 0x100000000ULL); ++ } ++ else ++ gtt_size = (u64)lima_max_mem << 20; ++ ++ err = ttm_bo_init_mm(&dev->mman.bdev, TTM_PL_TT, gtt_size >> PAGE_SHIFT); ++ if (err) { ++ dev_err(dev->dev, "Failed initializing GTT heap.\n"); ++ goto err_out1; ++ } ++ return 0; ++ ++err_out1: ++ ttm_bo_device_release(&dev->mman.bdev); ++err_out0: ++ lima_ttm_global_fini(dev); ++ return err; ++} ++ ++void lima_ttm_fini(struct lima_device *dev) ++{ ++ ttm_bo_device_release(&dev->mman.bdev); ++ lima_ttm_global_fini(dev); ++ dev_info(dev->dev, "ttm finalized\n"); ++} +diff --git a/drivers/gpu/drm/lima/lima_ttm.h b/drivers/gpu/drm/lima/lima_ttm.h +new file mode 100644 +index 000000000000..1d36d06a47a3 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_ttm.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_TTM_H__ ++#define __LIMA_TTM_H__ ++ ++#include ++ ++struct lima_mman { ++ struct ttm_bo_global_ref bo_global_ref; ++ struct drm_global_reference mem_global_ref; ++ struct ttm_bo_device bdev; ++ bool mem_global_referenced; ++}; ++ ++struct lima_ttm_tt { ++ struct ttm_dma_tt ttm; ++}; ++ ++struct lima_device; ++struct lima_bo; ++ ++int lima_ttm_init(struct lima_device *dev); ++void lima_ttm_fini(struct lima_device *dev); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0055-drm-lima-add-buffer-object-functions.patch b/patch/kernel/sunxi-dev/0055-drm-lima-add-buffer-object-functions.patch new file mode 100644 index 000000000..b9542191c --- /dev/null +++ b/patch/kernel/sunxi-dev/0055-drm-lima-add-buffer-object-functions.patch @@ -0,0 +1,235 @@ +From bde1f6b4f2fc7c20343e175ea9f1ef18f0aaedfa Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Wed, 16 May 2018 10:31:44 +0800 +Subject: [PATCH 055/146] drm/lima: add buffer object functions + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_object.c | 120 +++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_object.h | 87 +++++++++++++++++++++ + 2 files changed, 207 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_object.c + create mode 100644 drivers/gpu/drm/lima/lima_object.h + +diff --git a/drivers/gpu/drm/lima/lima_object.c b/drivers/gpu/drm/lima/lima_object.c +new file mode 100644 +index 000000000000..5a22b235626b +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_object.c +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++ ++#include "lima_object.h" ++ ++static void lima_bo_init_placement(struct lima_bo *bo) ++{ ++ struct ttm_placement *placement = &bo->placement; ++ struct ttm_place *place = &bo->place; ++ ++ place->fpfn = 0; ++ place->lpfn = 0; ++ place->flags = TTM_PL_FLAG_TT | TTM_PL_FLAG_WC; ++ ++ /* pin all bo for now */ ++ place->flags |= TTM_PL_FLAG_NO_EVICT; ++ ++ placement->num_placement = 1; ++ placement->placement = place; ++ ++ placement->num_busy_placement = 1; ++ placement->busy_placement = place; ++} ++ ++static void lima_bo_destroy(struct ttm_buffer_object *tbo) ++{ ++ struct lima_bo *bo = ttm_to_lima_bo(tbo); ++ ++ if (bo->gem.import_attach) ++ drm_prime_gem_destroy(&bo->gem, bo->tbo.sg); ++ drm_gem_object_release(&bo->gem); ++ kfree(bo); ++} ++ ++struct lima_bo *lima_bo_create(struct lima_device *dev, u64 size, ++ u32 flags, enum ttm_bo_type type, ++ struct sg_table *sg, ++ struct reservation_object *resv) ++{ ++ struct lima_bo *bo; ++ struct ttm_mem_type_manager *man; ++ size_t acc_size; ++ int err; ++ ++ size = PAGE_ALIGN(size); ++ man = dev->mman.bdev.man + TTM_PL_TT; ++ if (size >= (man->size << PAGE_SHIFT)) ++ return ERR_PTR(-ENOMEM); ++ ++ acc_size = ttm_bo_dma_acc_size(&dev->mman.bdev, size, ++ sizeof(struct lima_bo)); ++ ++ bo = kzalloc(sizeof(*bo), GFP_KERNEL); ++ if (!bo) ++ return ERR_PTR(-ENOMEM); ++ ++ drm_gem_private_object_init(dev->ddev, &bo->gem, size); ++ ++ INIT_LIST_HEAD(&bo->va); ++ ++ bo->tbo.bdev = &dev->mman.bdev; ++ ++ lima_bo_init_placement(bo); ++ ++ err = ttm_bo_init(&dev->mman.bdev, &bo->tbo, size, type, ++ &bo->placement, 0, type != ttm_bo_type_kernel, ++ acc_size, sg, resv, &lima_bo_destroy); ++ if (err) ++ goto err_out; ++ ++ return bo; ++ ++err_out: ++ kfree(bo); ++ return ERR_PTR(err); ++} ++ ++dma_addr_t *lima_bo_get_pages(struct lima_bo *bo) ++{ ++ struct lima_ttm_tt *ttm = (void *)bo->tbo.ttm; ++ return ttm->ttm.dma_address; ++} ++ ++void *lima_bo_kmap(struct lima_bo *bo) ++{ ++ bool is_iomem; ++ void *ret; ++ int err; ++ ++ ret = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem); ++ if (ret) ++ return ret; ++ ++ err = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap); ++ if (err) ++ return ERR_PTR(err); ++ ++ return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem); ++} +diff --git a/drivers/gpu/drm/lima/lima_object.h b/drivers/gpu/drm/lima/lima_object.h +new file mode 100644 +index 000000000000..2b8b8fcb9063 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_object.h +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_OBJECT_H__ ++#define __LIMA_OBJECT_H__ ++ ++#include ++#include ++#include ++ ++#include "lima_device.h" ++ ++struct lima_bo { ++ struct drm_gem_object gem; ++ ++ struct ttm_place place; ++ struct ttm_placement placement; ++ struct ttm_buffer_object tbo; ++ struct ttm_bo_kmap_obj kmap; ++ ++ struct list_head va; ++}; ++ ++static inline struct lima_bo * ++to_lima_bo(struct drm_gem_object *obj) ++{ ++ return container_of(obj, struct lima_bo, gem); ++} ++ ++static inline struct lima_bo * ++ttm_to_lima_bo(struct ttm_buffer_object *tbo) ++{ ++ return container_of(tbo, struct lima_bo, tbo); ++} ++ ++static inline int lima_bo_reserve(struct lima_bo *bo, bool intr) ++{ ++ struct lima_device *dev = ttm_to_lima_dev(bo->tbo.bdev); ++ int r; ++ ++ r = ttm_bo_reserve(&bo->tbo, intr, false, NULL); ++ if (unlikely(r != 0)) { ++ if (r != -ERESTARTSYS) ++ dev_err(dev->dev, "%p reserve failed\n", bo); ++ return r; ++ } ++ return 0; ++} ++ ++static inline void lima_bo_unreserve(struct lima_bo *bo) ++{ ++ ttm_bo_unreserve(&bo->tbo); ++} ++ ++struct lima_bo *lima_bo_create(struct lima_device *dev, u64 size, ++ u32 flags, enum ttm_bo_type type, ++ struct sg_table *sg, ++ struct reservation_object *resv); ++ ++static inline void lima_bo_unref(struct lima_bo *bo) ++{ ++ struct ttm_buffer_object *tbo = &bo->tbo; ++ ttm_bo_unref(&tbo); ++} ++ ++dma_addr_t *lima_bo_get_pages(struct lima_bo *bo); ++void *lima_bo_kmap(struct lima_bo *bo); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0056-drm-lima-add-GEM-related-functions.patch b/patch/kernel/sunxi-dev/0056-drm-lima-add-GEM-related-functions.patch new file mode 100644 index 000000000..2cc84aa11 --- /dev/null +++ b/patch/kernel/sunxi-dev/0056-drm-lima-add-GEM-related-functions.patch @@ -0,0 +1,530 @@ +From fda6ccdbd4930361a5a1dce1d2adf0998f63441e Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Wed, 16 May 2018 10:34:29 +0800 +Subject: [PATCH 056/146] drm/lima: add GEM related functions + +Signed-off-by: Qiang Yu +Signed-off-by: Erico Nunes +Signed-off-by: Heiko Stuebner +--- + drivers/gpu/drm/lima/lima_gem.c | 459 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_gem.h | 41 +++ + 2 files changed, 500 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_gem.c + create mode 100644 drivers/gpu/drm/lima/lima_gem.h + +diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c +new file mode 100644 +index 000000000000..1ad3f38ddfde +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_gem.c +@@ -0,0 +1,459 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "lima_drv.h" ++#include "lima_gem.h" ++#include "lima_vm.h" ++#include "lima_object.h" ++ ++int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, ++ u32 size, u32 flags, u32 *handle) ++{ ++ int err; ++ struct lima_bo *bo; ++ struct lima_device *ldev = to_lima_dev(dev); ++ ++ bo = lima_bo_create(ldev, size, flags, ttm_bo_type_device, NULL, NULL); ++ if (IS_ERR(bo)) ++ return PTR_ERR(bo); ++ ++ err = drm_gem_handle_create(file, &bo->gem, handle); ++ ++ /* drop reference from allocate - handle holds it now */ ++ drm_gem_object_put_unlocked(&bo->gem); ++ ++ return err; ++} ++ ++void lima_gem_free_object(struct drm_gem_object *obj) ++{ ++ struct lima_bo *bo = to_lima_bo(obj); ++ ++ if (!list_empty(&bo->va)) ++ dev_err(obj->dev->dev, "lima gem free bo still has va\n"); ++ ++ lima_bo_unref(bo); ++} ++ ++int lima_gem_object_open(struct drm_gem_object *obj, struct drm_file *file) ++{ ++ struct lima_bo *bo = to_lima_bo(obj); ++ struct lima_drm_priv *priv = to_lima_drm_priv(file); ++ struct lima_vm *vm = priv->vm; ++ int err; ++ ++ err = lima_bo_reserve(bo, true); ++ if (err) ++ return err; ++ ++ err = lima_vm_bo_add(vm, bo); ++ ++ lima_bo_unreserve(bo); ++ return err; ++} ++ ++void lima_gem_object_close(struct drm_gem_object *obj, struct drm_file *file) ++{ ++ struct lima_bo *bo = to_lima_bo(obj); ++ struct lima_device *dev = to_lima_dev(obj->dev); ++ struct lima_drm_priv *priv = to_lima_drm_priv(file); ++ struct lima_vm *vm = priv->vm; ++ ++ LIST_HEAD(list); ++ struct ttm_validate_buffer tv_bo, tv_pd; ++ struct ww_acquire_ctx ticket; ++ int r; ++ ++ tv_bo.bo = &bo->tbo; ++ tv_bo.shared = true; ++ list_add(&tv_bo.head, &list); ++ ++ tv_pd.bo = &vm->pd->tbo; ++ tv_pd.shared = true; ++ list_add(&tv_pd.head, &list); ++ ++ r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); ++ if (r) { ++ dev_err(dev->dev, "leeking bo va because we " ++ "fail to reserve bo (%d)\n", r); ++ return; ++ } ++ ++ lima_vm_bo_del(vm, bo); ++ ++ ttm_eu_backoff_reservation(&ticket, &list); ++} ++ ++int lima_gem_mmap_offset(struct drm_file *file, u32 handle, u64 *offset) ++{ ++ struct drm_gem_object *obj; ++ struct lima_bo *bo; ++ ++ obj = drm_gem_object_lookup(file, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ bo = to_lima_bo(obj); ++ *offset = drm_vma_node_offset_addr(&bo->tbo.vma_node); ++ ++ drm_gem_object_put_unlocked(obj); ++ return 0; ++} ++ ++int lima_gem_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ struct drm_file *file_priv; ++ struct lima_device *dev; ++ ++ if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) ++ return -EINVAL; ++ ++ file_priv = filp->private_data; ++ dev = file_priv->minor->dev->dev_private; ++ if (dev == NULL) ++ return -EINVAL; ++ ++ return ttm_bo_mmap(filp, vma, &dev->mman.bdev); ++} ++ ++int lima_gem_va_map(struct drm_file *file, u32 handle, u32 flags, u32 va) ++{ ++ struct lima_drm_priv *priv = to_lima_drm_priv(file); ++ struct lima_vm *vm = priv->vm; ++ struct drm_gem_object *obj; ++ struct lima_bo *bo; ++ struct lima_device *dev; ++ int err; ++ ++ LIST_HEAD(list); ++ struct ttm_validate_buffer tv_bo, tv_pd; ++ struct ww_acquire_ctx ticket; ++ ++ if (!PAGE_ALIGNED(va)) ++ return -EINVAL; ++ ++ obj = drm_gem_object_lookup(file, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ bo = to_lima_bo(obj); ++ dev = to_lima_dev(obj->dev); ++ ++ /* carefully handle overflow when calculate range */ ++ if (va < dev->va_start || dev->va_end - obj->size < va) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ tv_bo.bo = &bo->tbo; ++ tv_bo.shared = true; ++ list_add(&tv_bo.head, &list); ++ ++ tv_pd.bo = &vm->pd->tbo; ++ tv_pd.shared = true; ++ list_add(&tv_pd.head, &list); ++ ++ err = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); ++ if (err) ++ goto out; ++ ++ err = lima_vm_bo_map(vm, bo, va); ++ ++ ttm_eu_backoff_reservation(&ticket, &list); ++out: ++ drm_gem_object_put_unlocked(obj); ++ return err; ++} ++ ++int lima_gem_va_unmap(struct drm_file *file, u32 handle, u32 va) ++{ ++ struct lima_drm_priv *priv = to_lima_drm_priv(file); ++ struct lima_vm *vm = priv->vm; ++ struct drm_gem_object *obj; ++ struct lima_bo *bo; ++ int err; ++ ++ LIST_HEAD(list); ++ struct ttm_validate_buffer tv_bo, tv_pd; ++ struct ww_acquire_ctx ticket; ++ ++ if (!PAGE_ALIGNED(va)) ++ return -EINVAL; ++ ++ obj = drm_gem_object_lookup(file, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ bo = to_lima_bo(obj); ++ ++ tv_bo.bo = &bo->tbo; ++ tv_bo.shared = true; ++ list_add(&tv_bo.head, &list); ++ ++ tv_pd.bo = &vm->pd->tbo; ++ tv_pd.shared = true; ++ list_add(&tv_pd.head, &list); ++ ++ err = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); ++ if (err) ++ goto out; ++ ++ err = lima_vm_bo_unmap(vm, bo, va); ++ ++ ttm_eu_backoff_reservation(&ticket, &list); ++out: ++ drm_gem_object_put_unlocked(obj); ++ return err; ++} ++ ++static int lima_gem_sync_bo(struct lima_sched_task *task, struct lima_bo *bo, ++ bool write, bool explicit) ++{ ++ int i, err; ++ struct dma_fence *f; ++ u64 context = task->base.s_fence->finished.context; ++ ++ if (!write) { ++ err = reservation_object_reserve_shared(bo->tbo.resv); ++ if (err) ++ return err; ++ } ++ ++ /* explicit sync use user passed dep fence */ ++ if (explicit) ++ return 0; ++ ++ /* implicit sync use bo fence in resv obj */ ++ if (write) { ++ struct reservation_object_list *fobj = ++ reservation_object_get_list(bo->tbo.resv); ++ ++ if (fobj && fobj->shared_count > 0) { ++ for (i = 0; i < fobj->shared_count; i++) { ++ f = rcu_dereference_protected( ++ fobj->shared[i], ++ reservation_object_held(bo->tbo.resv)); ++ if (f->context != context) { ++ err = lima_sched_task_add_dep(task, f); ++ if (err) ++ return err; ++ } ++ } ++ } ++ } ++ ++ f = reservation_object_get_excl(bo->tbo.resv); ++ if (f) { ++ err = lima_sched_task_add_dep(task, f); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int lima_gem_add_deps(struct lima_ctx_mgr *mgr, struct lima_submit *submit) ++{ ++ int i, err = 0; ++ ++ for (i = 0; i < submit->nr_deps; i++) { ++ union drm_lima_gem_submit_dep *dep = submit->deps + i; ++ struct dma_fence *fence; ++ ++ if (dep->type == LIMA_SUBMIT_DEP_FENCE) { ++ fence = lima_ctx_get_native_fence( ++ mgr, dep->fence.ctx, dep->fence.pipe, ++ dep->fence.seq); ++ if (IS_ERR(fence)) { ++ err = PTR_ERR(fence); ++ break; ++ } ++ } ++ else if (dep->type == LIMA_SUBMIT_DEP_SYNC_FD) { ++ fence = sync_file_get_fence(dep->sync_fd.fd); ++ if (!fence) { ++ err = -EINVAL; ++ break; ++ } ++ } ++ else { ++ err = -EINVAL; ++ break; ++ } ++ ++ if (fence) { ++ err = lima_sched_task_add_dep(submit->task, fence); ++ dma_fence_put(fence); ++ if (err) ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++static int lima_gem_get_sync_fd(struct dma_fence *fence) ++{ ++ struct sync_file *sync_file; ++ int fd; ++ ++ fd = get_unused_fd_flags(O_CLOEXEC); ++ if (fd < 0) ++ return fd; ++ ++ sync_file = sync_file_create(fence); ++ if (!sync_file) { ++ put_unused_fd(fd); ++ return -ENOMEM; ++ } ++ ++ fd_install(fd, sync_file->file); ++ return fd; ++} ++ ++int lima_gem_submit(struct drm_file *file, struct lima_submit *submit) ++{ ++ int i, err = 0; ++ struct lima_drm_priv *priv = to_lima_drm_priv(file); ++ struct lima_vm *vm = priv->vm; ++ ++ INIT_LIST_HEAD(&submit->validated); ++ INIT_LIST_HEAD(&submit->duplicates); ++ ++ for (i = 0; i < submit->nr_bos; i++) { ++ struct drm_gem_object *obj; ++ struct drm_lima_gem_submit_bo *bo = submit->bos + i; ++ struct ttm_validate_buffer *vb = submit->vbs + i; ++ ++ obj = drm_gem_object_lookup(file, bo->handle); ++ if (!obj) { ++ err = -ENOENT; ++ goto out0; ++ } ++ ++ vb->bo = &to_lima_bo(obj)->tbo; ++ vb->shared = !(bo->flags & LIMA_SUBMIT_BO_WRITE); ++ list_add_tail(&vb->head, &submit->validated); ++ } ++ ++ submit->vm_pd_vb.bo = &vm->pd->tbo; ++ submit->vm_pd_vb.shared = true; ++ list_add(&submit->vm_pd_vb.head, &submit->validated); ++ ++ err = ttm_eu_reserve_buffers(&submit->ticket, &submit->validated, ++ true, &submit->duplicates); ++ if (err) ++ goto out0; ++ ++ err = lima_sched_task_init( ++ submit->task, submit->ctx->context + submit->pipe, vm); ++ if (err) ++ goto out1; ++ ++ err = lima_gem_add_deps(&priv->ctx_mgr, submit); ++ if (err) ++ goto out2; ++ ++ for (i = 0; i < submit->nr_bos; i++) { ++ struct ttm_validate_buffer *vb = submit->vbs + i; ++ struct lima_bo *bo = ttm_to_lima_bo(vb->bo); ++ err = lima_gem_sync_bo( ++ submit->task, bo, !vb->shared, ++ submit->flags & LIMA_SUBMIT_FLAG_EXPLICIT_FENCE); ++ if (err) ++ goto out2; ++ } ++ ++ if (submit->flags & LIMA_SUBMIT_FLAG_SYNC_FD_OUT) { ++ int fd = lima_gem_get_sync_fd( ++ &submit->task->base.s_fence->finished); ++ if (fd < 0) { ++ err = fd; ++ goto out2; ++ } ++ submit->sync_fd = fd; ++ } ++ ++ submit->fence = lima_sched_context_queue_task( ++ submit->ctx->context + submit->pipe, submit->task, ++ &submit->done); ++ ++ ttm_eu_fence_buffer_objects(&submit->ticket, &submit->validated, ++ &submit->task->base.s_fence->finished); ++ ++out2: ++ if (err) ++ lima_sched_task_fini(submit->task); ++out1: ++ if (err) ++ ttm_eu_backoff_reservation(&submit->ticket, &submit->validated); ++out0: ++ for (i = 0; i < submit->nr_bos; i++) { ++ struct ttm_validate_buffer *vb = submit->vbs + i; ++ if (!vb->bo) ++ break; ++ drm_gem_object_put_unlocked(&ttm_to_lima_bo(vb->bo)->gem); ++ } ++ return err; ++} ++ ++int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, u64 timeout_ns) ++{ ++ bool write = op & LIMA_GEM_WAIT_WRITE; ++ struct drm_gem_object *obj; ++ struct lima_bo *bo; ++ signed long ret; ++ unsigned long timeout; ++ ++ obj = drm_gem_object_lookup(file, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ bo = to_lima_bo(obj); ++ ++ timeout = timeout_ns ? lima_timeout_to_jiffies(timeout_ns) : 0; ++ ++ ret = lima_bo_reserve(bo, true); ++ if (ret) ++ goto out; ++ ++ /* must use long for result check because in 64bit arch int ++ * will overflow if timeout is too large and get <0 result ++ */ ++ ret = reservation_object_wait_timeout_rcu(bo->tbo.resv, write, true, timeout); ++ if (ret == 0) ++ ret = timeout ? -ETIMEDOUT : -EBUSY; ++ else if (ret > 0) ++ ret = 0; ++ ++ lima_bo_unreserve(bo); ++out: ++ drm_gem_object_put_unlocked(obj); ++ return ret; ++} +diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h +new file mode 100644 +index 000000000000..8e3c4110825d +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_gem.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_GEM_H__ ++#define __LIMA_GEM_H__ ++ ++struct lima_bo; ++struct lima_submit; ++ ++struct lima_bo *lima_gem_create_bo(struct drm_device *dev, u32 size, u32 flags); ++int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, ++ u32 size, u32 flags, u32 *handle); ++void lima_gem_free_object(struct drm_gem_object *obj); ++int lima_gem_object_open(struct drm_gem_object *obj, struct drm_file *file); ++void lima_gem_object_close(struct drm_gem_object *obj, struct drm_file *file); ++int lima_gem_mmap_offset(struct drm_file *file, u32 handle, u64 *offset); ++int lima_gem_mmap(struct file *filp, struct vm_area_struct *vma); ++int lima_gem_va_map(struct drm_file *file, u32 handle, u32 flags, u32 va); ++int lima_gem_va_unmap(struct drm_file *file, u32 handle, u32 va); ++int lima_gem_submit(struct drm_file *file, struct lima_submit *submit); ++int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, u64 timeout_ns); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0057-drm-lima-add-GEM-Prime-related-functions.patch b/patch/kernel/sunxi-dev/0057-drm-lima-add-GEM-Prime-related-functions.patch new file mode 100644 index 000000000..3bce77c6c --- /dev/null +++ b/patch/kernel/sunxi-dev/0057-drm-lima-add-GEM-Prime-related-functions.patch @@ -0,0 +1,126 @@ +From 2a5a3ab8cf45c868fa158fb2766f7a9707d187b0 Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Wed, 16 May 2018 10:38:28 +0800 +Subject: [PATCH 057/146] drm/lima: add GEM Prime related functions + +Signed-off-by: Qiang Yu +Signed-off-by: Erico Nunes +--- + drivers/gpu/drm/lima/lima_gem_prime.c | 66 +++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_gem_prime.h | 31 +++++++++++++ + 2 files changed, 97 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_gem_prime.c + create mode 100644 drivers/gpu/drm/lima/lima_gem_prime.h + +diff --git a/drivers/gpu/drm/lima/lima_gem_prime.c b/drivers/gpu/drm/lima/lima_gem_prime.c +new file mode 100644 +index 000000000000..74da43a4378f +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_gem_prime.c +@@ -0,0 +1,66 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "lima_device.h" ++#include "lima_object.h" ++#include "lima_gem_prime.h" ++ ++struct drm_gem_object *lima_gem_prime_import_sg_table( ++ struct drm_device *dev, struct dma_buf_attachment *attach, ++ struct sg_table *sgt) ++{ ++ struct reservation_object *resv = attach->dmabuf->resv; ++ struct lima_device *ldev = to_lima_dev(dev); ++ struct lima_bo *bo; ++ ++ ww_mutex_lock(&resv->lock, NULL); ++ ++ bo = lima_bo_create(ldev, attach->dmabuf->size, 0, ++ ttm_bo_type_sg, sgt, resv); ++ if (IS_ERR(bo)) ++ goto err_out; ++ ++ ww_mutex_unlock(&resv->lock); ++ return &bo->gem; ++ ++err_out: ++ ww_mutex_unlock(&resv->lock); ++ return (void *)bo; ++} ++ ++struct reservation_object *lima_gem_prime_res_obj(struct drm_gem_object *obj) ++{ ++ struct lima_bo *bo = to_lima_bo(obj); ++ ++ return bo->tbo.resv; ++} ++ ++struct sg_table *lima_gem_prime_get_sg_table(struct drm_gem_object *obj) ++{ ++ struct lima_bo *bo = to_lima_bo(obj); ++ int npages = bo->tbo.num_pages; ++ ++ return drm_prime_pages_to_sg(bo->tbo.ttm->pages, npages); ++} +diff --git a/drivers/gpu/drm/lima/lima_gem_prime.h b/drivers/gpu/drm/lima/lima_gem_prime.h +new file mode 100644 +index 000000000000..023bf5ba2d7b +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_gem_prime.h +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_GEM_PRIME_H__ ++#define __LIMA_GEM_PRIME_H__ ++ ++struct drm_gem_object *lima_gem_prime_import_sg_table( ++ struct drm_device *dev, struct dma_buf_attachment *attach, ++ struct sg_table *sgt); ++struct sg_table *lima_gem_prime_get_sg_table(struct drm_gem_object *obj); ++struct reservation_object *lima_gem_prime_res_obj(struct drm_gem_object *obj); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0058-drm-lima-add-GPU-schedule-using-DRM_SCHED.patch b/patch/kernel/sunxi-dev/0058-drm-lima-add-GPU-schedule-using-DRM_SCHED.patch new file mode 100644 index 000000000..12d5c8f82 --- /dev/null +++ b/patch/kernel/sunxi-dev/0058-drm-lima-add-GPU-schedule-using-DRM_SCHED.patch @@ -0,0 +1,651 @@ +From f76c22d3c634633a1d27dce98d042f211f0ac35e Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Wed, 16 May 2018 10:40:58 +0800 +Subject: [PATCH 058/146] drm/lima: add GPU schedule using DRM_SCHED + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_sched.c | 497 ++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_sched.h | 126 ++++++++ + 2 files changed, 623 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_sched.c + create mode 100644 drivers/gpu/drm/lima/lima_sched.h + +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +new file mode 100644 +index 000000000000..190932955e9b +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -0,0 +1,497 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "lima_drv.h" ++#include "lima_sched.h" ++#include "lima_vm.h" ++#include "lima_mmu.h" ++#include "lima_l2_cache.h" ++ ++struct lima_fence { ++ struct dma_fence base; ++ struct lima_sched_pipe *pipe; ++}; ++ ++static struct kmem_cache *lima_fence_slab = NULL; ++ ++int lima_sched_slab_init(void) ++{ ++ lima_fence_slab = kmem_cache_create( ++ "lima_fence", sizeof(struct lima_fence), 0, ++ SLAB_HWCACHE_ALIGN, NULL); ++ if (!lima_fence_slab) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++void lima_sched_slab_fini(void) ++{ ++ if (lima_fence_slab) ++ kmem_cache_destroy(lima_fence_slab); ++} ++ ++static inline struct lima_fence *to_lima_fence(struct dma_fence *fence) ++{ ++ return container_of(fence, struct lima_fence, base); ++} ++ ++static const char *lima_fence_get_driver_name(struct dma_fence *fence) ++{ ++ return "lima"; ++} ++ ++static const char *lima_fence_get_timeline_name(struct dma_fence *fence) ++{ ++ struct lima_fence *f = to_lima_fence(fence); ++ ++ return f->pipe->base.name; ++} ++ ++static bool lima_fence_enable_signaling(struct dma_fence *fence) ++{ ++ return true; ++} ++ ++static void lima_fence_release_rcu(struct rcu_head *rcu) ++{ ++ struct dma_fence *f = container_of(rcu, struct dma_fence, rcu); ++ struct lima_fence *fence = to_lima_fence(f); ++ ++ kmem_cache_free(lima_fence_slab, fence); ++} ++ ++static void lima_fence_release(struct dma_fence *fence) ++{ ++ struct lima_fence *f = to_lima_fence(fence); ++ ++ call_rcu(&f->base.rcu, lima_fence_release_rcu); ++} ++ ++static const struct dma_fence_ops lima_fence_ops = { ++ .get_driver_name = lima_fence_get_driver_name, ++ .get_timeline_name = lima_fence_get_timeline_name, ++ .enable_signaling = lima_fence_enable_signaling, ++ .wait = dma_fence_default_wait, ++ .release = lima_fence_release, ++}; ++ ++static struct lima_fence *lima_fence_create(struct lima_sched_pipe *pipe) ++{ ++ struct lima_fence *fence; ++ ++ fence = kmem_cache_zalloc(lima_fence_slab, GFP_KERNEL); ++ if (!fence) ++ return NULL; ++ ++ fence->pipe = pipe; ++ dma_fence_init(&fence->base, &lima_fence_ops, &pipe->fence_lock, ++ pipe->fence_context, ++pipe->fence_seqno); ++ ++ return fence; ++} ++ ++static inline struct lima_sched_task *to_lima_task(struct drm_sched_job *job) ++{ ++ return container_of(job, struct lima_sched_task, base); ++} ++ ++static inline struct lima_sched_pipe *to_lima_pipe(struct drm_gpu_scheduler *sched) ++{ ++ return container_of(sched, struct lima_sched_pipe, base); ++} ++ ++int lima_sched_task_init(struct lima_sched_task *task, ++ struct lima_sched_context *context, ++ struct lima_vm *vm) ++{ ++ int err; ++ ++ err = drm_sched_job_init(&task->base, context->base.sched, ++ &context->base, context); ++ if (err) ++ return err; ++ ++ task->vm = lima_vm_get(vm); ++ return 0; ++} ++ ++void lima_sched_task_fini(struct lima_sched_task *task) ++{ ++ dma_fence_put(&task->base.s_fence->finished); ++ lima_vm_put(task->vm); ++} ++ ++int lima_sched_task_add_dep(struct lima_sched_task *task, struct dma_fence *fence) ++{ ++ int i, new_dep = 4; ++ ++ if (task->dep && task->num_dep == task->max_dep) ++ new_dep = task->max_dep * 2; ++ ++ if (task->max_dep < new_dep) { ++ void *dep = krealloc(task->dep, sizeof(*task->dep) * new_dep, GFP_KERNEL); ++ if (!dep) ++ return -ENOMEM; ++ task->max_dep = new_dep; ++ task->dep = dep; ++ } ++ ++ dma_fence_get(fence); ++ for (i = 0; i < task->num_dep; i++) { ++ if (task->dep[i]->context == fence->context && ++ dma_fence_is_later(fence, task->dep[i])) { ++ dma_fence_put(task->dep[i]); ++ task->dep[i] = fence; ++ return 0; ++ } ++ } ++ ++ task->dep[task->num_dep++] = fence; ++ return 0; ++} ++ ++int lima_sched_context_init(struct lima_sched_pipe *pipe, ++ struct lima_sched_context *context, ++ atomic_t *guilty) ++{ ++ struct drm_sched_rq *rq = pipe->base.sched_rq + DRM_SCHED_PRIORITY_NORMAL; ++ int err; ++ ++ context->fences = ++ kzalloc(sizeof(*context->fences) * lima_sched_max_tasks, GFP_KERNEL); ++ if (!context->fences) ++ return -ENOMEM; ++ ++ mutex_init(&context->lock); ++ err = drm_sched_entity_init(&pipe->base, &context->base, rq, ++ lima_sched_max_tasks, guilty); ++ if (err) { ++ kfree(context->fences); ++ context->fences = NULL; ++ return err; ++ } ++ ++ return 0; ++} ++ ++void lima_sched_context_fini(struct lima_sched_pipe *pipe, ++ struct lima_sched_context *context) ++{ ++ drm_sched_entity_fini(&pipe->base, &context->base); ++ ++ mutex_destroy(&context->lock); ++ ++ if (context->fences) ++ kfree(context->fences); ++} ++ ++static uint32_t lima_sched_context_add_fence(struct lima_sched_context *context, ++ struct dma_fence *fence, ++ uint32_t *done) ++{ ++ uint32_t seq, idx, i; ++ struct dma_fence *other; ++ ++ mutex_lock(&context->lock); ++ ++ seq = context->sequence; ++ idx = seq & (lima_sched_max_tasks - 1); ++ other = context->fences[idx]; ++ ++ if (other) { ++ int err = dma_fence_wait(other, false); ++ if (err) ++ DRM_ERROR("Error %d waiting context fence\n", err); ++ } ++ ++ context->fences[idx] = dma_fence_get(fence); ++ context->sequence++; ++ ++ /* get finished fence offset from seq */ ++ for (i = 1; i < lima_sched_max_tasks; i++) { ++ idx = (seq - i) & (lima_sched_max_tasks - 1); ++ if (!context->fences[idx] || ++ dma_fence_is_signaled(context->fences[idx])) ++ break; ++ } ++ ++ mutex_unlock(&context->lock); ++ ++ dma_fence_put(other); ++ ++ *done = i; ++ return seq; ++} ++ ++struct dma_fence *lima_sched_context_get_fence( ++ struct lima_sched_context *context, uint32_t seq) ++{ ++ struct dma_fence *fence; ++ int idx; ++ uint32_t max, min; ++ ++ mutex_lock(&context->lock); ++ ++ max = context->sequence - 1; ++ min = context->sequence - lima_sched_max_tasks; ++ ++ /* handle overflow case */ ++ if ((min < max && (seq < min || seq > max)) || ++ (min > max && (seq < min && seq > max))) { ++ fence = NULL; ++ goto out; ++ } ++ ++ idx = seq & (lima_sched_max_tasks - 1); ++ fence = dma_fence_get(context->fences[idx]); ++ ++out: ++ mutex_unlock(&context->lock); ++ ++ return fence; ++} ++ ++uint32_t lima_sched_context_queue_task(struct lima_sched_context *context, ++ struct lima_sched_task *task, ++ uint32_t *done) ++{ ++ uint32_t seq = lima_sched_context_add_fence( ++ context, &task->base.s_fence->finished, done); ++ drm_sched_entity_push_job(&task->base, &context->base); ++ return seq; ++} ++ ++static struct dma_fence *lima_sched_dependency(struct drm_sched_job *job, ++ struct drm_sched_entity *entity) ++{ ++ struct lima_sched_task *task = to_lima_task(job); ++ int i; ++ ++ for (i = 0; i < task->num_dep; i++) { ++ struct dma_fence *fence = task->dep[i]; ++ ++ if (!task->dep[i]) ++ continue; ++ ++ task->dep[i] = NULL; ++ ++ if (!dma_fence_is_signaled(fence)) ++ return fence; ++ ++ dma_fence_put(fence); ++ } ++ ++ return NULL; ++} ++ ++static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) ++{ ++ struct lima_sched_task *task = to_lima_task(job); ++ struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); ++ struct lima_fence *fence; ++ struct dma_fence *ret; ++ struct lima_vm *vm = NULL, *last_vm = NULL; ++ int i; ++ ++ /* after GPU reset */ ++ if (job->s_fence->finished.error < 0) ++ return NULL; ++ ++ fence = lima_fence_create(pipe); ++ if (!fence) ++ return NULL; ++ task->fence = &fence->base; ++ ++ /* for caller usage of the fence, otherwise irq handler ++ * may consume the fence before caller use it */ ++ ret = dma_fence_get(task->fence); ++ ++ pipe->current_task = task; ++ ++ /* this is needed for MMU to work correctly, otherwise GP/PP ++ * will hang or page fault for unknown reason after running for ++ * a while. ++ * ++ * Need to investigate: ++ * 1. is it related to TLB ++ * 2. how much performance will be affected by L2 cache flush ++ * 3. can we reduce the calling of this function because all ++ * GP/PP use the same L2 cache on mali400 ++ * ++ * TODO: ++ * 1. move this to task fini to save some wait time? ++ * 2. when GP/PP use different l2 cache, need PP wait GP l2 ++ * cache flush? ++ */ ++ for (i = 0; i < pipe->num_l2_cache; i++) ++ lima_l2_cache_flush(pipe->l2_cache[i]); ++ ++ if (task->vm != pipe->current_vm) { ++ vm = lima_vm_get(task->vm); ++ last_vm = pipe->current_vm; ++ pipe->current_vm = task->vm; ++ } ++ ++ if (pipe->bcast_mmu) ++ lima_mmu_switch_vm(pipe->bcast_mmu, vm); ++ else { ++ for (i = 0; i < pipe->num_mmu; i++) ++ lima_mmu_switch_vm(pipe->mmu[i], vm); ++ } ++ ++ if (last_vm) ++ lima_vm_put(last_vm); ++ ++ pipe->error = false; ++ pipe->task_run(pipe, task); ++ ++ return task->fence; ++} ++ ++static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe, ++ struct lima_sched_task *task) ++{ ++ kthread_park(pipe->base.thread); ++ drm_sched_hw_job_reset(&pipe->base, &task->base); ++ ++ pipe->task_error(pipe); ++ ++ if (pipe->bcast_mmu) ++ lima_mmu_page_fault_resume(pipe->bcast_mmu); ++ else { ++ int i; ++ for (i = 0; i < pipe->num_mmu; i++) ++ lima_mmu_page_fault_resume(pipe->mmu[i]); ++ } ++ ++ if (pipe->current_vm) ++ lima_vm_put(pipe->current_vm); ++ ++ pipe->current_vm = NULL; ++ pipe->current_task = NULL; ++ ++ drm_sched_job_recovery(&pipe->base); ++ kthread_unpark(pipe->base.thread); ++} ++ ++static void lima_sched_timedout_job(struct drm_sched_job *job) ++{ ++ struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); ++ struct lima_sched_task *task = to_lima_task(job); ++ ++ lima_sched_handle_error_task(pipe, task); ++} ++ ++static void lima_sched_free_job(struct drm_sched_job *job) ++{ ++ struct lima_sched_task *task = to_lima_task(job); ++ struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); ++ int i; ++ ++ dma_fence_put(task->fence); ++ ++ for (i = 0; i < task->num_dep; i++) { ++ if (task->dep[i]) ++ dma_fence_put(task->dep[i]); ++ } ++ ++ if (task->dep) ++ kfree(task->dep); ++ ++ lima_vm_put(task->vm); ++ kmem_cache_free(pipe->task_slab, task); ++} ++ ++const struct drm_sched_backend_ops lima_sched_ops = { ++ .dependency = lima_sched_dependency, ++ .run_job = lima_sched_run_job, ++ .timedout_job = lima_sched_timedout_job, ++ .free_job = lima_sched_free_job, ++}; ++ ++static void lima_sched_error_work(struct work_struct *work) ++{ ++ struct lima_sched_pipe *pipe = ++ container_of(work, struct lima_sched_pipe, error_work); ++ struct lima_sched_task *task = pipe->current_task; ++ ++ lima_sched_handle_error_task(pipe, task); ++} ++ ++int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) ++{ ++ long timeout; ++ ++ if (lima_sched_timeout_ms <= 0) ++ timeout = MAX_SCHEDULE_TIMEOUT; ++ else ++ timeout = msecs_to_jiffies(lima_sched_timeout_ms); ++ ++ pipe->fence_context = dma_fence_context_alloc(1); ++ spin_lock_init(&pipe->fence_lock); ++ ++ INIT_WORK(&pipe->error_work, lima_sched_error_work); ++ ++ return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0, timeout, name); ++} ++ ++void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) ++{ ++ drm_sched_fini(&pipe->base); ++} ++ ++unsigned long lima_timeout_to_jiffies(u64 timeout_ns) ++{ ++ unsigned long timeout_jiffies; ++ ktime_t timeout; ++ ++ /* clamp timeout if it's to large */ ++ if (((s64)timeout_ns) < 0) ++ return MAX_SCHEDULE_TIMEOUT; ++ ++ timeout = ktime_sub(ns_to_ktime(timeout_ns), ktime_get()); ++ if (ktime_to_ns(timeout) < 0) ++ return 0; ++ ++ timeout_jiffies = nsecs_to_jiffies(ktime_to_ns(timeout)); ++ /* clamp timeout to avoid unsigned-> signed overflow */ ++ if (timeout_jiffies > MAX_SCHEDULE_TIMEOUT ) ++ return MAX_SCHEDULE_TIMEOUT; ++ ++ return timeout_jiffies; ++} ++ ++void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe) ++{ ++ if (pipe->error) ++ schedule_work(&pipe->error_work); ++ else { ++ struct lima_sched_task *task = pipe->current_task; ++ ++ pipe->task_fini(pipe); ++ dma_fence_signal(task->fence); ++ } ++} +diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h +new file mode 100644 +index 000000000000..b93b7b4eded4 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_sched.h +@@ -0,0 +1,126 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_SCHED_H__ ++#define __LIMA_SCHED_H__ ++ ++#include ++ ++struct lima_vm; ++ ++struct lima_sched_task { ++ struct drm_sched_job base; ++ ++ struct lima_vm *vm; ++ void *frame; ++ ++ struct dma_fence **dep; ++ int num_dep; ++ int max_dep; ++ ++ /* pipe fence */ ++ struct dma_fence *fence; ++}; ++ ++struct lima_sched_context { ++ struct drm_sched_entity base; ++ struct mutex lock; ++ struct dma_fence **fences; ++ uint32_t sequence; ++}; ++ ++#define LIMA_SCHED_PIPE_MAX_MMU 8 ++#define LIMA_SCHED_PIPE_MAX_L2_CACHE 2 ++#define LIMA_SCHED_PIPE_MAX_PROCESSOR 8 ++ ++struct lima_ip; ++ ++struct lima_sched_pipe { ++ struct drm_gpu_scheduler base; ++ ++ u64 fence_context; ++ u32 fence_seqno; ++ spinlock_t fence_lock; ++ ++ struct lima_sched_task *current_task; ++ struct lima_vm *current_vm; ++ ++ struct lima_ip *mmu[LIMA_SCHED_PIPE_MAX_MMU]; ++ int num_mmu; ++ ++ struct lima_ip *l2_cache[LIMA_SCHED_PIPE_MAX_L2_CACHE]; ++ int num_l2_cache; ++ ++ struct lima_ip *processor[LIMA_SCHED_PIPE_MAX_PROCESSOR]; ++ int num_processor; ++ ++ struct lima_ip *bcast_processor; ++ struct lima_ip *bcast_mmu; ++ ++ u32 done; ++ bool error; ++ atomic_t task; ++ ++ int frame_size; ++ struct kmem_cache *task_slab; ++ ++ int (*task_validate)(struct lima_sched_pipe *pipe, struct lima_sched_task *task); ++ void (*task_run)(struct lima_sched_pipe *pipe, struct lima_sched_task *task); ++ void (*task_fini)(struct lima_sched_pipe *pipe); ++ void (*task_error)(struct lima_sched_pipe *pipe); ++ void (*task_mmu_error)(struct lima_sched_pipe *pipe); ++ ++ struct work_struct error_work; ++}; ++ ++int lima_sched_task_init(struct lima_sched_task *task, ++ struct lima_sched_context *context, ++ struct lima_vm *vm); ++void lima_sched_task_fini(struct lima_sched_task *task); ++int lima_sched_task_add_dep(struct lima_sched_task *task, struct dma_fence *fence); ++ ++int lima_sched_context_init(struct lima_sched_pipe *pipe, ++ struct lima_sched_context *context, ++ atomic_t *guilty); ++void lima_sched_context_fini(struct lima_sched_pipe *pipe, ++ struct lima_sched_context *context); ++uint32_t lima_sched_context_queue_task(struct lima_sched_context *context, ++ struct lima_sched_task *task, ++ uint32_t *done); ++struct dma_fence *lima_sched_context_get_fence( ++ struct lima_sched_context *context, uint32_t seq); ++ ++int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name); ++void lima_sched_pipe_fini(struct lima_sched_pipe *pipe); ++void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe); ++ ++static inline void lima_sched_pipe_mmu_error(struct lima_sched_pipe *pipe) ++{ ++ pipe->error = true; ++ pipe->task_mmu_error(pipe); ++} ++ ++int lima_sched_slab_init(void); ++void lima_sched_slab_fini(void); ++ ++unsigned long lima_timeout_to_jiffies(u64 timeout_ns); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0059-drm-lima-add-context-related-functions.patch b/patch/kernel/sunxi-dev/0059-drm-lima-add-context-related-functions.patch new file mode 100644 index 000000000..2f45be14f --- /dev/null +++ b/patch/kernel/sunxi-dev/0059-drm-lima-add-context-related-functions.patch @@ -0,0 +1,222 @@ +From fcfa6c7b5a84fac51109efd86b4edf5085359485 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Wed, 16 May 2018 11:14:41 +0800 +Subject: [PATCH 059/146] drm/lima: add context related functions + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_ctx.c | 143 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_ctx.h | 51 ++++++++++++ + 2 files changed, 194 insertions(+) + create mode 100644 drivers/gpu/drm/lima/lima_ctx.c + create mode 100644 drivers/gpu/drm/lima/lima_ctx.h + +diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c +new file mode 100644 +index 000000000000..7243861760b4 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_ctx.c +@@ -0,0 +1,143 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include ++ ++#include "lima_device.h" ++#include "lima_ctx.h" ++ ++int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id) ++{ ++ struct lima_ctx *ctx; ++ int i, err; ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ctx->dev = dev; ++ kref_init(&ctx->refcnt); ++ ++ for (i = 0; i < lima_pipe_num; i++) { ++ err = lima_sched_context_init(dev->pipe + i, ctx->context + i, &ctx->guilty); ++ if (err) ++ goto err_out0; ++ } ++ ++ idr_preload(GFP_KERNEL); ++ spin_lock(&mgr->lock); ++ err = idr_alloc(&mgr->handles, ctx, 1, 0, GFP_ATOMIC); ++ spin_unlock(&mgr->lock); ++ idr_preload_end(); ++ if (err < 0) ++ goto err_out0; ++ ++ *id = err; ++ return 0; ++ ++err_out0: ++ for (i--; i >= 0; i--) ++ lima_sched_context_fini(dev->pipe + i, ctx->context + i); ++ kfree(ctx); ++ return err; ++} ++ ++static void lima_ctx_do_release(struct kref *ref) ++{ ++ struct lima_ctx *ctx = container_of(ref, struct lima_ctx, refcnt); ++ int i; ++ ++ for (i = 0; i < lima_pipe_num; i++) ++ lima_sched_context_fini(ctx->dev->pipe + i, ctx->context + i); ++ kfree(ctx); ++} ++ ++int lima_ctx_free(struct lima_ctx_mgr *mgr, u32 id) ++{ ++ struct lima_ctx *ctx; ++ ++ spin_lock(&mgr->lock); ++ ctx = idr_remove(&mgr->handles, id); ++ spin_unlock(&mgr->lock); ++ ++ if (ctx) { ++ kref_put(&ctx->refcnt, lima_ctx_do_release); ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++struct lima_ctx *lima_ctx_get(struct lima_ctx_mgr *mgr, u32 id) ++{ ++ struct lima_ctx *ctx; ++ ++ spin_lock(&mgr->lock); ++ ctx = idr_find(&mgr->handles, id); ++ if (ctx) ++ kref_get(&ctx->refcnt); ++ spin_unlock(&mgr->lock); ++ return ctx; ++} ++ ++void lima_ctx_put(struct lima_ctx *ctx) ++{ ++ kref_put(&ctx->refcnt, lima_ctx_do_release); ++} ++ ++void lima_ctx_mgr_init(struct lima_ctx_mgr *mgr) ++{ ++ spin_lock_init(&mgr->lock); ++ idr_init(&mgr->handles); ++} ++ ++void lima_ctx_mgr_fini(struct lima_ctx_mgr *mgr) ++{ ++ struct lima_ctx *ctx; ++ struct idr *idp; ++ uint32_t id; ++ ++ idp = &mgr->handles; ++ ++ idr_for_each_entry(idp, ctx, id) { ++ kref_put(&ctx->refcnt, lima_ctx_do_release); ++ } ++ ++ idr_destroy(&mgr->handles); ++} ++ ++struct dma_fence *lima_ctx_get_native_fence(struct lima_ctx_mgr *mgr, ++ u32 ctx, u32 pipe, u32 seq) ++{ ++ struct lima_ctx *c; ++ struct dma_fence *ret; ++ ++ if (pipe >= lima_pipe_num) ++ return ERR_PTR(-EINVAL); ++ ++ c = lima_ctx_get(mgr, ctx); ++ if (!c) ++ return ERR_PTR(-ENOENT); ++ ++ ret = lima_sched_context_get_fence(c->context + pipe, seq); ++ ++ lima_ctx_put(c); ++ return ret; ++} +diff --git a/drivers/gpu/drm/lima/lima_ctx.h b/drivers/gpu/drm/lima/lima_ctx.h +new file mode 100644 +index 000000000000..591f64532772 +--- /dev/null ++++ b/drivers/gpu/drm/lima/lima_ctx.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2017-2018 Lima Project ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++#ifndef __LIMA_CTX_H__ ++#define __LIMA_CTX_H__ ++ ++#include ++ ++#include "lima_device.h" ++ ++struct lima_ctx { ++ struct kref refcnt; ++ struct lima_device *dev; ++ struct lima_sched_context context[lima_pipe_num]; ++ atomic_t guilty; ++}; ++ ++struct lima_ctx_mgr { ++ spinlock_t lock; ++ struct idr handles; ++}; ++ ++int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id); ++int lima_ctx_free(struct lima_ctx_mgr *mgr, u32 id); ++struct lima_ctx *lima_ctx_get(struct lima_ctx_mgr *mgr, u32 id); ++void lima_ctx_put(struct lima_ctx *ctx); ++void lima_ctx_mgr_init(struct lima_ctx_mgr *mgr); ++void lima_ctx_mgr_fini(struct lima_ctx_mgr *mgr); ++ ++struct dma_fence *lima_ctx_get_native_fence(struct lima_ctx_mgr *mgr, ++ u32 ctx, u32 pipe, u32 seq); ++ ++#endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0060-drm-lima-add-makefile-and-kconfig.patch b/patch/kernel/sunxi-dev/0060-drm-lima-add-makefile-and-kconfig.patch new file mode 100644 index 000000000..f77ea4d29 --- /dev/null +++ b/patch/kernel/sunxi-dev/0060-drm-lima-add-makefile-and-kconfig.patch @@ -0,0 +1,83 @@ +From f7f324da0402ba4efe3656e68d573fb649fd60f5 Mon Sep 17 00:00:00 2001 +From: Lima Project Developers +Date: Wed, 16 May 2018 11:17:06 +0800 +Subject: [PATCH 060/146] drm/lima: add makefile and kconfig + +Signed-off-by: Qiang Yu +Signed-off-by: Neil Armstrong +Signed-off-by: Simon Shields +Signed-off-by: Heiko Stuebner +--- + drivers/gpu/drm/Kconfig | 2 ++ + drivers/gpu/drm/Makefile | 1 + + drivers/gpu/drm/lima/Kconfig | 9 +++++++++ + drivers/gpu/drm/lima/Makefile | 19 +++++++++++++++++++ + 4 files changed, 31 insertions(+) + create mode 100644 drivers/gpu/drm/lima/Kconfig + create mode 100644 drivers/gpu/drm/lima/Makefile + +diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig +index cb88528e7b10..145c093c3dec 100644 +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -315,6 +315,8 @@ source "drivers/gpu/drm/tve200/Kconfig" + + source "drivers/gpu/drm/xen/Kconfig" + ++source "drivers/gpu/drm/lima/Kconfig" ++ + # Keep legacy drivers last + + menuconfig DRM_LEGACY +diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile +index a6771cef85e2..302b4c8e7cf0 100644 +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -107,3 +107,4 @@ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ + obj-$(CONFIG_DRM_PL111) += pl111/ + obj-$(CONFIG_DRM_TVE200) += tve200/ + obj-$(CONFIG_DRM_XEN) += xen/ ++obj-$(CONFIG_DRM_LIMA) += lima/ +diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig +new file mode 100644 +index 000000000000..4ce9ac2e8204 +--- /dev/null ++++ b/drivers/gpu/drm/lima/Kconfig +@@ -0,0 +1,9 @@ ++ ++config DRM_LIMA ++ tristate "LIMA (DRM support for ARM Mali 400/450 GPU)" ++ depends on DRM ++ depends on ARCH_SUNXI || ARCH_ROCKCHIP || ARCH_EXYNOS || ARCH_MESON ++ select DRM_SCHED ++ select DRM_TTM ++ help ++ DRM driver for ARM Mali 400/450 GPUs. +diff --git a/drivers/gpu/drm/lima/Makefile b/drivers/gpu/drm/lima/Makefile +new file mode 100644 +index 000000000000..0a1d6605f164 +--- /dev/null ++++ b/drivers/gpu/drm/lima/Makefile +@@ -0,0 +1,19 @@ ++lima-y := \ ++ lima_drv.o \ ++ lima_device.o \ ++ lima_pmu.o \ ++ lima_l2_cache.o \ ++ lima_mmu.o \ ++ lima_gp.o \ ++ lima_pp.o \ ++ lima_gem.o \ ++ lima_vm.o \ ++ lima_sched.o \ ++ lima_ctx.o \ ++ lima_gem_prime.o \ ++ lima_dlbu.o \ ++ lima_bcast.o \ ++ lima_ttm.o \ ++ lima_object.o ++ ++obj-$(CONFIG_DRM_LIMA) += lima.o +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0061-drm-lima-use-SPDX-identifiers-and-change-copyright.patch b/patch/kernel/sunxi-dev/0061-drm-lima-use-SPDX-identifiers-and-change-copyright.patch new file mode 100644 index 000000000..a413dca0e --- /dev/null +++ b/patch/kernel/sunxi-dev/0061-drm-lima-use-SPDX-identifiers-and-change-copyright.patch @@ -0,0 +1,1115 @@ +From ff22535cdf89a99b126778945fa5c952fdfe75fa Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 21 May 2018 18:00:43 +0800 +Subject: [PATCH 061/146] drm/lima: use SPDX identifiers and change copyright + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/Kconfig | 2 ++ + drivers/gpu/drm/lima/Makefile | 3 +++ + drivers/gpu/drm/lima/lima_bcast.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_bcast.h | 22 ++-------------------- + drivers/gpu/drm/lima/lima_ctx.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_ctx.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_device.c | 23 +++-------------------- + drivers/gpu/drm/lima/lima_device.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_dlbu.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_dlbu.h | 22 ++-------------------- + drivers/gpu/drm/lima/lima_drv.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_drv.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_gem.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_gem.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_gem_prime.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_gem_prime.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_gp.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_gp.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_l2_cache.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_l2_cache.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_mmu.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_mmu.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_object.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_object.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_pmu.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_pmu.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_pp.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_pp.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_regs.h | 16 +++------------- + drivers/gpu/drm/lima/lima_sched.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_sched.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_ttm.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_ttm.h | 23 +++-------------------- + drivers/gpu/drm/lima/lima_vm.c | 22 ++-------------------- + drivers/gpu/drm/lima/lima_vm.h | 23 +++-------------------- + include/uapi/drm/lima_drm.h | 23 +++-------------------- + 36 files changed, 90 insertions(+), 673 deletions(-) + +diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig +index 4ce9ac2e8204..7256625aee04 100644 +--- a/drivers/gpu/drm/lima/Kconfig ++++ b/drivers/gpu/drm/lima/Kconfig +@@ -1,3 +1,5 @@ ++# Copyright 2017-2018 Qiang Yu ++# SPDX-License-Identifier: MIT + + config DRM_LIMA + tristate "LIMA (DRM support for ARM Mali 400/450 GPU)" +diff --git a/drivers/gpu/drm/lima/Makefile b/drivers/gpu/drm/lima/Makefile +index 0a1d6605f164..848310557e42 100644 +--- a/drivers/gpu/drm/lima/Makefile ++++ b/drivers/gpu/drm/lima/Makefile +@@ -1,3 +1,6 @@ ++# Copyright 2017-2018 Qiang Yu ++# SPDX-License-Identifier: MIT ++ + lima-y := \ + lima_drv.o \ + lima_device.o \ +diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c +index 32012a61ea6a..0786336d3c77 100644 +--- a/drivers/gpu/drm/lima/lima_bcast.c ++++ b/drivers/gpu/drm/lima/lima_bcast.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h +index abafd4f613c7..f1ba32852742 100644 +--- a/drivers/gpu/drm/lima/lima_bcast.h ++++ b/drivers/gpu/drm/lima/lima_bcast.h +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #ifndef __LIMA_BCAST_H__ +diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c +index 7243861760b4..3c8f0aba0169 100644 +--- a/drivers/gpu/drm/lima/lima_ctx.c ++++ b/drivers/gpu/drm/lima/lima_ctx.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_ctx.h b/drivers/gpu/drm/lima/lima_ctx.h +index 591f64532772..f3bee2e1893a 100644 +--- a/drivers/gpu/drm/lima/lima_ctx.h ++++ b/drivers/gpu/drm/lima/lima_ctx.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_CTX_H__ + #define __LIMA_CTX_H__ + +diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c +index a6c3905a0c85..8611ed466a29 100644 +--- a/drivers/gpu/drm/lima/lima_device.c ++++ b/drivers/gpu/drm/lima/lima_device.c +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #include + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h +index 6c9c26b9e122..29501f8361d9 100644 +--- a/drivers/gpu/drm/lima/lima_device.h ++++ b/drivers/gpu/drm/lima/lima_device.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_DEVICE_H__ + #define __LIMA_DEVICE_H__ + +diff --git a/drivers/gpu/drm/lima/lima_dlbu.c b/drivers/gpu/drm/lima/lima_dlbu.c +index 5281dd3c0417..0b612149accb 100644 +--- a/drivers/gpu/drm/lima/lima_dlbu.c ++++ b/drivers/gpu/drm/lima/lima_dlbu.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_dlbu.h b/drivers/gpu/drm/lima/lima_dlbu.h +index 4521a5dda9e0..bc441dccb1ba 100644 +--- a/drivers/gpu/drm/lima/lima_dlbu.h ++++ b/drivers/gpu/drm/lima/lima_dlbu.h +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #ifndef __LIMA_DLBU_H__ +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +index 4df24a6cfff3..7f2e47da6801 100644 +--- a/drivers/gpu/drm/lima/lima_drv.c ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h +index 2f5f51da21db..d7dba79950d6 100644 +--- a/drivers/gpu/drm/lima/lima_drv.h ++++ b/drivers/gpu/drm/lima/lima_drv.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_DRV_H__ + #define __LIMA_DRV_H__ + +diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c +index 1ad3f38ddfde..d9c15acb7cf8 100644 +--- a/drivers/gpu/drm/lima/lima_gem.c ++++ b/drivers/gpu/drm/lima/lima_gem.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h +index 8e3c4110825d..35098b692b2e 100644 +--- a/drivers/gpu/drm/lima/lima_gem.h ++++ b/drivers/gpu/drm/lima/lima_gem.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_GEM_H__ + #define __LIMA_GEM_H__ + +diff --git a/drivers/gpu/drm/lima/lima_gem_prime.c b/drivers/gpu/drm/lima/lima_gem_prime.c +index 74da43a4378f..9a401a6a039b 100644 +--- a/drivers/gpu/drm/lima/lima_gem_prime.c ++++ b/drivers/gpu/drm/lima/lima_gem_prime.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_gem_prime.h b/drivers/gpu/drm/lima/lima_gem_prime.h +index 023bf5ba2d7b..407482f1a7c0 100644 +--- a/drivers/gpu/drm/lima/lima_gem_prime.h ++++ b/drivers/gpu/drm/lima/lima_gem_prime.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_GEM_PRIME_H__ + #define __LIMA_GEM_PRIME_H__ + +diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c +index 8fb49986418a..280a40d857f4 100644 +--- a/drivers/gpu/drm/lima/lima_gp.c ++++ b/drivers/gpu/drm/lima/lima_gp.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_gp.h b/drivers/gpu/drm/lima/lima_gp.h +index 8354911e50ce..45e654737767 100644 +--- a/drivers/gpu/drm/lima/lima_gp.h ++++ b/drivers/gpu/drm/lima/lima_gp.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_GP_H__ + #define __LIMA_GP_H__ + +diff --git a/drivers/gpu/drm/lima/lima_l2_cache.c b/drivers/gpu/drm/lima/lima_l2_cache.c +index a9b85de5c51a..25313ab5fe92 100644 +--- a/drivers/gpu/drm/lima/lima_l2_cache.c ++++ b/drivers/gpu/drm/lima/lima_l2_cache.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_l2_cache.h b/drivers/gpu/drm/lima/lima_l2_cache.h +index 4a35725bf38d..6ecc07e33430 100644 +--- a/drivers/gpu/drm/lima/lima_l2_cache.h ++++ b/drivers/gpu/drm/lima/lima_l2_cache.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_L2_CACHE_H__ + #define __LIMA_L2_CACHE_H__ + +diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c +index 22ac4db07849..7de3935b5cc6 100644 +--- a/drivers/gpu/drm/lima/lima_mmu.c ++++ b/drivers/gpu/drm/lima/lima_mmu.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_mmu.h b/drivers/gpu/drm/lima/lima_mmu.h +index 9930521ddfa1..ac32f620e3d9 100644 +--- a/drivers/gpu/drm/lima/lima_mmu.h ++++ b/drivers/gpu/drm/lima/lima_mmu.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_MMU_H__ + #define __LIMA_MMU_H__ + +diff --git a/drivers/gpu/drm/lima/lima_object.c b/drivers/gpu/drm/lima/lima_object.c +index 5a22b235626b..6ca17ef2e701 100644 +--- a/drivers/gpu/drm/lima/lima_object.c ++++ b/drivers/gpu/drm/lima/lima_object.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_object.h b/drivers/gpu/drm/lima/lima_object.h +index 2b8b8fcb9063..ae67de9d2565 100644 +--- a/drivers/gpu/drm/lima/lima_object.h ++++ b/drivers/gpu/drm/lima/lima_object.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_OBJECT_H__ + #define __LIMA_OBJECT_H__ + +diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c +index 255a64e9f265..f4548c90b6b7 100644 +--- a/drivers/gpu/drm/lima/lima_pmu.c ++++ b/drivers/gpu/drm/lima/lima_pmu.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_pmu.h b/drivers/gpu/drm/lima/lima_pmu.h +index fb68a7059a37..b807e9f42928 100644 +--- a/drivers/gpu/drm/lima/lima_pmu.h ++++ b/drivers/gpu/drm/lima/lima_pmu.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_PMU_H__ + #define __LIMA_PMU_H__ + +diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c +index 371d6b70c271..8db3d134e244 100644 +--- a/drivers/gpu/drm/lima/lima_pp.c ++++ b/drivers/gpu/drm/lima/lima_pp.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_pp.h b/drivers/gpu/drm/lima/lima_pp.h +index 4bd1d9fcbcdf..b928f9516d30 100644 +--- a/drivers/gpu/drm/lima/lima_pp.h ++++ b/drivers/gpu/drm/lima/lima_pp.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_PP_H__ + #define __LIMA_PP_H__ + +diff --git a/drivers/gpu/drm/lima/lima_regs.h b/drivers/gpu/drm/lima/lima_regs.h +index ea4a37d69b98..0d8dced21633 100644 +--- a/drivers/gpu/drm/lima/lima_regs.h ++++ b/drivers/gpu/drm/lima/lima_regs.h +@@ -1,16 +1,6 @@ +-/* +- * Copyright (C) 2010-2017 ARM Limited. All rights reserved. +- * Copyright (C) 2017-2018 Lima Project +- * +- * This program is free software and is provided to you under +- * the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation, and any use by +- * you of this program is subject to the terms of such GNU +- * licence. +- * +- * A copy of the licence is included with the program, and +- * can also be obtained from Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++/* Copyright 2010-2017 ARM Limited. All rights reserved. ++ * Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: GPL-2.0 + */ + + #ifndef __LIMA_REGS_H__ +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index 190932955e9b..3b5ea2e4674d 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h +index b93b7b4eded4..581b8601fe81 100644 +--- a/drivers/gpu/drm/lima/lima_sched.h ++++ b/drivers/gpu/drm/lima/lima_sched.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_SCHED_H__ + #define __LIMA_SCHED_H__ + +diff --git a/drivers/gpu/drm/lima/lima_ttm.c b/drivers/gpu/drm/lima/lima_ttm.c +index 5325f3f48ae7..4be441b02f6c 100644 +--- a/drivers/gpu/drm/lima/lima_ttm.c ++++ b/drivers/gpu/drm/lima/lima_ttm.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_ttm.h b/drivers/gpu/drm/lima/lima_ttm.h +index 1d36d06a47a3..42af0b136ffb 100644 +--- a/drivers/gpu/drm/lima/lima_ttm.h ++++ b/drivers/gpu/drm/lima/lima_ttm.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_TTM_H__ + #define __LIMA_TTM_H__ + +diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c +index 00a3f6b59a33..11eb3c278df2 100644 +--- a/drivers/gpu/drm/lima/lima_vm.c ++++ b/drivers/gpu/drm/lima/lima_vm.c +@@ -1,23 +1,5 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ + + #include +diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h +index 20506459def0..c891a1ee95df 100644 +--- a/drivers/gpu/drm/lima/lima_vm.h ++++ b/drivers/gpu/drm/lima/lima_vm.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_VM_H__ + #define __LIMA_VM_H__ + +diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h +index 9df95e46fb2c..a489bba517c7 100644 +--- a/include/uapi/drm/lima_drm.h ++++ b/include/uapi/drm/lima_drm.h +@@ -1,24 +1,7 @@ +-/* +- * Copyright (C) 2017-2018 Lima Project +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. ++/* Copyright 2017-2018 Qiang Yu ++ * SPDX-License-Identifier: MIT + */ ++ + #ifndef __LIMA_DRM_H__ + #define __LIMA_DRM_H__ + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0062-drm-lima-lima_reg.h-use-BIT.patch b/patch/kernel/sunxi-dev/0062-drm-lima-lima_reg.h-use-BIT.patch new file mode 100644 index 000000000..84fc7ea12 --- /dev/null +++ b/patch/kernel/sunxi-dev/0062-drm-lima-lima_reg.h-use-BIT.patch @@ -0,0 +1,306 @@ +From 7e7c821aec6eb45f26b40f3ec2f3d8408ec58300 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 21 May 2018 18:47:02 +0800 +Subject: [PATCH 062/146] drm/lima: lima_reg.h use BIT() + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_regs.h | 238 +++++++++++++++---------------- + 1 file changed, 119 insertions(+), 119 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_regs.h b/drivers/gpu/drm/lima/lima_regs.h +index 0d8dced21633..91ae9d6c197b 100644 +--- a/drivers/gpu/drm/lima/lima_regs.h ++++ b/drivers/gpu/drm/lima/lima_regs.h +@@ -9,9 +9,9 @@ + /* PMU regs */ + #define LIMA_PMU_POWER_UP 0x00 + #define LIMA_PMU_POWER_DOWN 0x04 +-#define LIMA_PMU_POWER_GP0_MASK (1 << 0) +-#define LIMA_PMU_POWER_L2_MASK (1 << 1) +-#define LIMA_PMU_POWER_PP_MASK(i) (1 << (2 + i)) ++#define LIMA_PMU_POWER_GP0_MASK BIT(0) ++#define LIMA_PMU_POWER_L2_MASK BIT(1) ++#define LIMA_PMU_POWER_PP_MASK(i) BIT(2 + i) + + /* + * On Mali450 each block automatically starts up its corresponding L2 +@@ -26,25 +26,25 @@ + #define LIMA_PMU_INT_MASK 0x0C + #define LIMA_PMU_INT_RAWSTAT 0x10 + #define LIMA_PMU_INT_CLEAR 0x18 +-#define LIMA_PMU_INT_CMD_MASK (1 << 0) ++#define LIMA_PMU_INT_CMD_MASK BIT(0) + #define LIMA_PMU_SW_DELAY 0x1C + + /* L2 cache regs */ +-#define LIMA_L2_CACHE_SIZE 0x0004 +-#define LIMA_L2_CACHE_STATUS 0x0008 +-#define LIMA_L2_CACHE_STATUS_COMMAND_BUSY (1 << 0) +-#define LIMA_L2_CACHE_STATUS_DATA_BUSY (1 << 1) +-#define LIMA_L2_CACHE_COMMAND 0x0010 +-#define LIMA_L2_CACHE_COMMAND_CLEAR_ALL (1 << 0) +-#define LIMA_L2_CACHE_CLEAR_PAGE 0x0014 +-#define LIMA_L2_CACHE_MAX_READS 0x0018 +-#define LIMA_L2_CACHE_ENABLE 0x001C +-#define LIMA_L2_CACHE_ENABLE_ACCESS (1 << 0) +-#define LIMA_L2_CACHE_ENABLE_READ_ALLOCATE (1 << 1) +-#define LIMA_L2_CACHE_PERFCNT_SRC0 0x0020 +-#define LIMA_L2_CACHE_PERFCNT_VAL0 0x0024 +-#define LIMA_L2_CACHE_PERFCNT_SRC1 0x0028 +-#define LIMA_L2_CACHE_ERFCNT_VAL1 0x002C ++#define LIMA_L2_CACHE_SIZE 0x0004 ++#define LIMA_L2_CACHE_STATUS 0x0008 ++#define LIMA_L2_CACHE_STATUS_COMMAND_BUSY BIT(0) ++#define LIMA_L2_CACHE_STATUS_DATA_BUSY BIT(1) ++#define LIMA_L2_CACHE_COMMAND 0x0010 ++#define LIMA_L2_CACHE_COMMAND_CLEAR_ALL BIT(0) ++#define LIMA_L2_CACHE_CLEAR_PAGE 0x0014 ++#define LIMA_L2_CACHE_MAX_READS 0x0018 ++#define LIMA_L2_CACHE_ENABLE 0x001C ++#define LIMA_L2_CACHE_ENABLE_ACCESS BIT(0) ++#define LIMA_L2_CACHE_ENABLE_READ_ALLOCATE BIT(1) ++#define LIMA_L2_CACHE_PERFCNT_SRC0 0x0020 ++#define LIMA_L2_CACHE_PERFCNT_VAL0 0x0024 ++#define LIMA_L2_CACHE_PERFCNT_SRC1 0x0028 ++#define LIMA_L2_CACHE_ERFCNT_VAL1 0x002C + + /* GP regs */ + #define LIMA_GP_VSCL_START_ADDR 0x00 +@@ -54,36 +54,36 @@ + #define LIMA_GP_PLBU_ALLOC_START_ADDR 0x10 + #define LIMA_GP_PLBU_ALLOC_END_ADDR 0x14 + #define LIMA_GP_CMD 0x20 +-#define LIMA_GP_CMD_START_VS (1 << 0) +-#define LIMA_GP_CMD_START_PLBU (1 << 1) +-#define LIMA_GP_CMD_UPDATE_PLBU_ALLOC (1 << 4) +-#define LIMA_GP_CMD_RESET (1 << 5) +-#define LIMA_GP_CMD_FORCE_HANG (1 << 6) +-#define LIMA_GP_CMD_STOP_BUS (1 << 9) +-#define LIMA_GP_CMD_SOFT_RESET (1 << 10) ++#define LIMA_GP_CMD_START_VS BIT(0) ++#define LIMA_GP_CMD_START_PLBU BIT(1) ++#define LIMA_GP_CMD_UPDATE_PLBU_ALLOC BIT(4) ++#define LIMA_GP_CMD_RESET BIT(5) ++#define LIMA_GP_CMD_FORCE_HANG BIT(6) ++#define LIMA_GP_CMD_STOP_BUS BIT(9) ++#define LIMA_GP_CMD_SOFT_RESET BIT(10) + #define LIMA_GP_INT_RAWSTAT 0x24 + #define LIMA_GP_INT_CLEAR 0x28 + #define LIMA_GP_INT_MASK 0x2C + #define LIMA_GP_INT_STAT 0x30 +-#define LIMA_GP_IRQ_VS_END_CMD_LST (1 << 0) +-#define LIMA_GP_IRQ_PLBU_END_CMD_LST (1 << 1) +-#define LIMA_GP_IRQ_PLBU_OUT_OF_MEM (1 << 2) +-#define LIMA_GP_IRQ_VS_SEM_IRQ (1 << 3) +-#define LIMA_GP_IRQ_PLBU_SEM_IRQ (1 << 4) +-#define LIMA_GP_IRQ_HANG (1 << 5) +-#define LIMA_GP_IRQ_FORCE_HANG (1 << 6) +-#define LIMA_GP_IRQ_PERF_CNT_0_LIMIT (1 << 7) +-#define LIMA_GP_IRQ_PERF_CNT_1_LIMIT (1 << 8) +-#define LIMA_GP_IRQ_WRITE_BOUND_ERR (1 << 9) +-#define LIMA_GP_IRQ_SYNC_ERROR (1 << 10) +-#define LIMA_GP_IRQ_AXI_BUS_ERROR (1 << 11) +-#define LIMA_GP_IRQ_AXI_BUS_STOPPED (1 << 12) +-#define LIMA_GP_IRQ_VS_INVALID_CMD (1 << 13) +-#define LIMA_GP_IRQ_PLB_INVALID_CMD (1 << 14) +-#define LIMA_GP_IRQ_RESET_COMPLETED (1 << 19) +-#define LIMA_GP_IRQ_SEMAPHORE_UNDERFLOW (1 << 20) +-#define LIMA_GP_IRQ_SEMAPHORE_OVERFLOW (1 << 21) +-#define LIMA_GP_IRQ_PTR_ARRAY_OUT_OF_BOUNDS (1 << 22) ++#define LIMA_GP_IRQ_VS_END_CMD_LST BIT(0) ++#define LIMA_GP_IRQ_PLBU_END_CMD_LST BIT(1) ++#define LIMA_GP_IRQ_PLBU_OUT_OF_MEM BIT(2) ++#define LIMA_GP_IRQ_VS_SEM_IRQ BIT(3) ++#define LIMA_GP_IRQ_PLBU_SEM_IRQ BIT(4) ++#define LIMA_GP_IRQ_HANG BIT(5) ++#define LIMA_GP_IRQ_FORCE_HANG BIT(6) ++#define LIMA_GP_IRQ_PERF_CNT_0_LIMIT BIT(7) ++#define LIMA_GP_IRQ_PERF_CNT_1_LIMIT BIT(8) ++#define LIMA_GP_IRQ_WRITE_BOUND_ERR BIT(9) ++#define LIMA_GP_IRQ_SYNC_ERROR BIT(10) ++#define LIMA_GP_IRQ_AXI_BUS_ERROR BIT(11) ++#define LIMA_GP_IRQ_AXI_BUS_STOPPED BIT(12) ++#define LIMA_GP_IRQ_VS_INVALID_CMD BIT(13) ++#define LIMA_GP_IRQ_PLB_INVALID_CMD BIT(14) ++#define LIMA_GP_IRQ_RESET_COMPLETED BIT(19) ++#define LIMA_GP_IRQ_SEMAPHORE_UNDERFLOW BIT(20) ++#define LIMA_GP_IRQ_SEMAPHORE_OVERFLOW BIT(21) ++#define LIMA_GP_IRQ_PTR_ARRAY_OUT_OF_BOUNDS BIT(22) + #define LIMA_GP_WRITE_BOUND_LOW 0x34 + #define LIMA_GP_PERF_CNT_0_ENABLE 0x3C + #define LIMA_GP_PERF_CNT_1_ENABLE 0x40 +@@ -93,11 +93,11 @@ + #define LIMA_GP_PERF_CNT_1_VALUE 0x50 + #define LIMA_GP_PERF_CNT_0_LIMIT 0x54 + #define LIMA_GP_STATUS 0x68 +-#define LIMA_GP_STATUS_VS_ACTIVE (1 << 1) +-#define LIMA_GP_STATUS_BUS_STOPPED (1 << 2) +-#define LIMA_GP_STATUS_PLBU_ACTIVE (1 << 3) +-#define LIMA_GP_STATUS_BUS_ERROR (1 << 6) +-#define LIMA_GP_STATUS_WRITE_BOUND_ERR (1 << 8) ++#define LIMA_GP_STATUS_VS_ACTIVE BIT(1) ++#define LIMA_GP_STATUS_BUS_STOPPED BIT(2) ++#define LIMA_GP_STATUS_PLBU_ACTIVE BIT(3) ++#define LIMA_GP_STATUS_BUS_ERROR BIT(6) ++#define LIMA_GP_STATUS_WRITE_BOUND_ERR BIT(8) + #define LIMA_GP_VERSION 0x6C + #define LIMA_GP_VSCL_START_ADDR_READ 0x80 + #define LIMA_GP_PLBCL_START_ADDR_READ 0x84 +@@ -156,42 +156,42 @@ + + #define LIMA_PP_VERSION 0x1000 + #define LIMA_PP_CURRENT_REND_LIST_ADDR 0x1004 +-#define LIMA_PP_STATUS 0x1008 +-#define LIMA_PP_STATUS_RENDERING_ACTIVE (1 << 0) +-#define LIMA_PP_STATUS_BUS_STOPPED (1 << 4) +-#define LIMA_PP_CTRL 0x100c +-#define LIMA_PP_CTRL_STOP_BUS (1 << 0) +-#define LIMA_PP_CTRL_FLUSH_CACHES (1 << 3) +-#define LIMA_PP_CTRL_FORCE_RESET (1 << 5) +-#define LIMA_PP_CTRL_START_RENDERING (1 << 6) +-#define LIMA_PP_CTRL_SOFT_RESET (1 << 7) +-#define LIMA_PP_INT_RAWSTAT 0x1020 +-#define LIMA_PP_INT_CLEAR 0x1024 +-#define LIMA_PP_INT_MASK 0x1028 +-#define LIMA_PP_INT_STATUS 0x102c +-#define LIMA_PP_IRQ_END_OF_FRAME (1 << 0) +-#define LIMA_PP_IRQ_END_OF_TILE (1 << 1) +-#define LIMA_PP_IRQ_HANG (1 << 2) +-#define LIMA_PP_IRQ_FORCE_HANG (1 << 3) +-#define LIMA_PP_IRQ_BUS_ERROR (1 << 4) +-#define LIMA_PP_IRQ_BUS_STOP (1 << 5) +-#define LIMA_PP_IRQ_CNT_0_LIMIT (1 << 6) +-#define LIMA_PP_IRQ_CNT_1_LIMIT (1 << 7) +-#define LIMA_PP_IRQ_WRITE_BOUNDARY_ERROR (1 << 8) +-#define LIMA_PP_IRQ_INVALID_PLIST_COMMAND (1 << 9) +-#define LIMA_PP_IRQ_CALL_STACK_UNDERFLOW (1 << 10) +-#define LIMA_PP_IRQ_CALL_STACK_OVERFLOW (1 << 11) +-#define LIMA_PP_IRQ_RESET_COMPLETED (1 << 12) +-#define LIMA_PP_WRITE_BOUNDARY_LOW 0x1044 +-#define LIMA_PP_BUS_ERROR_STATUS 0x1050 +-#define LIMA_PP_PERF_CNT_0_ENABLE 0x1080 +-#define LIMA_PP_PERF_CNT_0_SRC 0x1084 +-#define LIMA_PP_PERF_CNT_0_LIMIT 0x1088 +-#define LIMA_PP_PERF_CNT_0_VALUE 0x108c +-#define LIMA_PP_PERF_CNT_1_ENABLE 0x10a0 +-#define LIMA_PP_PERF_CNT_1_SRC 0x10a4 +-#define LIMA_PP_PERF_CNT_1_LIMIT 0x10a8 +-#define LIMA_PP_PERF_CNT_1_VALUE 0x10ac ++#define LIMA_PP_STATUS 0x1008 ++#define LIMA_PP_STATUS_RENDERING_ACTIVE BIT(0) ++#define LIMA_PP_STATUS_BUS_STOPPED BIT(4) ++#define LIMA_PP_CTRL 0x100c ++#define LIMA_PP_CTRL_STOP_BUS BIT(0) ++#define LIMA_PP_CTRL_FLUSH_CACHES BIT(3) ++#define LIMA_PP_CTRL_FORCE_RESET BIT(5) ++#define LIMA_PP_CTRL_START_RENDERING BIT(6) ++#define LIMA_PP_CTRL_SOFT_RESET BIT(7) ++#define LIMA_PP_INT_RAWSTAT 0x1020 ++#define LIMA_PP_INT_CLEAR 0x1024 ++#define LIMA_PP_INT_MASK 0x1028 ++#define LIMA_PP_INT_STATUS 0x102c ++#define LIMA_PP_IRQ_END_OF_FRAME BIT(0) ++#define LIMA_PP_IRQ_END_OF_TILE BIT(1) ++#define LIMA_PP_IRQ_HANG BIT(2) ++#define LIMA_PP_IRQ_FORCE_HANG BIT(3) ++#define LIMA_PP_IRQ_BUS_ERROR BIT(4) ++#define LIMA_PP_IRQ_BUS_STOP BIT(5) ++#define LIMA_PP_IRQ_CNT_0_LIMIT BIT(6) ++#define LIMA_PP_IRQ_CNT_1_LIMIT BIT(7) ++#define LIMA_PP_IRQ_WRITE_BOUNDARY_ERROR BIT(8) ++#define LIMA_PP_IRQ_INVALID_PLIST_COMMAND BIT(9) ++#define LIMA_PP_IRQ_CALL_STACK_UNDERFLOW BIT(10) ++#define LIMA_PP_IRQ_CALL_STACK_OVERFLOW BIT(11) ++#define LIMA_PP_IRQ_RESET_COMPLETED BIT(12) ++#define LIMA_PP_WRITE_BOUNDARY_LOW 0x1044 ++#define LIMA_PP_BUS_ERROR_STATUS 0x1050 ++#define LIMA_PP_PERF_CNT_0_ENABLE 0x1080 ++#define LIMA_PP_PERF_CNT_0_SRC 0x1084 ++#define LIMA_PP_PERF_CNT_0_LIMIT 0x1088 ++#define LIMA_PP_PERF_CNT_0_VALUE 0x108c ++#define LIMA_PP_PERF_CNT_1_ENABLE 0x10a0 ++#define LIMA_PP_PERF_CNT_1_SRC 0x10a4 ++#define LIMA_PP_PERF_CNT_1_LIMIT 0x10a8 ++#define LIMA_PP_PERF_CNT_1_VALUE 0x10ac + #define LIMA_PP_PERFMON_CONTR 0x10b0 + #define LIMA_PP_PERFMON_BASE 0x10b4 + +@@ -226,41 +226,41 @@ + LIMA_PP_IRQ_MASK_ERROR) + + /* MMU regs */ +-#define LIMA_MMU_DTE_ADDR 0x0000 +-#define LIMA_MMU_STATUS 0x0004 +-#define LIMA_MMU_STATUS_PAGING_ENABLED (1 << 0) +-#define LIMA_MMU_STATUS_PAGE_FAULT_ACTIVE (1 << 1) +-#define LIMA_MMU_STATUS_STALL_ACTIVE (1 << 2) +-#define LIMA_MMU_STATUS_IDLE (1 << 3) +-#define LIMA_MMU_STATUS_REPLAY_BUFFER_EMPTY (1 << 4) +-#define LIMA_MMU_STATUS_PAGE_FAULT_IS_WRITE (1 << 5) ++#define LIMA_MMU_DTE_ADDR 0x0000 ++#define LIMA_MMU_STATUS 0x0004 ++#define LIMA_MMU_STATUS_PAGING_ENABLED BIT(0) ++#define LIMA_MMU_STATUS_PAGE_FAULT_ACTIVE BIT(1) ++#define LIMA_MMU_STATUS_STALL_ACTIVE BIT(2) ++#define LIMA_MMU_STATUS_IDLE BIT(3) ++#define LIMA_MMU_STATUS_REPLAY_BUFFER_EMPTY BIT(4) ++#define LIMA_MMU_STATUS_PAGE_FAULT_IS_WRITE BIT(5) + #define LIMA_MMU_STATUS_BUS_ID(x) ((x >> 6) & 0x1F) +-#define LIMA_MMU_COMMAND 0x0008 +-#define LIMA_MMU_COMMAND_ENABLE_PAGING 0x00 +-#define LIMA_MMU_COMMAND_DISABLE_PAGING 0x01 +-#define LIMA_MMU_COMMAND_ENABLE_STALL 0x02 +-#define LIMA_MMU_COMMAND_DISABLE_STALL 0x03 +-#define LIMA_MMU_COMMAND_ZAP_CACHE 0x04 +-#define LIMA_MMU_COMMAND_PAGE_FAULT_DONE 0x05 +-#define LIMA_MMU_COMMAND_HARD_RESET 0x06 +-#define LIMA_MMU_PAGE_FAULT_ADDR 0x000C +-#define LIMA_MMU_ZAP_ONE_LINE 0x0010 +-#define LIMA_MMU_INT_RAWSTAT 0x0014 +-#define LIMA_MMU_INT_CLEAR 0x0018 +-#define LIMA_MMU_INT_MASK 0x001C +-#define LIMA_MMU_INT_PAGE_FAULT 0x01 +-#define LIMA_MMU_INT_READ_BUS_ERROR 0x02 +-#define LIMA_MMU_INT_STATUS 0x0020 ++#define LIMA_MMU_COMMAND 0x0008 ++#define LIMA_MMU_COMMAND_ENABLE_PAGING 0x00 ++#define LIMA_MMU_COMMAND_DISABLE_PAGING 0x01 ++#define LIMA_MMU_COMMAND_ENABLE_STALL 0x02 ++#define LIMA_MMU_COMMAND_DISABLE_STALL 0x03 ++#define LIMA_MMU_COMMAND_ZAP_CACHE 0x04 ++#define LIMA_MMU_COMMAND_PAGE_FAULT_DONE 0x05 ++#define LIMA_MMU_COMMAND_HARD_RESET 0x06 ++#define LIMA_MMU_PAGE_FAULT_ADDR 0x000C ++#define LIMA_MMU_ZAP_ONE_LINE 0x0010 ++#define LIMA_MMU_INT_RAWSTAT 0x0014 ++#define LIMA_MMU_INT_CLEAR 0x0018 ++#define LIMA_MMU_INT_MASK 0x001C ++#define LIMA_MMU_INT_PAGE_FAULT BIT(0) ++#define LIMA_MMU_INT_READ_BUS_ERROR BIT(1) ++#define LIMA_MMU_INT_STATUS 0x0020 + +-#define LIMA_VM_FLAG_PRESENT (1 << 0) +-#define LIMA_VM_FLAG_READ_PERMISSION (1 << 1) +-#define LIMA_VM_FLAG_WRITE_PERMISSION (1 << 2) +-#define LIMA_VM_FLAG_OVERRIDE_CACHE (1 << 3) +-#define LIMA_VM_FLAG_WRITE_CACHEABLE (1 << 4) +-#define LIMA_VM_FLAG_WRITE_ALLOCATE (1 << 5) +-#define LIMA_VM_FLAG_WRITE_BUFFERABLE (1 << 6) +-#define LIMA_VM_FLAG_READ_CACHEABLE (1 << 7) +-#define LIMA_VM_FLAG_READ_ALLOCATE (1 << 8) ++#define LIMA_VM_FLAG_PRESENT BIT(0) ++#define LIMA_VM_FLAG_READ_PERMISSION BIT(1) ++#define LIMA_VM_FLAG_WRITE_PERMISSION BIT(2) ++#define LIMA_VM_FLAG_OVERRIDE_CACHE BIT(3) ++#define LIMA_VM_FLAG_WRITE_CACHEABLE BIT(4) ++#define LIMA_VM_FLAG_WRITE_ALLOCATE BIT(5) ++#define LIMA_VM_FLAG_WRITE_BUFFERABLE BIT(6) ++#define LIMA_VM_FLAG_READ_CACHEABLE BIT(7) ++#define LIMA_VM_FLAG_READ_ALLOCATE BIT(8) + #define LIMA_VM_FLAG_MASK 0x1FF + + #define LIMA_VM_FLAGS_CACHE ( \ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0063-drm-lima-add-IRQF_SHARED-for-GP-irq.patch b/patch/kernel/sunxi-dev/0063-drm-lima-add-IRQF_SHARED-for-GP-irq.patch new file mode 100644 index 000000000..6ed612c6c --- /dev/null +++ b/patch/kernel/sunxi-dev/0063-drm-lima-add-IRQF_SHARED-for-GP-irq.patch @@ -0,0 +1,30 @@ +From 9d7b31732a23ae2f07df1276b7d94cff59d7f0f6 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Thu, 24 May 2018 08:36:21 +0800 +Subject: [PATCH 063/146] drm/lima: add IRQF_SHARED for GP irq + +On some platform all IRQs of GPU share the same line. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_gp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c +index 280a40d857f4..10d7ee16a1d5 100644 +--- a/drivers/gpu/drm/lima/lima_gp.c ++++ b/drivers/gpu/drm/lima/lima_gp.c +@@ -224,8 +224,8 @@ int lima_gp_init(struct lima_ip *ip) + if (err) + return err; + +- err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler, 0, +- lima_ip_name(ip), ip); ++ err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler, ++ IRQF_SHARED, lima_ip_name(ip), ip); + if (err) { + dev_err(dev->dev, "gp %s fail to request irq\n", + lima_ip_name(ip)); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0064-drm-lima-Kconfig-only-depend-on-ARM-or-ARM64.patch b/patch/kernel/sunxi-dev/0064-drm-lima-Kconfig-only-depend-on-ARM-or-ARM64.patch new file mode 100644 index 000000000..060c6b3a5 --- /dev/null +++ b/patch/kernel/sunxi-dev/0064-drm-lima-Kconfig-only-depend-on-ARM-or-ARM64.patch @@ -0,0 +1,30 @@ +From 6d3f37068bbfac21355642148a182c125eb28d19 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Thu, 24 May 2018 14:22:03 +0800 +Subject: [PATCH 064/146] drm/lima: Kconfig only depend on ARM or ARM64 + +The depend list gets longer and longer. When adding +ARCH_ZYNQMP I decide to just depend on ARM or ARM64 +as this GPU can be seen on many ARM SoCs. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig +index 7256625aee04..870f66f407b8 100644 +--- a/drivers/gpu/drm/lima/Kconfig ++++ b/drivers/gpu/drm/lima/Kconfig +@@ -4,7 +4,7 @@ + config DRM_LIMA + tristate "LIMA (DRM support for ARM Mali 400/450 GPU)" + depends on DRM +- depends on ARCH_SUNXI || ARCH_ROCKCHIP || ARCH_EXYNOS || ARCH_MESON ++ depends on ARM || ARM64 || COMPILE_TEST + select DRM_SCHED + select DRM_TTM + help +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0065-drm-lima-add-comments-for-lima_reg.h.patch b/patch/kernel/sunxi-dev/0065-drm-lima-add-comments-for-lima_reg.h.patch new file mode 100644 index 000000000..61e4e54ab --- /dev/null +++ b/patch/kernel/sunxi-dev/0065-drm-lima-add-comments-for-lima_reg.h.patch @@ -0,0 +1,31 @@ +From 27a1223c73a19b993d0b0a45d0908fc0d76fae0d Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Thu, 24 May 2018 14:33:36 +0800 +Subject: [PATCH 065/146] drm/lima: add comments for lima_reg.h + +This file is based on official ARM Mali Utgard GPU +kernel driver. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_regs.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/lima/lima_regs.h b/drivers/gpu/drm/lima/lima_regs.h +index 91ae9d6c197b..d8c762c17e52 100644 +--- a/drivers/gpu/drm/lima/lima_regs.h ++++ b/drivers/gpu/drm/lima/lima_regs.h +@@ -6,6 +6,10 @@ + #ifndef __LIMA_REGS_H__ + #define __LIMA_REGS_H__ + ++/* This file's register definition is collected from the ++ * official ARM Mali Utgard GPU kernel driver source code ++ */ ++ + /* PMU regs */ + #define LIMA_PMU_POWER_UP 0x00 + #define LIMA_PMU_POWER_DOWN 0x04 +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0066-drm-lima-wait-bo-fence-before-bo-close.patch b/patch/kernel/sunxi-dev/0066-drm-lima-wait-bo-fence-before-bo-close.patch new file mode 100644 index 000000000..0a7fb0c33 --- /dev/null +++ b/patch/kernel/sunxi-dev/0066-drm-lima-wait-bo-fence-before-bo-close.patch @@ -0,0 +1,114 @@ +From 4402e0d7858450f531f38aa7766233b4b8c8e1bb Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 28 May 2018 17:36:59 +0800 +Subject: [PATCH 066/146] drm/lima: wait bo fence before bo close + +We can't bring preclose back, so use this +method for user application termination. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_drv.c | 9 +-------- + drivers/gpu/drm/lima/lima_sched.c | 2 +- + drivers/gpu/drm/lima/lima_vm.c | 32 +++++++++++++++++++++++++++++++ + 3 files changed, 34 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +index 7f2e47da6801..d3ab9f7abb93 100644 +--- a/drivers/gpu/drm/lima/lima_drv.c ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -270,17 +270,11 @@ static int lima_drm_driver_open(struct drm_device *dev, struct drm_file *file) + return err; + } + +-static void lima_drm_driver_preclose(struct drm_device *dev, struct drm_file *file) +-{ +- struct lima_drm_priv *priv = file->driver_priv; +- +- lima_ctx_mgr_fini(&priv->ctx_mgr); +-} +- + static void lima_drm_driver_postclose(struct drm_device *dev, struct drm_file *file) + { + struct lima_drm_priv *priv = file->driver_priv; + ++ lima_ctx_mgr_fini(&priv->ctx_mgr); + lima_vm_put(priv->vm); + kfree(priv); + } +@@ -310,7 +304,6 @@ static const struct file_operations lima_drm_driver_fops = { + static struct drm_driver lima_drm_driver = { + .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_PRIME, + .open = lima_drm_driver_open, +- .preclose = lima_drm_driver_preclose, + .postclose = lima_drm_driver_postclose, + .ioctls = lima_drm_driver_ioctls, + .num_ioctls = ARRAY_SIZE(lima_drm_driver_ioctls), +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index 3b5ea2e4674d..89e758718d62 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -112,7 +112,7 @@ int lima_sched_task_init(struct lima_sched_task *task, + int err; + + err = drm_sched_job_init(&task->base, context->base.sched, +- &context->base, context); ++ &context->base, vm); + if (err) + return err; + +diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c +index 11eb3c278df2..19a683c2921b 100644 +--- a/drivers/gpu/drm/lima/lima_vm.c ++++ b/drivers/gpu/drm/lima/lima_vm.c +@@ -195,15 +195,47 @@ int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo) + return 0; + } + ++/* wait only fence of resv from task using vm */ ++static int lima_vm_wait_resv(struct lima_vm *vm, ++ struct reservation_object *resv) ++{ ++ unsigned nr_fences; ++ struct dma_fence **fences; ++ int i; ++ long err; ++ ++ err = reservation_object_get_fences_rcu(resv, NULL, &nr_fences, &fences); ++ if (err || !nr_fences) ++ return err; ++ ++ for (i = 0; i < nr_fences; i++) { ++ struct drm_sched_fence *sf = to_drm_sched_fence(fences[i]); ++ if (sf && sf->owner == vm) ++ err |= dma_fence_wait(fences[i], false); ++ dma_fence_put(fences[i]); ++ } ++ ++ kfree(fences); ++ return err; ++} ++ + int lima_vm_bo_del(struct lima_vm *vm, struct lima_bo *bo) + { + struct lima_bo_va *bo_va; + struct lima_bo_va_mapping *mapping, *tmp; ++ int err; + + bo_va = lima_vm_bo_find(vm, bo); + if (--bo_va->ref_count > 0) + return 0; + ++ /* wait bo idle before unmap it from vm in case user ++ * space application is terminated when bo is busy. ++ */ ++ err = lima_vm_wait_resv(vm, bo->tbo.resv); ++ if (err) ++ dev_err(vm->dev->dev, "bo del fail to wait (%d)\n", err); ++ + list_for_each_entry_safe(mapping, tmp, &bo_va->mapping, list) { + lima_vm_unmap(vm, mapping); + } +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0067-drm-lima-refine-lima_gem_sync_bo.patch b/patch/kernel/sunxi-dev/0067-drm-lima-refine-lima_gem_sync_bo.patch new file mode 100644 index 000000000..79d8a4f85 --- /dev/null +++ b/patch/kernel/sunxi-dev/0067-drm-lima-refine-lima_gem_sync_bo.patch @@ -0,0 +1,125 @@ +From 5c2d27d3a2b35475ea707b14a41e5c557c9ebad2 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 28 May 2018 18:55:39 +0800 +Subject: [PATCH 067/146] drm/lima: refine lima_gem_sync_bo + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_gem.c | 58 +++++++++++++++++-------------- + drivers/gpu/drm/lima/lima_sched.c | 5 ++- + 2 files changed, 36 insertions(+), 27 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c +index d9c15acb7cf8..3bdff19eb2f9 100644 +--- a/drivers/gpu/drm/lima/lima_gem.c ++++ b/drivers/gpu/drm/lima/lima_gem.c +@@ -217,9 +217,7 @@ int lima_gem_va_unmap(struct drm_file *file, u32 handle, u32 va) + static int lima_gem_sync_bo(struct lima_sched_task *task, struct lima_bo *bo, + bool write, bool explicit) + { +- int i, err; +- struct dma_fence *f; +- u64 context = task->base.s_fence->finished.context; ++ int err = 0; + + if (!write) { + err = reservation_object_reserve_shared(bo->tbo.resv); +@@ -233,31 +231,38 @@ static int lima_gem_sync_bo(struct lima_sched_task *task, struct lima_bo *bo, + + /* implicit sync use bo fence in resv obj */ + if (write) { +- struct reservation_object_list *fobj = +- reservation_object_get_list(bo->tbo.resv); +- +- if (fobj && fobj->shared_count > 0) { +- for (i = 0; i < fobj->shared_count; i++) { +- f = rcu_dereference_protected( +- fobj->shared[i], +- reservation_object_held(bo->tbo.resv)); +- if (f->context != context) { +- err = lima_sched_task_add_dep(task, f); +- if (err) +- return err; +- } +- } +- } +- } ++ unsigned nr_fences; ++ struct dma_fence **fences; ++ int i; + +- f = reservation_object_get_excl(bo->tbo.resv); +- if (f) { +- err = lima_sched_task_add_dep(task, f); +- if (err) ++ err = reservation_object_get_fences_rcu( ++ bo->tbo.resv, NULL, &nr_fences, &fences); ++ if (err || !nr_fences) + return err; ++ ++ for (i = 0; i < nr_fences; i++) { ++ err = lima_sched_task_add_dep(task, fences[i]); ++ if (err) ++ break; ++ } ++ ++ /* for error case free remaining fences */ ++ for ( ; i < nr_fences; i++) ++ dma_fence_put(fences[i]); ++ ++ kfree(fences); ++ } ++ else { ++ struct dma_fence *fence; ++ fence = reservation_object_get_excl_rcu(bo->tbo.resv); ++ if (fence) { ++ err = lima_sched_task_add_dep(task, fence); ++ if (err) ++ dma_fence_put(fence); ++ } + } + +- return 0; ++ return err; + } + + static int lima_gem_add_deps(struct lima_ctx_mgr *mgr, struct lima_submit *submit) +@@ -291,9 +296,10 @@ static int lima_gem_add_deps(struct lima_ctx_mgr *mgr, struct lima_submit *submi + + if (fence) { + err = lima_sched_task_add_dep(submit->task, fence); +- dma_fence_put(fence); +- if (err) ++ if (err) { ++ dma_fence_put(fence); + break; ++ } + } + } + +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index 89e758718d62..91ec00811071 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -130,6 +130,10 @@ int lima_sched_task_add_dep(struct lima_sched_task *task, struct dma_fence *fenc + { + int i, new_dep = 4; + ++ /* same context's fence is definitly earlier then this task */ ++ if (fence->context == task->base.s_fence->finished.context) ++ return 0; ++ + if (task->dep && task->num_dep == task->max_dep) + new_dep = task->max_dep * 2; + +@@ -141,7 +145,6 @@ int lima_sched_task_add_dep(struct lima_sched_task *task, struct dma_fence *fenc + task->dep = dep; + } + +- dma_fence_get(fence); + for (i = 0; i < task->num_dep; i++) { + if (task->dep[i]->context == fence->context && + dma_fence_is_later(fence, task->dep[i])) { +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0068-drm-lima-vm-will-be-freed-when-lima_sched_free_job.patch b/patch/kernel/sunxi-dev/0068-drm-lima-vm-will-be-freed-when-lima_sched_free_job.patch new file mode 100644 index 000000000..09eb6d614 --- /dev/null +++ b/patch/kernel/sunxi-dev/0068-drm-lima-vm-will-be-freed-when-lima_sched_free_job.patch @@ -0,0 +1,25 @@ +From 2d89860b45cc744356186504b9880c361c158476 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Mon, 28 May 2018 19:01:48 +0800 +Subject: [PATCH 068/146] drm/lima: vm will be freed when lima_sched_free_job + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_sched.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index 91ec00811071..20ed966578a3 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -123,7 +123,6 @@ int lima_sched_task_init(struct lima_sched_task *task, + void lima_sched_task_fini(struct lima_sched_task *task) + { + dma_fence_put(&task->base.s_fence->finished); +- lima_vm_put(task->vm); + } + + int lima_sched_task_add_dep(struct lima_sched_task *task, struct dma_fence *fence) +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0069-drm-lima-vm-alloc-buffer-with-multi-page-table.patch b/patch/kernel/sunxi-dev/0069-drm-lima-vm-alloc-buffer-with-multi-page-table.patch new file mode 100644 index 000000000..7144c2ed4 --- /dev/null +++ b/patch/kernel/sunxi-dev/0069-drm-lima-vm-alloc-buffer-with-multi-page-table.patch @@ -0,0 +1,189 @@ +From 063d7ebf17304fe8a7b85ecb4662f20c4839b6af Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Wed, 30 May 2018 19:18:03 +0800 +Subject: [PATCH 069/146] drm/lima: vm alloc buffer with multi page table + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_vm.c | 95 ++++++++++++++++++++++------------ + drivers/gpu/drm/lima/lima_vm.h | 6 ++- + 2 files changed, 66 insertions(+), 35 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c +index 19a683c2921b..ab7438685234 100644 +--- a/drivers/gpu/drm/lima/lima_vm.c ++++ b/drivers/gpu/drm/lima/lima_vm.c +@@ -28,8 +28,18 @@ struct lima_bo_va { + struct lima_vm *vm; + }; + +-#define LIMA_PDE(va) (va >> 22) +-#define LIMA_PTE(va) ((va & 0x3FFFFF) >> 12) ++#define LIMA_VM_PD_SHIFT 22 ++#define LIMA_VM_PT_SHIFT 12 ++#define LIMA_VM_PB_SHIFT (LIMA_VM_PD_SHIFT + LIMA_VM_NUM_PT_PER_BT_SHIFT) ++#define LIMA_VM_BT_SHIFT LIMA_VM_PT_SHIFT ++ ++#define LIMA_VM_PT_MASK ((1 << LIMA_VM_PD_SHIFT) - 1) ++#define LIMA_VM_BT_MASK ((1 << LIMA_VM_PB_SHIFT) - 1) ++ ++#define LIMA_PDE(va) (va >> LIMA_VM_PD_SHIFT) ++#define LIMA_PTE(va) ((va & LIMA_VM_PT_MASK) >> LIMA_VM_PT_SHIFT) ++#define LIMA_PBE(va) (va >> LIMA_VM_PB_SHIFT) ++#define LIMA_BTE(va) ((va & LIMA_VM_BT_MASK) >> LIMA_VM_BT_SHIFT) + + #define START(node) ((node)->start) + #define LAST(node) ((node)->last) +@@ -45,12 +55,12 @@ static void lima_vm_unmap_page_table(struct lima_vm *vm, u32 start, u32 end) + u32 addr; + + for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) { +- u32 pde = LIMA_PDE(addr); +- u32 pte = LIMA_PTE(addr); +- u32 *pt; ++ u32 pbe = LIMA_PBE(addr); ++ u32 bte = LIMA_BTE(addr); ++ u32 *bt; + +- pt = lima_bo_kmap(vm->pt[pde]); +- pt[pte] = 0; ++ bt = lima_bo_kmap(vm->bts[pbe]); ++ bt[bte] = 0; + } + } + +@@ -61,32 +71,43 @@ static int lima_vm_map_page_table(struct lima_vm *vm, dma_addr_t *dma, + int err, i = 0; + + for (addr = start; addr <= end; addr += LIMA_PAGE_SIZE) { +- u32 pde = LIMA_PDE(addr); +- u32 pte = LIMA_PTE(addr); +- u32 *pd, *pt; ++ u32 pbe = LIMA_PBE(addr); ++ u32 bte = LIMA_BTE(addr); ++ u32 *bt; + +- if (vm->pt[pde]) +- pt = lima_bo_kmap(vm->pt[pde]); ++ if (vm->bts[pbe]) ++ bt = lima_bo_kmap(vm->bts[pbe]); + else { +- vm->pt[pde] = lima_bo_create( +- vm->dev, LIMA_PAGE_SIZE, 0, ttm_bo_type_kernel, ++ struct lima_bo *bt_bo; ++ dma_addr_t *pts; ++ u32 *pd; ++ int j; ++ ++ bt_bo = lima_bo_create( ++ vm->dev, LIMA_PAGE_SIZE << LIMA_VM_NUM_PT_PER_BT_SHIFT, ++ 0, ttm_bo_type_kernel, + NULL, vm->pd->tbo.resv); +- if (IS_ERR(vm->pt[pde])) { +- err = PTR_ERR(vm->pt[pde]); ++ if (IS_ERR(bt_bo)) { ++ err = PTR_ERR(bt_bo); + goto err_out; + } + +- pt = lima_bo_kmap(vm->pt[pde]); +- if (IS_ERR(pt)) { +- err = PTR_ERR(pt); ++ bt = lima_bo_kmap(bt_bo); ++ if (IS_ERR(bt)) { ++ lima_bo_unref(bt_bo); ++ err = PTR_ERR(bt); + goto err_out; + } + ++ vm->bts[pbe] = bt_bo; + pd = lima_bo_kmap(vm->pd); +- pd[pde] = *lima_bo_get_pages(vm->pt[pde]) | LIMA_VM_FLAG_PRESENT; ++ pd += pbe << LIMA_VM_NUM_PT_PER_BT_SHIFT; ++ pts = lima_bo_get_pages(bt_bo); ++ for (j = 0; j < LIMA_VM_NUM_PT_PER_BT; j++) ++ *pd++ = *pts++ | LIMA_VM_FLAG_PRESENT; + } + +- pt[pte] = dma[i++] | LIMA_VM_FLAGS_CACHE; ++ bt[bte] = dma[i++] | LIMA_VM_FLAGS_CACHE; + } + + return 0; +@@ -293,9 +314,9 @@ void lima_vm_release(struct kref *kref) + dev_err(dev->dev, "still active bo inside vm\n"); + } + +- for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) { +- if (vm->pt[i]) +- lima_bo_unref(vm->pt[i]); ++ for (i = 0; i < LIMA_VM_NUM_BT; i++) { ++ if (vm->bts[i]) ++ lima_bo_unref(vm->bts[i]); + } + + if (vm->pd) +@@ -306,20 +327,26 @@ void lima_vm_release(struct kref *kref) + + void lima_vm_print(struct lima_vm *vm) + { +- int i, j; +- u32 *pd = lima_bo_kmap(vm->pd); ++ int i, j, k; ++ u32 *pd, *pt; + + /* to avoid the defined by not used warning */ + (void)&lima_vm_it_iter_next; + +- for (i = 0; i < LIMA_PAGE_ENT_NUM; i++) { +- if (pd[i]) { +- u32 *pt = lima_bo_kmap(vm->pt[i]); +- +- printk(KERN_INFO "lima vm pd %03x:%08x\n", i, pd[i]); +- for (j = 0; j < LIMA_PAGE_ENT_NUM; j++) { +- if (pt[j]) +- printk(KERN_INFO " pt %03x:%08x\n", j, pt[j]); ++ pd = lima_bo_kmap(vm->pd); ++ for (i = 0; i < LIMA_VM_NUM_BT; i++) { ++ if (!vm->bts[i]) ++ continue; ++ ++ pt = lima_bo_kmap(vm->bts[i]); ++ for (j = 0; j < LIMA_VM_NUM_PT_PER_BT; j++) { ++ int idx = (i << LIMA_VM_NUM_PT_PER_BT_SHIFT) + j; ++ printk(KERN_INFO "lima vm pd %03x:%08x\n", idx, pd[idx]); ++ ++ for (k = 0; k < LIMA_PAGE_ENT_NUM; k++) { ++ u32 pte = *pt++; ++ if (pte) ++ printk(KERN_INFO " pt %03x:%08x\n", k, pte); + } + } + } +diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h +index c891a1ee95df..598708ac0d31 100644 +--- a/drivers/gpu/drm/lima/lima_vm.h ++++ b/drivers/gpu/drm/lima/lima_vm.h +@@ -12,6 +12,10 @@ + #define LIMA_PAGE_MASK (LIMA_PAGE_SIZE - 1) + #define LIMA_PAGE_ENT_NUM (LIMA_PAGE_SIZE / sizeof(u32)) + ++#define LIMA_VM_NUM_PT_PER_BT_SHIFT 3 ++#define LIMA_VM_NUM_PT_PER_BT (1 << LIMA_VM_NUM_PT_PER_BT_SHIFT) ++#define LIMA_VM_NUM_BT (LIMA_PAGE_ENT_NUM >> LIMA_VM_NUM_PT_PER_BT_SHIFT) ++ + #define LIMA_VA_RESERVE_START 0xFFF00000 + #define LIMA_VA_RESERVE_DLBU LIMA_VA_RESERVE_START + #define LIMA_VA_RESERVE_END 0x100000000 +@@ -28,7 +32,7 @@ struct lima_vm { + struct lima_device *dev; + + struct lima_bo *pd; +- struct lima_bo *pt[LIMA_PAGE_ENT_NUM]; ++ struct lima_bo *bts[LIMA_VM_NUM_BT]; + }; + + int lima_vm_bo_map(struct lima_vm *vm, struct lima_bo *bo, u32 start); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0070-drm-lima-clear-vm-page-table-when-alloc.patch b/patch/kernel/sunxi-dev/0070-drm-lima-clear-vm-page-table-when-alloc.patch new file mode 100644 index 000000000..4faf4aab1 --- /dev/null +++ b/patch/kernel/sunxi-dev/0070-drm-lima-clear-vm-page-table-when-alloc.patch @@ -0,0 +1,35 @@ +From 3930833ef2781427cccc0860a86525498d646f72 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Thu, 31 May 2018 16:19:07 +0800 +Subject: [PATCH 070/146] drm/lima: clear vm page table when alloc + +ttm_bo_type_kernel will not be cleared when alloc. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_vm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c +index ab7438685234..514115df4e4c 100644 +--- a/drivers/gpu/drm/lima/lima_vm.c ++++ b/drivers/gpu/drm/lima/lima_vm.c +@@ -98,6 +98,7 @@ static int lima_vm_map_page_table(struct lima_vm *vm, dma_addr_t *dma, + err = PTR_ERR(bt); + goto err_out; + } ++ memset(bt, 0, LIMA_PAGE_SIZE << LIMA_VM_NUM_PT_PER_BT_SHIFT); + + vm->bts[pbe] = bt_bo; + pd = lima_bo_kmap(vm->pd); +@@ -286,6 +287,7 @@ struct lima_vm *lima_vm_create(struct lima_device *dev) + pd = lima_bo_kmap(vm->pd); + if (IS_ERR(pd)) + goto err_out1; ++ memset(pd, 0, LIMA_PAGE_SIZE); + + if (dev->dlbu_cpu) { + int err = lima_vm_map_page_table( +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0071-drm-lima-update-SPDX-header-to-match-kernel-rules.patch b/patch/kernel/sunxi-dev/0071-drm-lima-update-SPDX-header-to-match-kernel-rules.patch new file mode 100644 index 000000000..2c9d4f696 --- /dev/null +++ b/patch/kernel/sunxi-dev/0071-drm-lima-update-SPDX-header-to-match-kernel-rules.patch @@ -0,0 +1,514 @@ +From d1267be906c38af372a6b1ebe5145158667e6768 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Thu, 31 May 2018 22:37:45 +0800 +Subject: [PATCH 071/146] drm/lima: update SPDX header to match kernel rules + +See +https://www.kernel.org/doc/html/latest/process/license-rules.html + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/Kconfig | 2 +- + drivers/gpu/drm/lima/Makefile | 2 +- + drivers/gpu/drm/lima/lima_bcast.c | 5 ++--- + drivers/gpu/drm/lima/lima_bcast.h | 5 ++--- + drivers/gpu/drm/lima/lima_ctx.c | 5 ++--- + drivers/gpu/drm/lima/lima_ctx.h | 5 ++--- + drivers/gpu/drm/lima/lima_device.c | 5 ++--- + drivers/gpu/drm/lima/lima_device.h | 5 ++--- + drivers/gpu/drm/lima/lima_dlbu.c | 5 ++--- + drivers/gpu/drm/lima/lima_dlbu.h | 5 ++--- + drivers/gpu/drm/lima/lima_drv.c | 5 ++--- + drivers/gpu/drm/lima/lima_drv.h | 5 ++--- + drivers/gpu/drm/lima/lima_gem.c | 5 ++--- + drivers/gpu/drm/lima/lima_gem.h | 5 ++--- + drivers/gpu/drm/lima/lima_gem_prime.c | 5 ++--- + drivers/gpu/drm/lima/lima_gem_prime.h | 5 ++--- + drivers/gpu/drm/lima/lima_gp.c | 5 ++--- + drivers/gpu/drm/lima/lima_gp.h | 5 ++--- + drivers/gpu/drm/lima/lima_l2_cache.c | 5 ++--- + drivers/gpu/drm/lima/lima_l2_cache.h | 5 ++--- + drivers/gpu/drm/lima/lima_mmu.c | 5 ++--- + drivers/gpu/drm/lima/lima_mmu.h | 5 ++--- + drivers/gpu/drm/lima/lima_object.c | 5 ++--- + drivers/gpu/drm/lima/lima_object.h | 5 ++--- + drivers/gpu/drm/lima/lima_pmu.c | 5 ++--- + drivers/gpu/drm/lima/lima_pmu.h | 5 ++--- + drivers/gpu/drm/lima/lima_pp.c | 5 ++--- + drivers/gpu/drm/lima/lima_pp.h | 5 ++--- + drivers/gpu/drm/lima/lima_regs.h | 2 +- + drivers/gpu/drm/lima/lima_sched.c | 5 ++--- + drivers/gpu/drm/lima/lima_sched.h | 5 ++--- + drivers/gpu/drm/lima/lima_ttm.c | 5 ++--- + drivers/gpu/drm/lima/lima_ttm.h | 5 ++--- + drivers/gpu/drm/lima/lima_vm.c | 5 ++--- + drivers/gpu/drm/lima/lima_vm.h | 5 ++--- + include/uapi/drm/lima_drm.h | 5 ++--- + 36 files changed, 69 insertions(+), 102 deletions(-) + +diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig +index 870f66f407b8..bb75bcb97ccb 100644 +--- a/drivers/gpu/drm/lima/Kconfig ++++ b/drivers/gpu/drm/lima/Kconfig +@@ -1,5 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0 OR MIT + # Copyright 2017-2018 Qiang Yu +-# SPDX-License-Identifier: MIT + + config DRM_LIMA + tristate "LIMA (DRM support for ARM Mali 400/450 GPU)" +diff --git a/drivers/gpu/drm/lima/Makefile b/drivers/gpu/drm/lima/Makefile +index 848310557e42..8bb97410d961 100644 +--- a/drivers/gpu/drm/lima/Makefile ++++ b/drivers/gpu/drm/lima/Makefile +@@ -1,5 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0 OR MIT + # Copyright 2017-2018 Qiang Yu +-# SPDX-License-Identifier: MIT + + lima-y := \ + lima_drv.o \ +diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c +index 0786336d3c77..6c2004dce648 100644 +--- a/drivers/gpu/drm/lima/lima_bcast.c ++++ b/drivers/gpu/drm/lima/lima_bcast.c +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h +index f1ba32852742..fb8e1f318c5c 100644 +--- a/drivers/gpu/drm/lima/lima_bcast.h ++++ b/drivers/gpu/drm/lima/lima_bcast.h +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2018 Qiang Yu */ + + #ifndef __LIMA_BCAST_H__ + #define __LIMA_BCAST_H__ +diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c +index 3c8f0aba0169..3f8a944d9266 100644 +--- a/drivers/gpu/drm/lima/lima_ctx.c ++++ b/drivers/gpu/drm/lima/lima_ctx.c +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2018 Qiang Yu */ + + #include + +diff --git a/drivers/gpu/drm/lima/lima_ctx.h b/drivers/gpu/drm/lima/lima_ctx.h +index f3bee2e1893a..80e55e16619f 100644 +--- a/drivers/gpu/drm/lima/lima_ctx.h ++++ b/drivers/gpu/drm/lima/lima_ctx.h +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2018 Qiang Yu */ + + #ifndef __LIMA_CTX_H__ + #define __LIMA_CTX_H__ +diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c +index 8611ed466a29..c85196af8830 100644 +--- a/drivers/gpu/drm/lima/lima_device.c ++++ b/drivers/gpu/drm/lima/lima_device.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h +index 29501f8361d9..d355a2c5c40b 100644 +--- a/drivers/gpu/drm/lima/lima_device.h ++++ b/drivers/gpu/drm/lima/lima_device.h +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2018 Qiang Yu */ + + #ifndef __LIMA_DEVICE_H__ + #define __LIMA_DEVICE_H__ +diff --git a/drivers/gpu/drm/lima/lima_dlbu.c b/drivers/gpu/drm/lima/lima_dlbu.c +index 0b612149accb..444a74348d5e 100644 +--- a/drivers/gpu/drm/lima/lima_dlbu.c ++++ b/drivers/gpu/drm/lima/lima_dlbu.c +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_dlbu.h b/drivers/gpu/drm/lima/lima_dlbu.h +index bc441dccb1ba..6d85403fa410 100644 +--- a/drivers/gpu/drm/lima/lima_dlbu.h ++++ b/drivers/gpu/drm/lima/lima_dlbu.h +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2018 Qiang Yu */ + + #ifndef __LIMA_DLBU_H__ + #define __LIMA_DLBU_H__ +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +index d3ab9f7abb93..e7004e4e1853 100644 +--- a/drivers/gpu/drm/lima/lima_drv.c ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h +index d7dba79950d6..455bf44ae25e 100644 +--- a/drivers/gpu/drm/lima/lima_drv.h ++++ b/drivers/gpu/drm/lima/lima_drv.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_DRV_H__ + #define __LIMA_DRV_H__ +diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c +index 3bdff19eb2f9..ee903ce17494 100644 +--- a/drivers/gpu/drm/lima/lima_gem.c ++++ b/drivers/gpu/drm/lima/lima_gem.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h +index 35098b692b2e..03daad9a85af 100644 +--- a/drivers/gpu/drm/lima/lima_gem.h ++++ b/drivers/gpu/drm/lima/lima_gem.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_GEM_H__ + #define __LIMA_GEM_H__ +diff --git a/drivers/gpu/drm/lima/lima_gem_prime.c b/drivers/gpu/drm/lima/lima_gem_prime.c +index 9a401a6a039b..0e0350ca7f87 100644 +--- a/drivers/gpu/drm/lima/lima_gem_prime.c ++++ b/drivers/gpu/drm/lima/lima_gem_prime.c +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_gem_prime.h b/drivers/gpu/drm/lima/lima_gem_prime.h +index 407482f1a7c0..6dea7dd65b1a 100644 +--- a/drivers/gpu/drm/lima/lima_gem_prime.h ++++ b/drivers/gpu/drm/lima/lima_gem_prime.h +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2018 Qiang Yu */ + + #ifndef __LIMA_GEM_PRIME_H__ + #define __LIMA_GEM_PRIME_H__ +diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c +index 10d7ee16a1d5..706652cb1741 100644 +--- a/drivers/gpu/drm/lima/lima_gp.c ++++ b/drivers/gpu/drm/lima/lima_gp.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_gp.h b/drivers/gpu/drm/lima/lima_gp.h +index 45e654737767..55bc48ec7603 100644 +--- a/drivers/gpu/drm/lima/lima_gp.h ++++ b/drivers/gpu/drm/lima/lima_gp.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_GP_H__ + #define __LIMA_GP_H__ +diff --git a/drivers/gpu/drm/lima/lima_l2_cache.c b/drivers/gpu/drm/lima/lima_l2_cache.c +index 25313ab5fe92..e7cdec720e5d 100644 +--- a/drivers/gpu/drm/lima/lima_l2_cache.c ++++ b/drivers/gpu/drm/lima/lima_l2_cache.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_l2_cache.h b/drivers/gpu/drm/lima/lima_l2_cache.h +index 6ecc07e33430..2ff91eafefbe 100644 +--- a/drivers/gpu/drm/lima/lima_l2_cache.h ++++ b/drivers/gpu/drm/lima/lima_l2_cache.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_L2_CACHE_H__ + #define __LIMA_L2_CACHE_H__ +diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c +index 7de3935b5cc6..234fb90a4285 100644 +--- a/drivers/gpu/drm/lima/lima_mmu.c ++++ b/drivers/gpu/drm/lima/lima_mmu.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_mmu.h b/drivers/gpu/drm/lima/lima_mmu.h +index ac32f620e3d9..ca173b60fc73 100644 +--- a/drivers/gpu/drm/lima/lima_mmu.h ++++ b/drivers/gpu/drm/lima/lima_mmu.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_MMU_H__ + #define __LIMA_MMU_H__ +diff --git a/drivers/gpu/drm/lima/lima_object.c b/drivers/gpu/drm/lima/lima_object.c +index 6ca17ef2e701..c44e1f81abf8 100644 +--- a/drivers/gpu/drm/lima/lima_object.c ++++ b/drivers/gpu/drm/lima/lima_object.c +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2018 Qiang Yu */ + + #include + +diff --git a/drivers/gpu/drm/lima/lima_object.h b/drivers/gpu/drm/lima/lima_object.h +index ae67de9d2565..7286514c0f07 100644 +--- a/drivers/gpu/drm/lima/lima_object.h ++++ b/drivers/gpu/drm/lima/lima_object.h +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2018 Qiang Yu */ + + #ifndef __LIMA_OBJECT_H__ + #define __LIMA_OBJECT_H__ +diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c +index f4548c90b6b7..e852077c1e52 100644 +--- a/drivers/gpu/drm/lima/lima_pmu.c ++++ b/drivers/gpu/drm/lima/lima_pmu.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_pmu.h b/drivers/gpu/drm/lima/lima_pmu.h +index b807e9f42928..1cf94a35bdf9 100644 +--- a/drivers/gpu/drm/lima/lima_pmu.h ++++ b/drivers/gpu/drm/lima/lima_pmu.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_PMU_H__ + #define __LIMA_PMU_H__ +diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c +index 8db3d134e244..29e3ddfb394b 100644 +--- a/drivers/gpu/drm/lima/lima_pp.c ++++ b/drivers/gpu/drm/lima/lima_pp.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_pp.h b/drivers/gpu/drm/lima/lima_pp.h +index b928f9516d30..f83f8cb4d30a 100644 +--- a/drivers/gpu/drm/lima/lima_pp.h ++++ b/drivers/gpu/drm/lima/lima_pp.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_PP_H__ + #define __LIMA_PP_H__ +diff --git a/drivers/gpu/drm/lima/lima_regs.h b/drivers/gpu/drm/lima/lima_regs.h +index d8c762c17e52..d5ade8fc8901 100644 +--- a/drivers/gpu/drm/lima/lima_regs.h ++++ b/drivers/gpu/drm/lima/lima_regs.h +@@ -1,6 +1,6 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ + /* Copyright 2010-2017 ARM Limited. All rights reserved. + * Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: GPL-2.0 + */ + + #ifndef __LIMA_REGS_H__ +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index 20ed966578a3..e725e793a668 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h +index 581b8601fe81..e1393767128f 100644 +--- a/drivers/gpu/drm/lima/lima_sched.h ++++ b/drivers/gpu/drm/lima/lima_sched.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_SCHED_H__ + #define __LIMA_SCHED_H__ +diff --git a/drivers/gpu/drm/lima/lima_ttm.c b/drivers/gpu/drm/lima/lima_ttm.c +index 4be441b02f6c..a79ff0e86929 100644 +--- a/drivers/gpu/drm/lima/lima_ttm.c ++++ b/drivers/gpu/drm/lima/lima_ttm.c +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_ttm.h b/drivers/gpu/drm/lima/lima_ttm.h +index 42af0b136ffb..df3c06aa92a9 100644 +--- a/drivers/gpu/drm/lima/lima_ttm.h ++++ b/drivers/gpu/drm/lima/lima_ttm.h +@@ -1,6 +1,5 @@ +-/* Copyright 2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2018 Qiang Yu */ + + #ifndef __LIMA_TTM_H__ + #define __LIMA_TTM_H__ +diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c +index 514115df4e4c..a264f3ae83fe 100644 +--- a/drivers/gpu/drm/lima/lima_vm.c ++++ b/drivers/gpu/drm/lima/lima_vm.c +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++// SPDX-License-Identifier: GPL-2.0 OR MIT ++/* Copyright 2017-2018 Qiang Yu */ + + #include + #include +diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h +index 598708ac0d31..f615f8dfe71d 100644 +--- a/drivers/gpu/drm/lima/lima_vm.h ++++ b/drivers/gpu/drm/lima/lima_vm.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: GPL-2.0 OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_VM_H__ + #define __LIMA_VM_H__ +diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h +index a489bba517c7..e453bc4f0de4 100644 +--- a/include/uapi/drm/lima_drm.h ++++ b/include/uapi/drm/lima_drm.h +@@ -1,6 +1,5 @@ +-/* Copyright 2017-2018 Qiang Yu +- * SPDX-License-Identifier: MIT +- */ ++/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT */ ++/* Copyright 2017-2018 Qiang Yu */ + + #ifndef __LIMA_DRM_H__ + #define __LIMA_DRM_H__ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0072-drm-fourcc-add-ARM-tiled-format-modifier.patch b/patch/kernel/sunxi-dev/0072-drm-fourcc-add-ARM-tiled-format-modifier.patch new file mode 100644 index 000000000..1b4f0aa4b --- /dev/null +++ b/patch/kernel/sunxi-dev/0072-drm-fourcc-add-ARM-tiled-format-modifier.patch @@ -0,0 +1,33 @@ +From c578aadd5ccfe5c64f628ef3aa8c7ff88600e421 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Tue, 19 Jun 2018 13:51:17 +0800 +Subject: [PATCH 072/146] drm/fourcc: add ARM tiled format modifier + +Signed-off-by: Qiang Yu +--- + include/uapi/drm/drm_fourcc.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 721ab7e54d96..097d9faca608 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -581,6 +581,15 @@ extern "C" { + */ + #define AFBC_FORMAT_MOD_SC (1ULL << 9) + ++/* ++ * ARM tiled format ++ * ++ * This is used by ARM Mali Utgard/Midgard GPU. It divides buffer into ++ * 16x16 pixel blocks. Blocks are stored linearly in order, but pixels ++ * in the block are reordered. ++ */ ++#define DRM_FORMAT_MOD_ARM_TILED fourcc_mod_code(ARM, 1) ++ + #if defined(__cplusplus) + } + #endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0073-drm-lima-add-DRM_LIMA_GEM_MOD-ioctl.patch b/patch/kernel/sunxi-dev/0073-drm-lima-add-DRM_LIMA_GEM_MOD-ioctl.patch new file mode 100644 index 000000000..ba4d2ab89 --- /dev/null +++ b/patch/kernel/sunxi-dev/0073-drm-lima-add-DRM_LIMA_GEM_MOD-ioctl.patch @@ -0,0 +1,172 @@ +From e0cc638d05b59eb60cd268106d883e1913c62de5 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Tue, 19 Jun 2018 22:22:09 +0800 +Subject: [PATCH 073/146] drm/lima: add DRM_LIMA_GEM_MOD ioctl + +Used to share buffer format across processes. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_drv.c | 13 ++++++++++++ + drivers/gpu/drm/lima/lima_gem.c | 32 ++++++++++++++++++++++++++++++ + drivers/gpu/drm/lima/lima_gem.h | 2 ++ + drivers/gpu/drm/lima/lima_object.c | 2 ++ + drivers/gpu/drm/lima/lima_object.h | 2 ++ + include/uapi/drm/lima_drm.h | 11 ++++++++++ + 6 files changed, 62 insertions(+) + +diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c +index e7004e4e1853..536d0d442970 100644 +--- a/drivers/gpu/drm/lima/lima_drv.c ++++ b/drivers/gpu/drm/lima/lima_drv.c +@@ -243,6 +243,18 @@ static int lima_ioctl_ctx(struct drm_device *dev, void *data, struct drm_file *f + return -EINVAL; + } + ++static int lima_ioctl_gem_mod(struct drm_device *dev, void *data, struct drm_file *file) ++{ ++ struct drm_lima_gem_mod *args = data; ++ ++ if (args->op == LIMA_GEM_MOD_OP_GET) ++ return lima_gem_get_modifier(file, args->handle, &args->modifier); ++ else if (args->op == LIMA_GEM_MOD_OP_SET) ++ return lima_gem_set_modifier(file, args->handle, args->modifier); ++ ++ return -EINVAL; ++} ++ + static int lima_drm_driver_open(struct drm_device *dev, struct drm_file *file) + { + int err; +@@ -287,6 +299,7 @@ static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = { + DRM_IOCTL_DEF_DRV(LIMA_WAIT_FENCE, lima_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT, lima_ioctl_gem_wait, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_CTX, lima_ioctl_ctx, DRM_AUTH|DRM_RENDER_ALLOW), ++ DRM_IOCTL_DEF_DRV(LIMA_GEM_MOD, lima_ioctl_gem_mod, DRM_AUTH|DRM_RENDER_ALLOW), + }; + + static const struct file_operations lima_drm_driver_fops = { +diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c +index ee903ce17494..02bf76113a66 100644 +--- a/drivers/gpu/drm/lima/lima_gem.c ++++ b/drivers/gpu/drm/lima/lima_gem.c +@@ -444,3 +444,35 @@ int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, u64 timeout_ns) + drm_gem_object_put_unlocked(obj); + return ret; + } ++ ++int lima_gem_get_modifier(struct drm_file *file, u32 handle, u64 *modifier) ++{ ++ struct drm_gem_object *obj; ++ struct lima_bo *bo; ++ ++ obj = drm_gem_object_lookup(file, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ bo = to_lima_bo(obj); ++ *modifier = bo->modifier; ++ ++ drm_gem_object_put_unlocked(obj); ++ return 0; ++} ++ ++int lima_gem_set_modifier(struct drm_file *file, u32 handle, u64 modifier) ++{ ++ struct drm_gem_object *obj; ++ struct lima_bo *bo; ++ ++ obj = drm_gem_object_lookup(file, handle); ++ if (!obj) ++ return -ENOENT; ++ ++ bo = to_lima_bo(obj); ++ bo->modifier = modifier; ++ ++ drm_gem_object_put_unlocked(obj); ++ return 0; ++} +diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h +index 03daad9a85af..da6968fab6bb 100644 +--- a/drivers/gpu/drm/lima/lima_gem.h ++++ b/drivers/gpu/drm/lima/lima_gem.h +@@ -19,5 +19,7 @@ int lima_gem_va_map(struct drm_file *file, u32 handle, u32 flags, u32 va); + int lima_gem_va_unmap(struct drm_file *file, u32 handle, u32 va); + int lima_gem_submit(struct drm_file *file, struct lima_submit *submit); + int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, u64 timeout_ns); ++int lima_gem_get_modifier(struct drm_file *file, u32 handle, u64 *modifier); ++int lima_gem_set_modifier(struct drm_file *file, u32 handle, u64 modifier); + + #endif +diff --git a/drivers/gpu/drm/lima/lima_object.c b/drivers/gpu/drm/lima/lima_object.c +index c44e1f81abf8..34d9b4dc2df6 100644 +--- a/drivers/gpu/drm/lima/lima_object.c ++++ b/drivers/gpu/drm/lima/lima_object.c +@@ -2,6 +2,7 @@ + /* Copyright 2018 Qiang Yu */ + + #include ++#include + + #include "lima_object.h" + +@@ -70,6 +71,7 @@ struct lima_bo *lima_bo_create(struct lima_device *dev, u64 size, + if (err) + goto err_out; + ++ bo->modifier = DRM_FORMAT_MOD_INVALID; + return bo; + + err_out: +diff --git a/drivers/gpu/drm/lima/lima_object.h b/drivers/gpu/drm/lima/lima_object.h +index 7286514c0f07..f854a25637f2 100644 +--- a/drivers/gpu/drm/lima/lima_object.h ++++ b/drivers/gpu/drm/lima/lima_object.h +@@ -19,6 +19,8 @@ struct lima_bo { + struct ttm_bo_kmap_obj kmap; + + struct list_head va; ++ ++ u64 modifier; + }; + + static inline struct lima_bo * +diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h +index e453bc4f0de4..77cb39af1a45 100644 +--- a/include/uapi/drm/lima_drm.h ++++ b/include/uapi/drm/lima_drm.h +@@ -152,6 +152,15 @@ struct drm_lima_ctx { + __u32 id; /* in/out */ + }; + ++#define LIMA_GEM_MOD_OP_GET 0 ++#define LIMA_GEM_MOD_OP_SET 1 ++ ++struct drm_lima_gem_mod { ++ __u32 handle; /* in */ ++ __u32 op; /* in */ ++ __u64 modifier; /* in/out */ ++}; ++ + #define DRM_LIMA_INFO 0x00 + #define DRM_LIMA_GEM_CREATE 0x01 + #define DRM_LIMA_GEM_INFO 0x02 +@@ -160,6 +169,7 @@ struct drm_lima_ctx { + #define DRM_LIMA_WAIT_FENCE 0x05 + #define DRM_LIMA_GEM_WAIT 0x06 + #define DRM_LIMA_CTX 0x07 ++#define DRM_LIMA_GEM_MOD 0x08 + + #define DRM_IOCTL_LIMA_INFO DRM_IOR(DRM_COMMAND_BASE + DRM_LIMA_INFO, struct drm_lima_info) + #define DRM_IOCTL_LIMA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GEM_CREATE, struct drm_lima_gem_create) +@@ -169,6 +179,7 @@ struct drm_lima_ctx { + #define DRM_IOCTL_LIMA_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_WAIT_FENCE, struct drm_lima_wait_fence) + #define DRM_IOCTL_LIMA_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_GEM_WAIT, struct drm_lima_gem_wait) + #define DRM_IOCTL_LIMA_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_CTX, struct drm_lima_ctx) ++#define DRM_IOCTL_LIMA_GEM_MOD DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GEM_MOD, struct drm_lima_gem_mod) + + #if defined(__cplusplus) + } +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0074-a64-ccu-enable-LDOs-for-pll-mipi-and-add-min-max-rat.patch b/patch/kernel/sunxi-dev/0074-a64-ccu-enable-LDOs-for-pll-mipi-and-add-min-max-rat.patch new file mode 100644 index 000000000..e07113f0f --- /dev/null +++ b/patch/kernel/sunxi-dev/0074-a64-ccu-enable-LDOs-for-pll-mipi-and-add-min-max-rat.patch @@ -0,0 +1,58 @@ +From 9c4d2eb582078788a3f115fef91824d9213e237d Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Tue, 24 Jul 2018 10:17:55 -0700 +Subject: [PATCH 074/146] a64: ccu: enable LDOs for pll-mipi and add min/max + rate for it + +--- + drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 ++ + drivers/clk/sunxi-ng/ccu_nkm.c | 5 +++++ + drivers/clk/sunxi-ng/ccu_nkm.h | 3 +++ + 3 files changed, 10 insertions(+) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +index 1fe3c3fbc9bc..7c645f2c017a 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +@@ -163,6 +163,8 @@ static struct ccu_nkm pll_mipi_clk = { + .n = _SUNXI_CCU_MULT(8, 4), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), + .m = _SUNXI_CCU_DIV(0, 4), ++ .min_rate = 300000000, ++ .max_rate = 1400000000, + .common = { + .reg = 0x040, + .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0", +diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c +index 841840e35e61..01e6df4c1232 100644 +--- a/drivers/clk/sunxi-ng/ccu_nkm.c ++++ b/drivers/clk/sunxi-ng/ccu_nkm.c +@@ -122,6 +122,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, + _nkm.min_m = 1; + _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; + ++ if (rate < nkm->min_rate) ++ rate = nkm->min_rate; ++ if (nkm->max_rate && (rate > nkm->max_rate)) ++ rate = nkm->max_rate; ++ + if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate *= nkm->fixed_post_div; + +diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h +index cc6efb70a102..6e01836ef122 100644 +--- a/drivers/clk/sunxi-ng/ccu_nkm.h ++++ b/drivers/clk/sunxi-ng/ccu_nkm.h +@@ -36,6 +36,9 @@ struct ccu_nkm { + + unsigned int fixed_post_div; + ++ unsigned int min_rate; ++ unsigned int max_rate; ++ + struct ccu_common common; + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0075-sopine-baseboard-enable-HS200-for-eMMC.patch b/patch/kernel/sunxi-dev/0075-sopine-baseboard-enable-HS200-for-eMMC.patch new file mode 100644 index 000000000..f406439df --- /dev/null +++ b/patch/kernel/sunxi-dev/0075-sopine-baseboard-enable-HS200-for-eMMC.patch @@ -0,0 +1,25 @@ +From 1d3ae34846fcee5e4d4ec54476c85992d03d204e Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Mon, 10 Sep 2018 16:09:30 -0700 +Subject: [PATCH 075/146] sopine: baseboard: enable HS200 for eMMC + +Signed-off-by: Vasily Khoruzhick +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +index dc728b3b5556..abad307b414a 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +@@ -119,6 +119,7 @@ + bus-width = <8>; + non-removable; + cap-mmc-hw-reset; ++ mmc-hs200-1_8v; + status = "okay"; + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0076-drm-lima-remove-depend-on-ARM-arch.patch b/patch/kernel/sunxi-dev/0076-drm-lima-remove-depend-on-ARM-arch.patch new file mode 100644 index 000000000..e415c79c9 --- /dev/null +++ b/patch/kernel/sunxi-dev/0076-drm-lima-remove-depend-on-ARM-arch.patch @@ -0,0 +1,63 @@ +From fa09957c702e5aa41c09ca452bd7220c1e8a6985 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Sun, 15 Jul 2018 11:24:41 +0800 +Subject: [PATCH 076/146] drm/lima: remove depend on ARM arch + +Mali GPU is used on x86-64 arch too: +https://en.wikipedia.org/wiki/Rockchip#Tablet_processors_with_integrated_modem + +Always use need_dma32 as it won't cause any trouble +on 32bit arch. + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/Kconfig | 1 - + drivers/gpu/drm/lima/lima_ttm.c | 9 +-------- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/lima/Kconfig b/drivers/gpu/drm/lima/Kconfig +index bb75bcb97ccb..89d63cca8a75 100644 +--- a/drivers/gpu/drm/lima/Kconfig ++++ b/drivers/gpu/drm/lima/Kconfig +@@ -4,7 +4,6 @@ + config DRM_LIMA + tristate "LIMA (DRM support for ARM Mali 400/450 GPU)" + depends on DRM +- depends on ARM || ARM64 || COMPILE_TEST + select DRM_SCHED + select DRM_TTM + help +diff --git a/drivers/gpu/drm/lima/lima_ttm.c b/drivers/gpu/drm/lima/lima_ttm.c +index a79ff0e86929..af46dd1edf43 100644 +--- a/drivers/gpu/drm/lima/lima_ttm.c ++++ b/drivers/gpu/drm/lima/lima_ttm.c +@@ -333,25 +333,18 @@ static struct ttm_bo_driver lima_bo_driver = { + int lima_ttm_init(struct lima_device *dev) + { + int err; +- bool need_dma32; + u64 gtt_size; + + err = lima_ttm_global_init(dev); + if (err) + return err; + +-#if defined(CONFIG_ARM) && !defined(CONFIG_ARM_LPAE) +- need_dma32 = false; +-#else +- need_dma32 = true; +-#endif +- + err = ttm_bo_device_init(&dev->mman.bdev, + dev->mman.bo_global_ref.ref.object, + &lima_bo_driver, + dev->ddev->anon_inode->i_mapping, + DRM_FILE_PAGE_OFFSET, +- need_dma32); ++ true); + if (err) { + dev_err(dev->dev, "failed initializing buffer object " + "driver(%d).\n", err); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0077-drm-lima-port-to-4.18-kernel.patch b/patch/kernel/sunxi-dev/0077-drm-lima-port-to-4.18-kernel.patch new file mode 100644 index 000000000..4f5303683 --- /dev/null +++ b/patch/kernel/sunxi-dev/0077-drm-lima-port-to-4.18-kernel.patch @@ -0,0 +1,27 @@ +From 3785d95f0a1735e427c3ddf6c5f49545ff7559e9 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Sun, 15 Jul 2018 12:26:26 +0800 +Subject: [PATCH 077/146] drm/lima: port to 4.18 kernel + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_sched.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index e725e793a668..1e715e58d33b 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -169,8 +169,7 @@ int lima_sched_context_init(struct lima_sched_pipe *pipe, + return -ENOMEM; + + mutex_init(&context->lock); +- err = drm_sched_entity_init(&pipe->base, &context->base, rq, +- lima_sched_max_tasks, guilty); ++ err = drm_sched_entity_init(&pipe->base, &context->base, rq, guilty); + if (err) { + kfree(context->fences); + context->fences = NULL; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0078-drm-lima-user-can-choose-not-to-use-dlbu-on-mali450.patch b/patch/kernel/sunxi-dev/0078-drm-lima-user-can-choose-not-to-use-dlbu-on-mali450.patch new file mode 100644 index 000000000..748b8598e --- /dev/null +++ b/patch/kernel/sunxi-dev/0078-drm-lima-user-can-choose-not-to-use-dlbu-on-mali450.patch @@ -0,0 +1,309 @@ +From ed6a8088a598439e2cd5d1ab86389b658f19e465 Mon Sep 17 00:00:00 2001 +From: Qiang Yu +Date: Wed, 15 Aug 2018 11:17:09 +0800 +Subject: [PATCH 078/146] drm/lima: user can choose not to use dlbu on mali450 + +Signed-off-by: Qiang Yu +--- + drivers/gpu/drm/lima/lima_bcast.c | 24 +++++----- + drivers/gpu/drm/lima/lima_bcast.h | 3 +- + drivers/gpu/drm/lima/lima_device.c | 5 -- + drivers/gpu/drm/lima/lima_dlbu.c | 4 +- + drivers/gpu/drm/lima/lima_dlbu.h | 2 +- + drivers/gpu/drm/lima/lima_pp.c | 75 ++++++++++++++++++------------ + include/uapi/drm/lima_drm.h | 9 +++- + 7 files changed, 67 insertions(+), 55 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c +index 6c2004dce648..63754f6465ea 100644 +--- a/drivers/gpu/drm/lima/lima_bcast.c ++++ b/drivers/gpu/drm/lima/lima_bcast.c +@@ -11,31 +11,31 @@ + #define bcast_write(reg, data) writel(data, ip->iomem + LIMA_BCAST_##reg) + #define bcast_read(reg) readl(ip->iomem + LIMA_BCAST_##reg) + +-void lima_bcast_enable(struct lima_device *dev) ++void lima_bcast_enable(struct lima_device *dev, int num_pp) + { + struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; + struct lima_ip *ip = dev->ip + lima_ip_bcast; +- int i, mask = 0; ++ int i, mask = bcast_read(BROADCAST_MASK) & 0xffff0000; + +- for (i = 0; i < pipe->num_processor; i++) { ++ for (i = 0; i < num_pp; i++) { + struct lima_ip *pp = pipe->processor[i]; + mask |= 1 << (pp->id - lima_ip_pp0); + } + +- bcast_write(BROADCAST_MASK, (mask << 16) | mask); +- bcast_write(INTERRUPT_MASK, mask); ++ bcast_write(BROADCAST_MASK, mask); + } + +-void lima_bcast_disable(struct lima_device *dev) ++int lima_bcast_init(struct lima_ip *ip) + { +- struct lima_ip *ip = dev->ip + lima_ip_bcast; ++ int i, mask = 0; + +- bcast_write(BROADCAST_MASK, 0); +- bcast_write(INTERRUPT_MASK, 0); +-} ++ for (i = lima_ip_pp0; i <= lima_ip_pp7; i++) { ++ if (ip->dev->ip[i].present) ++ mask |= 1 << (i - lima_ip_pp0); ++ } + +-int lima_bcast_init(struct lima_ip *ip) +-{ ++ bcast_write(BROADCAST_MASK, mask << 16); ++ bcast_write(INTERRUPT_MASK, mask); + return 0; + } + +diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h +index fb8e1f318c5c..345e3e809860 100644 +--- a/drivers/gpu/drm/lima/lima_bcast.h ++++ b/drivers/gpu/drm/lima/lima_bcast.h +@@ -9,7 +9,6 @@ struct lima_ip; + int lima_bcast_init(struct lima_ip *ip); + void lima_bcast_fini(struct lima_ip *ip); + +-void lima_bcast_enable(struct lima_device *dev); +-void lima_bcast_disable(struct lima_device *dev); ++void lima_bcast_enable(struct lima_device *dev, int num_pp); + + #endif +diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c +index c85196af8830..b88c84d796fc 100644 +--- a/drivers/gpu/drm/lima/lima_device.c ++++ b/drivers/gpu/drm/lima/lima_device.c +@@ -338,11 +338,6 @@ int lima_device_init(struct lima_device *ldev) + if (err) + goto err_out6; + +- if (ldev->id == lima_gpu_mali450) { +- lima_dlbu_enable(ldev); +- lima_bcast_enable(ldev); +- } +- + return 0; + + err_out6: +diff --git a/drivers/gpu/drm/lima/lima_dlbu.c b/drivers/gpu/drm/lima/lima_dlbu.c +index 444a74348d5e..6697d4ddd887 100644 +--- a/drivers/gpu/drm/lima/lima_dlbu.c ++++ b/drivers/gpu/drm/lima/lima_dlbu.c +@@ -12,13 +12,13 @@ + #define dlbu_write(reg, data) writel(data, ip->iomem + LIMA_DLBU_##reg) + #define dlbu_read(reg) readl(ip->iomem + LIMA_DLBU_##reg) + +-void lima_dlbu_enable(struct lima_device *dev) ++void lima_dlbu_enable(struct lima_device *dev, int num_pp) + { + struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; + struct lima_ip *ip = dev->ip + lima_ip_dlbu; + int i, mask = 0; + +- for (i = 0; i < pipe->num_processor; i++) { ++ for (i = 0; i < num_pp; i++) { + struct lima_ip *pp = pipe->processor[i]; + mask |= 1 << (pp->id - lima_ip_pp0); + } +diff --git a/drivers/gpu/drm/lima/lima_dlbu.h b/drivers/gpu/drm/lima/lima_dlbu.h +index 6d85403fa410..60cba387cf30 100644 +--- a/drivers/gpu/drm/lima/lima_dlbu.h ++++ b/drivers/gpu/drm/lima/lima_dlbu.h +@@ -7,7 +7,7 @@ + struct lima_ip; + struct lima_device; + +-void lima_dlbu_enable(struct lima_device *dev); ++void lima_dlbu_enable(struct lima_device *dev, int num_pp); + void lima_dlbu_disable(struct lima_device *dev); + + void lima_dlbu_set_reg(struct lima_ip *ip, u32 *reg); +diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c +index 29e3ddfb394b..3355895ceeba 100644 +--- a/drivers/gpu/drm/lima/lima_pp.c ++++ b/drivers/gpu/drm/lima/lima_pp.c +@@ -64,8 +64,9 @@ static irqreturn_t lima_pp_bcast_irq_handler(int irq, void *data) + struct lima_ip *pp_bcast = data; + struct lima_device *dev = pp_bcast->dev; + struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; ++ struct drm_lima_m450_pp_frame *frame = pipe->current_task->frame; + +- for (i = 0; i < pipe->num_processor; i++) { ++ for (i = 0; i < frame->num_pp; i++) { + struct lima_ip *ip = pipe->processor[i]; + u32 status, state; + +@@ -135,7 +136,9 @@ static int lima_pp_soft_reset_async_wait(struct lima_ip *ip) + if (ip->id == lima_ip_pp_bcast) { + struct lima_device *dev = ip->dev; + struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp; +- for (i = 0; i < pipe->num_processor; i++) ++ struct drm_lima_m450_pp_frame *frame = pipe->current_task->frame; ++ ++ for (i = 0; i < frame->num_pp; i++) + err |= lima_pp_soft_reset_async_wait_one(pipe->processor[i]); + } + else +@@ -145,24 +148,17 @@ static int lima_pp_soft_reset_async_wait(struct lima_ip *ip) + return err; + } + +-static void lima_pp_start_task(struct lima_ip *ip, u32 *frame, u32 *wb, +- bool skip_stack_addr) ++static void lima_pp_write_frame(struct lima_ip *ip, u32 *frame, u32 *wb) + { + int i, j, n = 0; + +- for (i = 0; i < LIMA_PP_FRAME_REG_NUM; i++) { +- if (skip_stack_addr && i * 4 == LIMA_PP_STACK) +- continue; +- ++ for (i = 0; i < LIMA_PP_FRAME_REG_NUM; i++) + writel(frame[i], ip->iomem + LIMA_PP_FRAME + i * 4); +- } + + for (i = 0; i < 3; i++) { + for (j = 0; j < LIMA_PP_WB_REG_NUM; j++) + writel(wb[n++], ip->iomem + LIMA_PP_WB(i) + j * 4); + } +- +- pp_write(CTRL, LIMA_PP_CTRL_START_RENDERING); + } + + static int lima_pp_hard_reset(struct lima_ip *ip) +@@ -271,13 +267,20 @@ void lima_pp_bcast_fini(struct lima_ip *ip) + static int lima_pp_task_validate(struct lima_sched_pipe *pipe, + struct lima_sched_task *task) + { +- if (!pipe->bcast_processor) { +- struct drm_lima_m400_pp_frame *f = task->frame; ++ u32 num_pp; + +- if (f->num_pp > pipe->num_processor) +- return -EINVAL; ++ if (pipe->bcast_processor) { ++ struct drm_lima_m450_pp_frame *f = task->frame; ++ num_pp = f->num_pp; ++ } ++ else { ++ struct drm_lima_m400_pp_frame *f = task->frame; ++ num_pp = f->num_pp; + } + ++ if (num_pp == 0 || num_pp > pipe->num_processor) ++ return -EINVAL; ++ + return 0; + } + +@@ -287,23 +290,36 @@ static void lima_pp_task_run(struct lima_sched_pipe *pipe, + if (pipe->bcast_processor) { + struct drm_lima_m450_pp_frame *frame = task->frame; + struct lima_device *dev = pipe->bcast_processor->dev; ++ struct lima_ip *ip = pipe->bcast_processor; + int i; + + pipe->done = 0; +- atomic_set(&pipe->task, pipe->num_processor); ++ atomic_set(&pipe->task, frame->num_pp); + +- frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU; +- lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs); ++ if (frame->use_dlbu) { ++ lima_dlbu_enable(dev, frame->num_pp); + +- lima_pp_soft_reset_async_wait(pipe->bcast_processor); ++ frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU; ++ lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs); ++ } ++ else ++ lima_dlbu_disable(dev); ++ ++ lima_bcast_enable(dev, frame->num_pp); ++ ++ lima_pp_soft_reset_async_wait(ip); ++ ++ lima_pp_write_frame(ip, frame->frame, frame->wb); + +- for (i = 0; i < pipe->num_processor; i++) { ++ for (i = 0; i < frame->num_pp; i++) { + struct lima_ip *ip = pipe->processor[i]; ++ + pp_write(STACK, frame->fragment_stack_address[i]); ++ if (!frame->use_dlbu) ++ pp_write(FRAME, frame->plbu_array_address[i]); + } + +- lima_pp_start_task(pipe->bcast_processor, frame->frame, +- frame->wb, true); ++ pp_write(CTRL, LIMA_PP_CTRL_START_RENDERING); + } + else { + struct drm_lima_m400_pp_frame *frame = task->frame; +@@ -312,15 +328,18 @@ static void lima_pp_task_run(struct lima_sched_pipe *pipe, + atomic_set(&pipe->task, frame->num_pp); + + for (i = 0; i < frame->num_pp; i++) { ++ struct lima_ip *ip = pipe->processor[i]; ++ + frame->frame[LIMA_PP_FRAME >> 2] = + frame->plbu_array_address[i]; + frame->frame[LIMA_PP_STACK >> 2] = + frame->fragment_stack_address[i]; + +- lima_pp_soft_reset_async_wait(pipe->processor[i]); ++ lima_pp_soft_reset_async_wait(ip); ++ ++ lima_pp_write_frame(ip, frame->frame, frame->wb); + +- lima_pp_start_task(pipe->processor[i], frame->frame, +- frame->wb, false); ++ pp_write(CTRL, LIMA_PP_CTRL_START_RENDERING); + } + } + } +@@ -340,14 +359,8 @@ static void lima_pp_task_error(struct lima_sched_pipe *pipe) + { + int i; + +- if (pipe->bcast_processor) +- lima_bcast_disable(pipe->bcast_processor->dev); +- + for (i = 0; i < pipe->num_processor; i++) + lima_pp_hard_reset(pipe->processor[i]); +- +- if (pipe->bcast_processor) +- lima_bcast_enable(pipe->bcast_processor->dev); + } + + static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe) +diff --git a/include/uapi/drm/lima_drm.h b/include/uapi/drm/lima_drm.h +index 77cb39af1a45..0c17bf693184 100644 +--- a/include/uapi/drm/lima_drm.h ++++ b/include/uapi/drm/lima_drm.h +@@ -91,9 +91,14 @@ struct drm_lima_m400_pp_frame { + + struct drm_lima_m450_pp_frame { + __u32 frame[LIMA_PP_FRAME_REG_NUM]; +- __u32 _pad; ++ __u32 num_pp; + __u32 wb[3 * LIMA_PP_WB_REG_NUM]; +- __u32 dlbu_regs[4]; ++ __u32 use_dlbu; ++ __u32 _pad; ++ union { ++ __u32 plbu_array_address[8]; ++ __u32 dlbu_regs[4]; ++ }; + __u32 fragment_stack_address[8]; + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0079-drm-bridge-Add-audio-workaround-for-dw_hdmi-v1.32a.patch.disabled b/patch/kernel/sunxi-dev/0079-drm-bridge-Add-audio-workaround-for-dw_hdmi-v1.32a.patch.disabled new file mode 100644 index 000000000..da9d1dee7 --- /dev/null +++ b/patch/kernel/sunxi-dev/0079-drm-bridge-Add-audio-workaround-for-dw_hdmi-v1.32a.patch.disabled @@ -0,0 +1,58 @@ +From 87c27a1c822a43d8f6d7bc2bb889be2d3d80a100 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 3 Sep 2017 11:32:34 +0200 +Subject: [PATCH 079/146] drm: bridge: Add audio workaround for dw_hdmi v1.32a + +Allwinner SoCs with dw hdmi v1.32a seems to have an issue with manual +setting CTS value. BSP driver sets it to auto mode and that works +here too. + +Signed-off-by: Jernej Skrabec +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 30 +++++++++++++++-------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 5971976284bf..4b08840749bd 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -424,16 +424,26 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi) + static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, + unsigned int n) + { +- /* Must be set/cleared first */ +- hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); +- +- /* nshift factor = 0 */ +- hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); +- +- hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | +- HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); +- hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); +- hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); ++ /* ++ * Manual CTS setting doesn't work correctly on Allwinner SoCs with ++ * dw hdmi v1.32a. ++ */ ++ if (hdmi->version != 0x132a) { ++ /* Must be set/cleared first */ ++ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); ++ ++ /* nshift factor = 0 */ ++ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); ++ ++ hdmi_writeb(hdmi, ++ ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | ++ HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); ++ hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); ++ hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); ++ } else { ++ /* set automatic CTS calculation */ ++ hdmi_writeb(hdmi, 0x00, HDMI_AUD_CTS3); ++ } + + hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3); + hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0080-rtl8723bs-disable-error-message-about-failure-to-all.patch b/patch/kernel/sunxi-dev/0080-rtl8723bs-disable-error-message-about-failure-to-all.patch new file mode 100644 index 000000000..089417348 --- /dev/null +++ b/patch/kernel/sunxi-dev/0080-rtl8723bs-disable-error-message-about-failure-to-all.patch @@ -0,0 +1,26 @@ +From 02d04263581ac956a4822b02ee7ccd15aa5600af Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Mon, 10 Sep 2018 20:32:51 -0700 +Subject: [PATCH 080/146] rtl8723bs: disable error message about failure to + alloc recvbuf + +--- + drivers/staging/rtl8723bs/hal/sdio_ops.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c b/drivers/staging/rtl8723bs/hal/sdio_ops.c +index d6b93e1f78d8..ecc4d1db9bbe 100644 +--- a/drivers/staging/rtl8723bs/hal/sdio_ops.c ++++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c +@@ -947,7 +947,7 @@ static struct recv_buf *sd_recv_rxfifo(struct adapter *adapter, u32 size) + recv_priv = &adapter->recvpriv; + recvbuf = rtw_dequeue_recvbuf(&recv_priv->free_recv_buf_queue); + if (!recvbuf) { +- DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__); ++ //DBG_871X_LEVEL(_drv_err_, "%s: alloc recvbuf FAIL!\n", __func__); + return NULL; + } + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0081-arm64-arch_timer-Workaround-for-Allwinner-A64-timer-.patch b/patch/kernel/sunxi-dev/0081-arm64-arch_timer-Workaround-for-Allwinner-A64-timer-.patch new file mode 100644 index 000000000..c33891116 --- /dev/null +++ b/patch/kernel/sunxi-dev/0081-arm64-arch_timer-Workaround-for-Allwinner-A64-timer-.patch @@ -0,0 +1,178 @@ +From 40fc81b67d761368566053d7498c03088adedc10 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Thu, 10 May 2018 21:27:50 -0500 +Subject: [PATCH 081/146] arm64: arch_timer: Workaround for Allwinner A64 timer + instability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Allwinner A64 SoC is known [1] to have an unstable architectural +timer, which manifests itself most obviously in the time jumping forward +a multiple of 95 years [2][3]. This coincides with 2^56 cycles at a +timer frequency of 24 MHz, implying that the time went slightly backward +(and this was interpreted by the kernel as it jumping forward and +wrapping around past the epoch). + +Further investigation revealed instability in the low bits of CNTVCT at +the point a high bit rolls over. This leads to power-of-two cycle +forward and backward jumps. (Testing shows that forward jumps are about +twice as likely as backward jumps.) + +Without trapping reads to CNTVCT, a userspace program is able to read it +in a loop faster than it changes. A test program running on all 4 CPU +cores that reported jumps larger than 100 ms was run for 13.6 hours and +reported the following: + + Count | Event +-------+--------------------------- + 9940 | jumped backward 699ms + 268 | jumped backward 1398ms + 1 | jumped backward 2097ms + 16020 | jumped forward 175ms + 6443 | jumped forward 699ms + 2976 | jumped forward 1398ms + 9 | jumped forward 356516ms + 9 | jumped forward 357215ms + 4 | jumped forward 714430ms + 1 | jumped forward 3578440ms + +This works out to a jump larger than 100 ms about every 5.5 seconds on +each CPU core. + +The largest jump (almost an hour!) was the following sequence of reads: + 0x0000007fffffffff → 0x00000093feffffff → 0x0000008000000000 + +Note that the middle bits don't necessarily all read as all zeroes or +all ones during the anomalous behavior; however the low 11 bits checked +by the function in this patch have never been observed with any other +value. + +Also note that smaller jumps are much more common, with the smallest +backward jumps of 2048 cycles observed over 400 times per second on each +core. (Of course, this is partially due to lower bits rolling over more +frequently.) Any one of these could have caused the 95 year time skip. + +Similar anomalies were observed while reading CNTPCT (after patching the +kernel to allow reads from userspace). However, the jumps are much less +frequent, and only small jumps were observed. The same program as before +(except now reading CNTPCT) observed after 72 hours: + + Count | Event +-------+--------------------------- + 17 | jumped backward 699ms + 52 | jumped forward 175ms + 2831 | jumped forward 699ms + 5 | jumped forward 1398ms +Acked-by: Maxime Ripard +Tested-by: Andre Przywara + +======================================================================== + +Because the CPU can read the CNTPCT/CNTVCT registers faster than they +change, performing two reads of the register and comparing the high bits +(like other workarounds) is not a workable solution. And because the +timer can jump both forward and backward, no pair of reads can +distinguish a good value from a bad one. The only way to guarantee a +good value from consecutive reads would be to read _three_ times, and +take the middle value iff the three values are 1) individually unique +and 2) increasing. This takes at minimum 3 cycles (125 ns), or more if +an anomaly is detected. + +However, since there is a distinct pattern to the bad values, we can +optimize the common case (2046/2048 of the time) to a single read by +simply ignoring values that match the pattern. This still takes no more +than 3 cycles in the worst case, and requires much less code. + +[1]: https://github.com/armbian/build/commit/a08cd6fe7ae9 +[2]: https://forum.armbian.com/topic/3458-a64-datetime-clock-issue/ +[3]: https://irclog.whitequark.org/linux-sunxi/2018-01-26 + +Signed-off-by: Samuel Holland +--- + drivers/clocksource/Kconfig | 11 ++++++++ + drivers/clocksource/arm_arch_timer.c | 39 ++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+) + +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index a11f4ba98b05..bb7fa4175954 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -364,6 +364,17 @@ config ARM64_ERRATUM_858921 + The workaround will be dynamically enabled when an affected + core is detected. + ++config SUN50I_A64_UNSTABLE_TIMER ++ bool "Workaround for Allwinner A64 timer instability" ++ default y ++ depends on ARM_ARCH_TIMER && ARM64 && ARCH_SUNXI ++ select ARM_ARCH_TIMER_OOL_WORKAROUND ++ help ++ This option enables a workaround for instability in the timer on ++ the Allwinner A64 SoC. The workaround will only be active if the ++ allwinner,sun50i-a64-unstable-timer property is found in the ++ timer node. ++ + config ARM_GLOBAL_TIMER + bool "Support for the ARM global timer" if COMPILE_TEST + select TIMER_OF if OF +diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c +index d8c7f5750cdb..e10456525dda 100644 +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -319,6 +319,36 @@ static u64 notrace arm64_858921_read_cntvct_el0(void) + } + #endif + ++#ifdef CONFIG_SUN50I_A64_UNSTABLE_TIMER ++/* ++ * The low bits of each register can transiently read as all ones or all zeroes ++ * when bit 11 or greater rolls over. Since the value can jump both backward ++ * (7ff -> 000 -> 800) and forward (7ff -> fff -> 800), it is simplest to just ++ * ignore register values with all ones or zeros in the low bits. ++ */ ++static u64 notrace sun50i_a64_read_cntpct_el0(void) ++{ ++ u64 val; ++ ++ do { ++ val = read_sysreg(cntpct_el0); ++ } while (((val + 1) & GENMASK(10, 0)) <= 1); ++ ++ return val; ++} ++ ++static u64 notrace sun50i_a64_read_cntvct_el0(void) ++{ ++ u64 val; ++ ++ do { ++ val = read_sysreg(cntvct_el0); ++ } while (((val + 1) & GENMASK(10, 0)) <= 1); ++ ++ return val; ++} ++#endif ++ + #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND + DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); + EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); +@@ -408,6 +438,15 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { + .read_cntvct_el0 = arm64_858921_read_cntvct_el0, + }, + #endif ++#ifdef CONFIG_SUN50I_A64_UNSTABLE_TIMER ++ { ++ .match_type = ate_match_dt, ++ .id = "allwinner,sun50i-a64-unstable-timer", ++ .desc = "Allwinner A64 timer instability", ++ .read_cntpct_el0 = sun50i_a64_read_cntpct_el0, ++ .read_cntvct_el0 = sun50i_a64_read_cntvct_el0, ++ }, ++#endif + }; + + typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0082-arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch b/patch/kernel/sunxi-dev/0082-arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch new file mode 100644 index 000000000..f87b1419d --- /dev/null +++ b/patch/kernel/sunxi-dev/0082-arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch @@ -0,0 +1,30 @@ +From a740ecc40aa9df18fbfb12925c1b7600c043a3cd Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Thu, 10 May 2018 21:27:51 -0500 +Subject: [PATCH 082/146] arm64: dts: allwinner: a64: Enable A64 timer + workaround + +As instability in the architectural timer has been observed on multiple +devices using this SoC, inluding the Pine64 and the Orange Pi Win, +enable the workaround in the SoC's device tree. + +Signed-off-by: Samuel Holland +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 62b880f68d6a..73f7e69755f8 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -281,6 +281,7 @@ + + timer { + compatible = "arm,armv8-timer"; ++ allwinner,sun50i-a64-unstable-timer; + interrupts = , + +Date: Thu, 9 Aug 2018 18:52:13 +0200 +Subject: [PATCH 083/146] clk: sunxi-ng: Add maximum rate constraint to NM PLLs + +On some NM PLLs, frequency can be set above PLL working range. + +Add a constraint for maximum supported rate. This way, drivers can +specify which is maximum allowed rate for PLL. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Maxime Ripard +--- + drivers/clk/sunxi-ng/ccu_nm.c | 7 +++++++ + drivers/clk/sunxi-ng/ccu_nm.h | 30 ++++++++++++++++++++++++++++++ + 2 files changed, 37 insertions(+) + diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c index 4e2073307f34..6fe3c14f7b2d 100644 --- a/drivers/clk/sunxi-ng/ccu_nm.c @@ -64,3 +81,6 @@ index 1d8b459c50b7..de232f2199a6 100644 #define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \ _nshift, _nwidth, \ _mshift, _mwidth, \ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/board-a83t-2-5-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-video.patch b/patch/kernel/sunxi-dev/0084-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-v.patch similarity index 57% rename from patch/kernel/sunxi-dev/board-a83t-2-5-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-video.patch rename to patch/kernel/sunxi-dev/0084-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-v.patch index 686fcda44..e872e4727 100644 --- a/patch/kernel/sunxi-dev/board-a83t-2-5-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-video.patch +++ b/patch/kernel/sunxi-dev/0084-clk-sunxi-ng-h3-h5-Add-max.-rate-constraint-to-pll-v.patch @@ -1,3 +1,27 @@ +From 461aa98f7ee6d5347625728949d51122ee92999b Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Thu, 9 Aug 2018 18:52:14 +0200 +Subject: [PATCH 084/146] clk: sunxi-ng: h3/h5: Add max. rate constraint to + pll-video + +As it turns out, pll-video can be set to higher rate that it is really +supported by HW. + +For example, one monitor requested 185.58 MHz pixel clock. Clock +framework calculated that minimum rate error would be when pll-video +is set to 2040 MHz. This is clearly out of specs. + +Both H3 and H5 user manuals specify 600 MHz as maximum supported rate. +However, BSP clock drivers allow up to 912 MHz and 1008 MHz +respectively. Here 912 MHz is chosen because user manuals were already +proven wrong once for lower limits. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Maxime Ripard +--- + drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 77ed0b0ba681..eb5c608428fa 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -34,3 +58,6 @@ index 77ed0b0ba681..eb5c608428fa 100644 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", "osc24M", 0x0018, +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0085-clk-sunxi-ng-Adjust-MP-clock-parent-rate-when-allowe.patch b/patch/kernel/sunxi-dev/0085-clk-sunxi-ng-Adjust-MP-clock-parent-rate-when-allowe.patch new file mode 100644 index 000000000..f5ba597e5 --- /dev/null +++ b/patch/kernel/sunxi-dev/0085-clk-sunxi-ng-Adjust-MP-clock-parent-rate-when-allowe.patch @@ -0,0 +1,107 @@ +From b0019c82e8ffbce13b5a98eb4fa16b966809c04a Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 7 Oct 2018 11:38:38 +0200 +Subject: [PATCH 085/146] clk: sunxi-ng: Adjust MP clock parent rate when + allowed + +Currently MP clocks don't consider adjusting parent rate even if they +are allowed to do so. Such behaviour considerably lowers amount of +possible rates, which is very inconvenient when such clock is used for +pixel clock, for example. + +In order to improve the situation, adjusting parent rate is considered +when allowed. + +This code is inspired by clk_divider_bestdiv() function, which does +basically the same thing for different clock type. + +Signed-off-by: Jernej Skrabec +--- + drivers/clk/sunxi-ng/ccu_mp.c | 64 +++++++++++++++++++++++++++++++++-- + 1 file changed, 62 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c +index 5d0af4051737..0357349eb767 100644 +--- a/drivers/clk/sunxi-ng/ccu_mp.c ++++ b/drivers/clk/sunxi-ng/ccu_mp.c +@@ -40,6 +40,61 @@ static void ccu_mp_find_best(unsigned long parent, unsigned long rate, + *p = best_p; + } + ++static unsigned long ccu_mp_find_best_with_parent_adj(struct clk_hw *hw, ++ unsigned long *parent, ++ unsigned long rate, ++ unsigned int max_m, ++ unsigned int max_p) ++{ ++ unsigned long parent_rate_saved; ++ unsigned long parent_rate, now; ++ unsigned long best_rate = 0; ++ unsigned int _m, _p, div; ++ unsigned long maxdiv; ++ ++ parent_rate_saved = *parent; ++ ++ /* ++ * The maximum divider we can use without overflowing ++ * unsigned long in rate * m * p below ++ */ ++ maxdiv = max_m * max_p; ++ maxdiv = min(ULONG_MAX / rate, maxdiv); ++ ++ for (_p = 1; _p <= max_p; _p <<= 1) { ++ for (_m = 1; _m <= max_m; _m++) { ++ div = _m * _p; ++ ++ if (div > maxdiv) ++ break; ++ ++ if (rate * div == parent_rate_saved) { ++ /* ++ * It's the most ideal case if the requested ++ * rate can be divided from parent clock without ++ * needing to change parent rate, so return the ++ * divider immediately. ++ */ ++ *parent = parent_rate_saved; ++ return rate; ++ } ++ ++ parent_rate = clk_hw_round_rate(hw, rate * div); ++ now = parent_rate / div; ++ ++ if (now <= rate && now > best_rate) { ++ best_rate = now; ++ *parent = parent_rate; ++ ++ if (now == rate) ++ return rate; ++ } ++ } ++ } ++ ++ return best_rate; ++} ++ + static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux, + struct clk_hw *hw, + unsigned long *parent_rate, +@@ -56,8 +111,13 @@ static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux, + max_m = cmp->m.max ?: 1 << cmp->m.width; + max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1); + +- ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p); +- rate = *parent_rate / p / m; ++ if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { ++ ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p); ++ rate = *parent_rate / p / m; ++ } else { ++ rate = ccu_mp_find_best_with_parent_adj(hw, parent_rate, rate, ++ max_m, max_p); ++ } + + if (cmp->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate /= cmp->fixed_post_div; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0086-clk-sunxi-ng-Use-u64-for-calculation-of-NM-rate.patch b/patch/kernel/sunxi-dev/0086-clk-sunxi-ng-Use-u64-for-calculation-of-NM-rate.patch new file mode 100644 index 000000000..644c91db9 --- /dev/null +++ b/patch/kernel/sunxi-dev/0086-clk-sunxi-ng-Use-u64-for-calculation-of-NM-rate.patch @@ -0,0 +1,74 @@ +From 96d78cd2590710fc7e08a4445349a0b4a21df04a Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sun, 7 Oct 2018 11:38:39 +0200 +Subject: [PATCH 086/146] clk: sunxi-ng: Use u64 for calculation of NM rate + +Allwinner H6 SoC has multiplier N range between 1 and 254. Since parent +rate is 24MHz, intermediate result when calculating final rate easily +overflows 32 bit variable. + +Because of that, introduce function for calculating clock rate which +uses 64 bit variable for intermediate result. + +Fixes: 6174a1e24b0d ("clk: sunxi-ng: Add N-M-factor clock support") +Fixes: ee28648cb2b4 ("clk: sunxi-ng: Remove the use of rational computations") + +CC: +Signed-off-by: Jernej Skrabec +--- + drivers/clk/sunxi-ng/ccu_nm.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c +index 6fe3c14f7b2d..424d8635b053 100644 +--- a/drivers/clk/sunxi-ng/ccu_nm.c ++++ b/drivers/clk/sunxi-ng/ccu_nm.c +@@ -19,6 +19,17 @@ struct _ccu_nm { + unsigned long m, min_m, max_m; + }; + ++static unsigned long ccu_nm_calc_rate(unsigned long parent, ++ unsigned long n, unsigned long m) ++{ ++ u64 rate = parent; ++ ++ rate *= n; ++ do_div(rate, m); ++ ++ return rate; ++} ++ + static void ccu_nm_find_best(unsigned long parent, unsigned long rate, + struct _ccu_nm *nm) + { +@@ -28,7 +39,8 @@ static void ccu_nm_find_best(unsigned long parent, unsigned long rate, + + for (_n = nm->min_n; _n <= nm->max_n; _n++) { + for (_m = nm->min_m; _m <= nm->max_m; _m++) { +- unsigned long tmp_rate = parent * _n / _m; ++ unsigned long tmp_rate = ccu_nm_calc_rate(parent, ++ _n, _m); + + if (tmp_rate > rate) + continue; +@@ -100,7 +112,7 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw, + if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm)) + rate = ccu_sdm_helper_read_rate(&nm->common, &nm->sdm, m, n); + else +- rate = parent_rate * n / m; ++ rate = ccu_nm_calc_rate(parent_rate, n, m); + + if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate /= nm->fixed_post_div; +@@ -149,7 +161,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, + _nm.max_m = nm->m.max ?: 1 << nm->m.width; + + ccu_nm_find_best(*parent_rate, rate, &_nm); +- rate = *parent_rate * _nm.n / _nm.m; ++ rate = ccu_nm_calc_rate(*parent_rate, _nm.n, _nm.m); + + if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV) + rate /= nm->fixed_post_div; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0087-drm-sun4i-tcon-Pass-drm_encoder-into-sun4i_tcon0_mod.patch b/patch/kernel/sunxi-dev/0087-drm-sun4i-tcon-Pass-drm_encoder-into-sun4i_tcon0_mod.patch new file mode 100644 index 000000000..6e9d0fbf5 --- /dev/null +++ b/patch/kernel/sunxi-dev/0087-drm-sun4i-tcon-Pass-drm_encoder-into-sun4i_tcon0_mod.patch @@ -0,0 +1,66 @@ +From af6d185a66b416cb714fb3f1602e8e3f5ca46632 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 7 Sep 2018 12:19:43 +0800 +Subject: [PATCH 087/146] drm/sun4i: tcon: Pass drm_encoder * into + sun4i_tcon0_mode_set_cpu + +sun4i_tcon0_mode_set_cpu() currently accepts struct mipi_dsi_device * +as its second parameter. This is derived from drm_encoder. + +The DSI encoder is tied to the CPU interface mode of the TCON as a +special case. In theory, if hardware were available, we could also +support normal CPU interface modes. It is better to pass the generic +encoder instead of the specialized mipi_dsi_device, and handle the +differences inside the function. + +Passing the encoder would also enable the function to pass it, or any +other data structures related to it, to other functions expecting it. +One such example would be dithering support that will be added in a +later patch, which looks at properties tied to the connector to +determine whether dithering should be enabled or not. + +Signed-off-by: Chen-Yu Tsai +--- + drivers/gpu/drm/sun4i/sun4i_tcon.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c +index 3fb084f802e2..52e1150612ba 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c +@@ -276,9 +276,12 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon, + } + + static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon, +- struct mipi_dsi_device *device, ++ const struct drm_encoder *encoder, + const struct drm_display_mode *mode) + { ++ /* TODO support normal CPU interface modes */ ++ struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder); ++ struct mipi_dsi_device *device = dsi->device; + u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format); + u8 lanes = device->lanes; + u32 block_space, start_delay; +@@ -581,16 +584,10 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon, + const struct drm_encoder *encoder, + const struct drm_display_mode *mode) + { +- struct sun6i_dsi *dsi; +- + switch (encoder->encoder_type) { + case DRM_MODE_ENCODER_DSI: +- /* +- * This is not really elegant, but it's the "cleaner" +- * way I could think of... +- */ +- dsi = encoder_to_sun6i_dsi(encoder); +- sun4i_tcon0_mode_set_cpu(tcon, dsi->device, mode); ++ /* DSI is tied to special case of CPU interface */ ++ sun4i_tcon0_mode_set_cpu(tcon, encoder, mode); + break; + case DRM_MODE_ENCODER_LVDS: + sun4i_tcon0_mode_set_lvds(tcon, encoder, mode); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0088-drm-sun4i-tcon-Rename-Dithering-related-register-mac.patch b/patch/kernel/sunxi-dev/0088-drm-sun4i-tcon-Rename-Dithering-related-register-mac.patch new file mode 100644 index 000000000..3332362bc --- /dev/null +++ b/patch/kernel/sunxi-dev/0088-drm-sun4i-tcon-Rename-Dithering-related-register-mac.patch @@ -0,0 +1,59 @@ +From cf81b437511bf56512273c773013c40b11a01520 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 7 Sep 2018 12:19:44 +0800 +Subject: [PATCH 088/146] drm/sun4i: tcon: Rename Dithering related register + macros + +Dithering is only supported for TCON channel 0. Throughout the datasheet +all the names associated with these register are prefixed "TCON0", +instead of "TCON". The only exception is the control register +"TCON_FRM_CTL_REG". + +Rename the macros to reflect this. + +Signed-off-by: Chen-Yu Tsai +--- + drivers/gpu/drm/sun4i/sun4i_tcon.h | 27 +++++++++++++++------------ + 1 file changed, 15 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h +index f6a071cd5a6f..3d492c8be1fc 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h +@@ -37,18 +37,21 @@ + #define SUN4I_TCON_GINT1_REG 0x8 + + #define SUN4I_TCON_FRM_CTL_REG 0x10 +-#define SUN4I_TCON_FRM_CTL_EN BIT(31) +- +-#define SUN4I_TCON_FRM_SEED_PR_REG 0x14 +-#define SUN4I_TCON_FRM_SEED_PG_REG 0x18 +-#define SUN4I_TCON_FRM_SEED_PB_REG 0x1c +-#define SUN4I_TCON_FRM_SEED_LR_REG 0x20 +-#define SUN4I_TCON_FRM_SEED_LG_REG 0x24 +-#define SUN4I_TCON_FRM_SEED_LB_REG 0x28 +-#define SUN4I_TCON_FRM_TBL0_REG 0x2c +-#define SUN4I_TCON_FRM_TBL1_REG 0x30 +-#define SUN4I_TCON_FRM_TBL2_REG 0x34 +-#define SUN4I_TCON_FRM_TBL3_REG 0x38 ++#define SUN4I_TCON0_FRM_CTL_EN BIT(31) ++#define SUN4I_TCON0_FRM_CTL_MODE_R BIT(6) ++#define SUN4I_TCON0_FRM_CTL_MODE_G BIT(5) ++#define SUN4I_TCON0_FRM_CTL_MODE_B BIT(4) ++ ++#define SUN4I_TCON0_FRM_SEED_PR_REG 0x14 ++#define SUN4I_TCON0_FRM_SEED_PG_REG 0x18 ++#define SUN4I_TCON0_FRM_SEED_PB_REG 0x1c ++#define SUN4I_TCON0_FRM_SEED_LR_REG 0x20 ++#define SUN4I_TCON0_FRM_SEED_LG_REG 0x24 ++#define SUN4I_TCON0_FRM_SEED_LB_REG 0x28 ++#define SUN4I_TCON0_FRM_TBL0_REG 0x2c ++#define SUN4I_TCON0_FRM_TBL1_REG 0x30 ++#define SUN4I_TCON0_FRM_TBL2_REG 0x34 ++#define SUN4I_TCON0_FRM_TBL3_REG 0x38 + + #define SUN4I_TCON0_CTL_REG 0x40 + #define SUN4I_TCON0_CTL_TCON_ENABLE BIT(31) +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0089-drm-sun4i-tcon-Add-dithering-support-for-RGB565-RGB6.patch b/patch/kernel/sunxi-dev/0089-drm-sun4i-tcon-Add-dithering-support-for-RGB565-RGB6.patch new file mode 100644 index 000000000..bff716f43 --- /dev/null +++ b/patch/kernel/sunxi-dev/0089-drm-sun4i-tcon-Add-dithering-support-for-RGB565-RGB6.patch @@ -0,0 +1,132 @@ +From 559d035001097a7ce6018117866e8f573fb15211 Mon Sep 17 00:00:00 2001 +From: Jonathan Liu +Date: Fri, 7 Sep 2018 12:19:45 +0800 +Subject: [PATCH 089/146] drm/sun4i: tcon: Add dithering support for + RGB565/RGB666 LCD panels + +The hardware supports dithering on TCON channel 0 which is used for LCD +panels. + +Dithering is a method of approximating a color from a mixture of other +colors when the required color isn't available. It reduces color +banding artifacts that can be observed when displaying gradients +(e.g. grayscale gradients). This may occur when the image that needs +to be displayed is 24-bit but the LCD panel is a lower bit depth and +does not perform dithering on its own. + +Signed-off-by: Jonathan Liu +[wens@csie.org: check display_info.bpc first; handle LVDS and MIPI DSI] +Signed-off-by: Chen-Yu Tsai +--- + drivers/gpu/drm/sun4i/sun4i_tcon.c | 62 ++++++++++++++++++++++++++++++ + 1 file changed, 62 insertions(+) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c +index 52e1150612ba..0d438f633b5d 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c +@@ -12,11 +12,13 @@ + + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + + #include + +@@ -275,6 +277,57 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon, + SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); + } + ++static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon, ++ const struct drm_connector *connector) ++{ ++ u32 bus_format = 0; ++ u32 val = 0; ++ ++ /* XXX Would this ever happen? */ ++ if (!connector) ++ return; ++ ++ /* ++ * FIXME: Undocumented bits ++ * ++ * The whole dithering process and these parameters are not ++ * explained in the vendor documents or BSP kernel code. ++ */ ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PR_REG, 0x11111111); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PG_REG, 0x11111111); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PB_REG, 0x11111111); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LR_REG, 0x11111111); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LG_REG, 0x11111111); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LB_REG, 0x11111111); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL0_REG, 0x01010000); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL1_REG, 0x15151111); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL2_REG, 0x57575555); ++ regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL3_REG, 0x7f7f7777); ++ ++ /* Do dithering if panel only supports 6 bits per color */ ++ if (connector->display_info.bpc == 6) ++ val |= SUN4I_TCON0_FRM_CTL_EN; ++ ++ if (connector->display_info.num_bus_formats == 1) ++ bus_format = connector->display_info.bus_formats[0]; ++ ++ /* Check the connection format */ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB565_1X16: ++ /* R and B components are only 5 bits deep */ ++ val |= SUN4I_TCON0_FRM_CTL_MODE_R; ++ val |= SUN4I_TCON0_FRM_CTL_MODE_B; ++ case MEDIA_BUS_FMT_RGB666_1X18: ++ case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: ++ /* Fall through: enable dithering */ ++ val |= SUN4I_TCON0_FRM_CTL_EN; ++ break; ++ } ++ ++ /* Write dithering settings */ ++ regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val); ++} ++ + static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon, + const struct drm_encoder *encoder, + const struct drm_display_mode *mode) +@@ -292,6 +345,9 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon, + + sun4i_tcon0_mode_set_common(tcon, mode); + ++ /* Set dithering if needed */ ++ sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder)); ++ + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, + SUN4I_TCON0_CTL_IF_MASK, + SUN4I_TCON0_CTL_IF_8080); +@@ -357,6 +413,9 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, + tcon->dclk_max_div = 7; + sun4i_tcon0_mode_set_common(tcon, mode); + ++ /* Set dithering if needed */ ++ sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder)); ++ + /* Adjust clock delay */ + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, +@@ -430,6 +489,9 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, + tcon->dclk_max_div = 127; + sun4i_tcon0_mode_set_common(tcon, mode); + ++ /* Set dithering if needed */ ++ sun4i_tcon0_mode_set_dithering(tcon, tcon->panel->connector); ++ + /* Adjust clock delay */ + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0090-drm-sun4i-tcon-prevent-tcon-panel-dereference-if-nul.patch b/patch/kernel/sunxi-dev/0090-drm-sun4i-tcon-prevent-tcon-panel-dereference-if-nul.patch new file mode 100644 index 000000000..a35a7f57b --- /dev/null +++ b/patch/kernel/sunxi-dev/0090-drm-sun4i-tcon-prevent-tcon-panel-dereference-if-nul.patch @@ -0,0 +1,34 @@ +From 99b4088bcefec2a055c1d7caa1f135168405ccf1 Mon Sep 17 00:00:00 2001 +From: Giulio Benetti +Date: Tue, 2 Oct 2018 23:59:17 +0200 +Subject: [PATCH 090/146] drm/sun4i: tcon: prevent tcon->panel dereference if + null + +If using tcon with VGA, tcon->panel will be null(0), this will cause +segmentation fault when trying to dereference tcon->panel->connector. + +Add tcon->panel null check before calling +sun4i_tcon0_mode_set_dithering(). + +Signed-off-by: Giulio Benetti +--- + drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c +index 0d438f633b5d..1b28fd9c2908 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c +@@ -490,7 +490,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, + sun4i_tcon0_mode_set_common(tcon, mode); + + /* Set dithering if needed */ +- sun4i_tcon0_mode_set_dithering(tcon, tcon->panel->connector); ++ if (tcon->panel) ++ sun4i_tcon0_mode_set_dithering(tcon, tcon->panel->connector); + + /* Adjust clock delay */ + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0091-clk-sunxi-ng-a64-Add-minimal-rate-for-video-PLLs.patch b/patch/kernel/sunxi-dev/0091-clk-sunxi-ng-a64-Add-minimal-rate-for-video-PLLs.patch new file mode 100644 index 000000000..b55b2b501 --- /dev/null +++ b/patch/kernel/sunxi-dev/0091-clk-sunxi-ng-a64-Add-minimal-rate-for-video-PLLs.patch @@ -0,0 +1,84 @@ +From 8a348934a01914c7e6ada897d7ba121209961032 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:43 +0800 +Subject: [PATCH 091/146] clk: sunxi-ng: a64: Add minimal rate for video PLLs + +According to documentation and experience with other similar SoCs, video +PLLs don't work stable if their output frequency is set below 192 MHz. + +Because of that, set minimal rate to both A64 video PLLs to 192 MHz. + +Signed-off-by: Jagan Teki +Signed-off-by: Icenowy Zheng +Reviewed-by: Jernej Skrabec +--- + drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 46 ++++++++++++++------------- + 1 file changed, 24 insertions(+), 22 deletions(-) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +index 7c645f2c017a..40a7b5fd091c 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +@@ -64,17 +64,18 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", +- "osc24M", 0x010, +- 8, 7, /* N */ +- 0, 4, /* M */ +- BIT(24), /* frac enable */ +- BIT(25), /* frac select */ +- 270000000, /* frac rate 0 */ +- 297000000, /* frac rate 1 */ +- BIT(31), /* gate */ +- BIT(28), /* lock */ +- CLK_SET_RATE_UNGATE); ++static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0", ++ "osc24M", 0x010, ++ 192000000, /* Minimum rate */ ++ 8, 7, /* N */ ++ 0, 4, /* M */ ++ BIT(24), /* frac enable */ ++ BIT(25), /* frac select */ ++ 270000000, /* frac rate 0 */ ++ 297000000, /* frac rate 1 */ ++ BIT(31), /* gate */ ++ BIT(28), /* lock */ ++ CLK_SET_RATE_UNGATE); + + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", + "osc24M", 0x018, +@@ -125,17 +126,18 @@ static struct ccu_nk pll_periph1_clk = { + }, + }; + +-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", +- "osc24M", 0x030, +- 8, 7, /* N */ +- 0, 4, /* M */ +- BIT(24), /* frac enable */ +- BIT(25), /* frac select */ +- 270000000, /* frac rate 0 */ +- 297000000, /* frac rate 1 */ +- BIT(31), /* gate */ +- BIT(28), /* lock */ +- CLK_SET_RATE_UNGATE); ++static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1", ++ "osc24M", 0x030, ++ 192000000, /* Minimum rate */ ++ 8, 7, /* N */ ++ 0, 4, /* M */ ++ BIT(24), /* frac enable */ ++ BIT(25), /* frac select */ ++ 270000000, /* frac rate 0 */ ++ 297000000, /* frac rate 1 */ ++ BIT(31), /* gate */ ++ BIT(28), /* lock */ ++ CLK_SET_RATE_UNGATE); + + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", + "osc24M", 0x038, +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0092-clk-sunxi-ng-a64-Add-max.-rate-constraint-to-video-P.patch b/patch/kernel/sunxi-dev/0092-clk-sunxi-ng-a64-Add-max.-rate-constraint-to-video-P.patch new file mode 100644 index 000000000..c15f791b6 --- /dev/null +++ b/patch/kernel/sunxi-dev/0092-clk-sunxi-ng-a64-Add-max.-rate-constraint-to-video-P.patch @@ -0,0 +1,90 @@ +From 99ce6e04231a5a185c1cc7d8d2bd9484c8eabc56 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Tue, 4 Sep 2018 12:40:44 +0800 +Subject: [PATCH 092/146] clk: sunxi-ng: a64: Add max. rate constraint to video + PLLs + +Video PLLs on A64 can be set to higher rate that it is actually +supported by HW. + +Limit maximum rate to 1008 MHz. This is the maximum allowed rate by BSP +clock driver. Interestengly, user manual specifies maximum frequency to +be 600 MHz. Historically, this data was wrong in some user manuals for +other SoCs, so more faith is put in BSP clock driver. + +Signed-off-by: Icenowy Zheng +--- + drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 50 ++++++++++++++------------- + 1 file changed, 26 insertions(+), 24 deletions(-) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +index 40a7b5fd091c..90ffee824c33 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +@@ -64,18 +64,19 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0", +- "osc24M", 0x010, +- 192000000, /* Minimum rate */ +- 8, 7, /* N */ +- 0, 4, /* M */ +- BIT(24), /* frac enable */ +- BIT(25), /* frac select */ +- 270000000, /* frac rate 0 */ +- 297000000, /* frac rate 1 */ +- BIT(31), /* gate */ +- BIT(28), /* lock */ +- CLK_SET_RATE_UNGATE); ++static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0", ++ "osc24M", 0x010, ++ 192000000, /* Minimum rate */ ++ 1008000000, /* Maximum rate */ ++ 8, 7, /* N */ ++ 0, 4, /* M */ ++ BIT(24), /* frac enable */ ++ BIT(25), /* frac select */ ++ 270000000, /* frac rate 0 */ ++ 297000000, /* frac rate 1 */ ++ BIT(31), /* gate */ ++ BIT(28), /* lock */ ++ CLK_SET_RATE_UNGATE); + + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", + "osc24M", 0x018, +@@ -126,18 +127,19 @@ static struct ccu_nk pll_periph1_clk = { + }, + }; + +-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1", +- "osc24M", 0x030, +- 192000000, /* Minimum rate */ +- 8, 7, /* N */ +- 0, 4, /* M */ +- BIT(24), /* frac enable */ +- BIT(25), /* frac select */ +- 270000000, /* frac rate 0 */ +- 297000000, /* frac rate 1 */ +- BIT(31), /* gate */ +- BIT(28), /* lock */ +- CLK_SET_RATE_UNGATE); ++static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1", ++ "osc24M", 0x030, ++ 192000000, /* Minimum rate */ ++ 1008000000, /* Maximum rate */ ++ 8, 7, /* N */ ++ 0, 4, /* M */ ++ BIT(24), /* frac enable */ ++ BIT(25), /* frac select */ ++ 270000000, /* frac rate 0 */ ++ 297000000, /* frac rate 1 */ ++ BIT(31), /* gate */ ++ BIT(28), /* lock */ ++ CLK_SET_RATE_UNGATE); + + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", + "osc24M", 0x038, +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0093-dt-bindings-display-Add-compatible-for-A64-DE2-displ.patch b/patch/kernel/sunxi-dev/0093-dt-bindings-display-Add-compatible-for-A64-DE2-displ.patch new file mode 100644 index 000000000..5f607c3f5 --- /dev/null +++ b/patch/kernel/sunxi-dev/0093-dt-bindings-display-Add-compatible-for-A64-DE2-displ.patch @@ -0,0 +1,52 @@ +From 3c133c6aa20eacb1b7f77e6b3136d483fdd80582 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:45 +0800 +Subject: [PATCH 093/146] dt-bindings: display: Add compatible for A64 DE2 + display pipeline + +Allwinner A64 has a DE2 display pipeline. The TCONs are similar to the +ones in A83T, but the mixers are new (similar to the later R40 SoC). + +This patch adds dt-binding documentation for A64 DE2 display pipeline. + +Signed-off-by: Jagan Teki +Reviewed-by: Rob Herring +[Icenowy: Refactor and also cover TCON1] +Signed-off-by: Icenowy Zheng +--- + .../devicetree/bindings/display/sunxi/sun4i-drm.txt | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +index f8773ecb7525..7b79c5e3dffc 100644 +--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt ++++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +@@ -151,6 +151,8 @@ Required properties: + * allwinner,sun8i-v3s-tcon + * allwinner,sun9i-a80-tcon-lcd + * allwinner,sun9i-a80-tcon-tv ++ * "allwinner,sun50i-a64-tcon-lcd", "allwinner,sun8i-a83t-tcon-lcd" ++ * "allwinner,sun50i-a64-tcon-tv", "allwinner,sun8i-a83t-tcon-tv" + - reg: base address and size of memory-mapped region + - interrupts: interrupt associated to this IP + - clocks: phandles to the clocks feeding the TCON. +@@ -370,6 +372,8 @@ Required properties: + * allwinner,sun8i-a83t-de2-mixer-1 + * allwinner,sun8i-h3-de2-mixer-0 + * allwinner,sun8i-v3s-de2-mixer ++ * allwinner,sun50i-a64-de2-mixer-0 ++ * allwinner,sun50i-a64-de2-mixer-1 + - reg: base address and size of the memory-mapped region. + - clocks: phandles to the clocks feeding the mixer + * bus: the mixer interface clock +@@ -403,6 +407,7 @@ Required properties: + * allwinner,sun8i-r40-display-engine + * allwinner,sun8i-v3s-display-engine + * allwinner,sun9i-a80-display-engine ++ * allwinner,sun50i-a64-display-engine + + - allwinner,pipelines: list of phandle to the display engine + frontends (DE 1.0) or mixers (DE 2.0) available. +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0094-drm-sun4i-Add-support-for-A64-mixers.patch b/patch/kernel/sunxi-dev/0094-drm-sun4i-Add-support-for-A64-mixers.patch new file mode 100644 index 000000000..b13df124c --- /dev/null +++ b/patch/kernel/sunxi-dev/0094-drm-sun4i-Add-support-for-A64-mixers.patch @@ -0,0 +1,62 @@ +From 06cbcf31db7e0f3604f248e1731a0f316837cd64 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:46 +0800 +Subject: [PATCH 094/146] drm/sun4i: Add support for A64 mixers + +Mixers in Allwinner have similar capabilities as others SoCs with DE2. + +Add support for them. + +Signed-off-by: Jagan Teki +[Icenowy: Add mixer1] +Signed-off-by: Icenowy Zheng +Reviewed-by: Jernej Skrabec +--- + drivers/gpu/drm/sun4i/sun8i_mixer.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c +index cb65b0ed53fd..091f6cf40353 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c ++++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c +@@ -553,6 +553,22 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { + .mod_rate = 150000000, + }; + ++static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = { ++ .ccsc = 0, ++ .mod_rate = 297000000, ++ .scaler_mask = 0xf, ++ .ui_num = 3, ++ .vi_num = 1, ++}; ++ ++static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = { ++ .ccsc = 1, ++ .mod_rate = 297000000, ++ .scaler_mask = 0x3, ++ .ui_num = 1, ++ .vi_num = 1, ++}; ++ + static const struct of_device_id sun8i_mixer_of_table[] = { + { + .compatible = "allwinner,sun8i-a83t-de2-mixer-0", +@@ -570,6 +586,14 @@ static const struct of_device_id sun8i_mixer_of_table[] = { + .compatible = "allwinner,sun8i-v3s-de2-mixer", + .data = &sun8i_v3s_mixer_cfg, + }, ++ { ++ .compatible = "allwinner,sun50i-a64-de2-mixer-0", ++ .data = &sun50i_a64_mixer0_cfg, ++ }, ++ { ++ .compatible = "allwinner,sun50i-a64-de2-mixer-1", ++ .data = &sun50i_a64_mixer1_cfg, ++ }, + { } + }; + MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0095-drm-sun4i-Add-support-for-A64-display-engine.patch b/patch/kernel/sunxi-dev/0095-drm-sun4i-Add-support-for-A64-display-engine.patch new file mode 100644 index 000000000..99e0b6238 --- /dev/null +++ b/patch/kernel/sunxi-dev/0095-drm-sun4i-Add-support-for-A64-display-engine.patch @@ -0,0 +1,33 @@ +From dd3d2cbe3b5312585fd0c525d0515ef0493192fa Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:47 +0800 +Subject: [PATCH 095/146] drm/sun4i: Add support for A64 display engine + +Display Engine(DE2) in Allwinner A64 has two mixers and tcons. + +The routing for mixer0 is through tcon0 and connected to +LVDS/RGB/MIPI-DSI controller. + +The routing for mixer1 is through tcon1 and connected to HDMI. + +Signed-off-by: Jagan Teki +Signed-off-by: Icenowy Zheng +--- + drivers/gpu/drm/sun4i/sun4i_drv.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c +index 9f5de14fb2fe..486ae8507ae9 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_drv.c ++++ b/drivers/gpu/drm/sun4i/sun4i_drv.c +@@ -447,6 +447,7 @@ static const struct of_device_id sun4i_drv_of_table[] = { + { .compatible = "allwinner,sun8i-h3-display-engine" }, + { .compatible = "allwinner,sun8i-v3s-display-engine" }, + { .compatible = "allwinner,sun9i-a80-display-engine" }, ++ { .compatible = "allwinner,sun50i-a64-display-engine" }, + { } + }; + MODULE_DEVICE_TABLE(of, sun4i_drv_of_table); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0096-dt-bindings-display-Add-compatible-for-A64-HDMI.patch b/patch/kernel/sunxi-dev/0096-dt-bindings-display-Add-compatible-for-A64-HDMI.patch new file mode 100644 index 000000000..19ee6a52e --- /dev/null +++ b/patch/kernel/sunxi-dev/0096-dt-bindings-display-Add-compatible-for-A64-HDMI.patch @@ -0,0 +1,33 @@ +From 9985b7ab016e7dd192c717de1f0431e1e66212d9 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:48 +0800 +Subject: [PATCH 096/146] dt-bindings: display: Add compatible for A64 HDMI + +The HDMI controller on Allwinner A64 is similar on the one on +H3/H5/A83T (although the PHY is different with A83T). + +Add A64 compatible and append A83T compatible as fallback. + +Signed-off-by: Jagan Teki +Reviewed-by: Rob Herring +[Icenowy: refactor commit log] +Signed-off-by: Icenowy Zheng +--- + Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +index 7b79c5e3dffc..fdb8fb29033f 100644 +--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt ++++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +@@ -78,6 +78,7 @@ Required properties: + + - compatible: value must be one of: + * "allwinner,sun8i-a83t-dw-hdmi" ++ * "allwinner,sun50i-a64-dw-hdmi", "allwinner,sun8i-a83t-dw-hdmi" + - reg: base address and size of memory-mapped region + - reg-io-width: See dw_hdmi.txt. Shall be 1. + - interrupts: HDMI interrupt number +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0097-dt-bindings-clock-sun50i-a64-ccu-Add-PLL_VIDEO0-macr.patch b/patch/kernel/sunxi-dev/0097-dt-bindings-clock-sun50i-a64-ccu-Add-PLL_VIDEO0-macr.patch new file mode 100644 index 000000000..bf1ec2ae9 --- /dev/null +++ b/patch/kernel/sunxi-dev/0097-dt-bindings-clock-sun50i-a64-ccu-Add-PLL_VIDEO0-macr.patch @@ -0,0 +1,49 @@ +From b82507436dc7629f7a1e0ec8fffac4aa42e3c81d Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:49 +0800 +Subject: [PATCH 097/146] dt-bindings: clock: sun50i-a64-ccu: Add PLL_VIDEO0 + macro + +Allwinner A64 HDMI PHY clock has PLL_VIDEO0 as a parent. + +Include the macro on dt-bindings so-that the same can be used +while defining CCU clock phandles. + +Signed-off-by: Jagan Teki +Reviewed-by: Rob Herring +Signed-off-by: Icenowy Zheng +--- + drivers/clk/sunxi-ng/ccu-sun50i-a64.h | 4 +++- + include/dt-bindings/clock/sun50i-a64-ccu.h | 1 + + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h +index 91f79512cee4..704f038a8496 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.h ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h +@@ -27,7 +27,9 @@ + #define CLK_PLL_AUDIO_2X 4 + #define CLK_PLL_AUDIO_4X 5 + #define CLK_PLL_AUDIO_8X 6 +-#define CLK_PLL_VIDEO0 7 ++ ++/* PLL_VIDEO0 exported for HDMI PHY */ ++ + #define CLK_PLL_VIDEO0_2X 8 + #define CLK_PLL_VE 9 + #define CLK_PLL_DDR0 10 +diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h +index d7f42dd22663..e512a1c9b0fc 100644 +--- a/include/dt-bindings/clock/sun50i-a64-ccu.h ++++ b/include/dt-bindings/clock/sun50i-a64-ccu.h +@@ -43,6 +43,7 @@ + #ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_ + #define _DT_BINDINGS_CLK_SUN50I_A64_H_ + ++#define CLK_PLL_VIDEO0 7 + #define CLK_PLL_PERIPH0 11 + + #define CLK_CPUX 21 +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0098-arm64-dts-allwinner-a64-Add-display-pipeline.patch b/patch/kernel/sunxi-dev/0098-arm64-dts-allwinner-a64-Add-display-pipeline.patch new file mode 100644 index 000000000..a70ec6448 --- /dev/null +++ b/patch/kernel/sunxi-dev/0098-arm64-dts-allwinner-a64-Add-display-pipeline.patch @@ -0,0 +1,221 @@ +From 38727062e2758832418fbf250f327e5e916f877e Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:50 +0800 +Subject: [PATCH 098/146] arm64: dts: allwinner: a64: Add display pipeline + +Allwinner A64 have a display pipeline with 2 mixers/TCONs, the first +TCON is connected to LCD and the second is to HDMI. + +The HDMI controller/PHY pair is similar to the one on H3/H5. + +Add all required device tree nodes of the display pipeline, including +the TCON0 LCD one and the TCON1 HDMI one. + +Signed-off-by: Jagan Teki +[Icenowy: refactor commit message and add 1st pipeline] +Signed-off-by: Icenowy Zheng +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 166 ++++++++++++++++++ + 1 file changed, 166 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 73f7e69755f8..132da408aa52 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -166,6 +166,13 @@ + }; + }; + ++ de: display-engine { ++ compatible = "allwinner,sun50i-a64-display-engine"; ++ allwinner,pipelines = <&mixer0>, ++ <&mixer1>; ++ status = "disabled"; ++ }; ++ + osc24M: osc24M_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; +@@ -317,6 +324,52 @@ + #clock-cells = <1>; + #reset-cells = <1>; + }; ++ ++ mixer0: mixer@100000 { ++ compatible = "allwinner,sun50i-a64-de2-mixer-0"; ++ reg = <0x100000 0x100000>; ++ clocks = <&display_clocks CLK_BUS_MIXER0>, ++ <&display_clocks CLK_MIXER0>; ++ clock-names = "bus", ++ "mod"; ++ resets = <&display_clocks RST_MIXER0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mixer0_out: port@1 { ++ reg = <1>; ++ ++ mixer0_out_tcon0: endpoint { ++ remote-endpoint = <&tcon0_in_mixer0>; ++ }; ++ }; ++ }; ++ }; ++ ++ mixer1: mixer@200000 { ++ compatible = "allwinner,sun50i-a64-de2-mixer-1"; ++ reg = <0x200000 0x100000>; ++ clocks = <&display_clocks CLK_BUS_MIXER1>, ++ <&display_clocks CLK_MIXER1>; ++ clock-names = "bus", ++ "mod"; ++ resets = <&display_clocks RST_MIXER1>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mixer1_out: port@1 { ++ reg = <1>; ++ ++ mixer1_out_tcon1: endpoint { ++ remote-endpoint = <&tcon1_in_mixer1>; ++ }; ++ }; ++ }; ++ }; + }; + + syscon: syscon@1c00000 { +@@ -351,6 +404,75 @@ + #dma-cells = <1>; + }; + ++ tcon0: lcd-controller@1c0c000 { ++ compatible = "allwinner,sun50i-a64-tcon-lcd", ++ "allwinner,sun8i-a83t-tcon-lcd"; ++ reg = <0x01c0c000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>; ++ clock-names = "ahb", "tcon-ch0"; ++ clock-output-names = "tcon-pixel-clock"; ++ resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>; ++ reset-names = "lcd", "lvds"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ tcon0_in: port@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ tcon0_in_mixer0: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&mixer0_out_tcon0>; ++ }; ++ }; ++ ++ tcon0_out: port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ }; ++ }; ++ }; ++ ++ tcon1: lcd-controller@1c0d000 { ++ compatible = "allwinner,sun50i-a64-tcon-tv", ++ "allwinner,sun8i-a83t-tcon-tv"; ++ reg = <0x01c0d000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_TCON1>, <&ccu CLK_TCON1>; ++ clock-names = "ahb", "tcon-ch1"; ++ resets = <&ccu RST_BUS_TCON1>; ++ reset-names = "lcd"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ tcon1_in: port@0 { ++ reg = <0>; ++ ++ tcon1_in_mixer1: endpoint { ++ remote-endpoint = <&mixer1_out_tcon1>; ++ }; ++ }; ++ ++ tcon1_out: port@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ tcon1_out_hdmi: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&hdmi_in_tcon1>; ++ }; ++ }; ++ }; ++ }; ++ + mmc0: mmc@1c0f000 { + compatible = "allwinner,sun50i-a64-mmc"; + reg = <0x01c0f000 0x1000>; +@@ -860,6 +982,50 @@ + status = "disabled"; + }; + ++ hdmi: hdmi@1ee0000 { ++ compatible = "allwinner,sun50i-a64-dw-hdmi", ++ "allwinner,sun8i-a83t-dw-hdmi"; ++ reg = <0x01ee0000 0x10000>; ++ reg-io-width = <1>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_DDC>, ++ <&ccu CLK_HDMI>; ++ clock-names = "iahb", "isfr", "tmds"; ++ resets = <&ccu RST_BUS_HDMI1>; ++ reset-names = "ctrl"; ++ phys = <&hdmi_phy>; ++ phy-names = "hdmi-phy"; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hdmi_in: port@0 { ++ reg = <0>; ++ ++ hdmi_in_tcon1: endpoint { ++ remote-endpoint = <&tcon1_out_hdmi>; ++ }; ++ }; ++ ++ hdmi_out: port@1 { ++ reg = <1>; ++ }; ++ }; ++ }; ++ ++ hdmi_phy: hdmi-phy@1ef0000 { ++ compatible = "allwinner,sun8i-h3-hdmi-phy"; ++ reg = <0x01ef0000 0x10000>; ++ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI_DDC>, ++ <&ccu 7>; ++ clock-names = "bus", "mod", "pll-0"; ++ resets = <&ccu RST_BUS_HDMI0>; ++ reset-names = "phy"; ++ #phy-cells = <0>; ++ }; ++ + sound_hdmi: sound_hdmi { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0099-dt-bindings-sun4i-drm-add-HDMI-VCC-supply-property-f.patch b/patch/kernel/sunxi-dev/0099-dt-bindings-sun4i-drm-add-HDMI-VCC-supply-property-f.patch new file mode 100644 index 000000000..a8e0639fd --- /dev/null +++ b/patch/kernel/sunxi-dev/0099-dt-bindings-sun4i-drm-add-HDMI-VCC-supply-property-f.patch @@ -0,0 +1,33 @@ +From d2deb88ff41a528b4c35f1f6e344e6a097eabedd Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Tue, 4 Sep 2018 12:40:51 +0800 +Subject: [PATCH 099/146] dt-bindings: sun4i-drm: add HDMI VCC supply property + for sun8i-dw-hdmi + +Allwiner SoCs with DesignWare HDMI controller all come with a "HVCC" +pin, which is the VCC of HDMI part. + +Add a supply property to specify HVCC's regulator in the device tree. + +Signed-off-by: Icenowy Zheng +--- + Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +index fdb8fb29033f..0bbb5d47f228 100644 +--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt ++++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +@@ -97,6 +97,9 @@ Required properties: + first port should be the input endpoint. The second should be the + output, usually to an HDMI connector. + ++Optional properties: ++ - hvcc-supply: the VCC power supply of the controller ++ + DWC HDMI PHY + ------------ + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0100-drm-sun4i-Add-support-for-HDMI-voltage-regulator.patch b/patch/kernel/sunxi-dev/0100-drm-sun4i-Add-support-for-HDMI-voltage-regulator.patch new file mode 100644 index 000000000..d5a343bb1 --- /dev/null +++ b/patch/kernel/sunxi-dev/0100-drm-sun4i-Add-support-for-HDMI-voltage-regulator.patch @@ -0,0 +1,87 @@ +From f50ad947fd638dc7dde8afb54db743dfc5db6177 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 4 Sep 2018 12:40:52 +0800 +Subject: [PATCH 100/146] drm/sun4i: Add support for HDMI voltage regulator + +Some boards have HDMI VCC pin connected to voltage regulator which may +not be turned on by default. + +Add support for such boards by adding voltage regulator handling code to +HDMI driver. + +Signed-off-by: Jernej Skrabec +[Icenowy: change supply name to "hvcc"] +Signed-off-by: Icenowy Zheng +--- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 17 ++++++++++++++++- + drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 ++ + 2 files changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +index 31875b636434..ed2983770e9c 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +@@ -125,10 +125,22 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + return PTR_ERR(hdmi->clk_tmds); + } + ++ hdmi->regulator = devm_regulator_get(dev, "hvcc"); ++ if (IS_ERR(hdmi->regulator)) { ++ dev_err(dev, "Couldn't get regulator\n"); ++ return PTR_ERR(hdmi->regulator); ++ } ++ ++ ret = regulator_enable(hdmi->regulator); ++ if (ret) { ++ dev_err(dev, "Failed to enable regulator\n"); ++ return ret; ++ } ++ + ret = reset_control_deassert(hdmi->rst_ctrl); + if (ret) { + dev_err(dev, "Could not deassert ctrl reset control\n"); +- return ret; ++ goto err_disable_regulator; + } + + ret = clk_prepare_enable(hdmi->clk_tmds); +@@ -183,6 +195,8 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, + clk_disable_unprepare(hdmi->clk_tmds); + err_assert_ctrl_reset: + reset_control_assert(hdmi->rst_ctrl); ++err_disable_regulator: ++ regulator_disable(hdmi->regulator); + + return ret; + } +@@ -196,6 +210,7 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master, + sun8i_hdmi_phy_remove(hdmi); + clk_disable_unprepare(hdmi->clk_tmds); + reset_control_assert(hdmi->rst_ctrl); ++ regulator_disable(hdmi->regulator); + } + + static const struct component_ops sun8i_dw_hdmi_ops = { +diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +index aadbe0a10b0c..7fdc1ecd2892 100644 +--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h ++++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + + #define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000 +@@ -176,6 +177,7 @@ struct sun8i_dw_hdmi { + struct drm_encoder encoder; + struct sun8i_hdmi_phy *phy; + struct dw_hdmi_plat_data plat_data; ++ struct regulator *regulator; + struct reset_control *rst_ctrl; + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0101-arm64-dts-allwinner-a64-Enable-HDMI-output-on-A64-bo.patch b/patch/kernel/sunxi-dev/0101-arm64-dts-allwinner-a64-Enable-HDMI-output-on-A64-bo.patch new file mode 100644 index 000000000..2b1729a59 --- /dev/null +++ b/patch/kernel/sunxi-dev/0101-arm64-dts-allwinner-a64-Enable-HDMI-output-on-A64-bo.patch @@ -0,0 +1,364 @@ +From e7623ac862573d231eea2ec77d393adbf2db3392 Mon Sep 17 00:00:00 2001 +From: Jagan Teki +Date: Tue, 4 Sep 2018 12:40:53 +0800 +Subject: [PATCH 101/146] arm64: dts: allwinner: a64: Enable HDMI output on A64 + boards w/ HDMI + +Enable all necessary device tree nodes and add connector node to device +trees for all supported A64 boards with HDMI. + +Signed-off-by: Jagan Teki +[Icenowy: squash all board patches altogether and change supply name] +Signed-off-by: Icenowy Zheng +Tested-by: Jagan Teki # BPI-M64, OPI-Win, +Tested-by: Vasily Khoruzhick +--- + .../dts/allwinner/sun50i-a64-bananapi-m64.dts | 26 ++++++++++++++++++ + .../dts/allwinner/sun50i-a64-nanopi-a64.dts | 27 +++++++++++++++++++ + .../dts/allwinner/sun50i-a64-olinuxino.dts | 26 ++++++++++++++++++ + .../dts/allwinner/sun50i-a64-orangepi-win.dts | 27 +++++++++++++++++++ + .../boot/dts/allwinner/sun50i-a64-pine64.dts | 27 +++++++++++++++++++ + .../dts/allwinner/sun50i-a64-pinebook.dts | 26 ++++++++++++++++++ + .../allwinner/sun50i-a64-sopine-baseboard.dts | 26 ++++++++++++++++++ + 7 files changed, 185 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts +index 094cfed13df9..c3cb0aa6ae83 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts +@@ -60,6 +60,17 @@ + stdout-path = "serial0:115200n8"; + }; + ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -86,6 +97,10 @@ + }; + }; + ++&de { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +@@ -103,6 +118,17 @@ + status = "okay"; + }; + ++&hdmi { ++ hvcc-supply = <®_dldo1>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts +index 98dbff19f5cc..f9fa87834b07 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts +@@ -57,6 +57,22 @@ + chosen { + stdout-path = "serial0:115200n8"; + }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ ++}; ++ ++&de { ++ status = "okay"; + }; + + &ehci0 { +@@ -67,6 +83,17 @@ + status = "okay"; + }; + ++&hdmi { ++ hvcc-supply = <®_dldo1>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + /* i2c1 connected with gpio headers like pine64, bananapi */ + &i2c1 { + pinctrl-names = "default"; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts +index 3f531393eaee..d1c713520ad5 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts +@@ -58,12 +58,38 @@ + stdout-path = "serial0:115200n8"; + }; + ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ + }; + }; + ++&de { ++ status = "okay"; ++}; ++ ++&hdmi { ++ hvcc-supply = <®_dldo1>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +index 1221764f5719..08d96ca9f4da 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +@@ -57,12 +57,39 @@ + chosen { + stdout-path = "serial0:115200n8"; + }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ ++}; ++ ++&de { ++ status = "okay"; + }; + + &ehci1 { + status = "okay"; + }; + ++&hdmi { ++ hvcc-supply = <®_dldo1>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +index cdf5169f2a1a..cd7e938db01a 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +@@ -63,6 +63,18 @@ + stdout-path = "serial0:115200n8"; + }; + ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ +@@ -73,6 +85,10 @@ + cpu-supply = <®_dcdc2>; + }; + ++&de { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +@@ -91,6 +107,17 @@ + + }; + ++&hdmi { ++ hvcc-supply = <®_dldo1>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +index b3698a8bb1d3..52cbb3052588 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +@@ -53,6 +53,17 @@ + }; + }; + ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; +@@ -70,6 +81,10 @@ + cpu-supply = <®_dcdc2>; + }; + ++&de { ++ status = "okay"; ++}; ++ + &ehci0 { + phys = <&usbphy 0>; + phy-names = "usb"; +@@ -80,6 +95,17 @@ + status = "okay"; + }; + ++&hdmi { ++ hvcc-supply = <®_dldo1>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +index abad307b414a..8e9191f489a6 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +@@ -61,6 +61,17 @@ + stdout-path = "serial0:115200n8"; + }; + ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ + reg_vcc1v8: vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8"; +@@ -73,6 +84,10 @@ + cpu-supply = <®_dcdc2>; + }; + ++&de { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +@@ -90,6 +105,17 @@ + status = "okay"; + }; + ++&hdmi { ++ hvcc-supply = <®_dldo1>; ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &i2s2 { + status = "okay"; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0102-dt-bindings-power-supply-axp20x-add-AXP813-AC-power-.patch b/patch/kernel/sunxi-dev/0102-dt-bindings-power-supply-axp20x-add-AXP813-AC-power-.patch new file mode 100644 index 000000000..a64a8fe58 --- /dev/null +++ b/patch/kernel/sunxi-dev/0102-dt-bindings-power-supply-axp20x-add-AXP813-AC-power-.patch @@ -0,0 +1,42 @@ +From 7e6f7bf5c8a482c2391a16d76a50aff7a47c8223 Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:20 +0300 +Subject: [PATCH 102/146] dt-bindings: power: supply: axp20x: add AXP813 AC + power DT binding + +The AXP803/AXP813 AC power supply can limit input current and voltage. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Rob Herring +Reviewed-by: Quentin Schulz +Reviewed-by: Chen-Yu Tsai +Reviewed-by: Sebastian Reichel +Tested-by: Vasily Khoruzhick +--- + .../devicetree/bindings/power/supply/axp20x_ac_power.txt | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt b/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt +index 826e8a879121..7a1fb532abe5 100644 +--- a/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt ++++ b/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt +@@ -4,6 +4,7 @@ Required Properties: + - compatible: One of: + "x-powers,axp202-ac-power-supply" + "x-powers,axp221-ac-power-supply" ++ "x-powers,axp813-ac-power-supply" + + This node is a subnode of the axp20x PMIC. + +@@ -13,6 +14,8 @@ reading ADC channels from the AXP20X ADC. + The AXP22X is only able to tell if an AC power supply is present and + usable. + ++AXP813/AXP803 are able to limit current and supply voltage ++ + Example: + + &axp209 { +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0103-dt-bindings-power-supply-axp20x-add-AXP803-power-bin.patch b/patch/kernel/sunxi-dev/0103-dt-bindings-power-supply-axp20x-add-AXP803-power-bin.patch new file mode 100644 index 000000000..043bb4c4c --- /dev/null +++ b/patch/kernel/sunxi-dev/0103-dt-bindings-power-supply-axp20x-add-AXP803-power-bin.patch @@ -0,0 +1,43 @@ +From 5b0f15a9da1cb6110bc2eded53bf18626626179c Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:21 +0300 +Subject: [PATCH 103/146] dt-bindings: power: supply: axp20x: add AXP803 power + bindings + +The AXP803 power supplies are compatible with AXP813, but +add specific compatibles for them. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Rob Herring +--- + .../devicetree/bindings/power/supply/axp20x_ac_power.txt | 1 + + .../devicetree/bindings/power/supply/axp20x_battery.txt | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt b/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt +index 7a1fb532abe5..acdeb4b8f4cc 100644 +--- a/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt ++++ b/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt +@@ -4,6 +4,7 @@ Required Properties: + - compatible: One of: + "x-powers,axp202-ac-power-supply" + "x-powers,axp221-ac-power-supply" ++ "x-powers,axp803-ac-power-supply" + "x-powers,axp813-ac-power-supply" + + This node is a subnode of the axp20x PMIC. +diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt +index 41916f69902c..780ebd7e3b84 100644 +--- a/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt ++++ b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt +@@ -4,6 +4,7 @@ Required Properties: + - compatible, one of: + "x-powers,axp209-battery-power-supply" + "x-powers,axp221-battery-power-supply" ++ "x-powers,axp803-battery-power-supply" + "x-powers,axp813-battery-power-supply" + + This node is a subnode of its respective PMIC DT node. +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0104-dt-bindings-gpio-gpio-axp209-add-AXP803-GPIO-binding.patch b/patch/kernel/sunxi-dev/0104-dt-bindings-gpio-gpio-axp209-add-AXP803-GPIO-binding.patch new file mode 100644 index 000000000..68153e05b --- /dev/null +++ b/patch/kernel/sunxi-dev/0104-dt-bindings-gpio-gpio-axp209-add-AXP803-GPIO-binding.patch @@ -0,0 +1,38 @@ +From 80694d54812c5fc49dd738e17a9cf5a91f343cae Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:22 +0300 +Subject: [PATCH 104/146] dt-bindings: gpio: gpio-axp209: add AXP803 GPIO + bindings + +The AXP803 GPIO is compatible with AXP813 GPIO, but add +specific compatible for it. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Rob Herring +--- + Documentation/devicetree/bindings/gpio/gpio-axp209.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/gpio/gpio-axp209.txt b/Documentation/devicetree/bindings/gpio/gpio-axp209.txt +index fc42b2caa06d..5337a21d7bcf 100644 +--- a/Documentation/devicetree/bindings/gpio/gpio-axp209.txt ++++ b/Documentation/devicetree/bindings/gpio/gpio-axp209.txt +@@ -11,6 +11,7 @@ This driver employs the per-pin muxing pattern. + Required properties: + - compatible: Should be one of: + - "x-powers,axp209-gpio" ++ - "x-powers,axp803-gpio" + - "x-powers,axp813-gpio" + - #gpio-cells: Should be two. The first cell is the pin number and the + second is the GPIO flags. +@@ -67,6 +68,7 @@ GPIO0 | gpio_in, gpio_out, ldo, adc + GPIO1 | gpio_in, gpio_out, ldo, adc + GPIO2 | gpio_in, gpio_out + ++axp803 + axp813 + ------ + GPIO | Functions +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0105-dt-bindings-iio-adc-add-AXP803-ADC-bindings.patch b/patch/kernel/sunxi-dev/0105-dt-bindings-iio-adc-add-AXP803-ADC-bindings.patch new file mode 100644 index 000000000..b8831c8eb --- /dev/null +++ b/patch/kernel/sunxi-dev/0105-dt-bindings-iio-adc-add-AXP803-ADC-bindings.patch @@ -0,0 +1,37 @@ +From fd2f21f1e63f52476bbbb0ce17fb6288a623f2ae Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:23 +0300 +Subject: [PATCH 105/146] dt-bindings: iio: adc: add AXP803 ADC bindings + +The AXP803 ADC is compatible with AXP813 ADC, but add +specific compatible for it. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Rob Herring +--- + Documentation/devicetree/bindings/iio/adc/axp20x_adc.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/iio/adc/axp20x_adc.txt b/Documentation/devicetree/bindings/iio/adc/axp20x_adc.txt +index 7a6313913923..1dbd5e480acd 100644 +--- a/Documentation/devicetree/bindings/iio/adc/axp20x_adc.txt ++++ b/Documentation/devicetree/bindings/iio/adc/axp20x_adc.txt +@@ -4,6 +4,7 @@ Required properties: + - compatible: should be one of: + - "x-powers,axp209-adc", + - "x-powers,axp221-adc", ++ - "x-powers,axp803-adc", + - "x-powers,axp813-adc", + - #io-channel-cells: should be 1, + +@@ -39,6 +40,7 @@ AXP22x + 2 | batt_chrg_i + 3 | batt_dischrg_i + ++AXP803 + AXP813 + ------ + 0 | pmic_temp +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0106-ARM-dts-axp81x-add-AC-power-supply-subnode.patch b/patch/kernel/sunxi-dev/0106-ARM-dts-axp81x-add-AC-power-supply-subnode.patch new file mode 100644 index 000000000..1147b6be3 --- /dev/null +++ b/patch/kernel/sunxi-dev/0106-ARM-dts-axp81x-add-AC-power-supply-subnode.patch @@ -0,0 +1,34 @@ +From 89dba78ca59cf4f8973fff843abfe956a7788f27 Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:24 +0300 +Subject: [PATCH 106/146] ARM: dts: axp81x: add AC power supply subnode + +Add AC power supply subnode for AXP81X PMIC. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Quentin Schulz +Reviewed-by: Chen-Yu Tsai +Tested-by: Vasily Khoruzhick +--- + arch/arm/boot/dts/axp81x.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/boot/dts/axp81x.dtsi b/arch/arm/boot/dts/axp81x.dtsi +index 043c717dcef1..bd83962d3627 100644 +--- a/arch/arm/boot/dts/axp81x.dtsi ++++ b/arch/arm/boot/dts/axp81x.dtsi +@@ -48,6 +48,11 @@ + interrupt-controller; + #interrupt-cells = <1>; + ++ ac_power_supply: ac-power-supply { ++ compatible = "x-powers,axp813-ac-power-supply"; ++ status = "disabled"; ++ }; ++ + axp_adc: adc { + compatible = "x-powers,axp813-adc"; + #io-channel-cells = <1>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0107-arm64-dts-allwinner-axp803-add-AC-and-battery-power-.patch b/patch/kernel/sunxi-dev/0107-arm64-dts-allwinner-axp803-add-AC-and-battery-power-.patch new file mode 100644 index 000000000..e7f21bbe0 --- /dev/null +++ b/patch/kernel/sunxi-dev/0107-arm64-dts-allwinner-axp803-add-AC-and-battery-power-.patch @@ -0,0 +1,63 @@ +From 7466a08110850f608e2843a4b8089d184f05fb32 Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:25 +0300 +Subject: [PATCH 107/146] arm64: dts: allwinner: axp803: add AC and battery + power supplies + +Parts of the AXP803 are compatible with their counterparts on the AXP813. +Add DT nodes ADC, GPIO, AC and battery power supplies. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Quentin Schulz +Tested-by: Vasily Khoruzhick +--- + arch/arm64/boot/dts/allwinner/axp803.dtsi | 33 +++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/axp803.dtsi b/arch/arm64/boot/dts/allwinner/axp803.dtsi +index e5eae8bafc42..c3a618e1279a 100644 +--- a/arch/arm64/boot/dts/allwinner/axp803.dtsi ++++ b/arch/arm64/boot/dts/allwinner/axp803.dtsi +@@ -49,6 +49,39 @@ + interrupt-controller; + #interrupt-cells = <1>; + ++ ac_power_supply: ac-power-supply { ++ compatible = "x-powers,axp803-ac-power-supply", ++ "x-powers,axp813-ac-power-supply"; ++ status = "disabled"; ++ }; ++ ++ axp_adc: adc { ++ compatible = "x-powers,axp803-adc", "x-powers,axp813-adc"; ++ #io-channel-cells = <1>; ++ }; ++ ++ axp_gpio: gpio { ++ compatible = "x-powers,axp803-gpio", "x-powers,axp813-gpio"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ gpio0_ldo: gpio0-ldo { ++ pins = "GPIO0"; ++ function = "ldo"; ++ }; ++ ++ gpio1_ldo: gpio1-ldo { ++ pins = "GPIO1"; ++ function = "ldo"; ++ }; ++ }; ++ ++ battery_power_supply: battery-power-supply { ++ compatible = "x-powers,axp803-battery-power-supply", ++ "x-powers,axp813-battery-power-supply"; ++ status = "disabled"; ++ }; ++ + regulators { + /* Default work frequency for buck regulators */ + x-powers,dcdc-freq = <3000>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0108-arm64-dts-allwinner-a64-sopine-baseboard-enable-powe.patch b/patch/kernel/sunxi-dev/0108-arm64-dts-allwinner-a64-sopine-baseboard-enable-powe.patch new file mode 100644 index 000000000..f6b2c7d0b --- /dev/null +++ b/patch/kernel/sunxi-dev/0108-arm64-dts-allwinner-a64-sopine-baseboard-enable-powe.patch @@ -0,0 +1,39 @@ +From f16f4cbdb0deb70c03731fbccb4f52eb4d1d096a Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:26 +0300 +Subject: [PATCH 108/146] arm64: dts: allwinner: a64: sopine-baseboard: enable + power supplies + +AXP803 ACIN pins are routed from SOM to the DC jack on the baseboard. +AXP803 charger pins BATSENSE, LOADSENSE, N_BATDRV, LX_CHG, VIN_CHG +and IPSOUT are connected via PMOS driver to SOM VBAT pins. VBAT and +AXP803 TS pins are routed to the baseboard 3-pin battery connector. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Quentin Schulz +--- + .../boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +index 8e9191f489a6..df7aa8c5f751 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +@@ -80,6 +80,14 @@ + }; + }; + ++&ac_power_supply { ++ status = "okay"; ++}; ++ ++&battery_power_supply { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_dcdc2>; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0109-arm64-dts-allwinner-a64-pinebook-enable-power-suppli.patch b/patch/kernel/sunxi-dev/0109-arm64-dts-allwinner-a64-pinebook-enable-power-suppli.patch new file mode 100644 index 000000000..e17823861 --- /dev/null +++ b/patch/kernel/sunxi-dev/0109-arm64-dts-allwinner-a64-pinebook-enable-power-suppli.patch @@ -0,0 +1,35 @@ +From bedc59458dbad00e9e9b324ebf6836f724158539 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Tue, 23 Oct 2018 21:53:27 +0300 +Subject: [PATCH 109/146] arm64: dts: allwinner: a64: pinebook: enable power + supplies + +Pinebook has ACIN connector and 10000 mAh battery. + +Signed-off-by: Vasily Khoruzhick +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +index 52cbb3052588..dce16d9d6afb 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +@@ -179,6 +179,14 @@ + + #include "axp803.dtsi" + ++&ac_power_supply { ++ status = "okay"; ++}; ++ ++&battery_power_supply { ++ status = "okay"; ++}; ++ + ®_aldo1 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0110-power-supply-add-AC-power-supply-driver-for-AXP813.patch b/patch/kernel/sunxi-dev/0110-power-supply-add-AC-power-supply-driver-for-AXP813.patch new file mode 100644 index 000000000..ca9b56f2c --- /dev/null +++ b/patch/kernel/sunxi-dev/0110-power-supply-add-AC-power-supply-driver-for-AXP813.patch @@ -0,0 +1,179 @@ +From 361aaaf61fc87465c3a59a5e655ad2ce5c727f46 Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:28 +0300 +Subject: [PATCH 110/146] power: supply: add AC power supply driver for AXP813 + +AXP813 and AXP803 PMICs can control input current and minimum voltage. + +Both of these values are configurable. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Quentin Schulz +Acked-by: Lee Jones +--- + drivers/power/supply/axp20x_ac_power.c | 94 ++++++++++++++++++++++++++ + include/linux/mfd/axp20x.h | 1 + + 2 files changed, 95 insertions(+) + +diff --git a/drivers/power/supply/axp20x_ac_power.c b/drivers/power/supply/axp20x_ac_power.c +index 0771f951b11f..59b4c8d3b961 100644 +--- a/drivers/power/supply/axp20x_ac_power.c ++++ b/drivers/power/supply/axp20x_ac_power.c +@@ -27,6 +27,16 @@ + #define AXP20X_PWR_STATUS_ACIN_PRESENT BIT(7) + #define AXP20X_PWR_STATUS_ACIN_AVAIL BIT(6) + ++#define AXP813_VHOLD_MASK GENMASK(5, 3) ++#define AXP813_VHOLD_UV_TO_BIT(x) ((((x) / 100000) - 40) << 3) ++#define AXP813_VHOLD_REG_TO_UV(x) \ ++ (((((x) & AXP813_VHOLD_MASK) >> 3) + 40) * 100000) ++ ++#define AXP813_CURR_LIMIT_MASK GENMASK(2, 0) ++#define AXP813_CURR_LIMIT_UA_TO_BIT(x) (((x) / 500000) - 3) ++#define AXP813_CURR_LIMIT_REG_TO_UA(x) \ ++ ((((x) & AXP813_CURR_LIMIT_MASK) + 3) * 500000) ++ + #define DRVNAME "axp20x-ac-power-supply" + + struct axp20x_ac_power { +@@ -102,6 +112,57 @@ static int axp20x_ac_power_get_property(struct power_supply *psy, + + return 0; + ++ case POWER_SUPPLY_PROP_VOLTAGE_MIN: ++ ret = regmap_read(power->regmap, AXP813_ACIN_PATH_CTRL, ®); ++ if (ret) ++ return ret; ++ ++ val->intval = AXP813_VHOLD_REG_TO_UV(reg); ++ ++ return 0; ++ ++ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: ++ ret = regmap_read(power->regmap, AXP813_ACIN_PATH_CTRL, ®); ++ if (ret) ++ return ret; ++ ++ val->intval = AXP813_CURR_LIMIT_REG_TO_UA(reg); ++ /* AXP813 datasheet defines values 11x as 4000mA */ ++ if (val->intval > 4000000) ++ val->intval = 4000000; ++ ++ return 0; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return -EINVAL; ++} ++ ++static int axp813_ac_power_set_property(struct power_supply *psy, ++ enum power_supply_property psp, ++ const union power_supply_propval *val) ++{ ++ struct axp20x_ac_power *power = power_supply_get_drvdata(psy); ++ ++ switch (psp) { ++ case POWER_SUPPLY_PROP_VOLTAGE_MIN: ++ if (val->intval < 4000000 || val->intval > 4700000) ++ return -EINVAL; ++ ++ return regmap_update_bits(power->regmap, AXP813_ACIN_PATH_CTRL, ++ AXP813_VHOLD_MASK, ++ AXP813_VHOLD_UV_TO_BIT(val->intval)); ++ ++ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: ++ if (val->intval < 1500000 || val->intval > 4000000) ++ return -EINVAL; ++ ++ return regmap_update_bits(power->regmap, AXP813_ACIN_PATH_CTRL, ++ AXP813_CURR_LIMIT_MASK, ++ AXP813_CURR_LIMIT_UA_TO_BIT(val->intval)); ++ + default: + return -EINVAL; + } +@@ -109,6 +170,13 @@ static int axp20x_ac_power_get_property(struct power_supply *psy, + return -EINVAL; + } + ++static int axp813_ac_power_prop_writeable(struct power_supply *psy, ++ enum power_supply_property psp) ++{ ++ return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN || ++ psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT; ++} ++ + static enum power_supply_property axp20x_ac_power_properties[] = { + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_PRESENT, +@@ -123,6 +191,14 @@ static enum power_supply_property axp22x_ac_power_properties[] = { + POWER_SUPPLY_PROP_ONLINE, + }; + ++static enum power_supply_property axp813_ac_power_properties[] = { ++ POWER_SUPPLY_PROP_HEALTH, ++ POWER_SUPPLY_PROP_PRESENT, ++ POWER_SUPPLY_PROP_ONLINE, ++ POWER_SUPPLY_PROP_VOLTAGE_MIN, ++ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, ++}; ++ + static const struct power_supply_desc axp20x_ac_power_desc = { + .name = "axp20x-ac", + .type = POWER_SUPPLY_TYPE_MAINS, +@@ -139,6 +215,16 @@ static const struct power_supply_desc axp22x_ac_power_desc = { + .get_property = axp20x_ac_power_get_property, + }; + ++static const struct power_supply_desc axp813_ac_power_desc = { ++ .name = "axp813-ac", ++ .type = POWER_SUPPLY_TYPE_MAINS, ++ .properties = axp813_ac_power_properties, ++ .num_properties = ARRAY_SIZE(axp813_ac_power_properties), ++ .property_is_writeable = axp813_ac_power_prop_writeable, ++ .get_property = axp20x_ac_power_get_property, ++ .set_property = axp813_ac_power_set_property, ++}; ++ + struct axp_data { + const struct power_supply_desc *power_desc; + bool acin_adc; +@@ -154,6 +240,11 @@ static const struct axp_data axp22x_data = { + .acin_adc = false, + }; + ++static const struct axp_data axp813_data = { ++ .power_desc = &axp813_ac_power_desc, ++ .acin_adc = false, ++}; ++ + static int axp20x_ac_power_probe(struct platform_device *pdev) + { + struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); +@@ -234,6 +325,9 @@ static const struct of_device_id axp20x_ac_power_match[] = { + }, { + .compatible = "x-powers,axp221-ac-power-supply", + .data = &axp22x_data, ++ }, { ++ .compatible = "x-powers,axp813-ac-power-supply", ++ .data = &axp813_data, + }, { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, axp20x_ac_power_match); +diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h +index 517e60eecbcb..2302b620d238 100644 +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -266,6 +266,7 @@ enum axp20x_variants { + #define AXP288_RT_BATT_V_H 0xa0 + #define AXP288_RT_BATT_V_L 0xa1 + ++#define AXP813_ACIN_PATH_CTRL 0x3a + #define AXP813_ADC_RATE 0x85 + + /* Fuel Gauge */ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0111-mfd-axp20x-Add-AC-power-supply-cell-for-AXP813.patch b/patch/kernel/sunxi-dev/0111-mfd-axp20x-Add-AC-power-supply-cell-for-AXP813.patch new file mode 100644 index 000000000..22147f308 --- /dev/null +++ b/patch/kernel/sunxi-dev/0111-mfd-axp20x-Add-AC-power-supply-cell-for-AXP813.patch @@ -0,0 +1,41 @@ +From ea6865e1bfc1a1ac72fe95be42abb88b47413363 Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:29 +0300 +Subject: [PATCH 111/146] mfd: axp20x: Add AC power supply cell for AXP813 + +As axp20x-ac-power-supply now supports AXP813, add a cell for it. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Quentin Schulz +Reviewed-by: Chen-Yu Tsai +Tested-by: Vasily Khoruzhick + +Changed-by: Igor@armbian +--- + drivers/mfd/axp20x.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index 0be511dd93d0..dfc3cff1d08b 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -805,8 +805,13 @@ static const struct mfd_cell axp813_cells[] = { + .name = "axp813-adc", + .of_compatible = "x-powers,axp813-adc", + }, { +- .name = "axp20x-battery-power-supply", +- .of_compatible = "x-powers,axp813-battery-power-supply", ++ .name = "axp20x-battery-power-supply", ++ .of_compatible = "x-powers,axp813-battery-power-supply", ++ }, { ++ .name = "axp20x-ac-power-supply", ++ .of_compatible = "x-powers,axp813-ac-power-supply", ++ .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), ++ .resources = axp20x_ac_power_supply_resources, + }, { + .name = "axp20x-usb-power-supply", + .of_compatible = "x-powers,axp813-usb-power-supply", + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0112-mfd-axp20x-Add-supported-cells-for-AXP803.patch b/patch/kernel/sunxi-dev/0112-mfd-axp20x-Add-supported-cells-for-AXP803.patch new file mode 100644 index 000000000..08e9e95c2 --- /dev/null +++ b/patch/kernel/sunxi-dev/0112-mfd-axp20x-Add-supported-cells-for-AXP803.patch @@ -0,0 +1,49 @@ +From e6def83260bb6ab11d1886b4734b92d589325ebe Mon Sep 17 00:00:00 2001 +From: Oskari Lemmela +Date: Tue, 23 Oct 2018 21:53:30 +0300 +Subject: [PATCH 112/146] mfd: axp20x: Add supported cells for AXP803 + +Parts of the AXP803 are compatible with their counterparts on the AXP813. +These include the GPIO, ADC, AC and battery power supplies. + +Signed-off-by: Oskari Lemmela +Reviewed-by: Chen-Yu Tsai +Tested-by: Vasily Khoruzhick +--- + drivers/mfd/axp20x.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index dfc3cff1d08b..e415b967d38c 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -728,11 +728,26 @@ static const struct mfd_cell axp288_cells[] = { + + static const struct mfd_cell axp803_cells[] = { + { ++ .name = "axp20x-gpio", ++ .of_compatible = "x-powers,axp813-gpio", ++ }, { + .name = "axp221-pek", + .num_resources = ARRAY_SIZE(axp803_pek_resources), + .resources = axp803_pek_resources, + }, + { .name = "axp20x-regulator" }, ++ { ++ .name = "axp813-adc", ++ .of_compatible = "x-powers,axp813-adc", ++ }, { ++ .name = "axp20x-battery-power-supply", ++ .of_compatible = "x-powers,axp813-battery-power-supply", ++ }, { ++ .name = "axp20x-ac-power-supply", ++ .of_compatible = "x-powers,axp813-ac-power-supply", ++ .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), ++ .resources = axp20x_ac_power_supply_resources, ++ }, + }; + + static const struct mfd_cell axp806_self_working_cells[] = { +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0113-ASoC-sun4i-i2s-move-code-from-startup-shutdown-hooks.patch b/patch/kernel/sunxi-dev/0113-ASoC-sun4i-i2s-move-code-from-startup-shutdown-hooks.patch new file mode 100644 index 000000000..2d6eaa9f3 --- /dev/null +++ b/patch/kernel/sunxi-dev/0113-ASoC-sun4i-i2s-move-code-from-startup-shutdown-hooks.patch @@ -0,0 +1,117 @@ +From e4ff7b4f7eddc3a9adc41f3f1d97444a72561910 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Fri, 12 Oct 2018 08:27:43 -0700 +Subject: [PATCH 113/146] ASoC: sun4i-i2s: move code from startup/shutdown + hooks into pm_runtime hooks + +startup() and shutdown() hooks are called for both substreams, +so stopping either substream when another is running breaks the +latter. + +E.g. playback breaks if capture is stopped when playback is running. + +Move code from startup() and shutdown() to resume() and suspend() +hooks respectively to fix this issue + +Signed-off-by: Vasily Khoruzhick +Acked-by: Maxime Ripard +--- + sound/soc/sunxi/sun4i-i2s.c | 61 +++++++++++++++---------------------- + 1 file changed, 25 insertions(+), 36 deletions(-) + +diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c +index a4aa931ebfae..daa6c08cffbc 100644 +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -644,40 +644,6 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd, + return 0; + } + +-static int sun4i_i2s_startup(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai) +-{ +- struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); +- +- /* Enable the whole hardware block */ +- regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, +- SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN); +- +- /* Enable the first output line */ +- regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, +- SUN4I_I2S_CTRL_SDO_EN_MASK, +- SUN4I_I2S_CTRL_SDO_EN(0)); +- +- +- return clk_prepare_enable(i2s->mod_clk); +-} +- +-static void sun4i_i2s_shutdown(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai) +-{ +- struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); +- +- clk_disable_unprepare(i2s->mod_clk); +- +- /* Disable our output lines */ +- regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, +- SUN4I_I2S_CTRL_SDO_EN_MASK, 0); +- +- /* Disable the whole hardware block */ +- regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, +- SUN4I_I2S_CTRL_GL_EN, 0); +-} +- + static int sun4i_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) + { +@@ -695,8 +661,6 @@ static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { + .hw_params = sun4i_i2s_hw_params, + .set_fmt = sun4i_i2s_set_fmt, + .set_sysclk = sun4i_i2s_set_sysclk, +- .shutdown = sun4i_i2s_shutdown, +- .startup = sun4i_i2s_startup, + .trigger = sun4i_i2s_trigger, + }; + +@@ -869,6 +833,21 @@ static int sun4i_i2s_runtime_resume(struct device *dev) + goto err_disable_clk; + } + ++ /* Enable the whole hardware block */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN); ++ ++ /* Enable the first output line */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN4I_I2S_CTRL_SDO_EN_MASK, ++ SUN4I_I2S_CTRL_SDO_EN(0)); ++ ++ ret = clk_prepare_enable(i2s->mod_clk); ++ if (ret) { ++ dev_err(dev, "Failed to enable module clock\n"); ++ goto err_disable_clk; ++ } ++ + return 0; + + err_disable_clk: +@@ -880,6 +859,16 @@ static int sun4i_i2s_runtime_suspend(struct device *dev) + { + struct sun4i_i2s *i2s = dev_get_drvdata(dev); + ++ clk_disable_unprepare(i2s->mod_clk); ++ ++ /* Disable our output lines */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN4I_I2S_CTRL_SDO_EN_MASK, 0); ++ ++ /* Disable the whole hardware block */ ++ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG, ++ SUN4I_I2S_CTRL_GL_EN, 0); ++ + regcache_cache_only(i2s->regmap, true); + + clk_disable_unprepare(i2s->bus_clk); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0114-ASoC-sun4i-i2s-Add-compatibility-with-A64-codec-I2S.patch b/patch/kernel/sunxi-dev/0114-ASoC-sun4i-i2s-Add-compatibility-with-A64-codec-I2S.patch new file mode 100644 index 000000000..537f260f1 --- /dev/null +++ b/patch/kernel/sunxi-dev/0114-ASoC-sun4i-i2s-Add-compatibility-with-A64-codec-I2S.patch @@ -0,0 +1,80 @@ +From 4bfc6b2d77838f3c04e4a1b0814fcf17be2b048f Mon Sep 17 00:00:00 2001 +From: Marcus Cooper +Date: Sun, 3 Dec 2017 10:09:08 -0800 +Subject: [PATCH 114/146] ASoC: sun4i-i2s: Add compatibility with A64 codec I2S + +The I2S block used for the audio codec in the A64 differs from other 3 +I2S modules in A64 and isn't compatible with H3. But it is very similar +to what is found in A10(sun4i). However, its TX FIFO is +located at a different address. + +Signed-off-by: Marcus Cooper +Signed-off-by: Vasily Khoruzhick +Acked-by: Maxime Ripard +--- + .../devicetree/bindings/sound/sun4i-i2s.txt | 2 ++ + sound/soc/sunxi/sun4i-i2s.c | 21 +++++++++++++++++++ + 2 files changed, 23 insertions(+) + +diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt +index b9d50d6cdef3..61e71c1729e0 100644 +--- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt ++++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt +@@ -10,6 +10,7 @@ Required properties: + - "allwinner,sun6i-a31-i2s" + - "allwinner,sun8i-a83t-i2s" + - "allwinner,sun8i-h3-i2s" ++ - "allwinner,sun50i-a64-codec-i2s" + - reg: physical base address of the controller and length of memory mapped + region. + - interrupts: should contain the I2S interrupt. +@@ -26,6 +27,7 @@ Required properties for the following compatibles: + - "allwinner,sun6i-a31-i2s" + - "allwinner,sun8i-a83t-i2s" + - "allwinner,sun8i-h3-i2s" ++ - "allwinner,sun50i-a64-codec-i2s" + - resets: phandle to the reset line for this codec + + Example: +diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c +index daa6c08cffbc..d5ec1a20499d 100644 +--- a/sound/soc/sunxi/sun4i-i2s.c ++++ b/sound/soc/sunxi/sun4i-i2s.c +@@ -950,6 +950,23 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { + .field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2), + }; + ++static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { ++ .has_reset = true, ++ .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, ++ .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, ++ .has_slave_select_bit = true, ++ .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), ++ .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 2, 3), ++ .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 5), ++ .field_fmt_bclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 6, 6), ++ .field_fmt_lrclk = REG_FIELD(SUN4I_I2S_FMT0_REG, 7, 7), ++ .field_fmt_mode = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 1), ++ .field_txchanmap = REG_FIELD(SUN4I_I2S_TX_CHAN_MAP_REG, 0, 31), ++ .field_rxchanmap = REG_FIELD(SUN4I_I2S_RX_CHAN_MAP_REG, 0, 31), ++ .field_txchansel = REG_FIELD(SUN4I_I2S_TX_CHAN_SEL_REG, 0, 2), ++ .field_rxchansel = REG_FIELD(SUN4I_I2S_RX_CHAN_SEL_REG, 0, 2), ++}; ++ + static int sun4i_i2s_init_regmap_fields(struct device *dev, + struct sun4i_i2s *i2s) + { +@@ -1158,6 +1175,10 @@ static const struct of_device_id sun4i_i2s_match[] = { + .compatible = "allwinner,sun8i-h3-i2s", + .data = &sun8i_h3_i2s_quirks, + }, ++ { ++ .compatible = "allwinner,sun50i-a64-codec-i2s", ++ .data = &sun50i_a64_codec_i2s_quirks, ++ }, + {} + }; + MODULE_DEVICE_TABLE(of, sun4i_i2s_match); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0115-ASoC-sun8i-codec-Don-t-hardcode-BCLK-LRCK-ratio.patch b/patch/kernel/sunxi-dev/0115-ASoC-sun8i-codec-Don-t-hardcode-BCLK-LRCK-ratio.patch new file mode 100644 index 000000000..c65852577 --- /dev/null +++ b/patch/kernel/sunxi-dev/0115-ASoC-sun8i-codec-Don-t-hardcode-BCLK-LRCK-ratio.patch @@ -0,0 +1,79 @@ +From a773d556e204228df20f8622d24a37f400f96f96 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sat, 9 Dec 2017 11:15:27 -0800 +Subject: [PATCH 115/146] ASoC: sun8i-codec: Don't hardcode BCLK / LRCK ratio + +BCLK / LRCK ratio should be sample size * channels, but it was +hardcoded to 32 (0x1 is 32 as per A33 and A64 datasheets). + +Calculate it basing on sample size and number of channels. + +Signed-off-by: Vasily Khoruzhick +--- + sound/soc/sunxi/sun8i-codec.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c +index fb37dd927e33..522a72fde78d 100644 +--- a/sound/soc/sunxi/sun8i-codec.c ++++ b/sound/soc/sunxi/sun8i-codec.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -52,7 +53,6 @@ + #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV 13 + #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 + #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 +-#define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16 (1 << 6) + #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 + #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16 (1 << 4) + #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 +@@ -300,12 +300,23 @@ static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec, + return best_val; + } + ++static int sun8i_codec_get_lrck_div(unsigned int channels, ++ unsigned int word_size) ++{ ++ unsigned int div = word_size * channels; ++ ++ if (div < 16 || div > 256) ++ return -EINVAL; ++ ++ return ilog2(div) - 4; ++} ++ + static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) + { + struct sun8i_codec *scodec = snd_soc_component_get_drvdata(dai->component); +- int sample_rate; ++ int sample_rate, lrck_div; + u8 bclk_div; + + /* +@@ -321,9 +332,14 @@ static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, + SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, + bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); + ++ lrck_div = sun8i_codec_get_lrck_div(params_channels(params), ++ params_physical_width(params)); ++ if (lrck_div < 0) ++ return lrck_div; ++ + regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, + SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, +- SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_16); ++ lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); + + sample_rate = sun8i_codec_get_hw_rate(params); + if (sample_rate < 0) +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0116-ASoC-sun8i-codec-analog-split-regmap-code-into-separ.patch b/patch/kernel/sunxi-dev/0116-ASoC-sun8i-codec-analog-split-regmap-code-into-separ.patch new file mode 100644 index 000000000..1b17dab85 --- /dev/null +++ b/patch/kernel/sunxi-dev/0116-ASoC-sun8i-codec-analog-split-regmap-code-into-separ.patch @@ -0,0 +1,283 @@ +From 0415b4bd59d85ccc3c93e1014a798a8092302648 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Thu, 11 Oct 2018 20:59:02 -0700 +Subject: [PATCH 116/146] ASoC: sun8i-codec-analog: split regmap code into + separate driver + +It will be reused by sun50i-codec-analog later. + +Signed-off-by: Vasily Khoruzhick +Acked-by: Maxime Ripard + +Changed by Igor + +--- + sound/soc/sunxi/Kconfig | 7 +- + sound/soc/sunxi/Makefile | 1 + + sound/soc/sunxi/sun8i-adda-pr-regmap.c | 102 +++++++++++++++++++++++++ + sound/soc/sunxi/sun8i-adda-pr-regmap.h | 7 ++ + sound/soc/sunxi/sun8i-codec-analog.c | 79 +------------------ + 5 files changed, 119 insertions(+), 77 deletions(-) + create mode 100644 sound/soc/sunxi/sun8i-adda-pr-regmap.c + create mode 100644 sound/soc/sunxi/sun8i-adda-pr-regmap.h + +diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig +index 22408bc2d6ec..83b770cdfdaa 100644 +--- a/sound/soc/sunxi/Kconfig ++++ b/sound/soc/sunxi/Kconfig +@@ -23,7 +23,7 @@ config SND_SUN8I_CODEC + config SND_SUN8I_CODEC_ANALOG + tristate "Allwinner sun8i Codec Analog Controls Support" + depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST +- select REGMAP ++ select SND_SUN8I_ADDA_PR_REGMAP + help + Say Y or M if you want to add support for the analog controls for + the codec embedded in newer Allwinner SoCs. +@@ -45,4 +45,9 @@ config SND_SUN4I_SPDIF + help + Say Y or M to add support for the S/PDIF audio block in the Allwinner + A10 and affiliated SoCs. ++ ++config SND_SUN8I_ADDA_PR_REGMAP ++ tristate ++ select REGMAP ++ + endmenu +diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile +index 4a9ef67386ca..74b99d55cfca 100644 +--- a/sound/soc/sunxi/Makefile ++++ b/sound/soc/sunxi/Makefile +@@ -4,3 +4,4 @@ obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o + obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o + obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o + obj-$(CONFIG_SND_AC100_CODEC) += ac100-codec.o ++obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) += sun8i-adda-pr-regmap.o +diff --git a/sound/soc/sunxi/sun8i-adda-pr-regmap.c b/sound/soc/sunxi/sun8i-adda-pr-regmap.c +new file mode 100644 +index 000000000000..e68ce9d2884d +--- /dev/null ++++ b/sound/soc/sunxi/sun8i-adda-pr-regmap.c +@@ -0,0 +1,102 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * This driver provides regmap to access to analog part of audio codec ++ * found on Allwinner A23, A31s, A33, H3 and A64 Socs ++ * ++ * Copyright 2016 Chen-Yu Tsai ++ * Copyright (C) 2018 Vasily Khoruzhick ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "sun8i-adda-pr-regmap.h" ++ ++/* Analog control register access bits */ ++#define ADDA_PR 0x0 /* PRCM base + 0x1c0 */ ++#define ADDA_PR_RESET BIT(28) ++#define ADDA_PR_WRITE BIT(24) ++#define ADDA_PR_ADDR_SHIFT 16 ++#define ADDA_PR_ADDR_MASK GENMASK(4, 0) ++#define ADDA_PR_DATA_IN_SHIFT 8 ++#define ADDA_PR_DATA_IN_MASK GENMASK(7, 0) ++#define ADDA_PR_DATA_OUT_SHIFT 0 ++#define ADDA_PR_DATA_OUT_MASK GENMASK(7, 0) ++ ++/* regmap access bits */ ++static int adda_reg_read(void *context, unsigned int reg, unsigned int *val) ++{ ++ void __iomem *base = (void __iomem *)context; ++ u32 tmp; ++ ++ /* De-assert reset */ ++ writel(readl(base) | ADDA_PR_RESET, base); ++ ++ /* Clear write bit */ ++ writel(readl(base) & ~ADDA_PR_WRITE, base); ++ ++ /* Set register address */ ++ tmp = readl(base); ++ tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); ++ tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; ++ writel(tmp, base); ++ ++ /* Read back value */ ++ *val = readl(base) & ADDA_PR_DATA_OUT_MASK; ++ ++ return 0; ++} ++ ++static int adda_reg_write(void *context, unsigned int reg, unsigned int val) ++{ ++ void __iomem *base = (void __iomem *)context; ++ u32 tmp; ++ ++ /* De-assert reset */ ++ writel(readl(base) | ADDA_PR_RESET, base); ++ ++ /* Set register address */ ++ tmp = readl(base); ++ tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); ++ tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; ++ writel(tmp, base); ++ ++ /* Set data to write */ ++ tmp = readl(base); ++ tmp &= ~(ADDA_PR_DATA_IN_MASK << ADDA_PR_DATA_IN_SHIFT); ++ tmp |= (val & ADDA_PR_DATA_IN_MASK) << ADDA_PR_DATA_IN_SHIFT; ++ writel(tmp, base); ++ ++ /* Set write bit to signal a write */ ++ writel(readl(base) | ADDA_PR_WRITE, base); ++ ++ /* Clear write bit */ ++ writel(readl(base) & ~ADDA_PR_WRITE, base); ++ ++ return 0; ++} ++ ++static const struct regmap_config adda_pr_regmap_cfg = { ++ .name = "adda-pr", ++ .reg_bits = 5, ++ .reg_stride = 1, ++ .val_bits = 8, ++ .reg_read = adda_reg_read, ++ .reg_write = adda_reg_write, ++ .fast_io = true, ++ .max_register = 31, ++}; ++ ++struct regmap *sun8i_adda_pr_regmap_init(struct device *dev, ++ void __iomem *base) ++{ ++ return devm_regmap_init(dev, NULL, base, &adda_pr_regmap_cfg); ++} ++EXPORT_SYMBOL_GPL(sun8i_adda_pr_regmap_init); ++ ++MODULE_DESCRIPTION("Allwinner analog audio codec regmap driver"); ++MODULE_AUTHOR("Vasily Khoruzhick "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:sunxi-adda-pr"); +diff --git a/sound/soc/sunxi/sun8i-adda-pr-regmap.h b/sound/soc/sunxi/sun8i-adda-pr-regmap.h +new file mode 100644 +index 000000000000..a5ae95dfebc1 +--- /dev/null ++++ b/sound/soc/sunxi/sun8i-adda-pr-regmap.h +@@ -0,0 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright (C) 2018 Vasily Khoruzhick ++ */ ++ ++struct regmap *sun8i_adda_pr_regmap_init(struct device *dev, ++ void __iomem *base); +diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c +index 485e79f292c4..916a46bbc1c8 100644 +--- a/sound/soc/sunxi/sun8i-codec-analog.c ++++ b/sound/soc/sunxi/sun8i-codec-analog.c +@@ -27,6 +27,8 @@ + #include + #include + ++#include "sun8i-adda-pr-regmap.h" ++ + /* Codec analog control register offsets and bit fields */ + #define SUN8I_ADDA_HP_VOLC 0x00 + #define SUN8I_ADDA_HP_VOLC_PA_CLK_GATE 7 +@@ -120,81 +122,6 @@ + #define SUN8I_ADDA_ADC_AP_EN_ADCLEN 6 + #define SUN8I_ADDA_ADC_AP_EN_ADCG 0 + +-/* Analog control register access bits */ +-#define ADDA_PR 0x0 /* PRCM base + 0x1c0 */ +-#define ADDA_PR_RESET BIT(28) +-#define ADDA_PR_WRITE BIT(24) +-#define ADDA_PR_ADDR_SHIFT 16 +-#define ADDA_PR_ADDR_MASK GENMASK(4, 0) +-#define ADDA_PR_DATA_IN_SHIFT 8 +-#define ADDA_PR_DATA_IN_MASK GENMASK(7, 0) +-#define ADDA_PR_DATA_OUT_SHIFT 0 +-#define ADDA_PR_DATA_OUT_MASK GENMASK(7, 0) +- +-/* regmap access bits */ +-static int adda_reg_read(void *context, unsigned int reg, unsigned int *val) +-{ +- void __iomem *base = (void __iomem *)context; +- u32 tmp; +- +- /* De-assert reset */ +- writel(readl(base) | ADDA_PR_RESET, base); +- +- /* Clear write bit */ +- writel(readl(base) & ~ADDA_PR_WRITE, base); +- +- /* Set register address */ +- tmp = readl(base); +- tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); +- tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; +- writel(tmp, base); +- +- /* Read back value */ +- *val = readl(base) & ADDA_PR_DATA_OUT_MASK; +- +- return 0; +-} +- +-static int adda_reg_write(void *context, unsigned int reg, unsigned int val) +-{ +- void __iomem *base = (void __iomem *)context; +- u32 tmp; +- +- /* De-assert reset */ +- writel(readl(base) | ADDA_PR_RESET, base); +- +- /* Set register address */ +- tmp = readl(base); +- tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT); +- tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT; +- writel(tmp, base); +- +- /* Set data to write */ +- tmp = readl(base); +- tmp &= ~(ADDA_PR_DATA_IN_MASK << ADDA_PR_DATA_IN_SHIFT); +- tmp |= (val & ADDA_PR_DATA_IN_MASK) << ADDA_PR_DATA_IN_SHIFT; +- writel(tmp, base); +- +- /* Set write bit to signal a write */ +- writel(readl(base) | ADDA_PR_WRITE, base); +- +- /* Clear write bit */ +- writel(readl(base) & ~ADDA_PR_WRITE, base); +- +- return 0; +-} +- +-static const struct regmap_config adda_pr_regmap_cfg = { +- .name = "adda-pr", +- .reg_bits = 5, +- .reg_stride = 1, +- .val_bits = 8, +- .reg_read = adda_reg_read, +- .reg_write = adda_reg_write, +- .fast_io = true, +- .max_register = 24, +-}; +- + /* mixer controls */ + static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = { + SOC_DAPM_DOUBLE_R("DAC Playback Switch", +@@ -912,7 +839,7 @@ static int sun8i_codec_analog_probe(struct platform_device *pdev) + return PTR_ERR(base); + } + +- regmap = devm_regmap_init(&pdev->dev, NULL, base, &adda_pr_regmap_cfg); ++ regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base); + if (IS_ERR(regmap)) { + dev_err(&pdev->dev, "Failed to create regmap\n"); + return PTR_ERR(regmap); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0117-ASoC-dt-binding-Add-bindings-for-Allwinner-A64-codec.patch b/patch/kernel/sunxi-dev/0117-ASoC-dt-binding-Add-bindings-for-Allwinner-A64-codec.patch new file mode 100644 index 000000000..cd90e2840 --- /dev/null +++ b/patch/kernel/sunxi-dev/0117-ASoC-dt-binding-Add-bindings-for-Allwinner-A64-codec.patch @@ -0,0 +1,40 @@ +From 426a0f3c97e6ea270e82ec36f5f7ac34fd960d56 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Thu, 11 Oct 2018 22:55:57 -0700 +Subject: [PATCH 117/146] ASoC: dt-binding: Add bindings for Allwinner A64 + codec's analog path controls + +The internal codec on Allwinner A64 is split into 2 parts. The +analog path controls are routed through an embedded custom register +bus accessed through the PRCM block just as on A23/A33/H3. + +Add a binding for this hardware. + +Signed-off-by: Vasily Khoruzhick +Acked-by: Maxime Ripard +--- + .../bindings/sound/sun50i-codec-analog.txt | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + create mode 100644 Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt + +diff --git a/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt +new file mode 100644 +index 000000000000..4f8ad0e04d20 +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/sun50i-codec-analog.txt +@@ -0,0 +1,12 @@ ++* Allwinner A64 Codec Analog Controls ++ ++Required properties: ++- compatible: must be one of the following compatibles: ++ - "allwinner,sun50i-a64-codec-analog" ++- reg: must contain the registers location and length ++ ++Example: ++ codec_analog: codec-analog@1f015c0 { ++ compatible = "allwinner,sun50i-a64-codec-analog"; ++ reg = <0x01f015c0 0x4>; ++ }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0118-ASoC-sunxi-Add-new-driver-for-Allwinner-A64-codec-s-.patch b/patch/kernel/sunxi-dev/0118-ASoC-sunxi-Add-new-driver-for-Allwinner-A64-codec-s-.patch new file mode 100644 index 000000000..25ee2e621 --- /dev/null +++ b/patch/kernel/sunxi-dev/0118-ASoC-sunxi-Add-new-driver-for-Allwinner-A64-codec-s-.patch @@ -0,0 +1,505 @@ +From 010a2d4736116f5464898c3118637a18a214281b Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Thu, 11 Oct 2018 23:07:40 -0700 +Subject: [PATCH 118/146] ASoC: sunxi: Add new driver for Allwinner A64 codec's + analog path controls + +The internal codec on A64 is split into 2 parts. The analog path controls +are routed through an embedded custom register bus accessed through +the PRCM block. + +Add an ASoC component driver for it. This should be tied to the codec +audio card as an auxiliary device. + +Signed-off-by: Vasily Khoruzhick +Acked-by: Maxime Ripard +--- + sound/soc/sunxi/Kconfig | 8 + + sound/soc/sunxi/Makefile | 1 + + sound/soc/sunxi/sun50i-codec-analog.c | 444 ++++++++++++++++++++++++++ + 3 files changed, 453 insertions(+) + create mode 100644 sound/soc/sunxi/sun50i-codec-analog.c + +diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig +index 83b770cdfdaa..8a055ca1819a 100644 +--- a/sound/soc/sunxi/Kconfig ++++ b/sound/soc/sunxi/Kconfig +@@ -28,6 +28,14 @@ config SND_SUN8I_CODEC_ANALOG + Say Y or M if you want to add support for the analog controls for + the codec embedded in newer Allwinner SoCs. + ++config SND_SUN50I_CODEC_ANALOG ++ tristate "Allwinner sun50i Codec Analog Controls Support" ++ depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST ++ select SND_SUNXI_ADDA_PR_REGMAP ++ help ++ Say Y or M if you want to add support for the analog controls for ++ the codec embedded in Allwinner A64 SoC. ++ + config SND_SUN4I_I2S + tristate "Allwinner A10 I2S Support" + select SND_SOC_GENERIC_DMAENGINE_PCM +diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile +index 74b99d55cfca..a86be340a076 100644 +--- a/sound/soc/sunxi/Makefile ++++ b/sound/soc/sunxi/Makefile +@@ -3,5 +3,6 @@ obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o + obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o + obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o + obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o ++obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) += sun50i-codec-analog.o + obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o + obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) += sun8i-adda-pr-regmap.o +diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c +new file mode 100644 +index 000000000000..8f5f999df631 +--- /dev/null ++++ b/sound/soc/sunxi/sun50i-codec-analog.c +@@ -0,0 +1,444 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * This driver supports the analog controls for the internal codec ++ * found in Allwinner's A64 SoC. ++ * ++ * Copyright (C) 2016 Chen-Yu Tsai ++ * Copyright (C) 2017 Marcus Cooper ++ * Copyright (C) 2018 Vasily Khoruzhick ++ * ++ * Based on sun8i-codec-analog.c ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "sun8i-adda-pr-regmap.h" ++ ++/* Codec analog control register offsets and bit fields */ ++#define SUN50I_ADDA_HP_CTRL 0x00 ++#define SUN50I_ADDA_HP_CTRL_PA_CLK_GATE 7 ++#define SUN50I_ADDA_HP_CTRL_HPPA_EN 6 ++#define SUN50I_ADDA_HP_CTRL_HPVOL 0 ++ ++#define SUN50I_ADDA_OL_MIX_CTRL 0x01 ++#define SUN50I_ADDA_OL_MIX_CTRL_MIC1 6 ++#define SUN50I_ADDA_OL_MIX_CTRL_MIC2 5 ++#define SUN50I_ADDA_OL_MIX_CTRL_PHONE 4 ++#define SUN50I_ADDA_OL_MIX_CTRL_PHONEN 3 ++#define SUN50I_ADDA_OL_MIX_CTRL_LINEINL 2 ++#define SUN50I_ADDA_OL_MIX_CTRL_DACL 1 ++#define SUN50I_ADDA_OL_MIX_CTRL_DACR 0 ++ ++#define SUN50I_ADDA_OR_MIX_CTRL 0x02 ++#define SUN50I_ADDA_OR_MIX_CTRL_MIC1 6 ++#define SUN50I_ADDA_OR_MIX_CTRL_MIC2 5 ++#define SUN50I_ADDA_OR_MIX_CTRL_PHONE 4 ++#define SUN50I_ADDA_OR_MIX_CTRL_PHONEP 3 ++#define SUN50I_ADDA_OR_MIX_CTRL_LINEINR 2 ++#define SUN50I_ADDA_OR_MIX_CTRL_DACR 1 ++#define SUN50I_ADDA_OR_MIX_CTRL_DACL 0 ++ ++#define SUN50I_ADDA_LINEOUT_CTRL0 0x05 ++#define SUN50I_ADDA_LINEOUT_CTRL0_LEN 7 ++#define SUN50I_ADDA_LINEOUT_CTRL0_REN 6 ++#define SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL 5 ++#define SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL 4 ++ ++#define SUN50I_ADDA_LINEOUT_CTRL1 0x06 ++#define SUN50I_ADDA_LINEOUT_CTRL1_VOL 0 ++ ++#define SUN50I_ADDA_MIC1_CTRL 0x07 ++#define SUN50I_ADDA_MIC1_CTRL_MIC1G 4 ++#define SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN 3 ++#define SUN50I_ADDA_MIC1_CTRL_MIC1BOOST 0 ++ ++#define SUN50I_ADDA_MIC2_CTRL 0x08 ++#define SUN50I_ADDA_MIC2_CTRL_MIC2G 4 ++#define SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN 3 ++#define SUN50I_ADDA_MIC2_CTRL_MIC2BOOST 0 ++ ++#define SUN50I_ADDA_LINEIN_CTRL 0x09 ++#define SUN50I_ADDA_LINEIN_CTRL_LINEING 0 ++ ++#define SUN50I_ADDA_MIX_DAC_CTRL 0x0a ++#define SUN50I_ADDA_MIX_DAC_CTRL_DACAREN 7 ++#define SUN50I_ADDA_MIX_DAC_CTRL_DACALEN 6 ++#define SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN 5 ++#define SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN 4 ++#define SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE 3 ++#define SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE 2 ++#define SUN50I_ADDA_MIX_DAC_CTRL_RHPIS 1 ++#define SUN50I_ADDA_MIX_DAC_CTRL_LHPIS 0 ++ ++#define SUN50I_ADDA_L_ADCMIX_SRC 0x0b ++#define SUN50I_ADDA_L_ADCMIX_SRC_MIC1 6 ++#define SUN50I_ADDA_L_ADCMIX_SRC_MIC2 5 ++#define SUN50I_ADDA_L_ADCMIX_SRC_PHONE 4 ++#define SUN50I_ADDA_L_ADCMIX_SRC_PHONEN 3 ++#define SUN50I_ADDA_L_ADCMIX_SRC_LINEINL 2 ++#define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL 1 ++#define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR 0 ++ ++#define SUN50I_ADDA_R_ADCMIX_SRC 0x0c ++#define SUN50I_ADDA_R_ADCMIX_SRC_MIC1 6 ++#define SUN50I_ADDA_R_ADCMIX_SRC_MIC2 5 ++#define SUN50I_ADDA_R_ADCMIX_SRC_PHONE 4 ++#define SUN50I_ADDA_R_ADCMIX_SRC_PHONEP 3 ++#define SUN50I_ADDA_R_ADCMIX_SRC_LINEINR 2 ++#define SUN50I_ADDA_R_ADCMIX_SRC_OMIXR 1 ++#define SUN50I_ADDA_R_ADCMIX_SRC_OMIXL 0 ++ ++#define SUN50I_ADDA_ADC_CTRL 0x0d ++#define SUN50I_ADDA_ADC_CTRL_ADCREN 7 ++#define SUN50I_ADDA_ADC_CTRL_ADCLEN 6 ++#define SUN50I_ADDA_ADC_CTRL_ADCG 0 ++ ++#define SUN50I_ADDA_HS_MBIAS_CTRL 0x0e ++#define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN 7 ++ ++#define SUN50I_ADDA_JACK_MIC_CTRL 0x1d ++#define SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN 5 ++ ++/* mixer controls */ ++static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = { ++ SOC_DAPM_DOUBLE_R("DAC Playback Switch", ++ SUN50I_ADDA_OL_MIX_CTRL, ++ SUN50I_ADDA_OR_MIX_CTRL, ++ SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0), ++ SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch", ++ SUN50I_ADDA_OL_MIX_CTRL, ++ SUN50I_ADDA_OR_MIX_CTRL, ++ SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0), ++ SOC_DAPM_DOUBLE_R("Line In Playback Switch", ++ SUN50I_ADDA_OL_MIX_CTRL, ++ SUN50I_ADDA_OR_MIX_CTRL, ++ SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0), ++ SOC_DAPM_DOUBLE_R("Mic1 Playback Switch", ++ SUN50I_ADDA_OL_MIX_CTRL, ++ SUN50I_ADDA_OR_MIX_CTRL, ++ SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0), ++ SOC_DAPM_DOUBLE_R("Mic2 Playback Switch", ++ SUN50I_ADDA_OL_MIX_CTRL, ++ SUN50I_ADDA_OR_MIX_CTRL, ++ SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0), ++}; ++ ++/* ADC mixer controls */ ++static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = { ++ SOC_DAPM_DOUBLE_R("Mixer Capture Switch", ++ SUN50I_ADDA_L_ADCMIX_SRC, ++ SUN50I_ADDA_R_ADCMIX_SRC, ++ SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0), ++ SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch", ++ SUN50I_ADDA_L_ADCMIX_SRC, ++ SUN50I_ADDA_R_ADCMIX_SRC, ++ SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0), ++ SOC_DAPM_DOUBLE_R("Line In Capture Switch", ++ SUN50I_ADDA_L_ADCMIX_SRC, ++ SUN50I_ADDA_R_ADCMIX_SRC, ++ SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0), ++ SOC_DAPM_DOUBLE_R("Mic1 Capture Switch", ++ SUN50I_ADDA_L_ADCMIX_SRC, ++ SUN50I_ADDA_R_ADCMIX_SRC, ++ SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0), ++ SOC_DAPM_DOUBLE_R("Mic2 Capture Switch", ++ SUN50I_ADDA_L_ADCMIX_SRC, ++ SUN50I_ADDA_R_ADCMIX_SRC, ++ SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0), ++}; ++ ++static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale, ++ -450, 150, 0); ++static const DECLARE_TLV_DB_RANGE(sun50i_codec_mic_gain_scale, ++ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), ++ 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0), ++); ++ ++static const DECLARE_TLV_DB_SCALE(sun50i_codec_hp_vol_scale, -6300, 100, 1); ++ ++static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale, ++ 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), ++ 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0), ++); ++ ++ ++/* volume / mute controls */ ++static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { ++ SOC_SINGLE_TLV("Headphone Playback Volume", ++ SUN50I_ADDA_HP_CTRL, ++ SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0, ++ sun50i_codec_hp_vol_scale), ++ ++ SOC_DOUBLE("Headphone Playback Switch", ++ SUN50I_ADDA_MIX_DAC_CTRL, ++ SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE, ++ SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0), ++ ++ /* Mixer pre-gain */ ++ SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL, ++ SUN50I_ADDA_MIC1_CTRL_MIC1G, ++ 0x7, 0, sun50i_codec_out_mixer_pregain_scale), ++ ++ /* Microphone Amp boost gain */ ++ SOC_SINGLE_TLV("Mic1 Boost Volume", SUN50I_ADDA_MIC1_CTRL, ++ SUN50I_ADDA_MIC1_CTRL_MIC1BOOST, 0x7, 0, ++ sun50i_codec_mic_gain_scale), ++ ++ /* Mixer pre-gain */ ++ SOC_SINGLE_TLV("Mic2 Playback Volume", ++ SUN50I_ADDA_MIC2_CTRL, SUN50I_ADDA_MIC2_CTRL_MIC2G, ++ 0x7, 0, sun50i_codec_out_mixer_pregain_scale), ++ ++ /* Microphone Amp boost gain */ ++ SOC_SINGLE_TLV("Mic2 Boost Volume", SUN50I_ADDA_MIC2_CTRL, ++ SUN50I_ADDA_MIC2_CTRL_MIC2BOOST, 0x7, 0, ++ sun50i_codec_mic_gain_scale), ++ ++ /* ADC */ ++ SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN50I_ADDA_ADC_CTRL, ++ SUN50I_ADDA_ADC_CTRL_ADCG, 0x7, 0, ++ sun50i_codec_out_mixer_pregain_scale), ++ ++ /* Mixer pre-gain */ ++ SOC_SINGLE_TLV("Line In Playback Volume", SUN50I_ADDA_LINEIN_CTRL, ++ SUN50I_ADDA_LINEIN_CTRL_LINEING, ++ 0x7, 0, sun50i_codec_out_mixer_pregain_scale), ++ ++ SOC_SINGLE_TLV("Line Out Playback Volume", ++ SUN50I_ADDA_LINEOUT_CTRL1, ++ SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0, ++ sun50i_codec_lineout_vol_scale), ++ ++ SOC_DOUBLE("Line Out Playback Switch", ++ SUN50I_ADDA_LINEOUT_CTRL0, ++ SUN50I_ADDA_LINEOUT_CTRL0_LEN, ++ SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0), ++ ++}; ++ ++static const char * const sun50i_codec_hp_src_enum_text[] = { ++ "DAC", "Mixer", ++}; ++ ++static SOC_ENUM_DOUBLE_DECL(sun50i_codec_hp_src_enum, ++ SUN50I_ADDA_MIX_DAC_CTRL, ++ SUN50I_ADDA_MIX_DAC_CTRL_LHPIS, ++ SUN50I_ADDA_MIX_DAC_CTRL_RHPIS, ++ sun50i_codec_hp_src_enum_text); ++ ++static const struct snd_kcontrol_new sun50i_codec_hp_src[] = { ++ SOC_DAPM_ENUM("Headphone Source Playback Route", ++ sun50i_codec_hp_src_enum), ++}; ++ ++static const char * const sun50i_codec_lineout_src_enum_text[] = { ++ "Stereo", "Mono Differential", ++}; ++ ++static SOC_ENUM_DOUBLE_DECL(sun50i_codec_lineout_src_enum, ++ SUN50I_ADDA_LINEOUT_CTRL0, ++ SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL, ++ SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL, ++ sun50i_codec_lineout_src_enum_text); ++ ++static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = { ++ SOC_DAPM_ENUM("Line Out Source Playback Route", ++ sun50i_codec_lineout_src_enum), ++}; ++ ++static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { ++ /* DAC */ ++ SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, ++ SUN50I_ADDA_MIX_DAC_CTRL_DACALEN, 0), ++ SND_SOC_DAPM_DAC("Right DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, ++ SUN50I_ADDA_MIX_DAC_CTRL_DACAREN, 0), ++ /* ADC */ ++ SND_SOC_DAPM_ADC("Left ADC", NULL, SUN50I_ADDA_ADC_CTRL, ++ SUN50I_ADDA_ADC_CTRL_ADCLEN, 0), ++ SND_SOC_DAPM_ADC("Right ADC", NULL, SUN50I_ADDA_ADC_CTRL, ++ SUN50I_ADDA_ADC_CTRL_ADCREN, 0), ++ /* ++ * Due to this component and the codec belonging to separate DAPM ++ * contexts, we need to manually link the above widgets to their ++ * stream widgets at the card level. ++ */ ++ ++ SND_SOC_DAPM_MUX("Headphone Source Playback Route", ++ SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src), ++ SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN50I_ADDA_HP_CTRL, ++ SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0), ++ SND_SOC_DAPM_OUTPUT("HP"), ++ ++ SND_SOC_DAPM_MUX("Line Out Source Playback Route", ++ SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src), ++ SND_SOC_DAPM_OUTPUT("LINEOUT"), ++ ++ /* Microphone inputs */ ++ SND_SOC_DAPM_INPUT("MIC1"), ++ ++ /* Microphone Bias */ ++ SND_SOC_DAPM_SUPPLY("MBIAS", SUN50I_ADDA_HS_MBIAS_CTRL, ++ SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN, ++ 0, NULL, 0), ++ ++ /* Mic input path */ ++ SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN50I_ADDA_MIC1_CTRL, ++ SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN, 0, NULL, 0), ++ ++ /* Microphone input */ ++ SND_SOC_DAPM_INPUT("MIC2"), ++ ++ /* Microphone Bias */ ++ SND_SOC_DAPM_SUPPLY("HBIAS", SUN50I_ADDA_JACK_MIC_CTRL, ++ SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN, ++ 0, NULL, 0), ++ ++ /* Mic input path */ ++ SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN50I_ADDA_MIC2_CTRL, ++ SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN, 0, NULL, 0), ++ ++ /* Line input */ ++ SND_SOC_DAPM_INPUT("LINEIN"), ++ ++ /* Mixers */ ++ SND_SOC_DAPM_MIXER("Left Mixer", SUN50I_ADDA_MIX_DAC_CTRL, ++ SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN, 0, ++ sun50i_a64_codec_mixer_controls, ++ ARRAY_SIZE(sun50i_a64_codec_mixer_controls)), ++ SND_SOC_DAPM_MIXER("Right Mixer", SUN50I_ADDA_MIX_DAC_CTRL, ++ SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0, ++ sun50i_a64_codec_mixer_controls, ++ ARRAY_SIZE(sun50i_a64_codec_mixer_controls)), ++ SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN50I_ADDA_ADC_CTRL, ++ SUN50I_ADDA_ADC_CTRL_ADCLEN, 0, ++ sun50i_codec_adc_mixer_controls, ++ ARRAY_SIZE(sun50i_codec_adc_mixer_controls)), ++ SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN50I_ADDA_ADC_CTRL, ++ SUN50I_ADDA_ADC_CTRL_ADCREN, 0, ++ sun50i_codec_adc_mixer_controls, ++ ARRAY_SIZE(sun50i_codec_adc_mixer_controls)), ++}; ++ ++static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { ++ /* Left Mixer Routes */ ++ { "Left Mixer", "DAC Playback Switch", "Left DAC" }, ++ { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, ++ { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, ++ ++ /* Right Mixer Routes */ ++ { "Right Mixer", "DAC Playback Switch", "Right DAC" }, ++ { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" }, ++ { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, ++ ++ /* Left ADC Mixer Routes */ ++ { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" }, ++ { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" }, ++ { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, ++ ++ /* Right ADC Mixer Routes */ ++ { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" }, ++ { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" }, ++ { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, ++ ++ /* ADC Routes */ ++ { "Left ADC", NULL, "Left ADC Mixer" }, ++ { "Right ADC", NULL, "Right ADC Mixer" }, ++ ++ /* Headphone Routes */ ++ { "Headphone Source Playback Route", "DAC", "Left DAC" }, ++ { "Headphone Source Playback Route", "DAC", "Right DAC" }, ++ { "Headphone Source Playback Route", "Mixer", "Left Mixer" }, ++ { "Headphone Source Playback Route", "Mixer", "Right Mixer" }, ++ { "Headphone Amp", NULL, "Headphone Source Playback Route" }, ++ { "HP", NULL, "Headphone Amp" }, ++ ++ /* Microphone Routes */ ++ { "Mic1 Amplifier", NULL, "MIC1"}, ++ ++ /* Microphone Routes */ ++ { "Mic2 Amplifier", NULL, "MIC2"}, ++ { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, ++ { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, ++ { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, ++ { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, ++ ++ /* Line-in Routes */ ++ { "Left Mixer", "Line In Playback Switch", "LINEIN" }, ++ { "Right Mixer", "Line In Playback Switch", "LINEIN" }, ++ { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" }, ++ { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" }, ++ ++ /* Line-out Routes */ ++ { "Line Out Source Playback Route", "Stereo", "Left Mixer" }, ++ { "Line Out Source Playback Route", "Stereo", "Right Mixer" }, ++ { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" }, ++ { "Line Out Source Playback Route", "Mono Differential", ++ "Right Mixer" }, ++ { "LINEOUT", NULL, "Line Out Source Playback Route" }, ++}; ++ ++static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { ++ .controls = sun50i_a64_codec_controls, ++ .num_controls = ARRAY_SIZE(sun50i_a64_codec_controls), ++ .dapm_widgets = sun50i_a64_codec_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(sun50i_a64_codec_widgets), ++ .dapm_routes = sun50i_a64_codec_routes, ++ .num_dapm_routes = ARRAY_SIZE(sun50i_a64_codec_routes), ++}; ++ ++static const struct of_device_id sun50i_codec_analog_of_match[] = { ++ { ++ .compatible = "allwinner,sun50i-a64-codec-analog", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match); ++ ++static int sun50i_codec_analog_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct regmap *regmap; ++ void __iomem *base; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) { ++ dev_err(&pdev->dev, "Failed to map the registers\n"); ++ return PTR_ERR(base); ++ } ++ ++ regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base); ++ if (IS_ERR(regmap)) { ++ dev_err(&pdev->dev, "Failed to create regmap\n"); ++ return PTR_ERR(regmap); ++ } ++ ++ return devm_snd_soc_register_component(&pdev->dev, ++ &sun50i_codec_analog_cmpnt_drv, ++ NULL, 0); ++} ++ ++static struct platform_driver sun50i_codec_analog_driver = { ++ .driver = { ++ .name = "sun50i-codec-analog", ++ .of_match_table = sun50i_codec_analog_of_match, ++ }, ++ .probe = sun50i_codec_analog_probe, ++}; ++module_platform_driver(sun50i_codec_analog_driver); ++ ++MODULE_DESCRIPTION("Allwinner internal codec analog controls driver for A64"); ++MODULE_AUTHOR("Vasily Khoruzhick "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:sun50i-codec-analog"); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0119-ASoC-sunxi-allow-the-sun8i-codec-driver-to-be-built-.patch b/patch/kernel/sunxi-dev/0119-ASoC-sunxi-allow-the-sun8i-codec-driver-to-be-built-.patch new file mode 100644 index 000000000..73f892814 --- /dev/null +++ b/patch/kernel/sunxi-dev/0119-ASoC-sunxi-allow-the-sun8i-codec-driver-to-be-built-.patch @@ -0,0 +1,31 @@ +From b66aa83817ae94f594e1c1505127530190ef4eba Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Fri, 12 Oct 2018 23:54:55 -0700 +Subject: [PATCH 119/146] ASoC: sunxi: allow the sun8i-codec driver to be built + on ARM64 + +Allwinner A64 uses the same digital codec part as in A33, so we need +to build this driver on ARM64 as well. + +Signed-off-by: Vasily Khoruzhick +Acked-by: Maxime Ripard +--- + sound/soc/sunxi/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig +index 8a055ca1819a..66aad0d3f9c7 100644 +--- a/sound/soc/sunxi/Kconfig ++++ b/sound/soc/sunxi/Kconfig +@@ -12,7 +12,7 @@ config SND_SUN4I_CODEC + config SND_SUN8I_CODEC + tristate "Allwinner SUN8I audio codec" + depends on OF +- depends on MACH_SUN8I || COMPILE_TEST ++ depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST + select REGMAP_MMIO + help + This option enables the digital part of the internal audio codec for +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0120-arm64-dts-allwinner-a64-add-nodes-necessary-for-anal.patch b/patch/kernel/sunxi-dev/0120-arm64-dts-allwinner-a64-add-nodes-necessary-for-anal.patch new file mode 100644 index 000000000..f782a073c --- /dev/null +++ b/patch/kernel/sunxi-dev/0120-arm64-dts-allwinner-a64-add-nodes-necessary-for-anal.patch @@ -0,0 +1,99 @@ +From 8cbc3090d64e850f1dc5a93e929deaed10d841f8 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sun, 3 Dec 2017 11:35:48 -0800 +Subject: [PATCH 120/146] arm64: dts: allwinner: a64: add nodes necessary for + analog sound support + +Add nodes for i2s, digital and analog parts of audiocodec on A64 + +Signed-off-by: Vasily Khoruzhick +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 58 +++++++++++++++++++ + 1 file changed, 58 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 132da408aa52..cb7d4a96e789 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -200,6 +200,34 @@ + method = "smc"; + }; + ++ sound: sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "sun50i-a64-audio"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,frame-master = <&cpudai>; ++ simple-audio-card,bitclock-master = <&cpudai>; ++ simple-audio-card,mclk-fs = <512>; ++ simple-audio-card,aux-devs = <&codec_analog>; ++ simple-audio-card,routing = ++ "Left DAC", "AIF1 Slot 0 Left", ++ "Right DAC", "AIF1 Slot 0 Right", ++ "AIF1 Slot 0 Left ADC", "Left ADC", ++ "AIF1 Slot 0 Right ADC", "Right ADC", ++ "Left ADC", "ADC", ++ "Right ADC", "ADC", ++ "MIC1", "Mic", ++ "MIC2", "Headset Mic"; ++ status = "disabled"; ++ ++ cpudai: simple-audio-card,cpu { ++ sound-dai = <&dai>; ++ }; ++ ++ link_codec: simple-audio-card,codec { ++ sound-dai = <&codec>; ++ }; ++ }; ++ + sound_spdif { + compatible = "simple-audio-card"; + simple-audio-card,name = "On-board SPDIF"; +@@ -767,6 +795,30 @@ + status = "disabled"; + }; + ++ dai: dai@1c22c00 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun50i-a64-codec-i2s"; ++ reg = <0x01c22c00 0x200>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>; ++ clock-names = "apb", "mod"; ++ resets = <&ccu RST_BUS_CODEC>; ++ reset-names = "rst"; ++ dmas = <&dma 15>, <&dma 15>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ codec: codec@1c22e00 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun8i-a33-codec"; ++ reg = <0x01c22e00 0x600>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>; ++ clock-names = "bus", "mod"; ++ status = "disabled"; ++ }; ++ + ths: thermal-sensor@1c25000 { + compatible = "allwinner,sun50i-a64-ths"; + reg = <0x01c25000 0x100>; +@@ -1071,6 +1123,12 @@ + #reset-cells = <1>; + }; + ++ codec_analog: codec-analog@1f015c0 { ++ compatible = "allwinner,sun50i-a64-codec-analog"; ++ reg = <0x01f015c0 0x4>; ++ status = "disabled"; ++ }; ++ + r_i2c: i2c@1f02400 { + compatible = "allwinner,sun50i-a64-i2c", + "allwinner,sun6i-a31-i2c"; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0121-arm64-dts-allwinner-a64-enable-sound-on-Pine64-and-S.patch b/patch/kernel/sunxi-dev/0121-arm64-dts-allwinner-a64-enable-sound-on-Pine64-and-S.patch new file mode 100644 index 000000000..6f7fb61e0 --- /dev/null +++ b/patch/kernel/sunxi-dev/0121-arm64-dts-allwinner-a64-enable-sound-on-Pine64-and-S.patch @@ -0,0 +1,120 @@ +From 4c61972a0318859afc6a2dbb9cdd355625f6cefc Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sun, 3 Dec 2017 11:39:19 -0800 +Subject: [PATCH 121/146] arm64: dts: allwinner: a64: enable sound on Pine64 + and SoPine + +This commit enables I2S, digital and analog parts of audiocodec on +Pine64 and SoPine boards. + +Signed-off-by: Vasily Khoruzhick +--- + .../boot/dts/allwinner/sun50i-a64-pine64.dts | 29 +++++++++++++++++++ + .../allwinner/sun50i-a64-sopine-baseboard.dts | 29 +++++++++++++++++++ + 2 files changed, 58 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +index cd7e938db01a..f6fc0ed2f4ec 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +@@ -81,10 +81,22 @@ + }; + }; + ++&codec { ++ status = "okay"; ++}; ++ ++&codec_analog { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_dcdc2>; + }; + ++&dai { ++ status = "okay"; ++}; ++ + &de { + status = "okay"; + }; +@@ -289,6 +301,23 @@ + status = "disabled"; + }; + ++&sound { ++ status = "okay"; ++ simple-audio-card,widgets = "Microphone", "Microphone Jack", ++ "Headphone", "Headphone Jack"; ++ simple-audio-card,routing = ++ "Left DAC", "AIF1 Slot 0 Left", ++ "Right DAC", "AIF1 Slot 0 Right", ++ "Speaker", "LINEOUT", ++ "Headphone Jack", "HP", ++ "AIF1 Slot 0 Left ADC", "Left ADC", ++ "AIF1 Slot 0 Right ADC", "Right ADC", ++ "Left ADC", "ADC", ++ "Right ADC", "ADC", ++ "Microphone Jack", "HBIAS", ++ "MIC2", "Microphone Jack"; ++}; ++ + &sound_hdmi { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +index df7aa8c5f751..9010bd58af1b 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +@@ -88,10 +88,22 @@ + status = "okay"; + }; + ++&codec { ++ status = "okay"; ++}; ++ ++&codec_analog { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_dcdc2>; + }; + ++&dai { ++ status = "okay"; ++}; ++ + &de { + status = "okay"; + }; +@@ -191,6 +203,23 @@ + vcc-hdmi-supply = <®_dldo1>; + }; + ++&sound { ++ status = "okay"; ++ simple-audio-card,widgets = "Microphone", "Microphone Jack", ++ "Headphone", "Headphone Jack"; ++ simple-audio-card,routing = ++ "Left DAC", "AIF1 Slot 0 Left", ++ "Right DAC", "AIF1 Slot 0 Right", ++ "Speaker", "LINEOUT", ++ "Headphone Jack", "HP", ++ "AIF1 Slot 0 Left ADC", "Left ADC", ++ "AIF1 Slot 0 Right ADC", "Right ADC", ++ "Left ADC", "ADC", ++ "Right ADC", "ADC", ++ "Microphone Jack", "HBIAS", ++ "MIC2", "Microphone Jack"; ++}; ++ + &sound_hdmi { + status = "okay"; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0122-arm64-dts-allwinner-a64-enable-sound-on-Pinebook.patch b/patch/kernel/sunxi-dev/0122-arm64-dts-allwinner-a64-enable-sound-on-Pinebook.patch new file mode 100644 index 000000000..3b1479df5 --- /dev/null +++ b/patch/kernel/sunxi-dev/0122-arm64-dts-allwinner-a64-enable-sound-on-Pinebook.patch @@ -0,0 +1,86 @@ +From d0970394839f5b09d564142c8a4687ef64458586 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sun, 3 Dec 2017 11:40:25 -0800 +Subject: [PATCH 122/146] arm64: dts: allwinner: a64: enable sound on Pinebook + +This commit enables I2S, digital and analog parts of audiocodec on +Pinebook + +Signed-off-by: Vasily Khoruzhick +--- + .../dts/allwinner/sun50i-a64-pinebook.dts | 42 +++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +index dce16d9d6afb..b55ac4e1df37 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +@@ -71,16 +71,33 @@ + regulator-max-microvolt = <3300000>; + }; + ++ speaker_amp: speaker_amp { ++ compatible = "simple-audio-amplifier"; ++ enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; ++ }; ++ + wifi_pwrseq: wifi_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ + }; + }; + ++&codec { ++ status = "okay"; ++}; ++ ++&codec_analog { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_dcdc2>; + }; + ++&dai { ++ status = "okay"; ++}; ++ + &de { + status = "okay"; + }; +@@ -306,6 +323,31 @@ + vcc-hdmi-supply = <®_dldo1>; + }; + ++&sound { ++ status = "okay"; ++ simple-audio-card,widgets = "Microphone", "Internal Microphone Left", ++ "Microphone", "Internal Microphone Right", ++ "Headphone", "Headphone Jack", ++ "Speaker", "Internal Speaker"; ++ simple-audio-card,aux-devs = <&codec_analog>, <&speaker_amp>; ++ simple-audio-card,routing = ++ "Left DAC", "AIF1 Slot 0 Left", ++ "Right DAC", "AIF1 Slot 0 Right", ++ "INL", "LINEOUT", ++ "INR", "LINEOUT", ++ "Internal Speaker", "OUTL", ++ "Internal Speaker", "OUTR", ++ "Headphone Jack", "HP", ++ "AIF1 Slot 0 Left ADC", "Left ADC", ++ "AIF1 Slot 0 Right ADC", "Right ADC", ++ "Left ADC", "ADC", ++ "Right ADC", "ADC", ++ "Internal Microphone Left", "MBIAS", ++ "MIC1", "Internal Microphone Left", ++ "Internal Microphone Right", "HBIAS", ++ "MIC2", "Internal Microphone Right"; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0123-drm-sun4i-tcon-enable-dithering-on-tcon0-is-there-s-.patch b/patch/kernel/sunxi-dev/0123-drm-sun4i-tcon-enable-dithering-on-tcon0-is-there-s-.patch new file mode 100644 index 000000000..1e6cda291 --- /dev/null +++ b/patch/kernel/sunxi-dev/0123-drm-sun4i-tcon-enable-dithering-on-tcon0-is-there-s-.patch @@ -0,0 +1,58 @@ +From 4690963a2d219abac912ebe2f0b22529c028db06 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sun, 28 Oct 2018 15:32:38 -0700 +Subject: [PATCH 123/146] drm/sun4i: tcon: enable dithering on tcon0 is there's + bridge connected + +RGB on A64 is 6bpc, so if bridge is connected we need to enable dithering + +Signed-off-by: Vasily Khoruzhick +--- + drivers/gpu/drm/sun4i/sun4i_tcon.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c +index 1b28fd9c2908..891ba4dbbf10 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c ++++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c +@@ -283,10 +283,6 @@ static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon, + u32 bus_format = 0; + u32 val = 0; + +- /* XXX Would this ever happen? */ +- if (!connector) +- return; +- + /* + * FIXME: Undocumented bits + * +@@ -304,11 +300,15 @@ static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon, + regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL2_REG, 0x57575555); + regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL3_REG, 0x7f7f7777); + ++ /* Do dithering if there's bridge connected */ ++ if (!connector) ++ val |= SUN4I_TCON0_FRM_CTL_EN; ++ + /* Do dithering if panel only supports 6 bits per color */ +- if (connector->display_info.bpc == 6) ++ if (connector && connector->display_info.bpc == 6) + val |= SUN4I_TCON0_FRM_CTL_EN; + +- if (connector->display_info.num_bus_formats == 1) ++ if (connector && connector->display_info.num_bus_formats == 1) + bus_format = connector->display_info.bus_formats[0]; + + /* Check the connection format */ +@@ -492,6 +492,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, + /* Set dithering if needed */ + if (tcon->panel) + sun4i_tcon0_mode_set_dithering(tcon, tcon->panel->connector); ++ else ++ sun4i_tcon0_mode_set_dithering(tcon, NULL); + + /* Adjust clock delay */ + clk_delay = sun4i_tcon_get_clk_delay(mode, 0); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0124-drm-lima-Fix-Lima-to-work-with-drm-scheduler-changes.patch b/patch/kernel/sunxi-dev/0124-drm-lima-Fix-Lima-to-work-with-drm-scheduler-changes.patch new file mode 100644 index 000000000..834a75467 --- /dev/null +++ b/patch/kernel/sunxi-dev/0124-drm-lima-Fix-Lima-to-work-with-drm-scheduler-changes.patch @@ -0,0 +1,46 @@ +From 2b07a3e1c8918d96db4939c85b5eafcffefd2285 Mon Sep 17 00:00:00 2001 +From: Andreas Baierl +Date: Thu, 4 Oct 2018 06:21:09 -0400 +Subject: [PATCH 124/146] drm/lima: Fix Lima to work with drm scheduler changes + since 4.19 + +Signed-off-by: Andreas Baierl +--- + drivers/gpu/drm/lima/lima_sched.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c +index 1e715e58d33b..d09aae446883 100644 +--- a/drivers/gpu/drm/lima/lima_sched.c ++++ b/drivers/gpu/drm/lima/lima_sched.c +@@ -110,8 +110,7 @@ int lima_sched_task_init(struct lima_sched_task *task, + { + int err; + +- err = drm_sched_job_init(&task->base, context->base.sched, +- &context->base, vm); ++ err = drm_sched_job_init(&task->base, &context->base, vm); + if (err) + return err; + +@@ -169,7 +168,7 @@ int lima_sched_context_init(struct lima_sched_pipe *pipe, + return -ENOMEM; + + mutex_init(&context->lock); +- err = drm_sched_entity_init(&pipe->base, &context->base, rq, guilty); ++ err = drm_sched_entity_init(&context->base, &rq, 1, guilty); + if (err) { + kfree(context->fences); + context->fences = NULL; +@@ -182,7 +181,7 @@ int lima_sched_context_init(struct lima_sched_pipe *pipe, + void lima_sched_context_fini(struct lima_sched_pipe *pipe, + struct lima_sched_context *context) + { +- drm_sched_entity_fini(&pipe->base, &context->base); ++ drm_sched_entity_fini(&context->base); + + mutex_destroy(&context->lock); + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0125-drm-lima-Fix-lima-cache-creation.patch b/patch/kernel/sunxi-dev/0125-drm-lima-Fix-lima-cache-creation.patch new file mode 100644 index 000000000..2712a0116 --- /dev/null +++ b/patch/kernel/sunxi-dev/0125-drm-lima-Fix-lima-cache-creation.patch @@ -0,0 +1,56 @@ +From 491af9a7e7ccddb1c3045c7f9cd2990f6d22154f Mon Sep 17 00:00:00 2001 +From: Andreas Baierl +Date: Tue, 16 Oct 2018 03:19:20 -0400 +Subject: [PATCH 125/146] drm/lima: Fix lima cache creation + +Due to the kernel merge of the hardened usercopy patch set +we have to whitelist the memory area which is used for +copy_from_user actions. Otherwise lima fails with an abort +and segmentation fault. + +This is necessary on systems with CONFIG_HARDENED_USERCOPY enabled. +It was tested on a Cubieboard 1, Allwinner A10. + +Signed-off-by: Andreas Baierl +--- + drivers/gpu/drm/lima/lima_gp.c | 5 +++-- + drivers/gpu/drm/lima/lima_pp.c | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c +index 706652cb1741..6c902648e5cd 100644 +--- a/drivers/gpu/drm/lima/lima_gp.c ++++ b/drivers/gpu/drm/lima/lima_gp.c +@@ -245,9 +245,10 @@ int lima_gp_pipe_init(struct lima_device *dev) + struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp; + + if (!lima_gp_task_slab) { +- lima_gp_task_slab = kmem_cache_create( ++ lima_gp_task_slab = kmem_cache_create_usercopy( + "lima_gp_task", sizeof(struct lima_sched_task) + frame_size, +- 0, SLAB_HWCACHE_ALIGN, NULL); ++ 0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task), ++ frame_size, NULL); + if (!lima_gp_task_slab) + return -ENOMEM; + } +diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c +index 3355895ceeba..502190d1bf3f 100644 +--- a/drivers/gpu/drm/lima/lima_pp.c ++++ b/drivers/gpu/drm/lima/lima_pp.c +@@ -383,9 +383,10 @@ int lima_pp_pipe_init(struct lima_device *dev) + frame_size = sizeof(struct drm_lima_m450_pp_frame); + + if (!lima_pp_task_slab) { +- lima_pp_task_slab = kmem_cache_create( ++ lima_pp_task_slab = kmem_cache_create_usercopy( + "lima_pp_task", sizeof(struct lima_sched_task) + frame_size, +- 0, SLAB_HWCACHE_ALIGN, NULL); ++ 0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task), ++ frame_size, NULL); + if (!lima_pp_task_slab) + return -ENOMEM; + } +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0126-drm-bridge-move-ANA78xx-driver-to-analogix-subdirect.patch b/patch/kernel/sunxi-dev/0126-drm-bridge-move-ANA78xx-driver-to-analogix-subdirect.patch new file mode 100644 index 000000000..ef311d2df --- /dev/null +++ b/patch/kernel/sunxi-dev/0126-drm-bridge-move-ANA78xx-driver-to-analogix-subdirect.patch @@ -0,0 +1,100 @@ +From c66953710d4c7205c380bf9c5a7e296bef3d4948 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:19 +0800 +Subject: [PATCH 126/146] drm/bridge: move ANA78xx driver to analogix + subdirectory + +As ANA78xx chips are designed and produced by Analogix Semiconductor, +Inc, move their driver codes into analogix subdirectory. + +Signed-off-by: Icenowy Zheng +Reviewed-by: Laurent Pinchart +--- + drivers/gpu/drm/bridge/Kconfig | 10 ---------- + drivers/gpu/drm/bridge/Makefile | 4 ++-- + drivers/gpu/drm/bridge/analogix/Kconfig | 10 ++++++++++ + drivers/gpu/drm/bridge/analogix/Makefile | 1 + + .../gpu/drm/bridge/{ => analogix}/analogix-anx78xx.c | 0 + .../gpu/drm/bridge/{ => analogix}/analogix-anx78xx.h | 0 + 6 files changed, 13 insertions(+), 12 deletions(-) + rename drivers/gpu/drm/bridge/{ => analogix}/analogix-anx78xx.c (100%) + rename drivers/gpu/drm/bridge/{ => analogix}/analogix-anx78xx.h (100%) + +diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig +index bf6cad6c9178..43f3c8ff54a4 100644 +--- a/drivers/gpu/drm/bridge/Kconfig ++++ b/drivers/gpu/drm/bridge/Kconfig +@@ -15,16 +15,6 @@ config DRM_PANEL_BRIDGE + menu "Display Interface Bridges" + depends on DRM && DRM_BRIDGE + +-config DRM_ANALOGIX_ANX78XX +- tristate "Analogix ANX78XX bridge" +- select DRM_KMS_HELPER +- select REGMAP_I2C +- ---help--- +- ANX78XX is an ultra-low Full-HD SlimPort transmitter +- designed for portable devices. The ANX78XX transforms +- the HDMI output of an application processor to MyDP +- or DisplayPort. +- + config DRM_CDNS_DSI + tristate "Cadence DPI/DSI bridge" + select DRM_KMS_HELPER +diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile +index 35f88d48ec20..49a5d92a0d9d 100644 +--- a/drivers/gpu/drm/bridge/Makefile ++++ b/drivers/gpu/drm/bridge/Makefile +@@ -1,5 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 +-obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o + obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o + obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o + obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o +@@ -11,7 +10,8 @@ obj-$(CONFIG_DRM_SII902X) += sii902x.o + obj-$(CONFIG_DRM_SII9234) += sii9234.o + obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o + obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o +-obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ + obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ + obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o ++ ++obj-y += analogix/ + obj-y += synopsys/ +diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig +index 80f286fa3a69..27b37aa2ea77 100644 +--- a/drivers/gpu/drm/bridge/analogix/Kconfig ++++ b/drivers/gpu/drm/bridge/analogix/Kconfig +@@ -1,3 +1,13 @@ + config DRM_ANALOGIX_DP + tristate + depends on DRM ++ ++config DRM_ANALOGIX_ANX78XX ++ tristate "Analogix ANX78XX bridge" ++ select DRM_KMS_HELPER ++ select REGMAP_I2C ++ ---help--- ++ ANX78XX is an ultra-low Full-HD SlimPort transmitter ++ designed for portable devices. The ANX78XX transforms ++ the HDMI output of an application processor to MyDP ++ or DisplayPort. +diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile +index cd4010ba6890..eb41be845055 100644 +--- a/drivers/gpu/drm/bridge/analogix/Makefile ++++ b/drivers/gpu/drm/bridge/analogix/Makefile +@@ -1,2 +1,3 @@ + analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o + obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o ++obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o +diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +similarity index 100% +rename from drivers/gpu/drm/bridge/analogix-anx78xx.c +rename to drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.h b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.h +similarity index 100% +rename from drivers/gpu/drm/bridge/analogix-anx78xx.h +rename to drivers/gpu/drm/bridge/analogix/analogix-anx78xx.h +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0127-drm-bridge-split-some-definitions-of-ANX78xx-to-dedi.patch b/patch/kernel/sunxi-dev/0127-drm-bridge-split-some-definitions-of-ANX78xx-to-dedi.patch new file mode 100644 index 000000000..03b380246 --- /dev/null +++ b/patch/kernel/sunxi-dev/0127-drm-bridge-split-some-definitions-of-ANX78xx-to-dedi.patch @@ -0,0 +1,1005 @@ +From d369162154e5d904c62ed6275ec71d8c2cbcb024 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:20 +0800 +Subject: [PATCH 127/146] drm/bridge: split some definitions of ANX78xx to + dedicated headers + +Some definitions currently in analogix-anx78xx.h are not restricted to +the ANX78xx series, but also applicable to other DisplayPort +transmitters by Analogix. + +Split out them to dedicated headers, and make analogix-anx78xx.h include +them. + +Signed-off-by: Icenowy Zheng +--- + .../drm/bridge/analogix/analogix-anx78xx.h | 464 +----------------- + .../drm/bridge/analogix/analogix-i2c-dptx.h | 248 ++++++++++ + .../bridge/analogix/analogix-i2c-txcommon.h | 237 +++++++++ + 3 files changed, 490 insertions(+), 459 deletions(-) + create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h + create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h + +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.h b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.h +index 38753c870137..8aa1eca306d3 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.h ++++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.h +@@ -15,9 +15,12 @@ + #ifndef __ANX78xx_H + #define __ANX78xx_H + +-#define TX_P0 0x70 ++#include "analogix-i2c-dptx.h" ++#include "analogix-i2c-txcommon.h" ++ ++#define TX_P0 ANALOGIX_I2C_DPTX + #define TX_P1 0x7a +-#define TX_P2 0x72 ++#define TX_P2 ANALOGIX_I2C_TXCOMMON + + #define RX_P0 0x7e + #define RX_P1 0x80 +@@ -225,463 +228,6 @@ + #define SP_CLEAR_AVMUTE BIT(4) + #define SP_SET_AVMUTE BIT(0) + +-/***************************************************************/ +-/* Register definition of device address 0x70 */ +-/***************************************************************/ +- +-/* HDCP Status Register */ +-#define SP_TX_HDCP_STATUS_REG 0x00 +-#define SP_AUTH_FAIL BIT(5) +-#define SP_AUTHEN_PASS BIT(1) +- +-/* HDCP Control Register 0 */ +-#define SP_HDCP_CTRL0_REG 0x01 +-#define SP_RX_REPEATER BIT(6) +-#define SP_RE_AUTH BIT(5) +-#define SP_SW_AUTH_OK BIT(4) +-#define SP_HARD_AUTH_EN BIT(3) +-#define SP_HDCP_ENC_EN BIT(2) +-#define SP_BKSV_SRM_PASS BIT(1) +-#define SP_KSVLIST_VLD BIT(0) +-/* HDCP Function Enabled */ +-#define SP_HDCP_FUNCTION_ENABLED (BIT(0) | BIT(1) | BIT(2) | BIT(3)) +- +-/* HDCP Receiver BSTATUS Register 0 */ +-#define SP_HDCP_RX_BSTATUS0_REG 0x1b +-/* HDCP Receiver BSTATUS Register 1 */ +-#define SP_HDCP_RX_BSTATUS1_REG 0x1c +- +-/* HDCP Embedded "Blue Screen" Content Registers */ +-#define SP_HDCP_VID0_BLUE_SCREEN_REG 0x2c +-#define SP_HDCP_VID1_BLUE_SCREEN_REG 0x2d +-#define SP_HDCP_VID2_BLUE_SCREEN_REG 0x2e +- +-/* HDCP Wait R0 Timing Register */ +-#define SP_HDCP_WAIT_R0_TIME_REG 0x40 +- +-/* HDCP Link Integrity Check Timer Register */ +-#define SP_HDCP_LINK_CHECK_TIMER_REG 0x41 +- +-/* HDCP Repeater Ready Wait Timer Register */ +-#define SP_HDCP_RPTR_RDY_WAIT_TIME_REG 0x42 +- +-/* HDCP Auto Timer Register */ +-#define SP_HDCP_AUTO_TIMER_REG 0x51 +- +-/* HDCP Key Status Register */ +-#define SP_HDCP_KEY_STATUS_REG 0x5e +- +-/* HDCP Key Command Register */ +-#define SP_HDCP_KEY_COMMAND_REG 0x5f +-#define SP_DISABLE_SYNC_HDCP BIT(2) +- +-/* OTP Memory Key Protection Registers */ +-#define SP_OTP_KEY_PROTECT1_REG 0x60 +-#define SP_OTP_KEY_PROTECT2_REG 0x61 +-#define SP_OTP_KEY_PROTECT3_REG 0x62 +-#define SP_OTP_PSW1 0xa2 +-#define SP_OTP_PSW2 0x7e +-#define SP_OTP_PSW3 0xc6 +- +-/* DP System Control Registers */ +-#define SP_DP_SYSTEM_CTRL_BASE (0x80 - 1) +-/* Bits for DP System Control Register 2 */ +-#define SP_CHA_STA BIT(2) +-/* Bits for DP System Control Register 3 */ +-#define SP_HPD_STATUS BIT(6) +-#define SP_STRM_VALID BIT(2) +-/* Bits for DP System Control Register 4 */ +-#define SP_ENHANCED_MODE BIT(3) +- +-/* DP Video Control Register */ +-#define SP_DP_VIDEO_CTRL_REG 0x84 +-#define SP_COLOR_F_MASK 0x06 +-#define SP_COLOR_F_SHIFT 1 +-#define SP_BPC_MASK 0xe0 +-#define SP_BPC_SHIFT 5 +-# define SP_BPC_6BITS 0x00 +-# define SP_BPC_8BITS 0x01 +-# define SP_BPC_10BITS 0x02 +-# define SP_BPC_12BITS 0x03 +- +-/* DP Audio Control Register */ +-#define SP_DP_AUDIO_CTRL_REG 0x87 +-#define SP_AUD_EN BIT(0) +- +-/* 10us Pulse Generate Timer Registers */ +-#define SP_I2C_GEN_10US_TIMER0_REG 0x88 +-#define SP_I2C_GEN_10US_TIMER1_REG 0x89 +- +-/* Packet Send Control Register */ +-#define SP_PACKET_SEND_CTRL_REG 0x90 +-#define SP_AUD_IF_UP BIT(7) +-#define SP_AVI_IF_UD BIT(6) +-#define SP_MPEG_IF_UD BIT(5) +-#define SP_SPD_IF_UD BIT(4) +-#define SP_AUD_IF_EN BIT(3) +-#define SP_AVI_IF_EN BIT(2) +-#define SP_MPEG_IF_EN BIT(1) +-#define SP_SPD_IF_EN BIT(0) +- +-/* DP HDCP Control Register */ +-#define SP_DP_HDCP_CTRL_REG 0x92 +-#define SP_AUTO_EN BIT(7) +-#define SP_AUTO_START BIT(5) +-#define SP_LINK_POLLING BIT(1) +- +-/* DP Main Link Bandwidth Setting Register */ +-#define SP_DP_MAIN_LINK_BW_SET_REG 0xa0 +-#define SP_LINK_BW_SET_MASK 0x1f +-#define SP_INITIAL_SLIM_M_AUD_SEL BIT(5) +- +-/* DP Training Pattern Set Register */ +-#define SP_DP_TRAINING_PATTERN_SET_REG 0xa2 +- +-/* DP Lane 0 Link Training Control Register */ +-#define SP_DP_LANE0_LT_CTRL_REG 0xa3 +-#define SP_TX_SW_SET_MASK 0x1b +-#define SP_MAX_PRE_REACH BIT(5) +-#define SP_MAX_DRIVE_REACH BIT(4) +-#define SP_PRE_EMP_LEVEL1 BIT(3) +-#define SP_DRVIE_CURRENT_LEVEL1 BIT(0) +- +-/* DP Link Training Control Register */ +-#define SP_DP_LT_CTRL_REG 0xa8 +-#define SP_LT_ERROR_TYPE_MASK 0x70 +-# define SP_LT_NO_ERROR 0x00 +-# define SP_LT_AUX_WRITE_ERROR 0x01 +-# define SP_LT_MAX_DRIVE_REACHED 0x02 +-# define SP_LT_WRONG_LANE_COUNT_SET 0x03 +-# define SP_LT_LOOP_SAME_5_TIME 0x04 +-# define SP_LT_CR_FAIL_IN_EQ 0x05 +-# define SP_LT_EQ_LOOP_5_TIME 0x06 +-#define SP_LT_EN BIT(0) +- +-/* DP CEP Training Control Registers */ +-#define SP_DP_CEP_TRAINING_CTRL0_REG 0xa9 +-#define SP_DP_CEP_TRAINING_CTRL1_REG 0xaa +- +-/* DP Debug Register 1 */ +-#define SP_DP_DEBUG1_REG 0xb0 +-#define SP_DEBUG_PLL_LOCK BIT(4) +-#define SP_POLLING_EN BIT(1) +- +-/* DP Polling Control Register */ +-#define SP_DP_POLLING_CTRL_REG 0xb4 +-#define SP_AUTO_POLLING_DISABLE BIT(0) +- +-/* DP Link Debug Control Register */ +-#define SP_DP_LINK_DEBUG_CTRL_REG 0xb8 +-#define SP_M_VID_DEBUG BIT(5) +-#define SP_NEW_PRBS7 BIT(4) +-#define SP_INSERT_ER BIT(1) +-#define SP_PRBS31_EN BIT(0) +- +-/* AUX Misc control Register */ +-#define SP_AUX_MISC_CTRL_REG 0xbf +- +-/* DP PLL control Register */ +-#define SP_DP_PLL_CTRL_REG 0xc7 +-#define SP_PLL_RST BIT(6) +- +-/* DP Analog Power Down Register */ +-#define SP_DP_ANALOG_POWER_DOWN_REG 0xc8 +-#define SP_CH0_PD BIT(0) +- +-/* DP Misc Control Register */ +-#define SP_DP_MISC_CTRL_REG 0xcd +-#define SP_EQ_TRAINING_LOOP BIT(6) +- +-/* DP Extra I2C Device Address Register */ +-#define SP_DP_EXTRA_I2C_DEV_ADDR_REG 0xce +-#define SP_I2C_STRETCH_DISABLE BIT(7) +- +-#define SP_I2C_EXTRA_ADDR 0x50 +- +-/* DP Downspread Control Register 1 */ +-#define SP_DP_DOWNSPREAD_CTRL1_REG 0xd0 +- +-/* DP M Value Calculation Control Register */ +-#define SP_DP_M_CALCULATION_CTRL_REG 0xd9 +-#define SP_M_GEN_CLK_SEL BIT(0) +- +-/* AUX Channel Access Status Register */ +-#define SP_AUX_CH_STATUS_REG 0xe0 +-#define SP_AUX_STATUS 0x0f +- +-/* AUX Channel DEFER Control Register */ +-#define SP_AUX_DEFER_CTRL_REG 0xe2 +-#define SP_DEFER_CTRL_EN BIT(7) +- +-/* DP Buffer Data Count Register */ +-#define SP_BUF_DATA_COUNT_REG 0xe4 +-#define SP_BUF_DATA_COUNT_MASK 0x1f +-#define SP_BUF_CLR BIT(7) +- +-/* DP AUX Channel Control Register 1 */ +-#define SP_DP_AUX_CH_CTRL1_REG 0xe5 +-#define SP_AUX_TX_COMM_MASK 0x0f +-#define SP_AUX_LENGTH_MASK 0xf0 +-#define SP_AUX_LENGTH_SHIFT 4 +- +-/* DP AUX CH Address Register 0 */ +-#define SP_AUX_ADDR_7_0_REG 0xe6 +- +-/* DP AUX CH Address Register 1 */ +-#define SP_AUX_ADDR_15_8_REG 0xe7 +- +-/* DP AUX CH Address Register 2 */ +-#define SP_AUX_ADDR_19_16_REG 0xe8 +-#define SP_AUX_ADDR_19_16_MASK 0x0f +- +-/* DP AUX Channel Control Register 2 */ +-#define SP_DP_AUX_CH_CTRL2_REG 0xe9 +-#define SP_AUX_SEL_RXCM BIT(6) +-#define SP_AUX_CHSEL BIT(3) +-#define SP_AUX_PN_INV BIT(2) +-#define SP_ADDR_ONLY BIT(1) +-#define SP_AUX_EN BIT(0) +- +-/* DP Video Stream Control InfoFrame Register */ +-#define SP_DP_3D_VSC_CTRL_REG 0xea +-#define SP_INFO_FRAME_VSC_EN BIT(0) +- +-/* DP Video Stream Data Byte 1 Register */ +-#define SP_DP_VSC_DB1_REG 0xeb +- +-/* DP AUX Channel Control Register 3 */ +-#define SP_DP_AUX_CH_CTRL3_REG 0xec +-#define SP_WAIT_COUNTER_7_0_MASK 0xff +- +-/* DP AUX Channel Control Register 4 */ +-#define SP_DP_AUX_CH_CTRL4_REG 0xed +- +-/* DP AUX Buffer Data Registers */ +-#define SP_DP_BUF_DATA0_REG 0xf0 +- +-/***************************************************************/ +-/* Register definition of device address 0x72 */ +-/***************************************************************/ +- +-/* +- * Core Register Definitions +- */ +- +-/* Device ID Low Byte Register */ +-#define SP_DEVICE_IDL_REG 0x02 +- +-/* Device ID High Byte Register */ +-#define SP_DEVICE_IDH_REG 0x03 +- +-/* Device version register */ +-#define SP_DEVICE_VERSION_REG 0x04 +- +-/* Power Down Control Register */ +-#define SP_POWERDOWN_CTRL_REG 0x05 +-#define SP_REGISTER_PD BIT(7) +-#define SP_HDCP_PD BIT(5) +-#define SP_AUDIO_PD BIT(4) +-#define SP_VIDEO_PD BIT(3) +-#define SP_LINK_PD BIT(2) +-#define SP_TOTAL_PD BIT(1) +- +-/* Reset Control Register 1 */ +-#define SP_RESET_CTRL1_REG 0x06 +-#define SP_MISC_RST BIT(7) +-#define SP_VIDCAP_RST BIT(6) +-#define SP_VIDFIF_RST BIT(5) +-#define SP_AUDFIF_RST BIT(4) +-#define SP_AUDCAP_RST BIT(3) +-#define SP_HDCP_RST BIT(2) +-#define SP_SW_RST BIT(1) +-#define SP_HW_RST BIT(0) +- +-/* Reset Control Register 2 */ +-#define SP_RESET_CTRL2_REG 0x07 +-#define SP_AUX_RST BIT(2) +-#define SP_SERDES_FIFO_RST BIT(1) +-#define SP_I2C_REG_RST BIT(0) +- +-/* Video Control Register 1 */ +-#define SP_VID_CTRL1_REG 0x08 +-#define SP_VIDEO_EN BIT(7) +-#define SP_VIDEO_MUTE BIT(2) +-#define SP_DE_GEN BIT(1) +-#define SP_DEMUX BIT(0) +- +-/* Video Control Register 2 */ +-#define SP_VID_CTRL2_REG 0x09 +-#define SP_IN_COLOR_F_MASK 0x03 +-#define SP_IN_YC_BIT_SEL BIT(2) +-#define SP_IN_BPC_MASK 0x70 +-#define SP_IN_BPC_SHIFT 4 +-# define SP_IN_BPC_12BIT 0x03 +-# define SP_IN_BPC_10BIT 0x02 +-# define SP_IN_BPC_8BIT 0x01 +-# define SP_IN_BPC_6BIT 0x00 +-#define SP_IN_D_RANGE BIT(7) +- +-/* Video Control Register 3 */ +-#define SP_VID_CTRL3_REG 0x0a +-#define SP_HPD_OUT BIT(6) +- +-/* Video Control Register 5 */ +-#define SP_VID_CTRL5_REG 0x0c +-#define SP_CSC_STD_SEL BIT(7) +-#define SP_XVYCC_RNG_LMT BIT(6) +-#define SP_RANGE_Y2R BIT(5) +-#define SP_CSPACE_Y2R BIT(4) +-#define SP_RGB_RNG_LMT BIT(3) +-#define SP_Y_RNG_LMT BIT(2) +-#define SP_RANGE_R2Y BIT(1) +-#define SP_CSPACE_R2Y BIT(0) +- +-/* Video Control Register 6 */ +-#define SP_VID_CTRL6_REG 0x0d +-#define SP_TEST_PATTERN_EN BIT(7) +-#define SP_VIDEO_PROCESS_EN BIT(6) +-#define SP_VID_US_MODE BIT(3) +-#define SP_VID_DS_MODE BIT(2) +-#define SP_UP_SAMPLE BIT(1) +-#define SP_DOWN_SAMPLE BIT(0) +- +-/* Video Control Register 8 */ +-#define SP_VID_CTRL8_REG 0x0f +-#define SP_VID_VRES_TH BIT(0) +- +-/* Total Line Status Low Byte Register */ +-#define SP_TOTAL_LINE_STAL_REG 0x24 +- +-/* Total Line Status High Byte Register */ +-#define SP_TOTAL_LINE_STAH_REG 0x25 +- +-/* Active Line Status Low Byte Register */ +-#define SP_ACT_LINE_STAL_REG 0x26 +- +-/* Active Line Status High Byte Register */ +-#define SP_ACT_LINE_STAH_REG 0x27 +- +-/* Vertical Front Porch Status Register */ +-#define SP_V_F_PORCH_STA_REG 0x28 +- +-/* Vertical SYNC Width Status Register */ +-#define SP_V_SYNC_STA_REG 0x29 +- +-/* Vertical Back Porch Status Register */ +-#define SP_V_B_PORCH_STA_REG 0x2a +- +-/* Total Pixel Status Low Byte Register */ +-#define SP_TOTAL_PIXEL_STAL_REG 0x2b +- +-/* Total Pixel Status High Byte Register */ +-#define SP_TOTAL_PIXEL_STAH_REG 0x2c +- +-/* Active Pixel Status Low Byte Register */ +-#define SP_ACT_PIXEL_STAL_REG 0x2d +- +-/* Active Pixel Status High Byte Register */ +-#define SP_ACT_PIXEL_STAH_REG 0x2e +- +-/* Horizontal Front Porch Status Low Byte Register */ +-#define SP_H_F_PORCH_STAL_REG 0x2f +- +-/* Horizontal Front Porch Statys High Byte Register */ +-#define SP_H_F_PORCH_STAH_REG 0x30 +- +-/* Horizontal SYNC Width Status Low Byte Register */ +-#define SP_H_SYNC_STAL_REG 0x31 +- +-/* Horizontal SYNC Width Status High Byte Register */ +-#define SP_H_SYNC_STAH_REG 0x32 +- +-/* Horizontal Back Porch Status Low Byte Register */ +-#define SP_H_B_PORCH_STAL_REG 0x33 +- +-/* Horizontal Back Porch Status High Byte Register */ +-#define SP_H_B_PORCH_STAH_REG 0x34 +- +-/* InfoFrame AVI Packet DB1 Register */ +-#define SP_INFOFRAME_AVI_DB1_REG 0x70 +- +-/* Bit Control Specific Register */ +-#define SP_BIT_CTRL_SPECIFIC_REG 0x80 +-#define SP_BIT_CTRL_SELECT_SHIFT 1 +-#define SP_ENABLE_BIT_CTRL BIT(0) +- +-/* InfoFrame Audio Packet DB1 Register */ +-#define SP_INFOFRAME_AUD_DB1_REG 0x83 +- +-/* InfoFrame MPEG Packet DB1 Register */ +-#define SP_INFOFRAME_MPEG_DB1_REG 0xb0 +- +-/* Audio Channel Status Registers */ +-#define SP_AUD_CH_STATUS_BASE 0xd0 +- +-/* Audio Channel Num Register 5 */ +-#define SP_I2S_CHANNEL_NUM_MASK 0xe0 +-# define SP_I2S_CH_NUM_1 (0x00 << 5) +-# define SP_I2S_CH_NUM_2 (0x01 << 5) +-# define SP_I2S_CH_NUM_3 (0x02 << 5) +-# define SP_I2S_CH_NUM_4 (0x03 << 5) +-# define SP_I2S_CH_NUM_5 (0x04 << 5) +-# define SP_I2S_CH_NUM_6 (0x05 << 5) +-# define SP_I2S_CH_NUM_7 (0x06 << 5) +-# define SP_I2S_CH_NUM_8 (0x07 << 5) +-#define SP_EXT_VUCP BIT(2) +-#define SP_VBIT BIT(1) +-#define SP_AUDIO_LAYOUT BIT(0) +- +-/* Analog Debug Register 2 */ +-#define SP_ANALOG_DEBUG2_REG 0xdd +-#define SP_FORCE_SW_OFF_BYPASS 0x20 +-#define SP_XTAL_FRQ 0x1c +-# define SP_XTAL_FRQ_19M2 (0x00 << 2) +-# define SP_XTAL_FRQ_24M (0x01 << 2) +-# define SP_XTAL_FRQ_25M (0x02 << 2) +-# define SP_XTAL_FRQ_26M (0x03 << 2) +-# define SP_XTAL_FRQ_27M (0x04 << 2) +-# define SP_XTAL_FRQ_38M4 (0x05 << 2) +-# define SP_XTAL_FRQ_52M (0x06 << 2) +-#define SP_POWERON_TIME_1P5MS 0x03 +- +-/* Analog Control 0 Register */ +-#define SP_ANALOG_CTRL0_REG 0xe1 +- +-/* Common Interrupt Status Register 1 */ +-#define SP_COMMON_INT_STATUS_BASE (0xf1 - 1) +-#define SP_PLL_LOCK_CHG 0x40 +- +-/* Common Interrupt Status Register 2 */ +-#define SP_COMMON_INT_STATUS2 0xf2 +-#define SP_HDCP_AUTH_CHG BIT(1) +-#define SP_HDCP_AUTH_DONE BIT(0) +- +-#define SP_HDCP_LINK_CHECK_FAIL BIT(0) +- +-/* Common Interrupt Status Register 4 */ +-#define SP_COMMON_INT_STATUS4_REG 0xf4 +-#define SP_HPD_IRQ BIT(6) +-#define SP_HPD_ESYNC_ERR BIT(4) +-#define SP_HPD_CHG BIT(2) +-#define SP_HPD_LOST BIT(1) +-#define SP_HPD_PLUG BIT(0) +- +-/* DP Interrupt Status Register */ +-#define SP_DP_INT_STATUS1_REG 0xf7 +-#define SP_TRAINING_FINISH BIT(5) +-#define SP_POLLING_ERR BIT(4) +- +-/* Common Interrupt Mask Register */ +-#define SP_COMMON_INT_MASK_BASE (0xf8 - 1) +- +-#define SP_COMMON_INT_MASK4_REG 0xfb +- +-/* DP Interrupts Mask Register */ +-#define SP_DP_INT_MASK1_REG 0xfe +- +-/* Interrupt Control Register */ +-#define SP_INT_CTRL_REG 0xff +- + /***************************************************************/ + /* Register definition of device address 0x7a */ + /***************************************************************/ +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h +new file mode 100644 +index 000000000000..bc0831b127bf +--- /dev/null ++++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h +@@ -0,0 +1,248 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright(c) 2017 Icenowy Zheng ++ * ++ * Based on analogix-anx78xx.h, which is: ++ * Copyright(c) 2016, Analogix Semiconductor. All rights reserved. ++ */ ++ ++#ifndef _ANALOGIX_I2C_DPTX_H_ ++#define _ANALOGIX_I2C_DPTX_H_ ++ ++#define ANALOGIX_I2C_DPTX 0x70 ++ ++/***************************************************************/ ++/* Register definition of device address 0x70 */ ++/***************************************************************/ ++ ++/* HDCP Status Register */ ++#define SP_TX_HDCP_STATUS_REG 0x00 ++#define SP_AUTH_FAIL BIT(5) ++#define SP_AUTHEN_PASS BIT(1) ++ ++/* HDCP Control Register 0 */ ++#define SP_HDCP_CTRL0_REG 0x01 ++#define SP_RX_REPEATER BIT(6) ++#define SP_RE_AUTH BIT(5) ++#define SP_SW_AUTH_OK BIT(4) ++#define SP_HARD_AUTH_EN BIT(3) ++#define SP_HDCP_ENC_EN BIT(2) ++#define SP_BKSV_SRM_PASS BIT(1) ++#define SP_KSVLIST_VLD BIT(0) ++/* HDCP Function Enabled */ ++#define SP_HDCP_FUNCTION_ENABLED (BIT(0) | BIT(1) | BIT(2) | BIT(3)) ++ ++/* HDCP Receiver BSTATUS Register 0 */ ++#define SP_HDCP_RX_BSTATUS0_REG 0x1b ++/* HDCP Receiver BSTATUS Register 1 */ ++#define SP_HDCP_RX_BSTATUS1_REG 0x1c ++ ++/* HDCP Embedded "Blue Screen" Content Registers */ ++#define SP_HDCP_VID0_BLUE_SCREEN_REG 0x2c ++#define SP_HDCP_VID1_BLUE_SCREEN_REG 0x2d ++#define SP_HDCP_VID2_BLUE_SCREEN_REG 0x2e ++ ++/* HDCP Wait R0 Timing Register */ ++#define SP_HDCP_WAIT_R0_TIME_REG 0x40 ++ ++/* HDCP Link Integrity Check Timer Register */ ++#define SP_HDCP_LINK_CHECK_TIMER_REG 0x41 ++ ++/* HDCP Repeater Ready Wait Timer Register */ ++#define SP_HDCP_RPTR_RDY_WAIT_TIME_REG 0x42 ++ ++/* HDCP Auto Timer Register */ ++#define SP_HDCP_AUTO_TIMER_REG 0x51 ++ ++/* HDCP Key Status Register */ ++#define SP_HDCP_KEY_STATUS_REG 0x5e ++ ++/* HDCP Key Command Register */ ++#define SP_HDCP_KEY_COMMAND_REG 0x5f ++#define SP_DISABLE_SYNC_HDCP BIT(2) ++ ++/* OTP Memory Key Protection Registers */ ++#define SP_OTP_KEY_PROTECT1_REG 0x60 ++#define SP_OTP_KEY_PROTECT2_REG 0x61 ++#define SP_OTP_KEY_PROTECT3_REG 0x62 ++#define SP_OTP_PSW1 0xa2 ++#define SP_OTP_PSW2 0x7e ++#define SP_OTP_PSW3 0xc6 ++ ++/* DP System Control Registers */ ++#define SP_DP_SYSTEM_CTRL_BASE (0x80 - 1) ++/* Bits for DP System Control Register 2 */ ++#define SP_CHA_STA BIT(2) ++/* Bits for DP System Control Register 3 */ ++#define SP_HPD_STATUS BIT(6) ++#define SP_STRM_VALID BIT(2) ++/* Bits for DP System Control Register 4 */ ++#define SP_ENHANCED_MODE BIT(3) ++ ++/* DP Video Control Register */ ++#define SP_DP_VIDEO_CTRL_REG 0x84 ++#define SP_COLOR_F_MASK 0x06 ++#define SP_COLOR_F_SHIFT 1 ++#define SP_BPC_MASK 0xe0 ++#define SP_BPC_SHIFT 5 ++# define SP_BPC_6BITS 0x00 ++# define SP_BPC_8BITS 0x01 ++# define SP_BPC_10BITS 0x02 ++# define SP_BPC_12BITS 0x03 ++ ++/* DP Audio Control Register */ ++#define SP_DP_AUDIO_CTRL_REG 0x87 ++#define SP_AUD_EN BIT(0) ++ ++/* 10us Pulse Generate Timer Registers */ ++#define SP_I2C_GEN_10US_TIMER0_REG 0x88 ++#define SP_I2C_GEN_10US_TIMER1_REG 0x89 ++ ++/* Packet Send Control Register */ ++#define SP_PACKET_SEND_CTRL_REG 0x90 ++#define SP_AUD_IF_UP BIT(7) ++#define SP_AVI_IF_UD BIT(6) ++#define SP_MPEG_IF_UD BIT(5) ++#define SP_SPD_IF_UD BIT(4) ++#define SP_AUD_IF_EN BIT(3) ++#define SP_AVI_IF_EN BIT(2) ++#define SP_MPEG_IF_EN BIT(1) ++#define SP_SPD_IF_EN BIT(0) ++ ++/* DP HDCP Control Register */ ++#define SP_DP_HDCP_CTRL_REG 0x92 ++#define SP_AUTO_EN BIT(7) ++#define SP_AUTO_START BIT(5) ++#define SP_LINK_POLLING BIT(1) ++ ++/* DP Main Link Bandwidth Setting Register */ ++#define SP_DP_MAIN_LINK_BW_SET_REG 0xa0 ++#define SP_LINK_BW_SET_MASK 0x1f ++#define SP_INITIAL_SLIM_M_AUD_SEL BIT(5) ++ ++/* DP Training Pattern Set Register */ ++#define SP_DP_TRAINING_PATTERN_SET_REG 0xa2 ++ ++/* DP Lane 0 Link Training Control Register */ ++#define SP_DP_LANE0_LT_CTRL_REG 0xa3 ++#define SP_TX_SW_SET_MASK 0x1b ++#define SP_MAX_PRE_REACH BIT(5) ++#define SP_MAX_DRIVE_REACH BIT(4) ++#define SP_PRE_EMP_LEVEL1 BIT(3) ++#define SP_DRVIE_CURRENT_LEVEL1 BIT(0) ++ ++/* DP Link Training Control Register */ ++#define SP_DP_LT_CTRL_REG 0xa8 ++#define SP_LT_ERROR_TYPE_MASK 0x70 ++# define SP_LT_NO_ERROR 0x00 ++# define SP_LT_AUX_WRITE_ERROR 0x01 ++# define SP_LT_MAX_DRIVE_REACHED 0x02 ++# define SP_LT_WRONG_LANE_COUNT_SET 0x03 ++# define SP_LT_LOOP_SAME_5_TIME 0x04 ++# define SP_LT_CR_FAIL_IN_EQ 0x05 ++# define SP_LT_EQ_LOOP_5_TIME 0x06 ++#define SP_LT_EN BIT(0) ++ ++/* DP CEP Training Control Registers */ ++#define SP_DP_CEP_TRAINING_CTRL0_REG 0xa9 ++#define SP_DP_CEP_TRAINING_CTRL1_REG 0xaa ++ ++/* DP Debug Register 1 */ ++#define SP_DP_DEBUG1_REG 0xb0 ++#define SP_DEBUG_PLL_LOCK BIT(4) ++#define SP_POLLING_EN BIT(1) ++ ++/* DP Polling Control Register */ ++#define SP_DP_POLLING_CTRL_REG 0xb4 ++#define SP_AUTO_POLLING_DISABLE BIT(0) ++ ++/* DP Link Debug Control Register */ ++#define SP_DP_LINK_DEBUG_CTRL_REG 0xb8 ++#define SP_M_VID_DEBUG BIT(5) ++#define SP_NEW_PRBS7 BIT(4) ++#define SP_INSERT_ER BIT(1) ++#define SP_PRBS31_EN BIT(0) ++ ++/* AUX Misc control Register */ ++#define SP_AUX_MISC_CTRL_REG 0xbf ++ ++/* DP PLL control Register */ ++#define SP_DP_PLL_CTRL_REG 0xc7 ++#define SP_PLL_RST BIT(6) ++ ++/* DP Analog Power Down Register */ ++#define SP_DP_ANALOG_POWER_DOWN_REG 0xc8 ++#define SP_CH0_PD BIT(0) ++ ++/* DP Misc Control Register */ ++#define SP_DP_MISC_CTRL_REG 0xcd ++#define SP_EQ_TRAINING_LOOP BIT(6) ++ ++/* DP Extra I2C Device Address Register */ ++#define SP_DP_EXTRA_I2C_DEV_ADDR_REG 0xce ++#define SP_I2C_STRETCH_DISABLE BIT(7) ++ ++#define SP_I2C_EXTRA_ADDR 0x50 ++ ++/* DP Downspread Control Register 1 */ ++#define SP_DP_DOWNSPREAD_CTRL1_REG 0xd0 ++ ++/* DP M Value Calculation Control Register */ ++#define SP_DP_M_CALCULATION_CTRL_REG 0xd9 ++#define SP_M_GEN_CLK_SEL BIT(0) ++ ++/* AUX Channel Access Status Register */ ++#define SP_AUX_CH_STATUS_REG 0xe0 ++#define SP_AUX_STATUS 0x0f ++ ++/* AUX Channel DEFER Control Register */ ++#define SP_AUX_DEFER_CTRL_REG 0xe2 ++#define SP_DEFER_CTRL_EN BIT(7) ++ ++/* DP Buffer Data Count Register */ ++#define SP_BUF_DATA_COUNT_REG 0xe4 ++#define SP_BUF_DATA_COUNT_MASK 0x1f ++#define SP_BUF_CLR BIT(7) ++ ++/* DP AUX Channel Control Register 1 */ ++#define SP_DP_AUX_CH_CTRL1_REG 0xe5 ++#define SP_AUX_TX_COMM_MASK 0x0f ++#define SP_AUX_LENGTH_MASK 0xf0 ++#define SP_AUX_LENGTH_SHIFT 4 ++ ++/* DP AUX CH Address Register 0 */ ++#define SP_AUX_ADDR_7_0_REG 0xe6 ++ ++/* DP AUX CH Address Register 1 */ ++#define SP_AUX_ADDR_15_8_REG 0xe7 ++ ++/* DP AUX CH Address Register 2 */ ++#define SP_AUX_ADDR_19_16_REG 0xe8 ++#define SP_AUX_ADDR_19_16_MASK 0x0f ++ ++/* DP AUX Channel Control Register 2 */ ++#define SP_DP_AUX_CH_CTRL2_REG 0xe9 ++#define SP_AUX_SEL_RXCM BIT(6) ++#define SP_AUX_CHSEL BIT(3) ++#define SP_AUX_PN_INV BIT(2) ++#define SP_ADDR_ONLY BIT(1) ++#define SP_AUX_EN BIT(0) ++ ++/* DP Video Stream Control InfoFrame Register */ ++#define SP_DP_3D_VSC_CTRL_REG 0xea ++#define SP_INFO_FRAME_VSC_EN BIT(0) ++ ++/* DP Video Stream Data Byte 1 Register */ ++#define SP_DP_VSC_DB1_REG 0xeb ++ ++/* DP AUX Channel Control Register 3 */ ++#define SP_DP_AUX_CH_CTRL3_REG 0xec ++#define SP_WAIT_COUNTER_7_0_MASK 0xff ++ ++/* DP AUX Channel Control Register 4 */ ++#define SP_DP_AUX_CH_CTRL4_REG 0xed ++ ++/* DP AUX Buffer Data Registers */ ++#define SP_DP_BUF_DATA0_REG 0xf0 ++ ++#endif +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h b/drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h +new file mode 100644 +index 000000000000..7d683573e970 +--- /dev/null ++++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h +@@ -0,0 +1,237 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright(c) 2017 Icenowy Zheng ++ * ++ * Based on analogix-anx78xx.h, which is: ++ * Copyright(c) 2016, Analogix Semiconductor. All rights reserved. ++ */ ++ ++#ifndef _ANALOGIX_I2C_TXCOMMON_H_ ++#define _ANALOGIX_I2C_TXCOMMON_H_ ++ ++#define ANALOGIX_I2C_TXCOMMON 0x72 ++ ++/***************************************************************/ ++/* Register definition of device address 0x72 */ ++/***************************************************************/ ++ ++/* ++ * Core Register Definitions ++ */ ++ ++/* Device ID Low Byte Register */ ++#define SP_DEVICE_IDL_REG 0x02 ++ ++/* Device ID High Byte Register */ ++#define SP_DEVICE_IDH_REG 0x03 ++ ++/* Device version register */ ++#define SP_DEVICE_VERSION_REG 0x04 ++ ++/* Power Down Control Register */ ++#define SP_POWERDOWN_CTRL_REG 0x05 ++#define SP_REGISTER_PD BIT(7) ++#define SP_HDCP_PD BIT(5) ++#define SP_AUDIO_PD BIT(4) ++#define SP_VIDEO_PD BIT(3) ++#define SP_LINK_PD BIT(2) ++#define SP_TOTAL_PD BIT(1) ++ ++/* Reset Control Register 1 */ ++#define SP_RESET_CTRL1_REG 0x06 ++#define SP_MISC_RST BIT(7) ++#define SP_VIDCAP_RST BIT(6) ++#define SP_VIDFIF_RST BIT(5) ++#define SP_AUDFIF_RST BIT(4) ++#define SP_AUDCAP_RST BIT(3) ++#define SP_HDCP_RST BIT(2) ++#define SP_SW_RST BIT(1) ++#define SP_HW_RST BIT(0) ++ ++/* Reset Control Register 2 */ ++#define SP_RESET_CTRL2_REG 0x07 ++#define SP_AUX_RST BIT(2) ++#define SP_SERDES_FIFO_RST BIT(1) ++#define SP_I2C_REG_RST BIT(0) ++ ++/* Video Control Register 1 */ ++#define SP_VID_CTRL1_REG 0x08 ++#define SP_VIDEO_EN BIT(7) ++#define SP_VIDEO_MUTE BIT(2) ++#define SP_DE_GEN BIT(1) ++#define SP_DEMUX BIT(0) ++ ++/* Video Control Register 2 */ ++#define SP_VID_CTRL2_REG 0x09 ++#define SP_IN_COLOR_F_MASK 0x03 ++#define SP_IN_YC_BIT_SEL BIT(2) ++#define SP_IN_BPC_MASK 0x70 ++#define SP_IN_BPC_SHIFT 4 ++# define SP_IN_BPC_12BIT 0x03 ++# define SP_IN_BPC_10BIT 0x02 ++# define SP_IN_BPC_8BIT 0x01 ++# define SP_IN_BPC_6BIT 0x00 ++#define SP_IN_D_RANGE BIT(7) ++ ++/* Video Control Register 3 */ ++#define SP_VID_CTRL3_REG 0x0a ++#define SP_HPD_OUT BIT(6) ++ ++/* Video Control Register 5 */ ++#define SP_VID_CTRL5_REG 0x0c ++#define SP_CSC_STD_SEL BIT(7) ++#define SP_XVYCC_RNG_LMT BIT(6) ++#define SP_RANGE_Y2R BIT(5) ++#define SP_CSPACE_Y2R BIT(4) ++#define SP_RGB_RNG_LMT BIT(3) ++#define SP_Y_RNG_LMT BIT(2) ++#define SP_RANGE_R2Y BIT(1) ++#define SP_CSPACE_R2Y BIT(0) ++ ++/* Video Control Register 6 */ ++#define SP_VID_CTRL6_REG 0x0d ++#define SP_TEST_PATTERN_EN BIT(7) ++#define SP_VIDEO_PROCESS_EN BIT(6) ++#define SP_VID_US_MODE BIT(3) ++#define SP_VID_DS_MODE BIT(2) ++#define SP_UP_SAMPLE BIT(1) ++#define SP_DOWN_SAMPLE BIT(0) ++ ++/* Video Control Register 8 */ ++#define SP_VID_CTRL8_REG 0x0f ++#define SP_VID_VRES_TH BIT(0) ++ ++/* Total Line Status Low Byte Register */ ++#define SP_TOTAL_LINE_STAL_REG 0x24 ++ ++/* Total Line Status High Byte Register */ ++#define SP_TOTAL_LINE_STAH_REG 0x25 ++ ++/* Active Line Status Low Byte Register */ ++#define SP_ACT_LINE_STAL_REG 0x26 ++ ++/* Active Line Status High Byte Register */ ++#define SP_ACT_LINE_STAH_REG 0x27 ++ ++/* Vertical Front Porch Status Register */ ++#define SP_V_F_PORCH_STA_REG 0x28 ++ ++/* Vertical SYNC Width Status Register */ ++#define SP_V_SYNC_STA_REG 0x29 ++ ++/* Vertical Back Porch Status Register */ ++#define SP_V_B_PORCH_STA_REG 0x2a ++ ++/* Total Pixel Status Low Byte Register */ ++#define SP_TOTAL_PIXEL_STAL_REG 0x2b ++ ++/* Total Pixel Status High Byte Register */ ++#define SP_TOTAL_PIXEL_STAH_REG 0x2c ++ ++/* Active Pixel Status Low Byte Register */ ++#define SP_ACT_PIXEL_STAL_REG 0x2d ++ ++/* Active Pixel Status High Byte Register */ ++#define SP_ACT_PIXEL_STAH_REG 0x2e ++ ++/* Horizontal Front Porch Status Low Byte Register */ ++#define SP_H_F_PORCH_STAL_REG 0x2f ++ ++/* Horizontal Front Porch Statys High Byte Register */ ++#define SP_H_F_PORCH_STAH_REG 0x30 ++ ++/* Horizontal SYNC Width Status Low Byte Register */ ++#define SP_H_SYNC_STAL_REG 0x31 ++ ++/* Horizontal SYNC Width Status High Byte Register */ ++#define SP_H_SYNC_STAH_REG 0x32 ++ ++/* Horizontal Back Porch Status Low Byte Register */ ++#define SP_H_B_PORCH_STAL_REG 0x33 ++ ++/* Horizontal Back Porch Status High Byte Register */ ++#define SP_H_B_PORCH_STAH_REG 0x34 ++ ++/* InfoFrame AVI Packet DB1 Register */ ++#define SP_INFOFRAME_AVI_DB1_REG 0x70 ++ ++/* Bit Control Specific Register */ ++#define SP_BIT_CTRL_SPECIFIC_REG 0x80 ++#define SP_BIT_CTRL_SELECT_SHIFT 1 ++#define SP_ENABLE_BIT_CTRL BIT(0) ++ ++/* InfoFrame Audio Packet DB1 Register */ ++#define SP_INFOFRAME_AUD_DB1_REG 0x83 ++ ++/* InfoFrame MPEG Packet DB1 Register */ ++#define SP_INFOFRAME_MPEG_DB1_REG 0xb0 ++ ++/* Audio Channel Status Registers */ ++#define SP_AUD_CH_STATUS_BASE 0xd0 ++ ++/* Audio Channel Num Register 5 */ ++#define SP_I2S_CHANNEL_NUM_MASK 0xe0 ++# define SP_I2S_CH_NUM_1 (0x00 << 5) ++# define SP_I2S_CH_NUM_2 (0x01 << 5) ++# define SP_I2S_CH_NUM_3 (0x02 << 5) ++# define SP_I2S_CH_NUM_4 (0x03 << 5) ++# define SP_I2S_CH_NUM_5 (0x04 << 5) ++# define SP_I2S_CH_NUM_6 (0x05 << 5) ++# define SP_I2S_CH_NUM_7 (0x06 << 5) ++# define SP_I2S_CH_NUM_8 (0x07 << 5) ++#define SP_EXT_VUCP BIT(2) ++#define SP_VBIT BIT(1) ++#define SP_AUDIO_LAYOUT BIT(0) ++ ++/* Analog Debug Register 2 */ ++#define SP_ANALOG_DEBUG2_REG 0xdd ++#define SP_FORCE_SW_OFF_BYPASS 0x20 ++#define SP_XTAL_FRQ 0x1c ++# define SP_XTAL_FRQ_19M2 (0x00 << 2) ++# define SP_XTAL_FRQ_24M (0x01 << 2) ++# define SP_XTAL_FRQ_25M (0x02 << 2) ++# define SP_XTAL_FRQ_26M (0x03 << 2) ++# define SP_XTAL_FRQ_27M (0x04 << 2) ++# define SP_XTAL_FRQ_38M4 (0x05 << 2) ++# define SP_XTAL_FRQ_52M (0x06 << 2) ++#define SP_POWERON_TIME_1P5MS 0x03 ++ ++/* Analog Control 0 Register */ ++#define SP_ANALOG_CTRL0_REG 0xe1 ++ ++/* Common Interrupt Status Register 1 */ ++#define SP_COMMON_INT_STATUS_BASE (0xf1 - 1) ++#define SP_PLL_LOCK_CHG 0x40 ++ ++/* Common Interrupt Status Register 2 */ ++#define SP_COMMON_INT_STATUS2 0xf2 ++#define SP_HDCP_AUTH_CHG BIT(1) ++#define SP_HDCP_AUTH_DONE BIT(0) ++ ++#define SP_HDCP_LINK_CHECK_FAIL BIT(0) ++ ++/* Common Interrupt Status Register 4 */ ++#define SP_COMMON_INT_STATUS4_REG 0xf4 ++#define SP_HPD_IRQ BIT(6) ++#define SP_HPD_ESYNC_ERR BIT(4) ++#define SP_HPD_CHG BIT(2) ++#define SP_HPD_LOST BIT(1) ++#define SP_HPD_PLUG BIT(0) ++ ++/* DP Interrupt Status Register */ ++#define SP_DP_INT_STATUS1_REG 0xf7 ++#define SP_TRAINING_FINISH BIT(5) ++#define SP_POLLING_ERR BIT(4) ++ ++/* Common Interrupt Mask Register */ ++#define SP_COMMON_INT_MASK_BASE (0xf8 - 1) ++ ++#define SP_COMMON_INT_MASK4_REG 0xfb ++ ++/* DP Interrupts Mask Register */ ++#define SP_DP_INT_MASK1_REG 0xfe ++ ++/* Interrupt Control Register */ ++#define SP_INT_CTRL_REG 0xff ++ ++#endif /* _ANALOGIX_I2C_TXCOMMON_H_ */ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0128-drm-bridge-extract-some-Analogix-I2C-DP-common-code.patch b/patch/kernel/sunxi-dev/0128-drm-bridge-extract-some-Analogix-I2C-DP-common-code.patch new file mode 100644 index 000000000..08c54137b --- /dev/null +++ b/patch/kernel/sunxi-dev/0128-drm-bridge-extract-some-Analogix-I2C-DP-common-code.patch @@ -0,0 +1,403 @@ +From d1f75332d44f26e734985493c134a727c79cb1f1 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:21 +0800 +Subject: [PATCH 128/146] drm/bridge: extract some Analogix I2C DP common code + +Some code can be shared within different DP bridges by Analogix. + +Extract them to a new module. + +Signed-off-by: Icenowy Zheng +--- + drivers/gpu/drm/bridge/analogix/Kconfig | 4 + + drivers/gpu/drm/bridge/analogix/Makefile | 2 + + .../drm/bridge/analogix/analogix-anx78xx.c | 146 +-------------- + .../drm/bridge/analogix/analogix-i2c-dptx.c | 169 ++++++++++++++++++ + .../drm/bridge/analogix/analogix-i2c-dptx.h | 2 + + 5 files changed, 178 insertions(+), 145 deletions(-) + create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c + +diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig +index 27b37aa2ea77..eb893b465dd8 100644 +--- a/drivers/gpu/drm/bridge/analogix/Kconfig ++++ b/drivers/gpu/drm/bridge/analogix/Kconfig +@@ -2,8 +2,12 @@ config DRM_ANALOGIX_DP + tristate + depends on DRM + ++config DRM_ANALOGIX_DP_I2C ++ tristate ++ + config DRM_ANALOGIX_ANX78XX + tristate "Analogix ANX78XX bridge" ++ select DRM_ANALOGIX_DP_I2C + select DRM_KMS_HELPER + select REGMAP_I2C + ---help--- +diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile +index eb41be845055..c37e2ded8ce3 100644 +--- a/drivers/gpu/drm/bridge/analogix/Makefile ++++ b/drivers/gpu/drm/bridge/analogix/Makefile +@@ -1,3 +1,5 @@ + analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o ++analogix_dp_i2c-objs := analogix-i2c-dptx.o + obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o ++obj-$(CONFIG_DRM_ANALOGIX_DP_I2C) += analogix_dp_i2c.o + obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +index f8433c93f463..bf8291d0ddd0 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +@@ -45,8 +45,6 @@ + #define I2C_IDX_RX_P1 4 + + #define XTAL_CLK 270 /* 27M */ +-#define AUX_CH_BUFFER_SIZE 16 +-#define AUX_WAIT_TIMEOUT_MS 15 + + static const u8 anx78xx_i2c_addresses[] = { + [I2C_IDX_TX_P0] = TX_P0, +@@ -109,153 +107,11 @@ static int anx78xx_clear_bits(struct regmap *map, u8 reg, u8 mask) + return regmap_update_bits(map, reg, mask, 0); + } + +-static bool anx78xx_aux_op_finished(struct anx78xx *anx78xx) +-{ +- unsigned int value; +- int err; +- +- err = regmap_read(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL2_REG, +- &value); +- if (err < 0) +- return false; +- +- return (value & SP_AUX_EN) == 0; +-} +- +-static int anx78xx_aux_wait(struct anx78xx *anx78xx) +-{ +- unsigned long timeout; +- unsigned int status; +- int err; +- +- timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1; +- +- while (!anx78xx_aux_op_finished(anx78xx)) { +- if (time_after(jiffies, timeout)) { +- if (!anx78xx_aux_op_finished(anx78xx)) { +- DRM_ERROR("Timed out waiting AUX to finish\n"); +- return -ETIMEDOUT; +- } +- +- break; +- } +- +- usleep_range(1000, 2000); +- } +- +- /* Read the AUX channel access status */ +- err = regmap_read(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_CH_STATUS_REG, +- &status); +- if (err < 0) { +- DRM_ERROR("Failed to read from AUX channel: %d\n", err); +- return err; +- } +- +- if (status & SP_AUX_STATUS) { +- DRM_ERROR("Failed to wait for AUX channel (status: %02x)\n", +- status); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +- +-static int anx78xx_aux_address(struct anx78xx *anx78xx, unsigned int addr) +-{ +- int err; +- +- err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_ADDR_7_0_REG, +- addr & 0xff); +- if (err) +- return err; +- +- err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_ADDR_15_8_REG, +- (addr & 0xff00) >> 8); +- if (err) +- return err; +- +- /* +- * DP AUX CH Address Register #2, only update bits[3:0] +- * [7:4] RESERVED +- * [3:0] AUX_ADDR[19:16], Register control AUX CH address. +- */ +- err = regmap_update_bits(anx78xx->map[I2C_IDX_TX_P0], +- SP_AUX_ADDR_19_16_REG, +- SP_AUX_ADDR_19_16_MASK, +- (addr & 0xf0000) >> 16); +- +- if (err) +- return err; +- +- return 0; +-} +- + static ssize_t anx78xx_aux_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) + { + struct anx78xx *anx78xx = container_of(aux, struct anx78xx, aux); +- u8 ctrl1 = msg->request; +- u8 ctrl2 = SP_AUX_EN; +- u8 *buffer = msg->buffer; +- int err; +- +- /* The DP AUX transmit and receive buffer has 16 bytes. */ +- if (WARN_ON(msg->size > AUX_CH_BUFFER_SIZE)) +- return -E2BIG; +- +- /* Zero-sized messages specify address-only transactions. */ +- if (msg->size < 1) +- ctrl2 |= SP_ADDR_ONLY; +- else /* For non-zero-sized set the length field. */ +- ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT; +- +- if ((msg->request & DP_AUX_I2C_READ) == 0) { +- /* When WRITE | MOT write values to data buffer */ +- err = regmap_bulk_write(anx78xx->map[I2C_IDX_TX_P0], +- SP_DP_BUF_DATA0_REG, buffer, +- msg->size); +- if (err) +- return err; +- } +- +- /* Write address and request */ +- err = anx78xx_aux_address(anx78xx, msg->address); +- if (err) +- return err; +- +- err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL1_REG, +- ctrl1); +- if (err) +- return err; +- +- /* Start transaction */ +- err = regmap_update_bits(anx78xx->map[I2C_IDX_TX_P0], +- SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY | +- SP_AUX_EN, ctrl2); +- if (err) +- return err; +- +- err = anx78xx_aux_wait(anx78xx); +- if (err) +- return err; +- +- msg->reply = DP_AUX_I2C_REPLY_ACK; +- +- if ((msg->size > 0) && (msg->request & DP_AUX_I2C_READ)) { +- /* Read values from data buffer */ +- err = regmap_bulk_read(anx78xx->map[I2C_IDX_TX_P0], +- SP_DP_BUF_DATA0_REG, buffer, +- msg->size); +- if (err) +- return err; +- } +- +- err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P0], +- SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY); +- if (err) +- return err; +- +- return msg->size; ++ return anx_aux_transfer(anx78xx->map[I2C_IDX_TX_P0], msg); + } + + static int anx78xx_set_hpd(struct anx78xx *anx78xx) +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c +new file mode 100644 +index 000000000000..9cb30962032e +--- /dev/null ++++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c +@@ -0,0 +1,169 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright(c) 2017 Icenowy Zheng ++ * ++ * Based on analogix-anx78xx.c, which is: ++ * Copyright(c) 2016, Analogix Semiconductor. All rights reserved. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "analogix-i2c-dptx.h" ++ ++#define AUX_WAIT_TIMEOUT_MS 15 ++#define AUX_CH_BUFFER_SIZE 16 ++ ++static int anx_clear_bits(struct regmap *map, u8 reg, u8 mask) ++{ ++ return regmap_update_bits(map, reg, mask, 0); ++} ++ ++static bool anx_aux_op_finished(struct regmap *map_dptx) ++{ ++ unsigned int value; ++ int err; ++ ++ err = regmap_read(map_dptx, SP_DP_AUX_CH_CTRL2_REG, &value); ++ if (err < 0) ++ return false; ++ ++ return (value & SP_AUX_EN) == 0; ++} ++ ++static int anx_aux_wait(struct regmap *map_dptx) ++{ ++ unsigned long timeout; ++ unsigned int status; ++ int err; ++ ++ timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1; ++ ++ while (!anx_aux_op_finished(map_dptx)) { ++ if (time_after(jiffies, timeout)) { ++ if (!anx_aux_op_finished(map_dptx)) { ++ DRM_ERROR("Timed out waiting AUX to finish\n"); ++ return -ETIMEDOUT; ++ } ++ ++ break; ++ } ++ ++ usleep_range(1000, 2000); ++ } ++ ++ /* Read the AUX channel access status */ ++ err = regmap_read(map_dptx, SP_AUX_CH_STATUS_REG, &status); ++ if (err < 0) { ++ DRM_ERROR("Failed to read from AUX channel: %d\n", err); ++ return err; ++ } ++ ++ if (status & SP_AUX_STATUS) { ++ DRM_ERROR("Failed to wait for AUX channel (status: %02x)\n", ++ status); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int anx_aux_address(struct regmap *map_dptx, unsigned int addr) ++{ ++ int err; ++ ++ err = regmap_write(map_dptx, SP_AUX_ADDR_7_0_REG, addr & 0xff); ++ if (err) ++ return err; ++ ++ err = regmap_write(map_dptx, SP_AUX_ADDR_15_8_REG, ++ (addr & 0xff00) >> 8); ++ if (err) ++ return err; ++ ++ /* ++ * DP AUX CH Address Register #2, only update bits[3:0] ++ * [7:4] RESERVED ++ * [3:0] AUX_ADDR[19:16], Register control AUX CH address. ++ */ ++ err = regmap_update_bits(map_dptx, SP_AUX_ADDR_19_16_REG, ++ SP_AUX_ADDR_19_16_MASK, ++ (addr & 0xf0000) >> 16); ++ ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++ssize_t anx_aux_transfer(struct regmap *map_dptx, struct drm_dp_aux_msg *msg) ++{ ++ u8 ctrl1 = msg->request; ++ u8 ctrl2 = SP_AUX_EN; ++ u8 *buffer = msg->buffer; ++ int err; ++ ++ /* The DP AUX transmit and receive buffer has 16 bytes. */ ++ if (WARN_ON(msg->size > AUX_CH_BUFFER_SIZE)) ++ return -E2BIG; ++ ++ /* Zero-sized messages specify address-only transactions. */ ++ if (msg->size < 1) ++ ctrl2 |= SP_ADDR_ONLY; ++ else /* For non-zero-sized set the length field. */ ++ ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT; ++ ++ if ((msg->request & DP_AUX_I2C_READ) == 0) { ++ /* When WRITE | MOT write values to data buffer */ ++ err = regmap_bulk_write(map_dptx, ++ SP_DP_BUF_DATA0_REG, buffer, ++ msg->size); ++ if (err) ++ return err; ++ } ++ ++ /* Write address and request */ ++ err = anx_aux_address(map_dptx, msg->address); ++ if (err) ++ return err; ++ ++ err = regmap_write(map_dptx, SP_DP_AUX_CH_CTRL1_REG, ctrl1); ++ if (err) ++ return err; ++ ++ /* Start transaction */ ++ err = regmap_update_bits(map_dptx, SP_DP_AUX_CH_CTRL2_REG, ++ SP_ADDR_ONLY | SP_AUX_EN, ctrl2); ++ if (err) ++ return err; ++ ++ err = anx_aux_wait(map_dptx); ++ if (err) ++ return err; ++ ++ msg->reply = DP_AUX_I2C_REPLY_ACK; ++ ++ if ((msg->size > 0) && (msg->request & DP_AUX_I2C_READ)) { ++ /* Read values from data buffer */ ++ err = regmap_bulk_read(map_dptx, ++ SP_DP_BUF_DATA0_REG, buffer, ++ msg->size); ++ if (err) ++ return err; ++ } ++ ++ err = anx_clear_bits(map_dptx, SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY); ++ if (err) ++ return err; ++ ++ return msg->size; ++} ++EXPORT_SYMBOL(anx_aux_transfer); ++ ++MODULE_DESCRIPTION("Analogix DisplayPort Transmitter common code"); ++MODULE_AUTHOR("Icenowy Zheng "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h +index bc0831b127bf..c2ca854613a0 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h ++++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h +@@ -245,4 +245,6 @@ + /* DP AUX Buffer Data Registers */ + #define SP_DP_BUF_DATA0_REG 0xf0 + ++ssize_t anx_aux_transfer(struct regmap *map_dptx, struct drm_dp_aux_msg *msg); ++ + #endif +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0129-dt-bindings-Add-ANX6345-DP-eDP-transmitter-binding.patch b/patch/kernel/sunxi-dev/0129-dt-bindings-Add-ANX6345-DP-eDP-transmitter-binding.patch new file mode 100644 index 000000000..5e76ebfb8 --- /dev/null +++ b/patch/kernel/sunxi-dev/0129-dt-bindings-Add-ANX6345-DP-eDP-transmitter-binding.patch @@ -0,0 +1,64 @@ +From db3c5b3983ab2395794ea3ebd5c73ab7b39d2caa Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:22 +0800 +Subject: [PATCH 129/146] dt-bindings: Add ANX6345 DP/eDP transmitter binding + +The ANX6345 is an ultra-low power DisplayPort/eDP transmitter designed +for portable devices. + +Add a binding document for it. + +Signed-off-by: Icenowy Zheng +--- + .../bindings/display/bridge/anx6345.txt | 39 +++++++++++++++++++ + 1 file changed, 39 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/bridge/anx6345.txt + +diff --git a/Documentation/devicetree/bindings/display/bridge/anx6345.txt b/Documentation/devicetree/bindings/display/bridge/anx6345.txt +new file mode 100644 +index 000000000000..0689d4eb5f65 +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/bridge/anx6345.txt +@@ -0,0 +1,39 @@ ++Analogix ANX6345 eDP Transmitter ++-------------------------------- ++ ++The ANX6345 is an ultra-low power Full-HD eDP transmitter designed for ++portable devices. ++ ++Required properties: ++ ++ - compatible : "analogix,anx6345" ++ - reg : I2C address of the device ++ - reset-gpios : Which GPIO to use for reset ++ ++Optional properties: ++ ++ - dvdd12-supply : Regulator for 1.2V digital core power. ++ - dvdd25-supply : Regulator for 2.5V digital core power. ++ - panel-supply : Regulator for the power of the panel. ++ - edid : verbatim EDID data block describing attached ++ panel, only used when the panel has no EDID info. ++ - Video port for RGB input, using the DT bindings defined in [1]. ++ ++[1]: Documentation/devicetree/bindings/media/video-interfaces.txt ++ ++Example: ++ ++anx6345: anx6345@38 { ++ compatible = "analogix,anx6345"; ++ reg = <0x38>; ++ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */ ++ panel-supply = <®_dc1sw>; ++ dvdd25-supply = <®_dldo2>; ++ dvdd12-supply = <®_fldo1>; ++ ++ port { ++ anx6345_in: endpoint { ++ remote-endpoint = <&tcon0_out_anx6345>; ++ }; ++ }; ++}; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0130-drm-bridge-Add-Analogix-anx6345-support.patch b/patch/kernel/sunxi-dev/0130-drm-bridge-Add-Analogix-anx6345-support.patch new file mode 100644 index 000000000..208115606 --- /dev/null +++ b/patch/kernel/sunxi-dev/0130-drm-bridge-Add-Analogix-anx6345-support.patch @@ -0,0 +1,981 @@ +From 2da065ab8aa3f562a02dfd3df4ad971d1229b136 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:23 +0800 +Subject: [PATCH 130/146] drm/bridge: Add Analogix anx6345 support + +The ANX6345 is an ultra-low power DisplayPower/eDP transmitter designed +for portable devices. This driver adds initial support for RGB to eDP +mode, without HPD and interrupts, but with possibility to inject EDID. +This is a configuration usually seen in eDP applications. + +Signed-off-by: Icenowy Zheng +--- + drivers/gpu/drm/bridge/analogix/Kconfig | 11 + + drivers/gpu/drm/bridge/analogix/Makefile | 1 + + .../drm/bridge/analogix/analogix-anx6345.c | 862 ++++++++++++++++++ + .../drm/bridge/analogix/analogix-i2c-dptx.c | 2 +- + .../drm/bridge/analogix/analogix-i2c-dptx.h | 8 + + .../bridge/analogix/analogix-i2c-txcommon.h | 3 + + 6 files changed, 886 insertions(+), 1 deletion(-) + create mode 100644 drivers/gpu/drm/bridge/analogix/analogix-anx6345.c + +diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig +index eb893b465dd8..784ddca83b47 100644 +--- a/drivers/gpu/drm/bridge/analogix/Kconfig ++++ b/drivers/gpu/drm/bridge/analogix/Kconfig +@@ -15,3 +15,14 @@ config DRM_ANALOGIX_ANX78XX + designed for portable devices. The ANX78XX transforms + the HDMI output of an application processor to MyDP + or DisplayPort. ++ ++config DRM_ANALOGIX_ANX6345 ++ tristate "Analogix ANX6345 bridge" ++ select DRM_ANALOGIX_DP_I2C ++ select DRM_KMS_HELPER ++ select REGMAP_I2C ++ help ++ ANX6345 is an ultra-low Full-HD DisplayPort/eDP ++ transmitter designed for portable devices. The ++ ANX6345 transforms the LVTTL RGB output of an ++ application processor to eDP or DisplayPort. +diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile +index c37e2ded8ce3..3af9feab6e17 100644 +--- a/drivers/gpu/drm/bridge/analogix/Makefile ++++ b/drivers/gpu/drm/bridge/analogix/Makefile +@@ -3,3 +3,4 @@ analogix_dp_i2c-objs := analogix-i2c-dptx.o + obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o + obj-$(CONFIG_DRM_ANALOGIX_DP_I2C) += analogix_dp_i2c.o + obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o ++obj-$(CONFIG_DRM_ANALOGIX_ANX6345) += analogix-anx6345.o +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +new file mode 100644 +index 000000000000..81676407aa6d +--- /dev/null ++++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +@@ -0,0 +1,862 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright(c) Icenowy Zheng ++ * Based on analogix-anx6345.c, which is: ++ * Copyright(c) 2016, Analogix Semiconductor. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "analogix-i2c-dptx.h" ++#include "analogix-i2c-txcommon.h" ++ ++#define I2C_NUM_ADDRESSES 2 ++#define I2C_IDX_DPTX 0 ++#define I2C_IDX_TXCOM 1 ++ ++#define XTAL_CLK 270 /* 27M */ ++ ++#define POLL_DELAY 50000 /* us */ ++#define POLL_TIMEOUT 5000000 /* us */ ++ ++static const u8 anx6345_i2c_addresses[] = { ++ [I2C_IDX_DPTX] = ANALOGIX_I2C_DPTX, ++ [I2C_IDX_TXCOM] = ANALOGIX_I2C_TXCOMMON, ++}; ++ ++struct anx6345_platform_data { ++ struct regulator *dvdd12; ++ struct regulator *dvdd25; ++ struct regulator *vcc_panel; ++ struct gpio_desc *gpiod_reset; ++}; ++ ++struct anx6345 { ++ struct drm_dp_aux aux; ++ struct drm_bridge bridge; ++ struct i2c_client *client; ++ struct edid *edid; ++ struct drm_connector connector; ++ struct drm_dp_link link; ++ struct anx6345_platform_data pdata; ++ struct mutex lock; ++ ++ /* ++ * I2C Slave addresses of ANX6345 are mapped as DPTX and SYS ++ */ ++ struct i2c_client *i2c_clients[I2C_NUM_ADDRESSES]; ++ struct regmap *map[I2C_NUM_ADDRESSES]; ++ ++ u16 chipid; ++ u8 dpcd[DP_RECEIVER_CAP_SIZE]; ++ ++ bool powered; ++}; ++ ++static inline struct anx6345 *connector_to_anx6345(struct drm_connector *c) ++{ ++ return container_of(c, struct anx6345, connector); ++} ++ ++static inline struct anx6345 *bridge_to_anx6345(struct drm_bridge *bridge) ++{ ++ return container_of(bridge, struct anx6345, bridge); ++} ++ ++static int anx6345_set_bits(struct regmap *map, u8 reg, u8 mask) ++{ ++ return regmap_update_bits(map, reg, mask, mask); ++} ++ ++static int anx6345_clear_bits(struct regmap *map, u8 reg, u8 mask) ++{ ++ return regmap_update_bits(map, reg, mask, 0); ++} ++ ++static ssize_t anx6345_aux_transfer(struct drm_dp_aux *aux, ++ struct drm_dp_aux_msg *msg) ++{ ++ struct anx6345 *anx6345 = container_of(aux, struct anx6345, aux); ++ ++ return anx_aux_transfer(anx6345->map[I2C_IDX_DPTX], msg); ++} ++ ++static int anx6345_dp_link_training(struct anx6345 *anx6345) ++{ ++ unsigned int value; ++ u8 dp_bw; ++ int err; ++ ++ err = anx6345_clear_bits(anx6345->map[I2C_IDX_TXCOM], ++ SP_POWERDOWN_CTRL_REG, ++ SP_TOTAL_PD); ++ if (err) ++ return err; ++ ++ err = drm_dp_dpcd_readb(&anx6345->aux, DP_MAX_LINK_RATE, &dp_bw); ++ if (err < 0) ++ return err; ++ ++ switch (dp_bw) { ++ case DP_LINK_BW_1_62: ++ case DP_LINK_BW_2_7: ++ break; ++ ++ default: ++ DRM_DEBUG_KMS("DP bandwidth (%#02x) not supported\n", dp_bw); ++ return -EINVAL; ++ } ++ ++ err = anx6345_set_bits(anx6345->map[I2C_IDX_TXCOM], SP_VID_CTRL1_REG, ++ SP_VIDEO_MUTE); ++ if (err) ++ return err; ++ ++ err = anx6345_clear_bits(anx6345->map[I2C_IDX_TXCOM], ++ SP_VID_CTRL1_REG, SP_VIDEO_EN); ++ if (err) ++ return err; ++ ++ /* Get DPCD info */ ++ err = drm_dp_dpcd_read(&anx6345->aux, DP_DPCD_REV, ++ &anx6345->dpcd, DP_RECEIVER_CAP_SIZE); ++ if (err < 0) { ++ DRM_ERROR("Failed to read DPCD: %d\n", err); ++ return err; ++ } ++ ++ /* Clear channel x SERDES power down */ ++ err = anx6345_clear_bits(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_ANALOG_POWER_DOWN_REG, SP_CH0_PD); ++ if (err) ++ return err; ++ ++ /* Check link capabilities */ ++ err = drm_dp_link_probe(&anx6345->aux, &anx6345->link); ++ if (err < 0) { ++ DRM_ERROR("Failed to probe link capabilities: %d\n", err); ++ return err; ++ } ++ ++ /* Power up the sink */ ++ err = drm_dp_link_power_up(&anx6345->aux, &anx6345->link); ++ if (err < 0) { ++ DRM_ERROR("Failed to power up DisplayPort link: %d\n", err); ++ return err; ++ } ++ ++ /* Possibly enable downspread on the sink */ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_DOWNSPREAD_CTRL1_REG, 0); ++ if (err) ++ return err; ++ ++ if (anx6345->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5) { ++ DRM_DEBUG("Enable downspread on the sink\n"); ++ /* 4000PPM */ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_DOWNSPREAD_CTRL1_REG, 8); ++ if (err) ++ return err; ++ ++ err = drm_dp_dpcd_writeb(&anx6345->aux, DP_DOWNSPREAD_CTRL, ++ DP_SPREAD_AMP_0_5); ++ if (err < 0) ++ return err; ++ } else { ++ err = drm_dp_dpcd_writeb(&anx6345->aux, DP_DOWNSPREAD_CTRL, 0); ++ if (err < 0) ++ return err; ++ } ++ ++ /* Set the lane count and the link rate on the sink */ ++ if (drm_dp_enhanced_frame_cap(anx6345->dpcd)) ++ err = anx6345_set_bits(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_SYSTEM_CTRL_BASE + 4, ++ SP_ENHANCED_MODE); ++ else ++ err = anx6345_clear_bits(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_SYSTEM_CTRL_BASE + 4, ++ SP_ENHANCED_MODE); ++ if (err) ++ return err; ++ ++ value = drm_dp_link_rate_to_bw_code(anx6345->link.rate); ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_MAIN_LINK_BW_SET_REG, value); ++ if (err) ++ return err; ++ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_LANE_COUNT_SET_REG, anx6345->link.num_lanes); ++ if (err) ++ return err; ++ ++ err = drm_dp_link_configure(&anx6345->aux, &anx6345->link); ++ if (err < 0) { ++ DRM_ERROR("Failed to configure DisplayPort link: %d\n", err); ++ return err; ++ } ++ ++ /* Start training on the source */ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], SP_DP_LT_CTRL_REG, ++ SP_LT_EN); ++ if (err) ++ return err; ++ ++ err = regmap_read_poll_timeout(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_LT_CTRL_REG, ++ value, !(value & SP_DP_LT_INPROGRESS), ++ POLL_DELAY, POLL_TIMEOUT); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static int anx6345_tx_initialization(struct anx6345 *anx6345) ++{ ++ int err, i; ++ ++ /* FIXME: hardcode color depth now */ ++ err = regmap_write(anx6345->map[I2C_IDX_TXCOM], SP_VID_CTRL2_REG, ++ SP_IN_BPC_6BIT << SP_IN_BPC_SHIFT); ++ if (err) ++ return err; ++ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], SP_DP_PLL_CTRL_REG, 0); ++ if (err) ++ return err; ++ ++ err = regmap_write(anx6345->map[I2C_IDX_TXCOM], ++ SP_ANALOG_DEBUG1_REG, 0); ++ if (err) ++ return err; ++ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_LINK_DEBUG_CTRL_REG, ++ SP_NEW_PRBS7 | SP_M_VID_DEBUG); ++ if (err) ++ return err; ++ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_ANALOG_POWER_DOWN_REG, 0); ++ if (err) ++ return err; ++ ++ /* Force HPD */ ++ err = anx6345_set_bits(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_SYSTEM_CTRL_BASE + 3, ++ SP_HPD_FORCE | SP_HPD_CTRL); ++ if (err) ++ return err; ++ ++ for (i = 0; i < 4; i++) { ++ /* 4 lanes */ ++ err = regmap_write(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_LANE0_LT_CTRL_REG + i, 0); ++ if (err) ++ return err; ++ } ++ ++ /* Reset AUX */ ++ err = anx6345_set_bits(anx6345->map[I2C_IDX_TXCOM], ++ SP_RESET_CTRL2_REG, SP_AUX_RST); ++ if (err) ++ return err; ++ ++ err = anx6345_clear_bits(anx6345->map[I2C_IDX_TXCOM], ++ SP_RESET_CTRL2_REG, SP_AUX_RST); ++ if (err) ++ return err; ++ ++ err = anx6345_dp_link_training(anx6345); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static void anx6345_poweron(struct anx6345 *anx6345) ++{ ++ struct anx6345_platform_data *pdata = &anx6345->pdata; ++ int err; ++ ++ if (WARN_ON(anx6345->powered)) ++ return; ++ ++ if (pdata->dvdd12) { ++ err = regulator_enable(pdata->dvdd12); ++ if (err) { ++ DRM_ERROR("Failed to enable DVDD12 regulator: %d\n", ++ err); ++ return; ++ } ++ ++ usleep_range(1000, 2000); ++ } ++ ++ if (pdata->dvdd25) { ++ err = regulator_enable(pdata->dvdd25); ++ if (err) { ++ DRM_ERROR("Failed to enable DVDD25 regulator: %d\n", ++ err); ++ return; ++ } ++ ++ usleep_range(5000, 10000); ++ } ++ ++ if (pdata->vcc_panel) { ++ err = regulator_enable(pdata->vcc_panel); ++ if (err) { ++ DRM_ERROR("Failed to enable panel regulator: %d\n", ++ err); ++ return; ++ } ++ } ++ ++ gpiod_set_value_cansleep(pdata->gpiod_reset, 0); ++ usleep_range(1000, 2000); ++ ++ gpiod_set_value_cansleep(pdata->gpiod_reset, 1); ++ ++ /* Power on registers module */ ++ anx6345_set_bits(anx6345->map[I2C_IDX_TXCOM], SP_POWERDOWN_CTRL_REG, ++ SP_HDCP_PD | SP_AUDIO_PD | SP_VIDEO_PD | SP_LINK_PD); ++ anx6345_clear_bits(anx6345->map[I2C_IDX_TXCOM], SP_POWERDOWN_CTRL_REG, ++ SP_REGISTER_PD | SP_TOTAL_PD); ++ ++ anx6345->powered = true; ++} ++ ++static void anx6345_poweroff(struct anx6345 *anx6345) ++{ ++ struct anx6345_platform_data *pdata = &anx6345->pdata; ++ int err; ++ ++ if (WARN_ON(!anx6345->powered)) ++ return; ++ ++ gpiod_set_value_cansleep(pdata->gpiod_reset, 1); ++ usleep_range(1000, 2000); ++ ++ if (pdata->vcc_panel) { ++ err = regulator_disable(pdata->vcc_panel); ++ if (err) { ++ DRM_ERROR("Failed to disable panel regulator: %d\n", ++ err); ++ return; ++ } ++ } ++ ++ if (pdata->dvdd25) { ++ err = regulator_disable(pdata->dvdd25); ++ if (err) { ++ DRM_ERROR("Failed to disable DVDD25 regulator: %d\n", ++ err); ++ return; ++ } ++ ++ usleep_range(5000, 10000); ++ } ++ ++ if (pdata->dvdd12) { ++ err = regulator_disable(pdata->dvdd12); ++ if (err) { ++ DRM_ERROR("Failed to disable DVDD12 regulator: %d\n", ++ err); ++ return; ++ } ++ ++ usleep_range(1000, 2000); ++ } ++ ++ anx6345->powered = false; ++} ++ ++static int anx6345_start(struct anx6345 *anx6345) ++{ ++ int err; ++ ++ if (!anx6345->powered) ++ anx6345_poweron(anx6345); ++ ++ /* Power on needed modules */ ++ err = anx6345_clear_bits(anx6345->map[I2C_IDX_TXCOM], ++ SP_POWERDOWN_CTRL_REG, ++ SP_VIDEO_PD | SP_LINK_PD); ++ ++ err = anx6345_tx_initialization(anx6345); ++ if (err) { ++ DRM_ERROR("Failed transmitter initialization: %d\n", err); ++ goto err_poweroff; ++ } ++ ++ /* ++ * This delay seems to help keep the hardware in a good state. Without ++ * it, there are times where it fails silently. ++ */ ++ usleep_range(10000, 15000); ++ ++ return 0; ++ ++err_poweroff: ++ DRM_ERROR("Failed DisplayPort transmitter initialization: %d\n", err); ++ anx6345_poweroff(anx6345); ++ ++ return err; ++} ++ ++static int anx6345_init_pdata(struct anx6345 *anx6345) ++{ ++ struct anx6345_platform_data *pdata = &anx6345->pdata; ++ struct device *dev = &anx6345->client->dev; ++ ++ /* 1.2V digital core power regulator */ ++ pdata->dvdd12 = devm_regulator_get(dev, "dvdd12"); ++ if (IS_ERR(pdata->dvdd12)) { ++ DRM_ERROR("DVDD12 regulator not found\n"); ++ return PTR_ERR(pdata->dvdd12); ++ } ++ ++ /* 2.5V digital core power regulator */ ++ pdata->dvdd25 = devm_regulator_get(dev, "dvdd25"); ++ if (IS_ERR(pdata->dvdd25)) { ++ DRM_ERROR("DVDD25 regulator not found\n"); ++ return PTR_ERR(pdata->dvdd25); ++ } ++ ++ /* panel power regulator */ ++ pdata->vcc_panel = devm_regulator_get(dev, "panel"); ++ if (IS_ERR(pdata->vcc_panel)) { ++ DRM_ERROR("panel regulator not found\n"); ++ return PTR_ERR(pdata->vcc_panel); ++ } ++ ++ /* GPIO for chip reset */ ++ pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); ++ ++ return PTR_ERR_OR_ZERO(pdata->gpiod_reset); ++} ++ ++static int anx6345_config_dp_output(struct anx6345 *anx6345) ++{ ++ int err; ++ ++ err = anx6345_clear_bits(anx6345->map[I2C_IDX_TXCOM], SP_VID_CTRL1_REG, ++ SP_VIDEO_MUTE); ++ if (err) ++ return err; ++ ++ /* Enable DP output */ ++ err = anx6345_set_bits(anx6345->map[I2C_IDX_TXCOM], SP_VID_CTRL1_REG, ++ SP_VIDEO_EN); ++ if (err) ++ return err; ++ ++ /* Force stream valid */ ++ err = anx6345_set_bits(anx6345->map[I2C_IDX_DPTX], ++ SP_DP_SYSTEM_CTRL_BASE + 3, ++ SP_STRM_FORCE | SP_STRM_CTRL); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static int anx6345_get_downstream_info(struct anx6345 *anx6345) ++{ ++ u8 value; ++ int err; ++ ++ err = drm_dp_dpcd_readb(&anx6345->aux, DP_SINK_COUNT, &value); ++ if (err < 0) { ++ DRM_ERROR("Get sink count failed %d\n", err); ++ return err; ++ } ++ ++ if (!DP_GET_SINK_COUNT(value)) { ++ DRM_ERROR("Downstream disconnected\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int anx6345_probe_edid_from_of(struct anx6345 *anx6345) ++{ ++ const u8 *edidp; ++ int len; ++ ++ if (!anx6345->bridge.of_node) ++ return -ENODEV; ++ ++ edidp = of_get_property(anx6345->bridge.of_node, "edid", &len); ++ if (!edidp || len != EDID_LENGTH) ++ return -EINVAL; ++ ++ anx6345->edid = devm_kmemdup(&anx6345->client->dev, edidp, ++ len, GFP_KERNEL); ++ ++ if (!anx6345->edid) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int anx6345_get_modes(struct drm_connector *connector) ++{ ++ struct anx6345 *anx6345 = connector_to_anx6345(connector); ++ int err, num_modes = 0; ++ ++ if (WARN_ON(!anx6345->powered)) ++ return 0; ++ ++ if (anx6345->edid) ++ return drm_add_edid_modes(connector, anx6345->edid); ++ ++ mutex_lock(&anx6345->lock); ++ ++ err = anx6345_get_downstream_info(anx6345); ++ if (err) { ++ DRM_ERROR("Failed to get downstream info: %d\n", err); ++ goto unlock; ++ } ++ ++ anx6345->edid = drm_get_edid(connector, &anx6345->aux.ddc); ++ if (!anx6345->edid) ++ DRM_ERROR("Failed to read EDID from panel\n"); ++ ++ if (!anx6345->edid) { ++ err = anx6345_probe_edid_from_of(anx6345); ++ if (err) { ++ DRM_ERROR("Failed to probe EDID from device tree\n"); ++ goto unlock; ++ } ++ } ++ ++ err = drm_connector_update_edid_property(connector, ++ anx6345->edid); ++ if (err) { ++ DRM_ERROR("Failed to update EDID property: %d\n", err); ++ goto unlock; ++ } ++ ++ num_modes = drm_add_edid_modes(connector, anx6345->edid); ++ ++unlock: ++ mutex_unlock(&anx6345->lock); ++ ++ return num_modes; ++} ++ ++static const struct drm_connector_helper_funcs anx6345_connector_helper_funcs = { ++ .get_modes = anx6345_get_modes, ++}; ++ ++static enum drm_connector_status anx6345_detect(struct drm_connector *connector, ++ bool force) ++{ ++ return connector_status_connected; ++} ++ ++static const struct drm_connector_funcs anx6345_connector_funcs = { ++ .fill_modes = drm_helper_probe_single_connector_modes, ++ .detect = anx6345_detect, ++ .destroy = drm_connector_cleanup, ++ .reset = drm_atomic_helper_connector_reset, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++}; ++ ++static int anx6345_bridge_attach(struct drm_bridge *bridge) ++{ ++ struct anx6345 *anx6345 = bridge_to_anx6345(bridge); ++ int err; ++ ++ if (!bridge->encoder) { ++ DRM_ERROR("Parent encoder object not found"); ++ return -ENODEV; ++ } ++ ++ /* Register aux channel */ ++ anx6345->aux.name = "DP-AUX"; ++ anx6345->aux.dev = &anx6345->client->dev; ++ anx6345->aux.transfer = anx6345_aux_transfer; ++ ++ err = drm_dp_aux_register(&anx6345->aux); ++ if (err < 0) { ++ DRM_ERROR("Failed to register aux channel: %d\n", err); ++ return err; ++ } ++ ++ err = drm_connector_init(bridge->dev, &anx6345->connector, ++ &anx6345_connector_funcs, ++ DRM_MODE_CONNECTOR_eDP); ++ if (err) { ++ DRM_ERROR("Failed to initialize connector: %d\n", err); ++ return err; ++ } ++ ++ drm_connector_helper_add(&anx6345->connector, ++ &anx6345_connector_helper_funcs); ++ ++ err = drm_connector_register(&anx6345->connector); ++ if (err) { ++ DRM_ERROR("Failed to register connector: %d\n", err); ++ return err; ++ } ++ ++ anx6345->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ ++ err = drm_connector_attach_encoder(&anx6345->connector, ++ bridge->encoder); ++ if (err) { ++ DRM_ERROR("Failed to link up connector to encoder: %d\n", err); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static bool anx6345_bridge_mode_fixup(struct drm_bridge *bridge, ++ const struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ if (mode->flags & DRM_MODE_FLAG_INTERLACE) ++ return false; ++ ++ /* Max 1200p at 5.4 Ghz, one lane */ ++ if (mode->clock > 154000) ++ return false; ++ ++ return true; ++} ++ ++static void anx6345_bridge_disable(struct drm_bridge *bridge) ++{ ++ struct anx6345 *anx6345 = bridge_to_anx6345(bridge); ++ ++ /* Power off all modules except configuration registers access */ ++ anx6345_set_bits(anx6345->map[I2C_IDX_TXCOM], SP_POWERDOWN_CTRL_REG, ++ SP_HDCP_PD | SP_AUDIO_PD | SP_VIDEO_PD | SP_LINK_PD); ++} ++ ++static void anx6345_bridge_mode_set(struct drm_bridge *bridge, ++ struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ struct anx6345 *anx6345 = bridge_to_anx6345(bridge); ++ ++ if (WARN_ON(!anx6345->powered)) ++ return; ++} ++ ++static void anx6345_bridge_enable(struct drm_bridge *bridge) ++{ ++ struct anx6345 *anx6345 = bridge_to_anx6345(bridge); ++ int err; ++ ++ err = anx6345_start(anx6345); ++ if (err) { ++ DRM_ERROR("Failed to initialize: %d\n", err); ++ return; ++ } ++ ++ err = anx6345_config_dp_output(anx6345); ++ if (err) ++ DRM_ERROR("Failed to enable DP output: %d\n", err); ++} ++ ++static const struct drm_bridge_funcs anx6345_bridge_funcs = { ++ .attach = anx6345_bridge_attach, ++ .mode_fixup = anx6345_bridge_mode_fixup, ++ .disable = anx6345_bridge_disable, ++ .mode_set = anx6345_bridge_mode_set, ++ .enable = anx6345_bridge_enable, ++}; ++ ++static void unregister_i2c_dummy_clients(struct anx6345 *anx6345) ++{ ++ unsigned int i; ++ ++ for (i = 1; i < ARRAY_SIZE(anx6345->i2c_clients); i++) ++ if (anx6345->i2c_clients[i] && ++ anx6345->i2c_clients[i]->addr != anx6345->client->addr) ++ i2c_unregister_device(anx6345->i2c_clients[i]); ++} ++ ++static const struct regmap_config anx6345_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = 0xff, ++}; ++ ++static const u16 anx6345_chipid_list[] = { ++ 0x6345, ++}; ++ ++static int anx6345_i2c_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct anx6345 *anx6345; ++ struct anx6345_platform_data *pdata; ++ unsigned int i, idl, idh, version; ++ bool found = false; ++ int err; ++ ++ anx6345 = devm_kzalloc(&client->dev, sizeof(*anx6345), GFP_KERNEL); ++ if (!anx6345) ++ return -ENOMEM; ++ ++ pdata = &anx6345->pdata; ++ ++ mutex_init(&anx6345->lock); ++ ++#if IS_ENABLED(CONFIG_OF) ++ anx6345->bridge.of_node = client->dev.of_node; ++#endif ++ ++ anx6345->client = client; ++ i2c_set_clientdata(client, anx6345); ++ ++ err = anx6345_init_pdata(anx6345); ++ if (err) { ++ DRM_ERROR("Failed to initialize pdata: %d\n", err); ++ return err; ++ } ++ ++ /* Map slave addresses of ANX6345 */ ++ for (i = 0; i < I2C_NUM_ADDRESSES; i++) { ++ if (anx6345_i2c_addresses[i] >> 1 != client->addr) ++ anx6345->i2c_clients[i] = i2c_new_dummy(client->adapter, ++ anx6345_i2c_addresses[i] >> 1); ++ else ++ anx6345->i2c_clients[i] = client; ++ ++ if (!anx6345->i2c_clients[i]) { ++ err = -ENOMEM; ++ DRM_ERROR("Failed to reserve I2C bus %02x\n", ++ anx6345_i2c_addresses[i]); ++ goto err_unregister_i2c; ++ } ++ ++ anx6345->map[i] = devm_regmap_init_i2c(anx6345->i2c_clients[i], ++ &anx6345_regmap_config); ++ if (IS_ERR(anx6345->map[i])) { ++ err = PTR_ERR(anx6345->map[i]); ++ DRM_ERROR("Failed regmap initialization %02x\n", ++ anx6345_i2c_addresses[i]); ++ goto err_unregister_i2c; ++ } ++ } ++ ++ /* Look for supported chip ID */ ++ anx6345_poweron(anx6345); ++ ++ err = regmap_read(anx6345->map[I2C_IDX_TXCOM], SP_DEVICE_IDL_REG, ++ &idl); ++ if (err) ++ goto err_poweroff; ++ ++ err = regmap_read(anx6345->map[I2C_IDX_TXCOM], SP_DEVICE_IDH_REG, ++ &idh); ++ if (err) ++ goto err_poweroff; ++ ++ anx6345->chipid = (u8)idl | ((u8)idh << 8); ++ ++ err = regmap_read(anx6345->map[I2C_IDX_TXCOM], SP_DEVICE_VERSION_REG, ++ &version); ++ if (err) ++ goto err_poweroff; ++ ++ for (i = 0; i < ARRAY_SIZE(anx6345_chipid_list); i++) { ++ if (anx6345->chipid == anx6345_chipid_list[i]) { ++ DRM_INFO("Found ANX%x (ver. %d) eDP Transmitter\n", ++ anx6345->chipid, version); ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ DRM_ERROR("ANX%x (ver. %d) not supported by this driver\n", ++ anx6345->chipid, version); ++ err = -ENODEV; ++ goto err_poweroff; ++ } ++ ++ anx6345->bridge.funcs = &anx6345_bridge_funcs; ++ ++ drm_bridge_add(&anx6345->bridge); ++ ++ return 0; ++ ++err_poweroff: ++ anx6345_poweroff(anx6345); ++ ++err_unregister_i2c: ++ unregister_i2c_dummy_clients(anx6345); ++ return err; ++} ++ ++static int anx6345_i2c_remove(struct i2c_client *client) ++{ ++ struct anx6345 *anx6345 = i2c_get_clientdata(client); ++ ++ drm_bridge_remove(&anx6345->bridge); ++ ++ unregister_i2c_dummy_clients(anx6345); ++ ++ kfree(anx6345->edid); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id anx6345_id[] = { ++ { "anx6345", 0 }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(i2c, anx6345_id); ++ ++#if IS_ENABLED(CONFIG_OF) ++static const struct of_device_id anx6345_match_table[] = { ++ { .compatible = "analogix,anx6345", }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, anx6345_match_table); ++#endif ++ ++static struct i2c_driver anx6345_driver = { ++ .driver = { ++ .name = "anx6345", ++ .of_match_table = of_match_ptr(anx6345_match_table), ++ }, ++ .probe = anx6345_i2c_probe, ++ .remove = anx6345_i2c_remove, ++ .id_table = anx6345_id, ++}; ++module_i2c_driver(anx6345_driver); ++ ++MODULE_DESCRIPTION("ANX6345 eDP Transmitter driver"); ++MODULE_AUTHOR("Icenowy Zheng "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c +index 9cb30962032e..53b0e73d6a24 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c ++++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c +@@ -117,7 +117,7 @@ ssize_t anx_aux_transfer(struct regmap *map_dptx, struct drm_dp_aux_msg *msg) + else /* For non-zero-sized set the length field. */ + ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT; + +- if ((msg->request & DP_AUX_I2C_READ) == 0) { ++ if ((msg->size > 0) && ((msg->request & DP_AUX_I2C_READ) == 0)) { + /* When WRITE | MOT write values to data buffer */ + err = regmap_bulk_write(map_dptx, + SP_DP_BUF_DATA0_REG, buffer, +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h +index c2ca854613a0..b29a0b3bc23c 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h ++++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.h +@@ -75,7 +75,11 @@ + #define SP_CHA_STA BIT(2) + /* Bits for DP System Control Register 3 */ + #define SP_HPD_STATUS BIT(6) ++#define SP_HPD_FORCE BIT(5) ++#define SP_HPD_CTRL BIT(4) + #define SP_STRM_VALID BIT(2) ++#define SP_STRM_FORCE BIT(1) ++#define SP_STRM_CTRL BIT(0) + /* Bits for DP System Control Register 4 */ + #define SP_ENHANCED_MODE BIT(3) + +@@ -120,6 +124,9 @@ + #define SP_LINK_BW_SET_MASK 0x1f + #define SP_INITIAL_SLIM_M_AUD_SEL BIT(5) + ++/* DP Lane Count Setting Register */ ++#define SP_DP_LANE_COUNT_SET_REG 0xa1 ++ + /* DP Training Pattern Set Register */ + #define SP_DP_TRAINING_PATTERN_SET_REG 0xa2 + +@@ -133,6 +140,7 @@ + + /* DP Link Training Control Register */ + #define SP_DP_LT_CTRL_REG 0xa8 ++#define SP_DP_LT_INPROGRESS 0x80 + #define SP_LT_ERROR_TYPE_MASK 0x70 + # define SP_LT_NO_ERROR 0x00 + # define SP_LT_AUX_WRITE_ERROR 0x01 +diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h b/drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h +index 7d683573e970..480c98a225b1 100644 +--- a/drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h ++++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-txcommon.h +@@ -183,6 +183,9 @@ + #define SP_VBIT BIT(1) + #define SP_AUDIO_LAYOUT BIT(0) + ++/* Analog Debug Register 1 */ ++#define SP_ANALOG_DEBUG1_REG 0xdc ++ + /* Analog Debug Register 2 */ + #define SP_ANALOG_DEBUG2_REG 0xdd + #define SP_FORCE_SW_OFF_BYPASS 0x20 +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0131-arm64-allwinner-a64-add-pinmux-for-RGB666-LCD.patch b/patch/kernel/sunxi-dev/0131-arm64-allwinner-a64-add-pinmux-for-RGB666-LCD.patch new file mode 100644 index 000000000..4c7d893ad --- /dev/null +++ b/patch/kernel/sunxi-dev/0131-arm64-allwinner-a64-add-pinmux-for-RGB666-LCD.patch @@ -0,0 +1,37 @@ +From 3d017794525d830a3251bed7ebbacbf74efe9605 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:24 +0800 +Subject: [PATCH 131/146] arm64: allwinner: a64: add pinmux for RGB666 LCD + +Allwinner A64's TCON0 can output RGB666 LCD signal. + +Add its pinmux. + +Signed-off-by: Icenowy Zheng +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index cb7d4a96e789..0f5b412cfc81 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -655,6 +655,15 @@ + function = "i2c1"; + }; + ++ lcd_rgb666_pins: lcd-rgb666 { ++ pins = "PD0", "PD1", "PD2", "PD3", "PD4", ++ "PD5", "PD6", "PD7", "PD8", "PD9", ++ "PD10", "PD11", "PD12", "PD13", ++ "PD14", "PD15", "PD16", "PD17", ++ "PD18", "PD19", "PD20", "PD21"; ++ function = "lcd0"; ++ }; ++ + mmc0_pins: mmc0-pins { + pins = "PF0", "PF1", "PF2", "PF3", + "PF4", "PF5"; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0132-arm64-allwinner-a64-enable-ANX6345-bridge-on-Pineboo.patch b/patch/kernel/sunxi-dev/0132-arm64-allwinner-a64-enable-ANX6345-bridge-on-Pineboo.patch new file mode 100644 index 000000000..edd0bff35 --- /dev/null +++ b/patch/kernel/sunxi-dev/0132-arm64-allwinner-a64-enable-ANX6345-bridge-on-Pineboo.patch @@ -0,0 +1,84 @@ +From 82fe5562e8d5cb289e97ff8d259b21889e72b03b Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:25 +0800 +Subject: [PATCH 132/146] arm64: allwinner: a64: enable ANX6345 bridge on + Pinebook + +Pinebook has an ANX6345 bridge connected to the RGB666 LCD output, and +the I2C controlling signals are connected to R_I2C bus. + +Enable it in the device tree, and add a usable EDID from the panel's +datasheet (at least 14" Pinebook used a panel without EDID). + +Signed-off-by: Icenowy Zheng +--- + .../dts/allwinner/sun50i-a64-pinebook.dts | 39 +++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +index b55ac4e1df37..8c9bd4dfbbba 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +@@ -123,6 +123,10 @@ + }; + }; + ++&mixer0 { ++ status = "okay"; ++}; ++ + &mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; +@@ -175,6 +179,27 @@ + status = "okay"; + }; + ++&r_i2c { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&r_i2c_pins_a>; ++ status = "okay"; ++ ++ anx6345: anx6345@38 { ++ compatible = "analogix,anx6345"; ++ reg = <0x38>; ++ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */ ++ panel-supply = <®_dc1sw>; ++ dvdd25-supply = <®_dldo2>; ++ dvdd12-supply = <®_fldo1>; ++ ++ port { ++ anx6345_in: endpoint { ++ remote-endpoint = <&tcon0_out_anx6345>; ++ }; ++ }; ++ }; ++}; ++ + &r_rsb { + status = "okay"; + +@@ -348,6 +373,20 @@ + "MIC2", "Internal Microphone Right"; + }; + ++&tcon0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lcd_rgb666_pins>; ++ ++ status = "okay"; ++}; ++ ++&tcon0_out { ++ tcon0_out_anx6345: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&anx6345_in>; ++ }; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0133-arm64-allwinner-a64-enable-ANX6345-bridge-on-TERES-I.patch b/patch/kernel/sunxi-dev/0133-arm64-allwinner-a64-enable-ANX6345-bridge-on-TERES-I.patch new file mode 100644 index 000000000..5098b5c9a --- /dev/null +++ b/patch/kernel/sunxi-dev/0133-arm64-allwinner-a64-enable-ANX6345-bridge-on-TERES-I.patch @@ -0,0 +1,87 @@ +From 955974c9ba484fc2b7e4396b5fdc6687a9a530a0 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:33:26 +0800 +Subject: [PATCH 133/146] arm64: allwinner: a64: enable ANX6345 bridge on + TERES-I + +TERES-I has an ANX6345 bridge connected to the RGB666 LCD output, and +the I2C controlling signals are connected to I2C0 bus. + +Enable it in the device tree. + +Signed-off-by: Icenowy Zheng +--- + .../boot/dts/allwinner/sun50i-a64-teres-i.dts | 40 +++++++++++++++++-- + 1 file changed, 36 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts +index 81f8e0098699..6c3318b3c648 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts +@@ -72,20 +72,38 @@ + }; + }; + ++&de { ++ status = "okay"; ++}; ++ + &ehci1 { + status = "okay"; + }; + + +-/* The ANX6345 eDP-bridge is on i2c0. There is no linux (mainline) +- * driver for this chip at the moment, the bootloader initializes it. +- * However it can be accessed with the i2c-dev driver from user space. +- */ + &i2c0 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; ++ ++ anx6345: anx6345@38 { ++ compatible = "analogix,anx6345"; ++ reg = <0x38>; ++ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */ ++ dvdd25-supply = <®_dldo2>; ++ dvdd12-supply = <®_dldo3>; ++ ++ port { ++ anx6345_in: endpoint { ++ remote-endpoint = <&tcon0_out_anx6345>; ++ }; ++ }; ++ }; ++}; ++ ++&mixer0 { ++ status = "okay"; + }; + + &mmc0 { +@@ -258,6 +276,20 @@ + vcc-hdmi-supply = <®_dldo1>; + }; + ++&tcon0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lcd_rgb666_pins>; ++ ++ status = "okay"; ++}; ++ ++&tcon0_out { ++ tcon0_out_anx6345: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&anx6345_in>; ++ }; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0134-drm-sun4i-rgb-Add-5-tolerance-to-dot-clock-frequency.patch b/patch/kernel/sunxi-dev/0134-drm-sun4i-rgb-Add-5-tolerance-to-dot-clock-frequency.patch new file mode 100644 index 000000000..3a9fb910c --- /dev/null +++ b/patch/kernel/sunxi-dev/0134-drm-sun4i-rgb-Add-5-tolerance-to-dot-clock-frequency.patch @@ -0,0 +1,58 @@ +From 0957f917d9a53bd9264bde6c2bd9d4f93cdd1d0c Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Thu, 18 Oct 2018 15:33:27 +0800 +Subject: [PATCH 134/146] drm/sun4i: rgb: Add 5% tolerance to dot clock + frequency check + +The panels shipped with Allwinner devices are very "generic", i.e. +they do not have model numbers or reliable sources of information +for the timings (that we know of) other than the fex files shipped +on them. The dot clock frequency provided in the fex files have all +been rounded to the nearest MHz, as that is the unit used in them. + +We were using the simple panel "urt,umsh-8596md-t" as a substitute +for the A13 Q8 tablets in the absence of a specific model for what +may be many different but otherwise timing compatible panels. This +was usable without any visual artifacts or side effects, until the +dot clock rate check was added in commit bb43d40d7c83 ("drm/sun4i: +rgb: Validate the clock rate"). + +The reason this check fails is because the dotclock frequency for +this model is 33.26 MHz, which is not achievable with our dot clock +hardware, and the rate returned by clk_round_rate deviates slightly, +causing the driver to reject the display mode. + +The LCD panels have some tolerance on the dot clock frequency, even +if it's not specified in their datasheets. + +This patch adds a 5% tolerence to the dot clock check. + +Signed-off-by: Chen-Yu Tsai +--- + drivers/gpu/drm/sun4i/sun4i_rgb.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c +index bf068da6b12e..23bdc449eacc 100644 +--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c ++++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c +@@ -92,13 +92,14 @@ static enum drm_mode_status sun4i_rgb_mode_valid(struct drm_encoder *crtc, + + DRM_DEBUG_DRIVER("Vertical parameters OK\n"); + ++ /* Check against a 5% tolerance for the dot clock */ + tcon->dclk_min_div = 6; + tcon->dclk_max_div = 127; + rounded_rate = clk_round_rate(tcon->dclk, rate); +- if (rounded_rate < rate) ++ if (rounded_rate < rate * 19 / 20 ) + return MODE_CLOCK_LOW; + +- if (rounded_rate > rate) ++ if (rounded_rate > rate * 21 / 20) + return MODE_CLOCK_HIGH; + + DRM_DEBUG_DRIVER("Clock rate OK\n"); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0135-clk-sunxi-ng-enable-so-said-LDOs-for-A64-SoC-s-pll-m.patch b/patch/kernel/sunxi-dev/0135-clk-sunxi-ng-enable-so-said-LDOs-for-A64-SoC-s-pll-m.patch new file mode 100644 index 000000000..6aa68872f --- /dev/null +++ b/patch/kernel/sunxi-dev/0135-clk-sunxi-ng-enable-so-said-LDOs-for-A64-SoC-s-pll-m.patch @@ -0,0 +1,43 @@ +From 734e26b5a4b061d5f0667d59ce27a4a50f6d5c25 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Thu, 18 Oct 2018 15:07:29 +0800 +Subject: [PATCH 135/146] clk: sunxi-ng: enable so-said LDOs for A64 SoC's + pll-mipi clock + +In the user manual of A64 SoC, the bit 22 and 23 of pll-mipi control +register is called "LDO{1,2}_EN", and according to the BSP source code +from Allwinner , the LDOs are enabled during the clock's enabling +process. + +The clock failed to generate output if the two LDOs are not enabled. + +Add the two bits to the clock's gate bits, so that the LDOs are enabled +when the PLL is enabled. + +Fixes: c6a0637460c2 ("clk: sunxi-ng: Add A64 clocks") +Signed-off-by: Icenowy Zheng +--- + drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +index 90ffee824c33..a637e62ae1c4 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +@@ -162,7 +162,12 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", + #define SUN50I_A64_PLL_MIPI_REG 0x040 + + static struct ccu_nkm pll_mipi_clk = { +- .enable = BIT(31), ++ /* ++ * The bit 23 and 22 are called "LDO{1,2}_EN" on the SoC's ++ * user manual, and by experiments the PLL doesn't work without ++ * these bits toggled. ++ */ ++ .enable = BIT(31) | BIT(23) | BIT(22), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 4), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0136-hdmi-audio-fixup.patch b/patch/kernel/sunxi-dev/0136-hdmi-audio-fixup.patch new file mode 100644 index 000000000..01a7dd5ff --- /dev/null +++ b/patch/kernel/sunxi-dev/0136-hdmi-audio-fixup.patch @@ -0,0 +1,24 @@ +From 2c38da8ed7cc1f7dabe72c4d455ba25e0ba18fe7 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sun, 28 Oct 2018 19:06:28 -0700 +Subject: [PATCH 136/146] hdmi audio fixup + +--- + arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +index 0f5b412cfc81..f507bb1d8c3d 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +@@ -1044,6 +1044,7 @@ + }; + + hdmi: hdmi@1ee0000 { ++ #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-a64-dw-hdmi", + "allwinner,sun8i-a83t-dw-hdmi"; + reg = <0x01ee0000 0x10000>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0137-Pinebook-HDMI-audio.patch b/patch/kernel/sunxi-dev/0137-Pinebook-HDMI-audio.patch new file mode 100644 index 000000000..2a881647f --- /dev/null +++ b/patch/kernel/sunxi-dev/0137-Pinebook-HDMI-audio.patch @@ -0,0 +1,39 @@ +From 59197ec5632d29d173aae2fbe6c92402fc2f0a58 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Sun, 28 Oct 2018 19:07:23 -0700 +Subject: [PATCH 137/146] Pinebook HDMI audio + +Signed-off-by: Vasily Khoruzhick +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +index 8c9bd4dfbbba..0f788400ece0 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +@@ -123,6 +123,10 @@ + }; + }; + ++&i2s2 { ++ status = "okay"; ++}; ++ + &mixer0 { + status = "okay"; + }; +@@ -373,6 +377,10 @@ + "MIC2", "Internal Microphone Right"; + }; + ++&sound_hdmi { ++ status = "okay"; ++}; ++ + &tcon0 { + pinctrl-names = "default"; + pinctrl-0 = <&lcd_rgb666_pins>; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0138-ASoC-sunxi-rename-SND_SUNXI_ADDA_PR_REGMAP-to-SND_SU.patch b/patch/kernel/sunxi-dev/0138-ASoC-sunxi-rename-SND_SUNXI_ADDA_PR_REGMAP-to-SND_SU.patch new file mode 100644 index 000000000..73bba2700 --- /dev/null +++ b/patch/kernel/sunxi-dev/0138-ASoC-sunxi-rename-SND_SUNXI_ADDA_PR_REGMAP-to-SND_SU.patch @@ -0,0 +1,36 @@ +From 4408d80fe8dd0a724cebcc9b0d50af8674d56377 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Fri, 2 Nov 2018 21:16:26 -0700 +Subject: [PATCH 138/146] ASoC: sunxi: rename SND_SUNXI_ADDA_PR_REGMAP to + SND_SUN8I_ADDA_PR_REGMAP + +SND_SUN50I_CODEC_ANALOG selects SND_SUNXI_ADDA_PR_REGMAP which is leftover +of renaming SND_SUNXI_ADDA_PR_REGMAP to SND_SUN8I_ADDA_PR_REGMAP. Replace +it with SND_SUN8I_ADDA_PR_REGMAP to fix possible link errors for some +configurations: + +sound/soc/sunxi/sun50i-codec-analog.o: In function `sun50i_codec_analog_probe': +sun50i-codec-analog.c:(.text+0x62): undefined reference to `sun8i_adda_pr_regmap_init' + +Fixes: 42371f327df0 ("ASoC: sunxi: Add new driver for Allwinner A64 codec's analog path controls") +Signed-off-by: Vasily Khoruzhick +--- + sound/soc/sunxi/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig +index 66aad0d3f9c7..8134c3c94229 100644 +--- a/sound/soc/sunxi/Kconfig ++++ b/sound/soc/sunxi/Kconfig +@@ -31,7 +31,7 @@ config SND_SUN8I_CODEC_ANALOG + config SND_SUN50I_CODEC_ANALOG + tristate "Allwinner sun50i Codec Analog Controls Support" + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST +- select SND_SUNXI_ADDA_PR_REGMAP ++ select SND_SUN8I_ADDA_PR_REGMAP + help + Say Y or M if you want to add support for the analog controls for + the codec embedded in Allwinner A64 SoC. +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0139-Bluetooth-Add-new-quirk-for-broken-local-ext-feature.patch.disabled b/patch/kernel/sunxi-dev/0139-Bluetooth-Add-new-quirk-for-broken-local-ext-feature.patch.disabled new file mode 100644 index 000000000..d7912e20a --- /dev/null +++ b/patch/kernel/sunxi-dev/0139-Bluetooth-Add-new-quirk-for-broken-local-ext-feature.patch.disabled @@ -0,0 +1,54 @@ +From e4a72ee5f7717daaa2928b3d18a5327739c8b180 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 19:40:18 -0700 +Subject: [PATCH 139/146] Bluetooth: Add new quirk for broken local ext + features max_page + +Some adapters (e.g. RTL8723CS) advertise that they have more than +2 pages for local ext features, but they don't support any features +declared in these pages. RTL8723CS reports max_page = 2 and declares +support for sync train and secure connection, but it responds with +either garbage or with error in status on corresponding commands. + +Signed-off-by: Vasily Khoruzhick +--- + include/net/bluetooth/hci.h | 7 +++++++ + net/bluetooth/hci_event.c | 4 +++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index cdd9f1fe7cfa..32b9195f6fca 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -192,6 +192,13 @@ enum { + * + */ + HCI_QUIRK_NON_PERSISTENT_SETUP, ++ ++ /* When this quirk is set, max_page for local extended features ++ * is set to 1, even if controller reports higher number. Some ++ * controllers (e.g. RTL8723CS) report more pages, but they ++ * don't actually support features declared there. ++ */ ++ HCI_QUIRK_BROKEN_LOCAL_EXT_FTR_MAX_PAGE, + }; + + /* HCI device flags */ +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index f12555f23a49..3eb289711dea 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -639,7 +639,9 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, + if (rp->status) + return; + +- if (hdev->max_page < rp->max_page) ++ if (!test_bit(HCI_QUIRK_BROKEN_LOCAL_EXT_FTR_MAX_PAGE, ++ &hdev->quirks) && ++ hdev->max_page < rp->max_page) + hdev->max_page = rp->max_page; + + if (rp->page < HCI_MAX_PAGES) +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0140-Bluetooth-hci_h5-Add-support-for-reset-GPIO.patch.disabled b/patch/kernel/sunxi-dev/0140-Bluetooth-hci_h5-Add-support-for-reset-GPIO.patch.disabled new file mode 100644 index 000000000..f82a5cde8 --- /dev/null +++ b/patch/kernel/sunxi-dev/0140-Bluetooth-hci_h5-Add-support-for-reset-GPIO.patch.disabled @@ -0,0 +1,57 @@ +From e8a404daea8d869304fdf810ac502cda8fbb4999 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 19:48:25 -0700 +Subject: [PATCH 140/146] Bluetooth: hci_h5: Add support for reset GPIO + +Some boards (e.g. Pine64 and Pinebook) wire a GPIO to reset pin of +RTL8723BS + +Signed-off-by: Vasily Khoruzhick +--- + drivers/bluetooth/hci_h5.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 8eede1197cd2..6e047df4f475 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -107,6 +107,7 @@ struct h5 { + const struct h5_vnd *vnd; + const char *id; + ++ struct gpio_desc *reset_gpio; + struct gpio_desc *enable_gpio; + struct gpio_desc *device_wake_gpio; + }; +@@ -831,6 +832,10 @@ static int h5_serdev_probe(struct serdev_device *serdev) + if (IS_ERR(h5->device_wake_gpio)) + return PTR_ERR(h5->device_wake_gpio); + ++ h5->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR(h5->reset_gpio)) ++ return PTR_ERR(h5->reset_gpio); ++ + return hci_uart_register_device(&h5->serdev_hu, &h5p); + } + +@@ -897,6 +902,9 @@ static void h5_btrtl_open(struct h5 *h5) + + /* The controller needs up to 500ms to wakeup */ + gpiod_set_value_cansleep(h5->enable_gpio, 1); ++ /* Take it out of reset */ ++ gpiod_set_value_cansleep(h5->reset_gpio, 0); ++ msleep(100); + gpiod_set_value_cansleep(h5->device_wake_gpio, 1); + msleep(500); + } +@@ -904,6 +912,7 @@ static void h5_btrtl_open(struct h5 *h5) + static void h5_btrtl_close(struct h5 *h5) + { + gpiod_set_value_cansleep(h5->device_wake_gpio, 0); ++ gpiod_set_value_cansleep(h5->reset_gpio, 1); + gpiod_set_value_cansleep(h5->enable_gpio, 0); + } + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0141-dt-bindings-net-bluetooth-Add-rtl8723bs-bluetooth.patch.disabled b/patch/kernel/sunxi-dev/0141-dt-bindings-net-bluetooth-Add-rtl8723bs-bluetooth.patch.disabled new file mode 100644 index 000000000..9b7732316 --- /dev/null +++ b/patch/kernel/sunxi-dev/0141-dt-bindings-net-bluetooth-Add-rtl8723bs-bluetooth.patch.disabled @@ -0,0 +1,57 @@ +From d063238f64a1f0a4e8baf11e55d9cc1989816ee6 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 20:05:14 -0700 +Subject: [PATCH 141/146] dt-bindings: net: bluetooth: Add rtl8723bs-bluetooth + +Add binding document for bluetooth part of RTL8723BS/RTL8723CS + +Signed-off-by: Vasily Khoruzhick +--- + .../bindings/net/rtl8723bs-bluetooth.txt | 35 +++++++++++++++++++ + 1 file changed, 35 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/rtl8723bs-bluetooth.txt + +diff --git a/Documentation/devicetree/bindings/net/rtl8723bs-bluetooth.txt b/Documentation/devicetree/bindings/net/rtl8723bs-bluetooth.txt +new file mode 100644 +index 000000000000..8357f242ae4c +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/rtl8723bs-bluetooth.txt +@@ -0,0 +1,35 @@ ++RTL8723BS/RTL8723CS Bluetooth ++--------------------- ++ ++RTL8723CS/RTL8723CS is WiFi + BT chip. WiFi part is connected over SDIO, while ++BT is connected over serial. It speaks H5 protocol with few extra commands ++to upload firmware and change module speed. ++ ++Required properties: ++ ++ - compatible: should be one of the following: ++ * "realtek,rtl8723bs-bt" ++ * "realtek,rtl8723cs-bt" ++Optional properties: ++ ++ - device-wake-gpios: GPIO specifier, used to wakeup the BT module (active high) ++ - enable-gpios: GPIO specifier, used to enable the BT module (active high) ++ - host-wake-gpios: GPIO specifier, used to wakeup the host processor (active high) ++ - firmware-postfix: firmware postfix to be used for firmware config ++ - reset-gpios: GPIO specifier, used to reset the BT module (active high) ++ ++Example: ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "realtek,rtl8723bs-bt"; ++ reset-gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; /* PL4 */ ++ device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */ ++ host-wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ ++ firmware-postfix="pine64"; ++ }; ++}; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0142-Bluetooth-hci_h5-Add-support-for-binding-RTL8723BS-w.patch.disabled b/patch/kernel/sunxi-dev/0142-Bluetooth-hci_h5-Add-support-for-binding-RTL8723BS-w.patch.disabled new file mode 100644 index 000000000..be3dc20c0 --- /dev/null +++ b/patch/kernel/sunxi-dev/0142-Bluetooth-hci_h5-Add-support-for-binding-RTL8723BS-w.patch.disabled @@ -0,0 +1,68 @@ +From 38caa52f547c63c9cd7aa19259bb6806cff7d50d Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 20:07:41 -0700 +Subject: [PATCH 142/146] Bluetooth: hci_h5: Add support for binding RTL8723BS + with device tree + +RTL8723BS is often used in ARM boards, so add ability to bind it +using device tree. + +Signed-off-by: Vasily Khoruzhick +--- + drivers/bluetooth/hci_h5.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 6e047df4f475..9cc10e299fa8 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -821,6 +822,11 @@ static int h5_serdev_probe(struct serdev_device *serdev) + if (h5->vnd->acpi_gpio_map) + devm_acpi_dev_add_driver_gpios(dev, + h5->vnd->acpi_gpio_map); ++ } else { ++ h5->vnd = (const struct h5_vnd *) ++ of_device_get_match_data(&serdev->dev); ++ of_property_read_string(serdev->dev.of_node, ++ "firmware-postfix", &h5->id); + } + + h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); +@@ -944,12 +950,26 @@ static const struct acpi_device_id h5_acpi_match[] = { + MODULE_DEVICE_TABLE(acpi, h5_acpi_match); + #endif + ++static struct h5_vnd rtl8723_of_vnd = { ++ .setup = h5_btrtl_setup, ++ .open = h5_btrtl_open, ++ .close = h5_btrtl_close, ++}; ++ ++static const struct of_device_id h5_of_match[] = { ++ { .compatible = "realtek,rtl8723bs-bt", .data = &rtl8723_of_vnd }, ++ { .compatible = "realtek,rtl8723cs-bt", .data = &rtl8723_of_vnd }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, h5_of_match); ++ + static struct serdev_device_driver h5_serdev_driver = { + .probe = h5_serdev_probe, + .remove = h5_serdev_remove, + .driver = { + .name = "hci_uart_h5", + .acpi_match_table = ACPI_PTR(h5_acpi_match), ++ .of_match_table = of_match_ptr(h5_of_match), + }, + }; + +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0143-Bluetooth-btrtl-add-support-for-the-RTL8723CS.patch.disabled b/patch/kernel/sunxi-dev/0143-Bluetooth-btrtl-add-support-for-the-RTL8723CS.patch.disabled new file mode 100644 index 000000000..22cea18cc --- /dev/null +++ b/patch/kernel/sunxi-dev/0143-Bluetooth-btrtl-add-support-for-the-RTL8723CS.patch.disabled @@ -0,0 +1,311 @@ +From 08c47cbb508e40e5e404055f77653474d5793e27 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 20:33:22 -0700 +Subject: [PATCH 143/146] Bluetooth: btrtl: add support for the RTL8723CS + +The Realtek RTL8723CS is SDIO WiFi chip. It also contains a Bluetooth +module which is connected via UART to the host. + +It shares lmp subversion with 8703B, so Realtek's userspace +initialization tool (rtk_hciattach) differentiates varieties of RTL8723CS +(CG, VF, XX) with RTL8703B using vendor's command to read chip type. + +Also this chip declares support for some features it doesn't support +so add a quirk to indicate that these features are broken. + +Signed-off-by: Vasily Khoruzhick +--- + drivers/bluetooth/btrtl.c | 128 ++++++++++++++++++++++++++++++++++++- + drivers/bluetooth/btrtl.h | 12 ++++ + drivers/bluetooth/hci_h5.c | 4 ++ + 3 files changed, 141 insertions(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c +index 7f9ea8e4c1b2..f9474e78bcfa 100644 +--- a/drivers/bluetooth/btrtl.c ++++ b/drivers/bluetooth/btrtl.c +@@ -27,8 +27,12 @@ + + #define VERSION "0.1" + ++#define RTL_CHIP_8723CS_CG 3 ++#define RTL_CHIP_8723CS_VF 4 ++#define RTL_CHIP_8723CS_XX 5 + #define RTL_EPATCH_SIGNATURE "Realtech" + #define RTL_ROM_LMP_3499 0x3499 ++#define RTL_ROM_LMP_8703B 0x8703 + #define RTL_ROM_LMP_8723A 0x1200 + #define RTL_ROM_LMP_8723B 0x8723 + #define RTL_ROM_LMP_8821A 0x8821 +@@ -40,6 +44,7 @@ + #define IC_MATCH_FL_HCIREV (1 << 1) + #define IC_MATCH_FL_HCIVER (1 << 2) + #define IC_MATCH_FL_HCIBUS (1 << 3) ++#define IC_MATCH_FL_CHIP_TYPE (1 << 4) + #define IC_INFO(lmps, hcir) \ + .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_HCIREV, \ + .lmp_subver = (lmps), \ +@@ -51,6 +56,7 @@ struct id_table { + __u16 hci_rev; + __u8 hci_ver; + __u8 hci_bus; ++ __u8 chip_type; + bool config_needed; + bool has_rom_version; + char *fw_name; +@@ -98,6 +104,39 @@ static const struct id_table ic_id_table[] = { + .fw_name = "rtl_bt/rtl8723b_fw.bin", + .cfg_name = "rtl_bt/rtl8723b_config" }, + ++ /* 8723CS-CG */ ++ { .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE | ++ IC_MATCH_FL_HCIBUS, ++ .lmp_subver = RTL_ROM_LMP_8703B, ++ .chip_type = RTL_CHIP_8723CS_CG, ++ .hci_bus = HCI_UART, ++ .config_needed = true, ++ .has_rom_version = true, ++ .fw_name = "rtl_bt/rtl8723cs_cg_fw.bin", ++ .cfg_name = "rtl_bt/rtl8723cs_cg_config" }, ++ ++ /* 8723CS-VF */ ++ { .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE | ++ IC_MATCH_FL_HCIBUS, ++ .lmp_subver = RTL_ROM_LMP_8703B, ++ .chip_type = RTL_CHIP_8723CS_VF, ++ .hci_bus = HCI_UART, ++ .config_needed = true, ++ .has_rom_version = true, ++ .fw_name = "rtl_bt/rtl8723cs_vf_fw.bin", ++ .cfg_name = "rtl_bt/rtl8723cs_vf_config" }, ++ ++ /* 8723CS-XX */ ++ { .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_CHIP_TYPE | ++ IC_MATCH_FL_HCIBUS, ++ .lmp_subver = RTL_ROM_LMP_8703B, ++ .chip_type = RTL_CHIP_8723CS_XX, ++ .hci_bus = HCI_UART, ++ .config_needed = true, ++ .has_rom_version = true, ++ .fw_name = "rtl_bt/rtl8723cs_xx_fw.bin", ++ .cfg_name = "rtl_bt/rtl8723cs_xx_config" }, ++ + /* 8723D */ + { IC_INFO(RTL_ROM_LMP_8723B, 0xd), + .config_needed = true, +@@ -147,7 +186,8 @@ static const struct id_table ic_id_table[] = { + }; + + static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev, +- u8 hci_ver, u8 hci_bus) ++ u8 hci_ver, u8 hci_bus, ++ u8 chip_type) + { + int i; + +@@ -164,6 +204,9 @@ static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev, + if ((ic_id_table[i].match_flags & IC_MATCH_FL_HCIBUS) && + (ic_id_table[i].hci_bus != hci_bus)) + continue; ++ if ((ic_id_table[i].match_flags & IC_MATCH_FL_CHIP_TYPE) && ++ (ic_id_table[i].chip_type != chip_type)) ++ continue; + + break; + } +@@ -225,6 +268,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, + { RTL_ROM_LMP_8723B, 1 }, + { RTL_ROM_LMP_8821A, 2 }, + { RTL_ROM_LMP_8761A, 3 }, ++ { RTL_ROM_LMP_8703B, 7 }, + { RTL_ROM_LMP_8822B, 8 }, + { RTL_ROM_LMP_8723B, 9 }, /* 8723D */ + { RTL_ROM_LMP_8821A, 10 }, /* 8821C */ +@@ -499,6 +543,48 @@ static struct sk_buff *btrtl_read_local_version(struct hci_dev *hdev) + return skb; + } + ++static bool rtl_has_chip_type(u16 lmp_subver) ++{ ++ switch (lmp_subver) { ++ case RTL_ROM_LMP_8703B: ++ return true; ++ default: ++ break; ++ } ++ ++ return false; ++} ++ ++static int rtl_read_chip_type(struct hci_dev *hdev, u8 *type) ++{ ++ struct rtl_chip_type_evt *chip_type; ++ struct sk_buff *skb; ++ const unsigned char cmd_buf[] = {0x00, 0x94, 0xa0, 0x00, 0xb0}; ++ ++ /* Read RTL chip type command */ ++ skb = __hci_cmd_sync(hdev, 0xfc61, 5, cmd_buf, HCI_INIT_TIMEOUT); ++ if (IS_ERR(skb)) { ++ rtl_dev_err(hdev, "Read chip type failed (%ld)", ++ PTR_ERR(skb)); ++ return PTR_ERR(skb); ++ } ++ ++ if (skb->len != sizeof(*chip_type)) { ++ rtl_dev_err(hdev, "RTL chip type event length mismatch"); ++ kfree_skb(skb); ++ return -EIO; ++ } ++ ++ chip_type = (struct rtl_chip_type_evt *)skb->data; ++ rtl_dev_info(hdev, "chip_type status=%x type=%x", ++ chip_type->status, chip_type->type); ++ ++ *type = chip_type->type & 0x0f; ++ ++ kfree_skb(skb); ++ return 0; ++} ++ + void btrtl_free(struct btrtl_device_info *btrtl_dev) + { + kfree(btrtl_dev->fw_data); +@@ -515,7 +601,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, + struct hci_rp_read_local_version *resp; + char cfg_name[40]; + u16 hci_rev, lmp_subver; +- u8 hci_ver; ++ u8 hci_ver, chip_type = 0; + int ret; + + btrtl_dev = kzalloc(sizeof(*btrtl_dev), GFP_KERNEL); +@@ -540,8 +626,14 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, + lmp_subver = le16_to_cpu(resp->lmp_subver); + kfree_skb(skb); + ++ if (rtl_has_chip_type(lmp_subver)) { ++ ret = rtl_read_chip_type(hdev, &chip_type); ++ if (ret) ++ goto err_free; ++ } ++ + btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver, +- hdev->bus); ++ hdev->bus, chip_type); + + if (!btrtl_dev->ic_info) { + rtl_dev_err(hdev, "rtl: unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x", +@@ -610,6 +702,7 @@ int btrtl_download_firmware(struct hci_dev *hdev, + case RTL_ROM_LMP_8821A: + case RTL_ROM_LMP_8761A: + case RTL_ROM_LMP_8822B: ++ case RTL_ROM_LMP_8703B: + return btrtl_setup_rtl8723b(hdev, btrtl_dev); + default: + rtl_dev_info(hdev, "rtl: assuming no firmware upload needed\n"); +@@ -628,7 +721,12 @@ int btrtl_setup_realtek(struct hci_dev *hdev) + return PTR_ERR(btrtl_dev); + + ret = btrtl_download_firmware(hdev, btrtl_dev); ++ if (ret) ++ goto out_free; + ++ btrtl_apply_quirks(hdev, btrtl_dev); ++ ++out_free: + btrtl_free(btrtl_dev); + + return ret; +@@ -743,6 +841,24 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, + } + EXPORT_SYMBOL_GPL(btrtl_get_uart_settings); + ++void btrtl_apply_quirks(struct hci_dev *hdev, ++ struct btrtl_device_info *btrtl_dev) ++{ ++ switch (btrtl_dev->ic_info->lmp_subver) { ++ case RTL_ROM_LMP_8703B: ++ /* 8723CS reports two pages for local ext features, ++ * but it doesn't support any features from page 2 - ++ * it either responds with garbage or with error status ++ */ ++ set_bit(HCI_QUIRK_BROKEN_LOCAL_EXT_FTR_MAX_PAGE, ++ &hdev->quirks); ++ break; ++ default: ++ break; ++ } ++} ++EXPORT_SYMBOL_GPL(btrtl_apply_quirks); ++ + MODULE_AUTHOR("Daniel Drake "); + MODULE_DESCRIPTION("Bluetooth support for Realtek devices ver " VERSION); + MODULE_VERSION(VERSION); +@@ -752,6 +868,12 @@ MODULE_FIRMWARE("rtl_bt/rtl8723b_fw.bin"); + MODULE_FIRMWARE("rtl_bt/rtl8723b_config.bin"); + MODULE_FIRMWARE("rtl_bt/rtl8723bs_fw.bin"); + MODULE_FIRMWARE("rtl_bt/rtl8723bs_config.bin"); ++MODULE_FIRMWARE("rtl_bt/rtl8723cs_cg_fw.bin"); ++MODULE_FIRMWARE("rtl_bt/rtl8723cs_cg_config.bin"); ++MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_fw.bin"); ++MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_config.bin"); ++MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_fw.bin"); ++MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_config.bin"); + MODULE_FIRMWARE("rtl_bt/rtl8723ds_fw.bin"); + MODULE_FIRMWARE("rtl_bt/rtl8723ds_config.bin"); + MODULE_FIRMWARE("rtl_bt/rtl8761a_fw.bin"); +diff --git a/drivers/bluetooth/btrtl.h b/drivers/bluetooth/btrtl.h +index f5e36f3993a8..db4e4a1542b7 100644 +--- a/drivers/bluetooth/btrtl.h ++++ b/drivers/bluetooth/btrtl.h +@@ -24,6 +24,11 @@ + + struct btrtl_device_info; + ++struct rtl_chip_type_evt { ++ __u8 status; ++ __u8 type; ++} __packed; ++ + struct rtl_download_cmd { + __u8 index; + __u8 data[RTL_FRAG_LEN]; +@@ -69,6 +74,8 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, + struct btrtl_device_info *btrtl_dev, + unsigned int *controller_baudrate, + u32 *device_baudrate, bool *flow_control); ++void btrtl_apply_quirks(struct hci_dev *hdev, ++ struct btrtl_device_info *btrtl_dev); + + #else + +@@ -100,6 +107,11 @@ static inline int btrtl_get_uart_settings(struct hci_dev *hdev, + bool *flow_control) + { + return -ENOENT; ++ ++static inline void btrtl_apply_quirks(struct hci_dev *hdev, ++ struct btrtl_device_info *btrtl_dev) ++{ ++} + } + + #endif +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 9cc10e299fa8..7d72e092ce9d 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -892,6 +892,10 @@ static int h5_btrtl_setup(struct h5 *h5) + err = btrtl_download_firmware(h5->hu->hdev, btrtl_dev); + /* Give the device some time before the hci-core sends it a reset */ + usleep_range(10000, 20000); ++ if (err) ++ goto out_free; ++ ++ btrtl_apply_quirks(h5->hu->hdev, btrtl_dev); + + out_free: + btrtl_free(btrtl_dev); +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0144-arm64-allwinner-a64-enable-Bluetooth-On-Pinebook.patch.disabled b/patch/kernel/sunxi-dev/0144-arm64-allwinner-a64-enable-Bluetooth-On-Pinebook.patch.disabled new file mode 100644 index 000000000..916a02d7a --- /dev/null +++ b/patch/kernel/sunxi-dev/0144-arm64-allwinner-a64-enable-Bluetooth-On-Pinebook.patch.disabled @@ -0,0 +1,44 @@ +From 26b3d6f8ffa77cb05066c11967a498d6dacbdc42 Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 20:43:26 -0700 +Subject: [PATCH 144/146] arm64: allwinner: a64: enable Bluetooth On Pinebook + +Pinebook has an RTL8723CS WiFi + BT chip, BT is connected to UART1 +and uses PL4 as BT reset, PL5 as device wake GPIO, PL6 as host wake GPIO +the I2C controlling signals are connected to R_I2C bus. + +Enable it in the device tree. + +Signed-off-by: Vasily Khoruzhick +--- + .../boot/dts/allwinner/sun50i-a64-pinebook.dts | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +index 0f788400ece0..c1e57597f76a 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +@@ -401,6 +401,20 @@ + status = "okay"; + }; + ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "realtek,rtl8723cs-bt"; ++ reset-gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; /* PL4 */ ++ device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */ ++ host-wake-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ ++ firmware-postfix = "pinebook"; ++ }; ++}; ++ + &usb_otg { + dr_mode = "host"; + }; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0145-arm64-allwinner-a64-enable-Bluetooth-On-Pine64.patch.disabled b/patch/kernel/sunxi-dev/0145-arm64-allwinner-a64-enable-Bluetooth-On-Pine64.patch.disabled new file mode 100644 index 000000000..47cce2654 --- /dev/null +++ b/patch/kernel/sunxi-dev/0145-arm64-allwinner-a64-enable-Bluetooth-On-Pine64.patch.disabled @@ -0,0 +1,40 @@ +From 7f24fdacc41a34b5d1a39ae81f4f39660a5b72ca Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 20:45:16 -0700 +Subject: [PATCH 145/146] arm64: allwinner: a64: enable Bluetooth On Pine64 + +Pine64 has optional RTL8723BS WiFi + BT module, BT is connected to UART1 +and uses PL4 as BT reset, PL5 as device wake GPIO, PL6 as host wake GPIO +the I2C controlling signals are connected to R_I2C bus. + +Enable it in the device tree. + +Signed-off-by: Vasily Khoruzhick +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +index f6fc0ed2f4ec..8e55e81c3236 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts +@@ -333,7 +333,15 @@ + &uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; +- status = "disabled"; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "realtek,rtl8723bs-bt"; ++ reset-gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; /* PL4 */ ++ device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */ ++ host-wake-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ ++ firmware-postfix = "pine64"; ++ }; + }; + + /* On Pi-2 connector */ +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/0146-arm64-allwinner-a64-enable-Bluetooth-On-SoPine-baseb.patch.disabled b/patch/kernel/sunxi-dev/0146-arm64-allwinner-a64-enable-Bluetooth-On-SoPine-baseb.patch.disabled new file mode 100644 index 000000000..827911157 --- /dev/null +++ b/patch/kernel/sunxi-dev/0146-arm64-allwinner-a64-enable-Bluetooth-On-SoPine-baseb.patch.disabled @@ -0,0 +1,45 @@ +From b325cd227f2426f938a08168b5c1b40111562e9e Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Wed, 31 Oct 2018 20:50:09 -0700 +Subject: [PATCH 146/146] arm64: allwinner: a64: enable Bluetooth On SoPine + baseboard + +SoPine has optional RTL8723BS WiFi + BT module, BT is connected to UART1 +and uses PL4 as BT reset, PL5 as device wake GPIO, PL6 as host wake GPIO +the I2C controlling signals are connected to R_I2C bus. + +Enable it in the device tree. + +Signed-off-by: Vasily Khoruzhick +--- + .../dts/allwinner/sun50i-a64-sopine-baseboard.dts | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +index 9010bd58af1b..590a77769cde 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +@@ -230,6 +230,20 @@ + status = "okay"; + }; + ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "realtek,rtl8723bs-bt"; ++ reset-gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; /* PL4 */ ++ device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */ ++ host-wake-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ ++ firmware-postfix = "pine64"; ++ }; ++}; ++ + &usb_otg { + dr_mode = "host"; + status = "okay"; +-- +2.17.1 + diff --git a/patch/kernel/sunxi-dev/board-a10-lime-a10-add-240-mhz-cpufreq.patch b/patch/kernel/sunxi-dev/board-a10-lime-a10-add-240-mhz-cpufreq.patch deleted file mode 100644 index 0b9f124f3..000000000 --- a/patch/kernel/sunxi-dev/board-a10-lime-a10-add-240-mhz-cpufreq.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts -index b350448..f65742d 100644 ---- a/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts -+++ b/arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts -@@ -86,6 +86,7 @@ - 912000 1350000 - 864000 1300000 - 624000 1250000 -+ 240000 1150000 - >; - cooling-max-level = <2>; - }; diff --git a/patch/kernel/sunxi-dev/board-a64-v3-01-19-arm64-dts-allwinner-a64-Add-L2-cache-nodes.patch b/patch/kernel/sunxi-dev/board-a64-v3-01-19-arm64-dts-allwinner-a64-Add-L2-cache-nodes.patch index 780cd552d..5608decbb 100644 --- a/patch/kernel/sunxi-dev/board-a64-v3-01-19-arm64-dts-allwinner-a64-Add-L2-cache-nodes.patch +++ b/patch/kernel/sunxi-dev/board-a64-v3-01-19-arm64-dts-allwinner-a64-Add-L2-cache-nodes.patch @@ -2,40 +2,41 @@ diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts index d3daf90a8715..934d7e87fa08 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -88,6 +88,7 @@ - device_type = "cpu"; - reg = <0>; - enable-method = "psci"; +@@ -134,6 +134,7 @@ + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; + next-level-cache = <&L2>; }; cpu1: cpu@1 { -@@ -95,6 +96,7 @@ - device_type = "cpu"; +@@ -142,6 +143,7 @@ reg = <1>; enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + next-level-cache = <&L2>; }; cpu2: cpu@2 { -@@ -102,6 +104,7 @@ - device_type = "cpu"; +@@ -150,6 +152,7 @@ reg = <2>; enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + next-level-cache = <&L2>; }; cpu3: cpu@3 { -@@ -109,6 +112,12 @@ - device_type = "cpu"; +@@ -158,7 +161,13 @@ reg = <3>; enable-method = "psci"; + operating-points-v2 = <&cpu0_opp_table>; + next-level-cache = <&L2>; -+ }; -+ + }; ++ + L2: l2-cache { + compatible = "cache"; + cache-level = <2>; - }; ++ }; }; + de: display-engine { diff --git a/patch/kernel/sunxi-dev/board-a64-v3-15-19-arm64-dts-allwinner-a64-Olinuxino-enable-USB.patch b/patch/kernel/sunxi-dev/board-a64-v3-15-19-arm64-dts-allwinner-a64-Olinuxino-enable-USB.patch index e3304f4e1..1df291a19 100644 --- a/patch/kernel/sunxi-dev/board-a64-v3-15-19-arm64-dts-allwinner-a64-Olinuxino-enable-USB.patch +++ b/patch/kernel/sunxi-dev/board-a64-v3-15-19-arm64-dts-allwinner-a64-Olinuxino-enable-USB.patch @@ -2,8 +2,8 @@ diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64 index 26075b9a76e3..a1c2f06ed474 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts -@@ -59,12 +59,31 @@ - stdout-path = "serial0:115200n8"; +@@ -77,6 +77,17 @@ + regulator-max-microvolt = <3300000>; }; + reg_usb1_vbus: usb1-vbus { @@ -16,10 +16,11 @@ index 26075b9a76e3..a1c2f06ed474 100644 + gpio = <&pio 6 9 GPIO_ACTIVE_HIGH>; /* PG9 */ + status = "okay"; + }; -+ ++ wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ +@@ -98,6 +109,14 @@ }; }; diff --git a/patch/kernel/sunxi-dev/board-h3-address-some-stability-issues.patch b/patch/kernel/sunxi-dev/board-h3-address-some-stability-issues.patch.disabled similarity index 100% rename from patch/kernel/sunxi-dev/board-h3-address-some-stability-issues.patch rename to patch/kernel/sunxi-dev/board-h3-address-some-stability-issues.patch.disabled diff --git a/patch/kernel/sunxi-dev/board-olinuxino-A64-add-eMMC.patch b/patch/kernel/sunxi-dev/board-olinuxino-A64-add-eMMC.patch index d48db6b71..2f3e58a31 100644 --- a/patch/kernel/sunxi-dev/board-olinuxino-A64-add-eMMC.patch +++ b/patch/kernel/sunxi-dev/board-olinuxino-A64-add-eMMC.patch @@ -2,17 +2,17 @@ diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64 index 3b3081b..24cde3d 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts -@@ -58,6 +58,13 @@ - stdout-path = "serial0:115200n8"; +@@ -81,6 +81,13 @@ + status = "okay"; }; - + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; -+ ++ wifi_pwrseq: wifi_pwrseq { compatible = "mmc-pwrseq-simple"; reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */ diff --git a/patch/kernel/sunxi-dev/camera-add-support-for-allwinner-CSI-with-tiny-fix.patch b/patch/kernel/sunxi-dev/camera-add-support-for-allwinner-CSI-with-tiny-fix.patch deleted file mode 100644 index 8ca076b9e..000000000 --- a/patch/kernel/sunxi-dev/camera-add-support-for-allwinner-CSI-with-tiny-fix.patch +++ /dev/null @@ -1,2225 +0,0 @@ -From aed85f7868404f33ccca464d9c38a6634e470acd Mon Sep 17 00:00:00 2001 -From: Yong Deng -Date: Tue, 6 Mar 2018 10:16:02 +0800 -Subject: [PATCH 38/60] media: V3s: Add support for Allwinner CSI. - -Allwinner V3s SoC features two CSI module. CSI0 is used for MIPI CSI-2 -interface and CSI1 is used for parallel interface. This is not -documented in datasheet but by test and guess. - -This patch implement a v4l2 framework driver for it. - -Currently, the driver only support the parallel interface. MIPI-CSI2, -ISP's support are not included in this patch. - -Reviewed-by: Maxime Ripard -Tested-by: Maxime Ripard -Signed-off-by: Yong Deng ---- - MAINTAINERS | 8 + - drivers/media/platform/Kconfig | 1 + - drivers/media/platform/Makefile | 2 + - .../media/platform/sunxi/sun6i-csi/Kconfig | 9 + - .../media/platform/sunxi/sun6i-csi/Makefile | 3 + - .../platform/sunxi/sun6i-csi/sun6i_csi.c | 936 ++++++++++++++++++ - .../platform/sunxi/sun6i-csi/sun6i_csi.h | 145 +++ - .../platform/sunxi/sun6i-csi/sun6i_csi_reg.h | 196 ++++ - .../platform/sunxi/sun6i-csi/sun6i_video.c | 759 ++++++++++++++ - .../platform/sunxi/sun6i-csi/sun6i_video.h | 53 + - 10 files changed, 2112 insertions(+) - create mode 100644 drivers/media/platform/sunxi/sun6i-csi/Kconfig - create mode 100644 drivers/media/platform/sunxi/sun6i-csi/Makefile - create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c - create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h - create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h - create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c - create mode 100644 drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h - -diff --git a/MAINTAINERS b/MAINTAINERS -index 4e62756936fa..9dd1b0c64975 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -3795,6 +3795,14 @@ M: Jaya Kumar - S: Maintained - F: sound/pci/cs5535audio/ - -+CSI DRIVERS FOR ALLWINNER V3s -+M: Yong Deng -+L: linux-media@vger.kernel.org -+T: git git://linuxtv.org/media_tree.git -+S: Maintained -+F: drivers/media/platform/sunxi/sun6i-csi/ -+F: Documentation/devicetree/bindings/media/sun6i-csi.txt -+ - CW1200 WLAN driver - M: Solomon Peachy - S: Maintained -diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 614fbef08ddc..82c9e007051e 100644 ---- a/drivers/media/platform/Kconfig -+++ b/drivers/media/platform/Kconfig -@@ -150,6 +150,7 @@ source "drivers/media/platform/am437x/Kconfig" - source "drivers/media/platform/xilinx/Kconfig" - source "drivers/media/platform/rcar-vin/Kconfig" - source "drivers/media/platform/atmel/Kconfig" -+source "drivers/media/platform/sunxi/sun6i-csi/Kconfig" - - config VIDEO_TI_CAL - tristate "TI CAL (Camera Adaptation Layer) driver" -diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 7f3080437be6..ace8628478ab 100644 ---- a/drivers/media/platform/Makefile -+++ b/drivers/media/platform/Makefile -@@ -95,3 +95,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss-8x16/ - obj-y += meson/ - - obj-y += cros-ec-cec/ -+ -+obj-$(CONFIG_VIDEO_SUN6I_CSI) += sunxi/sun6i-csi/ -diff --git a/drivers/media/platform/sunxi/sun6i-csi/Kconfig b/drivers/media/platform/sunxi/sun6i-csi/Kconfig -new file mode 100644 -index 000000000000..314188aae2c2 ---- /dev/null -+++ b/drivers/media/platform/sunxi/sun6i-csi/Kconfig -@@ -0,0 +1,9 @@ -+config VIDEO_SUN6I_CSI -+ tristate "Allwinner V3s Camera Sensor Interface driver" -+ depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API && HAS_DMA -+ depends on ARCH_SUNXI || COMPILE_TEST -+ select VIDEOBUF2_DMA_CONTIG -+ select REGMAP_MMIO -+ select V4L2_FWNODE -+ ---help--- -+ Support for the Allwinner Camera Sensor Interface Controller on V3s. -diff --git a/drivers/media/platform/sunxi/sun6i-csi/Makefile b/drivers/media/platform/sunxi/sun6i-csi/Makefile -new file mode 100644 -index 000000000000..213cb6be9e9c ---- /dev/null -+++ b/drivers/media/platform/sunxi/sun6i-csi/Makefile -@@ -0,0 +1,3 @@ -+sun6i-csi-y += sun6i_video.o sun6i_csi.o -+ -+obj-$(CONFIG_VIDEO_SUN6I_CSI) += sun6i-csi.o -diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c -new file mode 100644 -index 000000000000..26d57e6053df ---- /dev/null -+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c -@@ -0,0 +1,937 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing) -+ * All rights reserved. -+ * Author: Yong Deng -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sun6i_csi.h" -+#include "sun6i_csi_reg.h" -+ -+#define MODULE_NAME "sun6i-csi" -+ -+struct sun6i_csi_dev { -+ struct sun6i_csi csi; -+ struct device *dev; -+ -+ struct regmap *regmap; -+ struct clk *clk_mod; -+ struct clk *clk_ram; -+ struct reset_control *rstc_bus; -+ -+ int planar_offset[3]; -+}; -+ -+static const u32 supported_pixformats[] = { -+ V4L2_PIX_FMT_SBGGR8, -+ V4L2_PIX_FMT_SGBRG8, -+ V4L2_PIX_FMT_SGRBG8, -+ V4L2_PIX_FMT_SRGGB8, -+ V4L2_PIX_FMT_SBGGR10, -+ V4L2_PIX_FMT_SGBRG10, -+ V4L2_PIX_FMT_SGRBG10, -+ V4L2_PIX_FMT_SRGGB10, -+ V4L2_PIX_FMT_SBGGR12, -+ V4L2_PIX_FMT_SGBRG12, -+ V4L2_PIX_FMT_SGRBG12, -+ V4L2_PIX_FMT_SRGGB12, -+ V4L2_PIX_FMT_YUYV, -+ V4L2_PIX_FMT_YVYU, -+ V4L2_PIX_FMT_UYVY, -+ V4L2_PIX_FMT_VYUY, -+ V4L2_PIX_FMT_HM12, -+ V4L2_PIX_FMT_NV12, -+ V4L2_PIX_FMT_NV21, -+ V4L2_PIX_FMT_YUV420, -+ V4L2_PIX_FMT_YVU420, -+ V4L2_PIX_FMT_NV16, -+ V4L2_PIX_FMT_NV61, -+ V4L2_PIX_FMT_YUV422P, -+}; -+ -+static inline struct sun6i_csi_dev *sun6i_csi_to_dev(struct sun6i_csi *csi) -+{ -+ return container_of(csi, struct sun6i_csi_dev, csi); -+} -+ -+int sun6i_csi_get_supported_pixformats(struct sun6i_csi *csi, -+ const u32 **pixformats) -+{ -+ if (pixformats != NULL) -+ *pixformats = supported_pixformats; -+ -+ return ARRAY_SIZE(supported_pixformats); -+} -+ -+/* TODO add 10&12 bit YUV, RGB support */ -+bool sun6i_csi_is_format_support(struct sun6i_csi *csi, -+ u32 pixformat, u32 mbus_code) -+{ -+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi); -+ -+ /* -+ * Some video receivers have the ability to be compatible with -+ * 8bit and 16bit bus width. -+ * Identify the media bus format from device tree. -+ */ -+ if ((sdev->csi.v4l2_ep.bus_type == V4L2_MBUS_PARALLEL -+ || sdev->csi.v4l2_ep.bus_type == V4L2_MBUS_BT656) -+ && sdev->csi.v4l2_ep.bus.parallel.bus_width == 16) { -+ switch (pixformat) { -+ case V4L2_PIX_FMT_HM12: -+ case V4L2_PIX_FMT_NV12: -+ case V4L2_PIX_FMT_NV21: -+ case V4L2_PIX_FMT_NV16: -+ case V4L2_PIX_FMT_NV61: -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YVU420: -+ case V4L2_PIX_FMT_YUV422P: -+ switch (mbus_code) { -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ case MEDIA_BUS_FMT_VYUY8_1X16: -+ case MEDIA_BUS_FMT_YUYV8_1X16: -+ case MEDIA_BUS_FMT_YVYU8_1X16: -+ return true; -+ default: -+ dev_dbg(sdev->dev, "Unsupported mbus code: 0x%x\n", -+ mbus_code); -+ break; -+ } -+ break; -+ default: -+ dev_dbg(sdev->dev, "Unsupported pixformat: 0x%x\n", -+ pixformat); -+ break; -+ } -+ return false; -+ } -+ -+ switch (pixformat) { -+ case V4L2_PIX_FMT_SBGGR8: -+ return (mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8); -+ case V4L2_PIX_FMT_SGBRG8: -+ return (mbus_code == MEDIA_BUS_FMT_SGBRG8_1X8); -+ case V4L2_PIX_FMT_SGRBG8: -+ return (mbus_code == MEDIA_BUS_FMT_SGRBG8_1X8); -+ case V4L2_PIX_FMT_SRGGB8: -+ return (mbus_code == MEDIA_BUS_FMT_SRGGB8_1X8); -+ case V4L2_PIX_FMT_SBGGR10: -+ return (mbus_code == MEDIA_BUS_FMT_SBGGR10_1X10); -+ case V4L2_PIX_FMT_SGBRG10: -+ return (mbus_code == MEDIA_BUS_FMT_SGBRG10_1X10); -+ case V4L2_PIX_FMT_SGRBG10: -+ return (mbus_code == MEDIA_BUS_FMT_SGRBG10_1X10); -+ case V4L2_PIX_FMT_SRGGB10: -+ return (mbus_code == MEDIA_BUS_FMT_SRGGB10_1X10); -+ case V4L2_PIX_FMT_SBGGR12: -+ return (mbus_code == MEDIA_BUS_FMT_SBGGR12_1X12); -+ case V4L2_PIX_FMT_SGBRG12: -+ return (mbus_code == MEDIA_BUS_FMT_SGBRG12_1X12); -+ case V4L2_PIX_FMT_SGRBG12: -+ return (mbus_code == MEDIA_BUS_FMT_SGRBG12_1X12); -+ case V4L2_PIX_FMT_SRGGB12: -+ return (mbus_code == MEDIA_BUS_FMT_SRGGB12_1X12); -+ -+ case V4L2_PIX_FMT_YUYV: -+ return (mbus_code == MEDIA_BUS_FMT_YUYV8_2X8); -+ case V4L2_PIX_FMT_YVYU: -+ return (mbus_code == MEDIA_BUS_FMT_YVYU8_2X8); -+ case V4L2_PIX_FMT_UYVY: -+ return (mbus_code == MEDIA_BUS_FMT_UYVY8_2X8); -+ case V4L2_PIX_FMT_VYUY: -+ return (mbus_code == MEDIA_BUS_FMT_VYUY8_2X8); -+ -+ case V4L2_PIX_FMT_HM12: -+ case V4L2_PIX_FMT_NV12: -+ case V4L2_PIX_FMT_NV21: -+ case V4L2_PIX_FMT_NV16: -+ case V4L2_PIX_FMT_NV61: -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YVU420: -+ case V4L2_PIX_FMT_YUV422P: -+ switch (mbus_code) { -+ case MEDIA_BUS_FMT_UYVY8_2X8: -+ case MEDIA_BUS_FMT_VYUY8_2X8: -+ case MEDIA_BUS_FMT_YUYV8_2X8: -+ case MEDIA_BUS_FMT_YVYU8_2X8: -+ return true; -+ default: -+ dev_dbg(sdev->dev, "Unsupported mbus code: 0x%x\n", -+ mbus_code); -+ break; -+ } -+ break; -+ default: -+ dev_dbg(sdev->dev, "Unsupported pixformat: 0x%x\n", pixformat); -+ break; -+ } -+ -+ return false; -+} -+ -+int sun6i_csi_set_power(struct sun6i_csi *csi, bool enable) -+{ -+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi); -+ struct regmap *regmap = sdev->regmap; -+ int ret; -+ -+ if (!enable) { -+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0); -+ -+ clk_disable_unprepare(sdev->clk_ram); -+ clk_disable_unprepare(sdev->clk_mod); -+ reset_control_assert(sdev->rstc_bus); -+ return 0; -+ } -+ -+ ret = clk_prepare_enable(sdev->clk_mod); -+ if (ret) { -+ dev_err(sdev->dev, "Enable csi clk err %d\n", ret); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(sdev->clk_ram); -+ if (ret) { -+ dev_err(sdev->dev, "Enable clk_dram_csi clk err %d\n", ret); -+ return ret; -+ } -+ -+ ret = reset_control_deassert(sdev->rstc_bus); -+ if (ret) { -+ dev_err(sdev->dev, "reset err %d\n", ret); -+ return ret; -+ } -+ -+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, CSI_EN_CSI_EN); -+ -+ return 0; -+} -+ -+static enum csi_input_fmt get_csi_input_format(struct sun6i_csi_dev *sdev, -+ u32 mbus_code, u32 pixformat) -+{ -+ /* bayer */ -+ if ((mbus_code & 0xF000) == 0x3000) -+ return CSI_INPUT_FORMAT_RAW; -+ -+ switch (pixformat) { -+ case V4L2_PIX_FMT_YUYV: -+ case V4L2_PIX_FMT_YVYU: -+ case V4L2_PIX_FMT_UYVY: -+ case V4L2_PIX_FMT_VYUY: -+ return CSI_INPUT_FORMAT_RAW; -+ default: -+ break; -+ } -+ -+ /* not support YUV420 input format yet */ -+ dev_dbg(sdev->dev, "Select YUV422 as default input format of CSI.\n"); -+ return CSI_INPUT_FORMAT_YUV422; -+} -+ -+static enum csi_output_fmt get_csi_output_format(struct sun6i_csi_dev *sdev, -+ u32 pixformat, u32 field) -+{ -+ bool buf_interlaced = false; -+ -+ if (field == V4L2_FIELD_INTERLACED -+ || field == V4L2_FIELD_INTERLACED_TB -+ || field == V4L2_FIELD_INTERLACED_BT) -+ buf_interlaced = true; -+ -+ switch (pixformat) { -+ case V4L2_PIX_FMT_SBGGR8: -+ case V4L2_PIX_FMT_SGBRG8: -+ case V4L2_PIX_FMT_SGRBG8: -+ case V4L2_PIX_FMT_SRGGB8: -+ return buf_interlaced ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8; -+ case V4L2_PIX_FMT_SBGGR10: -+ case V4L2_PIX_FMT_SGBRG10: -+ case V4L2_PIX_FMT_SGRBG10: -+ case V4L2_PIX_FMT_SRGGB10: -+ return buf_interlaced ? CSI_FRAME_RAW_10 : CSI_FIELD_RAW_10; -+ case V4L2_PIX_FMT_SBGGR12: -+ case V4L2_PIX_FMT_SGBRG12: -+ case V4L2_PIX_FMT_SGRBG12: -+ case V4L2_PIX_FMT_SRGGB12: -+ return buf_interlaced ? CSI_FRAME_RAW_12 : CSI_FIELD_RAW_12; -+ -+ case V4L2_PIX_FMT_YUYV: -+ case V4L2_PIX_FMT_YVYU: -+ case V4L2_PIX_FMT_UYVY: -+ case V4L2_PIX_FMT_VYUY: -+ return buf_interlaced ? CSI_FRAME_RAW_8 : CSI_FIELD_RAW_8; -+ -+ case V4L2_PIX_FMT_HM12: -+ return buf_interlaced ? CSI_FRAME_MB_YUV420 : -+ CSI_FIELD_MB_YUV420; -+ case V4L2_PIX_FMT_NV12: -+ case V4L2_PIX_FMT_NV21: -+ return buf_interlaced ? CSI_FRAME_UV_CB_YUV420 : -+ CSI_FIELD_UV_CB_YUV420; -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YVU420: -+ return buf_interlaced ? CSI_FRAME_PLANAR_YUV420 : -+ CSI_FIELD_PLANAR_YUV420; -+ case V4L2_PIX_FMT_NV16: -+ case V4L2_PIX_FMT_NV61: -+ return buf_interlaced ? CSI_FRAME_UV_CB_YUV422 : -+ CSI_FIELD_UV_CB_YUV422; -+ case V4L2_PIX_FMT_YUV422P: -+ return buf_interlaced ? CSI_FRAME_PLANAR_YUV422 : -+ CSI_FIELD_PLANAR_YUV422; -+ default: -+ dev_warn(sdev->dev, "Unsupported pixformat: 0x%x\n", pixformat); -+ break; -+ } -+ -+ return CSI_FIELD_RAW_8; -+} -+ -+static enum csi_input_seq get_csi_input_seq(struct sun6i_csi_dev *sdev, -+ u32 mbus_code, u32 pixformat) -+{ -+ -+ switch (pixformat) { -+ case V4L2_PIX_FMT_HM12: -+ case V4L2_PIX_FMT_NV12: -+ case V4L2_PIX_FMT_NV16: -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YUV422P: -+ switch (mbus_code) { -+ case MEDIA_BUS_FMT_UYVY8_2X8: -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ return CSI_INPUT_SEQ_UYVY; -+ case MEDIA_BUS_FMT_VYUY8_2X8: -+ case MEDIA_BUS_FMT_VYUY8_1X16: -+ return CSI_INPUT_SEQ_VYUY; -+ case MEDIA_BUS_FMT_YUYV8_2X8: -+ case MEDIA_BUS_FMT_YUYV8_1X16: -+ return CSI_INPUT_SEQ_YUYV; -+ case MEDIA_BUS_FMT_YVYU8_1X16: -+ case MEDIA_BUS_FMT_YVYU8_2X8: -+ return CSI_INPUT_SEQ_YVYU; -+ default: -+ dev_warn(sdev->dev, "Unsupported mbus code: 0x%x\n", -+ mbus_code); -+ break; -+ } -+ break; -+ case V4L2_PIX_FMT_NV21: -+ case V4L2_PIX_FMT_NV61: -+ case V4L2_PIX_FMT_YVU420: -+ switch (mbus_code) { -+ case MEDIA_BUS_FMT_UYVY8_2X8: -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ return CSI_INPUT_SEQ_VYUY; -+ case MEDIA_BUS_FMT_VYUY8_2X8: -+ case MEDIA_BUS_FMT_VYUY8_1X16: -+ return CSI_INPUT_SEQ_UYVY; -+ case MEDIA_BUS_FMT_YUYV8_2X8: -+ case MEDIA_BUS_FMT_YUYV8_1X16: -+ return CSI_INPUT_SEQ_YVYU; -+ case MEDIA_BUS_FMT_YVYU8_1X16: -+ case MEDIA_BUS_FMT_YVYU8_2X8: -+ return CSI_INPUT_SEQ_YUYV; -+ default: -+ dev_warn(sdev->dev, "Unsupported mbus code: 0x%x\n", -+ mbus_code); -+ break; -+ } -+ break; -+ -+ case V4L2_PIX_FMT_YUYV: -+ return CSI_INPUT_SEQ_YUYV; -+ -+ default: -+ dev_warn(sdev->dev, "Unsupported pixformat: 0x%x, defaulting to YUYV\n", -+ pixformat); -+ break; -+ } -+ -+ return CSI_INPUT_SEQ_YUYV; -+} -+ -+static void sun6i_csi_setup_bus(struct sun6i_csi_dev *sdev) -+{ -+ struct v4l2_fwnode_endpoint *endpoint = &sdev->csi.v4l2_ep; -+ unsigned char bus_width; -+ u32 flags; -+ u32 cfg; -+ -+ bus_width = endpoint->bus.parallel.bus_width; -+ -+ regmap_read(sdev->regmap, CSI_IF_CFG_REG, &cfg); -+ -+ cfg &= ~(CSI_IF_CFG_CSI_IF_MASK | CSI_IF_CFG_MIPI_IF_MASK | -+ CSI_IF_CFG_IF_DATA_WIDTH_MASK | -+ CSI_IF_CFG_CLK_POL_MASK | CSI_IF_CFG_VREF_POL_MASK | -+ CSI_IF_CFG_HREF_POL_MASK | CSI_IF_CFG_FIELD_MASK); -+ -+ switch (endpoint->bus_type) { -+ case V4L2_MBUS_PARALLEL: -+ cfg |= CSI_IF_CFG_MIPI_IF_CSI; -+ -+ flags = endpoint->bus.parallel.flags; -+ -+ cfg |= (bus_width == 16) ? CSI_IF_CFG_CSI_IF_YUV422_16BIT : -+ CSI_IF_CFG_CSI_IF_YUV422_INTLV; -+ -+ if (flags & V4L2_MBUS_FIELD_EVEN_LOW) -+ cfg |= CSI_IF_CFG_FIELD_POSITIVE; -+ -+ if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) -+ cfg |= CSI_IF_CFG_VREF_POL_POSITIVE; -+ if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) -+ cfg |= CSI_IF_CFG_HREF_POL_POSITIVE; -+ -+ if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) -+ cfg |= CSI_IF_CFG_CLK_POL_FALLING_EDGE; -+ break; -+ case V4L2_MBUS_BT656: -+ cfg |= CSI_IF_CFG_MIPI_IF_CSI; -+ -+ flags = endpoint->bus.parallel.flags; -+ -+ cfg |= (bus_width == 16) ? CSI_IF_CFG_CSI_IF_BT1120 : -+ CSI_IF_CFG_CSI_IF_BT656; -+ -+ if (flags & V4L2_MBUS_FIELD_EVEN_LOW) -+ cfg |= CSI_IF_CFG_FIELD_POSITIVE; -+ -+ if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) -+ cfg |= CSI_IF_CFG_CLK_POL_FALLING_EDGE; -+ break; -+ default: -+ dev_warn(sdev->dev, "Unsupported bus type: %d\n", -+ endpoint->bus_type); -+ break; -+ } -+ -+ switch (bus_width) { -+ case 8: -+ cfg |= CSI_IF_CFG_IF_DATA_WIDTH_8BIT; -+ break; -+ case 10: -+ cfg |= CSI_IF_CFG_IF_DATA_WIDTH_10BIT; -+ break; -+ case 12: -+ cfg |= CSI_IF_CFG_IF_DATA_WIDTH_12BIT; -+ break; -+ case 16: /* No need to configure DATA_WIDTH for 16bit */ -+ break; -+ default: -+ dev_warn(sdev->dev, "Unsupported bus width: %d\n", bus_width); -+ break; -+ } -+ -+ regmap_write(sdev->regmap, CSI_IF_CFG_REG, cfg); -+} -+ -+static void sun6i_csi_set_format(struct sun6i_csi_dev *sdev) -+{ -+ struct sun6i_csi *csi = &sdev->csi; -+ u32 cfg; -+ u32 val; -+ -+ regmap_read(sdev->regmap, CSI_CH_CFG_REG, &cfg); -+ -+ cfg &= ~(CSI_CH_CFG_INPUT_FMT_MASK | -+ CSI_CH_CFG_OUTPUT_FMT_MASK | CSI_CH_CFG_VFLIP_EN | -+ CSI_CH_CFG_HFLIP_EN | CSI_CH_CFG_FIELD_SEL_MASK | -+ CSI_CH_CFG_INPUT_SEQ_MASK); -+ -+ val = get_csi_input_format(sdev, csi->config.code, -+ csi->config.pixelformat); -+ cfg |= CSI_CH_CFG_INPUT_FMT(val); -+ -+ val = get_csi_output_format(sdev, csi->config.pixelformat, -+ csi->config.field); -+ cfg |= CSI_CH_CFG_OUTPUT_FMT(val); -+ -+ val = get_csi_input_seq(sdev, csi->config.code, -+ csi->config.pixelformat); -+ cfg |= CSI_CH_CFG_INPUT_SEQ(val); -+ -+ if (csi->config.field == V4L2_FIELD_TOP) -+ cfg |= CSI_CH_CFG_FIELD_SEL_FIELD0; -+ else if (csi->config.field == V4L2_FIELD_BOTTOM) -+ cfg |= CSI_CH_CFG_FIELD_SEL_FIELD1; -+ else -+ cfg |= CSI_CH_CFG_FIELD_SEL_BOTH; -+ -+ regmap_write(sdev->regmap, CSI_CH_CFG_REG, cfg); -+} -+ -+static void sun6i_csi_set_window(struct sun6i_csi_dev *sdev) -+{ -+ struct sun6i_csi_config *config = &sdev->csi.config; -+ u32 bytesperline_y; -+ u32 bytesperline_c; -+ int *planar_offset = sdev->planar_offset; -+ u32 width = config->width; -+ u32 height = config->height; -+ u32 hor_len = width; -+ -+ switch (config->pixelformat) { -+ case V4L2_PIX_FMT_YUYV: -+ case V4L2_PIX_FMT_YVYU: -+ case V4L2_PIX_FMT_UYVY: -+ case V4L2_PIX_FMT_VYUY: -+ dev_dbg(sdev->dev, -+ "Horizontal length should be 2 times of width for packed YUV formats!\n"); -+ hor_len = width * 2; -+ break; -+ default: -+ break; -+ } -+ -+ regmap_write(sdev->regmap, CSI_CH_HSIZE_REG, -+ CSI_CH_HSIZE_HOR_LEN(hor_len) | -+ CSI_CH_HSIZE_HOR_START(0)); -+ regmap_write(sdev->regmap, CSI_CH_VSIZE_REG, -+ CSI_CH_VSIZE_VER_LEN(height) | -+ CSI_CH_VSIZE_VER_START(0)); -+ -+ planar_offset[0] = 0; -+ switch (config->pixelformat) { -+ case V4L2_PIX_FMT_HM12: -+ case V4L2_PIX_FMT_NV12: -+ case V4L2_PIX_FMT_NV21: -+ case V4L2_PIX_FMT_NV16: -+ case V4L2_PIX_FMT_NV61: -+ bytesperline_y = width; -+ bytesperline_c = width; -+ planar_offset[1] = bytesperline_y * height; -+ planar_offset[2] = -1; -+ break; -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YVU420: -+ bytesperline_y = width; -+ bytesperline_c = width / 2; -+ planar_offset[1] = bytesperline_y * height; -+ planar_offset[2] = planar_offset[1] + -+ bytesperline_c * height / 2; -+ break; -+ case V4L2_PIX_FMT_YUV422P: -+ bytesperline_y = width; -+ bytesperline_c = width / 2; -+ planar_offset[1] = bytesperline_y * height; -+ planar_offset[2] = planar_offset[1] + -+ bytesperline_c * height; -+ break; -+ default: /* raw */ -+ dev_dbg(sdev->dev, -+ "Calculating pixelformat(0x%x)'s bytesperline as a packed format\n", -+ config->pixelformat); -+ bytesperline_y = (sun6i_csi_get_bpp(config->pixelformat) * -+ config->width) / 8; -+ bytesperline_c = 0; -+ planar_offset[1] = -1; -+ planar_offset[2] = -1; -+ break; -+ } -+ -+ regmap_write(sdev->regmap, CSI_CH_BUF_LEN_REG, -+ CSI_CH_BUF_LEN_BUF_LEN_C(bytesperline_c) | -+ CSI_CH_BUF_LEN_BUF_LEN_Y(bytesperline_y)); -+} -+ -+int sun6i_csi_update_config(struct sun6i_csi *csi, -+ struct sun6i_csi_config *config) -+{ -+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi); -+ -+ if (config == NULL) -+ return -EINVAL; -+ -+ memcpy(&csi->config, config, sizeof(csi->config)); -+ -+ sun6i_csi_setup_bus(sdev); -+ sun6i_csi_set_format(sdev); -+ sun6i_csi_set_window(sdev); -+ -+ return 0; -+} -+ -+void sun6i_csi_update_buf_addr(struct sun6i_csi *csi, dma_addr_t addr) -+{ -+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi); -+ -+ regmap_write(sdev->regmap, CSI_CH_F0_BUFA_REG, -+ (addr + sdev->planar_offset[0]) >> 2); -+ if (sdev->planar_offset[1] != -1) -+ regmap_write(sdev->regmap, CSI_CH_F1_BUFA_REG, -+ (addr + sdev->planar_offset[1]) >> 2); -+ if (sdev->planar_offset[2] != -1) -+ regmap_write(sdev->regmap, CSI_CH_F2_BUFA_REG, -+ (addr + sdev->planar_offset[2]) >> 2); -+} -+ -+void sun6i_csi_set_stream(struct sun6i_csi *csi, bool enable) -+{ -+ struct sun6i_csi_dev *sdev = sun6i_csi_to_dev(csi); -+ struct regmap *regmap = sdev->regmap; -+ -+ if (!enable) { -+ regmap_update_bits(regmap, CSI_CAP_REG, CSI_CAP_CH0_VCAP_ON, 0); -+ regmap_write(regmap, CSI_CH_INT_EN_REG, 0); -+ return; -+ } -+ -+ regmap_write(regmap, CSI_CH_INT_STA_REG, 0xFF); -+ regmap_write(regmap, CSI_CH_INT_EN_REG, -+ CSI_CH_INT_EN_HB_OF_INT_EN | -+ CSI_CH_INT_EN_FIFO2_OF_INT_EN | -+ CSI_CH_INT_EN_FIFO1_OF_INT_EN | -+ CSI_CH_INT_EN_FIFO0_OF_INT_EN | -+ CSI_CH_INT_EN_FD_INT_EN | -+ CSI_CH_INT_EN_CD_INT_EN); -+ -+ regmap_update_bits(regmap, CSI_CAP_REG, CSI_CAP_CH0_VCAP_ON, -+ CSI_CAP_CH0_VCAP_ON); -+} -+ -+/* ----------------------------------------------------------------------------- -+ * Media Controller and V4L2 -+ */ -+static int sun6i_csi_link_entity(struct sun6i_csi *csi, -+ struct media_entity *entity) -+{ -+ struct media_entity *sink; -+ struct media_pad *sink_pad; -+ int ret; -+ int i; -+ -+ if (!entity->num_pads) { -+ dev_err(csi->dev, "%s: invalid entity\n", entity->name); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < entity->num_pads; i++) { -+ if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE) -+ break; -+ } -+ -+ if (i == entity->num_pads) { -+ dev_err(csi->dev, "%s: no source pad in external entity %s\n", -+ __func__, entity->name); -+ return -EINVAL; -+ } -+ -+ sink = &csi->video.vdev.entity; -+ sink_pad = &csi->video.pad; -+ -+ dev_dbg(csi->dev, "creating %s:%u -> %s:%u link\n", -+ entity->name, i, sink->name, sink_pad->index); -+ ret = media_create_pad_link(entity, i, sink, sink_pad->index, -+ MEDIA_LNK_FL_ENABLED); -+ if (ret < 0) { -+ dev_err(csi->dev, "failed to create %s:%u -> %s:%u link\n", -+ entity->name, i, sink->name, sink_pad->index); -+ return ret; -+ } -+ -+ return media_entity_call(sink, link_setup, sink_pad, &entity->pads[i], -+ MEDIA_LNK_FL_ENABLED); -+} -+ -+static int sun6i_subdev_notify_complete(struct v4l2_async_notifier *notifier) -+{ -+ struct sun6i_csi *csi = container_of(notifier, struct sun6i_csi, -+ notifier); -+ struct v4l2_device *v4l2_dev = &csi->v4l2_dev; -+ struct v4l2_subdev *sd; -+ int ret; -+ -+ dev_dbg(csi->dev, "notify complete, all subdevs registered\n"); -+ -+ if (notifier->num_subdevs != 1) -+ return -EINVAL; -+ -+ sd = list_first_entry(&v4l2_dev->subdevs, struct v4l2_subdev, list); -+ if (sd == NULL) -+ return -EINVAL; -+ -+ ret = sun6i_csi_link_entity(csi, &sd->entity); -+ if (ret < 0) -+ return ret; -+ -+ ret = v4l2_device_register_subdev_nodes(&csi->v4l2_dev); -+ if (ret < 0) -+ return ret; -+ -+ return media_device_register(&csi->media_dev); -+} -+ -+static const struct v4l2_async_notifier_operations sun6i_csi_async_ops = { -+ .complete = sun6i_subdev_notify_complete, -+}; -+ -+static int sun6i_csi_fwnode_parse(struct device *dev, -+ struct v4l2_fwnode_endpoint *vep, -+ struct v4l2_async_subdev *asd) -+{ -+ struct sun6i_csi *csi = dev_get_drvdata(dev); -+ -+ if (vep->base.port || vep->base.id) { -+ dev_warn(dev, "Only support a single port with one endpoint\n"); -+ return -ENOTCONN; -+ } -+ -+ switch (vep->bus_type) { -+ case V4L2_MBUS_PARALLEL: -+ case V4L2_MBUS_BT656: -+ csi->v4l2_ep = *vep; -+ return 0; -+ default: -+ dev_err(dev, "Unsupported media bus type\n"); -+ return -ENOTCONN; -+ } -+} -+ -+static void sun6i_csi_v4l2_cleanup(struct sun6i_csi *csi) -+{ -+ v4l2_async_notifier_cleanup(&csi->notifier); -+ v4l2_async_notifier_unregister(&csi->notifier); -+ sun6i_video_cleanup(&csi->video); -+ v4l2_device_unregister(&csi->v4l2_dev); -+ media_device_unregister(&csi->media_dev); -+ media_device_cleanup(&csi->media_dev); -+} -+ -+static int sun6i_csi_v4l2_init(struct sun6i_csi *csi) -+{ -+ int ret; -+ -+ csi->media_dev.dev = csi->dev; -+ strlcpy(csi->media_dev.model, "Allwinner Video Capture Device", -+ sizeof(csi->media_dev.model)); -+ csi->media_dev.hw_revision = 0; -+ -+ media_device_init(&csi->media_dev); -+ -+ ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 0); -+ if (ret) { -+ dev_err(csi->dev, "V4L2 controls handler init failed (%d)\n", -+ ret); -+ goto clean_media; -+ } -+ -+ csi->v4l2_dev.mdev = &csi->media_dev; -+ csi->v4l2_dev.ctrl_handler = &csi->ctrl_handler; -+ ret = v4l2_device_register(csi->dev, &csi->v4l2_dev); -+ if (ret) { -+ dev_err(csi->dev, "V4L2 device registration failed (%d)\n", -+ ret); -+ goto clean_media; -+ } -+ -+ ret = sun6i_video_init(&csi->video, csi, "sun6i-csi"); -+ if (ret) -+ goto unreg_v4l2; -+ -+ ret = v4l2_async_notifier_parse_fwnode_endpoints( -+ csi->dev, &csi->notifier, sizeof(struct v4l2_async_subdev), -+ sun6i_csi_fwnode_parse); -+ if (ret) -+ goto clean_video; -+ -+ csi->notifier.ops = &sun6i_csi_async_ops; -+ -+ ret = v4l2_async_notifier_register(&csi->v4l2_dev, &csi->notifier); -+ if (ret) { -+ dev_err(csi->dev, "notifier registration failed\n"); -+ goto clean_notifier; -+ } -+ -+ return 0; -+ -+clean_notifier: -+ v4l2_async_notifier_cleanup(&csi->notifier); -+clean_video: -+ sun6i_video_cleanup(&csi->video); -+unreg_v4l2: -+ v4l2_device_unregister(&csi->v4l2_dev); -+clean_media: -+ media_device_cleanup(&csi->media_dev); -+ -+ return ret; -+} -+ -+/* ----------------------------------------------------------------------------- -+ * Resources and IRQ -+ */ -+static irqreturn_t sun6i_csi_isr(int irq, void *dev_id) -+{ -+ struct sun6i_csi_dev *sdev = (struct sun6i_csi_dev *)dev_id; -+ struct regmap *regmap = sdev->regmap; -+ u32 status; -+ -+ regmap_read(regmap, CSI_CH_INT_STA_REG, &status); -+ -+ if (!(status & 0xFF)) -+ return IRQ_NONE; -+ -+ if ((status & CSI_CH_INT_STA_FIFO0_OF_PD) || -+ (status & CSI_CH_INT_STA_FIFO1_OF_PD) || -+ (status & CSI_CH_INT_STA_FIFO2_OF_PD) || -+ (status & CSI_CH_INT_STA_HB_OF_PD)) { -+ regmap_write(regmap, CSI_CH_INT_STA_REG, status); -+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0); -+ regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, -+ CSI_EN_CSI_EN); -+ return IRQ_HANDLED; -+ } -+ -+ if (status & CSI_CH_INT_STA_FD_PD) -+ sun6i_video_frame_done(&sdev->csi.video); -+ -+ regmap_write(regmap, CSI_CH_INT_STA_REG, status); -+ -+ return IRQ_HANDLED; -+} -+ -+static const struct regmap_config sun6i_csi_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x1000, -+}; -+ -+static int sun6i_csi_resource_request(struct sun6i_csi_dev *sdev, -+ struct platform_device *pdev) -+{ -+ struct resource *res; -+ void __iomem *io_base; -+ int ret; -+ int irq; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ io_base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(io_base)) -+ return PTR_ERR(io_base); -+ -+ sdev->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", io_base, -+ &sun6i_csi_regmap_config); -+ if (IS_ERR(sdev->regmap)) { -+ dev_err(&pdev->dev, "Failed to init register map\n"); -+ return PTR_ERR(sdev->regmap); -+ } -+ -+ sdev->clk_mod = devm_clk_get(&pdev->dev, "mod"); -+ if (IS_ERR(sdev->clk_mod)) { -+ dev_err(&pdev->dev, "Unable to acquire csi clock\n"); -+ return PTR_ERR(sdev->clk_mod); -+ } -+ -+ sdev->clk_ram = devm_clk_get(&pdev->dev, "ram"); -+ if (IS_ERR(sdev->clk_ram)) { -+ dev_err(&pdev->dev, "Unable to acquire dram-csi clock\n"); -+ return PTR_ERR(sdev->clk_ram); -+ } -+ -+ sdev->rstc_bus = devm_reset_control_get_shared(&pdev->dev, NULL); -+ if (IS_ERR(sdev->rstc_bus)) { -+ dev_err(&pdev->dev, "Cannot get reset controller\n"); -+ return PTR_ERR(sdev->rstc_bus); -+ } -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(&pdev->dev, "No csi IRQ specified\n"); -+ ret = -ENXIO; -+ return ret; -+ } -+ -+ ret = devm_request_irq(&pdev->dev, irq, sun6i_csi_isr, 0, MODULE_NAME, -+ sdev); -+ if (ret) { -+ dev_err(&pdev->dev, "Cannot request csi IRQ\n"); -+ return ret; -+ } -+ return 0; -+} -+ -+/* -+ * PHYS_OFFSET isn't available on all architectures. In order to -+ * accomodate for COMPILE_TEST, let's define it to something dumb. -+ */ -+#ifndef PHYS_OFFSET -+#define PHYS_OFFSET 0 -+#endif -+ -+static int sun6i_csi_probe(struct platform_device *pdev) -+{ -+ struct sun6i_csi_dev *sdev; -+ int ret; -+ -+ sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL); -+ if (!sdev) -+ return -ENOMEM; -+ -+ sdev->dev = &pdev->dev; -+ /* The DMA bus has the memory mapped at 0 */ -+ sdev->dev->dma_pfn_offset = PHYS_OFFSET >> PAGE_SHIFT; -+ -+ ret = sun6i_csi_resource_request(sdev, pdev); -+ if (ret) -+ return ret; -+ -+ platform_set_drvdata(pdev, sdev); -+ -+ sdev->csi.dev = &pdev->dev; -+ ret = sun6i_csi_v4l2_init(&sdev->csi); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int sun6i_csi_remove(struct platform_device *pdev) -+{ -+ struct sun6i_csi_dev *sdev = platform_get_drvdata(pdev); -+ -+ sun6i_csi_v4l2_cleanup(&sdev->csi); -+ -+ return 0; -+} -+ -+static const struct of_device_id sun6i_csi_of_match[] = { -+ { .compatible = "allwinner,sun6i-a31-csi", }, -+ { .compatible = "allwinner,sun8i-v3s-csi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, sun6i_csi_of_match); -+ -+static struct platform_driver sun6i_csi_platform_driver = { -+ .probe = sun6i_csi_probe, -+ .remove = sun6i_csi_remove, -+ .driver = { -+ .name = MODULE_NAME, -+ .of_match_table = of_match_ptr(sun6i_csi_of_match), -+ }, -+}; -+module_platform_driver(sun6i_csi_platform_driver); -+ -+MODULE_DESCRIPTION("Allwinner V3s Camera Sensor Interface driver"); -+MODULE_AUTHOR("Yong Deng "); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h -new file mode 100644 -index 000000000000..c0e8b14073d1 ---- /dev/null -+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h -@@ -0,0 +1,145 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing) -+ * All rights reserved. -+ * Author: Yong Deng -+ */ -+ -+#ifndef __SUN6I_CSI_H__ -+#define __SUN6I_CSI_H__ -+ -+#include -+#include -+#include -+ -+#include "sun6i_video.h" -+ -+struct sun6i_csi; -+ -+/** -+ * struct sun6i_csi_config - configs for sun6i csi -+ * @pixelformat: v4l2 pixel format (V4L2_PIX_FMT_*) -+ * @code: media bus format code (MEDIA_BUS_FMT_*) -+ * @field: used interlacing type (enum v4l2_field) -+ * @width: frame width -+ * @height: frame height -+ */ -+struct sun6i_csi_config { -+ u32 pixelformat; -+ u32 code; -+ u32 field; -+ u32 width; -+ u32 height; -+}; -+ -+struct sun6i_csi { -+ struct device *dev; -+ struct v4l2_ctrl_handler ctrl_handler; -+ struct v4l2_device v4l2_dev; -+ struct media_device media_dev; -+ -+ struct v4l2_async_notifier notifier; -+ -+ /* video port settings */ -+ struct v4l2_fwnode_endpoint v4l2_ep; -+ -+ struct sun6i_csi_config config; -+ -+ struct sun6i_video video; -+}; -+ -+/** -+ * sun6i_csi_get_supported_pixformats() - get csi supported pixformats -+ * @csi: pointer to the csi -+ * @pixformats: supported pixformats return from csi -+ * -+ * @return the count of pixformats or error(< 0) -+ */ -+int sun6i_csi_get_supported_pixformats(struct sun6i_csi *csi, -+ const u32 **pixformats); -+ -+/** -+ * sun6i_csi_is_format_support() - check if the format supported by csi -+ * @csi: pointer to the csi -+ * @pixformat: v4l2 pixel format (V4L2_PIX_FMT_*) -+ * @mbus_code: media bus format code (MEDIA_BUS_FMT_*) -+ */ -+bool sun6i_csi_is_format_support(struct sun6i_csi *csi, u32 pixformat, -+ u32 mbus_code); -+ -+/** -+ * sun6i_csi_set_power() - power on/off the csi -+ * @csi: pointer to the csi -+ * @enable: on/off -+ */ -+int sun6i_csi_set_power(struct sun6i_csi *csi, bool enable); -+ -+/** -+ * sun6i_csi_update_config() - update the csi register setttings -+ * @csi: pointer to the csi -+ * @config: see struct sun6i_csi_config -+ */ -+int sun6i_csi_update_config(struct sun6i_csi *csi, -+ struct sun6i_csi_config *config); -+ -+/** -+ * sun6i_csi_update_buf_addr() - update the csi frame buffer address -+ * @csi: pointer to the csi -+ * @addr: frame buffer's physical address -+ */ -+void sun6i_csi_update_buf_addr(struct sun6i_csi *csi, dma_addr_t addr); -+ -+/** -+ * sun6i_csi_set_stream() - start/stop csi streaming -+ * @csi: pointer to the csi -+ * @enable: start/stop -+ */ -+void sun6i_csi_set_stream(struct sun6i_csi *csi, bool enable); -+ -+/* get bpp form v4l2 pixformat */ -+static inline int sun6i_csi_get_bpp(unsigned int pixformat) -+{ -+ switch (pixformat) { -+ case V4L2_PIX_FMT_SBGGR8: -+ case V4L2_PIX_FMT_SGBRG8: -+ case V4L2_PIX_FMT_SGRBG8: -+ case V4L2_PIX_FMT_SRGGB8: -+ return 8; -+ case V4L2_PIX_FMT_SBGGR10: -+ case V4L2_PIX_FMT_SGBRG10: -+ case V4L2_PIX_FMT_SGRBG10: -+ case V4L2_PIX_FMT_SRGGB10: -+ return 10; -+ case V4L2_PIX_FMT_SBGGR12: -+ case V4L2_PIX_FMT_SGBRG12: -+ case V4L2_PIX_FMT_SGRBG12: -+ case V4L2_PIX_FMT_SRGGB12: -+ case V4L2_PIX_FMT_HM12: -+ case V4L2_PIX_FMT_NV12: -+ case V4L2_PIX_FMT_NV21: -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YVU420: -+ return 12; -+ case V4L2_PIX_FMT_YUYV: -+ case V4L2_PIX_FMT_YVYU: -+ case V4L2_PIX_FMT_UYVY: -+ case V4L2_PIX_FMT_VYUY: -+ case V4L2_PIX_FMT_NV16: -+ case V4L2_PIX_FMT_NV61: -+ case V4L2_PIX_FMT_YUV422P: -+ return 16; -+ case V4L2_PIX_FMT_RGB24: -+ case V4L2_PIX_FMT_BGR24: -+ return 24; -+ case V4L2_PIX_FMT_RGB32: -+ case V4L2_PIX_FMT_BGR32: -+ return 32; -+ default: -+ WARN(1, "Unsupported pixformat: 0x%x\n", pixformat); -+ break; -+ } -+ -+ return 0; -+} -+ -+#endif /* __SUN6I_CSI_H__ */ -diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h -new file mode 100644 -index 000000000000..b55b21f6e112 ---- /dev/null -+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h -@@ -0,0 +1,196 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing) -+ * All rights reserved. -+ * Author: Yong Deng -+ */ -+ -+#ifndef __SUN6I_CSI_REG_H__ -+#define __SUN6I_CSI_REG_H__ -+ -+#include -+ -+#define CSI_EN_REG 0x0 -+#define CSI_EN_VER_EN BIT(30) -+#define CSI_EN_CSI_EN BIT(0) -+ -+#define CSI_IF_CFG_REG 0x4 -+#define CSI_IF_CFG_SRC_TYPE_MASK BIT(21) -+#define CSI_IF_CFG_SRC_TYPE_PROGRESSED ((0 << 21) & CSI_IF_CFG_SRC_TYPE_MASK) -+#define CSI_IF_CFG_SRC_TYPE_INTERLACED ((1 << 21) & CSI_IF_CFG_SRC_TYPE_MASK) -+#define CSI_IF_CFG_FPS_DS_EN BIT(20) -+#define CSI_IF_CFG_FIELD_MASK BIT(19) -+#define CSI_IF_CFG_FIELD_NEGATIVE ((0 << 19) & CSI_IF_CFG_FIELD_MASK) -+#define CSI_IF_CFG_FIELD_POSITIVE ((1 << 19) & CSI_IF_CFG_FIELD_MASK) -+#define CSI_IF_CFG_VREF_POL_MASK BIT(18) -+#define CSI_IF_CFG_VREF_POL_NEGATIVE ((0 << 18) & CSI_IF_CFG_VREF_POL_MASK) -+#define CSI_IF_CFG_VREF_POL_POSITIVE ((1 << 18) & CSI_IF_CFG_VREF_POL_MASK) -+#define CSI_IF_CFG_HREF_POL_MASK BIT(17) -+#define CSI_IF_CFG_HREF_POL_NEGATIVE ((0 << 17) & CSI_IF_CFG_HREF_POL_MASK) -+#define CSI_IF_CFG_HREF_POL_POSITIVE ((1 << 17) & CSI_IF_CFG_HREF_POL_MASK) -+#define CSI_IF_CFG_CLK_POL_MASK BIT(16) -+#define CSI_IF_CFG_CLK_POL_RISING_EDGE ((0 << 16) & CSI_IF_CFG_CLK_POL_MASK) -+#define CSI_IF_CFG_CLK_POL_FALLING_EDGE ((1 << 16) & CSI_IF_CFG_CLK_POL_MASK) -+#define CSI_IF_CFG_IF_DATA_WIDTH_MASK GENMASK(10, 8) -+#define CSI_IF_CFG_IF_DATA_WIDTH_8BIT ((0 << 8) & CSI_IF_CFG_IF_DATA_WIDTH_MASK) -+#define CSI_IF_CFG_IF_DATA_WIDTH_10BIT ((1 << 8) & CSI_IF_CFG_IF_DATA_WIDTH_MASK) -+#define CSI_IF_CFG_IF_DATA_WIDTH_12BIT ((2 << 8) & CSI_IF_CFG_IF_DATA_WIDTH_MASK) -+#define CSI_IF_CFG_MIPI_IF_MASK BIT(7) -+#define CSI_IF_CFG_MIPI_IF_CSI (0 << 7) -+#define CSI_IF_CFG_MIPI_IF_MIPI (1 << 7) -+#define CSI_IF_CFG_CSI_IF_MASK GENMASK(4, 0) -+#define CSI_IF_CFG_CSI_IF_YUV422_INTLV ((0 << 0) & CSI_IF_CFG_CSI_IF_MASK) -+#define CSI_IF_CFG_CSI_IF_YUV422_16BIT ((1 << 0) & CSI_IF_CFG_CSI_IF_MASK) -+#define CSI_IF_CFG_CSI_IF_BT656 ((4 << 0) & CSI_IF_CFG_CSI_IF_MASK) -+#define CSI_IF_CFG_CSI_IF_BT1120 ((5 << 0) & CSI_IF_CFG_CSI_IF_MASK) -+ -+#define CSI_CAP_REG 0x8 -+#define CSI_CAP_CH0_CAP_MASK_MASK GENMASK(5, 2) -+#define CSI_CAP_CH0_CAP_MASK(count) ((count << 2) & CSI_CAP_CH0_CAP_MASK_MASK) -+#define CSI_CAP_CH0_VCAP_ON BIT(1) -+#define CSI_CAP_CH0_SCAP_ON BIT(0) -+ -+#define CSI_SYNC_CNT_REG 0xc -+#define CSI_FIFO_THRS_REG 0x10 -+#define CSI_BT656_HEAD_CFG_REG 0x14 -+#define CSI_PTN_LEN_REG 0x30 -+#define CSI_PTN_ADDR_REG 0x34 -+#define CSI_VER_REG 0x3c -+ -+#define CSI_CH_CFG_REG 0x44 -+#define CSI_CH_CFG_INPUT_FMT_MASK GENMASK(23, 20) -+#define CSI_CH_CFG_INPUT_FMT(fmt) ((fmt << 20) & CSI_CH_CFG_INPUT_FMT_MASK) -+#define CSI_CH_CFG_OUTPUT_FMT_MASK GENMASK(19, 16) -+#define CSI_CH_CFG_OUTPUT_FMT(fmt) ((fmt << 16) & CSI_CH_CFG_OUTPUT_FMT_MASK) -+#define CSI_CH_CFG_VFLIP_EN BIT(13) -+#define CSI_CH_CFG_HFLIP_EN BIT(12) -+#define CSI_CH_CFG_FIELD_SEL_MASK GENMASK(11, 10) -+#define CSI_CH_CFG_FIELD_SEL_FIELD0 ((0 << 10) & CSI_CH_CFG_FIELD_SEL_MASK) -+#define CSI_CH_CFG_FIELD_SEL_FIELD1 ((1 << 10) & CSI_CH_CFG_FIELD_SEL_MASK) -+#define CSI_CH_CFG_FIELD_SEL_BOTH ((2 << 10) & CSI_CH_CFG_FIELD_SEL_MASK) -+#define CSI_CH_CFG_INPUT_SEQ_MASK GENMASK(9, 8) -+#define CSI_CH_CFG_INPUT_SEQ(seq) ((seq << 8) & CSI_CH_CFG_INPUT_SEQ_MASK) -+ -+#define CSI_CH_SCALE_REG 0x4c -+#define CSI_CH_SCALE_QUART_EN BIT(0) -+ -+#define CSI_CH_F0_BUFA_REG 0x50 -+ -+#define CSI_CH_F1_BUFA_REG 0x58 -+ -+#define CSI_CH_F2_BUFA_REG 0x60 -+ -+#define CSI_CH_STA_REG 0x6c -+#define CSI_CH_STA_FIELD_STA_MASK BIT(2) -+#define CSI_CH_STA_FIELD_STA_FIELD0 ((0 << 2) & CSI_CH_STA_FIELD_STA_MASK) -+#define CSI_CH_STA_FIELD_STA_FIELD1 ((1 << 2) & CSI_CH_STA_FIELD_STA_MASK) -+#define CSI_CH_STA_VCAP_STA BIT(1) -+#define CSI_CH_STA_SCAP_STA BIT(0) -+ -+#define CSI_CH_INT_EN_REG 0x70 -+#define CSI_CH_INT_EN_VS_INT_EN BIT(7) -+#define CSI_CH_INT_EN_HB_OF_INT_EN BIT(6) -+#define CSI_CH_INT_EN_MUL_ERR_INT_EN BIT(5) -+#define CSI_CH_INT_EN_FIFO2_OF_INT_EN BIT(4) -+#define CSI_CH_INT_EN_FIFO1_OF_INT_EN BIT(3) -+#define CSI_CH_INT_EN_FIFO0_OF_INT_EN BIT(2) -+#define CSI_CH_INT_EN_FD_INT_EN BIT(1) -+#define CSI_CH_INT_EN_CD_INT_EN BIT(0) -+ -+#define CSI_CH_INT_STA_REG 0x74 -+#define CSI_CH_INT_STA_VS_PD BIT(7) -+#define CSI_CH_INT_STA_HB_OF_PD BIT(6) -+#define CSI_CH_INT_STA_MUL_ERR_PD BIT(5) -+#define CSI_CH_INT_STA_FIFO2_OF_PD BIT(4) -+#define CSI_CH_INT_STA_FIFO1_OF_PD BIT(3) -+#define CSI_CH_INT_STA_FIFO0_OF_PD BIT(2) -+#define CSI_CH_INT_STA_FD_PD BIT(1) -+#define CSI_CH_INT_STA_CD_PD BIT(0) -+ -+#define CSI_CH_FLD1_VSIZE_REG 0x78 -+ -+#define CSI_CH_HSIZE_REG 0x80 -+#define CSI_CH_HSIZE_HOR_LEN_MASK GENMASK(28, 16) -+#define CSI_CH_HSIZE_HOR_LEN(len) ((len << 16) & CSI_CH_HSIZE_HOR_LEN_MASK) -+#define CSI_CH_HSIZE_HOR_START_MASK GENMASK(12, 0) -+#define CSI_CH_HSIZE_HOR_START(start) ((start << 0) & CSI_CH_HSIZE_HOR_START_MASK) -+ -+#define CSI_CH_VSIZE_REG 0x84 -+#define CSI_CH_VSIZE_VER_LEN_MASK GENMASK(28, 16) -+#define CSI_CH_VSIZE_VER_LEN(len) ((len << 16) & CSI_CH_VSIZE_VER_LEN_MASK) -+#define CSI_CH_VSIZE_VER_START_MASK GENMASK(12, 0) -+#define CSI_CH_VSIZE_VER_START(start) ((start << 0) & CSI_CH_VSIZE_VER_START_MASK) -+ -+#define CSI_CH_BUF_LEN_REG 0x88 -+#define CSI_CH_BUF_LEN_BUF_LEN_C_MASK GENMASK(29, 16) -+#define CSI_CH_BUF_LEN_BUF_LEN_C(len) ((len << 16) & CSI_CH_BUF_LEN_BUF_LEN_C_MASK) -+#define CSI_CH_BUF_LEN_BUF_LEN_Y_MASK GENMASK(13, 0) -+#define CSI_CH_BUF_LEN_BUF_LEN_Y(len) ((len << 0) & CSI_CH_BUF_LEN_BUF_LEN_Y_MASK) -+ -+#define CSI_CH_FLIP_SIZE_REG 0x8c -+#define CSI_CH_FLIP_SIZE_VER_LEN_MASK GENMASK(28, 16) -+#define CSI_CH_FLIP_SIZE_VER_LEN(len) ((len << 16) & CSI_CH_FLIP_SIZE_VER_LEN_MASK) -+#define CSI_CH_FLIP_SIZE_VALID_LEN_MASK GENMASK(12, 0) -+#define CSI_CH_FLIP_SIZE_VALID_LEN(len) ((len << 0) & CSI_CH_FLIP_SIZE_VALID_LEN_MASK) -+ -+#define CSI_CH_FRM_CLK_CNT_REG 0x90 -+#define CSI_CH_ACC_ITNL_CLK_CNT_REG 0x94 -+#define CSI_CH_FIFO_STAT_REG 0x98 -+#define CSI_CH_PCLK_STAT_REG 0x9c -+ -+/* -+ * csi input data format -+ */ -+enum csi_input_fmt { -+ CSI_INPUT_FORMAT_RAW = 0, -+ CSI_INPUT_FORMAT_YUV422 = 3, -+ CSI_INPUT_FORMAT_YUV420 = 4, -+}; -+ -+/* -+ * csi output data format -+ */ -+enum csi_output_fmt { -+ /* only when input format is RAW */ -+ CSI_FIELD_RAW_8 = 0, -+ CSI_FIELD_RAW_10 = 1, -+ CSI_FIELD_RAW_12 = 2, -+ CSI_FIELD_RGB565 = 4, -+ CSI_FIELD_RGB888 = 5, -+ CSI_FIELD_PRGB888 = 6, -+ CSI_FRAME_RAW_8 = 8, -+ CSI_FRAME_RAW_10 = 9, -+ CSI_FRAME_RAW_12 = 10, -+ CSI_FRAME_RGB565 = 12, -+ CSI_FRAME_RGB888 = 13, -+ CSI_FRAME_PRGB888 = 14, -+ -+ /* only when input format is YUV422 */ -+ CSI_FIELD_PLANAR_YUV422 = 0, -+ CSI_FIELD_PLANAR_YUV420 = 1, -+ CSI_FRAME_PLANAR_YUV420 = 2, -+ CSI_FRAME_PLANAR_YUV422 = 3, -+ CSI_FIELD_UV_CB_YUV422 = 4, -+ CSI_FIELD_UV_CB_YUV420 = 5, -+ CSI_FRAME_UV_CB_YUV420 = 6, -+ CSI_FRAME_UV_CB_YUV422 = 7, -+ CSI_FIELD_MB_YUV422 = 8, -+ CSI_FIELD_MB_YUV420 = 9, -+ CSI_FRAME_MB_YUV420 = 10, -+ CSI_FRAME_MB_YUV422 = 11, -+ CSI_FIELD_UV_CB_YUV422_10 = 12, -+ CSI_FIELD_UV_CB_YUV420_10 = 13, -+}; -+ -+/* -+ * csi YUV input data sequence -+ */ -+enum csi_input_seq { -+ /* only when input format is YUV422 */ -+ CSI_INPUT_SEQ_YUYV = 0, -+ CSI_INPUT_SEQ_YVYU, -+ CSI_INPUT_SEQ_UYVY, -+ CSI_INPUT_SEQ_VYUY, -+}; -+ -+#endif /* __SUN6I_CSI_REG_H__ */ -diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c -new file mode 100644 -index 000000000000..bf7c0d1d1d47 ---- /dev/null -+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c -@@ -0,0 +1,759 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing) -+ * All rights reserved. -+ * Author: Yong Deng -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sun6i_csi.h" -+#include "sun6i_video.h" -+ -+struct sun6i_csi_buffer { -+ struct vb2_v4l2_buffer vb; -+ struct list_head list; -+ -+ dma_addr_t dma_addr; -+ bool queued_to_csi; -+}; -+ -+static struct sun6i_csi_format * -+find_format_by_pixformat(struct sun6i_video *video, unsigned int pixformat) -+{ -+ unsigned int num_formats = video->num_formats; -+ struct sun6i_csi_format *fmt; -+ unsigned int i; -+ -+ for (i = 0; i < num_formats; i++) { -+ fmt = &video->formats[i]; -+ if (fmt->pixformat == pixformat) -+ return fmt; -+ } -+ -+ return NULL; -+} -+ -+static struct v4l2_subdev * -+sun6i_video_remote_subdev(struct sun6i_video *video, u32 *pad) -+{ -+ struct media_pad *remote; -+ -+ remote = media_entity_remote_pad(&video->pad); -+ -+ if (!remote || !is_media_entity_v4l2_subdev(remote->entity)) -+ return NULL; -+ -+ if (pad) -+ *pad = remote->index; -+ -+ return media_entity_to_v4l2_subdev(remote->entity); -+} -+ -+static int sun6i_video_queue_setup(struct vb2_queue *vq, -+ unsigned int *nbuffers, unsigned int *nplanes, -+ unsigned int sizes[], -+ struct device *alloc_devs[]) -+{ -+ struct sun6i_video *video = vb2_get_drv_priv(vq); -+ unsigned int size = video->fmt.fmt.pix.sizeimage; -+ -+ if (*nplanes) -+ return sizes[0] < size ? -EINVAL : 0; -+ -+ *nplanes = 1; -+ sizes[0] = size; -+ -+ return 0; -+} -+ -+static int sun6i_video_buffer_prepare(struct vb2_buffer *vb) -+{ -+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); -+ struct sun6i_csi_buffer *buf = -+ container_of(vbuf, struct sun6i_csi_buffer, vb); -+ struct sun6i_video *video = vb2_get_drv_priv(vb->vb2_queue); -+ unsigned long size = video->fmt.fmt.pix.sizeimage; -+ -+ if (vb2_plane_size(vb, 0) < size) { -+ v4l2_err(video->vdev.v4l2_dev, "buffer too small (%lu < %lu)\n", -+ vb2_plane_size(vb, 0), size); -+ return -EINVAL; -+ } -+ -+ vb2_set_plane_payload(vb, 0, size); -+ -+ buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); -+ -+ vbuf->field = video->fmt.fmt.pix.field; -+ -+ return 0; -+} -+ -+static int sun6i_pipeline_set_stream(struct sun6i_video *video, bool enable) -+{ -+ struct media_entity *entity; -+ struct media_pad *pad; -+ struct v4l2_subdev *subdev; -+ int ret; -+ -+ entity = &video->vdev.entity; -+ while (1) { -+ pad = &entity->pads[0]; -+ if (!(pad->flags & MEDIA_PAD_FL_SINK)) -+ break; -+ -+ pad = media_entity_remote_pad(pad); -+ if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) -+ break; -+ -+ entity = pad->entity; -+ subdev = media_entity_to_v4l2_subdev(entity); -+ -+ ret = v4l2_subdev_call(subdev, video, s_stream, enable); -+ if (enable && ret < 0 && ret != -ENOIOCTLCMD) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int sun6i_video_start_streaming(struct vb2_queue *vq, unsigned int count) -+{ -+ struct sun6i_video *video = vb2_get_drv_priv(vq); -+ struct sun6i_csi_buffer *buf; -+ struct sun6i_csi_buffer *next_buf; -+ struct sun6i_csi_config config; -+ unsigned long flags; -+ int ret; -+ -+ video->sequence = 0; -+ -+ ret = media_pipeline_start(&video->vdev.entity, &video->vdev.pipe); -+ if (ret < 0) -+ goto clear_dma_queue; -+ -+ config.pixelformat = video->fmt.fmt.pix.pixelformat; -+ config.code = video->current_fmt->mbus_code; -+ config.field = video->fmt.fmt.pix.field; -+ config.width = video->fmt.fmt.pix.width; -+ config.height = video->fmt.fmt.pix.height; -+ -+ ret = sun6i_csi_update_config(video->csi, &config); -+ if (ret < 0) -+ goto stop_media_pipeline; -+ -+ spin_lock_irqsave(&video->dma_queue_lock, flags); -+ -+ buf = list_first_entry(&video->dma_queue, -+ struct sun6i_csi_buffer, list); -+ buf->queued_to_csi = true; -+ sun6i_csi_update_buf_addr(video->csi, buf->dma_addr); -+ -+ sun6i_csi_set_stream(video->csi, true); -+ -+ /* -+ * CSI will lookup the next dma buffer for next frame before the -+ * the current frame done IRQ triggered. This is not documented -+ * but reported by OndÅ™ej Jirman. -+ * The BSP code has workaround for this too. It skip to mark the -+ * first buffer as frame done for VB2 and pass the second buffer -+ * to CSI in the first frame done ISR call. Then in second frame -+ * done ISR call, it mark the first buffer as frame done for VB2 -+ * and pass the third buffer to CSI. And so on. The bad thing is -+ * that the first buffer will be written twice and the first frame -+ * is dropped even the queued buffer is sufficient. -+ * So, I make some improvement here. Pass the next buffer to CSI -+ * just follow starting the CSI. In this case, the first frame -+ * will be stored in first buffer, second frame in second buffer. -+ * This method is used to avoid dropping the first frame, it -+ * would also drop frame when lacking of queued buffer. -+ */ -+ next_buf = list_next_entry(buf, list); -+ next_buf->queued_to_csi = true; -+ sun6i_csi_update_buf_addr(video->csi, next_buf->dma_addr); -+ -+ spin_unlock_irqrestore(&video->dma_queue_lock, flags); -+ -+ ret = sun6i_pipeline_set_stream(video, true); -+ if (ret < 0) -+ goto stop_csi_stream; -+ -+ return 0; -+ -+stop_csi_stream: -+ sun6i_csi_set_stream(video->csi, false); -+stop_media_pipeline: -+ media_pipeline_stop(&video->vdev.entity); -+clear_dma_queue: -+ spin_lock_irqsave(&video->dma_queue_lock, flags); -+ list_for_each_entry(buf, &video->dma_queue, list) -+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); -+ INIT_LIST_HEAD(&video->dma_queue); -+ spin_unlock_irqrestore(&video->dma_queue_lock, flags); -+ -+ return ret; -+} -+ -+static void sun6i_video_stop_streaming(struct vb2_queue *vq) -+{ -+ struct sun6i_video *video = vb2_get_drv_priv(vq); -+ unsigned long flags; -+ struct sun6i_csi_buffer *buf; -+ -+ sun6i_pipeline_set_stream(video, false); -+ -+ sun6i_csi_set_stream(video->csi, false); -+ -+ media_pipeline_stop(&video->vdev.entity); -+ -+ /* Release all active buffers */ -+ spin_lock_irqsave(&video->dma_queue_lock, flags); -+ list_for_each_entry(buf, &video->dma_queue, list) -+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); -+ INIT_LIST_HEAD(&video->dma_queue); -+ spin_unlock_irqrestore(&video->dma_queue_lock, flags); -+} -+ -+static void sun6i_video_buffer_queue(struct vb2_buffer *vb) -+{ -+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); -+ struct sun6i_csi_buffer *buf = -+ container_of(vbuf, struct sun6i_csi_buffer, vb); -+ struct sun6i_video *video = vb2_get_drv_priv(vb->vb2_queue); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&video->dma_queue_lock, flags); -+ buf->queued_to_csi = false; -+ list_add_tail(&buf->list, &video->dma_queue); -+ spin_unlock_irqrestore(&video->dma_queue_lock, flags); -+} -+ -+void sun6i_video_frame_done(struct sun6i_video *video) -+{ -+ struct sun6i_csi_buffer *buf; -+ struct sun6i_csi_buffer *next_buf; -+ struct vb2_v4l2_buffer *vbuf; -+ -+ spin_lock(&video->dma_queue_lock); -+ -+ buf = list_first_entry(&video->dma_queue, -+ struct sun6i_csi_buffer, list); -+ if (list_is_last(&buf->list, &video->dma_queue)) { -+ dev_dbg(video->csi->dev, "Frame droped!\n"); -+ goto unlock; -+ } -+ -+ next_buf = list_next_entry(buf, list); -+ /* If a new buffer (#next_buf) had not been queued to CSI, the old -+ * buffer (#buf) is still holding by CSI for storing the next -+ * frame. So, we queue a new buffer (#next_buf) to CSI then wait -+ * for next ISR call. -+ */ -+ if (!next_buf->queued_to_csi) { -+ next_buf->queued_to_csi = true; -+ sun6i_csi_update_buf_addr(video->csi, next_buf->dma_addr); -+ dev_dbg(video->csi->dev, "Frame droped!\n"); -+ goto unlock; -+ } -+ -+ list_del(&buf->list); -+ vbuf = &buf->vb; -+ vbuf->vb2_buf.timestamp = ktime_get_ns(); -+ vbuf->sequence = video->sequence; -+ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); -+ -+ /* Prepare buffer for next frame but one. */ -+ if (!list_is_last(&next_buf->list, &video->dma_queue)) { -+ next_buf = list_next_entry(next_buf, list); -+ next_buf->queued_to_csi = true; -+ sun6i_csi_update_buf_addr(video->csi, next_buf->dma_addr); -+ } else { -+ dev_dbg(video->csi->dev, "Next frame will be dropped!\n"); -+ } -+ -+unlock: -+ video->sequence++; -+ spin_unlock(&video->dma_queue_lock); -+} -+ -+static struct vb2_ops sun6i_csi_vb2_ops = { -+ .queue_setup = sun6i_video_queue_setup, -+ .wait_prepare = vb2_ops_wait_prepare, -+ .wait_finish = vb2_ops_wait_finish, -+ .buf_prepare = sun6i_video_buffer_prepare, -+ .start_streaming = sun6i_video_start_streaming, -+ .stop_streaming = sun6i_video_stop_streaming, -+ .buf_queue = sun6i_video_buffer_queue, -+}; -+ -+static int vidioc_querycap(struct file *file, void *priv, -+ struct v4l2_capability *cap) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ -+ strlcpy(cap->driver, "sun6i-video", sizeof(cap->driver)); -+ strlcpy(cap->card, video->vdev.name, sizeof(cap->card)); -+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", -+ video->csi->dev->of_node->name); -+ -+ return 0; -+} -+ -+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_fmtdesc *f) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ u32 index = f->index; -+ -+ if (index >= video->num_formats) -+ return -EINVAL; -+ -+ f->pixelformat = video->formats[index].pixformat; -+ -+ return 0; -+} -+ -+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *fmt) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ -+ *fmt = video->fmt; -+ -+ return 0; -+} -+ -+ -+static int sun6i_video_try_fmt_source(struct sun6i_video *video, -+ u32 which, -+ struct v4l2_pix_format *pixfmt, -+ struct sun6i_csi_format *csi_fmt) -+{ -+ struct v4l2_subdev *subdev; -+ struct v4l2_subdev_pad_config *pad_cfg; -+ struct v4l2_subdev_format format = { -+ .which = which, -+ }; -+ u32 pad; -+ int ret; -+ -+ subdev = sun6i_video_remote_subdev(video, &pad); -+ if (subdev == NULL) -+ return -ENXIO; -+ -+ v4l2_fill_mbus_format(&format.format, pixfmt, csi_fmt->mbus_code); -+ -+ pad_cfg = v4l2_subdev_alloc_pad_config(subdev); -+ if (pad_cfg == NULL) -+ return -ENOMEM; -+ -+ format.pad = pad; -+ ret = v4l2_subdev_call(subdev, pad, set_fmt, pad_cfg, &format); -+ if (ret) -+ goto done; -+ -+ v4l2_fill_pix_format(pixfmt, &format.format); -+ -+done: -+ v4l2_subdev_free_pad_config(pad_cfg); -+ return ret; -+} -+ -+static int sun6i_video_try_fmt(struct sun6i_video *video, u32 which, -+ struct v4l2_format *f, -+ struct sun6i_csi_format **current_fmt) -+{ -+ struct sun6i_csi_format *csi_fmt; -+ struct v4l2_pix_format *pixfmt = &f->fmt.pix; -+ int ret; -+ -+ csi_fmt = find_format_by_pixformat(video, pixfmt->pixelformat); -+ if (csi_fmt == NULL) { -+ if (video->num_formats > 0) { -+ csi_fmt = &video->formats[0]; -+ pixfmt->pixelformat = csi_fmt->pixformat; -+ } else -+ return -EINVAL; -+ } -+ -+ ret = sun6i_video_try_fmt_source(video, which, pixfmt, csi_fmt); -+ if (ret) -+ return ret; -+ -+ pixfmt->bytesperline = (pixfmt->width * csi_fmt->bpp) >> 3; -+ pixfmt->sizeimage = (pixfmt->width * csi_fmt->bpp * pixfmt->height) / 8; -+ -+ if (current_fmt) -+ *current_fmt = csi_fmt; -+ -+ return 0; -+} -+ -+static int sun6i_video_set_fmt(struct sun6i_video *video, struct v4l2_format *f) -+{ -+ struct sun6i_csi_format *current_fmt; -+ int ret; -+ -+ ret = sun6i_video_try_fmt(video, V4L2_SUBDEV_FORMAT_ACTIVE, f, -+ ¤t_fmt); -+ if (ret) -+ return ret; -+ -+ video->fmt = *f; -+ video->current_fmt = current_fmt; -+ -+ return 0; -+} -+ -+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ -+ if (vb2_is_busy(&video->vb2_vidq)) -+ return -EBUSY; -+ -+ return sun6i_video_set_fmt(video, f); -+} -+ -+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ -+ return sun6i_video_try_fmt(video, V4L2_SUBDEV_FORMAT_TRY, f, NULL); -+} -+ -+static int vidioc_enum_input(struct file *file, void *fh, -+ struct v4l2_input *inp) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ struct v4l2_subdev *subdev; -+ u32 pad; -+ int ret; -+ -+ if (inp->index != 0) -+ return -EINVAL; -+ -+ subdev = sun6i_video_remote_subdev(video, &pad); -+ if (subdev == NULL) -+ return -ENXIO; -+ -+ ret = v4l2_subdev_call(subdev, video, g_input_status, &inp->status); -+ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) -+ return ret; -+ -+ inp->type = V4L2_INPUT_TYPE_CAMERA; -+ -+ inp->capabilities = 0; -+ inp->std = 0; -+ if (v4l2_subdev_has_op(subdev, pad, dv_timings_cap)) -+ inp->capabilities = V4L2_IN_CAP_DV_TIMINGS; -+ -+ strlcpy(inp->name, subdev->name, sizeof(inp->name)); -+ -+ return 0; -+} -+ -+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) -+{ -+ *i = 0; -+ -+ return 0; -+} -+ -+static int vidioc_s_input(struct file *file, void *fh, unsigned int i) -+{ -+ if (i != 0) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static const struct v4l2_ioctl_ops sun6i_video_ioctl_ops = { -+ .vidioc_querycap = vidioc_querycap, -+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, -+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, -+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, -+ -+ .vidioc_enum_input = vidioc_enum_input, -+ .vidioc_s_input = vidioc_s_input, -+ .vidioc_g_input = vidioc_g_input, -+ -+ .vidioc_reqbufs = vb2_ioctl_reqbufs, -+ .vidioc_querybuf = vb2_ioctl_querybuf, -+ .vidioc_qbuf = vb2_ioctl_qbuf, -+ .vidioc_expbuf = vb2_ioctl_expbuf, -+ .vidioc_dqbuf = vb2_ioctl_dqbuf, -+ .vidioc_create_bufs = vb2_ioctl_create_bufs, -+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, -+ .vidioc_streamon = vb2_ioctl_streamon, -+ .vidioc_streamoff = vb2_ioctl_streamoff, -+ -+ .vidioc_log_status = v4l2_ctrl_log_status, -+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -+ -+}; -+ -+/* ----------------------------------------------------------------------------- -+ * V4L2 file operations -+ */ -+static int sun6i_video_open(struct file *file) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ int ret; -+ -+ if (mutex_lock_interruptible(&video->lock)) -+ return -ERESTARTSYS; -+ -+ ret = v4l2_fh_open(file); -+ if (ret < 0) -+ goto unlock; -+ -+ ret = v4l2_pipeline_pm_use(&video->vdev.entity, 1); -+ if (ret < 0) -+ goto fh_release; -+ -+ /* check if already powered */ -+ if (!v4l2_fh_is_singular_file(file)) -+ goto unlock; -+ -+ ret = sun6i_csi_set_power(video->csi, true); -+ if (ret < 0) -+ goto fh_release; -+ -+ mutex_unlock(&video->lock); -+ return 0; -+ -+fh_release: -+ v4l2_fh_release(file); -+unlock: -+ mutex_unlock(&video->lock); -+ return ret; -+} -+ -+static int sun6i_video_close(struct file *file) -+{ -+ struct sun6i_video *video = video_drvdata(file); -+ bool last_fh; -+ -+ mutex_lock(&video->lock); -+ -+ last_fh = v4l2_fh_is_singular_file(file); -+ -+ _vb2_fop_release(file, NULL); -+ -+ v4l2_pipeline_pm_use(&video->vdev.entity, 0); -+ -+ if (last_fh) -+ sun6i_csi_set_power(video->csi, false); -+ -+ mutex_unlock(&video->lock); -+ -+ return 0; -+} -+ -+static const struct v4l2_file_operations sun6i_video_fops = { -+ .owner = THIS_MODULE, -+ .open = sun6i_video_open, -+ .release = sun6i_video_close, -+ .unlocked_ioctl = video_ioctl2, -+ .mmap = vb2_fop_mmap, -+ .poll = vb2_fop_poll -+}; -+ -+/* ----------------------------------------------------------------------------- -+ * Media Operations -+ */ -+static int sun6i_video_formats_init(struct sun6i_video *video) -+{ -+ struct v4l2_subdev_mbus_code_enum mbus_code = { 0 }; -+ struct sun6i_csi *csi = video->csi; -+ struct v4l2_format format; -+ struct v4l2_subdev *subdev; -+ u32 pad; -+ const u32 *pixformats; -+ int pixformat_count = 0; -+ u32 subdev_codes[32]; /* subdev format codes, 32 should be enough */ -+ int codes_count = 0; -+ int num_fmts = 0; -+ int i, j; -+ -+ subdev = sun6i_video_remote_subdev(video, &pad); -+ if (subdev == NULL) -+ return -ENXIO; -+ -+ /* Get supported pixformats of CSI */ -+ pixformat_count = sun6i_csi_get_supported_pixformats(csi, &pixformats); -+ if (pixformat_count <= 0) -+ return -ENXIO; -+ -+ /* Get subdev formats codes */ -+ mbus_code.pad = pad; -+ mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE; -+ while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, -+ &mbus_code)) { -+ if (codes_count >= ARRAY_SIZE(subdev_codes)) { -+ dev_warn(video->csi->dev, -+ "subdev_codes array is full!\n"); -+ break; -+ } -+ subdev_codes[codes_count] = mbus_code.code; -+ codes_count++; -+ mbus_code.index++; -+ } -+ -+ if (!codes_count) -+ return -ENXIO; -+ -+ /* Get supported formats count */ -+ for (i = 0; i < codes_count; i++) { -+ for (j = 0; j < pixformat_count; j++) { -+ if (!sun6i_csi_is_format_support(csi, pixformats[j], -+ subdev_codes[i])) { -+ continue; -+ } -+ num_fmts++; -+ } -+ } -+ -+ if (!num_fmts) -+ return -ENXIO; -+ -+ video->num_formats = num_fmts; -+ video->formats = devm_kcalloc(video->csi->dev, num_fmts, -+ sizeof(struct sun6i_csi_format), GFP_KERNEL); -+ if (!video->formats) -+ return -ENOMEM; -+ -+ /* Get supported formats */ -+ num_fmts = 0; -+ for (i = 0; i < codes_count; i++) { -+ for (j = 0; j < pixformat_count; j++) { -+ if (!sun6i_csi_is_format_support(csi, pixformats[j], -+ subdev_codes[i])) { -+ continue; -+ } -+ -+ video->formats[num_fmts].pixformat = pixformats[j]; -+ video->formats[num_fmts].mbus_code = subdev_codes[i]; -+ video->formats[num_fmts].bpp = -+ sun6i_csi_get_bpp(pixformats[j]); -+ num_fmts++; -+ } -+ } -+ -+ /* setup default format */ -+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ format.fmt.pix.width = 1280; -+ format.fmt.pix.height = 720; -+ format.fmt.pix.pixelformat = video->formats[0].pixformat; -+ sun6i_video_set_fmt(video, &format); -+ -+ return 0; -+} -+ -+static int sun6i_video_link_setup(struct media_entity *entity, -+ const struct media_pad *local, -+ const struct media_pad *remote, u32 flags) -+{ -+ struct video_device *vdev = media_entity_to_video_device(entity); -+ struct sun6i_video *video = video_get_drvdata(vdev); -+ -+ if (WARN_ON(video == NULL)) -+ return 0; -+ -+ return sun6i_video_formats_init(video); -+} -+ -+static const struct media_entity_operations sun6i_video_media_ops = { -+ .link_setup = sun6i_video_link_setup, -+}; -+ -+int sun6i_video_init(struct sun6i_video *video, struct sun6i_csi *csi, -+ const char *name) -+{ -+ struct video_device *vdev = &video->vdev; -+ struct vb2_queue *vidq = &video->vb2_vidq; -+ int ret; -+ -+ video->csi = csi; -+ -+ /* Initialize the media entity... */ -+ video->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT; -+ vdev->entity.ops = &sun6i_video_media_ops; -+ ret = media_entity_pads_init(&vdev->entity, 1, &video->pad); -+ if (ret < 0) -+ return ret; -+ -+ mutex_init(&video->lock); -+ -+ INIT_LIST_HEAD(&video->dma_queue); -+ spin_lock_init(&video->dma_queue_lock); -+ -+ video->sequence = 0; -+ video->num_formats = 0; -+ -+ /* Initialize videobuf2 queue */ -+ vidq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ vidq->io_modes = VB2_MMAP | VB2_DMABUF; -+ vidq->drv_priv = video; -+ vidq->buf_struct_size = sizeof(struct sun6i_csi_buffer); -+ vidq->ops = &sun6i_csi_vb2_ops; -+ vidq->mem_ops = &vb2_dma_contig_memops; -+ vidq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; -+ vidq->lock = &video->lock; -+ /* Make sure non-dropped frame */ -+ vidq->min_buffers_needed = 3; -+ vidq->dev = csi->dev; -+ -+ ret = vb2_queue_init(vidq); -+ if (ret) { -+ v4l2_err(&csi->v4l2_dev, "vb2_queue_init failed: %d\n", ret); -+ goto error; -+ } -+ -+ /* Register video device */ -+ strlcpy(vdev->name, name, sizeof(vdev->name)); -+ vdev->release = video_device_release_empty; -+ vdev->fops = &sun6i_video_fops; -+ vdev->ioctl_ops = &sun6i_video_ioctl_ops; -+ vdev->vfl_type = VFL_TYPE_GRABBER; -+ vdev->vfl_dir = VFL_DIR_RX; -+ vdev->v4l2_dev = &csi->v4l2_dev; -+ vdev->queue = vidq; -+ vdev->lock = &video->lock; -+ vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE; -+ video_set_drvdata(vdev, video); -+ -+ ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); -+ if (ret < 0) { -+ v4l2_err(&csi->v4l2_dev, -+ "video_register_device failed: %d\n", ret); -+ goto error; -+ } -+ -+ return 0; -+ -+error: -+ sun6i_video_cleanup(video); -+ return ret; -+} -+ -+void sun6i_video_cleanup(struct sun6i_video *video) -+{ -+ if (video_is_registered(&video->vdev)) -+ video_unregister_device(&video->vdev); -+ -+ media_entity_cleanup(&video->vdev.entity); -+} -diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h -new file mode 100644 -index 000000000000..9e7171be3e6f ---- /dev/null -+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h -@@ -0,0 +1,53 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing) -+ * All rights reserved. -+ * Author: Yong Deng -+ */ -+ -+#ifndef __SUN6I_VIDEO_H__ -+#define __SUN6I_VIDEO_H__ -+ -+#include -+#include -+ -+/* -+ * struct sun6i_csi_format - CSI media bus format information -+ * @pixformat: V4l2 pixformat for this format -+ * @mbus_code: V4L2 media bus format code. -+ * @bpp: Bytes per pixel (when stored in memory) -+ */ -+struct sun6i_csi_format { -+ u32 pixformat; -+ u32 mbus_code; -+ u8 bpp; -+}; -+ -+struct sun6i_csi; -+ -+struct sun6i_video { -+ struct video_device vdev; -+ struct media_pad pad; -+ struct sun6i_csi *csi; -+ -+ struct mutex lock; -+ -+ struct vb2_queue vb2_vidq; -+ spinlock_t dma_queue_lock; -+ struct list_head dma_queue; -+ -+ unsigned int sequence; -+ -+ struct sun6i_csi_format *formats; -+ unsigned int num_formats; -+ struct sun6i_csi_format *current_fmt; -+ struct v4l2_format fmt; -+}; -+ -+int sun6i_video_init(struct sun6i_video *video, struct sun6i_csi *csi, -+ const char *name); -+void sun6i_video_cleanup(struct sun6i_video *video); -+ -+void sun6i_video_frame_done(struct sun6i_video *video); -+ -+#endif /* __SUN6I_VIDEO_H__ */ --- -2.17.1 - diff --git a/patch/kernel/sunxi-dev/dvfs-regulator-opi-pc.patch b/patch/kernel/sunxi-dev/dvfs-regulator-opi-pc.patch deleted file mode 100644 index 62f9d45c0..000000000 --- a/patch/kernel/sunxi-dev/dvfs-regulator-opi-pc.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts -index 1a044b17..0732d8c0 100644 ---- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts -+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts -@@ -97,6 +97,10 @@ - status = "okay"; - }; - -+&cpu0 { -+ cpu-supply = <®_sy8106a>; -+}; -+ - &ehci0 { - status = "okay"; - }; -@@ -152,6 +156,20 @@ - }; - }; - -+&r_i2c { -+ status = "okay"; -+ -+ reg_sy8106a: regulator@65 { -+ compatible = "silergy,sy8106a"; -+ reg = <0x65>; -+ regulator-name = "vdd-cpux"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1400000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+}; -+ - &r_pio { - leds_r_opc: led_pins@0 { - pins = "PL10"; diff --git a/patch/kernel/sunxi-dev/dvfs-regulator-update-sy8106a.patch b/patch/kernel/sunxi-dev/dvfs-regulator-update-sy8106a.patch deleted file mode 100644 index 6d0d9356f..000000000 --- a/patch/kernel/sunxi-dev/dvfs-regulator-update-sy8106a.patch +++ /dev/null @@ -1,48 +0,0 @@ -diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts -index 415e0aeed..d99b7a5a9 100644 ---- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts -+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts -@@ -197,6 +197,7 @@ - compatible = "silergy,sy8106a"; - reg = <0x65>; - regulator-name = "vdd-cpux"; -+ silergy,fixed-microvolt = <1000000>; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1400000>; - regulator-boot-on; -diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts -index 4e64e24cb..7b7e00672 100644 ---- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts -+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts -@@ -221,6 +221,7 @@ - compatible = "silergy,sy8106a"; - reg = <0x65>; - regulator-name = "vdd-cpux"; -+ silergy,fixed-microvolt = <1000000>; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1400000>; - regulator-boot-on; -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts -index 1c5186246..75f2b0e78 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts -@@ -242,6 +242,7 @@ - vdd_cpu: regulator@65 { - compatible = "silergy,sy8106a"; - reg = <0x65>; -+ silergy,fixed-microvolt = <1000000>; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1400000>; - regulator-ramp-delay = <200>; -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts -index 2e5e6ad78..256331759 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts -@@ -237,6 +237,7 @@ - vdd_cpu: regulator@65 { - compatible = "silergy,sy8106a"; - reg = <0x65>; -+ silergy,fixed-microvolt = <1000000>; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1400000>; - regulator-ramp-delay = <200>; diff --git a/patch/kernel/sunxi-dev/general-a64-enable-fsl-timer-errata.patch b/patch/kernel/sunxi-dev/general-a64-enable-fsl-timer-errata.patch deleted file mode 100644 index e6f3aa034..000000000 --- a/patch/kernel/sunxi-dev/general-a64-enable-fsl-timer-errata.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -index 02c0385f..db616e73 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -105,6 +110,7 @@ - - timer { - compatible = "arm,armv8-timer"; -+ fsl,erratum-a008585; - interrupts = , - ; -+ status = "disabled"; -+ -+ simple-audio-card,codec { -+ sound-dai = <&hdmi>; -+ }; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s2>; -+ }; -+ }; -+ - clocks { - #address-cells = <1>; - #size-cells = <1>; -@@ -630,6 +646,19 @@ - status = "disabled"; - }; - -+ i2s2: i2s@1c22800 { -+ #sound-dai-cells = <0>; -+ compatible = "allwinner,sun8i-h3-i2s"; -+ reg = <0x01c22800 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>; -+ clock-names = "apb", "mod"; -+ dmas = <&dma 27>; -+ resets = <&ccu RST_BUS_I2S2>; -+ dma-names = "tx"; -+ status = "disabled"; -+ }; -+ - codec: codec@1c22c00 { - #sound-dai-cells = <0>; - compatible = "allwinner,sun8i-h3-codec"; -@@ -747,6 +776,7 @@ - }; - - hdmi: hdmi@1ee0000 { -+ #sound-dai-cells = <0>; - compatible = "allwinner,sun8i-h3-dw-hdmi", - "allwinner,sun8i-a83t-dw-hdmi"; - reg = <0x01ee0000 0x10000>; diff --git a/patch/kernel/sunxi-dev/general-add-proc-cpuinfo-entries.patch b/patch/kernel/sunxi-dev/general-arm64-add-proc-cpuinfo-entries.patch similarity index 100% rename from patch/kernel/sunxi-dev/general-add-proc-cpuinfo-entries.patch rename to patch/kernel/sunxi-dev/general-arm64-add-proc-cpuinfo-entries.patch diff --git a/patch/kernel/sunxi64-dev/a64-DT-DVFS.patch b/patch/kernel/sunxi-dev/need-to-check/a64-DT-DVFS.patch similarity index 100% rename from patch/kernel/sunxi64-dev/a64-DT-DVFS.patch rename to patch/kernel/sunxi-dev/need-to-check/a64-DT-DVFS.patch diff --git a/patch/kernel/sunxi64-dev/a64-DVFS-cpu-supply.patch b/patch/kernel/sunxi-dev/need-to-check/a64-DVFS-cpu-supply.patch similarity index 100% rename from patch/kernel/sunxi64-dev/a64-DVFS-cpu-supply.patch rename to patch/kernel/sunxi-dev/need-to-check/a64-DVFS-cpu-supply.patch diff --git a/patch/kernel/sunxi64-dev/a64-pll_cpux-test.patch b/patch/kernel/sunxi-dev/need-to-check/a64-pll_cpux-test.patch similarity index 100% rename from patch/kernel/sunxi64-dev/a64-pll_cpux-test.patch rename to patch/kernel/sunxi-dev/need-to-check/a64-pll_cpux-test.patch diff --git a/patch/kernel/sunxi64-dev/add-mtd-spi-nor-dts.patch.disabled b/patch/kernel/sunxi-dev/need-to-check/add-mtd-spi-nor-dts.patch.disabled similarity index 100% rename from patch/kernel/sunxi64-dev/add-mtd-spi-nor-dts.patch.disabled rename to patch/kernel/sunxi-dev/need-to-check/add-mtd-spi-nor-dts.patch.disabled diff --git a/patch/kernel/sunxi64-dev/add-overlay-compilation-support.patch b/patch/kernel/sunxi-dev/need-to-check/add-overlay-compilation-support.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add-overlay-compilation-support.patch rename to patch/kernel/sunxi-dev/need-to-check/add-overlay-compilation-support.patch diff --git a/patch/kernel/sunxi64-dev/add-spi-flash-pc2.patch b/patch/kernel/sunxi-dev/need-to-check/add-spi-flash-pc2.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add-spi-flash-pc2.patch rename to patch/kernel/sunxi-dev/need-to-check/add-spi-flash-pc2.patch diff --git a/patch/kernel/sunxi64-dev/add-sun50i-ths.patch b/patch/kernel/sunxi-dev/need-to-check/add-sun50i-ths.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add-sun50i-ths.patch rename to patch/kernel/sunxi-dev/need-to-check/add-sun50i-ths.patch diff --git a/patch/kernel/sunxi64-dev/add-sunxi64-overlays.patch b/patch/kernel/sunxi-dev/need-to-check/add-sunxi64-overlays.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add-sunxi64-overlays.patch rename to patch/kernel/sunxi-dev/need-to-check/add-sunxi64-overlays.patch diff --git a/patch/kernel/sunxi64-dev/add-sy8106a-driver.patch b/patch/kernel/sunxi-dev/need-to-check/add-sy8106a-driver.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add-sy8106a-driver.patch rename to patch/kernel/sunxi-dev/need-to-check/add-sy8106a-driver.patch diff --git a/patch/kernel/sunxi64-dev/add_BergMicro_flashes_to_SPI-NOR.patch b/patch/kernel/sunxi-dev/need-to-check/add_BergMicro_flashes_to_SPI-NOR.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add_BergMicro_flashes_to_SPI-NOR.patch rename to patch/kernel/sunxi-dev/need-to-check/add_BergMicro_flashes_to_SPI-NOR.patch diff --git a/patch/kernel/sunxi64-dev/add_configfs_overlay_for_v4.10.x.patch b/patch/kernel/sunxi-dev/need-to-check/add_configfs_overlay_for_v4.10.x.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add_configfs_overlay_for_v4.10.x.patch rename to patch/kernel/sunxi-dev/need-to-check/add_configfs_overlay_for_v4.10.x.patch diff --git a/patch/kernel/sunxi64-dev/add_nanopim1plus2_dts.patch b/patch/kernel/sunxi-dev/need-to-check/add_nanopim1plus2_dts.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add_nanopim1plus2_dts.patch rename to patch/kernel/sunxi-dev/need-to-check/add_nanopim1plus2_dts.patch diff --git a/patch/kernel/sunxi64-dev/add_proc_cpuinfo_entries_for_v4.10.x.patch b/patch/kernel/sunxi-dev/need-to-check/add_proc_cpuinfo_entries_for_v4.10.x.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add_proc_cpuinfo_entries_for_v4.10.x.patch rename to patch/kernel/sunxi-dev/need-to-check/add_proc_cpuinfo_entries_for_v4.10.x.patch diff --git a/patch/kernel/sunxi64-dev/add_sun50i_a64_spi.patch b/patch/kernel/sunxi-dev/need-to-check/add_sun50i_a64_spi.patch similarity index 100% rename from patch/kernel/sunxi64-dev/add_sun50i_a64_spi.patch rename to patch/kernel/sunxi-dev/need-to-check/add_sun50i_a64_spi.patch diff --git a/patch/kernel/sunxi64-dev/badd-nanopineoplus2.patch b/patch/kernel/sunxi-dev/need-to-check/badd-nanopineoplus2.patch similarity index 100% rename from patch/kernel/sunxi64-dev/badd-nanopineoplus2.patch rename to patch/kernel/sunxi-dev/need-to-check/badd-nanopineoplus2.patch diff --git a/patch/kernel/sunxi64-dev/bash_to_afterinstall.patch b/patch/kernel/sunxi-dev/need-to-check/bash_to_afterinstall.patch similarity index 100% rename from patch/kernel/sunxi64-dev/bash_to_afterinstall.patch rename to patch/kernel/sunxi-dev/need-to-check/bash_to_afterinstall.patch diff --git a/patch/kernel/sunxi64-dev/disable-reg_dc1sw-pine64.patch.disabled b/patch/kernel/sunxi-dev/need-to-check/disable-reg_dc1sw-pine64.patch.disabled similarity index 100% rename from patch/kernel/sunxi64-dev/disable-reg_dc1sw-pine64.patch.disabled rename to patch/kernel/sunxi-dev/need-to-check/disable-reg_dc1sw-pine64.patch.disabled diff --git a/patch/kernel/sunxi-dev/dvfs-regulator-opi-2.patch b/patch/kernel/sunxi-dev/need-to-check/dvfs-regulator-opi-2.patch similarity index 100% rename from patch/kernel/sunxi-dev/dvfs-regulator-opi-2.patch rename to patch/kernel/sunxi-dev/need-to-check/dvfs-regulator-opi-2.patch diff --git a/patch/kernel/sunxi-dev/dvfs-regulator-opi-pc2.patch b/patch/kernel/sunxi-dev/need-to-check/dvfs-regulator-opi-pc2.patch similarity index 100% rename from patch/kernel/sunxi-dev/dvfs-regulator-opi-pc2.patch rename to patch/kernel/sunxi-dev/need-to-check/dvfs-regulator-opi-pc2.patch diff --git a/patch/kernel/sunxi-dev/dvfs-regulator-prime.patch b/patch/kernel/sunxi-dev/need-to-check/dvfs-regulator-prime.patch similarity index 100% rename from patch/kernel/sunxi-dev/dvfs-regulator-prime.patch rename to patch/kernel/sunxi-dev/need-to-check/dvfs-regulator-prime.patch diff --git a/patch/kernel/sunxi64-dev/enable-fsl-timer-errata.patch b/patch/kernel/sunxi-dev/need-to-check/enable-fsl-timer-errata.patch similarity index 100% rename from patch/kernel/sunxi64-dev/enable-fsl-timer-errata.patch rename to patch/kernel/sunxi-dev/need-to-check/enable-fsl-timer-errata.patch diff --git a/patch/kernel/sunxi64-dev/fix-i2c2-reg-property.patch b/patch/kernel/sunxi-dev/need-to-check/fix-i2c2-reg-property.patch similarity index 100% rename from patch/kernel/sunxi64-dev/fix-i2c2-reg-property.patch rename to patch/kernel/sunxi-dev/need-to-check/fix-i2c2-reg-property.patch diff --git a/patch/kernel/sunxi64-dev/fix-pinebook-backlight.patch b/patch/kernel/sunxi-dev/need-to-check/fix-pinebook-backlight.patch similarity index 100% rename from patch/kernel/sunxi64-dev/fix-pinebook-backlight.patch rename to patch/kernel/sunxi-dev/need-to-check/fix-pinebook-backlight.patch diff --git a/patch/kernel/sunxi64-dev/fix-zeroplus2-mmc0-cd-polarity.patch b/patch/kernel/sunxi-dev/need-to-check/fix-zeroplus2-mmc0-cd-polarity.patch similarity index 100% rename from patch/kernel/sunxi64-dev/fix-zeroplus2-mmc0-cd-polarity.patch rename to patch/kernel/sunxi-dev/need-to-check/fix-zeroplus2-mmc0-cd-polarity.patch diff --git a/patch/kernel/sunxi64-dev/scripts-dtc-import-updates.patch b/patch/kernel/sunxi-dev/need-to-check/scripts-dtc-import-updates.patch similarity index 100% rename from patch/kernel/sunxi64-dev/scripts-dtc-import-updates.patch rename to patch/kernel/sunxi-dev/need-to-check/scripts-dtc-import-updates.patch diff --git a/patch/kernel/sunxi64-dev/set-default-target-to-Image.patch b/patch/kernel/sunxi-dev/need-to-check/set-default-target-to-Image.patch similarity index 100% rename from patch/kernel/sunxi64-dev/set-default-target-to-Image.patch rename to patch/kernel/sunxi-dev/need-to-check/set-default-target-to-Image.patch diff --git a/patch/kernel/sunxi64-dev/spidev-remove-warnings.patch b/patch/kernel/sunxi-dev/need-to-check/spidev-remove-warnings.patch similarity index 100% rename from patch/kernel/sunxi64-dev/spidev-remove-warnings.patch rename to patch/kernel/sunxi-dev/need-to-check/spidev-remove-warnings.patch diff --git a/patch/kernel/sunxi-dev/patch-4.19.1-2.patch b/patch/kernel/sunxi-dev/patch-4.19.1-2.patch new file mode 100644 index 000000000..62ce83cb6 --- /dev/null +++ b/patch/kernel/sunxi-dev/patch-4.19.1-2.patch @@ -0,0 +1,15435 @@ +diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst +index 48b424de85bb..cfbc18f0d9c9 100644 +--- a/Documentation/filesystems/fscrypt.rst ++++ b/Documentation/filesystems/fscrypt.rst +@@ -191,21 +191,11 @@ Currently, the following pairs of encryption modes are supported: + + - AES-256-XTS for contents and AES-256-CTS-CBC for filenames + - AES-128-CBC for contents and AES-128-CTS-CBC for filenames +-- Speck128/256-XTS for contents and Speck128/256-CTS-CBC for filenames + + It is strongly recommended to use AES-256-XTS for contents encryption. + AES-128-CBC was added only for low-powered embedded devices with + crypto accelerators such as CAAM or CESA that do not support XTS. + +-Similarly, Speck128/256 support was only added for older or low-end +-CPUs which cannot do AES fast enough -- especially ARM CPUs which have +-NEON instructions but not the Cryptography Extensions -- and for which +-it would not otherwise be feasible to use encryption at all. It is +-not recommended to use Speck on CPUs that have AES instructions. +-Speck support is only available if it has been enabled in the crypto +-API via CONFIG_CRYPTO_SPECK. Also, on ARM platforms, to get +-acceptable performance CONFIG_CRYPTO_SPECK_NEON must be enabled. +- + New encryption modes can be added relatively easily, without changes + to individual filesystems. However, authenticated encryption (AE) + modes are not currently supported because of the difficulty of dealing +diff --git a/Documentation/media/uapi/cec/cec-ioc-receive.rst b/Documentation/media/uapi/cec/cec-ioc-receive.rst +index e964074cd15b..b25e48afaa08 100644 +--- a/Documentation/media/uapi/cec/cec-ioc-receive.rst ++++ b/Documentation/media/uapi/cec/cec-ioc-receive.rst +@@ -16,10 +16,10 @@ CEC_RECEIVE, CEC_TRANSMIT - Receive or transmit a CEC message + Synopsis + ======== + +-.. c:function:: int ioctl( int fd, CEC_RECEIVE, struct cec_msg *argp ) ++.. c:function:: int ioctl( int fd, CEC_RECEIVE, struct cec_msg \*argp ) + :name: CEC_RECEIVE + +-.. c:function:: int ioctl( int fd, CEC_TRANSMIT, struct cec_msg *argp ) ++.. c:function:: int ioctl( int fd, CEC_TRANSMIT, struct cec_msg \*argp ) + :name: CEC_TRANSMIT + + Arguments +@@ -272,6 +272,19 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV'). + - The transmit failed after one or more retries. This status bit is + mutually exclusive with :ref:`CEC_TX_STATUS_OK `. + Other bits can still be set to explain which failures were seen. ++ * .. _`CEC-TX-STATUS-ABORTED`: ++ ++ - ``CEC_TX_STATUS_ABORTED`` ++ - 0x40 ++ - The transmit was aborted due to an HDMI disconnect, or the adapter ++ was unconfigured, or a transmit was interrupted, or the driver ++ returned an error when attempting to start a transmit. ++ * .. _`CEC-TX-STATUS-TIMEOUT`: ++ ++ - ``CEC_TX_STATUS_TIMEOUT`` ++ - 0x80 ++ - The transmit timed out. This should not normally happen and this ++ indicates a driver problem. + + + .. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}| +@@ -300,6 +313,14 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV'). + - The message was received successfully but the reply was + ``CEC_MSG_FEATURE_ABORT``. This status is only set if this message + was the reply to an earlier transmitted message. ++ * .. _`CEC-RX-STATUS-ABORTED`: ++ ++ - ``CEC_RX_STATUS_ABORTED`` ++ - 0x08 ++ - The wait for a reply to an earlier transmitted message was aborted ++ because the HDMI cable was disconnected, the adapter was unconfigured ++ or the :ref:`CEC_TRANSMIT ` that waited for a ++ reply was interrupted. + + + +diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst +index 1cedcfc04327..386d6cf83e9c 100644 +--- a/Documentation/media/uapi/v4l/biblio.rst ++++ b/Documentation/media/uapi/v4l/biblio.rst +@@ -226,16 +226,6 @@ xvYCC + + :author: International Electrotechnical Commission (http://www.iec.ch) + +-.. _adobergb: +- +-AdobeRGB +-======== +- +- +-:title: Adobe© RGB (1998) Color Image Encoding Version 2005-05 +- +-:author: Adobe Systems Incorporated (http://www.adobe.com) +- + .. _oprgb: + + opRGB +diff --git a/Documentation/media/uapi/v4l/colorspaces-defs.rst b/Documentation/media/uapi/v4l/colorspaces-defs.rst +index 410907fe9415..f24615544792 100644 +--- a/Documentation/media/uapi/v4l/colorspaces-defs.rst ++++ b/Documentation/media/uapi/v4l/colorspaces-defs.rst +@@ -51,8 +51,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum + - See :ref:`col-rec709`. + * - ``V4L2_COLORSPACE_SRGB`` + - See :ref:`col-srgb`. +- * - ``V4L2_COLORSPACE_ADOBERGB`` +- - See :ref:`col-adobergb`. ++ * - ``V4L2_COLORSPACE_OPRGB`` ++ - See :ref:`col-oprgb`. + * - ``V4L2_COLORSPACE_BT2020`` + - See :ref:`col-bt2020`. + * - ``V4L2_COLORSPACE_DCI_P3`` +@@ -90,8 +90,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum + - Use the Rec. 709 transfer function. + * - ``V4L2_XFER_FUNC_SRGB`` + - Use the sRGB transfer function. +- * - ``V4L2_XFER_FUNC_ADOBERGB`` +- - Use the AdobeRGB transfer function. ++ * - ``V4L2_XFER_FUNC_OPRGB`` ++ - Use the opRGB transfer function. + * - ``V4L2_XFER_FUNC_SMPTE240M`` + - Use the SMPTE 240M transfer function. + * - ``V4L2_XFER_FUNC_NONE`` +diff --git a/Documentation/media/uapi/v4l/colorspaces-details.rst b/Documentation/media/uapi/v4l/colorspaces-details.rst +index b5d551b9cc8f..09fabf4cd412 100644 +--- a/Documentation/media/uapi/v4l/colorspaces-details.rst ++++ b/Documentation/media/uapi/v4l/colorspaces-details.rst +@@ -290,15 +290,14 @@ Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range + 170M/BT.601. The Y'CbCr quantization is limited range. + + +-.. _col-adobergb: ++.. _col-oprgb: + +-Colorspace Adobe RGB (V4L2_COLORSPACE_ADOBERGB) ++Colorspace opRGB (V4L2_COLORSPACE_OPRGB) + =============================================== + +-The :ref:`adobergb` standard defines the colorspace used by computer +-graphics that use the AdobeRGB colorspace. This is also known as the +-:ref:`oprgb` standard. The default transfer function is +-``V4L2_XFER_FUNC_ADOBERGB``. The default Y'CbCr encoding is ++The :ref:`oprgb` standard defines the colorspace used by computer ++graphics that use the opRGB colorspace. The default transfer function is ++``V4L2_XFER_FUNC_OPRGB``. The default Y'CbCr encoding is + ``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is limited + range. + +@@ -312,7 +311,7 @@ The chromaticities of the primary colors and the white reference are: + + .. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}| + +-.. flat-table:: Adobe RGB Chromaticities ++.. flat-table:: opRGB Chromaticities + :header-rows: 1 + :stub-columns: 0 + :widths: 1 1 2 +diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions +index ca9f0edc579e..e420a39f1ebf 100644 +--- a/Documentation/media/videodev2.h.rst.exceptions ++++ b/Documentation/media/videodev2.h.rst.exceptions +@@ -56,7 +56,8 @@ replace symbol V4L2_MEMORY_USERPTR :c:type:`v4l2_memory` + # Documented enum v4l2_colorspace + replace symbol V4L2_COLORSPACE_470_SYSTEM_BG :c:type:`v4l2_colorspace` + replace symbol V4L2_COLORSPACE_470_SYSTEM_M :c:type:`v4l2_colorspace` +-replace symbol V4L2_COLORSPACE_ADOBERGB :c:type:`v4l2_colorspace` ++replace symbol V4L2_COLORSPACE_OPRGB :c:type:`v4l2_colorspace` ++replace define V4L2_COLORSPACE_ADOBERGB :c:type:`v4l2_colorspace` + replace symbol V4L2_COLORSPACE_BT2020 :c:type:`v4l2_colorspace` + replace symbol V4L2_COLORSPACE_DCI_P3 :c:type:`v4l2_colorspace` + replace symbol V4L2_COLORSPACE_DEFAULT :c:type:`v4l2_colorspace` +@@ -69,7 +70,8 @@ replace symbol V4L2_COLORSPACE_SRGB :c:type:`v4l2_colorspace` + + # Documented enum v4l2_xfer_func + replace symbol V4L2_XFER_FUNC_709 :c:type:`v4l2_xfer_func` +-replace symbol V4L2_XFER_FUNC_ADOBERGB :c:type:`v4l2_xfer_func` ++replace symbol V4L2_XFER_FUNC_OPRGB :c:type:`v4l2_xfer_func` ++replace define V4L2_XFER_FUNC_ADOBERGB :c:type:`v4l2_xfer_func` + replace symbol V4L2_XFER_FUNC_DCI_P3 :c:type:`v4l2_xfer_func` + replace symbol V4L2_XFER_FUNC_DEFAULT :c:type:`v4l2_xfer_func` + replace symbol V4L2_XFER_FUNC_NONE :c:type:`v4l2_xfer_func` +diff --git a/Makefile b/Makefile +index abcd8ca4966f..c8fe567f18ab 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 1 ++SUBLEVEL = 2 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi +index a0ddf497e8cd..2cb45ddd2ae3 100644 +--- a/arch/arm/boot/dts/dra7.dtsi ++++ b/arch/arm/boot/dts/dra7.dtsi +@@ -354,7 +354,7 @@ + ti,hwmods = "pcie1"; + phys = <&pcie1_phy>; + phy-names = "pcie-phy0"; +- ti,syscon-unaligned-access = <&scm_conf1 0x14 2>; ++ ti,syscon-unaligned-access = <&scm_conf1 0x14 1>; + status = "disabled"; + }; + }; +diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts +index 2ab99f9f3d0a..dd9ec05eb0f7 100644 +--- a/arch/arm/boot/dts/exynos4210-origen.dts ++++ b/arch/arm/boot/dts/exynos4210-origen.dts +@@ -151,6 +151,8 @@ + reg = <0x66>; + interrupt-parent = <&gpx0>; + interrupts = <4 IRQ_TYPE_NONE>, <3 IRQ_TYPE_NONE>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&max8997_irq>; + + max8997,pmic-buck1-dvs-voltage = <1350000>; + max8997,pmic-buck2-dvs-voltage = <1100000>; +@@ -288,6 +290,13 @@ + }; + }; + ++&pinctrl_1 { ++ max8997_irq: max8997-irq { ++ samsung,pins = "gpx0-3", "gpx0-4"; ++ samsung,pin-pud = ; ++ }; ++}; ++ + &sdhci_0 { + bus-width = <4>; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_cd>; +diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi +index da163a40af15..b85527faa6ea 100644 +--- a/arch/arm/boot/dts/exynos5250.dtsi ++++ b/arch/arm/boot/dts/exynos5250.dtsi +@@ -54,62 +54,109 @@ + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0>; +- clock-frequency = <1700000000>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; +- clock-latency = <140000>; +- +- operating-points = < +- 1700000 1300000 +- 1600000 1250000 +- 1500000 1225000 +- 1400000 1200000 +- 1300000 1150000 +- 1200000 1125000 +- 1100000 1100000 +- 1000000 1075000 +- 900000 1050000 +- 800000 1025000 +- 700000 1012500 +- 600000 1000000 +- 500000 975000 +- 400000 950000 +- 300000 937500 +- 200000 925000 +- >; ++ operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <1>; +- clock-frequency = <1700000000>; + clocks = <&clock CLK_ARM_CLK>; + clock-names = "cpu"; +- clock-latency = <140000>; +- +- operating-points = < +- 1700000 1300000 +- 1600000 1250000 +- 1500000 1225000 +- 1400000 1200000 +- 1300000 1150000 +- 1200000 1125000 +- 1100000 1100000 +- 1000000 1075000 +- 900000 1050000 +- 800000 1025000 +- 700000 1012500 +- 600000 1000000 +- 500000 975000 +- 400000 950000 +- 300000 937500 +- 200000 925000 +- >; ++ operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + }; + ++ cpu0_opp_table: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-200000000 { ++ opp-hz = /bits/ 64 <200000000>; ++ opp-microvolt = <925000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <937500>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <950000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-500000000 { ++ opp-hz = /bits/ 64 <500000000>; ++ opp-microvolt = <975000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <1000000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-700000000 { ++ opp-hz = /bits/ 64 <700000000>; ++ opp-microvolt = <1012500>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <1025000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-900000000 { ++ opp-hz = /bits/ 64 <900000000>; ++ opp-microvolt = <1050000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <1075000>; ++ clock-latency-ns = <140000>; ++ opp-suspend; ++ }; ++ opp-1100000000 { ++ opp-hz = /bits/ 64 <1100000000>; ++ opp-microvolt = <1100000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <1125000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-1300000000 { ++ opp-hz = /bits/ 64 <1300000000>; ++ opp-microvolt = <1150000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-1400000000 { ++ opp-hz = /bits/ 64 <1400000000>; ++ opp-microvolt = <1200000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-1500000000 { ++ opp-hz = /bits/ 64 <1500000000>; ++ opp-microvolt = <1225000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-1600000000 { ++ opp-hz = /bits/ 64 <1600000000>; ++ opp-microvolt = <1250000>; ++ clock-latency-ns = <140000>; ++ }; ++ opp-1700000000 { ++ opp-hz = /bits/ 64 <1700000000>; ++ opp-microvolt = <1300000>; ++ clock-latency-ns = <140000>; ++ }; ++ }; ++ + soc: soc { + sysram@2020000 { + compatible = "mmio-sram"; +diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi +index a4dcb68f4322..b4dd3846e8cc 100644 +--- a/arch/arm/boot/dts/socfpga_arria10.dtsi ++++ b/arch/arm/boot/dts/socfpga_arria10.dtsi +@@ -613,7 +613,7 @@ + status = "disabled"; + }; + +- sdr: sdr@ffc25000 { ++ sdr: sdr@ffcfb100 { + compatible = "altr,sdr-ctl", "syscon"; + reg = <0xffcfb100 0x80>; + }; +diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig +index 925d1364727a..b8e69fe282b8 100644 +--- a/arch/arm/crypto/Kconfig ++++ b/arch/arm/crypto/Kconfig +@@ -121,10 +121,4 @@ config CRYPTO_CHACHA20_NEON + select CRYPTO_BLKCIPHER + select CRYPTO_CHACHA20 + +-config CRYPTO_SPECK_NEON +- tristate "NEON accelerated Speck cipher algorithms" +- depends on KERNEL_MODE_NEON +- select CRYPTO_BLKCIPHER +- select CRYPTO_SPECK +- + endif +diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile +index 8de542c48ade..bd5bceef0605 100644 +--- a/arch/arm/crypto/Makefile ++++ b/arch/arm/crypto/Makefile +@@ -10,7 +10,6 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o + obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o + obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o + obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha20-neon.o +-obj-$(CONFIG_CRYPTO_SPECK_NEON) += speck-neon.o + + ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o + ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o +@@ -54,7 +53,6 @@ ghash-arm-ce-y := ghash-ce-core.o ghash-ce-glue.o + crct10dif-arm-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o + crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o + chacha20-neon-y := chacha20-neon-core.o chacha20-neon-glue.o +-speck-neon-y := speck-neon-core.o speck-neon-glue.o + + ifdef REGENERATE_ARM_CRYPTO + quiet_cmd_perl = PERL $@ +diff --git a/arch/arm/crypto/speck-neon-core.S b/arch/arm/crypto/speck-neon-core.S +deleted file mode 100644 +index 57caa742016e..000000000000 +--- a/arch/arm/crypto/speck-neon-core.S ++++ /dev/null +@@ -1,434 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * NEON-accelerated implementation of Speck128-XTS and Speck64-XTS +- * +- * Copyright (c) 2018 Google, Inc +- * +- * Author: Eric Biggers +- */ +- +-#include +- +- .text +- .fpu neon +- +- // arguments +- ROUND_KEYS .req r0 // const {u64,u32} *round_keys +- NROUNDS .req r1 // int nrounds +- DST .req r2 // void *dst +- SRC .req r3 // const void *src +- NBYTES .req r4 // unsigned int nbytes +- TWEAK .req r5 // void *tweak +- +- // registers which hold the data being encrypted/decrypted +- X0 .req q0 +- X0_L .req d0 +- X0_H .req d1 +- Y0 .req q1 +- Y0_H .req d3 +- X1 .req q2 +- X1_L .req d4 +- X1_H .req d5 +- Y1 .req q3 +- Y1_H .req d7 +- X2 .req q4 +- X2_L .req d8 +- X2_H .req d9 +- Y2 .req q5 +- Y2_H .req d11 +- X3 .req q6 +- X3_L .req d12 +- X3_H .req d13 +- Y3 .req q7 +- Y3_H .req d15 +- +- // the round key, duplicated in all lanes +- ROUND_KEY .req q8 +- ROUND_KEY_L .req d16 +- ROUND_KEY_H .req d17 +- +- // index vector for vtbl-based 8-bit rotates +- ROTATE_TABLE .req d18 +- +- // multiplication table for updating XTS tweaks +- GF128MUL_TABLE .req d19 +- GF64MUL_TABLE .req d19 +- +- // current XTS tweak value(s) +- TWEAKV .req q10 +- TWEAKV_L .req d20 +- TWEAKV_H .req d21 +- +- TMP0 .req q12 +- TMP0_L .req d24 +- TMP0_H .req d25 +- TMP1 .req q13 +- TMP2 .req q14 +- TMP3 .req q15 +- +- .align 4 +-.Lror64_8_table: +- .byte 1, 2, 3, 4, 5, 6, 7, 0 +-.Lror32_8_table: +- .byte 1, 2, 3, 0, 5, 6, 7, 4 +-.Lrol64_8_table: +- .byte 7, 0, 1, 2, 3, 4, 5, 6 +-.Lrol32_8_table: +- .byte 3, 0, 1, 2, 7, 4, 5, 6 +-.Lgf128mul_table: +- .byte 0, 0x87 +- .fill 14 +-.Lgf64mul_table: +- .byte 0, 0x1b, (0x1b << 1), (0x1b << 1) ^ 0x1b +- .fill 12 +- +-/* +- * _speck_round_128bytes() - Speck encryption round on 128 bytes at a time +- * +- * Do one Speck encryption round on the 128 bytes (8 blocks for Speck128, 16 for +- * Speck64) stored in X0-X3 and Y0-Y3, using the round key stored in all lanes +- * of ROUND_KEY. 'n' is the lane size: 64 for Speck128, or 32 for Speck64. +- * +- * The 8-bit rotates are implemented using vtbl instead of vshr + vsli because +- * the vtbl approach is faster on some processors and the same speed on others. +- */ +-.macro _speck_round_128bytes n +- +- // x = ror(x, 8) +- vtbl.8 X0_L, {X0_L}, ROTATE_TABLE +- vtbl.8 X0_H, {X0_H}, ROTATE_TABLE +- vtbl.8 X1_L, {X1_L}, ROTATE_TABLE +- vtbl.8 X1_H, {X1_H}, ROTATE_TABLE +- vtbl.8 X2_L, {X2_L}, ROTATE_TABLE +- vtbl.8 X2_H, {X2_H}, ROTATE_TABLE +- vtbl.8 X3_L, {X3_L}, ROTATE_TABLE +- vtbl.8 X3_H, {X3_H}, ROTATE_TABLE +- +- // x += y +- vadd.u\n X0, Y0 +- vadd.u\n X1, Y1 +- vadd.u\n X2, Y2 +- vadd.u\n X3, Y3 +- +- // x ^= k +- veor X0, ROUND_KEY +- veor X1, ROUND_KEY +- veor X2, ROUND_KEY +- veor X3, ROUND_KEY +- +- // y = rol(y, 3) +- vshl.u\n TMP0, Y0, #3 +- vshl.u\n TMP1, Y1, #3 +- vshl.u\n TMP2, Y2, #3 +- vshl.u\n TMP3, Y3, #3 +- vsri.u\n TMP0, Y0, #(\n - 3) +- vsri.u\n TMP1, Y1, #(\n - 3) +- vsri.u\n TMP2, Y2, #(\n - 3) +- vsri.u\n TMP3, Y3, #(\n - 3) +- +- // y ^= x +- veor Y0, TMP0, X0 +- veor Y1, TMP1, X1 +- veor Y2, TMP2, X2 +- veor Y3, TMP3, X3 +-.endm +- +-/* +- * _speck_unround_128bytes() - Speck decryption round on 128 bytes at a time +- * +- * This is the inverse of _speck_round_128bytes(). +- */ +-.macro _speck_unround_128bytes n +- +- // y ^= x +- veor TMP0, Y0, X0 +- veor TMP1, Y1, X1 +- veor TMP2, Y2, X2 +- veor TMP3, Y3, X3 +- +- // y = ror(y, 3) +- vshr.u\n Y0, TMP0, #3 +- vshr.u\n Y1, TMP1, #3 +- vshr.u\n Y2, TMP2, #3 +- vshr.u\n Y3, TMP3, #3 +- vsli.u\n Y0, TMP0, #(\n - 3) +- vsli.u\n Y1, TMP1, #(\n - 3) +- vsli.u\n Y2, TMP2, #(\n - 3) +- vsli.u\n Y3, TMP3, #(\n - 3) +- +- // x ^= k +- veor X0, ROUND_KEY +- veor X1, ROUND_KEY +- veor X2, ROUND_KEY +- veor X3, ROUND_KEY +- +- // x -= y +- vsub.u\n X0, Y0 +- vsub.u\n X1, Y1 +- vsub.u\n X2, Y2 +- vsub.u\n X3, Y3 +- +- // x = rol(x, 8); +- vtbl.8 X0_L, {X0_L}, ROTATE_TABLE +- vtbl.8 X0_H, {X0_H}, ROTATE_TABLE +- vtbl.8 X1_L, {X1_L}, ROTATE_TABLE +- vtbl.8 X1_H, {X1_H}, ROTATE_TABLE +- vtbl.8 X2_L, {X2_L}, ROTATE_TABLE +- vtbl.8 X2_H, {X2_H}, ROTATE_TABLE +- vtbl.8 X3_L, {X3_L}, ROTATE_TABLE +- vtbl.8 X3_H, {X3_H}, ROTATE_TABLE +-.endm +- +-.macro _xts128_precrypt_one dst_reg, tweak_buf, tmp +- +- // Load the next source block +- vld1.8 {\dst_reg}, [SRC]! +- +- // Save the current tweak in the tweak buffer +- vst1.8 {TWEAKV}, [\tweak_buf:128]! +- +- // XOR the next source block with the current tweak +- veor \dst_reg, TWEAKV +- +- /* +- * Calculate the next tweak by multiplying the current one by x, +- * modulo p(x) = x^128 + x^7 + x^2 + x + 1. +- */ +- vshr.u64 \tmp, TWEAKV, #63 +- vshl.u64 TWEAKV, #1 +- veor TWEAKV_H, \tmp\()_L +- vtbl.8 \tmp\()_H, {GF128MUL_TABLE}, \tmp\()_H +- veor TWEAKV_L, \tmp\()_H +-.endm +- +-.macro _xts64_precrypt_two dst_reg, tweak_buf, tmp +- +- // Load the next two source blocks +- vld1.8 {\dst_reg}, [SRC]! +- +- // Save the current two tweaks in the tweak buffer +- vst1.8 {TWEAKV}, [\tweak_buf:128]! +- +- // XOR the next two source blocks with the current two tweaks +- veor \dst_reg, TWEAKV +- +- /* +- * Calculate the next two tweaks by multiplying the current ones by x^2, +- * modulo p(x) = x^64 + x^4 + x^3 + x + 1. +- */ +- vshr.u64 \tmp, TWEAKV, #62 +- vshl.u64 TWEAKV, #2 +- vtbl.8 \tmp\()_L, {GF64MUL_TABLE}, \tmp\()_L +- vtbl.8 \tmp\()_H, {GF64MUL_TABLE}, \tmp\()_H +- veor TWEAKV, \tmp +-.endm +- +-/* +- * _speck_xts_crypt() - Speck-XTS encryption/decryption +- * +- * Encrypt or decrypt NBYTES bytes of data from the SRC buffer to the DST buffer +- * using Speck-XTS, specifically the variant with a block size of '2n' and round +- * count given by NROUNDS. The expanded round keys are given in ROUND_KEYS, and +- * the current XTS tweak value is given in TWEAK. It's assumed that NBYTES is a +- * nonzero multiple of 128. +- */ +-.macro _speck_xts_crypt n, decrypting +- push {r4-r7} +- mov r7, sp +- +- /* +- * The first four parameters were passed in registers r0-r3. Load the +- * additional parameters, which were passed on the stack. +- */ +- ldr NBYTES, [sp, #16] +- ldr TWEAK, [sp, #20] +- +- /* +- * If decrypting, modify the ROUND_KEYS parameter to point to the last +- * round key rather than the first, since for decryption the round keys +- * are used in reverse order. +- */ +-.if \decrypting +-.if \n == 64 +- add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #3 +- sub ROUND_KEYS, #8 +-.else +- add ROUND_KEYS, ROUND_KEYS, NROUNDS, lsl #2 +- sub ROUND_KEYS, #4 +-.endif +-.endif +- +- // Load the index vector for vtbl-based 8-bit rotates +-.if \decrypting +- ldr r12, =.Lrol\n\()_8_table +-.else +- ldr r12, =.Lror\n\()_8_table +-.endif +- vld1.8 {ROTATE_TABLE}, [r12:64] +- +- // One-time XTS preparation +- +- /* +- * Allocate stack space to store 128 bytes worth of tweaks. For +- * performance, this space is aligned to a 16-byte boundary so that we +- * can use the load/store instructions that declare 16-byte alignment. +- * For Thumb2 compatibility, don't do the 'bic' directly on 'sp'. +- */ +- sub r12, sp, #128 +- bic r12, #0xf +- mov sp, r12 +- +-.if \n == 64 +- // Load first tweak +- vld1.8 {TWEAKV}, [TWEAK] +- +- // Load GF(2^128) multiplication table +- ldr r12, =.Lgf128mul_table +- vld1.8 {GF128MUL_TABLE}, [r12:64] +-.else +- // Load first tweak +- vld1.8 {TWEAKV_L}, [TWEAK] +- +- // Load GF(2^64) multiplication table +- ldr r12, =.Lgf64mul_table +- vld1.8 {GF64MUL_TABLE}, [r12:64] +- +- // Calculate second tweak, packing it together with the first +- vshr.u64 TMP0_L, TWEAKV_L, #63 +- vtbl.u8 TMP0_L, {GF64MUL_TABLE}, TMP0_L +- vshl.u64 TWEAKV_H, TWEAKV_L, #1 +- veor TWEAKV_H, TMP0_L +-.endif +- +-.Lnext_128bytes_\@: +- +- /* +- * Load the source blocks into {X,Y}[0-3], XOR them with their XTS tweak +- * values, and save the tweaks on the stack for later. Then +- * de-interleave the 'x' and 'y' elements of each block, i.e. make it so +- * that the X[0-3] registers contain only the second halves of blocks, +- * and the Y[0-3] registers contain only the first halves of blocks. +- * (Speck uses the order (y, x) rather than the more intuitive (x, y).) +- */ +- mov r12, sp +-.if \n == 64 +- _xts128_precrypt_one X0, r12, TMP0 +- _xts128_precrypt_one Y0, r12, TMP0 +- _xts128_precrypt_one X1, r12, TMP0 +- _xts128_precrypt_one Y1, r12, TMP0 +- _xts128_precrypt_one X2, r12, TMP0 +- _xts128_precrypt_one Y2, r12, TMP0 +- _xts128_precrypt_one X3, r12, TMP0 +- _xts128_precrypt_one Y3, r12, TMP0 +- vswp X0_L, Y0_H +- vswp X1_L, Y1_H +- vswp X2_L, Y2_H +- vswp X3_L, Y3_H +-.else +- _xts64_precrypt_two X0, r12, TMP0 +- _xts64_precrypt_two Y0, r12, TMP0 +- _xts64_precrypt_two X1, r12, TMP0 +- _xts64_precrypt_two Y1, r12, TMP0 +- _xts64_precrypt_two X2, r12, TMP0 +- _xts64_precrypt_two Y2, r12, TMP0 +- _xts64_precrypt_two X3, r12, TMP0 +- _xts64_precrypt_two Y3, r12, TMP0 +- vuzp.32 Y0, X0 +- vuzp.32 Y1, X1 +- vuzp.32 Y2, X2 +- vuzp.32 Y3, X3 +-.endif +- +- // Do the cipher rounds +- +- mov r12, ROUND_KEYS +- mov r6, NROUNDS +- +-.Lnext_round_\@: +-.if \decrypting +-.if \n == 64 +- vld1.64 ROUND_KEY_L, [r12] +- sub r12, #8 +- vmov ROUND_KEY_H, ROUND_KEY_L +-.else +- vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12] +- sub r12, #4 +-.endif +- _speck_unround_128bytes \n +-.else +-.if \n == 64 +- vld1.64 ROUND_KEY_L, [r12]! +- vmov ROUND_KEY_H, ROUND_KEY_L +-.else +- vld1.32 {ROUND_KEY_L[],ROUND_KEY_H[]}, [r12]! +-.endif +- _speck_round_128bytes \n +-.endif +- subs r6, r6, #1 +- bne .Lnext_round_\@ +- +- // Re-interleave the 'x' and 'y' elements of each block +-.if \n == 64 +- vswp X0_L, Y0_H +- vswp X1_L, Y1_H +- vswp X2_L, Y2_H +- vswp X3_L, Y3_H +-.else +- vzip.32 Y0, X0 +- vzip.32 Y1, X1 +- vzip.32 Y2, X2 +- vzip.32 Y3, X3 +-.endif +- +- // XOR the encrypted/decrypted blocks with the tweaks we saved earlier +- mov r12, sp +- vld1.8 {TMP0, TMP1}, [r12:128]! +- vld1.8 {TMP2, TMP3}, [r12:128]! +- veor X0, TMP0 +- veor Y0, TMP1 +- veor X1, TMP2 +- veor Y1, TMP3 +- vld1.8 {TMP0, TMP1}, [r12:128]! +- vld1.8 {TMP2, TMP3}, [r12:128]! +- veor X2, TMP0 +- veor Y2, TMP1 +- veor X3, TMP2 +- veor Y3, TMP3 +- +- // Store the ciphertext in the destination buffer +- vst1.8 {X0, Y0}, [DST]! +- vst1.8 {X1, Y1}, [DST]! +- vst1.8 {X2, Y2}, [DST]! +- vst1.8 {X3, Y3}, [DST]! +- +- // Continue if there are more 128-byte chunks remaining, else return +- subs NBYTES, #128 +- bne .Lnext_128bytes_\@ +- +- // Store the next tweak +-.if \n == 64 +- vst1.8 {TWEAKV}, [TWEAK] +-.else +- vst1.8 {TWEAKV_L}, [TWEAK] +-.endif +- +- mov sp, r7 +- pop {r4-r7} +- bx lr +-.endm +- +-ENTRY(speck128_xts_encrypt_neon) +- _speck_xts_crypt n=64, decrypting=0 +-ENDPROC(speck128_xts_encrypt_neon) +- +-ENTRY(speck128_xts_decrypt_neon) +- _speck_xts_crypt n=64, decrypting=1 +-ENDPROC(speck128_xts_decrypt_neon) +- +-ENTRY(speck64_xts_encrypt_neon) +- _speck_xts_crypt n=32, decrypting=0 +-ENDPROC(speck64_xts_encrypt_neon) +- +-ENTRY(speck64_xts_decrypt_neon) +- _speck_xts_crypt n=32, decrypting=1 +-ENDPROC(speck64_xts_decrypt_neon) +diff --git a/arch/arm/crypto/speck-neon-glue.c b/arch/arm/crypto/speck-neon-glue.c +deleted file mode 100644 +index f012c3ea998f..000000000000 +--- a/arch/arm/crypto/speck-neon-glue.c ++++ /dev/null +@@ -1,288 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * NEON-accelerated implementation of Speck128-XTS and Speck64-XTS +- * +- * Copyright (c) 2018 Google, Inc +- * +- * Note: the NIST recommendation for XTS only specifies a 128-bit block size, +- * but a 64-bit version (needed for Speck64) is fairly straightforward; the math +- * is just done in GF(2^64) instead of GF(2^128), with the reducing polynomial +- * x^64 + x^4 + x^3 + x + 1 from the original XEX paper (Rogaway, 2004: +- * "Efficient Instantiations of Tweakable Blockciphers and Refinements to Modes +- * OCB and PMAC"), represented as 0x1B. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* The assembly functions only handle multiples of 128 bytes */ +-#define SPECK_NEON_CHUNK_SIZE 128 +- +-/* Speck128 */ +- +-struct speck128_xts_tfm_ctx { +- struct speck128_tfm_ctx main_key; +- struct speck128_tfm_ctx tweak_key; +-}; +- +-asmlinkage void speck128_xts_encrypt_neon(const u64 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-asmlinkage void speck128_xts_decrypt_neon(const u64 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-typedef void (*speck128_crypt_one_t)(const struct speck128_tfm_ctx *, +- u8 *, const u8 *); +-typedef void (*speck128_xts_crypt_many_t)(const u64 *, int, void *, +- const void *, unsigned int, void *); +- +-static __always_inline int +-__speck128_xts_crypt(struct skcipher_request *req, +- speck128_crypt_one_t crypt_one, +- speck128_xts_crypt_many_t crypt_many) +-{ +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- const struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct skcipher_walk walk; +- le128 tweak; +- int err; +- +- err = skcipher_walk_virt(&walk, req, true); +- +- crypto_speck128_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); +- +- while (walk.nbytes > 0) { +- unsigned int nbytes = walk.nbytes; +- u8 *dst = walk.dst.virt.addr; +- const u8 *src = walk.src.virt.addr; +- +- if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { +- unsigned int count; +- +- count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); +- kernel_neon_begin(); +- (*crypt_many)(ctx->main_key.round_keys, +- ctx->main_key.nrounds, +- dst, src, count, &tweak); +- kernel_neon_end(); +- dst += count; +- src += count; +- nbytes -= count; +- } +- +- /* Handle any remainder with generic code */ +- while (nbytes >= sizeof(tweak)) { +- le128_xor((le128 *)dst, (const le128 *)src, &tweak); +- (*crypt_one)(&ctx->main_key, dst, dst); +- le128_xor((le128 *)dst, (const le128 *)dst, &tweak); +- gf128mul_x_ble(&tweak, &tweak); +- +- dst += sizeof(tweak); +- src += sizeof(tweak); +- nbytes -= sizeof(tweak); +- } +- err = skcipher_walk_done(&walk, nbytes); +- } +- +- return err; +-} +- +-static int speck128_xts_encrypt(struct skcipher_request *req) +-{ +- return __speck128_xts_crypt(req, crypto_speck128_encrypt, +- speck128_xts_encrypt_neon); +-} +- +-static int speck128_xts_decrypt(struct skcipher_request *req) +-{ +- return __speck128_xts_crypt(req, crypto_speck128_decrypt, +- speck128_xts_decrypt_neon); +-} +- +-static int speck128_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, +- unsigned int keylen) +-{ +- struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- int err; +- +- err = xts_verify_key(tfm, key, keylen); +- if (err) +- return err; +- +- keylen /= 2; +- +- err = crypto_speck128_setkey(&ctx->main_key, key, keylen); +- if (err) +- return err; +- +- return crypto_speck128_setkey(&ctx->tweak_key, key + keylen, keylen); +-} +- +-/* Speck64 */ +- +-struct speck64_xts_tfm_ctx { +- struct speck64_tfm_ctx main_key; +- struct speck64_tfm_ctx tweak_key; +-}; +- +-asmlinkage void speck64_xts_encrypt_neon(const u32 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-asmlinkage void speck64_xts_decrypt_neon(const u32 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-typedef void (*speck64_crypt_one_t)(const struct speck64_tfm_ctx *, +- u8 *, const u8 *); +-typedef void (*speck64_xts_crypt_many_t)(const u32 *, int, void *, +- const void *, unsigned int, void *); +- +-static __always_inline int +-__speck64_xts_crypt(struct skcipher_request *req, speck64_crypt_one_t crypt_one, +- speck64_xts_crypt_many_t crypt_many) +-{ +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- const struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct skcipher_walk walk; +- __le64 tweak; +- int err; +- +- err = skcipher_walk_virt(&walk, req, true); +- +- crypto_speck64_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); +- +- while (walk.nbytes > 0) { +- unsigned int nbytes = walk.nbytes; +- u8 *dst = walk.dst.virt.addr; +- const u8 *src = walk.src.virt.addr; +- +- if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { +- unsigned int count; +- +- count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); +- kernel_neon_begin(); +- (*crypt_many)(ctx->main_key.round_keys, +- ctx->main_key.nrounds, +- dst, src, count, &tweak); +- kernel_neon_end(); +- dst += count; +- src += count; +- nbytes -= count; +- } +- +- /* Handle any remainder with generic code */ +- while (nbytes >= sizeof(tweak)) { +- *(__le64 *)dst = *(__le64 *)src ^ tweak; +- (*crypt_one)(&ctx->main_key, dst, dst); +- *(__le64 *)dst ^= tweak; +- tweak = cpu_to_le64((le64_to_cpu(tweak) << 1) ^ +- ((tweak & cpu_to_le64(1ULL << 63)) ? +- 0x1B : 0)); +- dst += sizeof(tweak); +- src += sizeof(tweak); +- nbytes -= sizeof(tweak); +- } +- err = skcipher_walk_done(&walk, nbytes); +- } +- +- return err; +-} +- +-static int speck64_xts_encrypt(struct skcipher_request *req) +-{ +- return __speck64_xts_crypt(req, crypto_speck64_encrypt, +- speck64_xts_encrypt_neon); +-} +- +-static int speck64_xts_decrypt(struct skcipher_request *req) +-{ +- return __speck64_xts_crypt(req, crypto_speck64_decrypt, +- speck64_xts_decrypt_neon); +-} +- +-static int speck64_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, +- unsigned int keylen) +-{ +- struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- int err; +- +- err = xts_verify_key(tfm, key, keylen); +- if (err) +- return err; +- +- keylen /= 2; +- +- err = crypto_speck64_setkey(&ctx->main_key, key, keylen); +- if (err) +- return err; +- +- return crypto_speck64_setkey(&ctx->tweak_key, key + keylen, keylen); +-} +- +-static struct skcipher_alg speck_algs[] = { +- { +- .base.cra_name = "xts(speck128)", +- .base.cra_driver_name = "xts-speck128-neon", +- .base.cra_priority = 300, +- .base.cra_blocksize = SPECK128_BLOCK_SIZE, +- .base.cra_ctxsize = sizeof(struct speck128_xts_tfm_ctx), +- .base.cra_alignmask = 7, +- .base.cra_module = THIS_MODULE, +- .min_keysize = 2 * SPECK128_128_KEY_SIZE, +- .max_keysize = 2 * SPECK128_256_KEY_SIZE, +- .ivsize = SPECK128_BLOCK_SIZE, +- .walksize = SPECK_NEON_CHUNK_SIZE, +- .setkey = speck128_xts_setkey, +- .encrypt = speck128_xts_encrypt, +- .decrypt = speck128_xts_decrypt, +- }, { +- .base.cra_name = "xts(speck64)", +- .base.cra_driver_name = "xts-speck64-neon", +- .base.cra_priority = 300, +- .base.cra_blocksize = SPECK64_BLOCK_SIZE, +- .base.cra_ctxsize = sizeof(struct speck64_xts_tfm_ctx), +- .base.cra_alignmask = 7, +- .base.cra_module = THIS_MODULE, +- .min_keysize = 2 * SPECK64_96_KEY_SIZE, +- .max_keysize = 2 * SPECK64_128_KEY_SIZE, +- .ivsize = SPECK64_BLOCK_SIZE, +- .walksize = SPECK_NEON_CHUNK_SIZE, +- .setkey = speck64_xts_setkey, +- .encrypt = speck64_xts_encrypt, +- .decrypt = speck64_xts_decrypt, +- } +-}; +- +-static int __init speck_neon_module_init(void) +-{ +- if (!(elf_hwcap & HWCAP_NEON)) +- return -ENODEV; +- return crypto_register_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); +-} +- +-static void __exit speck_neon_module_exit(void) +-{ +- crypto_unregister_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); +-} +- +-module_init(speck_neon_module_init); +-module_exit(speck_neon_module_exit); +- +-MODULE_DESCRIPTION("Speck block cipher (NEON-accelerated)"); +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Eric Biggers "); +-MODULE_ALIAS_CRYPTO("xts(speck128)"); +-MODULE_ALIAS_CRYPTO("xts-speck128-neon"); +-MODULE_ALIAS_CRYPTO("xts(speck64)"); +-MODULE_ALIAS_CRYPTO("xts-speck64-neon"); +diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +index d033da401c26..bc6c141d7372 100644 +--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi ++++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +@@ -335,7 +335,7 @@ + + sysmgr: sysmgr@ffd12000 { + compatible = "altr,sys-mgr", "syscon"; +- reg = <0xffd12000 0x1000>; ++ reg = <0xffd12000 0x228>; + }; + + /* Local timer */ +diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig +index e3fdb0fd6f70..d51944ff9f91 100644 +--- a/arch/arm64/crypto/Kconfig ++++ b/arch/arm64/crypto/Kconfig +@@ -119,10 +119,4 @@ config CRYPTO_AES_ARM64_BS + select CRYPTO_AES_ARM64 + select CRYPTO_SIMD + +-config CRYPTO_SPECK_NEON +- tristate "NEON accelerated Speck cipher algorithms" +- depends on KERNEL_MODE_NEON +- select CRYPTO_BLKCIPHER +- select CRYPTO_SPECK +- + endif +diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile +index bcafd016618e..7bc4bda6d9c6 100644 +--- a/arch/arm64/crypto/Makefile ++++ b/arch/arm64/crypto/Makefile +@@ -56,9 +56,6 @@ sha512-arm64-y := sha512-glue.o sha512-core.o + obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha20-neon.o + chacha20-neon-y := chacha20-neon-core.o chacha20-neon-glue.o + +-obj-$(CONFIG_CRYPTO_SPECK_NEON) += speck-neon.o +-speck-neon-y := speck-neon-core.o speck-neon-glue.o +- + obj-$(CONFIG_CRYPTO_AES_ARM64) += aes-arm64.o + aes-arm64-y := aes-cipher-core.o aes-cipher-glue.o + +diff --git a/arch/arm64/crypto/speck-neon-core.S b/arch/arm64/crypto/speck-neon-core.S +deleted file mode 100644 +index b14463438b09..000000000000 +--- a/arch/arm64/crypto/speck-neon-core.S ++++ /dev/null +@@ -1,352 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * ARM64 NEON-accelerated implementation of Speck128-XTS and Speck64-XTS +- * +- * Copyright (c) 2018 Google, Inc +- * +- * Author: Eric Biggers +- */ +- +-#include +- +- .text +- +- // arguments +- ROUND_KEYS .req x0 // const {u64,u32} *round_keys +- NROUNDS .req w1 // int nrounds +- NROUNDS_X .req x1 +- DST .req x2 // void *dst +- SRC .req x3 // const void *src +- NBYTES .req w4 // unsigned int nbytes +- TWEAK .req x5 // void *tweak +- +- // registers which hold the data being encrypted/decrypted +- // (underscores avoid a naming collision with ARM64 registers x0-x3) +- X_0 .req v0 +- Y_0 .req v1 +- X_1 .req v2 +- Y_1 .req v3 +- X_2 .req v4 +- Y_2 .req v5 +- X_3 .req v6 +- Y_3 .req v7 +- +- // the round key, duplicated in all lanes +- ROUND_KEY .req v8 +- +- // index vector for tbl-based 8-bit rotates +- ROTATE_TABLE .req v9 +- ROTATE_TABLE_Q .req q9 +- +- // temporary registers +- TMP0 .req v10 +- TMP1 .req v11 +- TMP2 .req v12 +- TMP3 .req v13 +- +- // multiplication table for updating XTS tweaks +- GFMUL_TABLE .req v14 +- GFMUL_TABLE_Q .req q14 +- +- // next XTS tweak value(s) +- TWEAKV_NEXT .req v15 +- +- // XTS tweaks for the blocks currently being encrypted/decrypted +- TWEAKV0 .req v16 +- TWEAKV1 .req v17 +- TWEAKV2 .req v18 +- TWEAKV3 .req v19 +- TWEAKV4 .req v20 +- TWEAKV5 .req v21 +- TWEAKV6 .req v22 +- TWEAKV7 .req v23 +- +- .align 4 +-.Lror64_8_table: +- .octa 0x080f0e0d0c0b0a090007060504030201 +-.Lror32_8_table: +- .octa 0x0c0f0e0d080b0a090407060500030201 +-.Lrol64_8_table: +- .octa 0x0e0d0c0b0a09080f0605040302010007 +-.Lrol32_8_table: +- .octa 0x0e0d0c0f0a09080b0605040702010003 +-.Lgf128mul_table: +- .octa 0x00000000000000870000000000000001 +-.Lgf64mul_table: +- .octa 0x0000000000000000000000002d361b00 +- +-/* +- * _speck_round_128bytes() - Speck encryption round on 128 bytes at a time +- * +- * Do one Speck encryption round on the 128 bytes (8 blocks for Speck128, 16 for +- * Speck64) stored in X0-X3 and Y0-Y3, using the round key stored in all lanes +- * of ROUND_KEY. 'n' is the lane size: 64 for Speck128, or 32 for Speck64. +- * 'lanes' is the lane specifier: "2d" for Speck128 or "4s" for Speck64. +- */ +-.macro _speck_round_128bytes n, lanes +- +- // x = ror(x, 8) +- tbl X_0.16b, {X_0.16b}, ROTATE_TABLE.16b +- tbl X_1.16b, {X_1.16b}, ROTATE_TABLE.16b +- tbl X_2.16b, {X_2.16b}, ROTATE_TABLE.16b +- tbl X_3.16b, {X_3.16b}, ROTATE_TABLE.16b +- +- // x += y +- add X_0.\lanes, X_0.\lanes, Y_0.\lanes +- add X_1.\lanes, X_1.\lanes, Y_1.\lanes +- add X_2.\lanes, X_2.\lanes, Y_2.\lanes +- add X_3.\lanes, X_3.\lanes, Y_3.\lanes +- +- // x ^= k +- eor X_0.16b, X_0.16b, ROUND_KEY.16b +- eor X_1.16b, X_1.16b, ROUND_KEY.16b +- eor X_2.16b, X_2.16b, ROUND_KEY.16b +- eor X_3.16b, X_3.16b, ROUND_KEY.16b +- +- // y = rol(y, 3) +- shl TMP0.\lanes, Y_0.\lanes, #3 +- shl TMP1.\lanes, Y_1.\lanes, #3 +- shl TMP2.\lanes, Y_2.\lanes, #3 +- shl TMP3.\lanes, Y_3.\lanes, #3 +- sri TMP0.\lanes, Y_0.\lanes, #(\n - 3) +- sri TMP1.\lanes, Y_1.\lanes, #(\n - 3) +- sri TMP2.\lanes, Y_2.\lanes, #(\n - 3) +- sri TMP3.\lanes, Y_3.\lanes, #(\n - 3) +- +- // y ^= x +- eor Y_0.16b, TMP0.16b, X_0.16b +- eor Y_1.16b, TMP1.16b, X_1.16b +- eor Y_2.16b, TMP2.16b, X_2.16b +- eor Y_3.16b, TMP3.16b, X_3.16b +-.endm +- +-/* +- * _speck_unround_128bytes() - Speck decryption round on 128 bytes at a time +- * +- * This is the inverse of _speck_round_128bytes(). +- */ +-.macro _speck_unround_128bytes n, lanes +- +- // y ^= x +- eor TMP0.16b, Y_0.16b, X_0.16b +- eor TMP1.16b, Y_1.16b, X_1.16b +- eor TMP2.16b, Y_2.16b, X_2.16b +- eor TMP3.16b, Y_3.16b, X_3.16b +- +- // y = ror(y, 3) +- ushr Y_0.\lanes, TMP0.\lanes, #3 +- ushr Y_1.\lanes, TMP1.\lanes, #3 +- ushr Y_2.\lanes, TMP2.\lanes, #3 +- ushr Y_3.\lanes, TMP3.\lanes, #3 +- sli Y_0.\lanes, TMP0.\lanes, #(\n - 3) +- sli Y_1.\lanes, TMP1.\lanes, #(\n - 3) +- sli Y_2.\lanes, TMP2.\lanes, #(\n - 3) +- sli Y_3.\lanes, TMP3.\lanes, #(\n - 3) +- +- // x ^= k +- eor X_0.16b, X_0.16b, ROUND_KEY.16b +- eor X_1.16b, X_1.16b, ROUND_KEY.16b +- eor X_2.16b, X_2.16b, ROUND_KEY.16b +- eor X_3.16b, X_3.16b, ROUND_KEY.16b +- +- // x -= y +- sub X_0.\lanes, X_0.\lanes, Y_0.\lanes +- sub X_1.\lanes, X_1.\lanes, Y_1.\lanes +- sub X_2.\lanes, X_2.\lanes, Y_2.\lanes +- sub X_3.\lanes, X_3.\lanes, Y_3.\lanes +- +- // x = rol(x, 8) +- tbl X_0.16b, {X_0.16b}, ROTATE_TABLE.16b +- tbl X_1.16b, {X_1.16b}, ROTATE_TABLE.16b +- tbl X_2.16b, {X_2.16b}, ROTATE_TABLE.16b +- tbl X_3.16b, {X_3.16b}, ROTATE_TABLE.16b +-.endm +- +-.macro _next_xts_tweak next, cur, tmp, n +-.if \n == 64 +- /* +- * Calculate the next tweak by multiplying the current one by x, +- * modulo p(x) = x^128 + x^7 + x^2 + x + 1. +- */ +- sshr \tmp\().2d, \cur\().2d, #63 +- and \tmp\().16b, \tmp\().16b, GFMUL_TABLE.16b +- shl \next\().2d, \cur\().2d, #1 +- ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8 +- eor \next\().16b, \next\().16b, \tmp\().16b +-.else +- /* +- * Calculate the next two tweaks by multiplying the current ones by x^2, +- * modulo p(x) = x^64 + x^4 + x^3 + x + 1. +- */ +- ushr \tmp\().2d, \cur\().2d, #62 +- shl \next\().2d, \cur\().2d, #2 +- tbl \tmp\().16b, {GFMUL_TABLE.16b}, \tmp\().16b +- eor \next\().16b, \next\().16b, \tmp\().16b +-.endif +-.endm +- +-/* +- * _speck_xts_crypt() - Speck-XTS encryption/decryption +- * +- * Encrypt or decrypt NBYTES bytes of data from the SRC buffer to the DST buffer +- * using Speck-XTS, specifically the variant with a block size of '2n' and round +- * count given by NROUNDS. The expanded round keys are given in ROUND_KEYS, and +- * the current XTS tweak value is given in TWEAK. It's assumed that NBYTES is a +- * nonzero multiple of 128. +- */ +-.macro _speck_xts_crypt n, lanes, decrypting +- +- /* +- * If decrypting, modify the ROUND_KEYS parameter to point to the last +- * round key rather than the first, since for decryption the round keys +- * are used in reverse order. +- */ +-.if \decrypting +- mov NROUNDS, NROUNDS /* zero the high 32 bits */ +-.if \n == 64 +- add ROUND_KEYS, ROUND_KEYS, NROUNDS_X, lsl #3 +- sub ROUND_KEYS, ROUND_KEYS, #8 +-.else +- add ROUND_KEYS, ROUND_KEYS, NROUNDS_X, lsl #2 +- sub ROUND_KEYS, ROUND_KEYS, #4 +-.endif +-.endif +- +- // Load the index vector for tbl-based 8-bit rotates +-.if \decrypting +- ldr ROTATE_TABLE_Q, .Lrol\n\()_8_table +-.else +- ldr ROTATE_TABLE_Q, .Lror\n\()_8_table +-.endif +- +- // One-time XTS preparation +-.if \n == 64 +- // Load first tweak +- ld1 {TWEAKV0.16b}, [TWEAK] +- +- // Load GF(2^128) multiplication table +- ldr GFMUL_TABLE_Q, .Lgf128mul_table +-.else +- // Load first tweak +- ld1 {TWEAKV0.8b}, [TWEAK] +- +- // Load GF(2^64) multiplication table +- ldr GFMUL_TABLE_Q, .Lgf64mul_table +- +- // Calculate second tweak, packing it together with the first +- ushr TMP0.2d, TWEAKV0.2d, #63 +- shl TMP1.2d, TWEAKV0.2d, #1 +- tbl TMP0.8b, {GFMUL_TABLE.16b}, TMP0.8b +- eor TMP0.8b, TMP0.8b, TMP1.8b +- mov TWEAKV0.d[1], TMP0.d[0] +-.endif +- +-.Lnext_128bytes_\@: +- +- // Calculate XTS tweaks for next 128 bytes +- _next_xts_tweak TWEAKV1, TWEAKV0, TMP0, \n +- _next_xts_tweak TWEAKV2, TWEAKV1, TMP0, \n +- _next_xts_tweak TWEAKV3, TWEAKV2, TMP0, \n +- _next_xts_tweak TWEAKV4, TWEAKV3, TMP0, \n +- _next_xts_tweak TWEAKV5, TWEAKV4, TMP0, \n +- _next_xts_tweak TWEAKV6, TWEAKV5, TMP0, \n +- _next_xts_tweak TWEAKV7, TWEAKV6, TMP0, \n +- _next_xts_tweak TWEAKV_NEXT, TWEAKV7, TMP0, \n +- +- // Load the next source blocks into {X,Y}[0-3] +- ld1 {X_0.16b-Y_1.16b}, [SRC], #64 +- ld1 {X_2.16b-Y_3.16b}, [SRC], #64 +- +- // XOR the source blocks with their XTS tweaks +- eor TMP0.16b, X_0.16b, TWEAKV0.16b +- eor Y_0.16b, Y_0.16b, TWEAKV1.16b +- eor TMP1.16b, X_1.16b, TWEAKV2.16b +- eor Y_1.16b, Y_1.16b, TWEAKV3.16b +- eor TMP2.16b, X_2.16b, TWEAKV4.16b +- eor Y_2.16b, Y_2.16b, TWEAKV5.16b +- eor TMP3.16b, X_3.16b, TWEAKV6.16b +- eor Y_3.16b, Y_3.16b, TWEAKV7.16b +- +- /* +- * De-interleave the 'x' and 'y' elements of each block, i.e. make it so +- * that the X[0-3] registers contain only the second halves of blocks, +- * and the Y[0-3] registers contain only the first halves of blocks. +- * (Speck uses the order (y, x) rather than the more intuitive (x, y).) +- */ +- uzp2 X_0.\lanes, TMP0.\lanes, Y_0.\lanes +- uzp1 Y_0.\lanes, TMP0.\lanes, Y_0.\lanes +- uzp2 X_1.\lanes, TMP1.\lanes, Y_1.\lanes +- uzp1 Y_1.\lanes, TMP1.\lanes, Y_1.\lanes +- uzp2 X_2.\lanes, TMP2.\lanes, Y_2.\lanes +- uzp1 Y_2.\lanes, TMP2.\lanes, Y_2.\lanes +- uzp2 X_3.\lanes, TMP3.\lanes, Y_3.\lanes +- uzp1 Y_3.\lanes, TMP3.\lanes, Y_3.\lanes +- +- // Do the cipher rounds +- mov x6, ROUND_KEYS +- mov w7, NROUNDS +-.Lnext_round_\@: +-.if \decrypting +- ld1r {ROUND_KEY.\lanes}, [x6] +- sub x6, x6, #( \n / 8 ) +- _speck_unround_128bytes \n, \lanes +-.else +- ld1r {ROUND_KEY.\lanes}, [x6], #( \n / 8 ) +- _speck_round_128bytes \n, \lanes +-.endif +- subs w7, w7, #1 +- bne .Lnext_round_\@ +- +- // Re-interleave the 'x' and 'y' elements of each block +- zip1 TMP0.\lanes, Y_0.\lanes, X_0.\lanes +- zip2 Y_0.\lanes, Y_0.\lanes, X_0.\lanes +- zip1 TMP1.\lanes, Y_1.\lanes, X_1.\lanes +- zip2 Y_1.\lanes, Y_1.\lanes, X_1.\lanes +- zip1 TMP2.\lanes, Y_2.\lanes, X_2.\lanes +- zip2 Y_2.\lanes, Y_2.\lanes, X_2.\lanes +- zip1 TMP3.\lanes, Y_3.\lanes, X_3.\lanes +- zip2 Y_3.\lanes, Y_3.\lanes, X_3.\lanes +- +- // XOR the encrypted/decrypted blocks with the tweaks calculated earlier +- eor X_0.16b, TMP0.16b, TWEAKV0.16b +- eor Y_0.16b, Y_0.16b, TWEAKV1.16b +- eor X_1.16b, TMP1.16b, TWEAKV2.16b +- eor Y_1.16b, Y_1.16b, TWEAKV3.16b +- eor X_2.16b, TMP2.16b, TWEAKV4.16b +- eor Y_2.16b, Y_2.16b, TWEAKV5.16b +- eor X_3.16b, TMP3.16b, TWEAKV6.16b +- eor Y_3.16b, Y_3.16b, TWEAKV7.16b +- mov TWEAKV0.16b, TWEAKV_NEXT.16b +- +- // Store the ciphertext in the destination buffer +- st1 {X_0.16b-Y_1.16b}, [DST], #64 +- st1 {X_2.16b-Y_3.16b}, [DST], #64 +- +- // Continue if there are more 128-byte chunks remaining +- subs NBYTES, NBYTES, #128 +- bne .Lnext_128bytes_\@ +- +- // Store the next tweak and return +-.if \n == 64 +- st1 {TWEAKV_NEXT.16b}, [TWEAK] +-.else +- st1 {TWEAKV_NEXT.8b}, [TWEAK] +-.endif +- ret +-.endm +- +-ENTRY(speck128_xts_encrypt_neon) +- _speck_xts_crypt n=64, lanes=2d, decrypting=0 +-ENDPROC(speck128_xts_encrypt_neon) +- +-ENTRY(speck128_xts_decrypt_neon) +- _speck_xts_crypt n=64, lanes=2d, decrypting=1 +-ENDPROC(speck128_xts_decrypt_neon) +- +-ENTRY(speck64_xts_encrypt_neon) +- _speck_xts_crypt n=32, lanes=4s, decrypting=0 +-ENDPROC(speck64_xts_encrypt_neon) +- +-ENTRY(speck64_xts_decrypt_neon) +- _speck_xts_crypt n=32, lanes=4s, decrypting=1 +-ENDPROC(speck64_xts_decrypt_neon) +diff --git a/arch/arm64/crypto/speck-neon-glue.c b/arch/arm64/crypto/speck-neon-glue.c +deleted file mode 100644 +index 6e233aeb4ff4..000000000000 +--- a/arch/arm64/crypto/speck-neon-glue.c ++++ /dev/null +@@ -1,282 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * NEON-accelerated implementation of Speck128-XTS and Speck64-XTS +- * (64-bit version; based on the 32-bit version) +- * +- * Copyright (c) 2018 Google, Inc +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* The assembly functions only handle multiples of 128 bytes */ +-#define SPECK_NEON_CHUNK_SIZE 128 +- +-/* Speck128 */ +- +-struct speck128_xts_tfm_ctx { +- struct speck128_tfm_ctx main_key; +- struct speck128_tfm_ctx tweak_key; +-}; +- +-asmlinkage void speck128_xts_encrypt_neon(const u64 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-asmlinkage void speck128_xts_decrypt_neon(const u64 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-typedef void (*speck128_crypt_one_t)(const struct speck128_tfm_ctx *, +- u8 *, const u8 *); +-typedef void (*speck128_xts_crypt_many_t)(const u64 *, int, void *, +- const void *, unsigned int, void *); +- +-static __always_inline int +-__speck128_xts_crypt(struct skcipher_request *req, +- speck128_crypt_one_t crypt_one, +- speck128_xts_crypt_many_t crypt_many) +-{ +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- const struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct skcipher_walk walk; +- le128 tweak; +- int err; +- +- err = skcipher_walk_virt(&walk, req, true); +- +- crypto_speck128_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); +- +- while (walk.nbytes > 0) { +- unsigned int nbytes = walk.nbytes; +- u8 *dst = walk.dst.virt.addr; +- const u8 *src = walk.src.virt.addr; +- +- if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { +- unsigned int count; +- +- count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); +- kernel_neon_begin(); +- (*crypt_many)(ctx->main_key.round_keys, +- ctx->main_key.nrounds, +- dst, src, count, &tweak); +- kernel_neon_end(); +- dst += count; +- src += count; +- nbytes -= count; +- } +- +- /* Handle any remainder with generic code */ +- while (nbytes >= sizeof(tweak)) { +- le128_xor((le128 *)dst, (const le128 *)src, &tweak); +- (*crypt_one)(&ctx->main_key, dst, dst); +- le128_xor((le128 *)dst, (const le128 *)dst, &tweak); +- gf128mul_x_ble(&tweak, &tweak); +- +- dst += sizeof(tweak); +- src += sizeof(tweak); +- nbytes -= sizeof(tweak); +- } +- err = skcipher_walk_done(&walk, nbytes); +- } +- +- return err; +-} +- +-static int speck128_xts_encrypt(struct skcipher_request *req) +-{ +- return __speck128_xts_crypt(req, crypto_speck128_encrypt, +- speck128_xts_encrypt_neon); +-} +- +-static int speck128_xts_decrypt(struct skcipher_request *req) +-{ +- return __speck128_xts_crypt(req, crypto_speck128_decrypt, +- speck128_xts_decrypt_neon); +-} +- +-static int speck128_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, +- unsigned int keylen) +-{ +- struct speck128_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- int err; +- +- err = xts_verify_key(tfm, key, keylen); +- if (err) +- return err; +- +- keylen /= 2; +- +- err = crypto_speck128_setkey(&ctx->main_key, key, keylen); +- if (err) +- return err; +- +- return crypto_speck128_setkey(&ctx->tweak_key, key + keylen, keylen); +-} +- +-/* Speck64 */ +- +-struct speck64_xts_tfm_ctx { +- struct speck64_tfm_ctx main_key; +- struct speck64_tfm_ctx tweak_key; +-}; +- +-asmlinkage void speck64_xts_encrypt_neon(const u32 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-asmlinkage void speck64_xts_decrypt_neon(const u32 *round_keys, int nrounds, +- void *dst, const void *src, +- unsigned int nbytes, void *tweak); +- +-typedef void (*speck64_crypt_one_t)(const struct speck64_tfm_ctx *, +- u8 *, const u8 *); +-typedef void (*speck64_xts_crypt_many_t)(const u32 *, int, void *, +- const void *, unsigned int, void *); +- +-static __always_inline int +-__speck64_xts_crypt(struct skcipher_request *req, speck64_crypt_one_t crypt_one, +- speck64_xts_crypt_many_t crypt_many) +-{ +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- const struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct skcipher_walk walk; +- __le64 tweak; +- int err; +- +- err = skcipher_walk_virt(&walk, req, true); +- +- crypto_speck64_encrypt(&ctx->tweak_key, (u8 *)&tweak, walk.iv); +- +- while (walk.nbytes > 0) { +- unsigned int nbytes = walk.nbytes; +- u8 *dst = walk.dst.virt.addr; +- const u8 *src = walk.src.virt.addr; +- +- if (nbytes >= SPECK_NEON_CHUNK_SIZE && may_use_simd()) { +- unsigned int count; +- +- count = round_down(nbytes, SPECK_NEON_CHUNK_SIZE); +- kernel_neon_begin(); +- (*crypt_many)(ctx->main_key.round_keys, +- ctx->main_key.nrounds, +- dst, src, count, &tweak); +- kernel_neon_end(); +- dst += count; +- src += count; +- nbytes -= count; +- } +- +- /* Handle any remainder with generic code */ +- while (nbytes >= sizeof(tweak)) { +- *(__le64 *)dst = *(__le64 *)src ^ tweak; +- (*crypt_one)(&ctx->main_key, dst, dst); +- *(__le64 *)dst ^= tweak; +- tweak = cpu_to_le64((le64_to_cpu(tweak) << 1) ^ +- ((tweak & cpu_to_le64(1ULL << 63)) ? +- 0x1B : 0)); +- dst += sizeof(tweak); +- src += sizeof(tweak); +- nbytes -= sizeof(tweak); +- } +- err = skcipher_walk_done(&walk, nbytes); +- } +- +- return err; +-} +- +-static int speck64_xts_encrypt(struct skcipher_request *req) +-{ +- return __speck64_xts_crypt(req, crypto_speck64_encrypt, +- speck64_xts_encrypt_neon); +-} +- +-static int speck64_xts_decrypt(struct skcipher_request *req) +-{ +- return __speck64_xts_crypt(req, crypto_speck64_decrypt, +- speck64_xts_decrypt_neon); +-} +- +-static int speck64_xts_setkey(struct crypto_skcipher *tfm, const u8 *key, +- unsigned int keylen) +-{ +- struct speck64_xts_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); +- int err; +- +- err = xts_verify_key(tfm, key, keylen); +- if (err) +- return err; +- +- keylen /= 2; +- +- err = crypto_speck64_setkey(&ctx->main_key, key, keylen); +- if (err) +- return err; +- +- return crypto_speck64_setkey(&ctx->tweak_key, key + keylen, keylen); +-} +- +-static struct skcipher_alg speck_algs[] = { +- { +- .base.cra_name = "xts(speck128)", +- .base.cra_driver_name = "xts-speck128-neon", +- .base.cra_priority = 300, +- .base.cra_blocksize = SPECK128_BLOCK_SIZE, +- .base.cra_ctxsize = sizeof(struct speck128_xts_tfm_ctx), +- .base.cra_alignmask = 7, +- .base.cra_module = THIS_MODULE, +- .min_keysize = 2 * SPECK128_128_KEY_SIZE, +- .max_keysize = 2 * SPECK128_256_KEY_SIZE, +- .ivsize = SPECK128_BLOCK_SIZE, +- .walksize = SPECK_NEON_CHUNK_SIZE, +- .setkey = speck128_xts_setkey, +- .encrypt = speck128_xts_encrypt, +- .decrypt = speck128_xts_decrypt, +- }, { +- .base.cra_name = "xts(speck64)", +- .base.cra_driver_name = "xts-speck64-neon", +- .base.cra_priority = 300, +- .base.cra_blocksize = SPECK64_BLOCK_SIZE, +- .base.cra_ctxsize = sizeof(struct speck64_xts_tfm_ctx), +- .base.cra_alignmask = 7, +- .base.cra_module = THIS_MODULE, +- .min_keysize = 2 * SPECK64_96_KEY_SIZE, +- .max_keysize = 2 * SPECK64_128_KEY_SIZE, +- .ivsize = SPECK64_BLOCK_SIZE, +- .walksize = SPECK_NEON_CHUNK_SIZE, +- .setkey = speck64_xts_setkey, +- .encrypt = speck64_xts_encrypt, +- .decrypt = speck64_xts_decrypt, +- } +-}; +- +-static int __init speck_neon_module_init(void) +-{ +- if (!(elf_hwcap & HWCAP_ASIMD)) +- return -ENODEV; +- return crypto_register_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); +-} +- +-static void __exit speck_neon_module_exit(void) +-{ +- crypto_unregister_skciphers(speck_algs, ARRAY_SIZE(speck_algs)); +-} +- +-module_init(speck_neon_module_init); +-module_exit(speck_neon_module_exit); +- +-MODULE_DESCRIPTION("Speck block cipher (NEON-accelerated)"); +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Eric Biggers "); +-MODULE_ALIAS_CRYPTO("xts(speck128)"); +-MODULE_ALIAS_CRYPTO("xts-speck128-neon"); +-MODULE_ALIAS_CRYPTO("xts(speck64)"); +-MODULE_ALIAS_CRYPTO("xts-speck64-neon"); +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index e238b7932096..93f69d82225d 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -848,15 +848,29 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus + } + + static bool has_cache_idc(const struct arm64_cpu_capabilities *entry, +- int __unused) ++ int scope) + { +- return read_sanitised_ftr_reg(SYS_CTR_EL0) & BIT(CTR_IDC_SHIFT); ++ u64 ctr; ++ ++ if (scope == SCOPE_SYSTEM) ++ ctr = arm64_ftr_reg_ctrel0.sys_val; ++ else ++ ctr = read_cpuid_cachetype(); ++ ++ return ctr & BIT(CTR_IDC_SHIFT); + } + + static bool has_cache_dic(const struct arm64_cpu_capabilities *entry, +- int __unused) ++ int scope) + { +- return read_sanitised_ftr_reg(SYS_CTR_EL0) & BIT(CTR_DIC_SHIFT); ++ u64 ctr; ++ ++ if (scope == SCOPE_SYSTEM) ++ ctr = arm64_ftr_reg_ctrel0.sys_val; ++ else ++ ctr = read_cpuid_cachetype(); ++ ++ return ctr & BIT(CTR_DIC_SHIFT); + } + + #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index 09dbea221a27..8556876c9109 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -589,7 +589,7 @@ el1_undef: + inherit_daif pstate=x23, tmp=x2 + mov x0, sp + bl do_undefinstr +- ASM_BUG() ++ kernel_exit 1 + el1_dbg: + /* + * Debug exception handling +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c +index 039e9ff379cc..b9da093e0341 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -310,10 +310,12 @@ static int call_undef_hook(struct pt_regs *regs) + int (*fn)(struct pt_regs *regs, u32 instr) = NULL; + void __user *pc = (void __user *)instruction_pointer(regs); + +- if (!user_mode(regs)) +- return 1; +- +- if (compat_thumb_mode(regs)) { ++ if (!user_mode(regs)) { ++ __le32 instr_le; ++ if (probe_kernel_address((__force __le32 *)pc, instr_le)) ++ goto exit; ++ instr = le32_to_cpu(instr_le); ++ } else if (compat_thumb_mode(regs)) { + /* 16-bit Thumb instruction */ + __le16 instr_le; + if (get_user(instr_le, (__le16 __user *)pc)) +@@ -407,6 +409,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) + return; + + force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc); ++ BUG_ON(!user_mode(regs)); + } + + void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused) +diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile +index 68755fd70dcf..5df2d611b77d 100644 +--- a/arch/arm64/lib/Makefile ++++ b/arch/arm64/lib/Makefile +@@ -12,7 +12,7 @@ lib-y := clear_user.o delay.o copy_from_user.o \ + # when supported by the CPU. Result and argument registers are handled + # correctly, based on the function prototype. + lib-$(CONFIG_ARM64_LSE_ATOMICS) += atomic_ll_sc.o +-CFLAGS_atomic_ll_sc.o := -fcall-used-x0 -ffixed-x1 -ffixed-x2 \ ++CFLAGS_atomic_ll_sc.o := -ffixed-x1 -ffixed-x2 \ + -ffixed-x3 -ffixed-x4 -ffixed-x5 -ffixed-x6 \ + -ffixed-x7 -fcall-saved-x8 -fcall-saved-x9 \ + -fcall-saved-x10 -fcall-saved-x11 -fcall-saved-x12 \ +diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig +index 1d5483f6e457..93a3c3c0238c 100644 +--- a/arch/m68k/configs/amiga_defconfig ++++ b/arch/m68k/configs/amiga_defconfig +@@ -657,7 +657,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig +index 52a0af127951..e3d0efd6397d 100644 +--- a/arch/m68k/configs/apollo_defconfig ++++ b/arch/m68k/configs/apollo_defconfig +@@ -614,7 +614,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig +index b3103e51268a..75ac0c76e884 100644 +--- a/arch/m68k/configs/atari_defconfig ++++ b/arch/m68k/configs/atari_defconfig +@@ -635,7 +635,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig +index fb7d651a4cab..c6e492700188 100644 +--- a/arch/m68k/configs/bvme6000_defconfig ++++ b/arch/m68k/configs/bvme6000_defconfig +@@ -606,7 +606,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig +index 6b37f5537c39..b00d1c477432 100644 +--- a/arch/m68k/configs/hp300_defconfig ++++ b/arch/m68k/configs/hp300_defconfig +@@ -616,7 +616,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig +index c717bf879449..85cac3770d89 100644 +--- a/arch/m68k/configs/mac_defconfig ++++ b/arch/m68k/configs/mac_defconfig +@@ -638,7 +638,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig +index 226c994ce794..b3a5d1e99d27 100644 +--- a/arch/m68k/configs/multi_defconfig ++++ b/arch/m68k/configs/multi_defconfig +@@ -720,7 +720,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig +index b383327fd77a..0ca22608453f 100644 +--- a/arch/m68k/configs/mvme147_defconfig ++++ b/arch/m68k/configs/mvme147_defconfig +@@ -606,7 +606,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig +index 9783d3deb9e9..8e3d10d12d9c 100644 +--- a/arch/m68k/configs/mvme16x_defconfig ++++ b/arch/m68k/configs/mvme16x_defconfig +@@ -606,7 +606,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig +index a35d10ee10cb..ff7e653ec7fa 100644 +--- a/arch/m68k/configs/q40_defconfig ++++ b/arch/m68k/configs/q40_defconfig +@@ -629,7 +629,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig +index 573bf922d448..612cf46f6d0c 100644 +--- a/arch/m68k/configs/sun3_defconfig ++++ b/arch/m68k/configs/sun3_defconfig +@@ -607,7 +607,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig +index efb27a7fcc55..a6a7bb6dc3fd 100644 +--- a/arch/m68k/configs/sun3x_defconfig ++++ b/arch/m68k/configs/sun3x_defconfig +@@ -608,7 +608,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_LZO=m +diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c +index 75108ec669eb..6c79e8a16a26 100644 +--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c +@@ -67,7 +67,7 @@ void (*cvmx_override_pko_queue_priority) (int pko_port, + void (*cvmx_override_ipd_port_setup) (int ipd_port); + + /* Port count per interface */ +-static int interface_port_count[5]; ++static int interface_port_count[9]; + + /** + * Return the number of interfaces the chip has. Each interface +diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h +index 49d6046ca1d0..c373eb605040 100644 +--- a/arch/mips/include/asm/processor.h ++++ b/arch/mips/include/asm/processor.h +@@ -81,7 +81,7 @@ extern unsigned int vced_count, vcei_count; + + #endif + +-#define VDSO_RANDOMIZE_SIZE (TASK_IS_32BIT_ADDR ? SZ_1M : SZ_256M) ++#define VDSO_RANDOMIZE_SIZE (TASK_IS_32BIT_ADDR ? SZ_1M : SZ_64M) + + extern unsigned long mips_stack_top(void); + #define STACK_TOP mips_stack_top() +diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S +index 242c5ab65611..d2f92273fe37 100644 +--- a/arch/parisc/kernel/entry.S ++++ b/arch/parisc/kernel/entry.S +@@ -186,7 +186,7 @@ + bv,n 0(%r3) + nop + .word 0 /* checksum (will be patched) */ +- .word PA(os_hpmc) /* address of handler */ ++ .word 0 /* address of handler */ + .word 0 /* length of handler */ + .endm + +diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S +index 781c3b9a3e46..fde654115564 100644 +--- a/arch/parisc/kernel/hpmc.S ++++ b/arch/parisc/kernel/hpmc.S +@@ -85,7 +85,7 @@ END(hpmc_pim_data) + + .import intr_save, code + .align 16 +-ENTRY_CFI(os_hpmc) ++ENTRY(os_hpmc) + .os_hpmc: + + /* +@@ -302,7 +302,6 @@ os_hpmc_6: + b . + nop + .align 16 /* make function length multiple of 16 bytes */ +-ENDPROC_CFI(os_hpmc) + .os_hpmc_end: + + +diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c +index 68f10f87073d..abeb5321a83f 100644 +--- a/arch/parisc/kernel/traps.c ++++ b/arch/parisc/kernel/traps.c +@@ -802,7 +802,8 @@ void __init initialize_ivt(const void *iva) + * the Length/4 words starting at Address is zero. + */ + +- /* Compute Checksum for HPMC handler */ ++ /* Setup IVA and compute checksum for HPMC handler */ ++ ivap[6] = (u32)__pa(os_hpmc); + length = os_hpmc_size; + ivap[7] = length; + +diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c +index 74842d28a7a1..aae9b0d71c1e 100644 +--- a/arch/parisc/mm/init.c ++++ b/arch/parisc/mm/init.c +@@ -494,12 +494,8 @@ static void __init map_pages(unsigned long start_vaddr, + pte = pte_mkhuge(pte); + } + +- if (address >= end_paddr) { +- if (force) +- break; +- else +- pte_val(pte) = 0; +- } ++ if (address >= end_paddr) ++ break; + + set_pte(pg_table, pte); + +diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h +index fad8ddd697ac..0abf2e7fd222 100644 +--- a/arch/powerpc/include/asm/mpic.h ++++ b/arch/powerpc/include/asm/mpic.h +@@ -393,7 +393,14 @@ extern struct bus_type mpic_subsys; + #define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ + + /* Get the version of primary MPIC */ ++#ifdef CONFIG_MPIC + extern u32 fsl_mpic_primary_get_version(void); ++#else ++static inline u32 fsl_mpic_primary_get_version(void) ++{ ++ return 0; ++} ++#endif + + /* Allocate the controller structure and setup the linux irq descs + * for the range if interrupts passed in. No HW initialization is +diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c +index 3497c8329c1d..3022d67f0c48 100644 +--- a/arch/powerpc/kernel/mce_power.c ++++ b/arch/powerpc/kernel/mce_power.c +@@ -89,6 +89,13 @@ static void flush_and_reload_slb(void) + + static void flush_erat(void) + { ++#ifdef CONFIG_PPC_BOOK3S_64 ++ if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { ++ flush_and_reload_slb(); ++ return; ++ } ++#endif ++ /* PPC_INVALIDATE_ERAT can only be used on ISA v3 and newer */ + asm volatile(PPC_INVALIDATE_ERAT : : :"memory"); + } + +diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c +index 77371c9ef3d8..2d861a36662e 100644 +--- a/arch/powerpc/kernel/module.c ++++ b/arch/powerpc/kernel/module.c +@@ -74,6 +74,14 @@ int module_finalize(const Elf_Ehdr *hdr, + (void *)sect->sh_addr + sect->sh_size); + #endif /* CONFIG_PPC64 */ + ++#ifdef PPC64_ELF_ABI_v1 ++ sect = find_section(hdr, sechdrs, ".opd"); ++ if (sect != NULL) { ++ me->arch.start_opd = sect->sh_addr; ++ me->arch.end_opd = sect->sh_addr + sect->sh_size; ++ } ++#endif /* PPC64_ELF_ABI_v1 */ ++ + #ifdef CONFIG_PPC_BARRIER_NOSPEC + sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); + if (sect != NULL) +diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c +index b8d61e019d06..2c53de9f3b6a 100644 +--- a/arch/powerpc/kernel/module_64.c ++++ b/arch/powerpc/kernel/module_64.c +@@ -360,11 +360,6 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr, + else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) + dedotify_versions((void *)hdr + sechdrs[i].sh_offset, + sechdrs[i].sh_size); +- else if (!strcmp(secstrings + sechdrs[i].sh_name, ".opd")) { +- me->arch.start_opd = sechdrs[i].sh_addr; +- me->arch.end_opd = sechdrs[i].sh_addr + +- sechdrs[i].sh_size; +- } + + /* We don't handle .init for the moment: rename to _init */ + while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init"))) +diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c +index 6a501b25dd85..faf00222b324 100644 +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -243,13 +243,19 @@ static void cpu_ready_for_interrupts(void) + } + + /* +- * Fixup HFSCR:TM based on CPU features. The bit is set by our +- * early asm init because at that point we haven't updated our +- * CPU features from firmware and device-tree. Here we have, +- * so let's do it. ++ * Set HFSCR:TM based on CPU features: ++ * In the special case of TM no suspend (P9N DD2.1), Linux is ++ * told TM is off via the dt-ftrs but told to (partially) use ++ * it via OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED. So HFSCR[TM] ++ * will be off from dt-ftrs but we need to turn it on for the ++ * no suspend case. + */ +- if (cpu_has_feature(CPU_FTR_HVMODE) && !cpu_has_feature(CPU_FTR_TM_COMP)) +- mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); ++ if (cpu_has_feature(CPU_FTR_HVMODE)) { ++ if (cpu_has_feature(CPU_FTR_TM_COMP)) ++ mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) | HFSCR_TM); ++ else ++ mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); ++ } + + /* Set IR and DR in PACA MSR */ + get_paca()->kernel_msr = MSR_KERNEL; +diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c +index 729f02df8290..aaa28fd918fe 100644 +--- a/arch/powerpc/mm/hash_native_64.c ++++ b/arch/powerpc/mm/hash_native_64.c +@@ -115,6 +115,8 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is) + tlbiel_hash_set_isa300(0, is, 0, 2, 1); + + asm volatile("ptesync": : :"memory"); ++ ++ asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); + } + + void hash__tlbiel_all(unsigned int action) +@@ -140,8 +142,6 @@ void hash__tlbiel_all(unsigned int action) + tlbiel_all_isa206(POWER7_TLB_SETS, is); + else + WARN(1, "%s called on pre-POWER7 CPU\n", __func__); +- +- asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); + } + + static inline unsigned long ___tlbie(unsigned long vpn, int psize, +diff --git a/arch/s390/defconfig b/arch/s390/defconfig +index f40600eb1762..5134c71a4937 100644 +--- a/arch/s390/defconfig ++++ b/arch/s390/defconfig +@@ -221,7 +221,6 @@ CONFIG_CRYPTO_SALSA20=m + CONFIG_CRYPTO_SEED=m + CONFIG_CRYPTO_SERPENT=m + CONFIG_CRYPTO_SM4=m +-CONFIG_CRYPTO_SPECK=m + CONFIG_CRYPTO_TEA=m + CONFIG_CRYPTO_TWOFISH=m + CONFIG_CRYPTO_DEFLATE=m +diff --git a/arch/s390/kernel/sthyi.c b/arch/s390/kernel/sthyi.c +index 0859cde36f75..888cc2f166db 100644 +--- a/arch/s390/kernel/sthyi.c ++++ b/arch/s390/kernel/sthyi.c +@@ -183,17 +183,19 @@ static void fill_hdr(struct sthyi_sctns *sctns) + static void fill_stsi_mac(struct sthyi_sctns *sctns, + struct sysinfo_1_1_1 *sysinfo) + { ++ sclp_ocf_cpc_name_copy(sctns->mac.infmname); ++ if (*(u64 *)sctns->mac.infmname != 0) ++ sctns->mac.infmval1 |= MAC_NAME_VLD; ++ + if (stsi(sysinfo, 1, 1, 1)) + return; + +- sclp_ocf_cpc_name_copy(sctns->mac.infmname); +- + memcpy(sctns->mac.infmtype, sysinfo->type, sizeof(sctns->mac.infmtype)); + memcpy(sctns->mac.infmmanu, sysinfo->manufacturer, sizeof(sctns->mac.infmmanu)); + memcpy(sctns->mac.infmpman, sysinfo->plant, sizeof(sctns->mac.infmpman)); + memcpy(sctns->mac.infmseq, sysinfo->sequence, sizeof(sctns->mac.infmseq)); + +- sctns->mac.infmval1 |= MAC_ID_VLD | MAC_NAME_VLD; ++ sctns->mac.infmval1 |= MAC_ID_VLD; + } + + static void fill_stsi_par(struct sthyi_sctns *sctns, +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 1458b1700fc7..8b4c5e001157 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -738,6 +738,7 @@ efi_main(struct efi_config *c, struct boot_params *boot_params) + struct desc_struct *desc; + void *handle; + efi_system_table_t *_table; ++ unsigned long cmdline_paddr; + + efi_early = c; + +@@ -755,6 +756,15 @@ efi_main(struct efi_config *c, struct boot_params *boot_params) + else + setup_boot_services32(efi_early); + ++ /* ++ * make_boot_params() may have been called before efi_main(), in which ++ * case this is the second time we parse the cmdline. This is ok, ++ * parsing the cmdline multiple times does not have side-effects. ++ */ ++ cmdline_paddr = ((u64)hdr->cmd_line_ptr | ++ ((u64)boot_params->ext_cmd_line_ptr << 32)); ++ efi_parse_options((char *)cmdline_paddr); ++ + /* + * If the boot loader gave us a value for secure_boot then we use that, + * otherwise we ask the BIOS. +diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c +index d4e6cd4577e5..bf0e82400358 100644 +--- a/arch/x86/boot/tools/build.c ++++ b/arch/x86/boot/tools/build.c +@@ -391,6 +391,13 @@ int main(int argc, char ** argv) + die("Unable to mmap '%s': %m", argv[2]); + /* Number of 16-byte paragraphs, including space for a 4-byte CRC */ + sys_size = (sz + 15 + 4) / 16; ++#ifdef CONFIG_EFI_STUB ++ /* ++ * COFF requires minimum 32-byte alignment of sections, and ++ * adding a signature is problematic without that alignment. ++ */ ++ sys_size = (sys_size + 1) & ~1; ++#endif + + /* Patch the setup code with the appropriate size parameters */ + buf[0x1f1] = setup_sectors-1; +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index acbe7e8336d8..e4b78f962874 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -817,7 +817,7 @@ static int gcmaes_crypt_by_sg(bool enc, struct aead_request *req, + /* Linearize assoc, if not already linear */ + if (req->src->length >= assoclen && req->src->length && + (!PageHighMem(sg_page(req->src)) || +- req->src->offset + req->src->length < PAGE_SIZE)) { ++ req->src->offset + req->src->length <= PAGE_SIZE)) { + scatterwalk_start(&assoc_sg_walk, req->src); + assoc = scatterwalk_map(&assoc_sg_walk); + } else { +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 09b2e3e2cf1b..1c09a0d1771f 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -177,6 +177,7 @@ enum { + + #define DR6_BD (1 << 13) + #define DR6_BS (1 << 14) ++#define DR6_BT (1 << 15) + #define DR6_RTM (1 << 16) + #define DR6_FIXED_1 0xfffe0ff0 + #define DR6_INIT 0xffff0ff0 +diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h +index 58ce5288878e..0e2130d8d6b1 100644 +--- a/arch/x86/include/asm/tlbflush.h ++++ b/arch/x86/include/asm/tlbflush.h +@@ -469,6 +469,12 @@ static inline void __native_flush_tlb_one_user(unsigned long addr) + */ + static inline void __flush_tlb_all(void) + { ++ /* ++ * This is to catch users with enabled preemption and the PGE feature ++ * and don't trigger the warning in __native_flush_tlb(). ++ */ ++ VM_WARN_ON_ONCE(preemptible()); ++ + if (boot_cpu_has(X86_FEATURE_PGE)) { + __flush_tlb_global(); + } else { +diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c +index 33399426793e..cc8258a5378b 100644 +--- a/arch/x86/kernel/check.c ++++ b/arch/x86/kernel/check.c +@@ -31,6 +31,11 @@ static __init int set_corruption_check(char *arg) + ssize_t ret; + unsigned long val; + ++ if (!arg) { ++ pr_err("memory_corruption_check config string not provided\n"); ++ return -EINVAL; ++ } ++ + ret = kstrtoul(arg, 10, &val); + if (ret) + return ret; +@@ -45,6 +50,11 @@ static __init int set_corruption_check_period(char *arg) + ssize_t ret; + unsigned long val; + ++ if (!arg) { ++ pr_err("memory_corruption_check_period config string not provided\n"); ++ return -EINVAL; ++ } ++ + ret = kstrtoul(arg, 10, &val); + if (ret) + return ret; +@@ -59,6 +69,11 @@ static __init int set_corruption_check_size(char *arg) + char *end; + unsigned size; + ++ if (!arg) { ++ pr_err("memory_corruption_check_size config string not provided\n"); ++ return -EINVAL; ++ } ++ + size = memparse(arg, &end); + + if (*end == '\0') +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index 40bdaea97fe7..53eb14a65610 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -35,12 +35,10 @@ static void __init spectre_v2_select_mitigation(void); + static void __init ssb_select_mitigation(void); + static void __init l1tf_select_mitigation(void); + +-/* +- * Our boot-time value of the SPEC_CTRL MSR. We read it once so that any +- * writes to SPEC_CTRL contain whatever reserved bits have been set. +- */ +-u64 __ro_after_init x86_spec_ctrl_base; ++/* The base value of the SPEC_CTRL MSR that always has to be preserved. */ ++u64 x86_spec_ctrl_base; + EXPORT_SYMBOL_GPL(x86_spec_ctrl_base); ++static DEFINE_MUTEX(spec_ctrl_mutex); + + /* + * The vendor and possibly platform specific bits which can be modified in +@@ -325,6 +323,46 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) + return cmd; + } + ++static bool stibp_needed(void) ++{ ++ if (spectre_v2_enabled == SPECTRE_V2_NONE) ++ return false; ++ ++ if (!boot_cpu_has(X86_FEATURE_STIBP)) ++ return false; ++ ++ return true; ++} ++ ++static void update_stibp_msr(void *info) ++{ ++ wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base); ++} ++ ++void arch_smt_update(void) ++{ ++ u64 mask; ++ ++ if (!stibp_needed()) ++ return; ++ ++ mutex_lock(&spec_ctrl_mutex); ++ mask = x86_spec_ctrl_base; ++ if (cpu_smt_control == CPU_SMT_ENABLED) ++ mask |= SPEC_CTRL_STIBP; ++ else ++ mask &= ~SPEC_CTRL_STIBP; ++ ++ if (mask != x86_spec_ctrl_base) { ++ pr_info("Spectre v2 cross-process SMT mitigation: %s STIBP\n", ++ cpu_smt_control == CPU_SMT_ENABLED ? ++ "Enabling" : "Disabling"); ++ x86_spec_ctrl_base = mask; ++ on_each_cpu(update_stibp_msr, NULL, 1); ++ } ++ mutex_unlock(&spec_ctrl_mutex); ++} ++ + static void __init spectre_v2_select_mitigation(void) + { + enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); +@@ -424,6 +462,9 @@ specv2_set_mode: + setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW); + pr_info("Enabling Restricted Speculation for firmware calls\n"); + } ++ ++ /* Enable STIBP if appropriate */ ++ arch_smt_update(); + } + + #undef pr_fmt +@@ -814,6 +855,8 @@ static ssize_t l1tf_show_state(char *buf) + static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, + char *buf, unsigned int bug) + { ++ int ret; ++ + if (!boot_cpu_has_bug(bug)) + return sprintf(buf, "Not affected\n"); + +@@ -831,10 +874,12 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr + return sprintf(buf, "Mitigation: __user pointer sanitization\n"); + + case X86_BUG_SPECTRE_V2: +- return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], ++ ret = sprintf(buf, "%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], + boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "", + boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "", ++ (x86_spec_ctrl_base & SPEC_CTRL_STIBP) ? ", STIBP" : "", + spectre_v2_module_string()); ++ return ret; + + case X86_BUG_SPEC_STORE_BYPASS: + return sprintf(buf, "%s\n", ssb_strings[ssb_mode]); +diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +index b140c68bc14b..643670fb8943 100644 +--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c ++++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +@@ -2805,6 +2805,13 @@ static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf) + { + if (rdt_resources_all[RDT_RESOURCE_L3DATA].alloc_enabled) + seq_puts(seq, ",cdp"); ++ ++ if (rdt_resources_all[RDT_RESOURCE_L2DATA].alloc_enabled) ++ seq_puts(seq, ",cdpl2"); ++ ++ if (is_mba_sc(&rdt_resources_all[RDT_RESOURCE_MBA])) ++ seq_puts(seq, ",mba_MBps"); ++ + return 0; + } + +diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c +index eaf02f2e7300..40b16b270656 100644 +--- a/arch/x86/kernel/kprobes/opt.c ++++ b/arch/x86/kernel/kprobes/opt.c +@@ -179,7 +179,7 @@ optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) + opt_pre_handler(&op->kp, regs); + __this_cpu_write(current_kprobe, NULL); + } +- preempt_enable_no_resched(); ++ preempt_enable(); + } + NOKPROBE_SYMBOL(optimized_callback); + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index e665aa7167cf..9f3def7baa6d 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -3294,10 +3294,13 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned long *exit + } + } else { + if (vmcs12->exception_bitmap & (1u << nr)) { +- if (nr == DB_VECTOR) ++ if (nr == DB_VECTOR) { + *exit_qual = vcpu->arch.dr6; +- else ++ *exit_qual &= ~(DR6_FIXED_1 | DR6_BT); ++ *exit_qual ^= DR6_RTM; ++ } else { + *exit_qual = 0; ++ } + return 1; + } + } +@@ -14010,13 +14013,6 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, + if (!page_address_valid(vcpu, kvm_state->vmx.vmxon_pa)) + return -EINVAL; + +- if (kvm_state->size < sizeof(kvm_state) + sizeof(*vmcs12)) +- return -EINVAL; +- +- if (kvm_state->vmx.vmcs_pa == kvm_state->vmx.vmxon_pa || +- !page_address_valid(vcpu, kvm_state->vmx.vmcs_pa)) +- return -EINVAL; +- + if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) && + (kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE)) + return -EINVAL; +@@ -14046,6 +14042,14 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, + if (ret) + return ret; + ++ /* Empty 'VMXON' state is permitted */ ++ if (kvm_state->size < sizeof(kvm_state) + sizeof(*vmcs12)) ++ return 0; ++ ++ if (kvm_state->vmx.vmcs_pa == kvm_state->vmx.vmxon_pa || ++ !page_address_valid(vcpu, kvm_state->vmx.vmcs_pa)) ++ return -EINVAL; ++ + set_current_vmptr(vmx, kvm_state->vmx.vmcs_pa); + + if (kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON) { +diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c +index b54d52a2d00a..d71d72cf6c66 100644 +--- a/arch/x86/mm/numa_emulation.c ++++ b/arch/x86/mm/numa_emulation.c +@@ -400,9 +400,17 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) + n = simple_strtoul(emu_cmdline, &emu_cmdline, 0); + ret = -1; + for_each_node_mask(i, physnode_mask) { ++ /* ++ * The reason we pass in blk[0] is due to ++ * numa_remove_memblk_from() called by ++ * emu_setup_memblk() will delete entry 0 ++ * and then move everything else up in the pi.blk ++ * array. Therefore we should always be looking ++ * at blk[0]. ++ */ + ret = split_nodes_size_interleave_uniform(&ei, &pi, +- pi.blk[i].start, pi.blk[i].end, 0, +- n, &pi.blk[i], nid); ++ pi.blk[0].start, pi.blk[0].end, 0, ++ n, &pi.blk[0], nid); + if (ret < 0) + break; + if (ret < n) { +diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c +index 51a5a69ecac9..e2d4b25c7aa4 100644 +--- a/arch/x86/mm/pageattr.c ++++ b/arch/x86/mm/pageattr.c +@@ -2086,9 +2086,13 @@ void __kernel_map_pages(struct page *page, int numpages, int enable) + + /* + * We should perform an IPI and flush all tlbs, +- * but that can deadlock->flush only current cpu: ++ * but that can deadlock->flush only current cpu. ++ * Preemption needs to be disabled around __flush_tlb_all() due to ++ * CR3 reload in __native_flush_tlb(). + */ ++ preempt_disable(); + __flush_tlb_all(); ++ preempt_enable(); + + arch_flush_lazy_mmu_mode(); + } +diff --git a/arch/x86/platform/olpc/olpc-xo1-rtc.c b/arch/x86/platform/olpc/olpc-xo1-rtc.c +index a2b4efddd61a..8e7ddd7e313a 100644 +--- a/arch/x86/platform/olpc/olpc-xo1-rtc.c ++++ b/arch/x86/platform/olpc/olpc-xo1-rtc.c +@@ -16,6 +16,7 @@ + + #include + #include ++#include + + static void rtc_wake_on(struct device *dev) + { +@@ -75,6 +76,8 @@ static int __init xo1_rtc_init(void) + if (r) + return r; + ++ x86_platform.legacy.rtc = 0; ++ + device_init_wakeup(&xo1_rtc_device.dev, 1); + return 0; + } +diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c +index c85d1a88f476..f7f77023288a 100644 +--- a/arch/x86/xen/enlighten_pvh.c ++++ b/arch/x86/xen/enlighten_pvh.c +@@ -75,7 +75,7 @@ static void __init init_pvh_bootparams(void) + * Version 2.12 supports Xen entry point but we will use default x86/PC + * environment (i.e. hardware_subarch 0). + */ +- pvh_bootparams.hdr.version = 0x212; ++ pvh_bootparams.hdr.version = (2 << 8) | 12; + pvh_bootparams.hdr.type_of_loader = (9 << 4) | 0; /* Xen loader */ + + x86_init.acpi.get_root_pointer = pvh_get_root_pointer; +diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c +index 33a783c77d96..184b36922397 100644 +--- a/arch/x86/xen/platform-pci-unplug.c ++++ b/arch/x86/xen/platform-pci-unplug.c +@@ -146,6 +146,10 @@ void xen_unplug_emulated_devices(void) + { + int r; + ++ /* PVH guests don't have emulated devices. */ ++ if (xen_pvh_domain()) ++ return; ++ + /* user explicitly requested no unplug */ + if (xen_emul_unplug & XEN_UNPLUG_NEVER) + return; +diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c +index 973f10e05211..717b4847b473 100644 +--- a/arch/x86/xen/spinlock.c ++++ b/arch/x86/xen/spinlock.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -21,6 +22,7 @@ + + static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; + static DEFINE_PER_CPU(char *, irq_name); ++static DEFINE_PER_CPU(atomic_t, xen_qlock_wait_nest); + static bool xen_pvspin = true; + + static void xen_qlock_kick(int cpu) +@@ -40,33 +42,24 @@ static void xen_qlock_kick(int cpu) + static void xen_qlock_wait(u8 *byte, u8 val) + { + int irq = __this_cpu_read(lock_kicker_irq); ++ atomic_t *nest_cnt = this_cpu_ptr(&xen_qlock_wait_nest); + + /* If kicker interrupts not initialized yet, just spin */ +- if (irq == -1) ++ if (irq == -1 || in_nmi()) + return; + +- /* clear pending */ +- xen_clear_irq_pending(irq); +- barrier(); +- +- /* +- * We check the byte value after clearing pending IRQ to make sure +- * that we won't miss a wakeup event because of the clearing. +- * +- * The sync_clear_bit() call in xen_clear_irq_pending() is atomic. +- * So it is effectively a memory barrier for x86. +- */ +- if (READ_ONCE(*byte) != val) +- return; ++ /* Detect reentry. */ ++ atomic_inc(nest_cnt); + +- /* +- * If an interrupt happens here, it will leave the wakeup irq +- * pending, which will cause xen_poll_irq() to return +- * immediately. +- */ ++ /* If irq pending already and no nested call clear it. */ ++ if (atomic_read(nest_cnt) == 1 && xen_test_irq_pending(irq)) { ++ xen_clear_irq_pending(irq); ++ } else if (READ_ONCE(*byte) == val) { ++ /* Block until irq becomes pending (or a spurious wakeup) */ ++ xen_poll_irq(irq); ++ } + +- /* Block until irq becomes pending (or perhaps a spurious wakeup) */ +- xen_poll_irq(irq); ++ atomic_dec(nest_cnt); + } + + static irqreturn_t dummy_handler(int irq, void *dev_id) +diff --git a/arch/x86/xen/xen-pvh.S b/arch/x86/xen/xen-pvh.S +index ca2d3b2bf2af..58722a052f9c 100644 +--- a/arch/x86/xen/xen-pvh.S ++++ b/arch/x86/xen/xen-pvh.S +@@ -181,7 +181,7 @@ canary: + .fill 48, 1, 0 + + early_stack: +- .fill 256, 1, 0 ++ .fill BOOT_STACK_SIZE, 1, 0 + early_stack_end: + + ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, +diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c +index ae52bff43ce4..ff7c2d470bb8 100644 +--- a/block/bfq-wf2q.c ++++ b/block/bfq-wf2q.c +@@ -1181,10 +1181,17 @@ bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree) + st = bfq_entity_service_tree(entity); + is_in_service = entity == sd->in_service_entity; + +- if (is_in_service) { +- bfq_calc_finish(entity, entity->service); ++ bfq_calc_finish(entity, entity->service); ++ ++ if (is_in_service) + sd->in_service_entity = NULL; +- } ++ else ++ /* ++ * Non in-service entity: nobody will take care of ++ * resetting its service counter on expiration. Do it ++ * now. ++ */ ++ entity->service = 0; + + if (entity->tree == &st->active) + bfq_active_extract(st, entity); +diff --git a/block/blk-lib.c b/block/blk-lib.c +index bbd44666f2b5..1f196cf0aa5d 100644 +--- a/block/blk-lib.c ++++ b/block/blk-lib.c +@@ -58,8 +58,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, + + if (!req_sects) + goto fail; +- if (req_sects > UINT_MAX >> 9) +- req_sects = UINT_MAX >> 9; ++ req_sects = min(req_sects, bio_allowed_max_sectors(q)); + + end_sect = sector + req_sects; + +@@ -162,7 +161,7 @@ static int __blkdev_issue_write_same(struct block_device *bdev, sector_t sector, + return -EOPNOTSUPP; + + /* Ensure that max_write_same_sectors doesn't overflow bi_size */ +- max_write_same_sectors = UINT_MAX >> 9; ++ max_write_same_sectors = bio_allowed_max_sectors(q); + + while (nr_sects) { + bio = next_bio(bio, 1, gfp_mask); +diff --git a/block/blk-merge.c b/block/blk-merge.c +index aaec38cc37b8..2e042190a4f1 100644 +--- a/block/blk-merge.c ++++ b/block/blk-merge.c +@@ -27,7 +27,8 @@ static struct bio *blk_bio_discard_split(struct request_queue *q, + /* Zero-sector (unknown) and one-sector granularities are the same. */ + granularity = max(q->limits.discard_granularity >> 9, 1U); + +- max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9); ++ max_discard_sectors = min(q->limits.max_discard_sectors, ++ bio_allowed_max_sectors(q)); + max_discard_sectors -= max_discard_sectors % granularity; + + if (unlikely(!max_discard_sectors)) { +diff --git a/block/blk.h b/block/blk.h +index 9db4e389582c..977d4b5d968d 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -328,6 +328,16 @@ static inline unsigned long blk_rq_deadline(struct request *rq) + return rq->__deadline & ~0x1UL; + } + ++/* ++ * The max size one bio can handle is UINT_MAX becasue bvec_iter.bi_size ++ * is defined as 'unsigned int', meantime it has to aligned to with logical ++ * block size which is the minimum accepted unit by hardware. ++ */ ++static inline unsigned int bio_allowed_max_sectors(struct request_queue *q) ++{ ++ return round_down(UINT_MAX, queue_logical_block_size(q)) >> 9; ++} ++ + /* + * Internal io_context interface + */ +diff --git a/block/bounce.c b/block/bounce.c +index bc63b3a2d18c..418677dcec60 100644 +--- a/block/bounce.c ++++ b/block/bounce.c +@@ -31,6 +31,24 @@ + static struct bio_set bounce_bio_set, bounce_bio_split; + static mempool_t page_pool, isa_page_pool; + ++static void init_bounce_bioset(void) ++{ ++ static bool bounce_bs_setup; ++ int ret; ++ ++ if (bounce_bs_setup) ++ return; ++ ++ ret = bioset_init(&bounce_bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); ++ BUG_ON(ret); ++ if (bioset_integrity_create(&bounce_bio_set, BIO_POOL_SIZE)) ++ BUG_ON(1); ++ ++ ret = bioset_init(&bounce_bio_split, BIO_POOL_SIZE, 0, 0); ++ BUG_ON(ret); ++ bounce_bs_setup = true; ++} ++ + #if defined(CONFIG_HIGHMEM) + static __init int init_emergency_pool(void) + { +@@ -44,14 +62,7 @@ static __init int init_emergency_pool(void) + BUG_ON(ret); + pr_info("pool size: %d pages\n", POOL_SIZE); + +- ret = bioset_init(&bounce_bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); +- BUG_ON(ret); +- if (bioset_integrity_create(&bounce_bio_set, BIO_POOL_SIZE)) +- BUG_ON(1); +- +- ret = bioset_init(&bounce_bio_split, BIO_POOL_SIZE, 0, 0); +- BUG_ON(ret); +- ++ init_bounce_bioset(); + return 0; + } + +@@ -86,6 +97,8 @@ static void *mempool_alloc_pages_isa(gfp_t gfp_mask, void *data) + return mempool_alloc_pages(gfp_mask | GFP_DMA, data); + } + ++static DEFINE_MUTEX(isa_mutex); ++ + /* + * gets called "every" time someone init's a queue with BLK_BOUNCE_ISA + * as the max address, so check if the pool has already been created. +@@ -94,14 +107,20 @@ int init_emergency_isa_pool(void) + { + int ret; + +- if (mempool_initialized(&isa_page_pool)) ++ mutex_lock(&isa_mutex); ++ ++ if (mempool_initialized(&isa_page_pool)) { ++ mutex_unlock(&isa_mutex); + return 0; ++ } + + ret = mempool_init(&isa_page_pool, ISA_POOL_SIZE, mempool_alloc_pages_isa, + mempool_free_pages, (void *) 0); + BUG_ON(ret); + + pr_info("isa pool size: %d pages\n", ISA_POOL_SIZE); ++ init_bounce_bioset(); ++ mutex_unlock(&isa_mutex); + return 0; + } + +diff --git a/crypto/Kconfig b/crypto/Kconfig +index f3e40ac56d93..59e32623a7ce 100644 +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -1590,20 +1590,6 @@ config CRYPTO_SM4 + + If unsure, say N. + +-config CRYPTO_SPECK +- tristate "Speck cipher algorithm" +- select CRYPTO_ALGAPI +- help +- Speck is a lightweight block cipher that is tuned for optimal +- performance in software (rather than hardware). +- +- Speck may not be as secure as AES, and should only be used on systems +- where AES is not fast enough. +- +- See also: +- +- If unsure, say N. +- + config CRYPTO_TEA + tristate "TEA, XTEA and XETA cipher algorithms" + select CRYPTO_ALGAPI +diff --git a/crypto/Makefile b/crypto/Makefile +index 6d1d40eeb964..f6a234d08882 100644 +--- a/crypto/Makefile ++++ b/crypto/Makefile +@@ -115,7 +115,6 @@ obj-$(CONFIG_CRYPTO_TEA) += tea.o + obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o + obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o + obj-$(CONFIG_CRYPTO_SEED) += seed.o +-obj-$(CONFIG_CRYPTO_SPECK) += speck.o + obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o + obj-$(CONFIG_CRYPTO_CHACHA20) += chacha20_generic.o + obj-$(CONFIG_CRYPTO_POLY1305) += poly1305_generic.o +diff --git a/crypto/aegis.h b/crypto/aegis.h +index f1c6900ddb80..405e025fc906 100644 +--- a/crypto/aegis.h ++++ b/crypto/aegis.h +@@ -21,7 +21,7 @@ + + union aegis_block { + __le64 words64[AEGIS_BLOCK_SIZE / sizeof(__le64)]; +- u32 words32[AEGIS_BLOCK_SIZE / sizeof(u32)]; ++ __le32 words32[AEGIS_BLOCK_SIZE / sizeof(__le32)]; + u8 bytes[AEGIS_BLOCK_SIZE]; + }; + +@@ -57,24 +57,22 @@ static void crypto_aegis_aesenc(union aegis_block *dst, + const union aegis_block *src, + const union aegis_block *key) + { +- u32 *d = dst->words32; + const u8 *s = src->bytes; +- const u32 *k = key->words32; + const u32 *t0 = crypto_ft_tab[0]; + const u32 *t1 = crypto_ft_tab[1]; + const u32 *t2 = crypto_ft_tab[2]; + const u32 *t3 = crypto_ft_tab[3]; + u32 d0, d1, d2, d3; + +- d0 = t0[s[ 0]] ^ t1[s[ 5]] ^ t2[s[10]] ^ t3[s[15]] ^ k[0]; +- d1 = t0[s[ 4]] ^ t1[s[ 9]] ^ t2[s[14]] ^ t3[s[ 3]] ^ k[1]; +- d2 = t0[s[ 8]] ^ t1[s[13]] ^ t2[s[ 2]] ^ t3[s[ 7]] ^ k[2]; +- d3 = t0[s[12]] ^ t1[s[ 1]] ^ t2[s[ 6]] ^ t3[s[11]] ^ k[3]; ++ d0 = t0[s[ 0]] ^ t1[s[ 5]] ^ t2[s[10]] ^ t3[s[15]]; ++ d1 = t0[s[ 4]] ^ t1[s[ 9]] ^ t2[s[14]] ^ t3[s[ 3]]; ++ d2 = t0[s[ 8]] ^ t1[s[13]] ^ t2[s[ 2]] ^ t3[s[ 7]]; ++ d3 = t0[s[12]] ^ t1[s[ 1]] ^ t2[s[ 6]] ^ t3[s[11]]; + +- d[0] = d0; +- d[1] = d1; +- d[2] = d2; +- d[3] = d3; ++ dst->words32[0] = cpu_to_le32(d0) ^ key->words32[0]; ++ dst->words32[1] = cpu_to_le32(d1) ^ key->words32[1]; ++ dst->words32[2] = cpu_to_le32(d2) ^ key->words32[2]; ++ dst->words32[3] = cpu_to_le32(d3) ^ key->words32[3]; + } + + #endif /* _CRYPTO_AEGIS_H */ +diff --git a/crypto/lrw.c b/crypto/lrw.c +index 393a782679c7..5504d1325a56 100644 +--- a/crypto/lrw.c ++++ b/crypto/lrw.c +@@ -143,7 +143,12 @@ static inline int get_index128(be128 *block) + return x + ffz(val); + } + +- return x; ++ /* ++ * If we get here, then x == 128 and we are incrementing the counter ++ * from all ones to all zeros. This means we must return index 127, i.e. ++ * the one corresponding to key2*{ 1,...,1 }. ++ */ ++ return 127; + } + + static int post_crypt(struct skcipher_request *req) +diff --git a/crypto/morus1280.c b/crypto/morus1280.c +index d057cf5ac4a8..3889c188f266 100644 +--- a/crypto/morus1280.c ++++ b/crypto/morus1280.c +@@ -385,14 +385,11 @@ static void crypto_morus1280_final(struct morus1280_state *state, + struct morus1280_block *tag_xor, + u64 assoclen, u64 cryptlen) + { +- u64 assocbits = assoclen * 8; +- u64 cryptbits = cryptlen * 8; +- + struct morus1280_block tmp; + unsigned int i; + +- tmp.words[0] = cpu_to_le64(assocbits); +- tmp.words[1] = cpu_to_le64(cryptbits); ++ tmp.words[0] = assoclen * 8; ++ tmp.words[1] = cryptlen * 8; + tmp.words[2] = 0; + tmp.words[3] = 0; + +diff --git a/crypto/morus640.c b/crypto/morus640.c +index 1ca76e54281b..da06ec2f6a80 100644 +--- a/crypto/morus640.c ++++ b/crypto/morus640.c +@@ -384,21 +384,13 @@ static void crypto_morus640_final(struct morus640_state *state, + struct morus640_block *tag_xor, + u64 assoclen, u64 cryptlen) + { +- u64 assocbits = assoclen * 8; +- u64 cryptbits = cryptlen * 8; +- +- u32 assocbits_lo = (u32)assocbits; +- u32 assocbits_hi = (u32)(assocbits >> 32); +- u32 cryptbits_lo = (u32)cryptbits; +- u32 cryptbits_hi = (u32)(cryptbits >> 32); +- + struct morus640_block tmp; + unsigned int i; + +- tmp.words[0] = cpu_to_le32(assocbits_lo); +- tmp.words[1] = cpu_to_le32(assocbits_hi); +- tmp.words[2] = cpu_to_le32(cryptbits_lo); +- tmp.words[3] = cpu_to_le32(cryptbits_hi); ++ tmp.words[0] = lower_32_bits(assoclen * 8); ++ tmp.words[1] = upper_32_bits(assoclen * 8); ++ tmp.words[2] = lower_32_bits(cryptlen * 8); ++ tmp.words[3] = upper_32_bits(cryptlen * 8); + + for (i = 0; i < MORUS_BLOCK_WORDS; i++) + state->s[4].words[i] ^= state->s[0].words[i]; +diff --git a/crypto/speck.c b/crypto/speck.c +deleted file mode 100644 +index 58aa9f7f91f7..000000000000 +--- a/crypto/speck.c ++++ /dev/null +@@ -1,307 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * Speck: a lightweight block cipher +- * +- * Copyright (c) 2018 Google, Inc +- * +- * Speck has 10 variants, including 5 block sizes. For now we only implement +- * the variants Speck128/128, Speck128/192, Speck128/256, Speck64/96, and +- * Speck64/128. Speck${B}/${K} denotes the variant with a block size of B bits +- * and a key size of K bits. The Speck128 variants are believed to be the most +- * secure variants, and they use the same block size and key sizes as AES. The +- * Speck64 variants are less secure, but on 32-bit processors are usually +- * faster. The remaining variants (Speck32, Speck48, and Speck96) are even less +- * secure and/or not as well suited for implementation on either 32-bit or +- * 64-bit processors, so are omitted. +- * +- * Reference: "The Simon and Speck Families of Lightweight Block Ciphers" +- * https://eprint.iacr.org/2013/404.pdf +- * +- * In a correspondence, the Speck designers have also clarified that the words +- * should be interpreted in little-endian format, and the words should be +- * ordered such that the first word of each block is 'y' rather than 'x', and +- * the first key word (rather than the last) becomes the first round key. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* Speck128 */ +- +-static __always_inline void speck128_round(u64 *x, u64 *y, u64 k) +-{ +- *x = ror64(*x, 8); +- *x += *y; +- *x ^= k; +- *y = rol64(*y, 3); +- *y ^= *x; +-} +- +-static __always_inline void speck128_unround(u64 *x, u64 *y, u64 k) +-{ +- *y ^= *x; +- *y = ror64(*y, 3); +- *x ^= k; +- *x -= *y; +- *x = rol64(*x, 8); +-} +- +-void crypto_speck128_encrypt(const struct speck128_tfm_ctx *ctx, +- u8 *out, const u8 *in) +-{ +- u64 y = get_unaligned_le64(in); +- u64 x = get_unaligned_le64(in + 8); +- int i; +- +- for (i = 0; i < ctx->nrounds; i++) +- speck128_round(&x, &y, ctx->round_keys[i]); +- +- put_unaligned_le64(y, out); +- put_unaligned_le64(x, out + 8); +-} +-EXPORT_SYMBOL_GPL(crypto_speck128_encrypt); +- +-static void speck128_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +-{ +- crypto_speck128_encrypt(crypto_tfm_ctx(tfm), out, in); +-} +- +-void crypto_speck128_decrypt(const struct speck128_tfm_ctx *ctx, +- u8 *out, const u8 *in) +-{ +- u64 y = get_unaligned_le64(in); +- u64 x = get_unaligned_le64(in + 8); +- int i; +- +- for (i = ctx->nrounds - 1; i >= 0; i--) +- speck128_unround(&x, &y, ctx->round_keys[i]); +- +- put_unaligned_le64(y, out); +- put_unaligned_le64(x, out + 8); +-} +-EXPORT_SYMBOL_GPL(crypto_speck128_decrypt); +- +-static void speck128_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +-{ +- crypto_speck128_decrypt(crypto_tfm_ctx(tfm), out, in); +-} +- +-int crypto_speck128_setkey(struct speck128_tfm_ctx *ctx, const u8 *key, +- unsigned int keylen) +-{ +- u64 l[3]; +- u64 k; +- int i; +- +- switch (keylen) { +- case SPECK128_128_KEY_SIZE: +- k = get_unaligned_le64(key); +- l[0] = get_unaligned_le64(key + 8); +- ctx->nrounds = SPECK128_128_NROUNDS; +- for (i = 0; i < ctx->nrounds; i++) { +- ctx->round_keys[i] = k; +- speck128_round(&l[0], &k, i); +- } +- break; +- case SPECK128_192_KEY_SIZE: +- k = get_unaligned_le64(key); +- l[0] = get_unaligned_le64(key + 8); +- l[1] = get_unaligned_le64(key + 16); +- ctx->nrounds = SPECK128_192_NROUNDS; +- for (i = 0; i < ctx->nrounds; i++) { +- ctx->round_keys[i] = k; +- speck128_round(&l[i % 2], &k, i); +- } +- break; +- case SPECK128_256_KEY_SIZE: +- k = get_unaligned_le64(key); +- l[0] = get_unaligned_le64(key + 8); +- l[1] = get_unaligned_le64(key + 16); +- l[2] = get_unaligned_le64(key + 24); +- ctx->nrounds = SPECK128_256_NROUNDS; +- for (i = 0; i < ctx->nrounds; i++) { +- ctx->round_keys[i] = k; +- speck128_round(&l[i % 3], &k, i); +- } +- break; +- default: +- return -EINVAL; +- } +- +- return 0; +-} +-EXPORT_SYMBOL_GPL(crypto_speck128_setkey); +- +-static int speck128_setkey(struct crypto_tfm *tfm, const u8 *key, +- unsigned int keylen) +-{ +- return crypto_speck128_setkey(crypto_tfm_ctx(tfm), key, keylen); +-} +- +-/* Speck64 */ +- +-static __always_inline void speck64_round(u32 *x, u32 *y, u32 k) +-{ +- *x = ror32(*x, 8); +- *x += *y; +- *x ^= k; +- *y = rol32(*y, 3); +- *y ^= *x; +-} +- +-static __always_inline void speck64_unround(u32 *x, u32 *y, u32 k) +-{ +- *y ^= *x; +- *y = ror32(*y, 3); +- *x ^= k; +- *x -= *y; +- *x = rol32(*x, 8); +-} +- +-void crypto_speck64_encrypt(const struct speck64_tfm_ctx *ctx, +- u8 *out, const u8 *in) +-{ +- u32 y = get_unaligned_le32(in); +- u32 x = get_unaligned_le32(in + 4); +- int i; +- +- for (i = 0; i < ctx->nrounds; i++) +- speck64_round(&x, &y, ctx->round_keys[i]); +- +- put_unaligned_le32(y, out); +- put_unaligned_le32(x, out + 4); +-} +-EXPORT_SYMBOL_GPL(crypto_speck64_encrypt); +- +-static void speck64_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +-{ +- crypto_speck64_encrypt(crypto_tfm_ctx(tfm), out, in); +-} +- +-void crypto_speck64_decrypt(const struct speck64_tfm_ctx *ctx, +- u8 *out, const u8 *in) +-{ +- u32 y = get_unaligned_le32(in); +- u32 x = get_unaligned_le32(in + 4); +- int i; +- +- for (i = ctx->nrounds - 1; i >= 0; i--) +- speck64_unround(&x, &y, ctx->round_keys[i]); +- +- put_unaligned_le32(y, out); +- put_unaligned_le32(x, out + 4); +-} +-EXPORT_SYMBOL_GPL(crypto_speck64_decrypt); +- +-static void speck64_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +-{ +- crypto_speck64_decrypt(crypto_tfm_ctx(tfm), out, in); +-} +- +-int crypto_speck64_setkey(struct speck64_tfm_ctx *ctx, const u8 *key, +- unsigned int keylen) +-{ +- u32 l[3]; +- u32 k; +- int i; +- +- switch (keylen) { +- case SPECK64_96_KEY_SIZE: +- k = get_unaligned_le32(key); +- l[0] = get_unaligned_le32(key + 4); +- l[1] = get_unaligned_le32(key + 8); +- ctx->nrounds = SPECK64_96_NROUNDS; +- for (i = 0; i < ctx->nrounds; i++) { +- ctx->round_keys[i] = k; +- speck64_round(&l[i % 2], &k, i); +- } +- break; +- case SPECK64_128_KEY_SIZE: +- k = get_unaligned_le32(key); +- l[0] = get_unaligned_le32(key + 4); +- l[1] = get_unaligned_le32(key + 8); +- l[2] = get_unaligned_le32(key + 12); +- ctx->nrounds = SPECK64_128_NROUNDS; +- for (i = 0; i < ctx->nrounds; i++) { +- ctx->round_keys[i] = k; +- speck64_round(&l[i % 3], &k, i); +- } +- break; +- default: +- return -EINVAL; +- } +- +- return 0; +-} +-EXPORT_SYMBOL_GPL(crypto_speck64_setkey); +- +-static int speck64_setkey(struct crypto_tfm *tfm, const u8 *key, +- unsigned int keylen) +-{ +- return crypto_speck64_setkey(crypto_tfm_ctx(tfm), key, keylen); +-} +- +-/* Algorithm definitions */ +- +-static struct crypto_alg speck_algs[] = { +- { +- .cra_name = "speck128", +- .cra_driver_name = "speck128-generic", +- .cra_priority = 100, +- .cra_flags = CRYPTO_ALG_TYPE_CIPHER, +- .cra_blocksize = SPECK128_BLOCK_SIZE, +- .cra_ctxsize = sizeof(struct speck128_tfm_ctx), +- .cra_module = THIS_MODULE, +- .cra_u = { +- .cipher = { +- .cia_min_keysize = SPECK128_128_KEY_SIZE, +- .cia_max_keysize = SPECK128_256_KEY_SIZE, +- .cia_setkey = speck128_setkey, +- .cia_encrypt = speck128_encrypt, +- .cia_decrypt = speck128_decrypt +- } +- } +- }, { +- .cra_name = "speck64", +- .cra_driver_name = "speck64-generic", +- .cra_priority = 100, +- .cra_flags = CRYPTO_ALG_TYPE_CIPHER, +- .cra_blocksize = SPECK64_BLOCK_SIZE, +- .cra_ctxsize = sizeof(struct speck64_tfm_ctx), +- .cra_module = THIS_MODULE, +- .cra_u = { +- .cipher = { +- .cia_min_keysize = SPECK64_96_KEY_SIZE, +- .cia_max_keysize = SPECK64_128_KEY_SIZE, +- .cia_setkey = speck64_setkey, +- .cia_encrypt = speck64_encrypt, +- .cia_decrypt = speck64_decrypt +- } +- } +- } +-}; +- +-static int __init speck_module_init(void) +-{ +- return crypto_register_algs(speck_algs, ARRAY_SIZE(speck_algs)); +-} +- +-static void __exit speck_module_exit(void) +-{ +- crypto_unregister_algs(speck_algs, ARRAY_SIZE(speck_algs)); +-} +- +-module_init(speck_module_init); +-module_exit(speck_module_exit); +- +-MODULE_DESCRIPTION("Speck block cipher (generic)"); +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Eric Biggers "); +-MODULE_ALIAS_CRYPTO("speck128"); +-MODULE_ALIAS_CRYPTO("speck128-generic"); +-MODULE_ALIAS_CRYPTO("speck64"); +-MODULE_ALIAS_CRYPTO("speck64-generic"); +diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c +index bdde95e8d369..6e0a054bb61d 100644 +--- a/crypto/tcrypt.c ++++ b/crypto/tcrypt.c +@@ -1103,6 +1103,9 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, + break; + } + ++ if (speed[i].klen) ++ crypto_ahash_setkey(tfm, tvmem[0], speed[i].klen); ++ + pr_info("test%3u " + "(%5u byte blocks,%5u bytes per update,%4u updates): ", + i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); +diff --git a/crypto/testmgr.c b/crypto/testmgr.c +index a1d42245082a..1c9bf38e59ea 100644 +--- a/crypto/testmgr.c ++++ b/crypto/testmgr.c +@@ -3037,18 +3037,6 @@ static const struct alg_test_desc alg_test_descs[] = { + .suite = { + .cipher = __VECS(sm4_tv_template) + } +- }, { +- .alg = "ecb(speck128)", +- .test = alg_test_skcipher, +- .suite = { +- .cipher = __VECS(speck128_tv_template) +- } +- }, { +- .alg = "ecb(speck64)", +- .test = alg_test_skcipher, +- .suite = { +- .cipher = __VECS(speck64_tv_template) +- } + }, { + .alg = "ecb(tea)", + .test = alg_test_skcipher, +@@ -3576,18 +3564,6 @@ static const struct alg_test_desc alg_test_descs[] = { + .suite = { + .cipher = __VECS(serpent_xts_tv_template) + } +- }, { +- .alg = "xts(speck128)", +- .test = alg_test_skcipher, +- .suite = { +- .cipher = __VECS(speck128_xts_tv_template) +- } +- }, { +- .alg = "xts(speck64)", +- .test = alg_test_skcipher, +- .suite = { +- .cipher = __VECS(speck64_xts_tv_template) +- } + }, { + .alg = "xts(twofish)", + .test = alg_test_skcipher, +diff --git a/crypto/testmgr.h b/crypto/testmgr.h +index 173111c70746..0b3d7cadbe93 100644 +--- a/crypto/testmgr.h ++++ b/crypto/testmgr.h +@@ -10198,744 +10198,6 @@ static const struct cipher_testvec sm4_tv_template[] = { + } + }; + +-/* +- * Speck test vectors taken from the original paper: +- * "The Simon and Speck Families of Lightweight Block Ciphers" +- * https://eprint.iacr.org/2013/404.pdf +- * +- * Note that the paper does not make byte and word order clear. But it was +- * confirmed with the authors that the intended orders are little endian byte +- * order and (y, x) word order. Equivalently, the printed test vectors, when +- * looking at only the bytes (ignoring the whitespace that divides them into +- * words), are backwards: the left-most byte is actually the one with the +- * highest memory address, while the right-most byte is actually the one with +- * the lowest memory address. +- */ +- +-static const struct cipher_testvec speck128_tv_template[] = { +- { /* Speck128/128 */ +- .key = "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", +- .klen = 16, +- .ptext = "\x20\x6d\x61\x64\x65\x20\x69\x74" +- "\x20\x65\x71\x75\x69\x76\x61\x6c", +- .ctext = "\x18\x0d\x57\x5c\xdf\xfe\x60\x78" +- "\x65\x32\x78\x79\x51\x98\x5d\xa6", +- .len = 16, +- }, { /* Speck128/192 */ +- .key = "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17", +- .klen = 24, +- .ptext = "\x65\x6e\x74\x20\x74\x6f\x20\x43" +- "\x68\x69\x65\x66\x20\x48\x61\x72", +- .ctext = "\x86\x18\x3c\xe0\x5d\x18\xbc\xf9" +- "\x66\x55\x13\x13\x3a\xcf\xe4\x1b", +- .len = 16, +- }, { /* Speck128/256 */ +- .key = "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", +- .klen = 32, +- .ptext = "\x70\x6f\x6f\x6e\x65\x72\x2e\x20" +- "\x49\x6e\x20\x74\x68\x6f\x73\x65", +- .ctext = "\x43\x8f\x18\x9c\x8d\xb4\xee\x4e" +- "\x3e\xf5\xc0\x05\x04\x01\x09\x41", +- .len = 16, +- }, +-}; +- +-/* +- * Speck128-XTS test vectors, taken from the AES-XTS test vectors with the +- * ciphertext recomputed with Speck128 as the cipher +- */ +-static const struct cipher_testvec speck128_xts_tv_template[] = { +- { +- .key = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .klen = 32, +- .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ctext = "\xbe\xa0\xe7\x03\xd7\xfe\xab\x62" +- "\x3b\x99\x4a\x64\x74\x77\xac\xed" +- "\xd8\xf4\xa6\xcf\xae\xb9\x07\x42" +- "\x51\xd9\xb6\x1d\xe0\x5e\xbc\x54", +- .len = 32, +- }, { +- .key = "\x11\x11\x11\x11\x11\x11\x11\x11" +- "\x11\x11\x11\x11\x11\x11\x11\x11" +- "\x22\x22\x22\x22\x22\x22\x22\x22" +- "\x22\x22\x22\x22\x22\x22\x22\x22", +- .klen = 32, +- .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44", +- .ctext = "\xfb\x53\x81\x75\x6f\x9f\x34\xad" +- "\x7e\x01\xed\x7b\xcc\xda\x4e\x4a" +- "\xd4\x84\xa4\x53\xd5\x88\x73\x1b" +- "\xfd\xcb\xae\x0d\xf3\x04\xee\xe6", +- .len = 32, +- }, { +- .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8" +- "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0" +- "\x22\x22\x22\x22\x22\x22\x22\x22" +- "\x22\x22\x22\x22\x22\x22\x22\x22", +- .klen = 32, +- .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44", +- .ctext = "\x21\x52\x84\x15\xd1\xf7\x21\x55" +- "\xd9\x75\x4a\xd3\xc5\xdb\x9f\x7d" +- "\xda\x63\xb2\xf1\x82\xb0\x89\x59" +- "\x86\xd4\xaa\xaa\xdd\xff\x4f\x92", +- .len = 32, +- }, { +- .key = "\x27\x18\x28\x18\x28\x45\x90\x45" +- "\x23\x53\x60\x28\x74\x71\x35\x26" +- "\x31\x41\x59\x26\x53\x58\x97\x93" +- "\x23\x84\x62\x64\x33\x83\x27\x95", +- .klen = 32, +- .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +- "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", +- .ctext = "\x57\xb5\xf8\x71\x6e\x6d\xdd\x82" +- "\x53\xd0\xed\x2d\x30\xc1\x20\xef" +- "\x70\x67\x5e\xff\x09\x70\xbb\xc1" +- "\x3a\x7b\x48\x26\xd9\x0b\xf4\x48" +- "\xbe\xce\xb1\xc7\xb2\x67\xc4\xa7" +- "\x76\xf8\x36\x30\xb7\xb4\x9a\xd9" +- "\xf5\x9d\xd0\x7b\xc1\x06\x96\x44" +- "\x19\xc5\x58\x84\x63\xb9\x12\x68" +- "\x68\xc7\xaa\x18\x98\xf2\x1f\x5c" +- "\x39\xa6\xd8\x32\x2b\xc3\x51\xfd" +- "\x74\x79\x2e\xb4\x44\xd7\x69\xc4" +- "\xfc\x29\xe6\xed\x26\x1e\xa6\x9d" +- "\x1c\xbe\x00\x0e\x7f\x3a\xca\xfb" +- "\x6d\x13\x65\xa0\xf9\x31\x12\xe2" +- "\x26\xd1\xec\x2b\x0a\x8b\x59\x99" +- "\xa7\x49\xa0\x0e\x09\x33\x85\x50" +- "\xc3\x23\xca\x7a\xdd\x13\x45\x5f" +- "\xde\x4c\xa7\xcb\x00\x8a\x66\x6f" +- "\xa2\xb6\xb1\x2e\xe1\xa0\x18\xf6" +- "\xad\xf3\xbd\xeb\xc7\xef\x55\x4f" +- "\x79\x91\x8d\x36\x13\x7b\xd0\x4a" +- "\x6c\x39\xfb\x53\xb8\x6f\x02\x51" +- "\xa5\x20\xac\x24\x1c\x73\x59\x73" +- "\x58\x61\x3a\x87\x58\xb3\x20\x56" +- "\x39\x06\x2b\x4d\xd3\x20\x2b\x89" +- "\x3f\xa2\xf0\x96\xeb\x7f\xa4\xcd" +- "\x11\xae\xbd\xcb\x3a\xb4\xd9\x91" +- "\x09\x35\x71\x50\x65\xac\x92\xe3" +- "\x7b\x32\xc0\x7a\xdd\xd4\xc3\x92" +- "\x6f\xeb\x79\xde\x6f\xd3\x25\xc9" +- "\xcd\x63\xf5\x1e\x7a\x3b\x26\x9d" +- "\x77\x04\x80\xa9\xbf\x38\xb5\xbd" +- "\xb8\x05\x07\xbd\xfd\xab\x7b\xf8" +- "\x2a\x26\xcc\x49\x14\x6d\x55\x01" +- "\x06\x94\xd8\xb2\x2d\x53\x83\x1b" +- "\x8f\xd4\xdd\x57\x12\x7e\x18\xba" +- "\x8e\xe2\x4d\x80\xef\x7e\x6b\x9d" +- "\x24\xa9\x60\xa4\x97\x85\x86\x2a" +- "\x01\x00\x09\xf1\xcb\x4a\x24\x1c" +- "\xd8\xf6\xe6\x5b\xe7\x5d\xf2\xc4" +- "\x97\x1c\x10\xc6\x4d\x66\x4f\x98" +- "\x87\x30\xac\xd5\xea\x73\x49\x10" +- "\x80\xea\xe5\x5f\x4d\x5f\x03\x33" +- "\x66\x02\x35\x3d\x60\x06\x36\x4f" +- "\x14\x1c\xd8\x07\x1f\x78\xd0\xf8" +- "\x4f\x6c\x62\x7c\x15\xa5\x7c\x28" +- "\x7c\xcc\xeb\x1f\xd1\x07\x90\x93" +- "\x7e\xc2\xa8\x3a\x80\xc0\xf5\x30" +- "\xcc\x75\xcf\x16\x26\xa9\x26\x3b" +- "\xe7\x68\x2f\x15\x21\x5b\xe4\x00" +- "\xbd\x48\x50\xcd\x75\x70\xc4\x62" +- "\xbb\x41\xfb\x89\x4a\x88\x3b\x3b" +- "\x51\x66\x02\x69\x04\x97\x36\xd4" +- "\x75\xae\x0b\xa3\x42\xf8\xca\x79" +- "\x8f\x93\xe9\xcc\x38\xbd\xd6\xd2" +- "\xf9\x70\x4e\xc3\x6a\x8e\x25\xbd" +- "\xea\x15\x5a\xa0\x85\x7e\x81\x0d" +- "\x03\xe7\x05\x39\xf5\x05\x26\xee" +- "\xec\xaa\x1f\x3d\xc9\x98\x76\x01" +- "\x2c\xf4\xfc\xa3\x88\x77\x38\xc4" +- "\x50\x65\x50\x6d\x04\x1f\xdf\x5a" +- "\xaa\xf2\x01\xa9\xc1\x8d\xee\xca" +- "\x47\x26\xef\x39\xb8\xb4\xf2\xd1" +- "\xd6\xbb\x1b\x2a\xc1\x34\x14\xcf", +- .len = 512, +- }, { +- .key = "\x27\x18\x28\x18\x28\x45\x90\x45" +- "\x23\x53\x60\x28\x74\x71\x35\x26" +- "\x62\x49\x77\x57\x24\x70\x93\x69" +- "\x99\x59\x57\x49\x66\x96\x76\x27" +- "\x31\x41\x59\x26\x53\x58\x97\x93" +- "\x23\x84\x62\x64\x33\x83\x27\x95" +- "\x02\x88\x41\x97\x16\x93\x99\x37" +- "\x51\x05\x82\x09\x74\x94\x45\x92", +- .klen = 64, +- .iv = "\xff\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +- "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", +- .ctext = "\xc5\x85\x2a\x4b\x73\xe4\xf6\xf1" +- "\x7e\xf9\xf6\xe9\xa3\x73\x36\xcb" +- "\xaa\xb6\x22\xb0\x24\x6e\x3d\x73" +- "\x92\x99\xde\xd3\x76\xed\xcd\x63" +- "\x64\x3a\x22\x57\xc1\x43\x49\xd4" +- "\x79\x36\x31\x19\x62\xae\x10\x7e" +- "\x7d\xcf\x7a\xe2\x6b\xce\x27\xfa" +- "\xdc\x3d\xd9\x83\xd3\x42\x4c\xe0" +- "\x1b\xd6\x1d\x1a\x6f\xd2\x03\x00" +- "\xfc\x81\x99\x8a\x14\x62\xf5\x7e" +- "\x0d\xe7\x12\xe8\x17\x9d\x0b\xec" +- "\xe2\xf7\xc9\xa7\x63\xd1\x79\xb6" +- "\x62\x62\x37\xfe\x0a\x4c\x4a\x37" +- "\x70\xc7\x5e\x96\x5f\xbc\x8e\x9e" +- "\x85\x3c\x4f\x26\x64\x85\xbc\x68" +- "\xb0\xe0\x86\x5e\x26\x41\xce\x11" +- "\x50\xda\x97\x14\xe9\x9e\xc7\x6d" +- "\x3b\xdc\x43\xde\x2b\x27\x69\x7d" +- "\xfc\xb0\x28\xbd\x8f\xb1\xc6\x31" +- "\x14\x4d\xf0\x74\x37\xfd\x07\x25" +- "\x96\x55\xe5\xfc\x9e\x27\x2a\x74" +- "\x1b\x83\x4d\x15\x83\xac\x57\xa0" +- "\xac\xa5\xd0\x38\xef\x19\x56\x53" +- "\x25\x4b\xfc\xce\x04\x23\xe5\x6b" +- "\xf6\xc6\x6c\x32\x0b\xb3\x12\xc5" +- "\xed\x22\x34\x1c\x5d\xed\x17\x06" +- "\x36\xa3\xe6\x77\xb9\x97\x46\xb8" +- "\xe9\x3f\x7e\xc7\xbc\x13\x5c\xdc" +- "\x6e\x3f\x04\x5e\xd1\x59\xa5\x82" +- "\x35\x91\x3d\x1b\xe4\x97\x9f\x92" +- "\x1c\x5e\x5f\x6f\x41\xd4\x62\xa1" +- "\x8d\x39\xfc\x42\xfb\x38\x80\xb9" +- "\x0a\xe3\xcc\x6a\x93\xd9\x7a\xb1" +- "\xe9\x69\xaf\x0a\x6b\x75\x38\xa7" +- "\xa1\xbf\xf7\xda\x95\x93\x4b\x78" +- "\x19\xf5\x94\xf9\xd2\x00\x33\x37" +- "\xcf\xf5\x9e\x9c\xf3\xcc\xa6\xee" +- "\x42\xb2\x9e\x2c\x5f\x48\x23\x26" +- "\x15\x25\x17\x03\x3d\xfe\x2c\xfc" +- "\xeb\xba\xda\xe0\x00\x05\xb6\xa6" +- "\x07\xb3\xe8\x36\x5b\xec\x5b\xbf" +- "\xd6\x5b\x00\x74\xc6\x97\xf1\x6a" +- "\x49\xa1\xc3\xfa\x10\x52\xb9\x14" +- "\xad\xb7\x73\xf8\x78\x12\xc8\x59" +- "\x17\x80\x4c\x57\x39\xf1\x6d\x80" +- "\x25\x77\x0f\x5e\x7d\xf0\xaf\x21" +- "\xec\xce\xb7\xc8\x02\x8a\xed\x53" +- "\x2c\x25\x68\x2e\x1f\x85\x5e\x67" +- "\xd1\x07\x7a\x3a\x89\x08\xe0\x34" +- "\xdc\xdb\x26\xb4\x6b\x77\xfc\x40" +- "\x31\x15\x72\xa0\xf0\x73\xd9\x3b" +- "\xd5\xdb\xfe\xfc\x8f\xa9\x44\xa2" +- "\x09\x9f\xc6\x33\xe5\xe2\x88\xe8" +- "\xf3\xf0\x1a\xf4\xce\x12\x0f\xd6" +- "\xf7\x36\xe6\xa4\xf4\x7a\x10\x58" +- "\xcc\x1f\x48\x49\x65\x47\x75\xe9" +- "\x28\xe1\x65\x7b\xf2\xc4\xb5\x07" +- "\xf2\xec\x76\xd8\x8f\x09\xf3\x16" +- "\xa1\x51\x89\x3b\xeb\x96\x42\xac" +- "\x65\xe0\x67\x63\x29\xdc\xb4\x7d" +- "\xf2\x41\x51\x6a\xcb\xde\x3c\xfb" +- "\x66\x8d\x13\xca\xe0\x59\x2a\x00" +- "\xc9\x53\x4c\xe6\x9e\xe2\x73\xd5" +- "\x67\x19\xb2\xbd\x9a\x63\xd7\x5c", +- .len = 512, +- .also_non_np = 1, +- .np = 3, +- .tap = { 512 - 20, 4, 16 }, +- } +-}; +- +-static const struct cipher_testvec speck64_tv_template[] = { +- { /* Speck64/96 */ +- .key = "\x00\x01\x02\x03\x08\x09\x0a\x0b" +- "\x10\x11\x12\x13", +- .klen = 12, +- .ptext = "\x65\x61\x6e\x73\x20\x46\x61\x74", +- .ctext = "\x6c\x94\x75\x41\xec\x52\x79\x9f", +- .len = 8, +- }, { /* Speck64/128 */ +- .key = "\x00\x01\x02\x03\x08\x09\x0a\x0b" +- "\x10\x11\x12\x13\x18\x19\x1a\x1b", +- .klen = 16, +- .ptext = "\x2d\x43\x75\x74\x74\x65\x72\x3b", +- .ctext = "\x8b\x02\x4e\x45\x48\xa5\x6f\x8c", +- .len = 8, +- }, +-}; +- +-/* +- * Speck64-XTS test vectors, taken from the AES-XTS test vectors with the +- * ciphertext recomputed with Speck64 as the cipher, and key lengths adjusted +- */ +-static const struct cipher_testvec speck64_xts_tv_template[] = { +- { +- .key = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .klen = 24, +- .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ctext = "\x84\xaf\x54\x07\x19\xd4\x7c\xa6" +- "\xe4\xfe\xdf\xc4\x1f\x34\xc3\xc2" +- "\x80\xf5\x72\xe7\xcd\xf0\x99\x22" +- "\x35\xa7\x2f\x06\xef\xdc\x51\xaa", +- .len = 32, +- }, { +- .key = "\x11\x11\x11\x11\x11\x11\x11\x11" +- "\x11\x11\x11\x11\x11\x11\x11\x11" +- "\x22\x22\x22\x22\x22\x22\x22\x22", +- .klen = 24, +- .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44", +- .ctext = "\x12\x56\x73\xcd\x15\x87\xa8\x59" +- "\xcf\x84\xae\xd9\x1c\x66\xd6\x9f" +- "\xb3\x12\x69\x7e\x36\xeb\x52\xff" +- "\x62\xdd\xba\x90\xb3\xe1\xee\x99", +- .len = 32, +- }, { +- .key = "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8" +- "\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0" +- "\x22\x22\x22\x22\x22\x22\x22\x22", +- .klen = 24, +- .iv = "\x33\x33\x33\x33\x33\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44" +- "\x44\x44\x44\x44\x44\x44\x44\x44", +- .ctext = "\x15\x1b\xe4\x2c\xa2\x5a\x2d\x2c" +- "\x27\x36\xc0\xbf\x5d\xea\x36\x37" +- "\x2d\x1a\x88\xbc\x66\xb5\xd0\x0b" +- "\xa1\xbc\x19\xb2\x0f\x3b\x75\x34", +- .len = 32, +- }, { +- .key = "\x27\x18\x28\x18\x28\x45\x90\x45" +- "\x23\x53\x60\x28\x74\x71\x35\x26" +- "\x31\x41\x59\x26\x53\x58\x97\x93", +- .klen = 24, +- .iv = "\x00\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +- "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", +- .ctext = "\xaf\xa1\x81\xa6\x32\xbb\x15\x8e" +- "\xf8\x95\x2e\xd3\xe6\xee\x7e\x09" +- "\x0c\x1a\xf5\x02\x97\x8b\xe3\xb3" +- "\x11\xc7\x39\x96\xd0\x95\xf4\x56" +- "\xf4\xdd\x03\x38\x01\x44\x2c\xcf" +- "\x88\xae\x8e\x3c\xcd\xe7\xaa\x66" +- "\xfe\x3d\xc6\xfb\x01\x23\x51\x43" +- "\xd5\xd2\x13\x86\x94\x34\xe9\x62" +- "\xf9\x89\xe3\xd1\x7b\xbe\xf8\xef" +- "\x76\x35\x04\x3f\xdb\x23\x9d\x0b" +- "\x85\x42\xb9\x02\xd6\xcc\xdb\x96" +- "\xa7\x6b\x27\xb6\xd4\x45\x8f\x7d" +- "\xae\xd2\x04\xd5\xda\xc1\x7e\x24" +- "\x8c\x73\xbe\x48\x7e\xcf\x65\x28" +- "\x29\xe5\xbe\x54\x30\xcb\x46\x95" +- "\x4f\x2e\x8a\x36\xc8\x27\xc5\xbe" +- "\xd0\x1a\xaf\xab\x26\xcd\x9e\x69" +- "\xa1\x09\x95\x71\x26\xe9\xc4\xdf" +- "\xe6\x31\xc3\x46\xda\xaf\x0b\x41" +- "\x1f\xab\xb1\x8e\xd6\xfc\x0b\xb3" +- "\x82\xc0\x37\x27\xfc\x91\xa7\x05" +- "\xfb\xc5\xdc\x2b\x74\x96\x48\x43" +- "\x5d\x9c\x19\x0f\x60\x63\x3a\x1f" +- "\x6f\xf0\x03\xbe\x4d\xfd\xc8\x4a" +- "\xc6\xa4\x81\x6d\xc3\x12\x2a\x5c" +- "\x07\xff\xf3\x72\x74\x48\xb5\x40" +- "\x50\xb5\xdd\x90\x43\x31\x18\x15" +- "\x7b\xf2\xa6\xdb\x83\xc8\x4b\x4a" +- "\x29\x93\x90\x8b\xda\x07\xf0\x35" +- "\x6d\x90\x88\x09\x4e\x83\xf5\x5b" +- "\x94\x12\xbb\x33\x27\x1d\x3f\x23" +- "\x51\xa8\x7c\x07\xa2\xae\x77\xa6" +- "\x50\xfd\xcc\xc0\x4f\x80\x7a\x9f" +- "\x66\xdd\xcd\x75\x24\x8b\x33\xf7" +- "\x20\xdb\x83\x9b\x4f\x11\x63\x6e" +- "\xcf\x37\xef\xc9\x11\x01\x5c\x45" +- "\x32\x99\x7c\x3c\x9e\x42\x89\xe3" +- "\x70\x6d\x15\x9f\xb1\xe6\xb6\x05" +- "\xfe\x0c\xb9\x49\x2d\x90\x6d\xcc" +- "\x5d\x3f\xc1\xfe\x89\x0a\x2e\x2d" +- "\xa0\xa8\x89\x3b\x73\x39\xa5\x94" +- "\x4c\xa4\xa6\xbb\xa7\x14\x46\x89" +- "\x10\xff\xaf\xef\xca\xdd\x4f\x80" +- "\xb3\xdf\x3b\xab\xd4\xe5\x5a\xc7" +- "\x33\xca\x00\x8b\x8b\x3f\xea\xec" +- "\x68\x8a\xc2\x6d\xfd\xd4\x67\x0f" +- "\x22\x31\xe1\x0e\xfe\x5a\x04\xd5" +- "\x64\xa3\xf1\x1a\x76\x28\xcc\x35" +- "\x36\xa7\x0a\x74\xf7\x1c\x44\x9b" +- "\xc7\x1b\x53\x17\x02\xea\xd1\xad" +- "\x13\x51\x73\xc0\xa0\xb2\x05\x32" +- "\xa8\xa2\x37\x2e\xe1\x7a\x3a\x19" +- "\x26\xb4\x6c\x62\x5d\xb3\x1a\x1d" +- "\x59\xda\xee\x1a\x22\x18\xda\x0d" +- "\x88\x0f\x55\x8b\x72\x62\xfd\xc1" +- "\x69\x13\xcd\x0d\x5f\xc1\x09\x52" +- "\xee\xd6\xe3\x84\x4d\xee\xf6\x88" +- "\xaf\x83\xdc\x76\xf4\xc0\x93\x3f" +- "\x4a\x75\x2f\xb0\x0b\x3e\xc4\x54" +- "\x7d\x69\x8d\x00\x62\x77\x0d\x14" +- "\xbe\x7c\xa6\x7d\xc5\x24\x4f\xf3" +- "\x50\xf7\x5f\xf4\xc2\xca\x41\x97" +- "\x37\xbe\x75\x74\xcd\xf0\x75\x6e" +- "\x25\x23\x94\xbd\xda\x8d\xb0\xd4", +- .len = 512, +- }, { +- .key = "\x27\x18\x28\x18\x28\x45\x90\x45" +- "\x23\x53\x60\x28\x74\x71\x35\x26" +- "\x62\x49\x77\x57\x24\x70\x93\x69" +- "\x99\x59\x57\x49\x66\x96\x76\x27", +- .klen = 32, +- .iv = "\xff\x00\x00\x00\x00\x00\x00\x00" +- "\x00\x00\x00\x00\x00\x00\x00\x00", +- .ptext = "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +- "\x00\x01\x02\x03\x04\x05\x06\x07" +- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +- "\x10\x11\x12\x13\x14\x15\x16\x17" +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +- "\x20\x21\x22\x23\x24\x25\x26\x27" +- "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +- "\x30\x31\x32\x33\x34\x35\x36\x37" +- "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" +- "\x40\x41\x42\x43\x44\x45\x46\x47" +- "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" +- "\x50\x51\x52\x53\x54\x55\x56\x57" +- "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +- "\x60\x61\x62\x63\x64\x65\x66\x67" +- "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" +- "\x70\x71\x72\x73\x74\x75\x76\x77" +- "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +- "\x80\x81\x82\x83\x84\x85\x86\x87" +- "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" +- "\x90\x91\x92\x93\x94\x95\x96\x97" +- "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +- "\xa8\xa9\xaa\xab\xac\xad\xae\xaf" +- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" +- "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" +- "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" +- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7" +- "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" +- "\xe8\xe9\xea\xeb\xec\xed\xee\xef" +- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7" +- "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", +- .ctext = "\x55\xed\x71\xd3\x02\x8e\x15\x3b" +- "\xc6\x71\x29\x2d\x3e\x89\x9f\x59" +- "\x68\x6a\xcc\x8a\x56\x97\xf3\x95" +- "\x4e\x51\x08\xda\x2a\xf8\x6f\x3c" +- "\x78\x16\xea\x80\xdb\x33\x75\x94" +- "\xf9\x29\xc4\x2b\x76\x75\x97\xc7" +- "\xf2\x98\x2c\xf9\xff\xc8\xd5\x2b" +- "\x18\xf1\xaf\xcf\x7c\xc5\x0b\xee" +- "\xad\x3c\x76\x7c\xe6\x27\xa2\x2a" +- "\xe4\x66\xe1\xab\xa2\x39\xfc\x7c" +- "\xf5\xec\x32\x74\xa3\xb8\x03\x88" +- "\x52\xfc\x2e\x56\x3f\xa1\xf0\x9f" +- "\x84\x5e\x46\xed\x20\x89\xb6\x44" +- "\x8d\xd0\xed\x54\x47\x16\xbe\x95" +- "\x8a\xb3\x6b\x72\xc4\x32\x52\x13" +- "\x1b\xb0\x82\xbe\xac\xf9\x70\xa6" +- "\x44\x18\xdd\x8c\x6e\xca\x6e\x45" +- "\x8f\x1e\x10\x07\x57\x25\x98\x7b" +- "\x17\x8c\x78\xdd\x80\xa7\xd9\xd8" +- "\x63\xaf\xb9\x67\x57\xfd\xbc\xdb" +- "\x44\xe9\xc5\x65\xd1\xc7\x3b\xff" +- "\x20\xa0\x80\x1a\xc3\x9a\xad\x5e" +- "\x5d\x3b\xd3\x07\xd9\xf5\xfd\x3d" +- "\x4a\x8b\xa8\xd2\x6e\x7a\x51\x65" +- "\x6c\x8e\x95\xe0\x45\xc9\x5f\x4a" +- "\x09\x3c\x3d\x71\x7f\x0c\x84\x2a" +- "\xc8\x48\x52\x1a\xc2\xd5\xd6\x78" +- "\x92\x1e\xa0\x90\x2e\xea\xf0\xf3" +- "\xdc\x0f\xb1\xaf\x0d\x9b\x06\x2e" +- "\x35\x10\x30\x82\x0d\xe7\xc5\x9b" +- "\xde\x44\x18\xbd\x9f\xd1\x45\xa9" +- "\x7b\x7a\x4a\xad\x35\x65\x27\xca" +- "\xb2\xc3\xd4\x9b\x71\x86\x70\xee" +- "\xf1\x89\x3b\x85\x4b\x5b\xaa\xaf" +- "\xfc\x42\xc8\x31\x59\xbe\x16\x60" +- "\x4f\xf9\xfa\x12\xea\xd0\xa7\x14" +- "\xf0\x7a\xf3\xd5\x8d\xbd\x81\xef" +- "\x52\x7f\x29\x51\x94\x20\x67\x3c" +- "\xd1\xaf\x77\x9f\x22\x5a\x4e\x63" +- "\xe7\xff\x73\x25\xd1\xdd\x96\x8a" +- "\x98\x52\x6d\xf3\xac\x3e\xf2\x18" +- "\x6d\xf6\x0a\x29\xa6\x34\x3d\xed" +- "\xe3\x27\x0d\x9d\x0a\x02\x44\x7e" +- "\x5a\x7e\x67\x0f\x0a\x9e\xd6\xad" +- "\x91\xe6\x4d\x81\x8c\x5c\x59\xaa" +- "\xfb\xeb\x56\x53\xd2\x7d\x4c\x81" +- "\x65\x53\x0f\x41\x11\xbd\x98\x99" +- "\xf9\xc6\xfa\x51\x2e\xa3\xdd\x8d" +- "\x84\x98\xf9\x34\xed\x33\x2a\x1f" +- "\x82\xed\xc1\x73\x98\xd3\x02\xdc" +- "\xe6\xc2\x33\x1d\xa2\xb4\xca\x76" +- "\x63\x51\x34\x9d\x96\x12\xae\xce" +- "\x83\xc9\x76\x5e\xa4\x1b\x53\x37" +- "\x17\xd5\xc0\x80\x1d\x62\xf8\x3d" +- "\x54\x27\x74\xbb\x10\x86\x57\x46" +- "\x68\xe1\xed\x14\xe7\x9d\xfc\x84" +- "\x47\xbc\xc2\xf8\x19\x4b\x99\xcf" +- "\x7a\xe9\xc4\xb8\x8c\x82\x72\x4d" +- "\x7b\x4f\x38\x55\x36\x71\x64\xc1" +- "\xfc\x5c\x75\x52\x33\x02\x18\xf8" +- "\x17\xe1\x2b\xc2\x43\x39\xbd\x76" +- "\x9b\x63\x76\x32\x2f\x19\x72\x10" +- "\x9f\x21\x0c\xf1\x66\x50\x7f\xa5" +- "\x0d\x1f\x46\xe0\xba\xd3\x2f\x3c", +- .len = 512, +- .also_non_np = 1, +- .np = 3, +- .tap = { 512 - 20, 4, 16 }, +- } +-}; +- + /* Cast6 test vectors from RFC 2612 */ + static const struct cipher_testvec cast6_tv_template[] = { + { +diff --git a/drivers/acpi/acpi_lpit.c b/drivers/acpi/acpi_lpit.c +index cf4fc0161164..e43cb71b6972 100644 +--- a/drivers/acpi/acpi_lpit.c ++++ b/drivers/acpi/acpi_lpit.c +@@ -117,11 +117,17 @@ static void lpit_update_residency(struct lpit_residency_info *info, + if (!info->iomem_addr) + return; + ++ if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) ++ return; ++ + /* Silently fail, if cpuidle attribute group is not present */ + sysfs_add_file_to_group(&cpu_subsys.dev_root->kobj, + &dev_attr_low_power_idle_system_residency_us.attr, + "cpuidle"); + } else if (info->gaddr.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { ++ if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) ++ return; ++ + /* Silently fail, if cpuidle attribute group is not present */ + sysfs_add_file_to_group(&cpu_subsys.dev_root->kobj, + &dev_attr_low_power_idle_cpu_residency_us.attr, +diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c +index bf64cfa30feb..969bf8d515c0 100644 +--- a/drivers/acpi/acpi_lpss.c ++++ b/drivers/acpi/acpi_lpss.c +@@ -327,9 +327,11 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { + { "INT33FC", }, + + /* Braswell LPSS devices */ ++ { "80862286", LPSS_ADDR(lpss_dma_desc) }, + { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) }, + { "8086228A", LPSS_ADDR(bsw_uart_dev_desc) }, + { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) }, ++ { "808622C0", LPSS_ADDR(lpss_dma_desc) }, + { "808622C1", LPSS_ADDR(bsw_i2c_dev_desc) }, + + /* Broadwell LPSS devices */ +diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c +index 449d86d39965..fc447410ae4d 100644 +--- a/drivers/acpi/acpi_processor.c ++++ b/drivers/acpi/acpi_processor.c +@@ -643,7 +643,7 @@ static acpi_status __init acpi_processor_ids_walk(acpi_handle handle, + + status = acpi_get_type(handle, &acpi_type); + if (ACPI_FAILURE(status)) +- return false; ++ return status; + + switch (acpi_type) { + case ACPI_TYPE_PROCESSOR: +@@ -663,11 +663,12 @@ static acpi_status __init acpi_processor_ids_walk(acpi_handle handle, + } + + processor_validated_ids_update(uid); +- return true; ++ return AE_OK; + + err: ++ /* Exit on error, but don't abort the namespace walk */ + acpi_handle_info(handle, "Invalid processor object\n"); +- return false; ++ return AE_OK; + + } + +diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c +index e9fb0bf3c8d2..78f9de260d5f 100644 +--- a/drivers/acpi/acpica/dsopcode.c ++++ b/drivers/acpi/acpica/dsopcode.c +@@ -417,6 +417,10 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, + ACPI_FORMAT_UINT64(obj_desc->region.address), + obj_desc->region.length)); + ++ status = acpi_ut_add_address_range(obj_desc->region.space_id, ++ obj_desc->region.address, ++ obj_desc->region.length, node); ++ + /* Now the address and length are valid for this opregion */ + + obj_desc->region.flags |= AOPOBJ_DATA_VALID; +diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c +index 34fc2f7476ed..b0789c483b0f 100644 +--- a/drivers/acpi/acpica/psloop.c ++++ b/drivers/acpi/acpica/psloop.c +@@ -417,6 +417,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) + union acpi_parse_object *op = NULL; /* current op */ + struct acpi_parse_state *parser_state; + u8 *aml_op_start = NULL; ++ u8 opcode_length; + + ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); + +@@ -540,8 +541,19 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) + "Skip parsing opcode %s", + acpi_ps_get_opcode_name + (walk_state->opcode))); ++ ++ /* ++ * Determine the opcode length before skipping the opcode. ++ * An opcode can be 1 byte or 2 bytes in length. ++ */ ++ opcode_length = 1; ++ if ((walk_state->opcode & 0xFF00) == ++ AML_EXTENDED_OPCODE) { ++ opcode_length = 2; ++ } + walk_state->parser_state.aml = +- walk_state->aml + 1; ++ walk_state->aml + opcode_length; ++ + walk_state->parser_state.aml = + acpi_ps_get_next_package_end + (&walk_state->parser_state); +diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c +index b072cfc5f20e..19b641208d86 100644 +--- a/drivers/acpi/nfit/core.c ++++ b/drivers/acpi/nfit/core.c +@@ -2466,7 +2466,8 @@ static int ars_get_cap(struct acpi_nfit_desc *acpi_desc, + return cmd_rc; + } + +-static int ars_start(struct acpi_nfit_desc *acpi_desc, struct nfit_spa *nfit_spa) ++static int ars_start(struct acpi_nfit_desc *acpi_desc, ++ struct nfit_spa *nfit_spa, enum nfit_ars_state req_type) + { + int rc; + int cmd_rc; +@@ -2477,7 +2478,7 @@ static int ars_start(struct acpi_nfit_desc *acpi_desc, struct nfit_spa *nfit_spa + memset(&ars_start, 0, sizeof(ars_start)); + ars_start.address = spa->address; + ars_start.length = spa->length; +- if (test_bit(ARS_SHORT, &nfit_spa->ars_state)) ++ if (req_type == ARS_REQ_SHORT) + ars_start.flags = ND_ARS_RETURN_PREV_DATA; + if (nfit_spa_type(spa) == NFIT_SPA_PM) + ars_start.type = ND_ARS_PERSISTENT; +@@ -2534,6 +2535,15 @@ static void ars_complete(struct acpi_nfit_desc *acpi_desc, + struct nd_region *nd_region = nfit_spa->nd_region; + struct device *dev; + ++ lockdep_assert_held(&acpi_desc->init_mutex); ++ /* ++ * Only advance the ARS state for ARS runs initiated by the ++ * kernel, ignore ARS results from BIOS initiated runs for scrub ++ * completion tracking. ++ */ ++ if (acpi_desc->scrub_spa != nfit_spa) ++ return; ++ + if ((ars_status->address >= spa->address && ars_status->address + < spa->address + spa->length) + || (ars_status->address < spa->address)) { +@@ -2553,28 +2563,13 @@ static void ars_complete(struct acpi_nfit_desc *acpi_desc, + } else + return; + +- if (test_bit(ARS_DONE, &nfit_spa->ars_state)) +- return; +- +- if (!test_and_clear_bit(ARS_REQ, &nfit_spa->ars_state)) +- return; +- ++ acpi_desc->scrub_spa = NULL; + if (nd_region) { + dev = nd_region_dev(nd_region); + nvdimm_region_notify(nd_region, NVDIMM_REVALIDATE_POISON); + } else + dev = acpi_desc->dev; +- +- dev_dbg(dev, "ARS: range %d %s complete\n", spa->range_index, +- test_bit(ARS_SHORT, &nfit_spa->ars_state) +- ? "short" : "long"); +- clear_bit(ARS_SHORT, &nfit_spa->ars_state); +- if (test_and_clear_bit(ARS_REQ_REDO, &nfit_spa->ars_state)) { +- set_bit(ARS_SHORT, &nfit_spa->ars_state); +- set_bit(ARS_REQ, &nfit_spa->ars_state); +- dev_dbg(dev, "ARS: processing scrub request received while in progress\n"); +- } else +- set_bit(ARS_DONE, &nfit_spa->ars_state); ++ dev_dbg(dev, "ARS: range %d complete\n", spa->range_index); + } + + static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc) +@@ -2855,46 +2850,55 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc) + return 0; + } + +-static int ars_register(struct acpi_nfit_desc *acpi_desc, struct nfit_spa *nfit_spa, +- int *query_rc) ++static int ars_register(struct acpi_nfit_desc *acpi_desc, ++ struct nfit_spa *nfit_spa) + { +- int rc = *query_rc; ++ int rc; + +- if (no_init_ars) ++ if (no_init_ars || test_bit(ARS_FAILED, &nfit_spa->ars_state)) + return acpi_nfit_register_region(acpi_desc, nfit_spa); + +- set_bit(ARS_REQ, &nfit_spa->ars_state); +- set_bit(ARS_SHORT, &nfit_spa->ars_state); ++ set_bit(ARS_REQ_SHORT, &nfit_spa->ars_state); ++ set_bit(ARS_REQ_LONG, &nfit_spa->ars_state); + +- switch (rc) { ++ switch (acpi_nfit_query_poison(acpi_desc)) { + case 0: + case -EAGAIN: +- rc = ars_start(acpi_desc, nfit_spa); +- if (rc == -EBUSY) { +- *query_rc = rc; ++ rc = ars_start(acpi_desc, nfit_spa, ARS_REQ_SHORT); ++ /* shouldn't happen, try again later */ ++ if (rc == -EBUSY) + break; +- } else if (rc == 0) { +- rc = acpi_nfit_query_poison(acpi_desc); +- } else { ++ if (rc) { + set_bit(ARS_FAILED, &nfit_spa->ars_state); + break; + } +- if (rc == -EAGAIN) +- clear_bit(ARS_SHORT, &nfit_spa->ars_state); +- else if (rc == 0) +- ars_complete(acpi_desc, nfit_spa); ++ clear_bit(ARS_REQ_SHORT, &nfit_spa->ars_state); ++ rc = acpi_nfit_query_poison(acpi_desc); ++ if (rc) ++ break; ++ acpi_desc->scrub_spa = nfit_spa; ++ ars_complete(acpi_desc, nfit_spa); ++ /* ++ * If ars_complete() says we didn't complete the ++ * short scrub, we'll try again with a long ++ * request. ++ */ ++ acpi_desc->scrub_spa = NULL; + break; + case -EBUSY: ++ case -ENOMEM: + case -ENOSPC: ++ /* ++ * BIOS was using ARS, wait for it to complete (or ++ * resources to become available) and then perform our ++ * own scrubs. ++ */ + break; + default: + set_bit(ARS_FAILED, &nfit_spa->ars_state); + break; + } + +- if (test_and_clear_bit(ARS_DONE, &nfit_spa->ars_state)) +- set_bit(ARS_REQ, &nfit_spa->ars_state); +- + return acpi_nfit_register_region(acpi_desc, nfit_spa); + } + +@@ -2916,6 +2920,8 @@ static unsigned int __acpi_nfit_scrub(struct acpi_nfit_desc *acpi_desc, + struct device *dev = acpi_desc->dev; + struct nfit_spa *nfit_spa; + ++ lockdep_assert_held(&acpi_desc->init_mutex); ++ + if (acpi_desc->cancel) + return 0; + +@@ -2939,21 +2945,49 @@ static unsigned int __acpi_nfit_scrub(struct acpi_nfit_desc *acpi_desc, + + ars_complete_all(acpi_desc); + list_for_each_entry(nfit_spa, &acpi_desc->spas, list) { ++ enum nfit_ars_state req_type; ++ int rc; ++ + if (test_bit(ARS_FAILED, &nfit_spa->ars_state)) + continue; +- if (test_bit(ARS_REQ, &nfit_spa->ars_state)) { +- int rc = ars_start(acpi_desc, nfit_spa); +- +- clear_bit(ARS_DONE, &nfit_spa->ars_state); +- dev = nd_region_dev(nfit_spa->nd_region); +- dev_dbg(dev, "ARS: range %d ARS start (%d)\n", +- nfit_spa->spa->range_index, rc); +- if (rc == 0 || rc == -EBUSY) +- return 1; +- dev_err(dev, "ARS: range %d ARS failed (%d)\n", +- nfit_spa->spa->range_index, rc); +- set_bit(ARS_FAILED, &nfit_spa->ars_state); ++ ++ /* prefer short ARS requests first */ ++ if (test_bit(ARS_REQ_SHORT, &nfit_spa->ars_state)) ++ req_type = ARS_REQ_SHORT; ++ else if (test_bit(ARS_REQ_LONG, &nfit_spa->ars_state)) ++ req_type = ARS_REQ_LONG; ++ else ++ continue; ++ rc = ars_start(acpi_desc, nfit_spa, req_type); ++ ++ dev = nd_region_dev(nfit_spa->nd_region); ++ dev_dbg(dev, "ARS: range %d ARS start %s (%d)\n", ++ nfit_spa->spa->range_index, ++ req_type == ARS_REQ_SHORT ? "short" : "long", ++ rc); ++ /* ++ * Hmm, we raced someone else starting ARS? Try again in ++ * a bit. ++ */ ++ if (rc == -EBUSY) ++ return 1; ++ if (rc == 0) { ++ dev_WARN_ONCE(dev, acpi_desc->scrub_spa, ++ "scrub start while range %d active\n", ++ acpi_desc->scrub_spa->spa->range_index); ++ clear_bit(req_type, &nfit_spa->ars_state); ++ acpi_desc->scrub_spa = nfit_spa; ++ /* ++ * Consider this spa last for future scrub ++ * requests ++ */ ++ list_move_tail(&nfit_spa->list, &acpi_desc->spas); ++ return 1; + } ++ ++ dev_err(dev, "ARS: range %d ARS failed (%d)\n", ++ nfit_spa->spa->range_index, rc); ++ set_bit(ARS_FAILED, &nfit_spa->ars_state); + } + return 0; + } +@@ -3009,6 +3043,7 @@ static void acpi_nfit_init_ars(struct acpi_nfit_desc *acpi_desc, + struct nd_cmd_ars_cap ars_cap; + int rc; + ++ set_bit(ARS_FAILED, &nfit_spa->ars_state); + memset(&ars_cap, 0, sizeof(ars_cap)); + rc = ars_get_cap(acpi_desc, &ars_cap, nfit_spa); + if (rc < 0) +@@ -3025,16 +3060,14 @@ static void acpi_nfit_init_ars(struct acpi_nfit_desc *acpi_desc, + nfit_spa->clear_err_unit = ars_cap.clear_err_unit; + acpi_desc->max_ars = max(nfit_spa->max_ars, acpi_desc->max_ars); + clear_bit(ARS_FAILED, &nfit_spa->ars_state); +- set_bit(ARS_REQ, &nfit_spa->ars_state); + } + + static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc) + { + struct nfit_spa *nfit_spa; +- int rc, query_rc; ++ int rc; + + list_for_each_entry(nfit_spa, &acpi_desc->spas, list) { +- set_bit(ARS_FAILED, &nfit_spa->ars_state); + switch (nfit_spa_type(nfit_spa->spa)) { + case NFIT_SPA_VOLATILE: + case NFIT_SPA_PM: +@@ -3043,20 +3076,12 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc) + } + } + +- /* +- * Reap any results that might be pending before starting new +- * short requests. +- */ +- query_rc = acpi_nfit_query_poison(acpi_desc); +- if (query_rc == 0) +- ars_complete_all(acpi_desc); +- + list_for_each_entry(nfit_spa, &acpi_desc->spas, list) + switch (nfit_spa_type(nfit_spa->spa)) { + case NFIT_SPA_VOLATILE: + case NFIT_SPA_PM: + /* register regions and kick off initial ARS run */ +- rc = ars_register(acpi_desc, nfit_spa, &query_rc); ++ rc = ars_register(acpi_desc, nfit_spa); + if (rc) + return rc; + break; +@@ -3251,7 +3276,8 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc, + return 0; + } + +-int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags) ++int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, ++ enum nfit_ars_state req_type) + { + struct device *dev = acpi_desc->dev; + int scheduled = 0, busy = 0; +@@ -3271,14 +3297,10 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags) + if (test_bit(ARS_FAILED, &nfit_spa->ars_state)) + continue; + +- if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state)) { ++ if (test_and_set_bit(req_type, &nfit_spa->ars_state)) + busy++; +- set_bit(ARS_REQ_REDO, &nfit_spa->ars_state); +- } else { +- if (test_bit(ARS_SHORT, &flags)) +- set_bit(ARS_SHORT, &nfit_spa->ars_state); ++ else + scheduled++; +- } + } + if (scheduled) { + sched_ars(acpi_desc); +@@ -3464,10 +3486,11 @@ static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle) + static void acpi_nfit_uc_error_notify(struct device *dev, acpi_handle handle) + { + struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(dev); +- unsigned long flags = (acpi_desc->scrub_mode == HW_ERROR_SCRUB_ON) ? +- 0 : 1 << ARS_SHORT; + +- acpi_nfit_ars_rescan(acpi_desc, flags); ++ if (acpi_desc->scrub_mode == HW_ERROR_SCRUB_ON) ++ acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_LONG); ++ else ++ acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_SHORT); + } + + void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event) +diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h +index d1274ea2d251..02c10de50386 100644 +--- a/drivers/acpi/nfit/nfit.h ++++ b/drivers/acpi/nfit/nfit.h +@@ -118,10 +118,8 @@ enum nfit_dimm_notifiers { + }; + + enum nfit_ars_state { +- ARS_REQ, +- ARS_REQ_REDO, +- ARS_DONE, +- ARS_SHORT, ++ ARS_REQ_SHORT, ++ ARS_REQ_LONG, + ARS_FAILED, + }; + +@@ -198,6 +196,7 @@ struct acpi_nfit_desc { + struct device *dev; + u8 ars_start_flags; + struct nd_cmd_ars_status *ars_status; ++ struct nfit_spa *scrub_spa; + struct delayed_work dwork; + struct list_head list; + struct kernfs_node *scrub_count_state; +@@ -252,7 +251,8 @@ struct nfit_blk { + + extern struct list_head acpi_descs; + extern struct mutex acpi_desc_lock; +-int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags); ++int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, ++ enum nfit_ars_state req_type); + + #ifdef CONFIG_X86_MCE + void nfit_mce_register(void); +diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c +index 8df9abfa947b..ed73f6fb0779 100644 +--- a/drivers/acpi/osl.c ++++ b/drivers/acpi/osl.c +@@ -617,15 +617,18 @@ void acpi_os_stall(u32 us) + } + + /* +- * Support ACPI 3.0 AML Timer operand +- * Returns 64-bit free-running, monotonically increasing timer +- * with 100ns granularity ++ * Support ACPI 3.0 AML Timer operand. Returns a 64-bit free-running, ++ * monotonically increasing timer with 100ns granularity. Do not use ++ * ktime_get() to implement this function because this function may get ++ * called after timekeeping has been suspended. Note: calling this function ++ * after timekeeping has been suspended may lead to unexpected results ++ * because when timekeeping is suspended the jiffies counter is not ++ * incremented. See also timekeeping_suspend(). + */ + u64 acpi_os_get_timer(void) + { +- u64 time_ns = ktime_to_ns(ktime_get()); +- do_div(time_ns, 100); +- return time_ns; ++ return (get_jiffies_64() - INITIAL_JIFFIES) * ++ (ACPI_100NSEC_PER_SEC / HZ); + } + + acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) +diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c +index d1e26cb599bf..da031b1df6f5 100644 +--- a/drivers/acpi/pptt.c ++++ b/drivers/acpi/pptt.c +@@ -338,9 +338,6 @@ static struct acpi_pptt_cache *acpi_find_cache_node(struct acpi_table_header *ta + return found; + } + +-/* total number of attributes checked by the properties code */ +-#define PPTT_CHECKED_ATTRIBUTES 4 +- + /** + * update_cache_properties() - Update cacheinfo for the given processor + * @this_leaf: Kernel cache info structure being updated +@@ -357,25 +354,15 @@ static void update_cache_properties(struct cacheinfo *this_leaf, + struct acpi_pptt_cache *found_cache, + struct acpi_pptt_processor *cpu_node) + { +- int valid_flags = 0; +- + this_leaf->fw_token = cpu_node; +- if (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID) { ++ if (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID) + this_leaf->size = found_cache->size; +- valid_flags++; +- } +- if (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID) { ++ if (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID) + this_leaf->coherency_line_size = found_cache->line_size; +- valid_flags++; +- } +- if (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID) { ++ if (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID) + this_leaf->number_of_sets = found_cache->number_of_sets; +- valid_flags++; +- } +- if (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID) { ++ if (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID) + this_leaf->ways_of_associativity = found_cache->associativity; +- valid_flags++; +- } + if (found_cache->flags & ACPI_PPTT_WRITE_POLICY_VALID) { + switch (found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY) { + case ACPI_PPTT_CACHE_POLICY_WT: +@@ -402,11 +389,17 @@ static void update_cache_properties(struct cacheinfo *this_leaf, + } + } + /* +- * If the above flags are valid, and the cache type is NOCACHE +- * update the cache type as well. ++ * If cache type is NOCACHE, then the cache hasn't been specified ++ * via other mechanisms. Update the type if a cache type has been ++ * provided. ++ * ++ * Note, we assume such caches are unified based on conventional system ++ * design and known examples. Significant work is required elsewhere to ++ * fully support data/instruction only type caches which are only ++ * specified in PPTT. + */ + if (this_leaf->type == CACHE_TYPE_NOCACHE && +- valid_flags == PPTT_CHECKED_ATTRIBUTES) ++ found_cache->flags & ACPI_PPTT_CACHE_TYPE_VALID) + this_leaf->type = CACHE_TYPE_UNIFIED; + } + +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index a9dd4ea7467d..6e594644cb1d 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4553,6 +4553,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + /* These specific Samsung models/firmware-revs do not handle LPM well */ + { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, }, + { "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_HORKAGE_NOLPM, }, ++ { "SAMSUNG MZ7TD256HAFV-000L9", "DXT02L5Q", ATA_HORKAGE_NOLPM, }, + + /* devices that don't properly handle queued TRIM commands */ + { "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | +diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c +index dfb2c2622e5a..822e3060d834 100644 +--- a/drivers/block/ataflop.c ++++ b/drivers/block/ataflop.c +@@ -1935,6 +1935,11 @@ static int __init atari_floppy_init (void) + unit[i].disk = alloc_disk(1); + if (!unit[i].disk) + goto Enomem; ++ ++ unit[i].disk->queue = blk_init_queue(do_fd_request, ++ &ataflop_lock); ++ if (!unit[i].disk->queue) ++ goto Enomem; + } + + if (UseTrackbuffer < 0) +@@ -1966,10 +1971,6 @@ static int __init atari_floppy_init (void) + sprintf(unit[i].disk->disk_name, "fd%d", i); + unit[i].disk->fops = &floppy_fops; + unit[i].disk->private_data = &unit[i]; +- unit[i].disk->queue = blk_init_queue(do_fd_request, +- &ataflop_lock); +- if (!unit[i].disk->queue) +- goto Enomem; + set_capacity(unit[i].disk, MAX_DISK_SIZE * 2); + add_disk(unit[i].disk); + } +@@ -1984,13 +1985,17 @@ static int __init atari_floppy_init (void) + + return 0; + Enomem: +- while (i--) { +- struct request_queue *q = unit[i].disk->queue; ++ do { ++ struct gendisk *disk = unit[i].disk; + +- put_disk(unit[i].disk); +- if (q) +- blk_cleanup_queue(q); +- } ++ if (disk) { ++ if (disk->queue) { ++ blk_cleanup_queue(disk->queue); ++ disk->queue = NULL; ++ } ++ put_disk(unit[i].disk); ++ } ++ } while (i--); + + unregister_blkdev(FLOPPY_MAJOR, "fd"); + return -ENOMEM; +diff --git a/drivers/block/swim.c b/drivers/block/swim.c +index 0e31884a9519..cbe909c51847 100644 +--- a/drivers/block/swim.c ++++ b/drivers/block/swim.c +@@ -887,8 +887,17 @@ static int swim_floppy_init(struct swim_priv *swd) + + exit_put_disks: + unregister_blkdev(FLOPPY_MAJOR, "fd"); +- while (drive--) +- put_disk(swd->unit[drive].disk); ++ do { ++ struct gendisk *disk = swd->unit[drive].disk; ++ ++ if (disk) { ++ if (disk->queue) { ++ blk_cleanup_queue(disk->queue); ++ disk->queue = NULL; ++ } ++ put_disk(disk); ++ } ++ } while (drive--); + return err; + } + +diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c +index 429d20131c7e..3e905da33bcb 100644 +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1919,6 +1919,7 @@ static int negotiate_mq(struct blkfront_info *info) + GFP_KERNEL); + if (!info->rinfo) { + xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure"); ++ info->nr_rings = 0; + return -ENOMEM; + } + +@@ -2493,6 +2494,9 @@ static int blkfront_remove(struct xenbus_device *xbdev) + + dev_dbg(&xbdev->dev, "%s removed", xbdev->nodename); + ++ if (!info) ++ return 0; ++ + blkif_free(info, 0); + + mutex_lock(&info->mutex); +diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c +index 99cde1f9467d..e3e4d929e74f 100644 +--- a/drivers/bluetooth/btbcm.c ++++ b/drivers/bluetooth/btbcm.c +@@ -324,6 +324,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { + { 0x4103, "BCM4330B1" }, /* 002.001.003 */ + { 0x410e, "BCM43341B0" }, /* 002.001.014 */ + { 0x4406, "BCM4324B3" }, /* 002.004.006 */ ++ { 0x6109, "BCM4335C0" }, /* 003.001.009 */ + { 0x610c, "BCM4354" }, /* 003.001.012 */ + { 0x2122, "BCM4343A0" }, /* 001.001.034 */ + { 0x2209, "BCM43430A1" }, /* 001.002.009 */ +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 2fee65886d50..f0d593c3fa72 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -167,7 +167,7 @@ struct qca_serdev { + }; + + static int qca_power_setup(struct hci_uart *hu, bool on); +-static void qca_power_shutdown(struct hci_dev *hdev); ++static void qca_power_shutdown(struct hci_uart *hu); + + static void __serial_clock_on(struct tty_struct *tty) + { +@@ -609,7 +609,7 @@ static int qca_close(struct hci_uart *hu) + if (hu->serdev) { + qcadev = serdev_device_get_drvdata(hu->serdev); + if (qcadev->btsoc_type == QCA_WCN3990) +- qca_power_shutdown(hu->hdev); ++ qca_power_shutdown(hu); + else + gpiod_set_value_cansleep(qcadev->bt_en, 0); + +@@ -1232,12 +1232,15 @@ static const struct qca_vreg_data qca_soc_data = { + .num_vregs = 4, + }; + +-static void qca_power_shutdown(struct hci_dev *hdev) ++static void qca_power_shutdown(struct hci_uart *hu) + { +- struct hci_uart *hu = hci_get_drvdata(hdev); ++ struct serdev_device *serdev = hu->serdev; ++ unsigned char cmd = QCA_WCN3990_POWEROFF_PULSE; + + host_set_baudrate(hu, 2400); +- qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE); ++ hci_uart_set_flow_control(hu, true); ++ serdev_device_write_buf(serdev, &cmd, sizeof(cmd)); ++ hci_uart_set_flow_control(hu, false); + qca_power_setup(hu, false); + } + +@@ -1413,7 +1416,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) + struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); + + if (qcadev->btsoc_type == QCA_WCN3990) +- qca_power_shutdown(qcadev->serdev_hu.hdev); ++ qca_power_shutdown(&qcadev->serdev_hu); + else + clk_disable_unprepare(qcadev->susclk); + +diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c +index 29e67a80fb20..9b786726e426 100644 +--- a/drivers/char/ipmi/ipmi_ssif.c ++++ b/drivers/char/ipmi/ipmi_ssif.c +@@ -606,8 +606,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, + flags = ipmi_ssif_lock_cond(ssif_info, &oflags); + ssif_info->waiting_alert = true; + ssif_info->rtc_us_timer = SSIF_MSG_USEC; +- mod_timer(&ssif_info->retry_timer, +- jiffies + SSIF_MSG_JIFFIES); ++ if (!ssif_info->stopping) ++ mod_timer(&ssif_info->retry_timer, ++ jiffies + SSIF_MSG_JIFFIES); + ipmi_ssif_unlock_cond(ssif_info, flags); + return; + } +@@ -939,8 +940,9 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result, + ssif_info->waiting_alert = true; + ssif_info->retries_left = SSIF_RECV_RETRIES; + ssif_info->rtc_us_timer = SSIF_MSG_PART_USEC; +- mod_timer(&ssif_info->retry_timer, +- jiffies + SSIF_MSG_PART_JIFFIES); ++ if (!ssif_info->stopping) ++ mod_timer(&ssif_info->retry_timer, ++ jiffies + SSIF_MSG_PART_JIFFIES); + ipmi_ssif_unlock_cond(ssif_info, flags); + } + } +diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c +index 1a803b0cf980..7d958ff426e0 100644 +--- a/drivers/char/tpm/tpm-interface.c ++++ b/drivers/char/tpm/tpm-interface.c +@@ -663,7 +663,8 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, + return len; + + err = be32_to_cpu(header->return_code); +- if (err != 0 && desc) ++ if (err != 0 && err != TPM_ERR_DISABLED && err != TPM_ERR_DEACTIVATED ++ && desc) + dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, + desc); + if (err) +@@ -1321,7 +1322,8 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) + } + + rlength = be32_to_cpu(tpm_cmd.header.out.length); +- if (rlength < offsetof(struct tpm_getrandom_out, rng_data) + ++ if (rlength < TPM_HEADER_SIZE + ++ offsetof(struct tpm_getrandom_out, rng_data) + + recd) { + total = -EFAULT; + break; +diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c +index c31b490bd41d..3acf4fd4e5a5 100644 +--- a/drivers/char/tpm/tpm2-cmd.c ++++ b/drivers/char/tpm/tpm2-cmd.c +@@ -329,7 +329,9 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) + &buf.data[TPM_HEADER_SIZE]; + recd = min_t(u32, be16_to_cpu(out->size), num_bytes); + if (tpm_buf_length(&buf) < +- offsetof(struct tpm2_get_random_out, buffer) + recd) { ++ TPM_HEADER_SIZE + ++ offsetof(struct tpm2_get_random_out, buffer) + ++ recd) { + err = -EFAULT; + goto out; + } +diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c +index 911475d36800..b150f87f38f5 100644 +--- a/drivers/char/tpm/xen-tpmfront.c ++++ b/drivers/char/tpm/xen-tpmfront.c +@@ -264,7 +264,7 @@ static int setup_ring(struct xenbus_device *dev, struct tpm_private *priv) + return -ENOMEM; + } + +- rv = xenbus_grant_ring(dev, &priv->shr, 1, &gref); ++ rv = xenbus_grant_ring(dev, priv->shr, 1, &gref); + if (rv < 0) + return rv; + +diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c +index 0a9ebf00be46..e58bfcb1169e 100644 +--- a/drivers/cpufreq/cpufreq-dt.c ++++ b/drivers/cpufreq/cpufreq-dt.c +@@ -32,6 +32,7 @@ struct private_data { + struct device *cpu_dev; + struct thermal_cooling_device *cdev; + const char *reg_name; ++ bool have_static_opps; + }; + + static struct freq_attr *cpufreq_dt_attr[] = { +@@ -204,6 +205,15 @@ static int cpufreq_init(struct cpufreq_policy *policy) + } + } + ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ ret = -ENOMEM; ++ goto out_put_regulator; ++ } ++ ++ priv->reg_name = name; ++ priv->opp_table = opp_table; ++ + /* + * Initialize OPP tables for all policy->cpus. They will be shared by + * all CPUs which have marked their CPUs shared with OPP bindings. +@@ -214,7 +224,8 @@ static int cpufreq_init(struct cpufreq_policy *policy) + * + * OPPs might be populated at runtime, don't check for error here + */ +- dev_pm_opp_of_cpumask_add_table(policy->cpus); ++ if (!dev_pm_opp_of_cpumask_add_table(policy->cpus)) ++ priv->have_static_opps = true; + + /* + * But we need OPP table to function so if it is not there let's +@@ -240,19 +251,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) + __func__, ret); + } + +- priv = kzalloc(sizeof(*priv), GFP_KERNEL); +- if (!priv) { +- ret = -ENOMEM; +- goto out_free_opp; +- } +- +- priv->reg_name = name; +- priv->opp_table = opp_table; +- + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); + if (ret) { + dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); +- goto out_free_priv; ++ goto out_free_opp; + } + + priv->cpu_dev = cpu_dev; +@@ -282,10 +284,11 @@ static int cpufreq_init(struct cpufreq_policy *policy) + + out_free_cpufreq_table: + dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); +-out_free_priv: +- kfree(priv); + out_free_opp: +- dev_pm_opp_of_cpumask_remove_table(policy->cpus); ++ if (priv->have_static_opps) ++ dev_pm_opp_of_cpumask_remove_table(policy->cpus); ++ kfree(priv); ++out_put_regulator: + if (name) + dev_pm_opp_put_regulators(opp_table); + out_put_clk: +@@ -300,7 +303,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy) + + cpufreq_cooling_unregister(priv->cdev); + dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); +- dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); ++ if (priv->have_static_opps) ++ dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); + if (priv->reg_name) + dev_pm_opp_put_regulators(priv->opp_table); + +diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c +index f20f20a77d4d..4268f87e99fc 100644 +--- a/drivers/cpufreq/cpufreq_conservative.c ++++ b/drivers/cpufreq/cpufreq_conservative.c +@@ -80,8 +80,10 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy) + * changed in the meantime, so fall back to current frequency in that + * case. + */ +- if (requested_freq > policy->max || requested_freq < policy->min) ++ if (requested_freq > policy->max || requested_freq < policy->min) { + requested_freq = policy->cur; ++ dbs_info->requested_freq = requested_freq; ++ } + + freq_step = get_freq_step(cs_tuners, policy); + +@@ -92,7 +94,7 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy) + if (policy_dbs->idle_periods < UINT_MAX) { + unsigned int freq_steps = policy_dbs->idle_periods * freq_step; + +- if (requested_freq > freq_steps) ++ if (requested_freq > policy->min + freq_steps) + requested_freq -= freq_steps; + else + requested_freq = policy->min; +diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h +index 4fb91ba39c36..ce3f9ad7120f 100644 +--- a/drivers/crypto/caam/regs.h ++++ b/drivers/crypto/caam/regs.h +@@ -70,22 +70,22 @@ + extern bool caam_little_end; + extern bool caam_imx; + +-#define caam_to_cpu(len) \ +-static inline u##len caam##len ## _to_cpu(u##len val) \ +-{ \ +- if (caam_little_end) \ +- return le##len ## _to_cpu(val); \ +- else \ +- return be##len ## _to_cpu(val); \ ++#define caam_to_cpu(len) \ ++static inline u##len caam##len ## _to_cpu(u##len val) \ ++{ \ ++ if (caam_little_end) \ ++ return le##len ## _to_cpu((__force __le##len)val); \ ++ else \ ++ return be##len ## _to_cpu((__force __be##len)val); \ + } + +-#define cpu_to_caam(len) \ +-static inline u##len cpu_to_caam##len(u##len val) \ +-{ \ +- if (caam_little_end) \ +- return cpu_to_le##len(val); \ +- else \ +- return cpu_to_be##len(val); \ ++#define cpu_to_caam(len) \ ++static inline u##len cpu_to_caam##len(u##len val) \ ++{ \ ++ if (caam_little_end) \ ++ return (__force u##len)cpu_to_le##len(val); \ ++ else \ ++ return (__force u##len)cpu_to_be##len(val); \ + } + + caam_to_cpu(16) +diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c +index 85820a2d69d4..987899610b46 100644 +--- a/drivers/dma/dma-jz4780.c ++++ b/drivers/dma/dma-jz4780.c +@@ -761,6 +761,11 @@ static int jz4780_dma_probe(struct platform_device *pdev) + struct resource *res; + int i, ret; + ++ if (!dev->of_node) { ++ dev_err(dev, "This driver must be probed from devicetree\n"); ++ return -EINVAL; ++ } ++ + jzdma = devm_kzalloc(dev, sizeof(*jzdma), GFP_KERNEL); + if (!jzdma) + return -ENOMEM; +diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c +index 4fa4c06c9edb..21a5708985bc 100644 +--- a/drivers/dma/ioat/init.c ++++ b/drivers/dma/ioat/init.c +@@ -1205,8 +1205,15 @@ static void ioat_shutdown(struct pci_dev *pdev) + + spin_lock_bh(&ioat_chan->prep_lock); + set_bit(IOAT_CHAN_DOWN, &ioat_chan->state); +- del_timer_sync(&ioat_chan->timer); + spin_unlock_bh(&ioat_chan->prep_lock); ++ /* ++ * Synchronization rule for del_timer_sync(): ++ * - The caller must not hold locks which would prevent ++ * completion of the timer's handler. ++ * So prep_lock cannot be held before calling it. ++ */ ++ del_timer_sync(&ioat_chan->timer); ++ + /* this should quiesce then reset */ + ioat_reset_hw(ioat_chan); + } +diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c +index 4cf0d4d0cecf..25610286979f 100644 +--- a/drivers/dma/ppc4xx/adma.c ++++ b/drivers/dma/ppc4xx/adma.c +@@ -4360,7 +4360,7 @@ static ssize_t enable_store(struct device_driver *dev, const char *buf, + } + static DRIVER_ATTR_RW(enable); + +-static ssize_t poly_store(struct device_driver *dev, char *buf) ++static ssize_t poly_show(struct device_driver *dev, char *buf) + { + ssize_t size = 0; + u32 reg; +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index 18aeabb1d5ee..e2addb2bca29 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -2200,6 +2200,15 @@ static struct amd64_family_type family_types[] = { + .dbam_to_cs = f17_base_addr_to_cs_size, + } + }, ++ [F17_M10H_CPUS] = { ++ .ctl_name = "F17h_M10h", ++ .f0_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F0, ++ .f6_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F6, ++ .ops = { ++ .early_channel_count = f17_early_channel_count, ++ .dbam_to_cs = f17_base_addr_to_cs_size, ++ } ++ }, + }; + + /* +@@ -3188,6 +3197,11 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) + break; + + case 0x17: ++ if (pvt->model >= 0x10 && pvt->model <= 0x2f) { ++ fam_type = &family_types[F17_M10H_CPUS]; ++ pvt->ops = &family_types[F17_M10H_CPUS].ops; ++ break; ++ } + fam_type = &family_types[F17_CPUS]; + pvt->ops = &family_types[F17_CPUS].ops; + break; +diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h +index 1d4b74e9a037..4242f8e39c18 100644 +--- a/drivers/edac/amd64_edac.h ++++ b/drivers/edac/amd64_edac.h +@@ -115,6 +115,8 @@ + #define PCI_DEVICE_ID_AMD_16H_M30H_NB_F2 0x1582 + #define PCI_DEVICE_ID_AMD_17H_DF_F0 0x1460 + #define PCI_DEVICE_ID_AMD_17H_DF_F6 0x1466 ++#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F0 0x15e8 ++#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F6 0x15ee + + /* + * Function 1 - Address Map +@@ -281,6 +283,7 @@ enum amd_families { + F16_CPUS, + F16_M30H_CPUS, + F17_CPUS, ++ F17_M10H_CPUS, + NUM_FAMILIES, + }; + +diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c +index 8e120bf60624..f1d19504a028 100644 +--- a/drivers/edac/i7core_edac.c ++++ b/drivers/edac/i7core_edac.c +@@ -1711,6 +1711,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, + u32 errnum = find_first_bit(&error, 32); + + if (uncorrected_error) { ++ core_err_cnt = 1; + if (ripv) + tp_event = HW_EVENT_ERR_FATAL; + else +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index 07726fb00321..72cea3cb8622 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -2888,6 +2888,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, + recoverable = GET_BITFIELD(m->status, 56, 56); + + if (uncorrected_error) { ++ core_err_cnt = 1; + if (ripv) { + type = "FATAL"; + tp_event = HW_EVENT_ERR_FATAL; +diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c +index fae095162c01..4ba92f1dd0f7 100644 +--- a/drivers/edac/skx_edac.c ++++ b/drivers/edac/skx_edac.c +@@ -668,7 +668,7 @@ sad_found: + break; + case 2: + lchan = (addr >> shift) % 2; +- lchan = (lchan << 1) | ~lchan; ++ lchan = (lchan << 1) | !lchan; + break; + case 3: + lchan = ((addr >> shift) % 2) << 1; +@@ -959,6 +959,7 @@ static void skx_mce_output_error(struct mem_ctl_info *mci, + recoverable = GET_BITFIELD(m->status, 56, 56); + + if (uncorrected_error) { ++ core_err_cnt = 1; + if (ripv) { + type = "FATAL"; + tp_event = HW_EVENT_ERR_FATAL; +diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c +index 19db5709ae28..898bb9abc41f 100644 +--- a/drivers/firmware/google/coreboot_table.c ++++ b/drivers/firmware/google/coreboot_table.c +@@ -110,7 +110,8 @@ int coreboot_table_init(struct device *dev, void __iomem *ptr) + + if (strncmp(header.signature, "LBIO", sizeof(header.signature))) { + pr_warn("coreboot_table: coreboot table missing or corrupt!\n"); +- return -ENODEV; ++ ret = -ENODEV; ++ goto out; + } + + ptr_entry = (void *)ptr_header + header.header_bytes; +@@ -137,7 +138,8 @@ int coreboot_table_init(struct device *dev, void __iomem *ptr) + + ptr_entry += entry.size; + } +- ++out: ++ iounmap(ptr); + return ret; + } + EXPORT_SYMBOL(coreboot_table_init); +@@ -146,7 +148,6 @@ int coreboot_table_exit(void) + { + if (ptr_header) { + bus_unregister(&coreboot_bus_type); +- iounmap(ptr_header); + ptr_header = NULL; + } + +diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c +index 16c7f9f49416..af936dcca659 100644 +--- a/drivers/gpio/gpio-brcmstb.c ++++ b/drivers/gpio/gpio-brcmstb.c +@@ -664,6 +664,18 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) + struct brcmstb_gpio_bank *bank; + struct gpio_chip *gc; + ++ /* ++ * If bank_width is 0, then there is an empty bank in the ++ * register block. Special handling for this case. ++ */ ++ if (bank_width == 0) { ++ dev_dbg(dev, "Width 0 found: Empty bank @ %d\n", ++ num_banks); ++ num_banks++; ++ gpio_base += MAX_GPIO_PER_BANK; ++ continue; ++ } ++ + bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL); + if (!bank) { + err = -ENOMEM; +@@ -740,9 +752,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) + goto fail; + } + +- dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n", +- num_banks, priv->gpio_base, gpio_base - 1); +- + if (priv->parent_wake_irq && need_wakeup_event) + pm_wakeup_event(dev, 0); + +diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c +index df30490da820..ea874fd033a5 100644 +--- a/drivers/gpio/gpio-mxs.c ++++ b/drivers/gpio/gpio-mxs.c +@@ -18,8 +18,6 @@ + #include + #include + #include +-/* FIXME: for gpio_get_value(), replace this by direct register read */ +-#include + #include + + #define MXS_SET 0x4 +@@ -86,7 +84,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) + port->both_edges &= ~pin_mask; + switch (type) { + case IRQ_TYPE_EDGE_BOTH: +- val = gpio_get_value(port->gc.base + d->hwirq); ++ val = port->gc.get(&port->gc, d->hwirq); + if (val) + edge = GPIO_INT_FALL_EDGE; + else +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index 2d45d1dd9554..643f5edd68fe 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -1446,8 +1446,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, + } + + /* The CEC module handles HDMI hotplug detection */ +- cec_np = of_find_compatible_node(np->parent, NULL, +- "mediatek,mt8173-cec"); ++ cec_np = of_get_compatible_child(np->parent, "mediatek,mt8173-cec"); + if (!cec_np) { + dev_err(dev, "Failed to find CEC node\n"); + return -EINVAL; +@@ -1457,8 +1456,10 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, + if (!cec_pdev) { + dev_err(hdmi->dev, "Waiting for CEC device %pOF\n", + cec_np); ++ of_node_put(cec_np); + return -EPROBE_DEFER; + } ++ of_node_put(cec_np); + hdmi->cec_dev = &cec_pdev->dev; + + /* +diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c +index cf2a18571d48..a132c37d7334 100644 +--- a/drivers/gpu/vga/vga_switcheroo.c ++++ b/drivers/gpu/vga/vga_switcheroo.c +@@ -380,6 +380,9 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, + mutex_unlock(&vgasr_mutex); + return -EINVAL; + } ++ /* notify if GPU has been already bound */ ++ if (ops->gpu_bound) ++ ops->gpu_bound(pdev, id); + } + mutex_unlock(&vgasr_mutex); + +diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c +index 23872d08308c..a746017fac17 100644 +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -512,14 +512,24 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, + if (cmd == HIDIOCGCOLLECTIONINDEX) { + if (uref->usage_index >= field->maxusage) + goto inval; ++ uref->usage_index = ++ array_index_nospec(uref->usage_index, ++ field->maxusage); + } else if (uref->usage_index >= field->report_count) + goto inval; + } + +- if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && +- (uref_multi->num_values > HID_MAX_MULTI_USAGES || +- uref->usage_index + uref_multi->num_values > field->report_count)) +- goto inval; ++ if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { ++ if (uref_multi->num_values > HID_MAX_MULTI_USAGES || ++ uref->usage_index + uref_multi->num_values > ++ field->report_count) ++ goto inval; ++ ++ uref->usage_index = ++ array_index_nospec(uref->usage_index, ++ field->report_count - ++ uref_multi->num_values); ++ } + + switch (cmd) { + case HIDIOCGUSAGE: +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index e0a06be5ef5c..5dd3a8245f0f 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -3335,6 +3335,7 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac) + + void wacom_setup_device_quirks(struct wacom *wacom) + { ++ struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom->wacom_wac.features; + + /* The pen and pad share the same interface on most devices */ +@@ -3464,6 +3465,24 @@ void wacom_setup_device_quirks(struct wacom *wacom) + + if (features->type == REMOTE) + features->device_type |= WACOM_DEVICETYPE_WL_MONITOR; ++ ++ /* HID descriptor for DTK-2451 / DTH-2452 claims to report lots ++ * of things it shouldn't. Lets fix up the damage... ++ */ ++ if (wacom->hdev->product == 0x382 || wacom->hdev->product == 0x37d) { ++ features->quirks &= ~WACOM_QUIRK_TOOLSERIAL; ++ __clear_bit(BTN_TOOL_BRUSH, wacom_wac->pen_input->keybit); ++ __clear_bit(BTN_TOOL_PENCIL, wacom_wac->pen_input->keybit); ++ __clear_bit(BTN_TOOL_AIRBRUSH, wacom_wac->pen_input->keybit); ++ __clear_bit(ABS_Z, wacom_wac->pen_input->absbit); ++ __clear_bit(ABS_DISTANCE, wacom_wac->pen_input->absbit); ++ __clear_bit(ABS_TILT_X, wacom_wac->pen_input->absbit); ++ __clear_bit(ABS_TILT_Y, wacom_wac->pen_input->absbit); ++ __clear_bit(ABS_WHEEL, wacom_wac->pen_input->absbit); ++ __clear_bit(ABS_MISC, wacom_wac->pen_input->absbit); ++ __clear_bit(MSC_SERIAL, wacom_wac->pen_input->mscbit); ++ __clear_bit(EV_MSC, wacom_wac->pen_input->evbit); ++ } + } + + int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 0f0e091c117c..c4a1ebcfffb6 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -606,16 +606,18 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) + bool perf_chn = vmbus_devs[dev_type].perf_device; + struct vmbus_channel *primary = channel->primary_channel; + int next_node; +- struct cpumask available_mask; ++ cpumask_var_t available_mask; + struct cpumask *alloced_mask; + + if ((vmbus_proto_version == VERSION_WS2008) || +- (vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) { ++ (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) || ++ !alloc_cpumask_var(&available_mask, GFP_KERNEL)) { + /* + * Prior to win8, all channel interrupts are + * delivered on cpu 0. + * Also if the channel is not a performance critical + * channel, bind it to cpu 0. ++ * In case alloc_cpumask_var() fails, bind it to cpu 0. + */ + channel->numa_node = 0; + channel->target_cpu = 0; +@@ -653,7 +655,7 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) + cpumask_clear(alloced_mask); + } + +- cpumask_xor(&available_mask, alloced_mask, ++ cpumask_xor(available_mask, alloced_mask, + cpumask_of_node(primary->numa_node)); + + cur_cpu = -1; +@@ -671,10 +673,10 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) + } + + while (true) { +- cur_cpu = cpumask_next(cur_cpu, &available_mask); ++ cur_cpu = cpumask_next(cur_cpu, available_mask); + if (cur_cpu >= nr_cpu_ids) { + cur_cpu = -1; +- cpumask_copy(&available_mask, ++ cpumask_copy(available_mask, + cpumask_of_node(primary->numa_node)); + continue; + } +@@ -704,6 +706,8 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) + + channel->target_cpu = cur_cpu; + channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu); ++ ++ free_cpumask_var(available_mask); + } + + static void vmbus_wait_for_unload(void) +diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c +index 7718e58dbda5..7688dab32f6e 100644 +--- a/drivers/hwmon/pmbus/pmbus.c ++++ b/drivers/hwmon/pmbus/pmbus.c +@@ -118,6 +118,8 @@ static int pmbus_identify(struct i2c_client *client, + } else { + info->pages = 1; + } ++ ++ pmbus_clear_faults(client); + } + + if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { +diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c +index 82c3754e21e3..2e2b5851139c 100644 +--- a/drivers/hwmon/pmbus/pmbus_core.c ++++ b/drivers/hwmon/pmbus/pmbus_core.c +@@ -2015,7 +2015,10 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, + if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK)) + client->flags |= I2C_CLIENT_PEC; + +- pmbus_clear_faults(client); ++ if (data->info->pages) ++ pmbus_clear_faults(client); ++ else ++ pmbus_clear_fault_page(client, -1); + + if (info->identify) { + ret = (*info->identify)(client, info); +diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c +index 7838af58f92d..9d611dd268e1 100644 +--- a/drivers/hwmon/pwm-fan.c ++++ b/drivers/hwmon/pwm-fan.c +@@ -290,9 +290,19 @@ static int pwm_fan_remove(struct platform_device *pdev) + static int pwm_fan_suspend(struct device *dev) + { + struct pwm_fan_ctx *ctx = dev_get_drvdata(dev); ++ struct pwm_args args; ++ int ret; ++ ++ pwm_get_args(ctx->pwm, &args); ++ ++ if (ctx->pwm_value) { ++ ret = pwm_config(ctx->pwm, 0, args.period); ++ if (ret < 0) ++ return ret; + +- if (ctx->pwm_value) + pwm_disable(ctx->pwm); ++ } ++ + return 0; + } + +diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c +index 306119eaf16a..0dad8626bcfb 100644 +--- a/drivers/hwtracing/coresight/coresight-etb10.c ++++ b/drivers/hwtracing/coresight/coresight-etb10.c +@@ -147,6 +147,10 @@ static int etb_enable(struct coresight_device *csdev, u32 mode) + if (val == CS_MODE_PERF) + return -EBUSY; + ++ /* Don't let perf disturb sysFS sessions */ ++ if (val == CS_MODE_SYSFS && mode == CS_MODE_PERF) ++ return -EBUSY; ++ + /* Nothing to do, the tracer is already enabled. */ + if (val == CS_MODE_SYSFS) + goto out; +diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c +index 44b516863c9d..75d2f73582a3 100644 +--- a/drivers/iio/adc/at91_adc.c ++++ b/drivers/iio/adc/at91_adc.c +@@ -248,12 +248,14 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) + struct iio_poll_func *pf = p; + struct iio_dev *idev = pf->indio_dev; + struct at91_adc_state *st = iio_priv(idev); ++ struct iio_chan_spec const *chan; + int i, j = 0; + + for (i = 0; i < idev->masklength; i++) { + if (!test_bit(i, idev->active_scan_mask)) + continue; +- st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i)); ++ chan = idev->channels + i; ++ st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, chan->channel)); + j++; + } + +@@ -279,6 +281,8 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev) + iio_trigger_poll(idev->trig); + } else { + st->last_value = at91_adc_readl(st, AT91_ADC_CHAN(st, st->chnb)); ++ /* Needed to ACK the DRDY interruption */ ++ at91_adc_readl(st, AT91_ADC_LCDR); + st->done = true; + wake_up_interruptible(&st->wq_data_avail); + } +diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c +index ea264fa9e567..929c617db364 100644 +--- a/drivers/iio/adc/fsl-imx25-gcq.c ++++ b/drivers/iio/adc/fsl-imx25-gcq.c +@@ -209,12 +209,14 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, + ret = of_property_read_u32(child, "reg", ®); + if (ret) { + dev_err(dev, "Failed to get reg property\n"); ++ of_node_put(child); + return ret; + } + + if (reg >= MX25_NUM_CFGS) { + dev_err(dev, + "reg value is greater than the number of available configuration registers\n"); ++ of_node_put(child); + return -EINVAL; + } + +@@ -228,6 +230,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, + if (IS_ERR(priv->vref[refp])) { + dev_err(dev, "Error, trying to use external voltage reference without a vref-%s regulator.", + mx25_gcq_refp_names[refp]); ++ of_node_put(child); + return PTR_ERR(priv->vref[refp]); + } + priv->channel_vref_mv[reg] = +@@ -240,6 +243,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, + break; + default: + dev_err(dev, "Invalid positive reference %d\n", refp); ++ of_node_put(child); + return -EINVAL; + } + +@@ -254,10 +258,12 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, + + if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp) { + dev_err(dev, "Invalid fsl,adc-refp property value\n"); ++ of_node_put(child); + return -EINVAL; + } + if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn) { + dev_err(dev, "Invalid fsl,adc-refn property value\n"); ++ of_node_put(child); + return -EINVAL; + } + +diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c +index bf4fc40ec84d..2f98cb2a3b96 100644 +--- a/drivers/iio/dac/ad5064.c ++++ b/drivers/iio/dac/ad5064.c +@@ -808,6 +808,40 @@ static int ad5064_set_config(struct ad5064_state *st, unsigned int val) + return ad5064_write(st, cmd, 0, val, 0); + } + ++static int ad5064_request_vref(struct ad5064_state *st, struct device *dev) ++{ ++ unsigned int i; ++ int ret; ++ ++ for (i = 0; i < ad5064_num_vref(st); ++i) ++ st->vref_reg[i].supply = ad5064_vref_name(st, i); ++ ++ if (!st->chip_info->internal_vref) ++ return devm_regulator_bulk_get(dev, ad5064_num_vref(st), ++ st->vref_reg); ++ ++ /* ++ * This assumes that when the regulator has an internal VREF ++ * there is only one external VREF connection, which is ++ * currently the case for all supported devices. ++ */ ++ st->vref_reg[0].consumer = devm_regulator_get_optional(dev, "vref"); ++ if (!IS_ERR(st->vref_reg[0].consumer)) ++ return 0; ++ ++ ret = PTR_ERR(st->vref_reg[0].consumer); ++ if (ret != -ENODEV) ++ return ret; ++ ++ /* If no external regulator was supplied use the internal VREF */ ++ st->use_internal_vref = true; ++ ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); ++ if (ret) ++ dev_err(dev, "Failed to enable internal vref: %d\n", ret); ++ ++ return ret; ++} ++ + static int ad5064_probe(struct device *dev, enum ad5064_type type, + const char *name, ad5064_write_func write) + { +@@ -828,22 +862,11 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, + st->dev = dev; + st->write = write; + +- for (i = 0; i < ad5064_num_vref(st); ++i) +- st->vref_reg[i].supply = ad5064_vref_name(st, i); ++ ret = ad5064_request_vref(st, dev); ++ if (ret) ++ return ret; + +- ret = devm_regulator_bulk_get(dev, ad5064_num_vref(st), +- st->vref_reg); +- if (ret) { +- if (!st->chip_info->internal_vref) +- return ret; +- st->use_internal_vref = true; +- ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); +- if (ret) { +- dev_err(dev, "Failed to enable internal vref: %d\n", +- ret); +- return ret; +- } +- } else { ++ if (!st->use_internal_vref) { + ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); + if (ret) + return ret; +diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c +index 6e39c27dca8e..4c533275d1f2 100644 +--- a/drivers/infiniband/core/cm.c ++++ b/drivers/infiniband/core/cm.c +@@ -3292,8 +3292,11 @@ static int cm_lap_handler(struct cm_work *work) + if (ret) + goto unlock; + +- cm_init_av_by_path(param->alternate_path, NULL, &cm_id_priv->alt_av, +- cm_id_priv); ++ ret = cm_init_av_by_path(param->alternate_path, NULL, ++ &cm_id_priv->alt_av, cm_id_priv); ++ if (ret) ++ goto unlock; ++ + cm_id_priv->id.lap_state = IB_CM_LAP_RCVD; + cm_id_priv->tid = lap_msg->hdr.tid; + ret = atomic_inc_and_test(&cm_id_priv->work_count); +diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c +index 7fd14ead7b37..ace40bb98624 100644 +--- a/drivers/infiniband/core/sysfs.c ++++ b/drivers/infiniband/core/sysfs.c +@@ -512,7 +512,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr, + ret = get_perf_mad(p->ibdev, p->port_num, tab_attr->attr_id, &data, + 40 + offset / 8, sizeof(data)); + if (ret < 0) +- return sprintf(buf, "N/A (no PMA)\n"); ++ return ret; + + switch (width) { + case 4: +@@ -1057,10 +1057,12 @@ static int add_port(struct ib_device *device, int port_num, + goto err_put; + } + +- p->pma_table = get_counter_table(device, port_num); +- ret = sysfs_create_group(&p->kobj, p->pma_table); +- if (ret) +- goto err_put_gid_attrs; ++ if (device->process_mad) { ++ p->pma_table = get_counter_table(device, port_num); ++ ret = sysfs_create_group(&p->kobj, p->pma_table); ++ if (ret) ++ goto err_put_gid_attrs; ++ } + + p->gid_group.name = "gids"; + p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len); +@@ -1173,7 +1175,8 @@ err_free_gid: + p->gid_group.attrs = NULL; + + err_remove_pma: +- sysfs_remove_group(&p->kobj, p->pma_table); ++ if (p->pma_table) ++ sysfs_remove_group(&p->kobj, p->pma_table); + + err_put_gid_attrs: + kobject_put(&p->gid_attr_group->kobj); +@@ -1285,7 +1288,9 @@ static void free_port_list_attributes(struct ib_device *device) + kfree(port->hw_stats); + free_hsag(&port->kobj, port->hw_stats_ag); + } +- sysfs_remove_group(p, port->pma_table); ++ ++ if (port->pma_table) ++ sysfs_remove_group(p, port->pma_table); + sysfs_remove_group(p, &port->pkey_group); + sysfs_remove_group(p, &port->gid_group); + sysfs_remove_group(&port->gid_attr_group->kobj, +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +index 6ad0d46ab879..249efa0a6aba 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c +@@ -360,7 +360,8 @@ void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq) + } + + /* Make sure the HW is stopped! */ +- bnxt_qplib_nq_stop_irq(nq, true); ++ if (nq->requested) ++ bnxt_qplib_nq_stop_irq(nq, true); + + if (nq->bar_reg_iomem) + iounmap(nq->bar_reg_iomem); +diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +index 2852d350ada1..6637df77d236 100644 +--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c ++++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +@@ -309,8 +309,17 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, + rcfw->aeq_handler(rcfw, qp_event, qp); + break; + default: +- /* Command Response */ +- spin_lock_irqsave(&cmdq->lock, flags); ++ /* ++ * Command Response ++ * cmdq->lock needs to be acquired to synchronie ++ * the command send and completion reaping. This function ++ * is always called with creq->lock held. Using ++ * the nested variant of spin_lock. ++ * ++ */ ++ ++ spin_lock_irqsave_nested(&cmdq->lock, flags, ++ SINGLE_DEPTH_NESTING); + cookie = le16_to_cpu(qp_event->cookie); + mcookie = qp_event->cookie; + blocked = cookie & RCFW_CMD_IS_BLOCKING; +diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c +index e22314837645..7df4a4fe4af4 100644 +--- a/drivers/infiniband/hw/mlx5/mr.c ++++ b/drivers/infiniband/hw/mlx5/mr.c +@@ -691,7 +691,6 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev) + init_completion(&ent->compl); + INIT_WORK(&ent->work, cache_work_func); + INIT_DELAYED_WORK(&ent->dwork, delayed_cache_work_func); +- queue_work(cache->wq, &ent->work); + + if (i > MR_CACHE_LAST_STD_ENTRY) { + mlx5_odp_init_mr_cache_entry(ent); +@@ -711,6 +710,7 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev) + ent->limit = dev->mdev->profile->mr_cache[i].limit; + else + ent->limit = 0; ++ queue_work(cache->wq, &ent->work); + } + + err = mlx5_mr_cache_debugfs_init(dev); +diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c +index 6cba2a02d11b..d53d954ac8af 100644 +--- a/drivers/infiniband/hw/mlx5/qp.c ++++ b/drivers/infiniband/hw/mlx5/qp.c +@@ -3243,7 +3243,9 @@ static bool modify_dci_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state new + int req = IB_QP_STATE; + int opt = 0; + +- if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) { ++ if (new_state == IB_QPS_RESET) { ++ return is_valid_mask(attr_mask, req, opt); ++ } else if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) { + req |= IB_QP_PKEY_INDEX | IB_QP_PORT; + return is_valid_mask(attr_mask, req, opt); + } else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_INIT) { +diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c +index aa5833318372..fc6c880756da 100644 +--- a/drivers/infiniband/sw/rxe/rxe_resp.c ++++ b/drivers/infiniband/sw/rxe/rxe_resp.c +@@ -682,6 +682,7 @@ static enum resp_states read_reply(struct rxe_qp *qp, + rxe_advance_resp_resource(qp); + + res->type = RXE_READ_MASK; ++ res->replay = 0; + + res->read.va = qp->resp.va; + res->read.va_org = qp->resp.va; +@@ -752,7 +753,8 @@ static enum resp_states read_reply(struct rxe_qp *qp, + state = RESPST_DONE; + } else { + qp->resp.res = NULL; +- qp->resp.opcode = -1; ++ if (!res->replay) ++ qp->resp.opcode = -1; + if (psn_compare(res->cur_psn, qp->resp.psn) >= 0) + qp->resp.psn = res->cur_psn; + state = RESPST_CLEANUP; +@@ -814,6 +816,7 @@ static enum resp_states execute(struct rxe_qp *qp, struct rxe_pkt_info *pkt) + + /* next expected psn, read handles this separately */ + qp->resp.psn = (pkt->psn + 1) & BTH_PSN_MASK; ++ qp->resp.ack_psn = qp->resp.psn; + + qp->resp.opcode = pkt->opcode; + qp->resp.status = IB_WC_SUCCESS; +@@ -1065,7 +1068,7 @@ static enum resp_states duplicate_request(struct rxe_qp *qp, + struct rxe_pkt_info *pkt) + { + enum resp_states rc; +- u32 prev_psn = (qp->resp.psn - 1) & BTH_PSN_MASK; ++ u32 prev_psn = (qp->resp.ack_psn - 1) & BTH_PSN_MASK; + + if (pkt->mask & RXE_SEND_MASK || + pkt->mask & RXE_WRITE_MASK) { +@@ -1108,6 +1111,7 @@ static enum resp_states duplicate_request(struct rxe_qp *qp, + res->state = (pkt->psn == res->first_psn) ? + rdatm_res_state_new : + rdatm_res_state_replay; ++ res->replay = 1; + + /* Reset the resource, except length. */ + res->read.va_org = iova; +diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h +index af1470d29391..332a16dad2a7 100644 +--- a/drivers/infiniband/sw/rxe/rxe_verbs.h ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.h +@@ -171,6 +171,7 @@ enum rdatm_res_state { + + struct resp_res { + int type; ++ int replay; + u32 first_psn; + u32 last_psn; + u32 cur_psn; +@@ -195,6 +196,7 @@ struct rxe_resp_info { + enum rxe_qp_state state; + u32 msn; + u32 psn; ++ u32 ack_psn; + int opcode; + int drop_msg; + int goto_error; +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c +index 3d5424f335cb..0428e01e8f69 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c +@@ -1438,11 +1438,15 @@ static void ipoib_cm_skb_reap(struct work_struct *work) + spin_unlock_irqrestore(&priv->lock, flags); + netif_tx_unlock_bh(dev); + +- if (skb->protocol == htons(ETH_P_IP)) ++ if (skb->protocol == htons(ETH_P_IP)) { ++ memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); ++ } + #if IS_ENABLED(CONFIG_IPV6) +- else if (skb->protocol == htons(ETH_P_IPV6)) ++ else if (skb->protocol == htons(ETH_P_IPV6)) { ++ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); ++ } + #endif + dev_kfree_skb_any(skb); + +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c +index e3d28f9ad9c0..30f840f874b3 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c +@@ -1880,6 +1880,8 @@ static int ipoib_parent_init(struct net_device *ndev) + sizeof(union ib_gid)); + + SET_NETDEV_DEV(priv->dev, priv->ca->dev.parent); ++ priv->dev->dev_port = priv->port - 1; ++ /* Let's set this one too for backwards compatibility. */ + priv->dev->dev_id = priv->port - 1; + + return 0; +diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c +index fd1b80ef9490..e7cbf4fcf61d 100644 +--- a/drivers/iommu/arm-smmu.c ++++ b/drivers/iommu/arm-smmu.c +@@ -469,6 +469,9 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size, + bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS; + void __iomem *reg = ARM_SMMU_CB(smmu_domain->smmu, cfg->cbndx); + ++ if (smmu_domain->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) ++ wmb(); ++ + if (stage1) { + reg += leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA; + +@@ -510,6 +513,9 @@ static void arm_smmu_tlb_inv_vmid_nosync(unsigned long iova, size_t size, + struct arm_smmu_domain *smmu_domain = cookie; + void __iomem *base = ARM_SMMU_GR0(smmu_domain->smmu); + ++ if (smmu_domain->smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) ++ wmb(); ++ + writel_relaxed(smmu_domain->cfg.vmid, base + ARM_SMMU_GR0_TLBIVMID); + } + +diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c +index b1b47a40a278..faa7d61b9d6c 100644 +--- a/drivers/irqchip/qcom-pdc.c ++++ b/drivers/irqchip/qcom-pdc.c +@@ -124,6 +124,7 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type) + break; + case IRQ_TYPE_EDGE_BOTH: + pdc_type = PDC_EDGE_DUAL; ++ type = IRQ_TYPE_EDGE_RISING; + break; + case IRQ_TYPE_LEVEL_HIGH: + pdc_type = PDC_LEVEL_HIGH; +diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c +index 00984b486fea..2940cdc87af1 100644 +--- a/drivers/lightnvm/pblk-core.c ++++ b/drivers/lightnvm/pblk-core.c +@@ -1539,13 +1539,14 @@ struct pblk_line *pblk_line_replace_data(struct pblk *pblk) + struct pblk_line *cur, *new = NULL; + unsigned int left_seblks; + +- cur = l_mg->data_line; + new = l_mg->data_next; + if (!new) + goto out; +- l_mg->data_line = new; + + spin_lock(&l_mg->free_lock); ++ cur = l_mg->data_line; ++ l_mg->data_line = new; ++ + pblk_line_setup_metadata(new, l_mg, &pblk->lm); + spin_unlock(&l_mg->free_lock); + +diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c +index e232e47e1353..df75d9caec45 100644 +--- a/drivers/lightnvm/pblk-recovery.c ++++ b/drivers/lightnvm/pblk-recovery.c +@@ -956,12 +956,14 @@ next: + } + } + +- spin_lock(&l_mg->free_lock); + if (!open_lines) { ++ spin_lock(&l_mg->free_lock); + WARN_ON_ONCE(!test_and_clear_bit(meta_line, + &l_mg->meta_bitmap)); ++ spin_unlock(&l_mg->free_lock); + pblk_line_replace_data(pblk); + } else { ++ spin_lock(&l_mg->free_lock); + /* Allocate next line for preparation */ + l_mg->data_next = pblk_line_get(pblk); + if (l_mg->data_next) { +@@ -969,8 +971,8 @@ next: + l_mg->data_next->type = PBLK_LINETYPE_DATA; + is_next = 1; + } ++ spin_unlock(&l_mg->free_lock); + } +- spin_unlock(&l_mg->free_lock); + + if (is_next) + pblk_line_erase(pblk, l_mg->data_next); +diff --git a/drivers/lightnvm/pblk-sysfs.c b/drivers/lightnvm/pblk-sysfs.c +index 9fc3dfa168b4..8d2ed510c04b 100644 +--- a/drivers/lightnvm/pblk-sysfs.c ++++ b/drivers/lightnvm/pblk-sysfs.c +@@ -262,8 +262,14 @@ static ssize_t pblk_sysfs_lines(struct pblk *pblk, char *page) + sec_in_line = l_mg->data_line->sec_in_line; + meta_weight = bitmap_weight(&l_mg->meta_bitmap, + PBLK_DATA_LINES); +- map_weight = bitmap_weight(l_mg->data_line->map_bitmap, ++ ++ spin_lock(&l_mg->data_line->lock); ++ if (l_mg->data_line->map_bitmap) ++ map_weight = bitmap_weight(l_mg->data_line->map_bitmap, + lm->sec_per_line); ++ else ++ map_weight = 0; ++ spin_unlock(&l_mg->data_line->lock); + } + spin_unlock(&l_mg->free_lock); + +diff --git a/drivers/lightnvm/pblk-write.c b/drivers/lightnvm/pblk-write.c +index ee774a86cf1e..879227d584e7 100644 +--- a/drivers/lightnvm/pblk-write.c ++++ b/drivers/lightnvm/pblk-write.c +@@ -417,12 +417,11 @@ int pblk_submit_meta_io(struct pblk *pblk, struct pblk_line *meta_line) + rqd->ppa_list[i] = addr_to_gen_ppa(pblk, paddr, id); + } + ++ spin_lock(&l_mg->close_lock); + emeta->mem += rq_len; +- if (emeta->mem >= lm->emeta_len[0]) { +- spin_lock(&l_mg->close_lock); ++ if (emeta->mem >= lm->emeta_len[0]) + list_del(&meta_line->list); +- spin_unlock(&l_mg->close_lock); +- } ++ spin_unlock(&l_mg->close_lock); + + pblk_down_page(pblk, rqd->ppa_list, rqd->nr_ppas); + +@@ -491,14 +490,15 @@ static struct pblk_line *pblk_should_submit_meta_io(struct pblk *pblk, + struct pblk_line *meta_line; + + spin_lock(&l_mg->close_lock); +-retry: + if (list_empty(&l_mg->emeta_list)) { + spin_unlock(&l_mg->close_lock); + return NULL; + } + meta_line = list_first_entry(&l_mg->emeta_list, struct pblk_line, list); +- if (meta_line->emeta->mem >= lm->emeta_len[0]) +- goto retry; ++ if (meta_line->emeta->mem >= lm->emeta_len[0]) { ++ spin_unlock(&l_mg->close_lock); ++ return NULL; ++ } + spin_unlock(&l_mg->close_lock); + + if (!pblk_valid_meta_ppa(pblk, meta_line, data_rqd)) +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 311e91b1a14f..256f18b67e8a 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -461,8 +461,11 @@ static int __init acpi_pcc_probe(void) + count = acpi_table_parse_entries_array(ACPI_SIG_PCCT, + sizeof(struct acpi_table_pcct), proc, + ACPI_PCCT_TYPE_RESERVED, MAX_PCC_SUBSPACES); +- if (count == 0 || count > MAX_PCC_SUBSPACES) { +- pr_warn("Invalid PCCT: %d PCC subspaces\n", count); ++ if (count <= 0 || count > MAX_PCC_SUBSPACES) { ++ if (count < 0) ++ pr_warn("Error parsing PCC subspaces from PCCT\n"); ++ else ++ pr_warn("Invalid PCCT: %d PCC subspaces\n", count); + return -EINVAL; + } + +diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c +index e7d4817681f2..3f4211b5cd33 100644 +--- a/drivers/md/bcache/btree.c ++++ b/drivers/md/bcache/btree.c +@@ -2434,7 +2434,7 @@ static int refill_keybuf_fn(struct btree_op *op, struct btree *b, + struct keybuf *buf = refill->buf; + int ret = MAP_CONTINUE; + +- if (bkey_cmp(k, refill->end) >= 0) { ++ if (bkey_cmp(k, refill->end) > 0) { + ret = MAP_DONE; + goto out; + } +diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c +index 51be355a3309..22944aa7d8e5 100644 +--- a/drivers/md/bcache/request.c ++++ b/drivers/md/bcache/request.c +@@ -850,7 +850,7 @@ static void cached_dev_read_done_bh(struct closure *cl) + + bch_mark_cache_accounting(s->iop.c, s->d, + !s->cache_missed, s->iop.bypass); +- trace_bcache_read(s->orig_bio, !s->cache_miss, s->iop.bypass); ++ trace_bcache_read(s->orig_bio, !s->cache_missed, s->iop.bypass); + + if (s->iop.status) + continue_at_nobarrier(cl, cached_dev_read_error, bcache_wq); +@@ -1218,6 +1218,9 @@ static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode, + { + struct cached_dev *dc = container_of(d, struct cached_dev, disk); + ++ if (dc->io_disable) ++ return -EIO; ++ + return __blkdev_driver_ioctl(dc->bdev, mode, cmd, arg); + } + +diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c +index 30ba9aeb5ee8..03bb5cee2b83 100644 +--- a/drivers/md/bcache/super.c ++++ b/drivers/md/bcache/super.c +@@ -643,10 +643,6 @@ static int ioctl_dev(struct block_device *b, fmode_t mode, + unsigned int cmd, unsigned long arg) + { + struct bcache_device *d = b->bd_disk->private_data; +- struct cached_dev *dc = container_of(d, struct cached_dev, disk); +- +- if (dc->io_disable) +- return -EIO; + + return d->ioctl(d, mode, cmd, arg); + } +@@ -1152,11 +1148,12 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c, + } + + if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) { +- bch_sectors_dirty_init(&dc->disk); + atomic_set(&dc->has_dirty, 1); + bch_writeback_queue(dc); + } + ++ bch_sectors_dirty_init(&dc->disk); ++ + bch_cached_dev_run(dc); + bcache_device_link(&dc->disk, c, "bdev"); + atomic_inc(&c->attached_dev_nr); +diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c +index 150cf4f4cf74..26f035a0c5b9 100644 +--- a/drivers/md/bcache/sysfs.c ++++ b/drivers/md/bcache/sysfs.c +@@ -285,6 +285,7 @@ STORE(__cached_dev) + 1, WRITEBACK_RATE_UPDATE_SECS_MAX); + d_strtoul(writeback_rate_i_term_inverse); + d_strtoul_nonzero(writeback_rate_p_term_inverse); ++ d_strtoul_nonzero(writeback_rate_minimum); + + sysfs_strtoul_clamp(io_error_limit, dc->error_limit, 0, INT_MAX); + +@@ -412,6 +413,7 @@ static struct attribute *bch_cached_dev_files[] = { + &sysfs_writeback_rate_update_seconds, + &sysfs_writeback_rate_i_term_inverse, + &sysfs_writeback_rate_p_term_inverse, ++ &sysfs_writeback_rate_minimum, + &sysfs_writeback_rate_debug, + &sysfs_errors, + &sysfs_io_error_limit, +diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c +index b810ea77e6b1..f666778ad237 100644 +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1720,8 +1720,7 @@ static void free_params(struct dm_ioctl *param, size_t param_size, int param_fla + } + + static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel, +- int ioctl_flags, +- struct dm_ioctl **param, int *param_flags) ++ int ioctl_flags, struct dm_ioctl **param, int *param_flags) + { + struct dm_ioctl *dmi; + int secure_data; +@@ -1762,18 +1761,13 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern + + *param_flags |= DM_PARAMS_MALLOC; + +- if (copy_from_user(dmi, user, param_kernel->data_size)) +- goto bad; ++ /* Copy from param_kernel (which was already copied from user) */ ++ memcpy(dmi, param_kernel, minimum_data_size); + +-data_copied: +- /* +- * Abort if something changed the ioctl data while it was being copied. +- */ +- if (dmi->data_size != param_kernel->data_size) { +- DMERR("rejecting ioctl: data size modified while processing parameters"); ++ if (copy_from_user(&dmi->data, (char __user *)user + minimum_data_size, ++ param_kernel->data_size - minimum_data_size)) + goto bad; +- } +- ++data_copied: + /* Wipe the user buffer so we do not return it to userspace */ + if (secure_data && clear_user(user, param_kernel->data_size)) + goto bad; +diff --git a/drivers/md/dm-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c +index 969954915566..fa68336560c3 100644 +--- a/drivers/md/dm-zoned-metadata.c ++++ b/drivers/md/dm-zoned-metadata.c +@@ -99,7 +99,7 @@ struct dmz_mblock { + struct rb_node node; + struct list_head link; + sector_t no; +- atomic_t ref; ++ unsigned int ref; + unsigned long state; + struct page *page; + void *data; +@@ -296,7 +296,7 @@ static struct dmz_mblock *dmz_alloc_mblock(struct dmz_metadata *zmd, + + RB_CLEAR_NODE(&mblk->node); + INIT_LIST_HEAD(&mblk->link); +- atomic_set(&mblk->ref, 0); ++ mblk->ref = 0; + mblk->state = 0; + mblk->no = mblk_no; + mblk->data = page_address(mblk->page); +@@ -339,10 +339,11 @@ static void dmz_insert_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk) + } + + /* +- * Lookup a metadata block in the rbtree. ++ * Lookup a metadata block in the rbtree. If the block is found, increment ++ * its reference count. + */ +-static struct dmz_mblock *dmz_lookup_mblock(struct dmz_metadata *zmd, +- sector_t mblk_no) ++static struct dmz_mblock *dmz_get_mblock_fast(struct dmz_metadata *zmd, ++ sector_t mblk_no) + { + struct rb_root *root = &zmd->mblk_rbtree; + struct rb_node *node = root->rb_node; +@@ -350,8 +351,17 @@ static struct dmz_mblock *dmz_lookup_mblock(struct dmz_metadata *zmd, + + while (node) { + mblk = container_of(node, struct dmz_mblock, node); +- if (mblk->no == mblk_no) ++ if (mblk->no == mblk_no) { ++ /* ++ * If this is the first reference to the block, ++ * remove it from the LRU list. ++ */ ++ mblk->ref++; ++ if (mblk->ref == 1 && ++ !test_bit(DMZ_META_DIRTY, &mblk->state)) ++ list_del_init(&mblk->link); + return mblk; ++ } + node = (mblk->no < mblk_no) ? node->rb_left : node->rb_right; + } + +@@ -382,32 +392,47 @@ static void dmz_mblock_bio_end_io(struct bio *bio) + } + + /* +- * Read a metadata block from disk. ++ * Read an uncached metadata block from disk and add it to the cache. + */ +-static struct dmz_mblock *dmz_fetch_mblock(struct dmz_metadata *zmd, +- sector_t mblk_no) ++static struct dmz_mblock *dmz_get_mblock_slow(struct dmz_metadata *zmd, ++ sector_t mblk_no) + { +- struct dmz_mblock *mblk; ++ struct dmz_mblock *mblk, *m; + sector_t block = zmd->sb[zmd->mblk_primary].block + mblk_no; + struct bio *bio; + +- /* Get block and insert it */ ++ /* Get a new block and a BIO to read it */ + mblk = dmz_alloc_mblock(zmd, mblk_no); + if (!mblk) + return NULL; + +- spin_lock(&zmd->mblk_lock); +- atomic_inc(&mblk->ref); +- set_bit(DMZ_META_READING, &mblk->state); +- dmz_insert_mblock(zmd, mblk); +- spin_unlock(&zmd->mblk_lock); +- + bio = bio_alloc(GFP_NOIO, 1); + if (!bio) { + dmz_free_mblock(zmd, mblk); + return NULL; + } + ++ spin_lock(&zmd->mblk_lock); ++ ++ /* ++ * Make sure that another context did not start reading ++ * the block already. ++ */ ++ m = dmz_get_mblock_fast(zmd, mblk_no); ++ if (m) { ++ spin_unlock(&zmd->mblk_lock); ++ dmz_free_mblock(zmd, mblk); ++ bio_put(bio); ++ return m; ++ } ++ ++ mblk->ref++; ++ set_bit(DMZ_META_READING, &mblk->state); ++ dmz_insert_mblock(zmd, mblk); ++ ++ spin_unlock(&zmd->mblk_lock); ++ ++ /* Submit read BIO */ + bio->bi_iter.bi_sector = dmz_blk2sect(block); + bio_set_dev(bio, zmd->dev->bdev); + bio->bi_private = mblk; +@@ -484,7 +509,8 @@ static void dmz_release_mblock(struct dmz_metadata *zmd, + + spin_lock(&zmd->mblk_lock); + +- if (atomic_dec_and_test(&mblk->ref)) { ++ mblk->ref--; ++ if (mblk->ref == 0) { + if (test_bit(DMZ_META_ERROR, &mblk->state)) { + rb_erase(&mblk->node, &zmd->mblk_rbtree); + dmz_free_mblock(zmd, mblk); +@@ -508,18 +534,12 @@ static struct dmz_mblock *dmz_get_mblock(struct dmz_metadata *zmd, + + /* Check rbtree */ + spin_lock(&zmd->mblk_lock); +- mblk = dmz_lookup_mblock(zmd, mblk_no); +- if (mblk) { +- /* Cache hit: remove block from LRU list */ +- if (atomic_inc_return(&mblk->ref) == 1 && +- !test_bit(DMZ_META_DIRTY, &mblk->state)) +- list_del_init(&mblk->link); +- } ++ mblk = dmz_get_mblock_fast(zmd, mblk_no); + spin_unlock(&zmd->mblk_lock); + + if (!mblk) { + /* Cache miss: read the block from disk */ +- mblk = dmz_fetch_mblock(zmd, mblk_no); ++ mblk = dmz_get_mblock_slow(zmd, mblk_no); + if (!mblk) + return ERR_PTR(-ENOMEM); + } +@@ -753,7 +773,7 @@ int dmz_flush_metadata(struct dmz_metadata *zmd) + + spin_lock(&zmd->mblk_lock); + clear_bit(DMZ_META_DIRTY, &mblk->state); +- if (atomic_read(&mblk->ref) == 0) ++ if (mblk->ref == 0) + list_add_tail(&mblk->link, &zmd->mblk_lru_list); + spin_unlock(&zmd->mblk_lock); + } +@@ -2308,7 +2328,7 @@ static void dmz_cleanup_metadata(struct dmz_metadata *zmd) + mblk = list_first_entry(&zmd->mblk_dirty_list, + struct dmz_mblock, link); + dmz_dev_warn(zmd->dev, "mblock %llu still in dirty list (ref %u)", +- (u64)mblk->no, atomic_read(&mblk->ref)); ++ (u64)mblk->no, mblk->ref); + list_del_init(&mblk->link); + rb_erase(&mblk->node, &zmd->mblk_rbtree); + dmz_free_mblock(zmd, mblk); +@@ -2326,8 +2346,8 @@ static void dmz_cleanup_metadata(struct dmz_metadata *zmd) + root = &zmd->mblk_rbtree; + rbtree_postorder_for_each_entry_safe(mblk, next, root, node) { + dmz_dev_warn(zmd->dev, "mblock %llu ref %u still in rbtree", +- (u64)mblk->no, atomic_read(&mblk->ref)); +- atomic_set(&mblk->ref, 0); ++ (u64)mblk->no, mblk->ref); ++ mblk->ref = 0; + dmz_free_mblock(zmd, mblk); + } + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 63ceabb4e020..8668793262d0 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -452,10 +452,11 @@ static void md_end_flush(struct bio *fbio) + rdev_dec_pending(rdev, mddev); + + if (atomic_dec_and_test(&fi->flush_pending)) { +- if (bio->bi_iter.bi_size == 0) ++ if (bio->bi_iter.bi_size == 0) { + /* an empty barrier - all done */ + bio_endio(bio); +- else { ++ mempool_free(fi, mddev->flush_pool); ++ } else { + INIT_WORK(&fi->flush_work, submit_flushes); + queue_work(md_wq, &fi->flush_work); + } +@@ -509,10 +510,11 @@ void md_flush_request(struct mddev *mddev, struct bio *bio) + rcu_read_unlock(); + + if (atomic_dec_and_test(&fi->flush_pending)) { +- if (bio->bi_iter.bi_size == 0) ++ if (bio->bi_iter.bi_size == 0) { + /* an empty barrier - all done */ + bio_endio(bio); +- else { ++ mempool_free(fi, mddev->flush_pool); ++ } else { + INIT_WORK(&fi->flush_work, submit_flushes); + queue_work(md_wq, &fi->flush_work); + } +@@ -5904,14 +5906,6 @@ static void __md_stop(struct mddev *mddev) + mddev->to_remove = &md_redundancy_group; + module_put(pers->owner); + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); +-} +- +-void md_stop(struct mddev *mddev) +-{ +- /* stop the array and free an attached data structures. +- * This is called from dm-raid +- */ +- __md_stop(mddev); + if (mddev->flush_bio_pool) { + mempool_destroy(mddev->flush_bio_pool); + mddev->flush_bio_pool = NULL; +@@ -5920,6 +5914,14 @@ void md_stop(struct mddev *mddev) + mempool_destroy(mddev->flush_pool); + mddev->flush_pool = NULL; + } ++} ++ ++void md_stop(struct mddev *mddev) ++{ ++ /* stop the array and free an attached data structures. ++ * This is called from dm-raid ++ */ ++ __md_stop(mddev); + bioset_exit(&mddev->bio_set); + bioset_exit(&mddev->sync_set); + } +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 4e990246225e..1d54109071cc 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1734,6 +1734,7 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev) + */ + if (rdev->saved_raid_disk >= 0 && + rdev->saved_raid_disk >= first && ++ rdev->saved_raid_disk < conf->raid_disks && + conf->mirrors[rdev->saved_raid_disk].rdev == NULL) + first = last = rdev->saved_raid_disk; + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index d6f7978b4449..811427e53126 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1808,6 +1808,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) + first = last = rdev->raid_disk; + + if (rdev->saved_raid_disk >= first && ++ rdev->saved_raid_disk < conf->geo.raid_disks && + conf->mirrors[rdev->saved_raid_disk].rdev == NULL) + mirror = rdev->saved_raid_disk; + else +diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c +index 030b2602faf0..dd8bad74a1f0 100644 +--- a/drivers/media/cec/cec-adap.c ++++ b/drivers/media/cec/cec-adap.c +@@ -341,7 +341,7 @@ static void cec_data_completed(struct cec_data *data) + * + * This function is called with adap->lock held. + */ +-static void cec_data_cancel(struct cec_data *data) ++static void cec_data_cancel(struct cec_data *data, u8 tx_status) + { + /* + * It's either the current transmit, or it is a pending +@@ -356,13 +356,11 @@ static void cec_data_cancel(struct cec_data *data) + } + + if (data->msg.tx_status & CEC_TX_STATUS_OK) { +- /* Mark the canceled RX as a timeout */ + data->msg.rx_ts = ktime_get_ns(); +- data->msg.rx_status = CEC_RX_STATUS_TIMEOUT; ++ data->msg.rx_status = CEC_RX_STATUS_ABORTED; + } else { +- /* Mark the canceled TX as an error */ + data->msg.tx_ts = ktime_get_ns(); +- data->msg.tx_status |= CEC_TX_STATUS_ERROR | ++ data->msg.tx_status |= tx_status | + CEC_TX_STATUS_MAX_RETRIES; + data->msg.tx_error_cnt++; + data->attempts = 0; +@@ -390,15 +388,15 @@ static void cec_flush(struct cec_adapter *adap) + while (!list_empty(&adap->transmit_queue)) { + data = list_first_entry(&adap->transmit_queue, + struct cec_data, list); +- cec_data_cancel(data); ++ cec_data_cancel(data, CEC_TX_STATUS_ABORTED); + } + if (adap->transmitting) +- cec_data_cancel(adap->transmitting); ++ cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED); + + /* Cancel the pending timeout work. */ + list_for_each_entry_safe(data, n, &adap->wait_queue, list) { + if (cancel_delayed_work(&data->work)) +- cec_data_cancel(data); ++ cec_data_cancel(data, CEC_TX_STATUS_OK); + /* + * If cancel_delayed_work returned false, then + * the cec_wait_timeout function is running, +@@ -474,12 +472,13 @@ int cec_thread_func(void *_adap) + * so much traffic on the bus that the adapter was + * unable to transmit for CEC_XFER_TIMEOUT_MS (2.1s). + */ +- dprintk(1, "%s: message %*ph timed out\n", __func__, ++ pr_warn("cec-%s: message %*ph timed out\n", adap->name, + adap->transmitting->msg.len, + adap->transmitting->msg.msg); + adap->tx_timeouts++; + /* Just give up on this. */ +- cec_data_cancel(adap->transmitting); ++ cec_data_cancel(adap->transmitting, ++ CEC_TX_STATUS_TIMEOUT); + goto unlock; + } + +@@ -514,9 +513,11 @@ int cec_thread_func(void *_adap) + if (data->attempts) { + /* should be >= 3 data bit periods for a retry */ + signal_free_time = CEC_SIGNAL_FREE_TIME_RETRY; +- } else if (data->new_initiator) { ++ } else if (adap->last_initiator != ++ cec_msg_initiator(&data->msg)) { + /* should be >= 5 data bit periods for new initiator */ + signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR; ++ adap->last_initiator = cec_msg_initiator(&data->msg); + } else { + /* + * should be >= 7 data bit periods for sending another +@@ -530,7 +531,7 @@ int cec_thread_func(void *_adap) + /* Tell the adapter to transmit, cancel on error */ + if (adap->ops->adap_transmit(adap, data->attempts, + signal_free_time, &data->msg)) +- cec_data_cancel(data); ++ cec_data_cancel(data, CEC_TX_STATUS_ABORTED); + + unlock: + mutex_unlock(&adap->lock); +@@ -701,9 +702,6 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + struct cec_fh *fh, bool block) + { + struct cec_data *data; +- u8 last_initiator = 0xff; +- unsigned int timeout; +- int res = 0; + + msg->rx_ts = 0; + msg->tx_ts = 0; +@@ -813,23 +811,6 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + data->adap = adap; + data->blocking = block; + +- /* +- * Determine if this message follows a message from the same +- * initiator. Needed to determine the free signal time later on. +- */ +- if (msg->len > 1) { +- if (!(list_empty(&adap->transmit_queue))) { +- const struct cec_data *last; +- +- last = list_last_entry(&adap->transmit_queue, +- const struct cec_data, list); +- last_initiator = cec_msg_initiator(&last->msg); +- } else if (adap->transmitting) { +- last_initiator = +- cec_msg_initiator(&adap->transmitting->msg); +- } +- } +- data->new_initiator = last_initiator != cec_msg_initiator(msg); + init_completion(&data->c); + INIT_DELAYED_WORK(&data->work, cec_wait_timeout); + +@@ -845,48 +826,23 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, + if (!block) + return 0; + +- /* +- * If we don't get a completion before this time something is really +- * wrong and we time out. +- */ +- timeout = CEC_XFER_TIMEOUT_MS; +- /* Add the requested timeout if we have to wait for a reply as well */ +- if (msg->timeout) +- timeout += msg->timeout; +- + /* + * Release the lock and wait, retake the lock afterwards. + */ + mutex_unlock(&adap->lock); +- res = wait_for_completion_killable_timeout(&data->c, +- msecs_to_jiffies(timeout)); ++ wait_for_completion_killable(&data->c); ++ if (!data->completed) ++ cancel_delayed_work_sync(&data->work); + mutex_lock(&adap->lock); + +- if (data->completed) { +- /* The transmit completed (possibly with an error) */ +- *msg = data->msg; +- kfree(data); +- return 0; +- } +- /* +- * The wait for completion timed out or was interrupted, so mark this +- * as non-blocking and disconnect from the filehandle since it is +- * still 'in flight'. When it finally completes it will just drop the +- * result silently. +- */ +- data->blocking = false; +- if (data->fh) +- list_del(&data->xfer_list); +- data->fh = NULL; ++ /* Cancel the transmit if it was interrupted */ ++ if (!data->completed) ++ cec_data_cancel(data, CEC_TX_STATUS_ABORTED); + +- if (res == 0) { /* timed out */ +- /* Check if the reply or the transmit failed */ +- if (msg->timeout && (msg->tx_status & CEC_TX_STATUS_OK)) +- msg->rx_status = CEC_RX_STATUS_TIMEOUT; +- else +- msg->tx_status = CEC_TX_STATUS_MAX_RETRIES; +- } +- return res > 0 ? 0 : res; ++ /* The transmit completed (possibly with an error) */ ++ *msg = data->msg; ++ kfree(data); ++ return 0; + } + + /* Helper function to be used by drivers and this framework. */ +@@ -1044,6 +1000,8 @@ void cec_received_msg_ts(struct cec_adapter *adap, + mutex_lock(&adap->lock); + dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); + ++ adap->last_initiator = 0xff; ++ + /* Check if this message was for us (directed or broadcast). */ + if (!cec_msg_is_broadcast(msg)) + valid_la = cec_has_log_addr(adap, msg_dest); +@@ -1506,6 +1464,8 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) + } + + mutex_lock(&adap->devnode.lock); ++ adap->last_initiator = 0xff; ++ + if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && + adap->ops->adap_enable(adap, true)) { + mutex_unlock(&adap->devnode.lock); +diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c +index b6536bbad530..4961573850d5 100644 +--- a/drivers/media/cec/cec-api.c ++++ b/drivers/media/cec/cec-api.c +@@ -101,6 +101,23 @@ static long cec_adap_g_phys_addr(struct cec_adapter *adap, + return 0; + } + ++static int cec_validate_phys_addr(u16 phys_addr) ++{ ++ int i; ++ ++ if (phys_addr == CEC_PHYS_ADDR_INVALID) ++ return 0; ++ for (i = 0; i < 16; i += 4) ++ if (phys_addr & (0xf << i)) ++ break; ++ if (i == 16) ++ return 0; ++ for (i += 4; i < 16; i += 4) ++ if ((phys_addr & (0xf << i)) == 0) ++ return -EINVAL; ++ return 0; ++} ++ + static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh, + bool block, __u16 __user *parg) + { +@@ -112,7 +129,7 @@ static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh, + if (copy_from_user(&phys_addr, parg, sizeof(phys_addr))) + return -EFAULT; + +- err = cec_phys_addr_validate(phys_addr, NULL, NULL); ++ err = cec_validate_phys_addr(phys_addr); + if (err) + return err; + mutex_lock(&adap->lock); +diff --git a/drivers/media/cec/cec-edid.c b/drivers/media/cec/cec-edid.c +index ec72ac1c0b91..f587e8eaefd8 100644 +--- a/drivers/media/cec/cec-edid.c ++++ b/drivers/media/cec/cec-edid.c +@@ -10,66 +10,6 @@ + #include + #include + +-/* +- * This EDID is expected to be a CEA-861 compliant, which means that there are +- * at least two blocks and one or more of the extensions blocks are CEA-861 +- * blocks. +- * +- * The returned location is guaranteed to be < size - 1. +- */ +-static unsigned int cec_get_edid_spa_location(const u8 *edid, unsigned int size) +-{ +- unsigned int blocks = size / 128; +- unsigned int block; +- u8 d; +- +- /* Sanity check: at least 2 blocks and a multiple of the block size */ +- if (blocks < 2 || size % 128) +- return 0; +- +- /* +- * If there are fewer extension blocks than the size, then update +- * 'blocks'. It is allowed to have more extension blocks than the size, +- * since some hardware can only read e.g. 256 bytes of the EDID, even +- * though more blocks are present. The first CEA-861 extension block +- * should normally be in block 1 anyway. +- */ +- if (edid[0x7e] + 1 < blocks) +- blocks = edid[0x7e] + 1; +- +- for (block = 1; block < blocks; block++) { +- unsigned int offset = block * 128; +- +- /* Skip any non-CEA-861 extension blocks */ +- if (edid[offset] != 0x02 || edid[offset + 1] != 0x03) +- continue; +- +- /* search Vendor Specific Data Block (tag 3) */ +- d = edid[offset + 2] & 0x7f; +- /* Check if there are Data Blocks */ +- if (d <= 4) +- continue; +- if (d > 4) { +- unsigned int i = offset + 4; +- unsigned int end = offset + d; +- +- /* Note: 'end' is always < 'size' */ +- do { +- u8 tag = edid[i] >> 5; +- u8 len = edid[i] & 0x1f; +- +- if (tag == 3 && len >= 5 && i + len <= end && +- edid[i + 1] == 0x03 && +- edid[i + 2] == 0x0c && +- edid[i + 3] == 0x00) +- return i + 4; +- i += len + 1; +- } while (i < end); +- } +- } +- return 0; +-} +- + u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, + unsigned int *offset) + { +diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c +index 3a3dc23c560c..a4341205c197 100644 +--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c ++++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c +@@ -602,14 +602,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][5] = { 3138, 657, 810 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][6] = { 731, 680, 3048 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][1] = { 3046, 3054, 886 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][2] = { 0, 3058, 3031 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][3] = { 360, 3079, 877 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][4] = { 3103, 587, 3027 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][5] = { 3116, 723, 861 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][6] = { 789, 744, 3025 }, +- [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][1] = { 3046, 3054, 886 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][2] = { 0, 3058, 3031 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][3] = { 360, 3079, 877 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][4] = { 3103, 587, 3027 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][5] = { 3116, 723, 861 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][6] = { 789, 744, 3025 }, ++ [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2941, 2950, 546 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][2] = { 0, 2954, 2924 }, +@@ -658,14 +658,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][5] = { 3138, 657, 810 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][6] = { 731, 680, 3048 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][1] = { 3046, 3054, 886 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][2] = { 0, 3058, 3031 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][3] = { 360, 3079, 877 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][4] = { 3103, 587, 3027 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][5] = { 3116, 723, 861 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][6] = { 789, 744, 3025 }, +- [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][1] = { 3046, 3054, 886 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][2] = { 0, 3058, 3031 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][3] = { 360, 3079, 877 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][4] = { 3103, 587, 3027 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][5] = { 3116, 723, 861 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][6] = { 789, 744, 3025 }, ++ [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2941, 2950, 546 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][2] = { 0, 2954, 2924 }, +@@ -714,14 +714,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][5] = { 3056, 800, 800 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3056 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 851 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][2] = { 851, 3033, 3033 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][3] = { 851, 3033, 851 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][4] = { 3033, 851, 3033 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][5] = { 3033, 851, 851 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3033 }, +- [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 851 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][2] = { 851, 3033, 3033 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][3] = { 851, 3033, 851 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][4] = { 3033, 851, 3033 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][5] = { 3033, 851, 851 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3033 }, ++ [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 507 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][2] = { 507, 2926, 2926 }, +@@ -770,14 +770,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][5] = { 2599, 901, 909 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][6] = { 991, 0, 2966 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][1] = { 2989, 3120, 1180 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][2] = { 1913, 3011, 3009 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][3] = { 1836, 3099, 1105 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][4] = { 2627, 413, 2966 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][5] = { 2576, 943, 951 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][6] = { 1026, 0, 2942 }, +- [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][1] = { 2989, 3120, 1180 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][2] = { 1913, 3011, 3009 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][3] = { 1836, 3099, 1105 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][4] = { 2627, 413, 2966 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][5] = { 2576, 943, 951 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][6] = { 1026, 0, 2942 }, ++ [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2879, 3022, 874 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][2] = { 1688, 2903, 2901 }, +@@ -826,14 +826,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][5] = { 3001, 800, 799 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3071 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 776 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][2] = { 1068, 3033, 3033 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][3] = { 1068, 3033, 776 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][4] = { 2977, 851, 3048 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][5] = { 2977, 851, 851 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3048 }, +- [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 776 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][2] = { 1068, 3033, 3033 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][3] = { 1068, 3033, 776 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][4] = { 2977, 851, 3048 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][5] = { 2977, 851, 851 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3048 }, ++ [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 423 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][2] = { 749, 2926, 2926 }, +@@ -882,14 +882,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][5] = { 3056, 800, 800 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3056 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 851 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][2] = { 851, 3033, 3033 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][3] = { 851, 3033, 851 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][4] = { 3033, 851, 3033 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][5] = { 3033, 851, 851 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3033 }, +- [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 851 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][2] = { 851, 3033, 3033 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][3] = { 851, 3033, 851 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][4] = { 3033, 851, 3033 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][5] = { 3033, 851, 851 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3033 }, ++ [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 507 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 507, 2926, 2926 }, +@@ -922,62 +922,62 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1812, 886, 886 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1812 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][3] = { 1622, 2939, 781 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][4] = { 2502, 547, 2881 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][5] = { 2502, 547, 547 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][6] = { 547, 547, 2881 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3056 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][1] = { 3056, 3056, 1031 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][2] = { 1838, 3056, 3056 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][3] = { 1838, 3056, 1031 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][4] = { 2657, 800, 3002 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][5] = { 2657, 800, 800 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3002 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 1063 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][2] = { 1828, 3033, 3033 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][3] = { 1828, 3033, 1063 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][4] = { 2633, 851, 2979 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][5] = { 2633, 851, 851 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 2979 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 744 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 1594, 2926, 2926 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][3] = { 1594, 2926, 744 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][4] = { 2484, 507, 2867 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][5] = { 2484, 507, 507 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][6] = { 507, 507, 2867 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][1] = { 2125, 2125, 212 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][2] = { 698, 2125, 2125 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][3] = { 698, 2125, 212 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][4] = { 1557, 130, 2043 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 1812, 1812, 1812 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 1812, 1812, 1022 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 1402, 1812, 1812 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 1402, 1812, 1022 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 1692, 886, 1797 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1692, 886, 886 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1797 }, +- [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][3] = { 1622, 2939, 781 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][4] = { 2502, 547, 2881 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][5] = { 2502, 547, 547 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][6] = { 547, 547, 2881 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3056 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][1] = { 3056, 3056, 1031 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][2] = { 1838, 3056, 3056 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][3] = { 1838, 3056, 1031 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][4] = { 2657, 800, 3002 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][5] = { 2657, 800, 800 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3002 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 1063 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][2] = { 1828, 3033, 3033 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][3] = { 1828, 3033, 1063 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][4] = { 2633, 851, 2979 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][5] = { 2633, 851, 851 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 2979 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 744 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 1594, 2926, 2926 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][3] = { 1594, 2926, 744 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][4] = { 2484, 507, 2867 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][5] = { 2484, 507, 507 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][6] = { 507, 507, 2867 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][1] = { 2125, 2125, 212 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][2] = { 698, 2125, 2125 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][3] = { 698, 2125, 212 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][4] = { 1557, 130, 2043 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 1812, 1812, 1812 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 1812, 1812, 1022 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 1402, 1812, 1812 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 1402, 1812, 1022 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 1692, 886, 1797 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1692, 886, 886 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1797 }, ++ [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][1] = { 2877, 2923, 1058 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][2] = { 1837, 2840, 2916 }, +@@ -994,14 +994,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][5] = { 2517, 1159, 900 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][6] = { 1042, 870, 2917 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][1] = { 2976, 3018, 1315 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][2] = { 2024, 2942, 3011 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][3] = { 1930, 2926, 1256 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][4] = { 2563, 1227, 2916 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][5] = { 2494, 1183, 943 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][6] = { 1073, 916, 2894 }, +- [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][1] = { 2976, 3018, 1315 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][2] = { 2024, 2942, 3011 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][3] = { 1930, 2926, 1256 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][4] = { 2563, 1227, 2916 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][5] = { 2494, 1183, 943 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][6] = { 1073, 916, 2894 }, ++ [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][1] = { 2864, 2910, 1024 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][2] = { 1811, 2826, 2903 }, +@@ -1050,14 +1050,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][5] = { 2880, 998, 902 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][6] = { 816, 823, 2940 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][1] = { 3029, 3028, 1255 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][2] = { 1406, 2988, 3011 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][3] = { 1398, 2983, 1190 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][4] = { 2860, 1050, 2939 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][5] = { 2857, 1033, 945 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][6] = { 866, 873, 2916 }, +- [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][1] = { 3029, 3028, 1255 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][2] = { 1406, 2988, 3011 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][3] = { 1398, 2983, 1190 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][4] = { 2860, 1050, 2939 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][5] = { 2857, 1033, 945 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][6] = { 866, 873, 2916 }, ++ [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][1] = { 2923, 2921, 957 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][2] = { 1125, 2877, 2902 }, +@@ -1128,7 +1128,7 @@ static const double rec709_to_240m[3][3] = { + { 0.0016327, 0.0044133, 0.9939540 }, + }; + +-static const double rec709_to_adobergb[3][3] = { ++static const double rec709_to_oprgb[3][3] = { + { 0.7151627, 0.2848373, -0.0000000 }, + { 0.0000000, 1.0000000, 0.0000000 }, + { -0.0000000, 0.0411705, 0.9588295 }, +@@ -1195,7 +1195,7 @@ static double transfer_rec709_to_rgb(double v) + return (v < 0.081) ? v / 4.5 : pow((v + 0.099) / 1.099, 1.0 / 0.45); + } + +-static double transfer_rgb_to_adobergb(double v) ++static double transfer_rgb_to_oprgb(double v) + { + return pow(v, 1.0 / 2.19921875); + } +@@ -1251,8 +1251,8 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func, + case V4L2_COLORSPACE_470_SYSTEM_M: + mult_matrix(r, g, b, rec709_to_ntsc1953); + break; +- case V4L2_COLORSPACE_ADOBERGB: +- mult_matrix(r, g, b, rec709_to_adobergb); ++ case V4L2_COLORSPACE_OPRGB: ++ mult_matrix(r, g, b, rec709_to_oprgb); + break; + case V4L2_COLORSPACE_BT2020: + mult_matrix(r, g, b, rec709_to_bt2020); +@@ -1284,10 +1284,10 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func, + *g = transfer_rgb_to_srgb(*g); + *b = transfer_rgb_to_srgb(*b); + break; +- case V4L2_XFER_FUNC_ADOBERGB: +- *r = transfer_rgb_to_adobergb(*r); +- *g = transfer_rgb_to_adobergb(*g); +- *b = transfer_rgb_to_adobergb(*b); ++ case V4L2_XFER_FUNC_OPRGB: ++ *r = transfer_rgb_to_oprgb(*r); ++ *g = transfer_rgb_to_oprgb(*g); ++ *b = transfer_rgb_to_oprgb(*b); + break; + case V4L2_XFER_FUNC_DCI_P3: + *r = transfer_rgb_to_dcip3(*r); +@@ -1321,7 +1321,7 @@ int main(int argc, char **argv) + V4L2_COLORSPACE_470_SYSTEM_BG, + 0, + V4L2_COLORSPACE_SRGB, +- V4L2_COLORSPACE_ADOBERGB, ++ V4L2_COLORSPACE_OPRGB, + V4L2_COLORSPACE_BT2020, + 0, + V4L2_COLORSPACE_DCI_P3, +@@ -1336,7 +1336,7 @@ int main(int argc, char **argv) + "V4L2_COLORSPACE_470_SYSTEM_BG", + "", + "V4L2_COLORSPACE_SRGB", +- "V4L2_COLORSPACE_ADOBERGB", ++ "V4L2_COLORSPACE_OPRGB", + "V4L2_COLORSPACE_BT2020", + "", + "V4L2_COLORSPACE_DCI_P3", +@@ -1345,7 +1345,7 @@ int main(int argc, char **argv) + "", + "V4L2_XFER_FUNC_709", + "V4L2_XFER_FUNC_SRGB", +- "V4L2_XFER_FUNC_ADOBERGB", ++ "V4L2_XFER_FUNC_OPRGB", + "V4L2_XFER_FUNC_SMPTE240M", + "V4L2_XFER_FUNC_NONE", + "V4L2_XFER_FUNC_DCI_P3", +diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +index abd4c788dffd..f40ab5704bf0 100644 +--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c ++++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +@@ -1770,7 +1770,7 @@ typedef struct { u16 __; u8 _; } __packed x24; + pos[7] = (chr & (0x01 << 0) ? fg : bg); \ + } \ + \ +- pos += (tpg->hflip ? -8 : 8) / hdiv; \ ++ pos += (tpg->hflip ? -8 : 8) / (int)hdiv; \ + } \ + } \ + } while (0) +diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c +index 55c2ea0720d9..f3899cc84e27 100644 +--- a/drivers/media/i2c/adv7511.c ++++ b/drivers/media/i2c/adv7511.c +@@ -1355,10 +1355,10 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, + state->xfer_func = format->format.xfer_func; + + switch (format->format.colorspace) { +- case V4L2_COLORSPACE_ADOBERGB: ++ case V4L2_COLORSPACE_OPRGB: + c = HDMI_COLORIMETRY_EXTENDED; +- ec = y ? HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601 : +- HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB; ++ ec = y ? HDMI_EXTENDED_COLORIMETRY_OPYCC_601 : ++ HDMI_EXTENDED_COLORIMETRY_OPRGB; + break; + case V4L2_COLORSPACE_SMPTE170M: + c = y ? HDMI_COLORIMETRY_ITU_601 : HDMI_COLORIMETRY_NONE; +diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c +index 668be2bca57a..c78698199ac5 100644 +--- a/drivers/media/i2c/adv7604.c ++++ b/drivers/media/i2c/adv7604.c +@@ -2284,8 +2284,10 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) + state->aspect_ratio.numerator = 16; + state->aspect_ratio.denominator = 9; + +- if (!state->edid.present) ++ if (!state->edid.present) { + state->edid.blocks = 0; ++ cec_phys_addr_invalidate(state->cec_adap); ++ } + + v4l2_dbg(2, debug, sd, "%s: clear EDID pad %d, edid.present = 0x%x\n", + __func__, edid->pad, state->edid.present); +@@ -2474,7 +2476,7 @@ static int adv76xx_log_status(struct v4l2_subdev *sd) + "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)", + "xvYCC Bt.601", "xvYCC Bt.709", + "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)", +- "sYCC", "Adobe YCC 601", "AdobeRGB", "invalid", "invalid", ++ "sYCC", "opYCC 601", "opRGB", "invalid", "invalid", + "invalid", "invalid", "invalid" + }; + static const char * const rgb_quantization_range_txt[] = { +diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c +index 4f8fbdd00e35..71fe56565f75 100644 +--- a/drivers/media/i2c/adv7842.c ++++ b/drivers/media/i2c/adv7842.c +@@ -786,8 +786,10 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) + /* Disable I2C access to internal EDID ram from HDMI DDC ports */ + rep_write_and_or(sd, 0x77, 0xf3, 0x00); + +- if (!state->hdmi_edid.present) ++ if (!state->hdmi_edid.present) { ++ cec_phys_addr_invalidate(state->cec_adap); + return 0; ++ } + + pa = cec_get_edid_phys_addr(edid, 256, &spa_loc); + err = cec_phys_addr_validate(pa, &pa, NULL); +diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c +index 31bf577b0bd3..64d1402882c8 100644 +--- a/drivers/media/i2c/ov7670.c ++++ b/drivers/media/i2c/ov7670.c +@@ -1808,17 +1808,24 @@ static int ov7670_probe(struct i2c_client *client, + info->pclk_hb_disable = true; + } + +- info->clk = devm_clk_get(&client->dev, "xclk"); +- if (IS_ERR(info->clk)) +- return PTR_ERR(info->clk); +- ret = clk_prepare_enable(info->clk); +- if (ret) +- return ret; ++ info->clk = devm_clk_get(&client->dev, "xclk"); /* optional */ ++ if (IS_ERR(info->clk)) { ++ ret = PTR_ERR(info->clk); ++ if (ret == -ENOENT) ++ info->clk = NULL; ++ else ++ return ret; ++ } ++ if (info->clk) { ++ ret = clk_prepare_enable(info->clk); ++ if (ret) ++ return ret; + +- info->clock_speed = clk_get_rate(info->clk) / 1000000; +- if (info->clock_speed < 10 || info->clock_speed > 48) { +- ret = -EINVAL; +- goto clk_disable; ++ info->clock_speed = clk_get_rate(info->clk) / 1000000; ++ if (info->clock_speed < 10 || info->clock_speed > 48) { ++ ret = -EINVAL; ++ goto clk_disable; ++ } + } + + ret = ov7670_init_gpio(client, info); +diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c +index 44c41933415a..ff25ea9aca48 100644 +--- a/drivers/media/i2c/tc358743.c ++++ b/drivers/media/i2c/tc358743.c +@@ -1243,9 +1243,9 @@ static int tc358743_log_status(struct v4l2_subdev *sd) + u8 vi_status3 = i2c_rd8(sd, VI_STATUS3); + const int deep_color_mode[4] = { 8, 10, 12, 16 }; + static const char * const input_color_space[] = { +- "RGB", "YCbCr 601", "Adobe RGB", "YCbCr 709", "NA (4)", ++ "RGB", "YCbCr 601", "opRGB", "YCbCr 709", "NA (4)", + "xvYCC 601", "NA(6)", "xvYCC 709", "NA(8)", "sYCC601", +- "NA(10)", "NA(11)", "NA(12)", "Adobe YCC 601"}; ++ "NA(10)", "NA(11)", "NA(12)", "opYCC 601"}; + + v4l2_info(sd, "-----Chip status-----\n"); + v4l2_info(sd, "Chip ID: 0x%02x\n", +diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c +index 76e6bed5a1da..805bd9c65940 100644 +--- a/drivers/media/i2c/tvp5150.c ++++ b/drivers/media/i2c/tvp5150.c +@@ -1534,7 +1534,7 @@ static int tvp5150_probe(struct i2c_client *c, + 27000000, 1, 27000000); + v4l2_ctrl_new_std_menu_items(&core->hdl, &tvp5150_ctrl_ops, + V4L2_CID_TEST_PATTERN, +- ARRAY_SIZE(tvp5150_test_patterns), ++ ARRAY_SIZE(tvp5150_test_patterns) - 1, + 0, 0, tvp5150_test_patterns); + sd->ctrl_handler = &core->hdl; + if (core->hdl.error) { +diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h +index 477c80a4d44c..cd4c8230563c 100644 +--- a/drivers/media/platform/vivid/vivid-core.h ++++ b/drivers/media/platform/vivid/vivid-core.h +@@ -111,7 +111,7 @@ enum vivid_colorspace { + VIVID_CS_170M, + VIVID_CS_709, + VIVID_CS_SRGB, +- VIVID_CS_ADOBERGB, ++ VIVID_CS_OPRGB, + VIVID_CS_2020, + VIVID_CS_DCI_P3, + VIVID_CS_240M, +diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c +index 5429193fbb91..999aa101b150 100644 +--- a/drivers/media/platform/vivid/vivid-ctrls.c ++++ b/drivers/media/platform/vivid/vivid-ctrls.c +@@ -348,7 +348,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl) + V4L2_COLORSPACE_SMPTE170M, + V4L2_COLORSPACE_REC709, + V4L2_COLORSPACE_SRGB, +- V4L2_COLORSPACE_ADOBERGB, ++ V4L2_COLORSPACE_OPRGB, + V4L2_COLORSPACE_BT2020, + V4L2_COLORSPACE_DCI_P3, + V4L2_COLORSPACE_SMPTE240M, +@@ -729,7 +729,7 @@ static const char * const vivid_ctrl_colorspace_strings[] = { + "SMPTE 170M", + "Rec. 709", + "sRGB", +- "AdobeRGB", ++ "opRGB", + "BT.2020", + "DCI-P3", + "SMPTE 240M", +@@ -752,7 +752,7 @@ static const char * const vivid_ctrl_xfer_func_strings[] = { + "Default", + "Rec. 709", + "sRGB", +- "AdobeRGB", ++ "opRGB", + "SMPTE 240M", + "None", + "DCI-P3", +diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c +index 51fec66d8d45..50248e2176a0 100644 +--- a/drivers/media/platform/vivid/vivid-vid-out.c ++++ b/drivers/media/platform/vivid/vivid-vid-out.c +@@ -413,7 +413,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv, + mp->colorspace = V4L2_COLORSPACE_SMPTE170M; + } else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M && + mp->colorspace != V4L2_COLORSPACE_REC709 && +- mp->colorspace != V4L2_COLORSPACE_ADOBERGB && ++ mp->colorspace != V4L2_COLORSPACE_OPRGB && + mp->colorspace != V4L2_COLORSPACE_BT2020 && + mp->colorspace != V4L2_COLORSPACE_SRGB) { + mp->colorspace = V4L2_COLORSPACE_REC709; +diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c +index 1aa88d94e57f..e28bd8836751 100644 +--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c ++++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c +@@ -31,6 +31,7 @@ MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver."); + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + + struct dvbsky_state { ++ struct mutex stream_mutex; + u8 ibuf[DVBSKY_BUF_LEN]; + u8 obuf[DVBSKY_BUF_LEN]; + u8 last_lock; +@@ -67,17 +68,18 @@ static int dvbsky_usb_generic_rw(struct dvb_usb_device *d, + + static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) + { ++ struct dvbsky_state *state = d_to_priv(d); + int ret; +- static u8 obuf_pre[3] = { 0x37, 0, 0 }; +- static u8 obuf_post[3] = { 0x36, 3, 0 }; ++ u8 obuf_pre[3] = { 0x37, 0, 0 }; ++ u8 obuf_post[3] = { 0x36, 3, 0 }; + +- mutex_lock(&d->usb_mutex); +- ret = dvb_usbv2_generic_rw_locked(d, obuf_pre, 3, NULL, 0); ++ mutex_lock(&state->stream_mutex); ++ ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0); + if (!ret && onoff) { + msleep(20); +- ret = dvb_usbv2_generic_rw_locked(d, obuf_post, 3, NULL, 0); ++ ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0); + } +- mutex_unlock(&d->usb_mutex); ++ mutex_unlock(&state->stream_mutex); + return ret; + } + +@@ -606,6 +608,8 @@ static int dvbsky_init(struct dvb_usb_device *d) + if (ret) + return ret; + */ ++ mutex_init(&state->stream_mutex); ++ + state->last_lock = 0; + + return 0; +diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c +index 71c829f31d3b..87b887b7604e 100644 +--- a/drivers/media/usb/em28xx/em28xx-cards.c ++++ b/drivers/media/usb/em28xx/em28xx-cards.c +@@ -2141,13 +2141,13 @@ const struct em28xx_board em28xx_boards[] = { + .input = { { + .type = EM28XX_VMUX_COMPOSITE, + .vmux = TVP5150_COMPOSITE1, +- .amux = EM28XX_AUDIO_SRC_LINE, ++ .amux = EM28XX_AMUX_LINE_IN, + .gpio = terratec_av350_unmute_gpio, + + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, +- .amux = EM28XX_AUDIO_SRC_LINE, ++ .amux = EM28XX_AMUX_LINE_IN, + .gpio = terratec_av350_unmute_gpio, + } }, + }, +@@ -3039,6 +3039,9 @@ static int em28xx_hint_board(struct em28xx *dev) + + static void em28xx_card_setup(struct em28xx *dev) + { ++ int i, j, idx; ++ bool duplicate_entry; ++ + /* + * If the device can be a webcam, seek for a sensor. + * If sensor is not found, then it isn't a webcam. +@@ -3195,6 +3198,32 @@ static void em28xx_card_setup(struct em28xx *dev) + /* Allow override tuner type by a module parameter */ + if (tuner >= 0) + dev->tuner_type = tuner; ++ ++ /* ++ * Dynamically generate a list of valid audio inputs for this ++ * specific board, mapping them via enum em28xx_amux. ++ */ ++ ++ idx = 0; ++ for (i = 0; i < MAX_EM28XX_INPUT; i++) { ++ if (!INPUT(i)->type) ++ continue; ++ ++ /* Skip already mapped audio inputs */ ++ duplicate_entry = false; ++ for (j = 0; j < idx; j++) { ++ if (INPUT(i)->amux == dev->amux_map[j]) { ++ duplicate_entry = true; ++ break; ++ } ++ } ++ if (duplicate_entry) ++ continue; ++ ++ dev->amux_map[idx++] = INPUT(i)->amux; ++ } ++ for (; idx < MAX_EM28XX_INPUT; idx++) ++ dev->amux_map[idx] = EM28XX_AMUX_UNUSED; + } + + void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) +diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c +index 68571bf36d28..3bf98ac897ec 100644 +--- a/drivers/media/usb/em28xx/em28xx-video.c ++++ b/drivers/media/usb/em28xx/em28xx-video.c +@@ -1093,6 +1093,8 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) + + em28xx_videodbg("%s\n", __func__); + ++ dev->v4l2->field_count = 0; ++ + /* + * Make sure streaming is not already in progress for this type + * of filehandle (e.g. video, vbi) +@@ -1471,9 +1473,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (!fmt) { +- em28xx_videodbg("Fourcc format (%08x) invalid.\n", +- f->fmt.pix.pixelformat); +- return -EINVAL; ++ fmt = &format[0]; ++ em28xx_videodbg("Fourcc format (%08x) invalid. Using default (%08x).\n", ++ f->fmt.pix.pixelformat, fmt->fourcc); + } + + if (dev->board.is_em2800) { +@@ -1666,6 +1668,7 @@ static int vidioc_enum_input(struct file *file, void *priv, + { + struct em28xx *dev = video_drvdata(file); + unsigned int n; ++ int j; + + n = i->index; + if (n >= MAX_EM28XX_INPUT) +@@ -1685,6 +1688,12 @@ static int vidioc_enum_input(struct file *file, void *priv, + if (dev->is_webcam) + i->capabilities = 0; + ++ /* Dynamically generates an audioset bitmask */ ++ i->audioset = 0; ++ for (j = 0; j < MAX_EM28XX_INPUT; j++) ++ if (dev->amux_map[j] != EM28XX_AMUX_UNUSED) ++ i->audioset |= 1 << j; ++ + return 0; + } + +@@ -1710,11 +1719,24 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) + return 0; + } + +-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) ++static int em28xx_fill_audio_input(struct em28xx *dev, ++ const char *s, ++ struct v4l2_audio *a, ++ unsigned int index) + { +- struct em28xx *dev = video_drvdata(file); ++ unsigned int idx = dev->amux_map[index]; ++ ++ /* ++ * With msp3400, almost all mappings use the default (amux = 0). ++ * The only one may use a different value is WinTV USB2, where it ++ * can also be SCART1 input. ++ * As it is very doubtful that we would see new boards with msp3400, ++ * let's just reuse the existing switch. ++ */ ++ if (dev->has_msp34xx && idx != EM28XX_AMUX_UNUSED) ++ idx = EM28XX_AMUX_LINE_IN; + +- switch (a->index) { ++ switch (idx) { + case EM28XX_AMUX_VIDEO: + strcpy(a->name, "Television"); + break; +@@ -1739,32 +1761,79 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) + case EM28XX_AMUX_PCM_OUT: + strcpy(a->name, "PCM"); + break; ++ case EM28XX_AMUX_UNUSED: + default: + return -EINVAL; + } +- +- a->index = dev->ctl_ainput; ++ a->index = index; + a->capability = V4L2_AUDCAP_STEREO; + ++ em28xx_videodbg("%s: audio input index %d is '%s'\n", ++ s, a->index, a->name); ++ + return 0; + } + ++static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) ++{ ++ struct em28xx *dev = video_drvdata(file); ++ ++ if (a->index >= MAX_EM28XX_INPUT) ++ return -EINVAL; ++ ++ return em28xx_fill_audio_input(dev, __func__, a, a->index); ++} ++ ++static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) ++{ ++ struct em28xx *dev = video_drvdata(file); ++ int i; ++ ++ for (i = 0; i < MAX_EM28XX_INPUT; i++) ++ if (dev->ctl_ainput == dev->amux_map[i]) ++ return em28xx_fill_audio_input(dev, __func__, a, i); ++ ++ /* Should never happen! */ ++ return -EINVAL; ++} ++ + static int vidioc_s_audio(struct file *file, void *priv, + const struct v4l2_audio *a) + { + struct em28xx *dev = video_drvdata(file); ++ int idx, i; + + if (a->index >= MAX_EM28XX_INPUT) + return -EINVAL; +- if (!INPUT(a->index)->type) ++ ++ idx = dev->amux_map[a->index]; ++ ++ if (idx == EM28XX_AMUX_UNUSED) + return -EINVAL; + +- dev->ctl_ainput = INPUT(a->index)->amux; +- dev->ctl_aoutput = INPUT(a->index)->aout; ++ dev->ctl_ainput = idx; ++ ++ /* ++ * FIXME: This is wrong, as different inputs at em28xx_cards ++ * may have different audio outputs. So, the right thing ++ * to do is to implement VIDIOC_G_AUDOUT/VIDIOC_S_AUDOUT. ++ * With the current board definitions, this would work fine, ++ * as, currently, all boards fit. ++ */ ++ for (i = 0; i < MAX_EM28XX_INPUT; i++) ++ if (idx == dev->amux_map[i]) ++ break; ++ if (i == MAX_EM28XX_INPUT) ++ return -EINVAL; ++ ++ dev->ctl_aoutput = INPUT(i)->aout; + + if (!dev->ctl_aoutput) + dev->ctl_aoutput = EM28XX_AOUT_MASTER; + ++ em28xx_videodbg("%s: set audio input to %d\n", __func__, ++ dev->ctl_ainput); ++ + return 0; + } + +@@ -2302,6 +2371,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { + .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_enum_framesizes = vidioc_enum_framesizes, ++ .vidioc_enumaudio = vidioc_enumaudio, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + +diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h +index 953caac025f2..a551072e62ed 100644 +--- a/drivers/media/usb/em28xx/em28xx.h ++++ b/drivers/media/usb/em28xx/em28xx.h +@@ -335,6 +335,9 @@ enum em28xx_usb_audio_type { + /** + * em28xx_amux - describes the type of audio input used by em28xx + * ++ * @EM28XX_AMUX_UNUSED: ++ * Used only on em28xx dev->map field, in order to mark an entry ++ * as unused. + * @EM28XX_AMUX_VIDEO: + * On devices without AC97, this is the only value that it is currently + * allowed. +@@ -369,7 +372,8 @@ enum em28xx_usb_audio_type { + * same time, via the alsa mux. + */ + enum em28xx_amux { +- EM28XX_AMUX_VIDEO, ++ EM28XX_AMUX_UNUSED = -1, ++ EM28XX_AMUX_VIDEO = 0, + EM28XX_AMUX_LINE_IN, + + /* Some less-common mixer setups */ +@@ -692,6 +696,8 @@ struct em28xx { + unsigned int ctl_input; // selected input + unsigned int ctl_ainput;// selected audio input + unsigned int ctl_aoutput;// selected audio output ++ enum em28xx_amux amux_map[MAX_EM28XX_INPUT]; ++ + int mute; + int volume; + +diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c +index c81faea96fba..c7c600c1f63b 100644 +--- a/drivers/media/v4l2-core/v4l2-dv-timings.c ++++ b/drivers/media/v4l2-core/v4l2-dv-timings.c +@@ -837,9 +837,9 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi, + switch (avi->colorimetry) { + case HDMI_COLORIMETRY_EXTENDED: + switch (avi->extended_colorimetry) { +- case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB: +- c.colorspace = V4L2_COLORSPACE_ADOBERGB; +- c.xfer_func = V4L2_XFER_FUNC_ADOBERGB; ++ case HDMI_EXTENDED_COLORIMETRY_OPRGB: ++ c.colorspace = V4L2_COLORSPACE_OPRGB; ++ c.xfer_func = V4L2_XFER_FUNC_OPRGB; + break; + case HDMI_EXTENDED_COLORIMETRY_BT2020: + c.colorspace = V4L2_COLORSPACE_BT2020; +@@ -908,10 +908,10 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi, + c.ycbcr_enc = V4L2_YCBCR_ENC_601; + c.xfer_func = V4L2_XFER_FUNC_SRGB; + break; +- case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601: +- c.colorspace = V4L2_COLORSPACE_ADOBERGB; ++ case HDMI_EXTENDED_COLORIMETRY_OPYCC_601: ++ c.colorspace = V4L2_COLORSPACE_OPRGB; + c.ycbcr_enc = V4L2_YCBCR_ENC_601; +- c.xfer_func = V4L2_XFER_FUNC_ADOBERGB; ++ c.xfer_func = V4L2_XFER_FUNC_OPRGB; + break; + case HDMI_EXTENDED_COLORIMETRY_BT2020: + c.colorspace = V4L2_COLORSPACE_BT2020; +diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c +index 29b7164a823b..d28ebe7ecd21 100644 +--- a/drivers/mfd/menelaus.c ++++ b/drivers/mfd/menelaus.c +@@ -1094,6 +1094,7 @@ static void menelaus_rtc_alarm_work(struct menelaus_chip *m) + static inline void menelaus_rtc_init(struct menelaus_chip *m) + { + int alarm = (m->client->irq > 0); ++ int err; + + /* assume 32KDETEN pin is pulled high */ + if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) { +@@ -1101,6 +1102,12 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m) + return; + } + ++ m->rtc = devm_rtc_allocate_device(&m->client->dev); ++ if (IS_ERR(m->rtc)) ++ return; ++ ++ m->rtc->ops = &menelaus_rtc_ops; ++ + /* support RTC alarm; it can issue wakeups */ + if (alarm) { + if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ, +@@ -1125,10 +1132,8 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m) + menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control); + } + +- m->rtc = rtc_device_register(DRIVER_NAME, +- &m->client->dev, +- &menelaus_rtc_ops, THIS_MODULE); +- if (IS_ERR(m->rtc)) { ++ err = rtc_register_device(m->rtc); ++ if (err) { + if (alarm) { + menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ); + device_init_wakeup(&m->client->dev, 0); +diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h +index 120738d6e58b..77ed3967c5b0 100644 +--- a/drivers/misc/genwqe/card_base.h ++++ b/drivers/misc/genwqe/card_base.h +@@ -408,7 +408,7 @@ struct genwqe_file { + struct file *filp; + + struct fasync_struct *async_queue; +- struct task_struct *owner; ++ struct pid *opener; + struct list_head list; /* entry in list of open files */ + + spinlock_t map_lock; /* lock for dma_mappings */ +diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c +index f453ab82f0d7..8c1b63a4337b 100644 +--- a/drivers/misc/genwqe/card_dev.c ++++ b/drivers/misc/genwqe/card_dev.c +@@ -52,7 +52,7 @@ static void genwqe_add_file(struct genwqe_dev *cd, struct genwqe_file *cfile) + { + unsigned long flags; + +- cfile->owner = current; ++ cfile->opener = get_pid(task_tgid(current)); + spin_lock_irqsave(&cd->file_lock, flags); + list_add(&cfile->list, &cd->file_list); + spin_unlock_irqrestore(&cd->file_lock, flags); +@@ -65,6 +65,7 @@ static int genwqe_del_file(struct genwqe_dev *cd, struct genwqe_file *cfile) + spin_lock_irqsave(&cd->file_lock, flags); + list_del(&cfile->list); + spin_unlock_irqrestore(&cd->file_lock, flags); ++ put_pid(cfile->opener); + + return 0; + } +@@ -275,7 +276,7 @@ static int genwqe_kill_fasync(struct genwqe_dev *cd, int sig) + return files; + } + +-static int genwqe_force_sig(struct genwqe_dev *cd, int sig) ++static int genwqe_terminate(struct genwqe_dev *cd) + { + unsigned int files = 0; + unsigned long flags; +@@ -283,7 +284,7 @@ static int genwqe_force_sig(struct genwqe_dev *cd, int sig) + + spin_lock_irqsave(&cd->file_lock, flags); + list_for_each_entry(cfile, &cd->file_list, list) { +- force_sig(sig, cfile->owner); ++ kill_pid(cfile->opener, SIGKILL, 1); + files++; + } + spin_unlock_irqrestore(&cd->file_lock, flags); +@@ -1352,7 +1353,7 @@ static int genwqe_inform_and_stop_processes(struct genwqe_dev *cd) + dev_warn(&pci_dev->dev, + "[%s] send SIGKILL and wait ...\n", __func__); + +- rc = genwqe_force_sig(cd, SIGKILL); /* force terminate */ ++ rc = genwqe_terminate(cd); + if (rc) { + /* Give kill_timout more seconds to end processes */ + for (i = 0; (i < GENWQE_KILL_TIMEOUT) && +diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c +index 2e30de9c694a..57a6bb1fd3c9 100644 +--- a/drivers/misc/ocxl/config.c ++++ b/drivers/misc/ocxl/config.c +@@ -280,7 +280,9 @@ int ocxl_config_check_afu_index(struct pci_dev *dev, + u32 val; + int rc, templ_major, templ_minor, len; + +- pci_write_config_word(dev, fn->dvsec_afu_info_pos, afu_idx); ++ pci_write_config_byte(dev, ++ fn->dvsec_afu_info_pos + OCXL_DVSEC_AFU_INFO_AFU_IDX, ++ afu_idx); + rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_VERSION, &val); + if (rc) + return rc; +diff --git a/drivers/misc/vmw_vmci/vmci_driver.c b/drivers/misc/vmw_vmci/vmci_driver.c +index d7eaf1eb11e7..003bfba40758 100644 +--- a/drivers/misc/vmw_vmci/vmci_driver.c ++++ b/drivers/misc/vmw_vmci/vmci_driver.c +@@ -113,5 +113,5 @@ module_exit(vmci_drv_exit); + + MODULE_AUTHOR("VMware, Inc."); + MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface."); +-MODULE_VERSION("1.1.5.0-k"); ++MODULE_VERSION("1.1.6.0-k"); + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/misc/vmw_vmci/vmci_resource.c b/drivers/misc/vmw_vmci/vmci_resource.c +index 1ab6e8737a5f..da1ee2e1ba99 100644 +--- a/drivers/misc/vmw_vmci/vmci_resource.c ++++ b/drivers/misc/vmw_vmci/vmci_resource.c +@@ -57,7 +57,8 @@ static struct vmci_resource *vmci_resource_lookup(struct vmci_handle handle, + + if (r->type == type && + rid == handle.resource && +- (cid == handle.context || cid == VMCI_INVALID_ID)) { ++ (cid == handle.context || cid == VMCI_INVALID_ID || ++ handle.context == VMCI_INVALID_ID)) { + resource = r; + break; + } +diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c +index 32321bd596d8..c61109f7b793 100644 +--- a/drivers/mmc/host/sdhci-acpi.c ++++ b/drivers/mmc/host/sdhci-acpi.c +@@ -76,6 +76,7 @@ struct sdhci_acpi_slot { + size_t priv_size; + int (*probe_slot)(struct platform_device *, const char *, const char *); + int (*remove_slot)(struct platform_device *); ++ int (*free_slot)(struct platform_device *pdev); + int (*setup_host)(struct platform_device *pdev); + }; + +@@ -756,6 +757,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev) + err_cleanup: + sdhci_cleanup_host(c->host); + err_free: ++ if (c->slot && c->slot->free_slot) ++ c->slot->free_slot(pdev); ++ + sdhci_free_host(c->host); + return err; + } +@@ -777,6 +781,10 @@ static int sdhci_acpi_remove(struct platform_device *pdev) + + dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0); + sdhci_remove_host(c->host, dead); ++ ++ if (c->slot && c->slot->free_slot) ++ c->slot->free_slot(pdev); ++ + sdhci_free_host(c->host); + + return 0; +diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c +index 77e9bc4aaee9..cc3ffeffd7a2 100644 +--- a/drivers/mmc/host/sdhci-pci-o2micro.c ++++ b/drivers/mmc/host/sdhci-pci-o2micro.c +@@ -490,6 +490,9 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); + break; + case PCI_DEVICE_ID_O2_SEABIRD0: ++ if (chip->pdev->revision == 0x01) ++ chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER; ++ /* fall through */ + case PCI_DEVICE_ID_O2_SEABIRD1: + /* UnLock WP */ + ret = pci_read_config_byte(chip->pdev, +diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c +index 9d9723693217..2e3a8da3ce72 100644 +--- a/drivers/mtd/maps/gpio-addr-flash.c ++++ b/drivers/mtd/maps/gpio-addr-flash.c +@@ -238,7 +238,7 @@ static int gpio_flash_probe(struct platform_device *pdev) + state->map.copy_to = gf_copy_to; + state->map.bankwidth = pdata->width; + state->map.size = state->win_size * (1 << state->gpio_count); +- state->map.virt = ioremap_nocache(memory->start, state->map.size); ++ state->map.virt = ioremap_nocache(memory->start, state->win_size); + if (!state->map.virt) + return -ENOMEM; + +diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c +index a068b214ebaa..a594fb1e9a99 100644 +--- a/drivers/mtd/nand/raw/atmel/nand-controller.c ++++ b/drivers/mtd/nand/raw/atmel/nand-controller.c +@@ -2063,6 +2063,10 @@ atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc) + nand_np = dev->of_node; + nfc_np = of_find_compatible_node(dev->of_node, NULL, + "atmel,sama5d3-nfc"); ++ if (!nfc_np) { ++ dev_err(dev, "Could not find device node for sama5d3-nfc\n"); ++ return -ENODEV; ++ } + + nc->clk = of_clk_get(nfc_np, 0); + if (IS_ERR(nc->clk)) { +diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c +index b864b93dd289..2242e999a76b 100644 +--- a/drivers/mtd/nand/raw/denali.c ++++ b/drivers/mtd/nand/raw/denali.c +@@ -28,6 +28,7 @@ + MODULE_LICENSE("GPL"); + + #define DENALI_NAND_NAME "denali-nand" ++#define DENALI_DEFAULT_OOB_SKIP_BYTES 8 + + /* for Indexed Addressing */ + #define DENALI_INDEXED_CTRL 0x00 +@@ -1105,12 +1106,17 @@ static void denali_hw_init(struct denali_nand_info *denali) + denali->revision = swab16(ioread32(denali->reg + REVISION)); + + /* +- * tell driver how many bit controller will skip before +- * writing ECC code in OOB, this register may be already +- * set by firmware. So we read this value out. +- * if this value is 0, just let it be. ++ * Set how many bytes should be skipped before writing data in OOB. ++ * If a non-zero value has already been set (by firmware or something), ++ * just use it. Otherwise, set the driver default. + */ + denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); ++ if (!denali->oob_skip_bytes) { ++ denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; ++ iowrite32(denali->oob_skip_bytes, ++ denali->reg + SPARE_AREA_SKIP_BYTES); ++ } ++ + denali_detect_max_banks(denali); + iowrite32(0x0F, denali->reg + RB_PIN_ENABLED); + iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); +diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c +index bc2ef5209783..c7573ccdbacd 100644 +--- a/drivers/mtd/nand/raw/marvell_nand.c ++++ b/drivers/mtd/nand/raw/marvell_nand.c +@@ -686,7 +686,7 @@ static irqreturn_t marvell_nfc_isr(int irq, void *dev_id) + + marvell_nfc_disable_int(nfc, st & NDCR_ALL_INT); + +- if (!(st & (NDSR_RDDREQ | NDSR_WRDREQ | NDSR_WRCMDREQ))) ++ if (st & (NDSR_RDY(0) | NDSR_RDY(1))) + complete(&nfc->complete); + + return IRQ_HANDLED; +diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c +index 7d9620c7ff6c..1ff3430f82c8 100644 +--- a/drivers/mtd/spi-nor/fsl-quadspi.c ++++ b/drivers/mtd/spi-nor/fsl-quadspi.c +@@ -478,6 +478,7 @@ static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) + { + switch (cmd) { + case SPINOR_OP_READ_1_1_4: ++ case SPINOR_OP_READ_1_1_4_4B: + return SEQID_READ; + case SPINOR_OP_WREN: + return SEQID_WREN; +@@ -543,6 +544,9 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len) + + /* trigger the LUT now */ + seqid = fsl_qspi_get_seqid(q, cmd); ++ if (seqid < 0) ++ return seqid; ++ + qspi_writel(q, (seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, + base + QUADSPI_IPCR); + +@@ -671,7 +675,7 @@ static void fsl_qspi_set_map_addr(struct fsl_qspi *q) + * causes the controller to clear the buffer, and use the sequence pointed + * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. + */ +-static void fsl_qspi_init_ahb_read(struct fsl_qspi *q) ++static int fsl_qspi_init_ahb_read(struct fsl_qspi *q) + { + void __iomem *base = q->iobase; + int seqid; +@@ -696,8 +700,13 @@ static void fsl_qspi_init_ahb_read(struct fsl_qspi *q) + + /* Set the default lut sequence for AHB Read. */ + seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode); ++ if (seqid < 0) ++ return seqid; ++ + qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT, + q->iobase + QUADSPI_BFGENCR); ++ ++ return 0; + } + + /* This function was used to prepare and enable QSPI clock */ +@@ -805,9 +814,7 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) + fsl_qspi_init_lut(q); + + /* Init for AHB read */ +- fsl_qspi_init_ahb_read(q); +- +- return 0; ++ return fsl_qspi_init_ahb_read(q); + } + + static const struct of_device_id fsl_qspi_dt_ids[] = { +diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/intel-spi-pci.c +index c0976f2e3dd1..872b40922608 100644 +--- a/drivers/mtd/spi-nor/intel-spi-pci.c ++++ b/drivers/mtd/spi-nor/intel-spi-pci.c +@@ -65,6 +65,7 @@ static void intel_spi_pci_remove(struct pci_dev *pdev) + static const struct pci_device_id intel_spi_pci_ids[] = { + { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, ++ { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, + { PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info }, + { }, +diff --git a/drivers/net/dsa/mv88e6xxx/phy.c b/drivers/net/dsa/mv88e6xxx/phy.c +index 46af8052e535..152a65d46e0b 100644 +--- a/drivers/net/dsa/mv88e6xxx/phy.c ++++ b/drivers/net/dsa/mv88e6xxx/phy.c +@@ -110,6 +110,9 @@ int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip *chip, int phy, + err = mv88e6xxx_phy_page_get(chip, phy, page); + if (!err) { + err = mv88e6xxx_phy_write(chip, phy, MV88E6XXX_PHY_PAGE, page); ++ if (!err) ++ err = mv88e6xxx_phy_write(chip, phy, reg, val); ++ + mv88e6xxx_phy_page_put(chip, phy); + } + +diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c +index 34af5f1569c8..de0e24d912fe 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c +@@ -342,7 +342,7 @@ static struct device_node *bcmgenet_mii_of_find_mdio(struct bcmgenet_priv *priv) + if (!compat) + return NULL; + +- priv->mdio_dn = of_find_compatible_node(dn, NULL, compat); ++ priv->mdio_dn = of_get_compatible_child(dn, compat); + kfree(compat); + if (!priv->mdio_dn) { + dev_err(kdev, "unable to find MDIO bus node\n"); +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index 955c4ab18b03..b7b2f8254ce1 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -1915,6 +1915,7 @@ static int is_valid_clean_head(struct hns3_enet_ring *ring, int h) + bool hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget) + { + struct net_device *netdev = ring->tqp->handle->kinfo.netdev; ++ struct hns3_nic_priv *priv = netdev_priv(netdev); + struct netdev_queue *dev_queue; + int bytes, pkts; + int head; +@@ -1961,7 +1962,8 @@ bool hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget) + * sees the new next_to_clean. + */ + smp_mb(); +- if (netif_tx_queue_stopped(dev_queue)) { ++ if (netif_tx_queue_stopped(dev_queue) && ++ !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) { + netif_tx_wake_queue(dev_queue); + ring->stats.restart_queue++; + } +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +index f70ee6910ee2..9684ad015c42 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +@@ -309,7 +309,7 @@ static void hns3_self_test(struct net_device *ndev, + h->flags & HNAE3_SUPPORT_SERDES_LOOPBACK; + + if (if_running) +- dev_close(ndev); ++ ndev->netdev_ops->ndo_stop(ndev); + + #if IS_ENABLED(CONFIG_VLAN_8021Q) + /* Disable the vlan filter for selftest does not support it */ +@@ -347,7 +347,7 @@ static void hns3_self_test(struct net_device *ndev, + #endif + + if (if_running) +- dev_open(ndev); ++ ndev->netdev_ops->ndo_open(ndev); + } + + static int hns3_get_sset_count(struct net_device *netdev, int stringset) +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +index f08ebb7caaaf..92f19384e258 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +@@ -73,6 +73,7 @@ static int hclge_ieee_getets(struct hnae3_handle *h, struct ieee_ets *ets) + static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets, + u8 *tc, bool *changed) + { ++ bool has_ets_tc = false; + u32 total_ets_bw = 0; + u8 max_tc = 0; + u8 i; +@@ -100,13 +101,14 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets, + *changed = true; + + total_ets_bw += ets->tc_tx_bw[i]; +- break; ++ has_ets_tc = true; ++ break; + default: + return -EINVAL; + } + } + +- if (total_ets_bw != BW_PERCENT) ++ if (has_ets_tc && total_ets_bw != BW_PERCENT) + return -EINVAL; + + *tc = max_tc + 1; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 8577dfc799ad..db763450e5e3 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -1657,11 +1657,13 @@ static int hclge_tx_buffer_calc(struct hclge_dev *hdev, + static int hclge_rx_buffer_calc(struct hclge_dev *hdev, + struct hclge_pkt_buf_alloc *buf_alloc) + { +- u32 rx_all = hdev->pkt_buf_size; ++#define HCLGE_BUF_SIZE_UNIT 128 ++ u32 rx_all = hdev->pkt_buf_size, aligned_mps; + int no_pfc_priv_num, pfc_priv_num; + struct hclge_priv_buf *priv; + int i; + ++ aligned_mps = round_up(hdev->mps, HCLGE_BUF_SIZE_UNIT); + rx_all -= hclge_get_tx_buff_alloced(buf_alloc); + + /* When DCB is not supported, rx private +@@ -1680,13 +1682,13 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev, + if (hdev->hw_tc_map & BIT(i)) { + priv->enable = 1; + if (hdev->tm_info.hw_pfc_map & BIT(i)) { +- priv->wl.low = hdev->mps; +- priv->wl.high = priv->wl.low + hdev->mps; ++ priv->wl.low = aligned_mps; ++ priv->wl.high = priv->wl.low + aligned_mps; + priv->buf_size = priv->wl.high + + HCLGE_DEFAULT_DV; + } else { + priv->wl.low = 0; +- priv->wl.high = 2 * hdev->mps; ++ priv->wl.high = 2 * aligned_mps; + priv->buf_size = priv->wl.high; + } + } else { +@@ -1718,11 +1720,11 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev, + + if (hdev->tm_info.hw_pfc_map & BIT(i)) { + priv->wl.low = 128; +- priv->wl.high = priv->wl.low + hdev->mps; ++ priv->wl.high = priv->wl.low + aligned_mps; + priv->buf_size = priv->wl.high + HCLGE_DEFAULT_DV; + } else { + priv->wl.low = 0; +- priv->wl.high = hdev->mps; ++ priv->wl.high = aligned_mps; + priv->buf_size = priv->wl.high; + } + } +@@ -2360,6 +2362,9 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev) + int mac_state; + int link_stat; + ++ if (test_bit(HCLGE_STATE_DOWN, &hdev->state)) ++ return 0; ++ + mac_state = hclge_get_mac_link_status(hdev); + + if (hdev->hw.mac.phydev) { +@@ -3809,6 +3814,8 @@ static void hclge_ae_stop(struct hnae3_handle *handle) + struct hclge_dev *hdev = vport->back; + int i; + ++ set_bit(HCLGE_STATE_DOWN, &hdev->state); ++ + del_timer_sync(&hdev->service_timer); + cancel_work_sync(&hdev->service_task); + clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); +@@ -4686,9 +4693,17 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid, + "Add vf vlan filter fail, ret =%d.\n", + req0->resp_code); + } else { ++#define HCLGE_VF_VLAN_DEL_NO_FOUND 1 + if (!req0->resp_code) + return 0; + ++ if (req0->resp_code == HCLGE_VF_VLAN_DEL_NO_FOUND) { ++ dev_warn(&hdev->pdev->dev, ++ "vlan %d filter is not in vf vlan table\n", ++ vlan); ++ return 0; ++ } ++ + dev_err(&hdev->pdev->dev, + "Kill vf vlan filter fail, ret =%d.\n", + req0->resp_code); +@@ -4732,6 +4747,9 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto, + u16 vport_idx, vport_num = 0; + int ret; + ++ if (is_kill && !vlan_id) ++ return 0; ++ + ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id, + 0, proto); + if (ret) { +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 9c0091f2addf..320043e87fc6 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -299,6 +299,9 @@ void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state) + + client = handle->client; + ++ link_state = ++ test_bit(HCLGEVF_STATE_DOWN, &hdev->state) ? 0 : link_state; ++ + if (link_state != hdev->hw.mac.link) { + client->ops->link_status_change(handle, !!link_state); + hdev->hw.mac.link = link_state; +@@ -1448,6 +1451,8 @@ static void hclgevf_ae_stop(struct hnae3_handle *handle) + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + int i, queue_id; + ++ set_bit(HCLGEVF_STATE_DOWN, &hdev->state); ++ + for (i = 0; i < hdev->num_tqps; i++) { + /* Ring disable */ + queue_id = hclgevf_get_queue_id(handle->kinfo.tqp[i]); +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 868f4a1d0f72..67591722c625 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -39,9 +39,9 @@ + extern const char ice_drv_ver[]; + #define ICE_BAR0 0 + #define ICE_DFLT_NUM_DESC 128 +-#define ICE_MIN_NUM_DESC 8 +-#define ICE_MAX_NUM_DESC 8160 + #define ICE_REQ_DESC_MULTIPLE 32 ++#define ICE_MIN_NUM_DESC ICE_REQ_DESC_MULTIPLE ++#define ICE_MAX_NUM_DESC 8160 + #define ICE_DFLT_TRAFFIC_CLASS BIT(0) + #define ICE_INT_NAME_STR_LEN (IFNAMSIZ + 16) + #define ICE_ETHTOOL_FWVER_LEN 32 +diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c +index 62be72fdc8f3..e783976c401d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_controlq.c ++++ b/drivers/net/ethernet/intel/ice/ice_controlq.c +@@ -518,22 +518,31 @@ shutdown_sq_out: + + /** + * ice_aq_ver_check - Check the reported AQ API version. +- * @fw_branch: The "branch" of FW, typically describes the device type +- * @fw_major: The major version of the FW API +- * @fw_minor: The minor version increment of the FW API ++ * @hw: pointer to the hardware structure + * + * Checks if the driver should load on a given AQ API version. + * + * Return: 'true' iff the driver should attempt to load. 'false' otherwise. + */ +-static bool ice_aq_ver_check(u8 fw_branch, u8 fw_major, u8 fw_minor) ++static bool ice_aq_ver_check(struct ice_hw *hw) + { +- if (fw_branch != EXP_FW_API_VER_BRANCH) +- return false; +- if (fw_major != EXP_FW_API_VER_MAJOR) +- return false; +- if (fw_minor != EXP_FW_API_VER_MINOR) ++ if (hw->api_maj_ver > EXP_FW_API_VER_MAJOR) { ++ /* Major API version is newer than expected, don't load */ ++ dev_warn(ice_hw_to_dev(hw), ++ "The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n"); + return false; ++ } else if (hw->api_maj_ver == EXP_FW_API_VER_MAJOR) { ++ if (hw->api_min_ver > (EXP_FW_API_VER_MINOR + 2)) ++ dev_info(ice_hw_to_dev(hw), ++ "The driver for the device detected a newer version of the NVM image than expected. Please install the most recent version of the network driver.\n"); ++ else if ((hw->api_min_ver + 2) < EXP_FW_API_VER_MINOR) ++ dev_info(ice_hw_to_dev(hw), ++ "The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n"); ++ } else { ++ /* Major API version is older than expected, log a warning */ ++ dev_info(ice_hw_to_dev(hw), ++ "The driver for the device detected an older version of the NVM image than expected. Please update the NVM image.\n"); ++ } + return true; + } + +@@ -588,8 +597,7 @@ static enum ice_status ice_init_check_adminq(struct ice_hw *hw) + if (status) + goto init_ctrlq_free_rq; + +- if (!ice_aq_ver_check(hw->api_branch, hw->api_maj_ver, +- hw->api_min_ver)) { ++ if (!ice_aq_ver_check(hw)) { + status = ICE_ERR_FW_API_VER; + goto init_ctrlq_free_rq; + } +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index c71a9b528d6d..9d6754f65a1a 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -478,9 +478,11 @@ ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) + ring->tx_max_pending = ICE_MAX_NUM_DESC; + ring->rx_pending = vsi->rx_rings[0]->count; + ring->tx_pending = vsi->tx_rings[0]->count; +- ring->rx_mini_pending = ICE_MIN_NUM_DESC; ++ ++ /* Rx mini and jumbo rings are not supported */ + ring->rx_mini_max_pending = 0; + ring->rx_jumbo_max_pending = 0; ++ ring->rx_mini_pending = 0; + ring->rx_jumbo_pending = 0; + } + +@@ -498,14 +500,23 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) + ring->tx_pending < ICE_MIN_NUM_DESC || + ring->rx_pending > ICE_MAX_NUM_DESC || + ring->rx_pending < ICE_MIN_NUM_DESC) { +- netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d]\n", ++ netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", + ring->tx_pending, ring->rx_pending, +- ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC); ++ ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC, ++ ICE_REQ_DESC_MULTIPLE); + return -EINVAL; + } + + new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE); ++ if (new_tx_cnt != ring->tx_pending) ++ netdev_info(netdev, ++ "Requested Tx descriptor count rounded up to %d\n", ++ new_tx_cnt); + new_rx_cnt = ALIGN(ring->rx_pending, ICE_REQ_DESC_MULTIPLE); ++ if (new_rx_cnt != ring->rx_pending) ++ netdev_info(netdev, ++ "Requested Rx descriptor count rounded up to %d\n", ++ new_rx_cnt); + + /* if nothing to do return success */ + if (new_tx_cnt == vsi->tx_rings[0]->count && +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c +index da4322e4daed..add124e0381d 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c +@@ -676,6 +676,9 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs) + } else { + struct tx_sa tsa; + ++ if (adapter->num_vfs) ++ return -EOPNOTSUPP; ++ + /* find the first unused index */ + ret = ixgbe_ipsec_find_empty_idx(ipsec, false); + if (ret < 0) { +diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +index 5a228582423b..4093a9c52c18 100644 +--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c ++++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +@@ -3849,6 +3849,10 @@ static void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring, + skb_checksum_help(skb); + goto no_csum; + } ++ ++ if (first->protocol == htons(ETH_P_IP)) ++ type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; ++ + /* update TX checksum flag */ + first->tx_flags |= IXGBE_TX_FLAGS_CSUM; + vlan_macip_lens = skb_checksum_start_offset(skb) - +diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +index db463e20a876..e9a4179e7e48 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c ++++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +@@ -96,6 +96,7 @@ nfp_devlink_port_split(struct devlink *devlink, unsigned int port_index, + { + struct nfp_pf *pf = devlink_priv(devlink); + struct nfp_eth_table_port eth_port; ++ unsigned int lanes; + int ret; + + if (count < 2) +@@ -114,8 +115,12 @@ nfp_devlink_port_split(struct devlink *devlink, unsigned int port_index, + goto out; + } + +- ret = nfp_devlink_set_lanes(pf, eth_port.index, +- eth_port.port_lanes / count); ++ /* Special case the 100G CXP -> 2x40G split */ ++ lanes = eth_port.port_lanes / count; ++ if (eth_port.lanes == 10 && count == 2) ++ lanes = 8 / count; ++ ++ ret = nfp_devlink_set_lanes(pf, eth_port.index, lanes); + out: + mutex_unlock(&pf->lock); + +@@ -128,6 +133,7 @@ nfp_devlink_port_unsplit(struct devlink *devlink, unsigned int port_index, + { + struct nfp_pf *pf = devlink_priv(devlink); + struct nfp_eth_table_port eth_port; ++ unsigned int lanes; + int ret; + + mutex_lock(&pf->lock); +@@ -143,7 +149,12 @@ nfp_devlink_port_unsplit(struct devlink *devlink, unsigned int port_index, + goto out; + } + +- ret = nfp_devlink_set_lanes(pf, eth_port.index, eth_port.port_lanes); ++ /* Special case the 100G CXP -> 2x40G unsplit */ ++ lanes = eth_port.port_lanes; ++ if (eth_port.port_lanes == 8) ++ lanes = 10; ++ ++ ret = nfp_devlink_set_lanes(pf, eth_port.index, lanes); + out: + mutex_unlock(&pf->lock); + +diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c +index 4289ccb26e4e..d2caeb9edc04 100644 +--- a/drivers/net/ethernet/socionext/netsec.c ++++ b/drivers/net/ethernet/socionext/netsec.c +@@ -940,6 +940,9 @@ static void netsec_uninit_pkt_dring(struct netsec_priv *priv, int id) + dring->head = 0; + dring->tail = 0; + dring->pkt_cnt = 0; ++ ++ if (id == NETSEC_RING_TX) ++ netdev_reset_queue(priv->ndev); + } + + static void netsec_free_dring(struct netsec_priv *priv, int id) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +index f9a61f90cfbc..0f660af01a4b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -714,8 +714,9 @@ static int get_ephy_nodes(struct stmmac_priv *priv) + return -ENODEV; + } + +- mdio_internal = of_find_compatible_node(mdio_mux, NULL, ++ mdio_internal = of_get_compatible_child(mdio_mux, + "allwinner,sun8i-h3-mdio-internal"); ++ of_node_put(mdio_mux); + if (!mdio_internal) { + dev_err(priv->device, "Cannot get internal_mdio node\n"); + return -ENODEV; +@@ -729,13 +730,20 @@ static int get_ephy_nodes(struct stmmac_priv *priv) + gmac->rst_ephy = of_reset_control_get_exclusive(iphynode, NULL); + if (IS_ERR(gmac->rst_ephy)) { + ret = PTR_ERR(gmac->rst_ephy); +- if (ret == -EPROBE_DEFER) ++ if (ret == -EPROBE_DEFER) { ++ of_node_put(iphynode); ++ of_node_put(mdio_internal); + return ret; ++ } + continue; + } + dev_info(priv->device, "Found internal PHY node\n"); ++ of_node_put(iphynode); ++ of_node_put(mdio_internal); + return 0; + } ++ ++ of_node_put(mdio_internal); + return -ENODEV; + } + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index 3af6d8d15233..1c37a821895b 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -2022,14 +2022,15 @@ static void netvsc_vf_setup(struct work_struct *w) + rtnl_unlock(); + } + +-/* Find netvsc by VMBus serial number. +- * The PCI hyperv controller records the serial number as the slot. ++/* Find netvsc by VF serial number. ++ * The PCI hyperv controller records the serial number as the slot kobj name. + */ + static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev) + { + struct device *parent = vf_netdev->dev.parent; + struct net_device_context *ndev_ctx; + struct pci_dev *pdev; ++ u32 serial; + + if (!parent || !dev_is_pci(parent)) + return NULL; /* not a PCI device */ +@@ -2040,16 +2041,22 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev) + return NULL; + } + ++ if (kstrtou32(pci_slot_name(pdev->slot), 10, &serial)) { ++ netdev_notice(vf_netdev, "Invalid vf serial:%s\n", ++ pci_slot_name(pdev->slot)); ++ return NULL; ++ } ++ + list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) { + if (!ndev_ctx->vf_alloc) + continue; + +- if (ndev_ctx->vf_serial == pdev->slot->number) ++ if (ndev_ctx->vf_serial == serial) + return hv_get_drvdata(ndev_ctx->device_ctx); + } + + netdev_notice(vf_netdev, +- "no netdev found for slot %u\n", pdev->slot->number); ++ "no netdev found for vf serial:%u\n", serial); + return NULL; + } + +diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c +index 30612497643c..d192936b76cf 100644 +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -75,6 +75,10 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, + int len; + + skb_tx_timestamp(skb); ++ ++ /* do not fool net_timestamp_check() with various clock bases */ ++ skb->tstamp = 0; ++ + skb_orphan(skb); + + /* Before queueing this packet to netif_rx(), +diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c +index 7ae1856d1f18..5a749dc25bec 100644 +--- a/drivers/net/net_failover.c ++++ b/drivers/net/net_failover.c +@@ -603,6 +603,9 @@ static int net_failover_slave_unregister(struct net_device *slave_dev, + primary_dev = rtnl_dereference(nfo_info->primary_dev); + standby_dev = rtnl_dereference(nfo_info->standby_dev); + ++ if (WARN_ON_ONCE(slave_dev != primary_dev && slave_dev != standby_dev)) ++ return -ENODEV; ++ + vlan_vids_del_by_dev(slave_dev, failover_dev); + dev_uc_unsync(slave_dev, failover_dev); + dev_mc_unsync(slave_dev, failover_dev); +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index 7abca86c3aa9..70f3f90c2ed6 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -907,6 +907,9 @@ void phylink_start(struct phylink *pl) + phylink_an_mode_str(pl->link_an_mode), + phy_modes(pl->link_config.interface)); + ++ /* Always set the carrier off */ ++ netif_carrier_off(pl->netdev); ++ + /* Apply the link configuration to the MAC when starting. This allows + * a fixed-link to start with the correct parameters, and also + * ensures that we set the appropriate advertisement for Serdes links. +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 50e9cc19023a..c52207beef88 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -2264,6 +2264,8 @@ static void tun_setup(struct net_device *dev) + static int tun_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) + { ++ if (!data) ++ return 0; + return -EINVAL; + } + +diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c +index fd612d2905b0..9f31b9a10850 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -1869,6 +1869,12 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id) + if (ret) + dev_kfree_skb_any(skb); + ++ if (ret == -EAGAIN) { ++ ath10k_warn(ar, "wmi command %d timeout, restarting hardware\n", ++ cmd_id); ++ queue_work(ar->workqueue, &ar->restart_work); ++ } ++ + return ret; + } + +@@ -2336,7 +2342,12 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, + dma_unmap_single(ar->dev, pkt_addr->paddr, + msdu->len, DMA_FROM_DEVICE); + info = IEEE80211_SKB_CB(msdu); +- info->flags |= status; ++ ++ if (status) ++ info->flags &= ~IEEE80211_TX_STAT_ACK; ++ else ++ info->flags |= IEEE80211_TX_STAT_ACK; ++ + ieee80211_tx_status_irqsafe(ar->hw, msdu); + + ret = 0; +diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c +index bca61cb44c37..3e7fc2983cbb 100644 +--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c ++++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c +@@ -279,9 +279,6 @@ static void wil_move_all_rx_buff_to_free_list(struct wil6210_priv *wil, + u16 buff_id; + + *d = *_d; +- pa = wil_rx_desc_get_addr_edma(&d->dma); +- dmalen = le16_to_cpu(d->dma.length); +- dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); + + /* Extract the SKB from the rx_buff management array */ + buff_id = __le16_to_cpu(d->mac.buff_id); +@@ -291,10 +288,15 @@ static void wil_move_all_rx_buff_to_free_list(struct wil6210_priv *wil, + } + skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb; + wil->rx_buff_mgmt.buff_arr[buff_id].skb = NULL; +- if (unlikely(!skb)) ++ if (unlikely(!skb)) { + wil_err(wil, "No Rx skb at buff_id %d\n", buff_id); +- else ++ } else { ++ pa = wil_rx_desc_get_addr_edma(&d->dma); ++ dmalen = le16_to_cpu(d->dma.length); ++ dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); ++ + kfree_skb(skb); ++ } + + /* Move the buffer from the active to the free list */ + list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list, +@@ -906,6 +908,9 @@ again: + wil->rx_buff_mgmt.buff_arr[buff_id].skb = NULL; + if (!skb) { + wil_err(wil, "No Rx skb at buff_id %d\n", buff_id); ++ /* Move the buffer from the active list to the free list */ ++ list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list, ++ &wil->rx_buff_mgmt.free); + goto again; + } + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c +index d8b79cb72b58..e7584b842dce 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c +@@ -77,6 +77,8 @@ static u16 d11ac_bw(enum brcmu_chan_bw bw) + return BRCMU_CHSPEC_D11AC_BW_40; + case BRCMU_CHAN_BW_80: + return BRCMU_CHSPEC_D11AC_BW_80; ++ case BRCMU_CHAN_BW_160: ++ return BRCMU_CHSPEC_D11AC_BW_160; + default: + WARN_ON(1); + } +@@ -190,8 +192,38 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch) + break; + } + break; +- case BRCMU_CHSPEC_D11AC_BW_8080: + case BRCMU_CHSPEC_D11AC_BW_160: ++ switch (ch->sb) { ++ case BRCMU_CHAN_SB_LLL: ++ ch->control_ch_num -= CH_70MHZ_APART; ++ break; ++ case BRCMU_CHAN_SB_LLU: ++ ch->control_ch_num -= CH_50MHZ_APART; ++ break; ++ case BRCMU_CHAN_SB_LUL: ++ ch->control_ch_num -= CH_30MHZ_APART; ++ break; ++ case BRCMU_CHAN_SB_LUU: ++ ch->control_ch_num -= CH_10MHZ_APART; ++ break; ++ case BRCMU_CHAN_SB_ULL: ++ ch->control_ch_num += CH_10MHZ_APART; ++ break; ++ case BRCMU_CHAN_SB_ULU: ++ ch->control_ch_num += CH_30MHZ_APART; ++ break; ++ case BRCMU_CHAN_SB_UUL: ++ ch->control_ch_num += CH_50MHZ_APART; ++ break; ++ case BRCMU_CHAN_SB_UUU: ++ ch->control_ch_num += CH_70MHZ_APART; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ break; ++ } ++ break; ++ case BRCMU_CHSPEC_D11AC_BW_8080: + default: + WARN_ON_ONCE(1); + break; +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +index 7b9a77981df1..75b2a0438cfa 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +@@ -29,6 +29,8 @@ + #define CH_UPPER_SB 0x01 + #define CH_LOWER_SB 0x02 + #define CH_EWA_VALID 0x04 ++#define CH_70MHZ_APART 14 ++#define CH_50MHZ_APART 10 + #define CH_30MHZ_APART 6 + #define CH_20MHZ_APART 4 + #define CH_10MHZ_APART 2 +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index 6bb1a99a197a..48a3611d6a31 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -704,8 +704,12 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm) + enabled = !!(wifi_pkg->package.elements[1].integer.value); + n_profiles = wifi_pkg->package.elements[2].integer.value; + +- /* in case of BIOS bug */ +- if (n_profiles <= 0) { ++ /* ++ * Check the validity of n_profiles. The EWRD profiles start ++ * from index 1, so the maximum value allowed here is ++ * ACPI_SAR_PROFILES_NUM - 1. ++ */ ++ if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) { + ret = -EINVAL; + goto out_free; + } +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +index b15b0d84bb7e..155cc2ac0120 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -1233,12 +1233,15 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) + iwl_mvm_del_aux_sta(mvm); + + /* +- * Clear IN_HW_RESTART flag when stopping the hw (as restart_complete() +- * won't be called in this case). ++ * Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the ++ * hw (as restart_complete() won't be called in this case) and mac80211 ++ * won't execute the restart. + * But make sure to cleanup interfaces that have gone down before/during + * HW restart was requested. + */ +- if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) ++ if (test_and_clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) || ++ test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, ++ &mvm->status)) + ieee80211_iterate_interfaces(mvm->hw, 0, + iwl_mvm_cleanup_iterator, mvm); + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +index 30cfd7d50bc9..f2830b5693d2 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +@@ -1239,7 +1239,11 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + !(info->flags & IEEE80211_TX_STAT_AMPDU)) + return; + +- rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); ++ if (rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, ++ &tx_resp_rate)) { ++ WARN_ON_ONCE(1); ++ return; ++ } + + #ifdef CONFIG_MAC80211_DEBUGFS + /* Disable last tx check if we are debugging with fixed rate but +@@ -1290,7 +1294,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + */ + table = &lq_sta->lq; + lq_hwrate = le32_to_cpu(table->rs_table[0]); +- rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate); ++ if (rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate)) { ++ WARN_ON_ONCE(1); ++ return; ++ } + + /* Here we actually compare this rate to the latest LQ command */ + if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) { +@@ -1392,8 +1399,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + /* Collect data for each rate used during failed TX attempts */ + for (i = 0; i <= retries; ++i) { + lq_hwrate = le32_to_cpu(table->rs_table[i]); +- rs_rate_from_ucode_rate(lq_hwrate, info->band, +- &lq_rate); ++ if (rs_rate_from_ucode_rate(lq_hwrate, info->band, ++ &lq_rate)) { ++ WARN_ON_ONCE(1); ++ return; ++ } ++ + /* + * Only collect stats if retried rate is in the same RS + * table as active/search. +@@ -3262,7 +3273,10 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm, + for (i = 0; i < num_rates; i++) + lq_cmd->rs_table[i] = ucode_rate_le32; + +- rs_rate_from_ucode_rate(ucode_rate, band, &rate); ++ if (rs_rate_from_ucode_rate(ucode_rate, band, &rate)) { ++ WARN_ON_ONCE(1); ++ return; ++ } + + if (is_mimo(&rate)) + lq_cmd->mimo_delim = num_rates - 1; +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +index ff193dca2020..2d21f0a1fa00 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +@@ -1405,6 +1405,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, + while (!skb_queue_empty(&skbs)) { + struct sk_buff *skb = __skb_dequeue(&skbs); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_hdr *hdr = (void *)skb->data; + bool flushed = false; + + skb_freed++; +@@ -1449,11 +1450,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + +- /* W/A FW bug: seq_ctl is wrong when the status isn't success */ +- if (status != TX_STATUS_SUCCESS) { +- struct ieee80211_hdr *hdr = (void *)skb->data; ++ /* W/A FW bug: seq_ctl is wrong upon failure / BAR frame */ ++ if (ieee80211_is_back_req(hdr->frame_control)) ++ seq_ctl = 0; ++ else if (status != TX_STATUS_SUCCESS) + seq_ctl = le16_to_cpu(hdr->seq_ctrl); +- } + + if (unlikely(!seq_ctl)) { + struct ieee80211_hdr *hdr = (void *)skb->data; +diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +index d017aa2a0a8b..d4a31e014c82 100644 +--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +@@ -1144,6 +1144,14 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) + kfree(trans_pcie->rxq); + } + ++static void iwl_pcie_rx_move_to_allocator(struct iwl_rxq *rxq, ++ struct iwl_rb_allocator *rba) ++{ ++ spin_lock(&rba->lock); ++ list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); ++ spin_unlock(&rba->lock); ++} ++ + /* + * iwl_pcie_rx_reuse_rbd - Recycle used RBDs + * +@@ -1175,9 +1183,7 @@ static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans, + if ((rxq->used_count % RX_CLAIM_REQ_ALLOC) == RX_POST_REQ_ALLOC) { + /* Move the 2 RBDs to the allocator ownership. + Allocator has another 6 from pool for the request completion*/ +- spin_lock(&rba->lock); +- list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); +- spin_unlock(&rba->lock); ++ iwl_pcie_rx_move_to_allocator(rxq, rba); + + atomic_inc(&rba->req_pending); + queue_work(rba->alloc_wq, &rba->rx_alloc); +@@ -1396,10 +1402,18 @@ restart: + IWL_DEBUG_RX(trans, "Q %d: HW = SW = %d\n", rxq->id, r); + + while (i != r) { ++ struct iwl_rb_allocator *rba = &trans_pcie->rba; + struct iwl_rx_mem_buffer *rxb; +- +- if (unlikely(rxq->used_count == rxq->queue_size / 2)) ++ /* number of RBDs still waiting for page allocation */ ++ u32 rb_pending_alloc = ++ atomic_read(&trans_pcie->rba.req_pending) * ++ RX_CLAIM_REQ_ALLOC; ++ ++ if (unlikely(rb_pending_alloc >= rxq->queue_size / 2 && ++ !emergency)) { ++ iwl_pcie_rx_move_to_allocator(rxq, rba); + emergency = true; ++ } + + rxb = iwl_pcie_get_rxb(trans, rxq, i); + if (!rxb) +@@ -1421,17 +1435,13 @@ restart: + iwl_pcie_rx_allocator_get(trans, rxq); + + if (rxq->used_count % RX_CLAIM_REQ_ALLOC == 0 && !emergency) { +- struct iwl_rb_allocator *rba = &trans_pcie->rba; +- + /* Add the remaining empty RBDs for allocator use */ +- spin_lock(&rba->lock); +- list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty); +- spin_unlock(&rba->lock); ++ iwl_pcie_rx_move_to_allocator(rxq, rba); + } else if (emergency) { + count++; + if (count == 8) { + count = 0; +- if (rxq->used_count < rxq->queue_size / 3) ++ if (rb_pending_alloc < rxq->queue_size / 3) + emergency = false; + + rxq->read = i; +diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c +index c67a8e7be310..3dbfce972c56 100644 +--- a/drivers/net/wireless/marvell/libertas/if_usb.c ++++ b/drivers/net/wireless/marvell/libertas/if_usb.c +@@ -456,8 +456,6 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, + MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, + cardp); + +- cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; +- + lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); + if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) { + lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); +diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c +index e92fc5001171..789337ea676a 100644 +--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c ++++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c +@@ -605,9 +605,10 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, + { + unsigned long flags; + +- if (recvlength > LBS_CMD_BUFFER_SIZE) { ++ if (recvlength < MESSAGE_HEADER_LEN || ++ recvlength > LBS_CMD_BUFFER_SIZE) { + lbtf_deb_usbd(&cardp->udev->dev, +- "The receive buffer is too large\n"); ++ "The receive buffer is invalid: %d\n", recvlength); + kfree_skb(skb); + return; + } +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c +index 23cf437d14f9..1a49d1be042d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c +@@ -128,8 +128,7 @@ __mt76x2_mac_set_beacon(struct mt76x2_dev *dev, u8 bcn_idx, struct sk_buff *skb) + if (skb) { + ret = mt76_write_beacon(dev, beacon_addr, skb); + if (!ret) +- dev->beacon_data_mask |= BIT(bcn_idx) & +- dev->beacon_mask; ++ dev->beacon_data_mask |= BIT(bcn_idx); + } else { + dev->beacon_data_mask &= ~BIT(bcn_idx); + for (i = 0; i < beacon_len; i += 4) +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c +index 1428cfdee579..9594433234cc 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x2_usb.c +@@ -107,16 +107,24 @@ static int __maybe_unused mt76x2u_resume(struct usb_interface *intf) + mt76u_mcu_complete_urb, + &usb->mcu.cmpl); + if (err < 0) +- return err; ++ goto err; + + err = mt76u_submit_rx_buffers(&dev->mt76); + if (err < 0) +- return err; ++ goto err; + + tasklet_enable(&usb->rx_tasklet); + tasklet_enable(&usb->tx_tasklet); + +- return mt76x2u_init_hardware(dev); ++ err = mt76x2u_init_hardware(dev); ++ if (err < 0) ++ goto err; ++ ++ return 0; ++ ++err: ++ mt76x2u_cleanup(dev); ++ return err; + } + + MODULE_DEVICE_TABLE(usb, mt76x2u_device_table); +diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c +index c0a163e40402..f360690396dd 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_usb.c ++++ b/drivers/net/wireless/rsi/rsi_91x_usb.c +@@ -266,15 +266,17 @@ static void rsi_rx_done_handler(struct urb *urb) + if (urb->status) + goto out; + +- if (urb->actual_length <= 0) { +- rsi_dbg(INFO_ZONE, "%s: Zero length packet\n", __func__); ++ if (urb->actual_length <= 0 || ++ urb->actual_length > rx_cb->rx_skb->len) { ++ rsi_dbg(INFO_ZONE, "%s: Invalid packet length = %d\n", ++ __func__, urb->actual_length); + goto out; + } + if (skb_queue_len(&dev->rx_q) >= RSI_MAX_RX_PKTS) { + rsi_dbg(INFO_ZONE, "Max RX packets reached\n"); + goto out; + } +- skb_put(rx_cb->rx_skb, urb->actual_length); ++ skb_trim(rx_cb->rx_skb, urb->actual_length); + skb_queue_tail(&dev->rx_q, rx_cb->rx_skb); + + rsi_set_event(&dev->rx_thread.event); +@@ -308,6 +310,7 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num) + if (!skb) + return -ENOMEM; + skb_reserve(skb, MAX_DWORD_ALIGN_BYTES); ++ skb_put(skb, RSI_MAX_RX_USB_PKT_SIZE - MAX_DWORD_ALIGN_BYTES); + dword_align_bytes = (unsigned long)skb->data & 0x3f; + if (dword_align_bytes > 0) + skb_push(skb, dword_align_bytes); +@@ -319,7 +322,7 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num) + usb_rcvbulkpipe(dev->usbdev, + dev->bulkin_endpoint_addr[ep_num - 1]), + urb->transfer_buffer, +- RSI_MAX_RX_USB_PKT_SIZE, ++ skb->len, + rsi_rx_done_handler, + rx_cb); + +diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c +index 89b0d0fade9f..19e3c5a0b715 100644 +--- a/drivers/net/wireless/ti/wlcore/main.c ++++ b/drivers/net/wireless/ti/wlcore/main.c +@@ -957,6 +957,8 @@ static void wl1271_recovery_work(struct work_struct *work) + BUG_ON(wl->conf.recovery.bug_on_recovery && + !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); + ++ clear_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); ++ + if (wl->conf.recovery.no_recovery) { + wl1271_info("No recovery (chosen on module load). Fw will remain stuck."); + goto out_unlock; +@@ -6710,6 +6712,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) + int ret; + unsigned long start_time = jiffies; + bool pending = false; ++ bool recovery = false; + + /* Nothing to do if no ELP mode requested */ + if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) +@@ -6726,7 +6729,7 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) + + ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); + if (ret < 0) { +- wl12xx_queue_recovery_work(wl); ++ recovery = true; + goto err; + } + +@@ -6734,11 +6737,12 @@ static int __maybe_unused wlcore_runtime_resume(struct device *dev) + ret = wait_for_completion_timeout(&compl, + msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); + if (ret == 0) { +- wl1271_error("ELP wakeup timeout!"); +- wl12xx_queue_recovery_work(wl); ++ wl1271_warning("ELP wakeup timeout!"); + + /* Return no error for runtime PM for recovery */ +- return 0; ++ ret = 0; ++ recovery = true; ++ goto err; + } + } + +@@ -6753,6 +6757,12 @@ err: + spin_lock_irqsave(&wl->wl_lock, flags); + wl->elp_compl = NULL; + spin_unlock_irqrestore(&wl->wl_lock, flags); ++ ++ if (recovery) { ++ set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); ++ wl12xx_queue_recovery_work(wl); ++ } ++ + return ret; + } + +diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c +index 91162f8e0366..9a22056e8d9e 100644 +--- a/drivers/nfc/nfcmrvl/uart.c ++++ b/drivers/nfc/nfcmrvl/uart.c +@@ -73,10 +73,9 @@ static int nfcmrvl_uart_parse_dt(struct device_node *node, + struct device_node *matched_node; + int ret; + +- matched_node = of_find_compatible_node(node, NULL, "marvell,nfc-uart"); ++ matched_node = of_get_compatible_child(node, "marvell,nfc-uart"); + if (!matched_node) { +- matched_node = of_find_compatible_node(node, NULL, +- "mrvl,nfc-uart"); ++ matched_node = of_get_compatible_child(node, "mrvl,nfc-uart"); + if (!matched_node) + return -ENODEV; + } +diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c +index 8aae6dcc839f..9148015ed803 100644 +--- a/drivers/nvdimm/bus.c ++++ b/drivers/nvdimm/bus.c +@@ -488,6 +488,8 @@ static void nd_async_device_register(void *d, async_cookie_t cookie) + put_device(dev); + } + put_device(dev); ++ if (dev->parent) ++ put_device(dev->parent); + } + + static void nd_async_device_unregister(void *d, async_cookie_t cookie) +@@ -507,6 +509,8 @@ void __nd_device_register(struct device *dev) + if (!dev) + return; + dev->bus = &nvdimm_bus_type; ++ if (dev->parent) ++ get_device(dev->parent); + get_device(dev); + async_schedule_domain(nd_async_device_register, dev, + &nd_async_domain); +diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c +index 6071e2942053..2082ae01b9c8 100644 +--- a/drivers/nvdimm/pmem.c ++++ b/drivers/nvdimm/pmem.c +@@ -421,9 +421,11 @@ static int pmem_attach_disk(struct device *dev, + addr = devm_memremap_pages(dev, &pmem->pgmap); + pmem->pfn_flags |= PFN_MAP; + memcpy(&bb_res, &pmem->pgmap.res, sizeof(bb_res)); +- } else ++ } else { + addr = devm_memremap(dev, pmem->phys_addr, + pmem->size, ARCH_MEMREMAP_PMEM); ++ memcpy(&bb_res, &nsio->res, sizeof(bb_res)); ++ } + + /* + * At release time the queue must be frozen before +diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c +index fa37afcd43ff..174a418cb171 100644 +--- a/drivers/nvdimm/region_devs.c ++++ b/drivers/nvdimm/region_devs.c +@@ -560,10 +560,17 @@ static ssize_t region_badblocks_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct nd_region *nd_region = to_nd_region(dev); ++ ssize_t rc; + +- return badblocks_show(&nd_region->bb, buf, 0); +-} ++ device_lock(dev); ++ if (dev->driver) ++ rc = badblocks_show(&nd_region->bb, buf, 0); ++ else ++ rc = -ENXIO; ++ device_unlock(dev); + ++ return rc; ++} + static DEVICE_ATTR(badblocks, 0444, region_badblocks_show, NULL); + + static ssize_t resource_show(struct device *dev, +diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c +index 206d63cb1afc..bcd09d3a44da 100644 +--- a/drivers/nvme/host/fabrics.c ++++ b/drivers/nvme/host/fabrics.c +@@ -552,8 +552,11 @@ blk_status_t nvmf_fail_nonready_command(struct nvme_ctrl *ctrl, + ctrl->state != NVME_CTRL_DEAD && + !blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH)) + return BLK_STS_RESOURCE; +- nvme_req(rq)->status = NVME_SC_ABORT_REQ; +- return BLK_STS_IOERR; ++ ++ nvme_req(rq)->status = NVME_SC_HOST_PATH_ERROR; ++ blk_mq_start_request(rq); ++ nvme_complete_rq(rq); ++ return BLK_STS_OK; + } + EXPORT_SYMBOL_GPL(nvmf_fail_nonready_command); + +diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c +index 9fe3fff818b8..b71c9ad1bf45 100644 +--- a/drivers/nvme/host/multipath.c ++++ b/drivers/nvme/host/multipath.c +@@ -77,6 +77,13 @@ void nvme_failover_req(struct request *req) + queue_work(nvme_wq, &ns->ctrl->ana_work); + } + break; ++ case NVME_SC_HOST_PATH_ERROR: ++ /* ++ * Temporary transport disruption in talking to the controller. ++ * Try to send on a new path. ++ */ ++ nvme_mpath_clear_current_path(ns); ++ break; + default: + /* + * Reset the controller for any non-ANA error as we don't know +diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c +index aa1657831b70..7c530c88b3fb 100644 +--- a/drivers/nvmem/core.c ++++ b/drivers/nvmem/core.c +@@ -516,11 +516,17 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) + goto err_device_del; + } + +- if (config->cells) +- nvmem_add_cells(nvmem, config->cells, config->ncells); ++ if (config->cells) { ++ rval = nvmem_add_cells(nvmem, config->cells, config->ncells); ++ if (rval) ++ goto err_teardown_compat; ++ } + + return nvmem; + ++err_teardown_compat: ++ if (config->compat) ++ device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); + err_device_del: + device_del(&nvmem->dev); + err_put_device: +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 74eaedd5b860..70f5fd08891b 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -67,6 +67,7 @@ bool of_node_name_eq(const struct device_node *np, const char *name) + + return (strlen(name) == len) && (strncmp(node_name, name, len) == 0); + } ++EXPORT_SYMBOL(of_node_name_eq); + + bool of_node_name_prefix(const struct device_node *np, const char *prefix) + { +@@ -75,6 +76,7 @@ bool of_node_name_prefix(const struct device_node *np, const char *prefix) + + return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0; + } ++EXPORT_SYMBOL(of_node_name_prefix); + + int of_n_addr_cells(struct device_node *np) + { +diff --git a/drivers/opp/of.c b/drivers/opp/of.c +index 7af0ddec936b..20988c426650 100644 +--- a/drivers/opp/of.c ++++ b/drivers/opp/of.c +@@ -425,6 +425,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np) + dev_err(dev, "Not all nodes have performance state set (%d: %d)\n", + count, pstate_count); + ret = -ENOENT; ++ _dev_pm_opp_remove_table(opp_table, dev, false); + goto put_opp_table; + } + +diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c +index ce9224a36f62..a32d6dde7a57 100644 +--- a/drivers/pci/controller/dwc/pci-dra7xx.c ++++ b/drivers/pci/controller/dwc/pci-dra7xx.c +@@ -542,7 +542,7 @@ static const struct of_device_id of_dra7xx_pcie_match[] = { + }; + + /* +- * dra7xx_pcie_ep_unaligned_memaccess: workaround for AM572x/AM571x Errata i870 ++ * dra7xx_pcie_unaligned_memaccess: workaround for AM572x/AM571x Errata i870 + * @dra7xx: the dra7xx device where the workaround should be applied + * + * Access to the PCIe slave port that are not 32-bit aligned will result +@@ -552,7 +552,7 @@ static const struct of_device_id of_dra7xx_pcie_match[] = { + * + * To avoid this issue set PCIE_SS1_AXI2OCP_LEGACY_MODE_ENABLE to 1. + */ +-static int dra7xx_pcie_ep_unaligned_memaccess(struct device *dev) ++static int dra7xx_pcie_unaligned_memaccess(struct device *dev) + { + int ret; + struct device_node *np = dev->of_node; +@@ -704,6 +704,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) + + dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, + DEVICE_TYPE_RC); ++ ++ ret = dra7xx_pcie_unaligned_memaccess(dev); ++ if (ret) ++ dev_err(dev, "WA for Errata i870 not applied\n"); ++ + ret = dra7xx_add_pcie_port(dra7xx, pdev); + if (ret < 0) + goto err_gpio; +@@ -717,7 +722,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) + dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, + DEVICE_TYPE_EP); + +- ret = dra7xx_pcie_ep_unaligned_memaccess(dev); ++ ret = dra7xx_pcie_unaligned_memaccess(dev); + if (ret) + goto err_gpio; + +diff --git a/drivers/pci/controller/pcie-cadence-ep.c b/drivers/pci/controller/pcie-cadence-ep.c +index 9e87dd7f9ac3..6692654798d4 100644 +--- a/drivers/pci/controller/pcie-cadence-ep.c ++++ b/drivers/pci/controller/pcie-cadence-ep.c +@@ -258,7 +258,6 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn, + u8 intx, bool is_asserted) + { + struct cdns_pcie *pcie = &ep->pcie; +- u32 r = ep->max_regions - 1; + u32 offset; + u16 status; + u8 msg_code; +@@ -268,8 +267,8 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn, + /* Set the outbound region if needed. */ + if (unlikely(ep->irq_pci_addr != CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY || + ep->irq_pci_fn != fn)) { +- /* Last region was reserved for IRQ writes. */ +- cdns_pcie_set_outbound_region_for_normal_msg(pcie, fn, r, ++ /* First region was reserved for IRQ writes. */ ++ cdns_pcie_set_outbound_region_for_normal_msg(pcie, fn, 0, + ep->irq_phys_addr); + ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY; + ep->irq_pci_fn = fn; +@@ -347,8 +346,8 @@ static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn, + /* Set the outbound region if needed. */ + if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) || + ep->irq_pci_fn != fn)) { +- /* Last region was reserved for IRQ writes. */ +- cdns_pcie_set_outbound_region(pcie, fn, ep->max_regions - 1, ++ /* First region was reserved for IRQ writes. */ ++ cdns_pcie_set_outbound_region(pcie, fn, 0, + false, + ep->irq_phys_addr, + pci_addr & ~pci_addr_mask, +@@ -517,6 +516,8 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev) + goto free_epc_mem; + } + ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE; ++ /* Reserve region 0 for IRQs */ ++ set_bit(0, &ep->ob_region_map); + + return 0; + +diff --git a/drivers/pci/controller/pcie-cadence.c b/drivers/pci/controller/pcie-cadence.c +index 975bcdd6b5c0..cd795f6fc1e2 100644 +--- a/drivers/pci/controller/pcie-cadence.c ++++ b/drivers/pci/controller/pcie-cadence.c +@@ -190,14 +190,16 @@ int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie) + + for (i = 0; i < phy_count; i++) { + of_property_read_string_index(np, "phy-names", i, &name); +- phy[i] = devm_phy_optional_get(dev, name); +- if (IS_ERR(phy)) +- return PTR_ERR(phy); +- ++ phy[i] = devm_phy_get(dev, name); ++ if (IS_ERR(phy[i])) { ++ ret = PTR_ERR(phy[i]); ++ goto err_phy; ++ } + link[i] = device_link_add(dev, &phy[i]->dev, DL_FLAG_STATELESS); + if (!link[i]) { ++ devm_phy_put(dev, phy[i]); + ret = -EINVAL; +- goto err_link; ++ goto err_phy; + } + } + +@@ -207,13 +209,15 @@ int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie) + + ret = cdns_pcie_enable_phy(pcie); + if (ret) +- goto err_link; ++ goto err_phy; + + return 0; + +-err_link: +- while (--i >= 0) ++err_phy: ++ while (--i >= 0) { + device_link_del(link[i]); ++ devm_phy_put(dev, phy[i]); ++ } + + return ret; + } +diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c +index 861dda69f366..c5ff6ca65eab 100644 +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -337,6 +337,17 @@ static struct mtk_pcie_port *mtk_pcie_find_port(struct pci_bus *bus, + { + struct mtk_pcie *pcie = bus->sysdata; + struct mtk_pcie_port *port; ++ struct pci_dev *dev = NULL; ++ ++ /* ++ * Walk the bus hierarchy to get the devfn value ++ * of the port in the root bus. ++ */ ++ while (bus && bus->number) { ++ dev = bus->self; ++ bus = dev->bus; ++ devfn = dev->devfn; ++ } + + list_for_each_entry(port, &pcie->ports, list) + if (port->slot == PCI_SLOT(devfn)) +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index f2ef896464b3..af24ed50a245 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -958,7 +958,6 @@ static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, + } + } + } +- WARN_ON(!!dev->msix_enabled); + + /* Check whether driver already requested for MSI irq */ + if (dev->msi_enabled) { +@@ -1028,8 +1027,6 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, + if (!pci_msi_supported(dev, minvec)) + return -EINVAL; + +- WARN_ON(!!dev->msi_enabled); +- + /* Check whether driver already requested MSI-X irqs */ + if (dev->msix_enabled) { + pci_info(dev, "can't enable MSI (MSI-X already enabled)\n"); +@@ -1039,6 +1036,9 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, + if (maxvec < minvec) + return -ERANGE; + ++ if (WARN_ON_ONCE(dev->msi_enabled)) ++ return -EINVAL; ++ + nvec = pci_msi_vec_count(dev); + if (nvec < 0) + return nvec; +@@ -1087,6 +1087,9 @@ static int __pci_enable_msix_range(struct pci_dev *dev, + if (maxvec < minvec) + return -ERANGE; + ++ if (WARN_ON_ONCE(dev->msix_enabled)) ++ return -EINVAL; ++ + for (;;) { + if (affd) { + nvec = irq_calc_affinity_vectors(minvec, nvec, affd); +diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c +index c2ab57705043..f8436d1c4d45 100644 +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -762,19 +762,33 @@ static void pci_acpi_setup(struct device *dev) + return; + + device_set_wakeup_capable(dev, true); ++ /* ++ * For bridges that can do D3 we enable wake automatically (as ++ * we do for the power management itself in that case). The ++ * reason is that the bridge may have additional methods such as ++ * _DSW that need to be called. ++ */ ++ if (pci_dev->bridge_d3) ++ device_wakeup_enable(dev); ++ + acpi_pci_wakeup(pci_dev, false); + } + + static void pci_acpi_cleanup(struct device *dev) + { + struct acpi_device *adev = ACPI_COMPANION(dev); ++ struct pci_dev *pci_dev = to_pci_dev(dev); + + if (!adev) + return; + + pci_acpi_remove_pm_notifier(adev); +- if (adev->wakeup.flags.valid) ++ if (adev->wakeup.flags.valid) { ++ if (pci_dev->bridge_d3) ++ device_wakeup_disable(dev); ++ + device_set_wakeup_capable(dev, false); ++ } + } + + static bool pci_acpi_bus_match(struct device *dev) +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index 5326916715d2..f78860ce884b 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -991,7 +991,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) + * All PCIe functions are in one slot, remove one function will remove + * the whole slot, so just wait until we are the last function left. + */ +- if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices)) ++ if (!list_empty(&parent->subordinate->devices)) + goto out; + + link = parent->link_state; +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 6bc27b7fd452..c0673a717239 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -3190,7 +3190,11 @@ static void disable_igfx_irq(struct pci_dev *dev) + + pci_iounmap(dev, regs); + } ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0042, disable_igfx_irq); ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0046, disable_igfx_irq); ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x004a, disable_igfx_irq); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0106, disable_igfx_irq); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); + +diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c +index 461e7fd2756f..e9c6b120cf45 100644 +--- a/drivers/pci/remove.c ++++ b/drivers/pci/remove.c +@@ -25,9 +25,6 @@ static void pci_stop_dev(struct pci_dev *dev) + + pci_dev_assign_added(dev, false); + } +- +- if (dev->bus->self) +- pcie_aspm_exit_link_state(dev); + } + + static void pci_destroy_dev(struct pci_dev *dev) +@@ -41,6 +38,7 @@ static void pci_destroy_dev(struct pci_dev *dev) + list_del(&dev->bus_list); + up_write(&pci_bus_sem); + ++ pcie_aspm_exit_link_state(dev); + pci_bridge_d3_update(dev); + pci_free_resources(dev); + put_device(&dev->dev); +diff --git a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h +index 01098c841f87..8ac7b138c094 100644 +--- a/drivers/pcmcia/ricoh.h ++++ b/drivers/pcmcia/ricoh.h +@@ -119,6 +119,10 @@ + #define RL5C4XX_MISC_CONTROL 0x2F /* 8 bit */ + #define RL5C4XX_ZV_ENABLE 0x08 + ++/* Misc Control 3 Register */ ++#define RL5C4XX_MISC3 0x00A2 /* 16 bit */ ++#define RL5C47X_MISC3_CB_CLKRUN_DIS BIT(1) ++ + #ifdef __YENTA_H + + #define rl_misc(socket) ((socket)->private[0]) +@@ -156,6 +160,35 @@ static void ricoh_set_zv(struct yenta_socket *socket) + } + } + ++static void ricoh_set_clkrun(struct yenta_socket *socket, bool quiet) ++{ ++ u16 misc3; ++ ++ /* ++ * RL5C475II likely has this setting, too, however no datasheet ++ * is publicly available for this chip ++ */ ++ if (socket->dev->device != PCI_DEVICE_ID_RICOH_RL5C476 && ++ socket->dev->device != PCI_DEVICE_ID_RICOH_RL5C478) ++ return; ++ ++ if (socket->dev->revision < 0x80) ++ return; ++ ++ misc3 = config_readw(socket, RL5C4XX_MISC3); ++ if (misc3 & RL5C47X_MISC3_CB_CLKRUN_DIS) { ++ if (!quiet) ++ dev_dbg(&socket->dev->dev, ++ "CLKRUN feature already disabled\n"); ++ } else if (disable_clkrun) { ++ if (!quiet) ++ dev_info(&socket->dev->dev, ++ "Disabling CLKRUN feature\n"); ++ misc3 |= RL5C47X_MISC3_CB_CLKRUN_DIS; ++ config_writew(socket, RL5C4XX_MISC3, misc3); ++ } ++} ++ + static void ricoh_save_state(struct yenta_socket *socket) + { + rl_misc(socket) = config_readw(socket, RL5C4XX_MISC); +@@ -172,6 +205,7 @@ static void ricoh_restore_state(struct yenta_socket *socket) + config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket)); + config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket)); + config_writew(socket, RL5C4XX_CONFIG, rl_config(socket)); ++ ricoh_set_clkrun(socket, true); + } + + +@@ -197,6 +231,7 @@ static int ricoh_override(struct yenta_socket *socket) + config_writew(socket, RL5C4XX_CONFIG, config); + + ricoh_set_zv(socket); ++ ricoh_set_clkrun(socket, false); + + return 0; + } +diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c +index ab3da2262f0f..ac6a3f46b1e6 100644 +--- a/drivers/pcmcia/yenta_socket.c ++++ b/drivers/pcmcia/yenta_socket.c +@@ -26,7 +26,8 @@ + + static bool disable_clkrun; + module_param(disable_clkrun, bool, 0444); +-MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option"); ++MODULE_PARM_DESC(disable_clkrun, ++ "If PC card doesn't function properly, please try this option (TI and Ricoh bridges only)"); + + static bool isa_probe = 1; + module_param(isa_probe, bool, 0444); +diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c +index 6556dbeae65e..ac251c62bc66 100644 +--- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c ++++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c +@@ -319,6 +319,8 @@ static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function, + pad->function = function; + + ret = pmic_mpp_write_mode_ctl(state, pad); ++ if (ret < 0) ++ return ret; + + val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT; + +@@ -343,13 +345,12 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev, + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: +- arg = pad->pullup == PMIC_MPP_PULL_UP_OPEN; ++ if (pad->pullup != PMIC_MPP_PULL_UP_OPEN) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (pad->pullup) { +- case PMIC_MPP_PULL_UP_OPEN: +- arg = 0; +- break; + case PMIC_MPP_PULL_UP_0P6KOHM: + arg = 600; + break; +@@ -364,13 +365,17 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev, + } + break; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: +- arg = !pad->is_enabled; ++ if (pad->is_enabled) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_POWER_SOURCE: + arg = pad->power_source; + break; + case PIN_CONFIG_INPUT_ENABLE: +- arg = pad->input_enabled; ++ if (!pad->input_enabled) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_OUTPUT: + arg = pad->out_value; +@@ -382,7 +387,9 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev, + arg = pad->amux_input; + break; + case PMIC_MPP_CONF_PAIRED: +- arg = pad->paired; ++ if (!pad->paired) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = pad->drive_strength; +@@ -455,7 +462,7 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin, + pad->dtest = arg; + break; + case PIN_CONFIG_DRIVE_STRENGTH: +- arg = pad->drive_strength; ++ pad->drive_strength = arg; + break; + case PMIC_MPP_CONF_AMUX_ROUTE: + if (arg >= PMIC_MPP_AMUX_ROUTE_ABUS4) +@@ -502,6 +509,10 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin, + if (ret < 0) + return ret; + ++ ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_SINK_CTL, pad->drive_strength); ++ if (ret < 0) ++ return ret; ++ + val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT; + + return pmic_mpp_write(state, pad, PMIC_MPP_REG_EN_CTL, val); +diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +index f53e32a9d8fc..0e153bae322e 100644 +--- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c ++++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +@@ -260,22 +260,32 @@ static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev, + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: +- arg = pin->bias == PM8XXX_GPIO_BIAS_NP; ++ if (pin->bias != PM8XXX_GPIO_BIAS_NP) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: +- arg = pin->bias == PM8XXX_GPIO_BIAS_PD; ++ if (pin->bias != PM8XXX_GPIO_BIAS_PD) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_BIAS_PULL_UP: +- arg = pin->bias <= PM8XXX_GPIO_BIAS_PU_1P5_30; ++ if (pin->bias > PM8XXX_GPIO_BIAS_PU_1P5_30) ++ return -EINVAL; ++ arg = 1; + break; + case PM8XXX_QCOM_PULL_UP_STRENGTH: + arg = pin->pull_up_strength; + break; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: +- arg = pin->disable; ++ if (!pin->disable) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_INPUT_ENABLE: +- arg = pin->mode == PM8XXX_GPIO_MODE_INPUT; ++ if (pin->mode != PM8XXX_GPIO_MODE_INPUT) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_OUTPUT: + if (pin->mode & PM8XXX_GPIO_MODE_OUTPUT) +@@ -290,10 +300,14 @@ static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev, + arg = pin->output_strength; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: +- arg = !pin->open_drain; ++ if (pin->open_drain) ++ return -EINVAL; ++ arg = 1; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: +- arg = pin->open_drain; ++ if (!pin->open_drain) ++ return -EINVAL; ++ arg = 1; + break; + default: + return -EINVAL; +diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c +index 4d9bf9b3e9f3..26ebedc1f6d3 100644 +--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c ++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c +@@ -1079,10 +1079,9 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) + * We suppose that we won't have any more functions than pins, + * we'll reallocate that later anyway + */ +- pctl->functions = devm_kcalloc(&pdev->dev, +- pctl->ngroups, +- sizeof(*pctl->functions), +- GFP_KERNEL); ++ pctl->functions = kcalloc(pctl->ngroups, ++ sizeof(*pctl->functions), ++ GFP_KERNEL); + if (!pctl->functions) + return -ENOMEM; + +@@ -1133,8 +1132,10 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) + + func_item = sunxi_pinctrl_find_function_by_name(pctl, + func->name); +- if (!func_item) ++ if (!func_item) { ++ kfree(pctl->functions); + return -EINVAL; ++ } + + if (!func_item->groups) { + func_item->groups = +@@ -1142,8 +1143,10 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) + func_item->ngroups, + sizeof(*func_item->groups), + GFP_KERNEL); +- if (!func_item->groups) ++ if (!func_item->groups) { ++ kfree(pctl->functions); + return -ENOMEM; ++ } + } + + func_grp = func_item->groups; +diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c +index bbcaee56db9d..b6a7d9f74cf3 100644 +--- a/drivers/power/supply/twl4030_charger.c ++++ b/drivers/power/supply/twl4030_charger.c +@@ -996,12 +996,13 @@ static int twl4030_bci_probe(struct platform_device *pdev) + if (bci->dev->of_node) { + struct device_node *phynode; + +- phynode = of_find_compatible_node(bci->dev->of_node->parent, +- NULL, "ti,twl4030-usb"); ++ phynode = of_get_compatible_child(bci->dev->of_node->parent, ++ "ti,twl4030-usb"); + if (phynode) { + bci->usb_nb.notifier_call = twl4030_bci_usb_ncb; + bci->transceiver = devm_usb_get_phy_by_node( + bci->dev, phynode, &bci->usb_nb); ++ of_node_put(phynode); + if (IS_ERR(bci->transceiver)) { + ret = PTR_ERR(bci->transceiver); + if (ret == -EPROBE_DEFER) +diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c +index 61a760ee4aac..e9ab90c19304 100644 +--- a/drivers/remoteproc/qcom_q6v5.c ++++ b/drivers/remoteproc/qcom_q6v5.c +@@ -198,6 +198,9 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, + } + + q6v5->fatal_irq = platform_get_irq_byname(pdev, "fatal"); ++ if (q6v5->fatal_irq == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ + ret = devm_request_threaded_irq(&pdev->dev, q6v5->fatal_irq, + NULL, q6v5_fatal_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, +@@ -208,6 +211,9 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, + } + + q6v5->ready_irq = platform_get_irq_byname(pdev, "ready"); ++ if (q6v5->ready_irq == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ + ret = devm_request_threaded_irq(&pdev->dev, q6v5->ready_irq, + NULL, q6v5_ready_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, +@@ -218,6 +224,9 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, + } + + q6v5->handover_irq = platform_get_irq_byname(pdev, "handover"); ++ if (q6v5->handover_irq == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ + ret = devm_request_threaded_irq(&pdev->dev, q6v5->handover_irq, + NULL, q6v5_handover_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, +@@ -229,6 +238,9 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, + disable_irq(q6v5->handover_irq); + + q6v5->stop_irq = platform_get_irq_byname(pdev, "stop-ack"); ++ if (q6v5->stop_irq == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ + ret = devm_request_threaded_irq(&pdev->dev, q6v5->stop_irq, + NULL, q6v5_stop_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, +diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c +index 8da83a4ebadc..b2e5a6abf7d5 100644 +--- a/drivers/rpmsg/qcom_smd.c ++++ b/drivers/rpmsg/qcom_smd.c +@@ -1122,8 +1122,10 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed + + channel->edge = edge; + channel->name = kstrdup(name, GFP_KERNEL); +- if (!channel->name) +- return ERR_PTR(-ENOMEM); ++ if (!channel->name) { ++ ret = -ENOMEM; ++ goto free_channel; ++ } + + spin_lock_init(&channel->tx_lock); + spin_lock_init(&channel->recv_lock); +@@ -1173,6 +1175,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed + + free_name_and_channel: + kfree(channel->name); ++free_channel: + kfree(channel); + + return ERR_PTR(ret); +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index cd3a2411bc2f..df0c5776d49b 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -50,6 +50,7 @@ + /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ + #include + ++#ifdef CONFIG_ACPI + /* + * Use ACPI SCI to replace HPET interrupt for RTC Alarm event + * +@@ -61,6 +62,18 @@ + static bool use_acpi_alarm; + module_param(use_acpi_alarm, bool, 0444); + ++static inline int cmos_use_acpi_alarm(void) ++{ ++ return use_acpi_alarm; ++} ++#else /* !CONFIG_ACPI */ ++ ++static inline int cmos_use_acpi_alarm(void) ++{ ++ return 0; ++} ++#endif ++ + struct cmos_rtc { + struct rtc_device *rtc; + struct device *dev; +@@ -167,9 +180,9 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler) + #endif + + /* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */ +-static int use_hpet_alarm(void) ++static inline int use_hpet_alarm(void) + { +- return is_hpet_enabled() && !use_acpi_alarm; ++ return is_hpet_enabled() && !cmos_use_acpi_alarm(); + } + + /*----------------------------------------------------------------*/ +@@ -340,7 +353,7 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask) + if (use_hpet_alarm()) + hpet_set_rtc_irq_bit(mask); + +- if ((mask & RTC_AIE) && use_acpi_alarm) { ++ if ((mask & RTC_AIE) && cmos_use_acpi_alarm()) { + if (cmos->wake_on) + cmos->wake_on(cmos->dev); + } +@@ -358,7 +371,7 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask) + if (use_hpet_alarm()) + hpet_mask_rtc_irq_bit(mask); + +- if ((mask & RTC_AIE) && use_acpi_alarm) { ++ if ((mask & RTC_AIE) && cmos_use_acpi_alarm()) { + if (cmos->wake_off) + cmos->wake_off(cmos->dev); + } +@@ -980,7 +993,7 @@ static int cmos_suspend(struct device *dev) + } + spin_unlock_irq(&rtc_lock); + +- if ((tmp & RTC_AIE) && !use_acpi_alarm) { ++ if ((tmp & RTC_AIE) && !cmos_use_acpi_alarm()) { + cmos->enabled_wake = 1; + if (cmos->wake_on) + cmos->wake_on(dev); +@@ -1031,7 +1044,7 @@ static void cmos_check_wkalrm(struct device *dev) + * ACPI RTC wake event is cleared after resume from STR, + * ACK the rtc irq here + */ +- if (t_now >= cmos->alarm_expires && use_acpi_alarm) { ++ if (t_now >= cmos->alarm_expires && cmos_use_acpi_alarm()) { + cmos_interrupt(0, (void *)cmos->rtc); + return; + } +@@ -1053,7 +1066,7 @@ static int __maybe_unused cmos_resume(struct device *dev) + struct cmos_rtc *cmos = dev_get_drvdata(dev); + unsigned char tmp; + +- if (cmos->enabled_wake && !use_acpi_alarm) { ++ if (cmos->enabled_wake && !cmos_use_acpi_alarm()) { + if (cmos->wake_off) + cmos->wake_off(dev); + else +@@ -1132,7 +1145,7 @@ static u32 rtc_handler(void *context) + * Or else, ACPI SCI is enabled during suspend/resume only, + * update rtc irq in that case. + */ +- if (use_acpi_alarm) ++ if (cmos_use_acpi_alarm()) + cmos_interrupt(0, (void *)cmos->rtc); + else { + /* Fix me: can we use cmos_interrupt() here as well? */ +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index 4b2b4627daeb..71396b62dc52 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1384,7 +1384,6 @@ static void ds1307_clks_register(struct ds1307 *ds1307) + static const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, +- .max_register = 0x9, + }; + + static int ds1307_probe(struct i2c_client *client, +diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c +index c3fc34b9964d..9e5d3f7d29ae 100644 +--- a/drivers/scsi/esp_scsi.c ++++ b/drivers/scsi/esp_scsi.c +@@ -1338,6 +1338,7 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent, + + bytes_sent = esp->data_dma_len; + bytes_sent -= ecount; ++ bytes_sent -= esp->send_cmd_residual; + + /* + * The am53c974 has a DMA 'pecularity'. The doc states: +diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h +index 8163dca2071b..a77772777a30 100644 +--- a/drivers/scsi/esp_scsi.h ++++ b/drivers/scsi/esp_scsi.h +@@ -540,6 +540,8 @@ struct esp { + + void *dma; + int dmarev; ++ ++ u32 send_cmd_residual; + }; + + /* A front-end driver for the ESP chip should do the following in +diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c +index 5c7858e735c9..200b5bca1f5f 100644 +--- a/drivers/scsi/lpfc/lpfc_scsi.c ++++ b/drivers/scsi/lpfc/lpfc_scsi.c +@@ -4158,9 +4158,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, + } + lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); + +- spin_lock_irqsave(&phba->hbalock, flags); +- lpfc_cmd->pCmd = NULL; +- spin_unlock_irqrestore(&phba->hbalock, flags); ++ /* If pCmd was set to NULL from abort path, do not call scsi_done */ ++ if (xchg(&lpfc_cmd->pCmd, NULL) == NULL) { ++ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, ++ "0711 FCP cmd already NULL, sid: 0x%06x, " ++ "did: 0x%06x, oxid: 0x%04x\n", ++ vport->fc_myDID, ++ (pnode) ? pnode->nlp_DID : 0, ++ phba->sli_rev == LPFC_SLI_REV4 ? ++ lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff); ++ return; ++ } + + /* The sdev is not guaranteed to be valid post scsi_done upcall. */ + cmd->scsi_done(cmd); +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index 9830bdb6e072..a95c823cd1a4 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -3797,6 +3797,7 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba, + struct hbq_dmabuf *dmabuf; + struct lpfc_cq_event *cq_event; + unsigned long iflag; ++ int count = 0; + + spin_lock_irqsave(&phba->hbalock, iflag); + phba->hba_flag &= ~HBA_SP_QUEUE_EVT; +@@ -3818,16 +3819,22 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba, + if (irspiocbq) + lpfc_sli_sp_handle_rspiocb(phba, pring, + irspiocbq); ++ count++; + break; + case CQE_CODE_RECEIVE: + case CQE_CODE_RECEIVE_V1: + dmabuf = container_of(cq_event, struct hbq_dmabuf, + cq_event); + lpfc_sli4_handle_received_buffer(phba, dmabuf); ++ count++; + break; + default: + break; + } ++ ++ /* Limit the number of events to 64 to avoid soft lockups */ ++ if (count == 64) ++ break; + } + } + +diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c +index eb551f3cc471..71879f2207e0 100644 +--- a/drivers/scsi/mac_esp.c ++++ b/drivers/scsi/mac_esp.c +@@ -427,6 +427,8 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, + scsi_esp_cmd(esp, ESP_CMD_TI); + } + } ++ ++ esp->send_cmd_residual = esp_count; + } + + static int mac_esp_irq_pending(struct esp *esp) +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 9aa9590c5373..f6de7526ded5 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -7523,6 +7523,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) + get_user(user_sense_off, &cioc->sense_off)) + return -EFAULT; + ++ if (local_sense_off != user_sense_off) ++ return -EINVAL; ++ + if (local_sense_len) { + void __user **sense_ioc_ptr = + (void __user **)((u8 *)((unsigned long)&ioc->frame.raw) + local_sense_off); +diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c +index 2c6c2cd5a0d0..596a9b214df1 100644 +--- a/drivers/scsi/qla2xxx/qla_mbx.c ++++ b/drivers/scsi/qla2xxx/qla_mbx.c +@@ -493,7 +493,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + } +- } else if (!abort_active) { ++ } else if (current == ha->dpc_thread) { + /* call abort directly since we are in the DPC thread */ + ql_dbg(ql_dbg_mbx, vha, 0x101d, + "Timeout, calling abort_isp.\n"); +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index c55f38ec391c..54074dd483a7 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -1691,8 +1691,9 @@ static void __ufshcd_release(struct ufs_hba *hba) + + hba->clk_gating.state = REQ_CLKS_OFF; + trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); +- schedule_delayed_work(&hba->clk_gating.gate_work, +- msecs_to_jiffies(hba->clk_gating.delay_ms)); ++ queue_delayed_work(hba->clk_gating.clk_gating_workq, ++ &hba->clk_gating.gate_work, ++ msecs_to_jiffies(hba->clk_gating.delay_ms)); + } + + void ufshcd_release(struct ufs_hba *hba) +diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c +index 8a3678c2e83c..97bb5989aa21 100644 +--- a/drivers/soc/qcom/rmtfs_mem.c ++++ b/drivers/soc/qcom/rmtfs_mem.c +@@ -212,6 +212,11 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "failed to parse qcom,vmid\n"); + goto remove_cdev; + } else if (!ret) { ++ if (!qcom_scm_is_available()) { ++ ret = -EPROBE_DEFER; ++ goto remove_cdev; ++ } ++ + perms[0].vmid = QCOM_SCM_VMID_HLOS; + perms[0].perm = QCOM_SCM_PERM_RW; + perms[1].vmid = vmid; +diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c +index 2d6f3fcf3211..ed71a4c9c8b2 100644 +--- a/drivers/soc/tegra/pmc.c ++++ b/drivers/soc/tegra/pmc.c +@@ -1288,7 +1288,7 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) + if (!pmc->soc->has_tsense_reset) + return; + +- np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip"); ++ np = of_get_child_by_name(pmc->dev->of_node, "i2c-thermtrip"); + if (!np) { + dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled); + return; +diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c +index 8612525fa4e3..584bcb018a62 100644 +--- a/drivers/spi/spi-bcm-qspi.c ++++ b/drivers/spi/spi-bcm-qspi.c +@@ -89,7 +89,7 @@ + #define BSPI_BPP_MODE_SELECT_MASK BIT(8) + #define BSPI_BPP_ADDR_SELECT_MASK BIT(16) + +-#define BSPI_READ_LENGTH 512 ++#define BSPI_READ_LENGTH 256 + + /* MSPI register offsets */ + #define MSPI_SPCR0_LSB 0x000 +@@ -355,7 +355,7 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, + int bpc = 0, bpp = 0; + u8 command = op->cmd.opcode; + int width = op->cmd.buswidth ? op->cmd.buswidth : SPI_NBITS_SINGLE; +- int addrlen = op->addr.nbytes * 8; ++ int addrlen = op->addr.nbytes; + int flex_mode = 1; + + dev_dbg(&qspi->pdev->dev, "set flex mode w %x addrlen %x hp %d\n", +diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c +index f1526757aaf6..79fc3940245a 100644 +--- a/drivers/spi/spi-ep93xx.c ++++ b/drivers/spi/spi-ep93xx.c +@@ -246,6 +246,19 @@ static int ep93xx_spi_read_write(struct spi_master *master) + return -EINPROGRESS; + } + ++static enum dma_transfer_direction ++ep93xx_dma_data_to_trans_dir(enum dma_data_direction dir) ++{ ++ switch (dir) { ++ case DMA_TO_DEVICE: ++ return DMA_MEM_TO_DEV; ++ case DMA_FROM_DEVICE: ++ return DMA_DEV_TO_MEM; ++ default: ++ return DMA_TRANS_NONE; ++ } ++} ++ + /** + * ep93xx_spi_dma_prepare() - prepares a DMA transfer + * @master: SPI master +@@ -257,7 +270,7 @@ static int ep93xx_spi_read_write(struct spi_master *master) + */ + static struct dma_async_tx_descriptor * + ep93xx_spi_dma_prepare(struct spi_master *master, +- enum dma_transfer_direction dir) ++ enum dma_data_direction dir) + { + struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct spi_transfer *xfer = master->cur_msg->state; +@@ -277,9 +290,9 @@ ep93xx_spi_dma_prepare(struct spi_master *master, + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + + memset(&conf, 0, sizeof(conf)); +- conf.direction = dir; ++ conf.direction = ep93xx_dma_data_to_trans_dir(dir); + +- if (dir == DMA_DEV_TO_MEM) { ++ if (dir == DMA_FROM_DEVICE) { + chan = espi->dma_rx; + buf = xfer->rx_buf; + sgt = &espi->rx_sgt; +@@ -343,7 +356,8 @@ ep93xx_spi_dma_prepare(struct spi_master *master, + if (!nents) + return ERR_PTR(-ENOMEM); + +- txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir, DMA_CTRL_ACK); ++ txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, conf.direction, ++ DMA_CTRL_ACK); + if (!txd) { + dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir); + return ERR_PTR(-ENOMEM); +@@ -360,13 +374,13 @@ ep93xx_spi_dma_prepare(struct spi_master *master, + * unmapped. + */ + static void ep93xx_spi_dma_finish(struct spi_master *master, +- enum dma_transfer_direction dir) ++ enum dma_data_direction dir) + { + struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct dma_chan *chan; + struct sg_table *sgt; + +- if (dir == DMA_DEV_TO_MEM) { ++ if (dir == DMA_FROM_DEVICE) { + chan = espi->dma_rx; + sgt = &espi->rx_sgt; + } else { +@@ -381,8 +395,8 @@ static void ep93xx_spi_dma_callback(void *callback_param) + { + struct spi_master *master = callback_param; + +- ep93xx_spi_dma_finish(master, DMA_MEM_TO_DEV); +- ep93xx_spi_dma_finish(master, DMA_DEV_TO_MEM); ++ ep93xx_spi_dma_finish(master, DMA_TO_DEVICE); ++ ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE); + + spi_finalize_current_transfer(master); + } +@@ -392,15 +406,15 @@ static int ep93xx_spi_dma_transfer(struct spi_master *master) + struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct dma_async_tx_descriptor *rxd, *txd; + +- rxd = ep93xx_spi_dma_prepare(master, DMA_DEV_TO_MEM); ++ rxd = ep93xx_spi_dma_prepare(master, DMA_FROM_DEVICE); + if (IS_ERR(rxd)) { + dev_err(&master->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd)); + return PTR_ERR(rxd); + } + +- txd = ep93xx_spi_dma_prepare(master, DMA_MEM_TO_DEV); ++ txd = ep93xx_spi_dma_prepare(master, DMA_TO_DEVICE); + if (IS_ERR(txd)) { +- ep93xx_spi_dma_finish(master, DMA_DEV_TO_MEM); ++ ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE); + dev_err(&master->dev, "DMA TX failed: %ld\n", PTR_ERR(txd)); + return PTR_ERR(txd); + } +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 421bfc7dda67..088772ebef9b 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -295,9 +295,11 @@ static int spi_gpio_request(struct device *dev, + spi_gpio->miso = devm_gpiod_get_optional(dev, "miso", GPIOD_IN); + if (IS_ERR(spi_gpio->miso)) + return PTR_ERR(spi_gpio->miso); +- if (!spi_gpio->miso) +- /* HW configuration without MISO pin */ +- *mflags |= SPI_MASTER_NO_RX; ++ /* ++ * No setting SPI_MASTER_NO_RX here - if there is only a MOSI ++ * pin connected the host can still do RX by changing the ++ * direction of the line. ++ */ + + spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW); + if (IS_ERR(spi_gpio->sck)) +@@ -423,7 +425,7 @@ static int spi_gpio_probe(struct platform_device *pdev) + spi_gpio->bitbang.chipselect = spi_gpio_chipselect; + spi_gpio->bitbang.set_line_direction = spi_gpio_set_direction; + +- if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { ++ if ((master_flags & SPI_MASTER_NO_TX) == 0) { + spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; + spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; + spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index e43842c7a31a..eb72dba71d83 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -346,10 +346,25 @@ EXPORT_SYMBOL_GPL(spi_mem_get_name); + int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) + { + struct spi_controller *ctlr = mem->spi->controller; ++ size_t len; ++ ++ len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; + + if (ctlr->mem_ops && ctlr->mem_ops->adjust_op_size) + return ctlr->mem_ops->adjust_op_size(mem, op); + ++ if (!ctlr->mem_ops || !ctlr->mem_ops->exec_op) { ++ if (len > spi_max_transfer_size(mem->spi)) ++ return -EINVAL; ++ ++ op->data.nbytes = min3((size_t)op->data.nbytes, ++ spi_max_transfer_size(mem->spi), ++ spi_max_message_size(mem->spi) - ++ len); ++ if (!op->data.nbytes) ++ return -EINVAL; ++ } ++ + return 0; + } + EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size); +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 86c0156e6c88..fc3093d21b96 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -2754,7 +2754,7 @@ static void target_release_cmd_kref(struct kref *kref) + if (se_sess) { + spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); + list_del_init(&se_cmd->se_cmd_list); +- if (list_empty(&se_sess->sess_cmd_list)) ++ if (se_sess->sess_tearing_down && list_empty(&se_sess->sess_cmd_list)) + wake_up(&se_sess->cmd_list_wq); + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); + } +@@ -2907,7 +2907,7 @@ void target_wait_for_sess_cmds(struct se_session *se_sess) + + spin_lock_irq(&se_sess->sess_cmd_lock); + do { +- ret = wait_event_interruptible_lock_irq_timeout( ++ ret = wait_event_lock_irq_timeout( + se_sess->cmd_list_wq, + list_empty(&se_sess->sess_cmd_list), + se_sess->sess_cmd_lock, 180 * HZ); +diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c +index 3be9519654e5..cf3fad2cb871 100644 +--- a/drivers/tc/tc.c ++++ b/drivers/tc/tc.c +@@ -2,7 +2,7 @@ + * TURBOchannel bus services. + * + * Copyright (c) Harald Koerfgen, 1998 +- * Copyright (c) 2001, 2003, 2005, 2006 Maciej W. Rozycki ++ * Copyright (c) 2001, 2003, 2005, 2006, 2018 Maciej W. Rozycki + * Copyright (c) 2005 James Simmons + * + * This file is subject to the terms and conditions of the GNU +@@ -10,6 +10,7 @@ + * directory of this archive for more details. + */ + #include ++#include + #include + #include + #include +@@ -92,6 +93,11 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) + tdev->dev.bus = &tc_bus_type; + tdev->slot = slot; + ++ /* TURBOchannel has 34-bit DMA addressing (16GiB space). */ ++ tdev->dma_mask = DMA_BIT_MASK(34); ++ tdev->dev.dma_mask = &tdev->dma_mask; ++ tdev->dev.coherent_dma_mask = DMA_BIT_MASK(34); ++ + for (i = 0; i < 8; i++) { + tdev->firmware[i] = + readb(module + offset + TC_FIRM_VER + 4 * i); +diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c +index dd8dd947b7f0..01b0cb994457 100644 +--- a/drivers/thermal/da9062-thermal.c ++++ b/drivers/thermal/da9062-thermal.c +@@ -106,7 +106,7 @@ static void da9062_thermal_poll_on(struct work_struct *work) + THERMAL_EVENT_UNSPECIFIED); + + delay = msecs_to_jiffies(thermal->zone->passive_delay); +- schedule_delayed_work(&thermal->work, delay); ++ queue_delayed_work(system_freezable_wq, &thermal->work, delay); + return; + } + +@@ -125,7 +125,7 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) + struct da9062_thermal *thermal = data; + + disable_irq_nosync(thermal->irq); +- schedule_delayed_work(&thermal->work, 0); ++ queue_delayed_work(system_freezable_wq, &thermal->work, 0); + + return IRQ_HANDLED; + } +diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c +index 78f932822d38..8df2ce94c28d 100644 +--- a/drivers/thermal/rcar_thermal.c ++++ b/drivers/thermal/rcar_thermal.c +@@ -453,6 +453,7 @@ static int rcar_thermal_remove(struct platform_device *pdev) + + rcar_thermal_for_each_priv(priv, common) { + rcar_thermal_irq_disable(priv); ++ cancel_delayed_work_sync(&priv->work); + if (priv->chip->use_of_thermal) + thermal_remove_hwmon_sysfs(priv->zone); + else +diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c +index b4ba2b1dab76..f4d0ef695225 100644 +--- a/drivers/tty/serial/kgdboc.c ++++ b/drivers/tty/serial/kgdboc.c +@@ -130,6 +130,11 @@ static void kgdboc_unregister_kbd(void) + + static int kgdboc_option_setup(char *opt) + { ++ if (!opt) { ++ pr_err("kgdboc: config string not provided\n"); ++ return -EINVAL; ++ } ++ + if (strlen(opt) >= MAX_CONFIG_LEN) { + printk(KERN_ERR "kgdboc: config string too long\n"); + return -ENOSPC; +diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c +index 5f1183b0b89d..476ec4b1b86c 100644 +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -1551,7 +1551,7 @@ static void csi_K(struct vc_data *vc, int vpar) + scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count); + vc->vc_need_wrap = 0; + if (con_should_update(vc)) +- do_update_region(vc, (unsigned long) start, count); ++ do_update_region(vc, (unsigned long)(start + offset), count); + } + + static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */ +diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c +index 70a7981b94b3..9916edda5271 100644 +--- a/drivers/uio/uio.c ++++ b/drivers/uio/uio.c +@@ -274,6 +274,8 @@ static struct class uio_class = { + .dev_groups = uio_groups, + }; + ++bool uio_class_registered; ++ + /* + * device functions + */ +@@ -876,6 +878,9 @@ static int init_uio_class(void) + printk(KERN_ERR "class_register failed for uio\n"); + goto err_class_register; + } ++ ++ uio_class_registered = true; ++ + return 0; + + err_class_register: +@@ -886,6 +891,7 @@ exit: + + static void release_uio_class(void) + { ++ uio_class_registered = false; + class_unregister(&uio_class); + uio_major_cleanup(); + } +@@ -912,6 +918,9 @@ int __uio_register_device(struct module *owner, + struct uio_device *idev; + int ret = 0; + ++ if (!uio_class_registered) ++ return -EPROBE_DEFER; ++ + if (!parent || !info || !info->name || !info->version) + return -EINVAL; + +diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h +index 7e7428e48bfa..4f8b8179ec96 100644 +--- a/drivers/usb/chipidea/otg.h ++++ b/drivers/usb/chipidea/otg.h +@@ -17,7 +17,8 @@ void ci_handle_vbus_change(struct ci_hdrc *ci); + static inline void ci_otg_queue_work(struct ci_hdrc *ci) + { + disable_irq_nosync(ci->irq); +- queue_work(ci->wq, &ci->work); ++ if (queue_work(ci->wq, &ci->work) == false) ++ enable_irq(ci->irq); + } + + #endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */ +diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c +index 2bd6e6bfc241..260010abf9d8 100644 +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -4393,6 +4393,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + struct usb_bus *bus = hcd_to_bus(hcd); + unsigned long flags; ++ int ret; + + dev_dbg(hsotg->dev, "DWC OTG HCD START\n"); + +@@ -4408,6 +4409,13 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) + + dwc2_hcd_reinit(hsotg); + ++ /* enable external vbus supply before resuming root hub */ ++ spin_unlock_irqrestore(&hsotg->lock, flags); ++ ret = dwc2_vbus_supply_init(hsotg); ++ if (ret) ++ return ret; ++ spin_lock_irqsave(&hsotg->lock, flags); ++ + /* Initialize and connect root hub if one is not already attached */ + if (bus->root_hub) { + dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n"); +@@ -4417,7 +4425,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) + + spin_unlock_irqrestore(&hsotg->lock, flags); + +- return dwc2_vbus_supply_init(hsotg); ++ return 0; + } + + /* +@@ -4482,7 +4490,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) + hprt0 |= HPRT0_SUSP; + hprt0 &= ~HPRT0_PWR; + dwc2_writel(hsotg, hprt0, HPRT0); ++ spin_unlock_irqrestore(&hsotg->lock, flags); + dwc2_vbus_supply_exit(hsotg); ++ spin_lock_irqsave(&hsotg->lock, flags); + } + + /* Enter partial_power_down */ +diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c +index 17147b8c771e..8f267be1745d 100644 +--- a/drivers/usb/gadget/udc/atmel_usba_udc.c ++++ b/drivers/usb/gadget/udc/atmel_usba_udc.c +@@ -2017,6 +2017,8 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, + + udc->errata = match->data; + udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc"); ++ if (IS_ERR(udc->pmc)) ++ udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9rl-pmc"); + if (IS_ERR(udc->pmc)) + udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc"); + if (udc->errata && IS_ERR(udc->pmc)) +diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c +index e1656f361e08..67d8a501d994 100644 +--- a/drivers/usb/gadget/udc/renesas_usb3.c ++++ b/drivers/usb/gadget/udc/renesas_usb3.c +@@ -2437,6 +2437,9 @@ static ssize_t renesas_usb3_b_device_write(struct file *file, + else + usb3->forced_b_device = false; + ++ if (usb3->workaround_for_vbus) ++ usb3_disconnect(usb3); ++ + /* Let this driver call usb3_connect() anyway */ + usb3_check_id(usb3); + +diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c +index e98673954020..ec6739ef3129 100644 +--- a/drivers/usb/host/ohci-at91.c ++++ b/drivers/usb/host/ohci-at91.c +@@ -551,6 +551,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) + pdata->overcurrent_pin[i] = + devm_gpiod_get_index_optional(&pdev->dev, "atmel,oc", + i, GPIOD_IN); ++ if (!pdata->overcurrent_pin[i]) ++ continue; + if (IS_ERR(pdata->overcurrent_pin[i])) { + err = PTR_ERR(pdata->overcurrent_pin[i]); + dev_err(&pdev->dev, "unable to claim gpio \"overcurrent\": %d\n", err); +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 7e2a531ba321..12eea73d9f20 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -900,6 +900,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + set_bit(wIndex, &bus_state->resuming_ports); + bus_state->resume_done[wIndex] = timeout; + mod_timer(&hcd->rh_timer, timeout); ++ usb_hcd_start_port_resume(&hcd->self, wIndex); + } + /* Has resume been signalled for USB_RESUME_TIME yet? */ + } else if (time_after_eq(jiffies, +@@ -940,6 +941,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + clear_bit(wIndex, &bus_state->rexit_ports); + } + ++ usb_hcd_end_port_resume(&hcd->self, wIndex); + bus_state->port_c_suspend |= 1 << wIndex; + bus_state->suspended_ports &= ~(1 << wIndex); + } else { +@@ -962,6 +964,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) { + bus_state->resume_done[wIndex] = 0; + clear_bit(wIndex, &bus_state->resuming_ports); ++ usb_hcd_end_port_resume(&hcd->self, wIndex); + } + + +@@ -1337,6 +1340,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + goto error; + + set_bit(wIndex, &bus_state->resuming_ports); ++ usb_hcd_start_port_resume(&hcd->self, wIndex); + xhci_set_link_state(xhci, ports[wIndex], + XDEV_RESUME); + spin_unlock_irqrestore(&xhci->lock, flags); +@@ -1345,6 +1349,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + xhci_set_link_state(xhci, ports[wIndex], + XDEV_U0); + clear_bit(wIndex, &bus_state->resuming_ports); ++ usb_hcd_end_port_resume(&hcd->self, wIndex); + } + bus_state->port_c_suspend |= 1 << wIndex; + +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index f0a99aa0ac58..cd4659703647 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1602,6 +1602,7 @@ static void handle_port_status(struct xhci_hcd *xhci, + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + mod_timer(&hcd->rh_timer, + bus_state->resume_done[hcd_portnum]); ++ usb_hcd_start_port_resume(&hcd->self, hcd_portnum); + bogus_port_status = true; + } + } +diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c +index 4f1f4215f3d6..c74cc9c309b1 100644 +--- a/drivers/usb/typec/tcpm.c ++++ b/drivers/usb/typec/tcpm.c +@@ -1430,8 +1430,8 @@ static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo, + if (pdo_apdo_type(pdo[i]) != APDO_TYPE_PPS) + break; + +- if (pdo_pps_apdo_max_current(pdo[i]) < +- pdo_pps_apdo_max_current(pdo[i - 1])) ++ if (pdo_pps_apdo_max_voltage(pdo[i]) < ++ pdo_pps_apdo_max_voltage(pdo[i - 1])) + return PDO_ERR_PPS_APDO_NOT_SORTED; + else if (pdo_pps_apdo_min_voltage(pdo[i]) == + pdo_pps_apdo_min_voltage(pdo[i - 1]) && +@@ -4116,6 +4116,9 @@ static int tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) + goto port_unlock; + } + ++ /* Round down operating current to align with PPS valid steps */ ++ op_curr = op_curr - (op_curr % RDO_PROG_CURR_MA_STEP); ++ + reinit_completion(&port->pps_complete); + port->pps_data.op_curr = op_curr; + port->pps_status = 0; +@@ -4169,6 +4172,9 @@ static int tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) + goto port_unlock; + } + ++ /* Round down output voltage to align with PPS valid steps */ ++ out_volt = out_volt - (out_volt % RDO_PROG_VOLT_MV_STEP); ++ + reinit_completion(&port->pps_complete); + port->pps_data.out_volt = out_volt; + port->pps_status = 0; +diff --git a/drivers/usb/usbip/vudc_main.c b/drivers/usb/usbip/vudc_main.c +index 3fc22037a82f..390733e6937e 100644 +--- a/drivers/usb/usbip/vudc_main.c ++++ b/drivers/usb/usbip/vudc_main.c +@@ -73,6 +73,10 @@ static int __init init(void) + cleanup: + list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) { + list_del(&udc_dev->dev_entry); ++ /* ++ * Just do platform_device_del() here, put_vudc_device() ++ * calls the platform_device_put() ++ */ + platform_device_del(udc_dev->pdev); + put_vudc_device(udc_dev); + } +@@ -89,7 +93,11 @@ static void __exit cleanup(void) + + list_for_each_entry_safe(udc_dev, udc_dev2, &vudc_devices, dev_entry) { + list_del(&udc_dev->dev_entry); +- platform_device_unregister(udc_dev->pdev); ++ /* ++ * Just do platform_device_del() here, put_vudc_device() ++ * calls the platform_device_put() ++ */ ++ platform_device_del(udc_dev->pdev); + put_vudc_device(udc_dev); + } + platform_driver_unregister(&vudc_driver); +diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c +index 38716eb50408..8a3e8f61b991 100644 +--- a/drivers/video/hdmi.c ++++ b/drivers/video/hdmi.c +@@ -592,10 +592,10 @@ hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col) + return "xvYCC 709"; + case HDMI_EXTENDED_COLORIMETRY_S_YCC_601: + return "sYCC 601"; +- case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601: +- return "Adobe YCC 601"; +- case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB: +- return "Adobe RGB"; ++ case HDMI_EXTENDED_COLORIMETRY_OPYCC_601: ++ return "opYCC 601"; ++ case HDMI_EXTENDED_COLORIMETRY_OPRGB: ++ return "opRGB"; + case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM: + return "BT.2020 Constant Luminance"; + case HDMI_EXTENDED_COLORIMETRY_BT2020: +diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c +index 83fc9aab34e8..3099052e1243 100644 +--- a/drivers/w1/masters/omap_hdq.c ++++ b/drivers/w1/masters/omap_hdq.c +@@ -763,6 +763,8 @@ static int omap_hdq_remove(struct platform_device *pdev) + /* remove module dependency */ + pm_runtime_disable(&pdev->dev); + ++ w1_remove_master_device(&omap_w1_master); ++ + return 0; + } + +diff --git a/drivers/xen/privcmd-buf.c b/drivers/xen/privcmd-buf.c +index df1ed37c3269..de01a6d0059d 100644 +--- a/drivers/xen/privcmd-buf.c ++++ b/drivers/xen/privcmd-buf.c +@@ -21,15 +21,9 @@ + + MODULE_LICENSE("GPL"); + +-static unsigned int limit = 64; +-module_param(limit, uint, 0644); +-MODULE_PARM_DESC(limit, "Maximum number of pages that may be allocated by " +- "the privcmd-buf device per open file"); +- + struct privcmd_buf_private { + struct mutex lock; + struct list_head list; +- unsigned int allocated; + }; + + struct privcmd_buf_vma_private { +@@ -60,13 +54,10 @@ static void privcmd_buf_vmapriv_free(struct privcmd_buf_vma_private *vma_priv) + { + unsigned int i; + +- vma_priv->file_priv->allocated -= vma_priv->n_pages; +- + list_del(&vma_priv->list); + + for (i = 0; i < vma_priv->n_pages; i++) +- if (vma_priv->pages[i]) +- __free_page(vma_priv->pages[i]); ++ __free_page(vma_priv->pages[i]); + + kfree(vma_priv); + } +@@ -146,8 +137,7 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma) + unsigned int i; + int ret = 0; + +- if (!(vma->vm_flags & VM_SHARED) || count > limit || +- file_priv->allocated + count > limit) ++ if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + vma_priv = kzalloc(sizeof(*vma_priv) + count * sizeof(void *), +@@ -155,19 +145,15 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma) + if (!vma_priv) + return -ENOMEM; + +- vma_priv->n_pages = count; +- count = 0; +- for (i = 0; i < vma_priv->n_pages; i++) { ++ for (i = 0; i < count; i++) { + vma_priv->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!vma_priv->pages[i]) + break; +- count++; ++ vma_priv->n_pages++; + } + + mutex_lock(&file_priv->lock); + +- file_priv->allocated += count; +- + vma_priv->file_priv = file_priv; + vma_priv->users = 1; + +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index a6f9ba85dc4b..aa081f806728 100644 +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -303,6 +303,9 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, + */ + flags &= ~(__GFP_DMA | __GFP_HIGHMEM); + ++ /* Convert the size to actually allocated. */ ++ size = 1UL << (order + XEN_PAGE_SHIFT); ++ + /* On ARM this function returns an ioremap'ped virtual address for + * which virt_to_phys doesn't return the corresponding physical + * address. In fact on ARM virt_to_phys only works for kernel direct +@@ -351,6 +354,9 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, + * physical address */ + phys = xen_bus_to_phys(dev_addr); + ++ /* Convert the size to actually allocated. */ ++ size = 1UL << (order + XEN_PAGE_SHIFT); ++ + if (((dev_addr + size - 1 <= dma_mask)) || + range_straddles_page_boundary(phys, size)) + xen_destroy_contiguous_region(phys, order); +diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c +index 63c1494a8d73..2acbfe104e46 100644 +--- a/drivers/xen/xen-balloon.c ++++ b/drivers/xen/xen-balloon.c +@@ -76,12 +76,15 @@ static void watch_target(struct xenbus_watch *watch, + + if (!watch_fired) { + watch_fired = true; +- err = xenbus_scanf(XBT_NIL, "memory", "static-max", "%llu", +- &static_max); +- if (err != 1) +- static_max = new_target; +- else ++ ++ if ((xenbus_scanf(XBT_NIL, "memory", "static-max", ++ "%llu", &static_max) == 1) || ++ (xenbus_scanf(XBT_NIL, "memory", "memory_static_max", ++ "%llu", &static_max) == 1)) + static_max >>= PAGE_SHIFT - 10; ++ else ++ static_max = new_target; ++ + target_diff = (xen_pv_domain() || xen_initial_domain()) ? 0 + : static_max - balloon_stats.target_pages; + } +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index d436fb4c002e..089b46c4d97f 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1050,9 +1050,26 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, + if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent) + parent_start = parent->start; + ++ /* ++ * If we are COWing a node/leaf from the extent, chunk or device trees, ++ * make sure that we do not finish block group creation of pending block ++ * groups. We do this to avoid a deadlock. ++ * COWing can result in allocation of a new chunk, and flushing pending ++ * block groups (btrfs_create_pending_block_groups()) can be triggered ++ * when finishing allocation of a new chunk. Creation of a pending block ++ * group modifies the extent, chunk and device trees, therefore we could ++ * deadlock with ourselves since we are holding a lock on an extent ++ * buffer that btrfs_create_pending_block_groups() may try to COW later. ++ */ ++ if (root == fs_info->extent_root || ++ root == fs_info->chunk_root || ++ root == fs_info->dev_root) ++ trans->can_flush_pending_bgs = false; ++ + cow = btrfs_alloc_tree_block(trans, root, parent_start, + root->root_key.objectid, &disk_key, level, + search_start, empty_size); ++ trans->can_flush_pending_bgs = true; + if (IS_ERR(cow)) + return PTR_ERR(cow); + +diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c +index dec01970d8c5..981434764bb9 100644 +--- a/fs/btrfs/dev-replace.c ++++ b/fs/btrfs/dev-replace.c +@@ -440,6 +440,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info, + break; + case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED: + case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED: ++ ASSERT(0); + ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED; + goto leave; + } +@@ -482,6 +483,10 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info, + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + btrfs_dev_replace_write_lock(dev_replace); ++ dev_replace->replace_state = ++ BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED; ++ dev_replace->srcdev = NULL; ++ dev_replace->tgtdev = NULL; + goto leave; + } + +@@ -503,8 +508,6 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info, + return ret; + + leave: +- dev_replace->srcdev = NULL; +- dev_replace->tgtdev = NULL; + btrfs_dev_replace_write_unlock(dev_replace); + btrfs_destroy_dev_replace_tgtdev(tgt_device); + return ret; +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 2d9074295d7f..51e41e53d4ae 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -2366,6 +2366,9 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans, + insert_reserved); + else + BUG(); ++ if (ret && insert_reserved) ++ btrfs_pin_extent(trans->fs_info, node->bytenr, ++ node->num_bytes, 1); + return ret; + } + +@@ -2911,7 +2914,6 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, + struct btrfs_delayed_ref_head *head; + int ret; + int run_all = count == (unsigned long)-1; +- bool can_flush_pending_bgs = trans->can_flush_pending_bgs; + + /* We'll clean this up in btrfs_cleanup_transaction */ + if (trans->aborted) +@@ -2928,7 +2930,6 @@ again: + #ifdef SCRAMBLE_DELAYED_REFS + delayed_refs->run_delayed_start = find_middle(&delayed_refs->root); + #endif +- trans->can_flush_pending_bgs = false; + ret = __btrfs_run_delayed_refs(trans, count); + if (ret < 0) { + btrfs_abort_transaction(trans, ret); +@@ -2959,7 +2960,6 @@ again: + goto again; + } + out: +- trans->can_flush_pending_bgs = can_flush_pending_bgs; + return 0; + } + +@@ -4533,6 +4533,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags, + goto out; + } else { + ret = 1; ++ space_info->max_extent_size = 0; + } + + space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; +@@ -4554,11 +4555,9 @@ out: + * the block groups that were made dirty during the lifetime of the + * transaction. + */ +- if (trans->can_flush_pending_bgs && +- trans->chunk_bytes_reserved >= (u64)SZ_2M) { ++ if (trans->chunk_bytes_reserved >= (u64)SZ_2M) + btrfs_create_pending_block_groups(trans); +- btrfs_trans_release_chunk_metadata(trans); +- } ++ + return ret; + } + +@@ -6436,6 +6435,7 @@ static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, + space_info->bytes_readonly += num_bytes; + cache->reserved -= num_bytes; + space_info->bytes_reserved -= num_bytes; ++ space_info->max_extent_size = 0; + + if (delalloc) + cache->delalloc_bytes -= num_bytes; +@@ -7233,6 +7233,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info, + struct btrfs_block_group_cache *block_group = NULL; + u64 search_start = 0; + u64 max_extent_size = 0; ++ u64 max_free_space = 0; + u64 empty_cluster = 0; + struct btrfs_space_info *space_info; + int loop = 0; +@@ -7528,8 +7529,8 @@ unclustered_alloc: + spin_lock(&ctl->tree_lock); + if (ctl->free_space < + num_bytes + empty_cluster + empty_size) { +- if (ctl->free_space > max_extent_size) +- max_extent_size = ctl->free_space; ++ max_free_space = max(max_free_space, ++ ctl->free_space); + spin_unlock(&ctl->tree_lock); + goto loop; + } +@@ -7696,6 +7697,8 @@ loop: + } + out: + if (ret == -ENOSPC) { ++ if (!max_extent_size) ++ max_extent_size = max_free_space; + spin_lock(&space_info->lock); + space_info->max_extent_size = max_extent_size; + spin_unlock(&space_info->lock); +@@ -7977,21 +7980,14 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, + } + + path = btrfs_alloc_path(); +- if (!path) { +- btrfs_free_and_pin_reserved_extent(fs_info, +- extent_key.objectid, +- fs_info->nodesize); ++ if (!path) + return -ENOMEM; +- } + + path->leave_spinning = 1; + ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, + &extent_key, size); + if (ret) { + btrfs_free_path(path); +- btrfs_free_and_pin_reserved_extent(fs_info, +- extent_key.objectid, +- fs_info->nodesize); + return ret; + } + +@@ -8119,6 +8115,19 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, + if (IS_ERR(buf)) + return buf; + ++ /* ++ * Extra safety check in case the extent tree is corrupted and extent ++ * allocator chooses to use a tree block which is already used and ++ * locked. ++ */ ++ if (buf->lock_owner == current->pid) { ++ btrfs_err_rl(fs_info, ++"tree block %llu owner %llu already locked by pid=%d, extent tree corruption detected", ++ buf->start, btrfs_header_owner(buf), current->pid); ++ free_extent_buffer(buf); ++ return ERR_PTR(-EUCLEAN); ++ } ++ + btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level); + btrfs_tree_lock(buf); + clean_tree_block(fs_info, buf); +@@ -8763,15 +8772,14 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, + if (eb == root->node) { + if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) + parent = eb->start; +- else +- BUG_ON(root->root_key.objectid != +- btrfs_header_owner(eb)); ++ else if (root->root_key.objectid != btrfs_header_owner(eb)) ++ goto owner_mismatch; + } else { + if (wc->flags[level + 1] & BTRFS_BLOCK_FLAG_FULL_BACKREF) + parent = path->nodes[level + 1]->start; +- else +- BUG_ON(root->root_key.objectid != +- btrfs_header_owner(path->nodes[level + 1])); ++ else if (root->root_key.objectid != ++ btrfs_header_owner(path->nodes[level + 1])) ++ goto owner_mismatch; + } + + btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1); +@@ -8779,6 +8787,11 @@ out: + wc->refs[level] = 0; + wc->flags[level] = 0; + return 0; ++ ++owner_mismatch: ++ btrfs_err_rl(fs_info, "unexpected tree owner, have %llu expect %llu", ++ btrfs_header_owner(eb), root->root_key.objectid); ++ return -EUCLEAN; + } + + static noinline int walk_down_tree(struct btrfs_trans_handle *trans, +@@ -8832,6 +8845,8 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans, + ret = walk_up_proc(trans, root, path, wc); + if (ret > 0) + return 0; ++ if (ret < 0) ++ return ret; + + if (path->locks[level]) { + btrfs_tree_unlock_rw(path->nodes[level], +@@ -9613,6 +9628,7 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info) + + block_group = btrfs_lookup_first_block_group(info, last); + while (block_group) { ++ wait_block_group_cache_done(block_group); + spin_lock(&block_group->lock); + if (block_group->iref) + break; +@@ -10074,15 +10090,19 @@ error: + void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans) + { + struct btrfs_fs_info *fs_info = trans->fs_info; +- struct btrfs_block_group_cache *block_group, *tmp; ++ struct btrfs_block_group_cache *block_group; + struct btrfs_root *extent_root = fs_info->extent_root; + struct btrfs_block_group_item item; + struct btrfs_key key; + int ret = 0; +- bool can_flush_pending_bgs = trans->can_flush_pending_bgs; + +- trans->can_flush_pending_bgs = false; +- list_for_each_entry_safe(block_group, tmp, &trans->new_bgs, bg_list) { ++ if (!trans->can_flush_pending_bgs) ++ return; ++ ++ while (!list_empty(&trans->new_bgs)) { ++ block_group = list_first_entry(&trans->new_bgs, ++ struct btrfs_block_group_cache, ++ bg_list); + if (ret) + goto next; + +@@ -10103,7 +10123,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans) + next: + list_del_init(&block_group->bg_list); + } +- trans->can_flush_pending_bgs = can_flush_pending_bgs; ++ btrfs_trans_release_chunk_metadata(trans); + } + + int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used, +@@ -10753,14 +10773,16 @@ int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, + * We don't want a transaction for this since the discard may take a + * substantial amount of time. We don't require that a transaction be + * running, but we do need to take a running transaction into account +- * to ensure that we're not discarding chunks that were released in +- * the current transaction. ++ * to ensure that we're not discarding chunks that were released or ++ * allocated in the current transaction. + * + * Holding the chunks lock will prevent other threads from allocating + * or releasing chunks, but it won't prevent a running transaction + * from committing and releasing the memory that the pending chunks + * list head uses. For that, we need to take a reference to the +- * transaction. ++ * transaction and hold the commit root sem. We only need to hold ++ * it while performing the free space search since we have already ++ * held back allocations. + */ + static int btrfs_trim_free_extents(struct btrfs_device *device, + u64 minlen, u64 *trimmed) +@@ -10770,6 +10792,10 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, + + *trimmed = 0; + ++ /* Discard not supported = nothing to do. */ ++ if (!blk_queue_discard(bdev_get_queue(device->bdev))) ++ return 0; ++ + /* Not writeable = nothing to do. */ + if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) + return 0; +@@ -10787,9 +10813,13 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, + + ret = mutex_lock_interruptible(&fs_info->chunk_mutex); + if (ret) +- return ret; ++ break; + +- down_read(&fs_info->commit_root_sem); ++ ret = down_read_killable(&fs_info->commit_root_sem); ++ if (ret) { ++ mutex_unlock(&fs_info->chunk_mutex); ++ break; ++ } + + spin_lock(&fs_info->trans_lock); + trans = fs_info->running_transaction; +@@ -10797,13 +10827,17 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, + refcount_inc(&trans->use_count); + spin_unlock(&fs_info->trans_lock); + ++ if (!trans) ++ up_read(&fs_info->commit_root_sem); ++ + ret = find_free_dev_extent_start(trans, device, minlen, start, + &start, &len); +- if (trans) ++ if (trans) { ++ up_read(&fs_info->commit_root_sem); + btrfs_put_transaction(trans); ++ } + + if (ret) { +- up_read(&fs_info->commit_root_sem); + mutex_unlock(&fs_info->chunk_mutex); + if (ret == -ENOSPC) + ret = 0; +@@ -10811,7 +10845,6 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, + } + + ret = btrfs_issue_discard(device->bdev, start, len, &bytes); +- up_read(&fs_info->commit_root_sem); + mutex_unlock(&fs_info->chunk_mutex); + + if (ret) +@@ -10831,6 +10864,15 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, + return ret; + } + ++/* ++ * Trim the whole filesystem by: ++ * 1) trimming the free space in each block group ++ * 2) trimming the unallocated space on each device ++ * ++ * This will also continue trimming even if a block group or device encounters ++ * an error. The return value will be the last error, or 0 if nothing bad ++ * happens. ++ */ + int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + { + struct btrfs_block_group_cache *cache = NULL; +@@ -10840,18 +10882,14 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + u64 start; + u64 end; + u64 trimmed = 0; +- u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy); ++ u64 bg_failed = 0; ++ u64 dev_failed = 0; ++ int bg_ret = 0; ++ int dev_ret = 0; + int ret = 0; + +- /* +- * try to trim all FS space, our block group may start from non-zero. +- */ +- if (range->len == total_bytes) +- cache = btrfs_lookup_first_block_group(fs_info, range->start); +- else +- cache = btrfs_lookup_block_group(fs_info, range->start); +- +- while (cache) { ++ cache = btrfs_lookup_first_block_group(fs_info, range->start); ++ for (; cache; cache = next_block_group(fs_info, cache)) { + if (cache->key.objectid >= (range->start + range->len)) { + btrfs_put_block_group(cache); + break; +@@ -10865,13 +10903,15 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + if (!block_group_cache_done(cache)) { + ret = cache_block_group(cache, 0); + if (ret) { +- btrfs_put_block_group(cache); +- break; ++ bg_failed++; ++ bg_ret = ret; ++ continue; + } + ret = wait_block_group_cache_done(cache); + if (ret) { +- btrfs_put_block_group(cache); +- break; ++ bg_failed++; ++ bg_ret = ret; ++ continue; + } + } + ret = btrfs_trim_block_group(cache, +@@ -10882,28 +10922,40 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) + + trimmed += group_trimmed; + if (ret) { +- btrfs_put_block_group(cache); +- break; ++ bg_failed++; ++ bg_ret = ret; ++ continue; + } + } +- +- cache = next_block_group(fs_info, cache); + } + ++ if (bg_failed) ++ btrfs_warn(fs_info, ++ "failed to trim %llu block group(s), last error %d", ++ bg_failed, bg_ret); + mutex_lock(&fs_info->fs_devices->device_list_mutex); +- devices = &fs_info->fs_devices->alloc_list; +- list_for_each_entry(device, devices, dev_alloc_list) { ++ devices = &fs_info->fs_devices->devices; ++ list_for_each_entry(device, devices, dev_list) { + ret = btrfs_trim_free_extents(device, range->minlen, + &group_trimmed); +- if (ret) ++ if (ret) { ++ dev_failed++; ++ dev_ret = ret; + break; ++ } + + trimmed += group_trimmed; + } + mutex_unlock(&fs_info->fs_devices->device_list_mutex); + ++ if (dev_failed) ++ btrfs_warn(fs_info, ++ "failed to trim %llu device(s), last error %d", ++ dev_failed, dev_ret); + range->len = trimmed; +- return ret; ++ if (bg_ret) ++ return bg_ret; ++ return dev_ret; + } + + /* +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 2be00e873e92..7d81cc415264 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -531,6 +531,14 @@ int btrfs_dirty_pages(struct inode *inode, struct page **pages, + + end_of_last_block = start_pos + num_bytes - 1; + ++ /* ++ * The pages may have already been dirty, clear out old accounting so ++ * we can set things up properly ++ */ ++ clear_extent_bit(&BTRFS_I(inode)->io_tree, start_pos, end_of_last_block, ++ EXTENT_DIRTY | EXTENT_DELALLOC | ++ EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0, cached); ++ + if (!btrfs_is_free_space_inode(BTRFS_I(inode))) { + if (start_pos >= isize && + !(BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC)) { +@@ -1500,18 +1508,27 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages, + } + if (ordered) + btrfs_put_ordered_extent(ordered); +- clear_extent_bit(&inode->io_tree, start_pos, last_pos, +- EXTENT_DIRTY | EXTENT_DELALLOC | +- EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, +- 0, 0, cached_state); ++ + *lockstart = start_pos; + *lockend = last_pos; + ret = 1; + } + ++ /* ++ * It's possible the pages are dirty right now, but we don't want ++ * to clean them yet because copy_from_user may catch a page fault ++ * and we might have to fall back to one page at a time. If that ++ * happens, we'll unlock these pages and we'd have a window where ++ * reclaim could sneak in and drop the once-dirty page on the floor ++ * without writing it. ++ * ++ * We have the pages locked and the extent range locked, so there's ++ * no way someone can start IO on any dirty pages in this range. ++ * ++ * We'll call btrfs_dirty_pages() later on, and that will flip around ++ * delalloc bits and dirty the pages as required. ++ */ + for (i = 0; i < num_pages; i++) { +- if (clear_page_dirty_for_io(pages[i])) +- account_page_redirty(pages[i]); + set_page_extent_mapped(pages[i]); + WARN_ON(!PageLocked(pages[i])); + } +@@ -2061,6 +2078,14 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + goto out; + + inode_lock(inode); ++ ++ /* ++ * We take the dio_sem here because the tree log stuff can race with ++ * lockless dio writes and get an extent map logged for an extent we ++ * never waited on. We need it this high up for lockdep reasons. ++ */ ++ down_write(&BTRFS_I(inode)->dio_sem); ++ + atomic_inc(&root->log_batch); + + /* +@@ -2069,6 +2094,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + */ + ret = btrfs_wait_ordered_range(inode, start, len); + if (ret) { ++ up_write(&BTRFS_I(inode)->dio_sem); + inode_unlock(inode); + goto out; + } +@@ -2092,6 +2118,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + * checked called fsync. + */ + ret = filemap_check_wb_err(inode->i_mapping, file->f_wb_err); ++ up_write(&BTRFS_I(inode)->dio_sem); + inode_unlock(inode); + goto out; + } +@@ -2110,6 +2137,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + trans = btrfs_start_transaction(root, 0); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); ++ up_write(&BTRFS_I(inode)->dio_sem); + inode_unlock(inode); + goto out; + } +@@ -2131,6 +2159,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + * file again, but that will end up using the synchronization + * inside btrfs_sync_log to keep things safe. + */ ++ up_write(&BTRFS_I(inode)->dio_sem); + inode_unlock(inode); + + /* +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 0adf38b00fa0..8ecf8c0e5fe6 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include "ctree.h" + #include "free-space-cache.h" + #include "transaction.h" +@@ -47,6 +48,7 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root, + struct btrfs_free_space_header *header; + struct extent_buffer *leaf; + struct inode *inode = NULL; ++ unsigned nofs_flag; + int ret; + + key.objectid = BTRFS_FREE_SPACE_OBJECTID; +@@ -68,7 +70,13 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root, + btrfs_disk_key_to_cpu(&location, &disk_key); + btrfs_release_path(path); + ++ /* ++ * We are often under a trans handle at this point, so we need to make ++ * sure NOFS is set to keep us from deadlocking. ++ */ ++ nofs_flag = memalloc_nofs_save(); + inode = btrfs_iget(fs_info->sb, &location, root, NULL); ++ memalloc_nofs_restore(nofs_flag); + if (IS_ERR(inode)) + return inode; + +@@ -1679,6 +1687,8 @@ static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, + bitmap_clear(info->bitmap, start, count); + + info->bytes -= bytes; ++ if (info->max_extent_size > ctl->unit) ++ info->max_extent_size = 0; + } + + static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, +@@ -1762,6 +1772,13 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl, + return -1; + } + ++static inline u64 get_max_extent_size(struct btrfs_free_space *entry) ++{ ++ if (entry->bitmap) ++ return entry->max_extent_size; ++ return entry->bytes; ++} ++ + /* Cache the size of the max extent in bytes */ + static struct btrfs_free_space * + find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, +@@ -1783,8 +1800,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, + for (node = &entry->offset_index; node; node = rb_next(node)) { + entry = rb_entry(node, struct btrfs_free_space, offset_index); + if (entry->bytes < *bytes) { +- if (entry->bytes > *max_extent_size) +- *max_extent_size = entry->bytes; ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + continue; + } + +@@ -1802,8 +1819,8 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, + } + + if (entry->bytes < *bytes + align_off) { +- if (entry->bytes > *max_extent_size) +- *max_extent_size = entry->bytes; ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + continue; + } + +@@ -1815,8 +1832,10 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, + *offset = tmp; + *bytes = size; + return entry; +- } else if (size > *max_extent_size) { +- *max_extent_size = size; ++ } else { ++ *max_extent_size = ++ max(get_max_extent_size(entry), ++ *max_extent_size); + } + continue; + } +@@ -2440,6 +2459,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, + struct rb_node *n; + int count = 0; + ++ spin_lock(&ctl->tree_lock); + for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) { + info = rb_entry(n, struct btrfs_free_space, offset_index); + if (info->bytes >= bytes && !block_group->ro) +@@ -2448,6 +2468,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, + info->offset, info->bytes, + (info->bitmap) ? "yes" : "no"); + } ++ spin_unlock(&ctl->tree_lock); + btrfs_info(fs_info, "block group has cluster?: %s", + list_empty(&block_group->cluster_list) ? "no" : "yes"); + btrfs_info(fs_info, +@@ -2676,8 +2697,8 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, + + err = search_bitmap(ctl, entry, &search_start, &search_bytes, true); + if (err) { +- if (search_bytes > *max_extent_size) +- *max_extent_size = search_bytes; ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + return 0; + } + +@@ -2714,8 +2735,9 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, + + entry = rb_entry(node, struct btrfs_free_space, offset_index); + while (1) { +- if (entry->bytes < bytes && entry->bytes > *max_extent_size) +- *max_extent_size = entry->bytes; ++ if (entry->bytes < bytes) ++ *max_extent_size = max(get_max_extent_size(entry), ++ *max_extent_size); + + if (entry->bytes < bytes || + (!entry->bitmap && entry->offset < min_start)) { +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 3ea5339603cf..83268d8f48c4 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -503,6 +503,7 @@ again: + pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS); + if (!pages) { + /* just bail out to the uncompressed code */ ++ nr_pages = 0; + goto cont; + } + +@@ -2944,6 +2945,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) + bool truncated = false; + bool range_locked = false; + bool clear_new_delalloc_bytes = false; ++ bool clear_reserved_extent = true; + + if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) && + !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags) && +@@ -3047,10 +3049,12 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent) + logical_len, logical_len, + compress_type, 0, 0, + BTRFS_FILE_EXTENT_REG); +- if (!ret) ++ if (!ret) { ++ clear_reserved_extent = false; + btrfs_release_delalloc_bytes(fs_info, + ordered_extent->start, + ordered_extent->disk_len); ++ } + } + unpin_extent_cache(&BTRFS_I(inode)->extent_tree, + ordered_extent->file_offset, ordered_extent->len, +@@ -3111,8 +3115,13 @@ out: + * wrong we need to return the space for this ordered extent + * back to the allocator. We only free the extent in the + * truncated case if we didn't write out the extent at all. ++ * ++ * If we made it past insert_reserved_file_extent before we ++ * errored out then we don't need to do this as the accounting ++ * has already been done. + */ + if ((ret || !logical_len) && ++ clear_reserved_extent && + !test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) && + !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) + btrfs_free_reserved_extent(fs_info, +@@ -5274,11 +5283,13 @@ static void evict_inode_truncate_pages(struct inode *inode) + struct extent_state *cached_state = NULL; + u64 start; + u64 end; ++ unsigned state_flags; + + node = rb_first(&io_tree->state); + state = rb_entry(node, struct extent_state, rb_node); + start = state->start; + end = state->end; ++ state_flags = state->state; + spin_unlock(&io_tree->lock); + + lock_extent_bits(io_tree, start, end, &cached_state); +@@ -5291,7 +5302,7 @@ static void evict_inode_truncate_pages(struct inode *inode) + * + * Note, end is the bytenr of last byte, so we need + 1 here. + */ +- if (state->state & EXTENT_DELALLOC) ++ if (state_flags & EXTENT_DELALLOC) + btrfs_qgroup_free_data(inode, NULL, start, end - start + 1); + + clear_extent_bit(io_tree, start, end, +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index d60b6caf09e8..bd4767f562cd 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -491,7 +491,6 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) + struct fstrim_range range; + u64 minlen = ULLONG_MAX; + u64 num_devices = 0; +- u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy); + int ret; + + if (!capable(CAP_SYS_ADMIN)) +@@ -515,11 +514,15 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) + return -EOPNOTSUPP; + if (copy_from_user(&range, arg, sizeof(range))) + return -EFAULT; +- if (range.start > total_bytes || +- range.len < fs_info->sb->s_blocksize) ++ ++ /* ++ * NOTE: Don't truncate the range using super->total_bytes. Bytenr of ++ * block group is in the logical address space, which can be any ++ * sectorsize aligned bytenr in the range [0, U64_MAX]. ++ */ ++ if (range.len < fs_info->sb->s_blocksize) + return -EINVAL; + +- range.len = min(range.len, total_bytes - range.start); + range.minlen = max(range.minlen, minlen); + ret = btrfs_trim_fs(fs_info, &range); + if (ret < 0) +diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c +index d4917c0cddf5..b070401406be 100644 +--- a/fs/btrfs/qgroup.c ++++ b/fs/btrfs/qgroup.c +@@ -2897,6 +2897,7 @@ qgroup_rescan_zero_tracking(struct btrfs_fs_info *fs_info) + qgroup->rfer_cmpr = 0; + qgroup->excl = 0; + qgroup->excl_cmpr = 0; ++ qgroup_dirty(fs_info, qgroup); + } + spin_unlock(&fs_info->qgroup_lock); + } +@@ -3106,6 +3107,10 @@ static int __btrfs_qgroup_release_data(struct inode *inode, + int trace_op = QGROUP_RELEASE; + int ret; + ++ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, ++ &BTRFS_I(inode)->root->fs_info->flags)) ++ return 0; ++ + /* In release case, we shouldn't have @reserved */ + WARN_ON(!free && reserved); + if (free && reserved) +diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h +index 54b8bb282c0e..4bbcc1e92a93 100644 +--- a/fs/btrfs/qgroup.h ++++ b/fs/btrfs/qgroup.h +@@ -249,6 +249,8 @@ void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info, + static inline void btrfs_qgroup_free_delayed_ref(struct btrfs_fs_info *fs_info, + u64 ref_root, u64 num_bytes) + { ++ if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) ++ return; + trace_btrfs_qgroup_free_delayed_ref(fs_info, ref_root, num_bytes); + btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes, + BTRFS_QGROUP_RSV_DATA); +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 8783a1776540..60bf8dfe7df4 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -1281,7 +1281,7 @@ static void __del_reloc_root(struct btrfs_root *root) + struct mapping_node *node = NULL; + struct reloc_control *rc = fs_info->reloc_ctl; + +- if (rc) { ++ if (rc && root->node) { + spin_lock(&rc->reloc_root_tree.lock); + rb_node = tree_search(&rc->reloc_root_tree.rb_root, + root->node->start); +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 3b84f5015029..bb8f6c020d22 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1929,6 +1929,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + return ret; + } + ++ btrfs_trans_release_metadata(trans); ++ trans->block_rsv = NULL; ++ + /* make a pass through all the delayed refs we have so far + * any runnings procs may add more while we are here + */ +@@ -1938,9 +1941,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + return ret; + } + +- btrfs_trans_release_metadata(trans); +- trans->block_rsv = NULL; +- + cur_trans = trans->transaction; + + /* +@@ -2280,15 +2280,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans) + + kmem_cache_free(btrfs_trans_handle_cachep, trans); + +- /* +- * If fs has been frozen, we can not handle delayed iputs, otherwise +- * it'll result in deadlock about SB_FREEZE_FS. +- */ +- if (current != fs_info->transaction_kthread && +- current != fs_info->cleaner_kthread && +- !test_bit(BTRFS_FS_FROZEN, &fs_info->flags)) +- btrfs_run_delayed_iputs(fs_info); +- + return ret; + + scrub_continue: +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 3c2ae0e4f25a..d0bcfbfc0e3a 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -258,6 +258,13 @@ struct walk_control { + /* what stage of the replay code we're currently in */ + int stage; + ++ /* ++ * Ignore any items from the inode currently being processed. Needs ++ * to be set every time we find a BTRFS_INODE_ITEM_KEY and we are in ++ * the LOG_WALK_REPLAY_INODES stage. ++ */ ++ bool ignore_cur_inode; ++ + /* the root we are currently replaying */ + struct btrfs_root *replay_dest; + +@@ -2487,6 +2494,20 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, + + inode_item = btrfs_item_ptr(eb, i, + struct btrfs_inode_item); ++ /* ++ * If we have a tmpfile (O_TMPFILE) that got fsync'ed ++ * and never got linked before the fsync, skip it, as ++ * replaying it is pointless since it would be deleted ++ * later. We skip logging tmpfiles, but it's always ++ * possible we are replaying a log created with a kernel ++ * that used to log tmpfiles. ++ */ ++ if (btrfs_inode_nlink(eb, inode_item) == 0) { ++ wc->ignore_cur_inode = true; ++ continue; ++ } else { ++ wc->ignore_cur_inode = false; ++ } + ret = replay_xattr_deletes(wc->trans, root, log, + path, key.objectid); + if (ret) +@@ -2524,16 +2545,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, + root->fs_info->sectorsize); + ret = btrfs_drop_extents(wc->trans, root, inode, + from, (u64)-1, 1); +- /* +- * If the nlink count is zero here, the iput +- * will free the inode. We bump it to make +- * sure it doesn't get freed until the link +- * count fixup is done. +- */ + if (!ret) { +- if (inode->i_nlink == 0) +- inc_nlink(inode); +- /* Update link count and nbytes. */ ++ /* Update the inode's nbytes. */ + ret = btrfs_update_inode(wc->trans, + root, inode); + } +@@ -2548,6 +2561,9 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, + break; + } + ++ if (wc->ignore_cur_inode) ++ continue; ++ + if (key.type == BTRFS_DIR_INDEX_KEY && + wc->stage == LOG_WALK_REPLAY_DIR_INDEX) { + ret = replay_one_dir_item(wc->trans, root, path, +@@ -3196,9 +3212,12 @@ static void free_log_tree(struct btrfs_trans_handle *trans, + }; + + ret = walk_log_tree(trans, log, &wc); +- /* I don't think this can happen but just in case */ +- if (ret) +- btrfs_abort_transaction(trans, ret); ++ if (ret) { ++ if (trans) ++ btrfs_abort_transaction(trans, ret); ++ else ++ btrfs_handle_fs_error(log->fs_info, ret, NULL); ++ } + + while (1) { + ret = find_first_extent_bit(&log->dirty_log_pages, +@@ -4374,7 +4393,6 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, + + INIT_LIST_HEAD(&extents); + +- down_write(&inode->dio_sem); + write_lock(&tree->lock); + test_gen = root->fs_info->last_trans_committed; + logged_start = start; +@@ -4440,7 +4458,6 @@ process: + } + WARN_ON(!list_empty(&extents)); + write_unlock(&tree->lock); +- up_write(&inode->dio_sem); + + btrfs_release_path(path); + if (!ret) +@@ -4636,7 +4653,8 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, + ASSERT(len == i_size || + (len == fs_info->sectorsize && + btrfs_file_extent_compression(leaf, extent) != +- BTRFS_COMPRESS_NONE)); ++ BTRFS_COMPRESS_NONE) || ++ (len < i_size && i_size < fs_info->sectorsize)); + return 0; + } + +@@ -5564,9 +5582,33 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans, + + dir_inode = btrfs_iget(fs_info->sb, &inode_key, + root, NULL); +- /* If parent inode was deleted, skip it. */ +- if (IS_ERR(dir_inode)) +- continue; ++ /* ++ * If the parent inode was deleted, return an error to ++ * fallback to a transaction commit. This is to prevent ++ * getting an inode that was moved from one parent A to ++ * a parent B, got its former parent A deleted and then ++ * it got fsync'ed, from existing at both parents after ++ * a log replay (and the old parent still existing). ++ * Example: ++ * ++ * mkdir /mnt/A ++ * mkdir /mnt/B ++ * touch /mnt/B/bar ++ * sync ++ * mv /mnt/B/bar /mnt/A/bar ++ * mv -T /mnt/A /mnt/B ++ * fsync /mnt/B/bar ++ * ++ * ++ * If we ignore the old parent B which got deleted, ++ * after a log replay we would have file bar linked ++ * at both parents and the old parent B would still ++ * exist. ++ */ ++ if (IS_ERR(dir_inode)) { ++ ret = PTR_ERR(dir_inode); ++ goto out; ++ } + + if (ctx) + ctx->log_new_dentries = false; +@@ -5640,7 +5682,13 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, + if (ret) + goto end_no_trans; + +- if (btrfs_inode_in_log(inode, trans->transid)) { ++ /* ++ * Skip already logged inodes or inodes corresponding to tmpfiles ++ * (since logging them is pointless, a link count of 0 means they ++ * will never be accessible). ++ */ ++ if (btrfs_inode_in_log(inode, trans->transid) || ++ inode->vfs_inode.i_nlink == 0) { + ret = BTRFS_NO_LOG_SYNC; + goto end_no_trans; + } +diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c +index f1fbea947fef..06576797cf31 100644 +--- a/fs/cifs/cifs_debug.c ++++ b/fs/cifs/cifs_debug.c +@@ -383,6 +383,9 @@ static ssize_t cifs_stats_proc_write(struct file *file, + atomic_set(&totBufAllocCount, 0); + atomic_set(&totSmBufAllocCount, 0); + #endif /* CONFIG_CIFS_STATS2 */ ++ atomic_set(&tcpSesReconnectCount, 0); ++ atomic_set(&tconInfoReconnectCount, 0); ++ + spin_lock(&GlobalMid_Lock); + GlobalMaxActiveXid = 0; + GlobalCurrentXid = 0; +diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c +index b611fc2e8984..7f01c6e60791 100644 +--- a/fs/cifs/cifs_spnego.c ++++ b/fs/cifs/cifs_spnego.c +@@ -147,8 +147,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) + sprintf(dp, ";sec=krb5"); + else if (server->sec_mskerberos) + sprintf(dp, ";sec=mskrb5"); +- else +- goto out; ++ else { ++ cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n"); ++ sprintf(dp, ";sec=krb5"); ++ } + + dp = description + strlen(description); + sprintf(dp, ";uid=0x%x", +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index 6e8765f44508..020f49c15b30 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -777,7 +777,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, + } else if (rc == -EREMOTE) { + cifs_create_dfs_fattr(&fattr, sb); + rc = 0; +- } else if (rc == -EACCES && backup_cred(cifs_sb)) { ++ } else if ((rc == -EACCES) && backup_cred(cifs_sb) && ++ (strcmp(server->vals->version_string, SMB1_VERSION_STRING) ++ == 0)) { ++ /* ++ * For SMB2 and later the backup intent flag is already ++ * sent if needed on open and there is no path based ++ * FindFirst operation to use to retry with ++ */ ++ + srchinf = kzalloc(sizeof(struct cifs_search_info), + GFP_KERNEL); + if (srchinf == NULL) { +diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c +index b48f43963da6..333729cf46cd 100644 +--- a/fs/cifs/transport.c ++++ b/fs/cifs/transport.c +@@ -786,7 +786,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + int i, j, rc = 0; + int timeout, optype; + struct mid_q_entry *midQ[MAX_COMPOUND]; +- unsigned int credits = 1; ++ unsigned int credits = 0; + char *buf; + + timeout = flags & CIFS_TIMEOUT_MASK; +@@ -851,17 +851,20 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + + mutex_unlock(&ses->server->srv_mutex); + +- for (i = 0; i < num_rqst; i++) { +- if (rc < 0) +- goto out; ++ if (rc < 0) ++ goto out; + +- if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) +- smb311_update_preauth_hash(ses, rqst[i].rq_iov, +- rqst[i].rq_nvec); ++ /* ++ * Compounding is never used during session establish. ++ */ ++ if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) ++ smb311_update_preauth_hash(ses, rqst[0].rq_iov, ++ rqst[0].rq_nvec); + +- if (timeout == CIFS_ASYNC_OP) +- goto out; ++ if (timeout == CIFS_ASYNC_OP) ++ goto out; + ++ for (i = 0; i < num_rqst; i++) { + rc = wait_for_response(ses->server, midQ[i]); + if (rc != 0) { + cifs_dbg(FYI, "Cancelling wait for mid %llu\n", +@@ -877,10 +880,21 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + } + spin_unlock(&GlobalMid_Lock); + } ++ } ++ ++ for (i = 0; i < num_rqst; i++) ++ if (midQ[i]->resp_buf) ++ credits += ses->server->ops->get_credits(midQ[i]); ++ if (!credits) ++ credits = 1; ++ ++ for (i = 0; i < num_rqst; i++) { ++ if (rc < 0) ++ goto out; + + rc = cifs_sync_mid_result(midQ[i], ses->server); + if (rc != 0) { +- add_credits(ses->server, 1, optype); ++ add_credits(ses->server, credits, optype); + return rc; + } + +@@ -901,23 +915,26 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + else + resp_buf_type[i] = CIFS_SMALL_BUFFER; + +- if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { +- struct kvec iov = { +- .iov_base = resp_iov[i].iov_base, +- .iov_len = resp_iov[i].iov_len +- }; +- smb311_update_preauth_hash(ses, &iov, 1); +- } +- +- credits = ses->server->ops->get_credits(midQ[i]); +- + rc = ses->server->ops->check_receive(midQ[i], ses->server, + flags & CIFS_LOG_ERROR); + + /* mark it so buf will not be freed by cifs_delete_mid */ + if ((flags & CIFS_NO_RESP) == 0) + midQ[i]->resp_buf = NULL; ++ + } ++ ++ /* ++ * Compounding is never used during session establish. ++ */ ++ if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { ++ struct kvec iov = { ++ .iov_base = resp_iov[0].iov_base, ++ .iov_len = resp_iov[0].iov_len ++ }; ++ smb311_update_preauth_hash(ses, &iov, 1); ++ } ++ + out: + /* + * This will dequeue all mids. After this it is important that the +diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c +index f408994fc632..6e000392e4a4 100644 +--- a/fs/cramfs/inode.c ++++ b/fs/cramfs/inode.c +@@ -202,7 +202,8 @@ static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset, + continue; + blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_SHIFT; + blk_offset += offset; +- if (blk_offset + len > BUFFER_SIZE) ++ if (blk_offset > BUFFER_SIZE || ++ blk_offset + len > BUFFER_SIZE) + continue; + return read_buffers[i] + blk_offset; + } +diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h +index 39c20ef26db4..79debfc9cef9 100644 +--- a/fs/crypto/fscrypt_private.h ++++ b/fs/crypto/fscrypt_private.h +@@ -83,10 +83,6 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode, + filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS) + return true; + +- if (contents_mode == FS_ENCRYPTION_MODE_SPECK128_256_XTS && +- filenames_mode == FS_ENCRYPTION_MODE_SPECK128_256_CTS) +- return true; +- + return false; + } + +diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c +index e997ca51192f..7874c9bb2fc5 100644 +--- a/fs/crypto/keyinfo.c ++++ b/fs/crypto/keyinfo.c +@@ -174,16 +174,6 @@ static struct fscrypt_mode { + .cipher_str = "cts(cbc(aes))", + .keysize = 16, + }, +- [FS_ENCRYPTION_MODE_SPECK128_256_XTS] = { +- .friendly_name = "Speck128/256-XTS", +- .cipher_str = "xts(speck128)", +- .keysize = 64, +- }, +- [FS_ENCRYPTION_MODE_SPECK128_256_CTS] = { +- .friendly_name = "Speck128/256-CTS-CBC", +- .cipher_str = "cts(cbc(speck128))", +- .keysize = 32, +- }, + }; + + static struct fscrypt_mode * +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index caff935fbeb8..5cfb1e2f6a5b 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1401,7 +1401,8 @@ struct ext4_sb_info { + u32 s_min_batch_time; + struct block_device *journal_bdev; + #ifdef CONFIG_QUOTA +- char *s_qf_names[EXT4_MAXQUOTAS]; /* Names of quota files with journalled quota */ ++ /* Names of quota files with journalled quota */ ++ char __rcu *s_qf_names[EXT4_MAXQUOTAS]; + int s_jquota_fmt; /* Format of quota to use */ + #endif + unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */ +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 7b4736022761..9c4bac18cc6c 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -863,7 +863,7 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping, + handle_t *handle; + struct page *page; + struct ext4_iloc iloc; +- int retries; ++ int retries = 0; + + ret = ext4_get_inode_loc(inode, &iloc); + if (ret) +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index a7074115d6f6..0edee31913d1 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -67,7 +67,6 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2) + ei1 = EXT4_I(inode1); + ei2 = EXT4_I(inode2); + +- swap(inode1->i_flags, inode2->i_flags); + swap(inode1->i_version, inode2->i_version); + swap(inode1->i_blocks, inode2->i_blocks); + swap(inode1->i_bytes, inode2->i_bytes); +@@ -85,6 +84,21 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2) + i_size_write(inode2, isize); + } + ++static void reset_inode_seed(struct inode *inode) ++{ ++ struct ext4_inode_info *ei = EXT4_I(inode); ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ __le32 inum = cpu_to_le32(inode->i_ino); ++ __le32 gen = cpu_to_le32(inode->i_generation); ++ __u32 csum; ++ ++ if (!ext4_has_metadata_csum(inode->i_sb)) ++ return; ++ ++ csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&inum, sizeof(inum)); ++ ei->i_csum_seed = ext4_chksum(sbi, csum, (__u8 *)&gen, sizeof(gen)); ++} ++ + /** + * Swap the information from the given @inode and the inode + * EXT4_BOOT_LOADER_INO. It will basically swap i_data and all other +@@ -102,10 +116,13 @@ static long swap_inode_boot_loader(struct super_block *sb, + struct inode *inode_bl; + struct ext4_inode_info *ei_bl; + +- if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode)) ++ if (inode->i_nlink != 1 || !S_ISREG(inode->i_mode) || ++ IS_SWAPFILE(inode) || IS_ENCRYPTED(inode) || ++ ext4_has_inline_data(inode)) + return -EINVAL; + +- if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) ++ if (IS_RDONLY(inode) || IS_APPEND(inode) || IS_IMMUTABLE(inode) || ++ !inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN)) + return -EPERM; + + inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO); +@@ -120,13 +137,13 @@ static long swap_inode_boot_loader(struct super_block *sb, + * that only 1 swap_inode_boot_loader is running. */ + lock_two_nondirectories(inode, inode_bl); + +- truncate_inode_pages(&inode->i_data, 0); +- truncate_inode_pages(&inode_bl->i_data, 0); +- + /* Wait for all existing dio workers */ + inode_dio_wait(inode); + inode_dio_wait(inode_bl); + ++ truncate_inode_pages(&inode->i_data, 0); ++ truncate_inode_pages(&inode_bl->i_data, 0); ++ + handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); + if (IS_ERR(handle)) { + err = -EINVAL; +@@ -159,6 +176,8 @@ static long swap_inode_boot_loader(struct super_block *sb, + + inode->i_generation = prandom_u32(); + inode_bl->i_generation = prandom_u32(); ++ reset_inode_seed(inode); ++ reset_inode_seed(inode_bl); + + ext4_discard_preallocations(inode); + +@@ -169,6 +188,7 @@ static long swap_inode_boot_loader(struct super_block *sb, + inode->i_ino, err); + /* Revert all changes: */ + swap_inode_data(inode, inode_bl); ++ ext4_mark_inode_dirty(handle, inode); + } else { + err = ext4_mark_inode_dirty(handle, inode_bl); + if (err < 0) { +@@ -178,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb, + /* Revert all changes: */ + swap_inode_data(inode, inode_bl); + ext4_mark_inode_dirty(handle, inode); ++ ext4_mark_inode_dirty(handle, inode_bl); + } + } + ext4_journal_stop(handle); +@@ -339,19 +360,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) + if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) + return 0; + +- err = mnt_want_write_file(filp); +- if (err) +- return err; +- + err = -EPERM; +- inode_lock(inode); + /* Is it quota file? Do not allow user to mess with it */ + if (ext4_is_quota_file(inode)) +- goto out_unlock; ++ return err; + + err = ext4_get_inode_loc(inode, &iloc); + if (err) +- goto out_unlock; ++ return err; + + raw_inode = ext4_raw_inode(&iloc); + if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) { +@@ -359,20 +375,20 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) + EXT4_SB(sb)->s_want_extra_isize, + &iloc); + if (err) +- goto out_unlock; ++ return err; + } else { + brelse(iloc.bh); + } + +- dquot_initialize(inode); ++ err = dquot_initialize(inode); ++ if (err) ++ return err; + + handle = ext4_journal_start(inode, EXT4_HT_QUOTA, + EXT4_QUOTA_INIT_BLOCKS(sb) + + EXT4_QUOTA_DEL_BLOCKS(sb) + 3); +- if (IS_ERR(handle)) { +- err = PTR_ERR(handle); +- goto out_unlock; +- } ++ if (IS_ERR(handle)) ++ return PTR_ERR(handle); + + err = ext4_reserve_inode_write(handle, inode, &iloc); + if (err) +@@ -400,9 +416,6 @@ out_dirty: + err = rc; + out_stop: + ext4_journal_stop(handle); +-out_unlock: +- inode_unlock(inode); +- mnt_drop_write_file(filp); + return err; + } + #else +@@ -626,6 +639,30 @@ group_add_out: + return err; + } + ++static int ext4_ioctl_check_project(struct inode *inode, struct fsxattr *fa) ++{ ++ /* ++ * Project Quota ID state is only allowed to change from within the init ++ * namespace. Enforce that restriction only if we are trying to change ++ * the quota ID state. Everything else is allowed in user namespaces. ++ */ ++ if (current_user_ns() == &init_user_ns) ++ return 0; ++ ++ if (__kprojid_val(EXT4_I(inode)->i_projid) != fa->fsx_projid) ++ return -EINVAL; ++ ++ if (ext4_test_inode_flag(inode, EXT4_INODE_PROJINHERIT)) { ++ if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT)) ++ return -EINVAL; ++ } else { ++ if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { + struct inode *inode = file_inode(filp); +@@ -1025,19 +1062,19 @@ resizefs_out: + return err; + + inode_lock(inode); ++ err = ext4_ioctl_check_project(inode, &fa); ++ if (err) ++ goto out; + flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) | + (flags & EXT4_FL_XFLAG_VISIBLE); + err = ext4_ioctl_setflags(inode, flags); +- inode_unlock(inode); +- mnt_drop_write_file(filp); + if (err) +- return err; +- ++ goto out; + err = ext4_ioctl_setproject(filp, fa.fsx_projid); +- if (err) +- return err; +- +- return 0; ++out: ++ inode_unlock(inode); ++ mnt_drop_write_file(filp); ++ return err; + } + case EXT4_IOC_SHUTDOWN: + return ext4_shutdown(sb, arg); +diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c +index a409ff70d67b..2f5be02fc6f6 100644 +--- a/fs/ext4/move_extent.c ++++ b/fs/ext4/move_extent.c +@@ -516,9 +516,13 @@ mext_check_arguments(struct inode *orig_inode, + orig_inode->i_ino, donor_inode->i_ino); + return -EINVAL; + } +- if (orig_eof < orig_start + *len - 1) ++ if (orig_eof <= orig_start) ++ *len = 0; ++ else if (orig_eof < orig_start + *len - 1) + *len = orig_eof - orig_start; +- if (donor_eof < donor_start + *len - 1) ++ if (donor_eof <= donor_start) ++ *len = 0; ++ else if (donor_eof < donor_start + *len - 1) + *len = donor_eof - donor_start; + if (!*len) { + ext4_debug("ext4 move extent: len should not be 0 " +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 1145109968ef..d3d4643ab79b 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -914,6 +914,18 @@ static inline void ext4_quota_off_umount(struct super_block *sb) + for (type = 0; type < EXT4_MAXQUOTAS; type++) + ext4_quota_off(sb, type); + } ++ ++/* ++ * This is a helper function which is used in the mount/remount ++ * codepaths (which holds s_umount) to fetch the quota file name. ++ */ ++static inline char *get_qf_name(struct super_block *sb, ++ struct ext4_sb_info *sbi, ++ int type) ++{ ++ return rcu_dereference_protected(sbi->s_qf_names[type], ++ lockdep_is_held(&sb->s_umount)); ++} + #else + static inline void ext4_quota_off_umount(struct super_block *sb) + { +@@ -965,7 +977,7 @@ static void ext4_put_super(struct super_block *sb) + percpu_free_rwsem(&sbi->s_journal_flag_rwsem); + #ifdef CONFIG_QUOTA + for (i = 0; i < EXT4_MAXQUOTAS; i++) +- kfree(sbi->s_qf_names[i]); ++ kfree(get_qf_name(sb, sbi, i)); + #endif + + /* Debugging code just in case the in-memory inode orphan list +@@ -1530,11 +1542,10 @@ static const char deprecated_msg[] = + static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); +- char *qname; ++ char *qname, *old_qname = get_qf_name(sb, sbi, qtype); + int ret = -1; + +- if (sb_any_quota_loaded(sb) && +- !sbi->s_qf_names[qtype]) { ++ if (sb_any_quota_loaded(sb) && !old_qname) { + ext4_msg(sb, KERN_ERR, + "Cannot change journaled " + "quota options when quota turned on"); +@@ -1551,8 +1562,8 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) + "Not enough memory for storing quotafile name"); + return -1; + } +- if (sbi->s_qf_names[qtype]) { +- if (strcmp(sbi->s_qf_names[qtype], qname) == 0) ++ if (old_qname) { ++ if (strcmp(old_qname, qname) == 0) + ret = 1; + else + ext4_msg(sb, KERN_ERR, +@@ -1565,7 +1576,7 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args) + "quotafile must be on filesystem root"); + goto errout; + } +- sbi->s_qf_names[qtype] = qname; ++ rcu_assign_pointer(sbi->s_qf_names[qtype], qname); + set_opt(sb, QUOTA); + return 1; + errout: +@@ -1577,15 +1588,16 @@ static int clear_qf_name(struct super_block *sb, int qtype) + { + + struct ext4_sb_info *sbi = EXT4_SB(sb); ++ char *old_qname = get_qf_name(sb, sbi, qtype); + +- if (sb_any_quota_loaded(sb) && +- sbi->s_qf_names[qtype]) { ++ if (sb_any_quota_loaded(sb) && old_qname) { + ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options" + " when quota turned on"); + return -1; + } +- kfree(sbi->s_qf_names[qtype]); +- sbi->s_qf_names[qtype] = NULL; ++ rcu_assign_pointer(sbi->s_qf_names[qtype], NULL); ++ synchronize_rcu(); ++ kfree(old_qname); + return 1; + } + #endif +@@ -1960,7 +1972,7 @@ static int parse_options(char *options, struct super_block *sb, + int is_remount) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); +- char *p; ++ char *p, __maybe_unused *usr_qf_name, __maybe_unused *grp_qf_name; + substring_t args[MAX_OPT_ARGS]; + int token; + +@@ -1991,11 +2003,13 @@ static int parse_options(char *options, struct super_block *sb, + "Cannot enable project quota enforcement."); + return 0; + } +- if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) { +- if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA]) ++ usr_qf_name = get_qf_name(sb, sbi, USRQUOTA); ++ grp_qf_name = get_qf_name(sb, sbi, GRPQUOTA); ++ if (usr_qf_name || grp_qf_name) { ++ if (test_opt(sb, USRQUOTA) && usr_qf_name) + clear_opt(sb, USRQUOTA); + +- if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA]) ++ if (test_opt(sb, GRPQUOTA) && grp_qf_name) + clear_opt(sb, GRPQUOTA); + + if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) { +@@ -2029,6 +2043,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq, + { + #if defined(CONFIG_QUOTA) + struct ext4_sb_info *sbi = EXT4_SB(sb); ++ char *usr_qf_name, *grp_qf_name; + + if (sbi->s_jquota_fmt) { + char *fmtname = ""; +@@ -2047,11 +2062,14 @@ static inline void ext4_show_quota_options(struct seq_file *seq, + seq_printf(seq, ",jqfmt=%s", fmtname); + } + +- if (sbi->s_qf_names[USRQUOTA]) +- seq_show_option(seq, "usrjquota", sbi->s_qf_names[USRQUOTA]); +- +- if (sbi->s_qf_names[GRPQUOTA]) +- seq_show_option(seq, "grpjquota", sbi->s_qf_names[GRPQUOTA]); ++ rcu_read_lock(); ++ usr_qf_name = rcu_dereference(sbi->s_qf_names[USRQUOTA]); ++ grp_qf_name = rcu_dereference(sbi->s_qf_names[GRPQUOTA]); ++ if (usr_qf_name) ++ seq_show_option(seq, "usrjquota", usr_qf_name); ++ if (grp_qf_name) ++ seq_show_option(seq, "grpjquota", grp_qf_name); ++ rcu_read_unlock(); + #endif + } + +@@ -5103,6 +5121,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) + int err = 0; + #ifdef CONFIG_QUOTA + int i, j; ++ char *to_free[EXT4_MAXQUOTAS]; + #endif + char *orig_data = kstrdup(data, GFP_KERNEL); + +@@ -5122,8 +5141,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) + old_opts.s_jquota_fmt = sbi->s_jquota_fmt; + for (i = 0; i < EXT4_MAXQUOTAS; i++) + if (sbi->s_qf_names[i]) { +- old_opts.s_qf_names[i] = kstrdup(sbi->s_qf_names[i], +- GFP_KERNEL); ++ char *qf_name = get_qf_name(sb, sbi, i); ++ ++ old_opts.s_qf_names[i] = kstrdup(qf_name, GFP_KERNEL); + if (!old_opts.s_qf_names[i]) { + for (j = 0; j < i; j++) + kfree(old_opts.s_qf_names[j]); +@@ -5352,9 +5372,12 @@ restore_opts: + #ifdef CONFIG_QUOTA + sbi->s_jquota_fmt = old_opts.s_jquota_fmt; + for (i = 0; i < EXT4_MAXQUOTAS; i++) { +- kfree(sbi->s_qf_names[i]); +- sbi->s_qf_names[i] = old_opts.s_qf_names[i]; ++ to_free[i] = get_qf_name(sb, sbi, i); ++ rcu_assign_pointer(sbi->s_qf_names[i], old_opts.s_qf_names[i]); + } ++ synchronize_rcu(); ++ for (i = 0; i < EXT4_MAXQUOTAS; i++) ++ kfree(to_free[i]); + #endif + kfree(orig_data); + return err; +@@ -5545,7 +5568,7 @@ static int ext4_write_info(struct super_block *sb, int type) + */ + static int ext4_quota_on_mount(struct super_block *sb, int type) + { +- return dquot_quota_on_mount(sb, EXT4_SB(sb)->s_qf_names[type], ++ return dquot_quota_on_mount(sb, get_qf_name(sb, EXT4_SB(sb), type), + EXT4_SB(sb)->s_jquota_fmt, type); + } + +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index e8b6b89bddb8..59d0472013f4 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -696,6 +696,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) + /* clear Orphan Flag */ + clear_ckpt_flags(sbi, CP_ORPHAN_PRESENT_FLAG); + out: ++ set_sbi_flag(sbi, SBI_IS_RECOVERED); ++ + #ifdef CONFIG_QUOTA + /* Turn quotas off */ + if (quota_enabled) +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index 382c1ef9a9e4..11f28342f641 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -80,7 +80,8 @@ static void __read_end_io(struct bio *bio) + /* PG_error was set if any post_read step failed */ + if (bio->bi_status || PageError(page)) { + ClearPageUptodate(page); +- SetPageError(page); ++ /* will re-read again later */ ++ ClearPageError(page); + } else { + SetPageUptodate(page); + } +@@ -456,12 +457,16 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) + bio_put(bio); + return -EFAULT; + } +- bio_set_op_attrs(bio, fio->op, fio->op_flags); + +- __submit_bio(fio->sbi, bio, fio->type); ++ if (fio->io_wbc && !is_read_io(fio->op)) ++ wbc_account_io(fio->io_wbc, page, PAGE_SIZE); ++ ++ bio_set_op_attrs(bio, fio->op, fio->op_flags); + + if (!is_read_io(fio->op)) + inc_page_count(fio->sbi, WB_DATA_TYPE(fio->page)); ++ ++ __submit_bio(fio->sbi, bio, fio->type); + return 0; + } + +@@ -586,6 +591,7 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, + bio_put(bio); + return -EFAULT; + } ++ ClearPageError(page); + __submit_bio(F2FS_I_SB(inode), bio, DATA); + return 0; + } +@@ -1561,6 +1567,7 @@ submit_and_realloc: + if (bio_add_page(bio, page, blocksize, 0) < blocksize) + goto submit_and_realloc; + ++ ClearPageError(page); + last_block_in_bio = block_nr; + goto next_page; + set_error_page: +@@ -2583,10 +2590,6 @@ static int f2fs_set_data_page_dirty(struct page *page) + if (!PageUptodate(page)) + SetPageUptodate(page); + +- /* don't remain PG_checked flag which was set during GC */ +- if (is_cold_data(page)) +- clear_cold_data(page); +- + if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) { + if (!IS_ATOMIC_WRITTEN_PAGE(page)) { + f2fs_register_inmem_page(inode, page); +diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c +index 231b77ef5a53..a70cd2580eae 100644 +--- a/fs/f2fs/extent_cache.c ++++ b/fs/f2fs/extent_cache.c +@@ -308,14 +308,13 @@ static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi, + return count - atomic_read(&et->node_cnt); + } + +-static void __drop_largest_extent(struct inode *inode, ++static void __drop_largest_extent(struct extent_tree *et, + pgoff_t fofs, unsigned int len) + { +- struct extent_info *largest = &F2FS_I(inode)->extent_tree->largest; +- +- if (fofs < largest->fofs + largest->len && fofs + len > largest->fofs) { +- largest->len = 0; +- f2fs_mark_inode_dirty_sync(inode, true); ++ if (fofs < et->largest.fofs + et->largest.len && ++ fofs + len > et->largest.fofs) { ++ et->largest.len = 0; ++ et->largest_updated = true; + } + } + +@@ -416,12 +415,11 @@ out: + return ret; + } + +-static struct extent_node *__try_merge_extent_node(struct inode *inode, ++static struct extent_node *__try_merge_extent_node(struct f2fs_sb_info *sbi, + struct extent_tree *et, struct extent_info *ei, + struct extent_node *prev_ex, + struct extent_node *next_ex) + { +- struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct extent_node *en = NULL; + + if (prev_ex && __is_back_mergeable(ei, &prev_ex->ei)) { +@@ -443,7 +441,7 @@ static struct extent_node *__try_merge_extent_node(struct inode *inode, + if (!en) + return NULL; + +- __try_update_largest_extent(inode, et, en); ++ __try_update_largest_extent(et, en); + + spin_lock(&sbi->extent_lock); + if (!list_empty(&en->list)) { +@@ -454,12 +452,11 @@ static struct extent_node *__try_merge_extent_node(struct inode *inode, + return en; + } + +-static struct extent_node *__insert_extent_tree(struct inode *inode, ++static struct extent_node *__insert_extent_tree(struct f2fs_sb_info *sbi, + struct extent_tree *et, struct extent_info *ei, + struct rb_node **insert_p, + struct rb_node *insert_parent) + { +- struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct rb_node **p; + struct rb_node *parent = NULL; + struct extent_node *en = NULL; +@@ -476,7 +473,7 @@ do_insert: + if (!en) + return NULL; + +- __try_update_largest_extent(inode, et, en); ++ __try_update_largest_extent(et, en); + + /* update in global extent list */ + spin_lock(&sbi->extent_lock); +@@ -497,6 +494,7 @@ static void f2fs_update_extent_tree_range(struct inode *inode, + struct rb_node **insert_p = NULL, *insert_parent = NULL; + unsigned int end = fofs + len; + unsigned int pos = (unsigned int)fofs; ++ bool updated = false; + + if (!et) + return; +@@ -517,7 +515,7 @@ static void f2fs_update_extent_tree_range(struct inode *inode, + * drop largest extent before lookup, in case it's already + * been shrunk from extent tree + */ +- __drop_largest_extent(inode, fofs, len); ++ __drop_largest_extent(et, fofs, len); + + /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ + en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root, +@@ -550,7 +548,7 @@ static void f2fs_update_extent_tree_range(struct inode *inode, + set_extent_info(&ei, end, + end - dei.fofs + dei.blk, + org_end - end); +- en1 = __insert_extent_tree(inode, et, &ei, ++ en1 = __insert_extent_tree(sbi, et, &ei, + NULL, NULL); + next_en = en1; + } else { +@@ -570,7 +568,7 @@ static void f2fs_update_extent_tree_range(struct inode *inode, + } + + if (parts) +- __try_update_largest_extent(inode, et, en); ++ __try_update_largest_extent(et, en); + else + __release_extent_node(sbi, et, en); + +@@ -590,15 +588,16 @@ static void f2fs_update_extent_tree_range(struct inode *inode, + if (blkaddr) { + + set_extent_info(&ei, fofs, blkaddr, len); +- if (!__try_merge_extent_node(inode, et, &ei, prev_en, next_en)) +- __insert_extent_tree(inode, et, &ei, ++ if (!__try_merge_extent_node(sbi, et, &ei, prev_en, next_en)) ++ __insert_extent_tree(sbi, et, &ei, + insert_p, insert_parent); + + /* give up extent_cache, if split and small updates happen */ + if (dei.len >= 1 && + prev.len < F2FS_MIN_EXTENT_LEN && + et->largest.len < F2FS_MIN_EXTENT_LEN) { +- __drop_largest_extent(inode, 0, UINT_MAX); ++ et->largest.len = 0; ++ et->largest_updated = true; + set_inode_flag(inode, FI_NO_EXTENT); + } + } +@@ -606,7 +605,15 @@ static void f2fs_update_extent_tree_range(struct inode *inode, + if (is_inode_flag_set(inode, FI_NO_EXTENT)) + __free_extent_tree(sbi, et); + ++ if (et->largest_updated) { ++ et->largest_updated = false; ++ updated = true; ++ } ++ + write_unlock(&et->lock); ++ ++ if (updated) ++ f2fs_mark_inode_dirty_sync(inode, true); + } + + unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) +@@ -705,6 +712,7 @@ void f2fs_drop_extent_tree(struct inode *inode) + { + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct extent_tree *et = F2FS_I(inode)->extent_tree; ++ bool updated = false; + + if (!f2fs_may_extent_tree(inode)) + return; +@@ -713,8 +721,13 @@ void f2fs_drop_extent_tree(struct inode *inode) + + write_lock(&et->lock); + __free_extent_tree(sbi, et); +- __drop_largest_extent(inode, 0, UINT_MAX); ++ if (et->largest.len) { ++ et->largest.len = 0; ++ updated = true; ++ } + write_unlock(&et->lock); ++ if (updated) ++ f2fs_mark_inode_dirty_sync(inode, true); + } + + void f2fs_destroy_extent_tree(struct inode *inode) +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index abf925664d9c..ecb735142276 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -572,6 +572,7 @@ struct extent_tree { + struct list_head list; /* to be used by sbi->zombie_list */ + rwlock_t lock; /* protect extent info rb-tree */ + atomic_t node_cnt; /* # of extent node in rb-tree*/ ++ bool largest_updated; /* largest extent updated */ + }; + + /* +@@ -754,12 +755,12 @@ static inline bool __is_front_mergeable(struct extent_info *cur, + } + + extern void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync); +-static inline void __try_update_largest_extent(struct inode *inode, +- struct extent_tree *et, struct extent_node *en) ++static inline void __try_update_largest_extent(struct extent_tree *et, ++ struct extent_node *en) + { + if (en->ei.len > et->largest.len) { + et->largest = en->ei; +- f2fs_mark_inode_dirty_sync(inode, true); ++ et->largest_updated = true; + } + } + +@@ -1088,6 +1089,7 @@ enum { + SBI_NEED_SB_WRITE, /* need to recover superblock */ + SBI_NEED_CP, /* need to checkpoint */ + SBI_IS_SHUTDOWN, /* shutdown by ioctl */ ++ SBI_IS_RECOVERED, /* recovered orphan/data */ + }; + + enum { +diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c +index 959df2249875..dd608b819a3c 100644 +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -368,6 +368,12 @@ static int do_read_inode(struct inode *inode) + if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode)) + __recover_inline_status(inode, node_page); + ++ /* try to recover cold bit for non-dir inode */ ++ if (!S_ISDIR(inode->i_mode) && !is_cold_node(node_page)) { ++ set_cold_node(node_page, false); ++ set_page_dirty(node_page); ++ } ++ + /* get rdev by using inline_info */ + __get_inode_rdev(inode, ri); + +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index dd2e45a661aa..42ea42acb487 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -1542,8 +1542,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, + } + + if (__is_valid_data_blkaddr(ni.blk_addr) && +- !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) ++ !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC)) { ++ up_read(&sbi->node_write); + goto redirty_out; ++ } + + if (atomic && !test_opt(sbi, NOBARRIER)) + fio.op_flags |= REQ_PREFLUSH | REQ_FUA; +@@ -2537,7 +2539,7 @@ retry: + if (!PageUptodate(ipage)) + SetPageUptodate(ipage); + fill_node_footer(ipage, ino, ino, 0, true); +- set_cold_node(page, false); ++ set_cold_node(ipage, false); + + src = F2FS_INODE(page); + dst = F2FS_INODE(ipage); +@@ -2560,6 +2562,13 @@ retry: + F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), + i_projid)) + dst->i_projid = src->i_projid; ++ ++ if (f2fs_sb_has_inode_crtime(sbi->sb) && ++ F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize), ++ i_crtime_nsec)) { ++ dst->i_crtime = src->i_crtime; ++ dst->i_crtime_nsec = src->i_crtime_nsec; ++ } + } + + new_ni = old_ni; +diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c +index 95511ed11a22..9a8579fb3a30 100644 +--- a/fs/f2fs/recovery.c ++++ b/fs/f2fs/recovery.c +@@ -221,6 +221,7 @@ static void recover_inode(struct inode *inode, struct page *page) + inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec); + + F2FS_I(inode)->i_advise = raw->i_advise; ++ F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags); + + recover_inline_flags(inode, raw); + +@@ -697,11 +698,15 @@ skip: + /* let's drop all the directory inodes for clean checkpoint */ + destroy_fsync_dnodes(&dir_list); + +- if (!err && need_writecp) { +- struct cp_control cpc = { +- .reason = CP_RECOVERY, +- }; +- err = f2fs_write_checkpoint(sbi, &cpc); ++ if (need_writecp) { ++ set_sbi_flag(sbi, SBI_IS_RECOVERED); ++ ++ if (!err) { ++ struct cp_control cpc = { ++ .reason = CP_RECOVERY, ++ }; ++ err = f2fs_write_checkpoint(sbi, &cpc); ++ } + } + + kmem_cache_destroy(fsync_entry_slab); +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 896b885f504e..287c9fe9fff9 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -1852,7 +1852,9 @@ static int f2fs_quota_off(struct super_block *sb, int type) + if (!inode || !igrab(inode)) + return dquot_quota_off(sb, type); + +- f2fs_quota_sync(sb, type); ++ err = f2fs_quota_sync(sb, type); ++ if (err) ++ goto out_put; + + err = dquot_quota_off(sb, type); + if (err || f2fs_sb_has_quota_ino(sb)) +@@ -1871,9 +1873,20 @@ out_put: + void f2fs_quota_off_umount(struct super_block *sb) + { + int type; ++ int err; + +- for (type = 0; type < MAXQUOTAS; type++) +- f2fs_quota_off(sb, type); ++ for (type = 0; type < MAXQUOTAS; type++) { ++ err = f2fs_quota_off(sb, type); ++ if (err) { ++ int ret = dquot_quota_off(sb, type); ++ ++ f2fs_msg(sb, KERN_ERR, ++ "Fail to turn off disk quota " ++ "(type: %d, err: %d, ret:%d), Please " ++ "run fsck to fix it.", type, err, ret); ++ set_sbi_flag(F2FS_SB(sb), SBI_NEED_FSCK); ++ } ++ } + } + + static int f2fs_get_projid(struct inode *inode, kprojid_t *projid) +@@ -3175,6 +3188,9 @@ static void kill_f2fs_super(struct super_block *sb) + }; + f2fs_write_checkpoint(sbi, &cpc); + } ++ ++ if (is_sbi_flag_set(sbi, SBI_IS_RECOVERED) && f2fs_readonly(sb)) ++ sb->s_flags &= ~SB_RDONLY; + } + kill_block_super(sb); + } +diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c +index c2469833b4fb..6b84ef6ccff3 100644 +--- a/fs/gfs2/ops_fstype.c ++++ b/fs/gfs2/ops_fstype.c +@@ -1333,6 +1333,9 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type, + struct path path; + int error; + ++ if (!dev_name || !*dev_name) ++ return ERR_PTR(-EINVAL); ++ + error = kern_path(dev_name, LOOKUP_FOLLOW, &path); + if (error) { + pr_warn("path_lookup on %s returned error %d\n", +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index c125d662777c..26f8d7e46462 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -251,8 +251,8 @@ restart: + bh = jh2bh(jh); + + if (buffer_locked(bh)) { +- spin_unlock(&journal->j_list_lock); + get_bh(bh); ++ spin_unlock(&journal->j_list_lock); + wait_on_buffer(bh); + /* the journal_head may have gone by now */ + BUFFER_TRACE(bh, "brelse"); +@@ -333,8 +333,8 @@ restart2: + jh = transaction->t_checkpoint_io_list; + bh = jh2bh(jh); + if (buffer_locked(bh)) { +- spin_unlock(&journal->j_list_lock); + get_bh(bh); ++ spin_unlock(&journal->j_list_lock); + wait_on_buffer(bh); + /* the journal_head may have gone by now */ + BUFFER_TRACE(bh, "brelse"); +diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c +index 87bdf0f4cba1..902a7dd10e5c 100644 +--- a/fs/jffs2/super.c ++++ b/fs/jffs2/super.c +@@ -285,10 +285,8 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) + sb->s_fs_info = c; + + ret = jffs2_parse_options(c, data); +- if (ret) { +- kfree(c); ++ if (ret) + return -EINVAL; +- } + + /* Initialize JFFS2 superblock locks, the further initialization will + * be done later */ +diff --git a/fs/lockd/host.c b/fs/lockd/host.c +index d35cd6be0675..93fb7cf0b92b 100644 +--- a/fs/lockd/host.c ++++ b/fs/lockd/host.c +@@ -341,7 +341,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, + }; + struct lockd_net *ln = net_generic(net, lockd_net_id); + +- dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, ++ dprintk("lockd: %s(host='%.*s', vers=%u, proto=%s)\n", __func__, + (int)hostname_len, hostname, rqstp->rq_vers, + (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); + +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index 146e30862234..8f53455c4765 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -950,10 +950,10 @@ EXPORT_SYMBOL_GPL(nfs4_set_ds_client); + + /* + * Session has been established, and the client marked ready. +- * Set the mount rsize and wsize with negotiated fore channel +- * attributes which will be bound checked in nfs_server_set_fsinfo. ++ * Limit the mount rsize, wsize and dtsize using negotiated fore ++ * channel attributes. + */ +-static void nfs4_session_set_rwsize(struct nfs_server *server) ++static void nfs4_session_limit_rwsize(struct nfs_server *server) + { + #ifdef CONFIG_NFS_V4_1 + struct nfs4_session *sess; +@@ -966,9 +966,11 @@ static void nfs4_session_set_rwsize(struct nfs_server *server) + server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead; + server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead; + +- if (!server->rsize || server->rsize > server_resp_sz) ++ if (server->dtsize > server_resp_sz) ++ server->dtsize = server_resp_sz; ++ if (server->rsize > server_resp_sz) + server->rsize = server_resp_sz; +- if (!server->wsize || server->wsize > server_rqst_sz) ++ if (server->wsize > server_rqst_sz) + server->wsize = server_rqst_sz; + #endif /* CONFIG_NFS_V4_1 */ + } +@@ -1015,12 +1017,12 @@ static int nfs4_server_common_setup(struct nfs_server *server, + (unsigned long long) server->fsid.minor); + nfs_display_fhandle(mntfh, "Pseudo-fs root FH"); + +- nfs4_session_set_rwsize(server); +- + error = nfs_probe_fsinfo(server, mntfh, fattr); + if (error < 0) + goto out; + ++ nfs4_session_limit_rwsize(server); ++ + if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) + server->namelen = NFS4_MAXNAMLEN; + +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index bb5476a6d264..3dbd15b47c27 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -1111,6 +1111,20 @@ static int nfs_pageio_add_request_mirror(struct nfs_pageio_descriptor *desc, + return ret; + } + ++static void nfs_pageio_error_cleanup(struct nfs_pageio_descriptor *desc) ++{ ++ u32 midx; ++ struct nfs_pgio_mirror *mirror; ++ ++ if (!desc->pg_error) ++ return; ++ ++ for (midx = 0; midx < desc->pg_mirror_count; midx++) { ++ mirror = &desc->pg_mirrors[midx]; ++ desc->pg_completion_ops->error_cleanup(&mirror->pg_list); ++ } ++} ++ + int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, + struct nfs_page *req) + { +@@ -1161,25 +1175,11 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, + return 1; + + out_failed: +- /* +- * We might have failed before sending any reqs over wire. +- * Clean up rest of the reqs in mirror pg_list. +- */ +- if (desc->pg_error) { +- struct nfs_pgio_mirror *mirror; +- void (*func)(struct list_head *); +- +- /* remember fatal errors */ +- if (nfs_error_is_fatal(desc->pg_error)) +- nfs_context_set_write_error(req->wb_context, +- desc->pg_error); +- +- func = desc->pg_completion_ops->error_cleanup; +- for (midx = 0; midx < desc->pg_mirror_count; midx++) { +- mirror = &desc->pg_mirrors[midx]; +- func(&mirror->pg_list); +- } +- } ++ /* remember fatal errors */ ++ if (nfs_error_is_fatal(desc->pg_error)) ++ nfs_context_set_write_error(req->wb_context, ++ desc->pg_error); ++ nfs_pageio_error_cleanup(desc); + return 0; + } + +@@ -1251,6 +1251,8 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc) + for (midx = 0; midx < desc->pg_mirror_count; midx++) + nfs_pageio_complete_mirror(desc, midx); + ++ if (desc->pg_error < 0) ++ nfs_pageio_error_cleanup(desc); + if (desc->pg_ops->pg_cleanup) + desc->pg_ops->pg_cleanup(desc); + nfs_pageio_cleanup_mirroring(desc); +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index b0ca0efd2875..9c6d1d57b598 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -4364,7 +4364,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, + + fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ); + if (!fl) +- goto out_stid; ++ goto out_clnt_odstate; + + status = vfs_setlease(fp->fi_deleg_file, fl->fl_type, &fl, NULL); + if (fl) +@@ -4389,7 +4389,6 @@ out_unlock: + vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp); + out_clnt_odstate: + put_clnt_odstate(dp->dl_clnt_odstate); +-out_stid: + nfs4_put_stid(&dp->dl_stid); + out_delegees: + put_deleg_file(fp); +diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c +index ababdbfab537..f43ea1aad542 100644 +--- a/fs/notify/fsnotify.c ++++ b/fs/notify/fsnotify.c +@@ -96,6 +96,9 @@ void fsnotify_unmount_inodes(struct super_block *sb) + + if (iput_inode) + iput(iput_inode); ++ /* Wait for outstanding inode references from connectors */ ++ wait_var_event(&sb->s_fsnotify_inode_refs, ++ !atomic_long_read(&sb->s_fsnotify_inode_refs)); + } + + /* +diff --git a/fs/notify/mark.c b/fs/notify/mark.c +index 59cdb27826de..09535f6423fc 100644 +--- a/fs/notify/mark.c ++++ b/fs/notify/mark.c +@@ -179,17 +179,20 @@ static void fsnotify_connector_destroy_workfn(struct work_struct *work) + } + } + +-static struct inode *fsnotify_detach_connector_from_object( +- struct fsnotify_mark_connector *conn) ++static void *fsnotify_detach_connector_from_object( ++ struct fsnotify_mark_connector *conn, ++ unsigned int *type) + { + struct inode *inode = NULL; + ++ *type = conn->type; + if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) + return NULL; + + if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) { + inode = fsnotify_conn_inode(conn); + inode->i_fsnotify_mask = 0; ++ atomic_long_inc(&inode->i_sb->s_fsnotify_inode_refs); + } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) { + fsnotify_conn_mount(conn)->mnt_fsnotify_mask = 0; + } +@@ -211,10 +214,29 @@ static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark) + fsnotify_put_group(group); + } + ++/* Drop object reference originally held by a connector */ ++static void fsnotify_drop_object(unsigned int type, void *objp) ++{ ++ struct inode *inode; ++ struct super_block *sb; ++ ++ if (!objp) ++ return; ++ /* Currently only inode references are passed to be dropped */ ++ if (WARN_ON_ONCE(type != FSNOTIFY_OBJ_TYPE_INODE)) ++ return; ++ inode = objp; ++ sb = inode->i_sb; ++ iput(inode); ++ if (atomic_long_dec_and_test(&sb->s_fsnotify_inode_refs)) ++ wake_up_var(&sb->s_fsnotify_inode_refs); ++} ++ + void fsnotify_put_mark(struct fsnotify_mark *mark) + { + struct fsnotify_mark_connector *conn; +- struct inode *inode = NULL; ++ void *objp = NULL; ++ unsigned int type = FSNOTIFY_OBJ_TYPE_DETACHED; + bool free_conn = false; + + /* Catch marks that were actually never attached to object */ +@@ -234,7 +256,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) + conn = mark->connector; + hlist_del_init_rcu(&mark->obj_list); + if (hlist_empty(&conn->list)) { +- inode = fsnotify_detach_connector_from_object(conn); ++ objp = fsnotify_detach_connector_from_object(conn, &type); + free_conn = true; + } else { + __fsnotify_recalc_mask(conn); +@@ -242,7 +264,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) + mark->connector = NULL; + spin_unlock(&conn->lock); + +- iput(inode); ++ fsnotify_drop_object(type, objp); + + if (free_conn) { + spin_lock(&destroy_lock); +@@ -709,7 +731,8 @@ void fsnotify_destroy_marks(fsnotify_connp_t *connp) + { + struct fsnotify_mark_connector *conn; + struct fsnotify_mark *mark, *old_mark = NULL; +- struct inode *inode; ++ void *objp; ++ unsigned int type; + + conn = fsnotify_grab_connector(connp); + if (!conn) +@@ -735,11 +758,11 @@ void fsnotify_destroy_marks(fsnotify_connp_t *connp) + * mark references get dropped. It would lead to strange results such + * as delaying inode deletion or blocking unmount. + */ +- inode = fsnotify_detach_connector_from_object(conn); ++ objp = fsnotify_detach_connector_from_object(conn, &type); + spin_unlock(&conn->lock); + if (old_mark) + fsnotify_put_mark(old_mark); +- iput(inode); ++ fsnotify_drop_object(type, objp); + } + + /* +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 5ea1d64cb0b4..a027473561c6 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -713,6 +713,8 @@ static void smap_gather_stats(struct vm_area_struct *vma, + smaps_walk.private = mss; + + #ifdef CONFIG_SHMEM ++ /* In case of smaps_rollup, reset the value from previous vma */ ++ mss->check_shmem_swap = false; + if (vma->vm_file && shmem_mapping(vma->vm_file->f_mapping)) { + /* + * For shared or readonly shmem mappings we know that all +@@ -728,7 +730,7 @@ static void smap_gather_stats(struct vm_area_struct *vma, + + if (!shmem_swapped || (vma->vm_flags & VM_SHARED) || + !(vma->vm_flags & VM_WRITE)) { +- mss->swap = shmem_swapped; ++ mss->swap += shmem_swapped; + } else { + mss->check_shmem_swap = true; + smaps_walk.pte_hole = smaps_pte_hole; +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index bfa0ec69f924..356d2b8568c1 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -1026,7 +1026,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait, + struct userfaultfd_ctx *fork_nctx = NULL; + + /* always take the fd_wqh lock before the fault_pending_wqh lock */ +- spin_lock(&ctx->fd_wqh.lock); ++ spin_lock_irq(&ctx->fd_wqh.lock); + __add_wait_queue(&ctx->fd_wqh, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); +@@ -1112,13 +1112,13 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait, + ret = -EAGAIN; + break; + } +- spin_unlock(&ctx->fd_wqh.lock); ++ spin_unlock_irq(&ctx->fd_wqh.lock); + schedule(); +- spin_lock(&ctx->fd_wqh.lock); ++ spin_lock_irq(&ctx->fd_wqh.lock); + } + __remove_wait_queue(&ctx->fd_wqh, &wait); + __set_current_state(TASK_RUNNING); +- spin_unlock(&ctx->fd_wqh.lock); ++ spin_unlock_irq(&ctx->fd_wqh.lock); + + if (!ret && msg->event == UFFD_EVENT_FORK) { + ret = resolve_userfault_fork(ctx, fork_nctx, msg); +diff --git a/include/crypto/speck.h b/include/crypto/speck.h +deleted file mode 100644 +index 73cfc952d405..000000000000 +--- a/include/crypto/speck.h ++++ /dev/null +@@ -1,62 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * Common values for the Speck algorithm +- */ +- +-#ifndef _CRYPTO_SPECK_H +-#define _CRYPTO_SPECK_H +- +-#include +- +-/* Speck128 */ +- +-#define SPECK128_BLOCK_SIZE 16 +- +-#define SPECK128_128_KEY_SIZE 16 +-#define SPECK128_128_NROUNDS 32 +- +-#define SPECK128_192_KEY_SIZE 24 +-#define SPECK128_192_NROUNDS 33 +- +-#define SPECK128_256_KEY_SIZE 32 +-#define SPECK128_256_NROUNDS 34 +- +-struct speck128_tfm_ctx { +- u64 round_keys[SPECK128_256_NROUNDS]; +- int nrounds; +-}; +- +-void crypto_speck128_encrypt(const struct speck128_tfm_ctx *ctx, +- u8 *out, const u8 *in); +- +-void crypto_speck128_decrypt(const struct speck128_tfm_ctx *ctx, +- u8 *out, const u8 *in); +- +-int crypto_speck128_setkey(struct speck128_tfm_ctx *ctx, const u8 *key, +- unsigned int keysize); +- +-/* Speck64 */ +- +-#define SPECK64_BLOCK_SIZE 8 +- +-#define SPECK64_96_KEY_SIZE 12 +-#define SPECK64_96_NROUNDS 26 +- +-#define SPECK64_128_KEY_SIZE 16 +-#define SPECK64_128_NROUNDS 27 +- +-struct speck64_tfm_ctx { +- u32 round_keys[SPECK64_128_NROUNDS]; +- int nrounds; +-}; +- +-void crypto_speck64_encrypt(const struct speck64_tfm_ctx *ctx, +- u8 *out, const u8 *in); +- +-void crypto_speck64_decrypt(const struct speck64_tfm_ctx *ctx, +- u8 *out, const u8 *in); +- +-int crypto_speck64_setkey(struct speck64_tfm_ctx *ctx, const u8 *key, +- unsigned int keysize); +- +-#endif /* _CRYPTO_SPECK_H */ +diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h +index 38b04f559ad3..1fd6fa822d2c 100644 +--- a/include/linux/bpf_verifier.h ++++ b/include/linux/bpf_verifier.h +@@ -50,6 +50,9 @@ struct bpf_reg_state { + * PTR_TO_MAP_VALUE_OR_NULL + */ + struct bpf_map *map_ptr; ++ ++ /* Max size from any of the above. */ ++ unsigned long raw; + }; + /* Fixed part of pointer offset, pointer types only */ + s32 off; +diff --git a/include/linux/compat.h b/include/linux/compat.h +index 1a3c4f37e908..de0c13bdcd2c 100644 +--- a/include/linux/compat.h ++++ b/include/linux/compat.h +@@ -103,6 +103,9 @@ typedef struct compat_sigaltstack { + compat_size_t ss_size; + } compat_stack_t; + #endif ++#ifndef COMPAT_MINSIGSTKSZ ++#define COMPAT_MINSIGSTKSZ MINSIGSTKSZ ++#endif + + #define compat_jiffies_to_clock_t(x) \ + (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 897eae8faee1..7b6084854bfe 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1428,6 +1428,9 @@ struct super_block { + /* Number of inodes with nlink == 0 but still referenced */ + atomic_long_t s_remove_count; + ++ /* Pending fsnotify inode refs */ ++ atomic_long_t s_fsnotify_inode_refs; ++ + /* Being remounted read-only */ + int s_readonly_remount; + +diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h +index d271ff23984f..4f3febc0f971 100644 +--- a/include/linux/hdmi.h ++++ b/include/linux/hdmi.h +@@ -101,8 +101,8 @@ enum hdmi_extended_colorimetry { + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601, + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709, + HDMI_EXTENDED_COLORIMETRY_S_YCC_601, +- HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601, +- HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB, ++ HDMI_EXTENDED_COLORIMETRY_OPYCC_601, ++ HDMI_EXTENDED_COLORIMETRY_OPRGB, + + /* The following EC values are only defined in CEA-861-F. */ + HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM, +diff --git a/include/linux/nvme.h b/include/linux/nvme.h +index 68e91ef5494c..818dbe9331be 100644 +--- a/include/linux/nvme.h ++++ b/include/linux/nvme.h +@@ -1241,6 +1241,7 @@ enum { + NVME_SC_ANA_PERSISTENT_LOSS = 0x301, + NVME_SC_ANA_INACCESSIBLE = 0x302, + NVME_SC_ANA_TRANSITION = 0x303, ++ NVME_SC_HOST_PATH_ERROR = 0x370, + + NVME_SC_DNR = 0x4000, + }; +diff --git a/include/linux/signal.h b/include/linux/signal.h +index 3d4cd5db30a9..e4d01469ed60 100644 +--- a/include/linux/signal.h ++++ b/include/linux/signal.h +@@ -36,7 +36,7 @@ enum siginfo_layout { + SIL_SYS, + }; + +-enum siginfo_layout siginfo_layout(int sig, int si_code); ++enum siginfo_layout siginfo_layout(unsigned sig, int si_code); + + /* + * Define some primitives to manipulate sigset_t. +diff --git a/include/linux/tc.h b/include/linux/tc.h +index f92511e57cdb..a60639f37963 100644 +--- a/include/linux/tc.h ++++ b/include/linux/tc.h +@@ -84,6 +84,7 @@ struct tc_dev { + device. */ + struct device dev; /* Generic device interface. */ + struct resource resource; /* Address space of this device. */ ++ u64 dma_mask; /* DMA addressable range. */ + char vendor[9]; + char name[9]; + char firmware[9]; +diff --git a/include/linux/wait.h b/include/linux/wait.h +index d9f131ecf708..ed7c122cb31f 100644 +--- a/include/linux/wait.h ++++ b/include/linux/wait.h +@@ -1052,10 +1052,9 @@ do { \ + __ret; \ + }) + +-#define __wait_event_interruptible_lock_irq_timeout(wq_head, condition, \ +- lock, timeout) \ ++#define __wait_event_lock_irq_timeout(wq_head, condition, lock, timeout, state) \ + ___wait_event(wq_head, ___wait_cond_timeout(condition), \ +- TASK_INTERRUPTIBLE, 0, timeout, \ ++ state, 0, timeout, \ + spin_unlock_irq(&lock); \ + __ret = schedule_timeout(__ret); \ + spin_lock_irq(&lock)); +@@ -1089,8 +1088,19 @@ do { \ + ({ \ + long __ret = timeout; \ + if (!___wait_cond_timeout(condition)) \ +- __ret = __wait_event_interruptible_lock_irq_timeout( \ +- wq_head, condition, lock, timeout); \ ++ __ret = __wait_event_lock_irq_timeout( \ ++ wq_head, condition, lock, timeout, \ ++ TASK_INTERRUPTIBLE); \ ++ __ret; \ ++}) ++ ++#define wait_event_lock_irq_timeout(wq_head, condition, lock, timeout) \ ++({ \ ++ long __ret = timeout; \ ++ if (!___wait_cond_timeout(condition)) \ ++ __ret = __wait_event_lock_irq_timeout( \ ++ wq_head, condition, lock, timeout, \ ++ TASK_UNINTERRUPTIBLE); \ + __ret; \ + }) + +diff --git a/include/media/cec.h b/include/media/cec.h +index ff9847f7f99d..9b7394a74dca 100644 +--- a/include/media/cec.h ++++ b/include/media/cec.h +@@ -63,7 +63,6 @@ struct cec_data { + struct delayed_work work; + struct completion c; + u8 attempts; +- bool new_initiator; + bool blocking; + bool completed; + }; +@@ -174,6 +173,7 @@ struct cec_adapter { + bool is_configuring; + bool is_configured; + bool cec_pin_is_high; ++ u8 last_initiator; + u32 monitor_all_cnt; + u32 monitor_pin_cnt; + u32 follower_cnt; +@@ -461,4 +461,74 @@ static inline void cec_phys_addr_invalidate(struct cec_adapter *adap) + cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false); + } + ++/** ++ * cec_get_edid_spa_location() - find location of the Source Physical Address ++ * ++ * @edid: the EDID ++ * @size: the size of the EDID ++ * ++ * This EDID is expected to be a CEA-861 compliant, which means that there are ++ * at least two blocks and one or more of the extensions blocks are CEA-861 ++ * blocks. ++ * ++ * The returned location is guaranteed to be <= size-2. ++ * ++ * This is an inline function since it is used by both CEC and V4L2. ++ * Ideally this would go in a module shared by both, but it is overkill to do ++ * that for just a single function. ++ */ ++static inline unsigned int cec_get_edid_spa_location(const u8 *edid, ++ unsigned int size) ++{ ++ unsigned int blocks = size / 128; ++ unsigned int block; ++ u8 d; ++ ++ /* Sanity check: at least 2 blocks and a multiple of the block size */ ++ if (blocks < 2 || size % 128) ++ return 0; ++ ++ /* ++ * If there are fewer extension blocks than the size, then update ++ * 'blocks'. It is allowed to have more extension blocks than the size, ++ * since some hardware can only read e.g. 256 bytes of the EDID, even ++ * though more blocks are present. The first CEA-861 extension block ++ * should normally be in block 1 anyway. ++ */ ++ if (edid[0x7e] + 1 < blocks) ++ blocks = edid[0x7e] + 1; ++ ++ for (block = 1; block < blocks; block++) { ++ unsigned int offset = block * 128; ++ ++ /* Skip any non-CEA-861 extension blocks */ ++ if (edid[offset] != 0x02 || edid[offset + 1] != 0x03) ++ continue; ++ ++ /* search Vendor Specific Data Block (tag 3) */ ++ d = edid[offset + 2] & 0x7f; ++ /* Check if there are Data Blocks */ ++ if (d <= 4) ++ continue; ++ if (d > 4) { ++ unsigned int i = offset + 4; ++ unsigned int end = offset + d; ++ ++ /* Note: 'end' is always < 'size' */ ++ do { ++ u8 tag = edid[i] >> 5; ++ u8 len = edid[i] & 0x1f; ++ ++ if (tag == 3 && len >= 5 && i + len <= end && ++ edid[i + 1] == 0x03 && ++ edid[i + 2] == 0x0c && ++ edid[i + 3] == 0x00) ++ return i + 4; ++ i += len + 1; ++ } while (i < end); ++ } ++ } ++ return 0; ++} ++ + #endif /* _MEDIA_CEC_H */ +diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h +index e950c2a68f06..ec299fcf55f7 100644 +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -1278,21 +1278,27 @@ struct ib_qp_attr { + }; + + enum ib_wr_opcode { +- IB_WR_RDMA_WRITE, +- IB_WR_RDMA_WRITE_WITH_IMM, +- IB_WR_SEND, +- IB_WR_SEND_WITH_IMM, +- IB_WR_RDMA_READ, +- IB_WR_ATOMIC_CMP_AND_SWP, +- IB_WR_ATOMIC_FETCH_AND_ADD, +- IB_WR_LSO, +- IB_WR_SEND_WITH_INV, +- IB_WR_RDMA_READ_WITH_INV, +- IB_WR_LOCAL_INV, +- IB_WR_REG_MR, +- IB_WR_MASKED_ATOMIC_CMP_AND_SWP, +- IB_WR_MASKED_ATOMIC_FETCH_AND_ADD, ++ /* These are shared with userspace */ ++ IB_WR_RDMA_WRITE = IB_UVERBS_WR_RDMA_WRITE, ++ IB_WR_RDMA_WRITE_WITH_IMM = IB_UVERBS_WR_RDMA_WRITE_WITH_IMM, ++ IB_WR_SEND = IB_UVERBS_WR_SEND, ++ IB_WR_SEND_WITH_IMM = IB_UVERBS_WR_SEND_WITH_IMM, ++ IB_WR_RDMA_READ = IB_UVERBS_WR_RDMA_READ, ++ IB_WR_ATOMIC_CMP_AND_SWP = IB_UVERBS_WR_ATOMIC_CMP_AND_SWP, ++ IB_WR_ATOMIC_FETCH_AND_ADD = IB_UVERBS_WR_ATOMIC_FETCH_AND_ADD, ++ IB_WR_LSO = IB_UVERBS_WR_TSO, ++ IB_WR_SEND_WITH_INV = IB_UVERBS_WR_SEND_WITH_INV, ++ IB_WR_RDMA_READ_WITH_INV = IB_UVERBS_WR_RDMA_READ_WITH_INV, ++ IB_WR_LOCAL_INV = IB_UVERBS_WR_LOCAL_INV, ++ IB_WR_MASKED_ATOMIC_CMP_AND_SWP = ++ IB_UVERBS_WR_MASKED_ATOMIC_CMP_AND_SWP, ++ IB_WR_MASKED_ATOMIC_FETCH_AND_ADD = ++ IB_UVERBS_WR_MASKED_ATOMIC_FETCH_AND_ADD, ++ ++ /* These are kernel only and can not be issued by userspace */ ++ IB_WR_REG_MR = 0x20, + IB_WR_REG_SIG_MR, ++ + /* reserve values for low level drivers' internal use. + * These values will not be used at all in the ib core layer. + */ +diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h +index 097fcd812471..3094af68b6e7 100644 +--- a/include/uapi/linux/cec.h ++++ b/include/uapi/linux/cec.h +@@ -152,10 +152,13 @@ static inline void cec_msg_set_reply_to(struct cec_msg *msg, + #define CEC_TX_STATUS_LOW_DRIVE (1 << 3) + #define CEC_TX_STATUS_ERROR (1 << 4) + #define CEC_TX_STATUS_MAX_RETRIES (1 << 5) ++#define CEC_TX_STATUS_ABORTED (1 << 6) ++#define CEC_TX_STATUS_TIMEOUT (1 << 7) + + #define CEC_RX_STATUS_OK (1 << 0) + #define CEC_RX_STATUS_TIMEOUT (1 << 1) + #define CEC_RX_STATUS_FEATURE_ABORT (1 << 2) ++#define CEC_RX_STATUS_ABORTED (1 << 3) + + static inline int cec_msg_status_is_ok(const struct cec_msg *msg) + { +diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h +index 73e01918f996..a441ea1bfe6d 100644 +--- a/include/uapi/linux/fs.h ++++ b/include/uapi/linux/fs.h +@@ -279,8 +279,8 @@ struct fsxattr { + #define FS_ENCRYPTION_MODE_AES_256_CTS 4 + #define FS_ENCRYPTION_MODE_AES_128_CBC 5 + #define FS_ENCRYPTION_MODE_AES_128_CTS 6 +-#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 +-#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 ++#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7 /* Removed, do not use. */ ++#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8 /* Removed, do not use. */ + + struct fscrypt_policy { + __u8 version; +diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h +index 7e27070b9440..2f2c43d633c5 100644 +--- a/include/uapi/linux/ndctl.h ++++ b/include/uapi/linux/ndctl.h +@@ -128,37 +128,31 @@ enum { + + static inline const char *nvdimm_bus_cmd_name(unsigned cmd) + { +- static const char * const names[] = { +- [ND_CMD_ARS_CAP] = "ars_cap", +- [ND_CMD_ARS_START] = "ars_start", +- [ND_CMD_ARS_STATUS] = "ars_status", +- [ND_CMD_CLEAR_ERROR] = "clear_error", +- [ND_CMD_CALL] = "cmd_call", +- }; +- +- if (cmd < ARRAY_SIZE(names) && names[cmd]) +- return names[cmd]; +- return "unknown"; ++ switch (cmd) { ++ case ND_CMD_ARS_CAP: return "ars_cap"; ++ case ND_CMD_ARS_START: return "ars_start"; ++ case ND_CMD_ARS_STATUS: return "ars_status"; ++ case ND_CMD_CLEAR_ERROR: return "clear_error"; ++ case ND_CMD_CALL: return "cmd_call"; ++ default: return "unknown"; ++ } + } + + static inline const char *nvdimm_cmd_name(unsigned cmd) + { +- static const char * const names[] = { +- [ND_CMD_SMART] = "smart", +- [ND_CMD_SMART_THRESHOLD] = "smart_thresh", +- [ND_CMD_DIMM_FLAGS] = "flags", +- [ND_CMD_GET_CONFIG_SIZE] = "get_size", +- [ND_CMD_GET_CONFIG_DATA] = "get_data", +- [ND_CMD_SET_CONFIG_DATA] = "set_data", +- [ND_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size", +- [ND_CMD_VENDOR_EFFECT_LOG] = "effect_log", +- [ND_CMD_VENDOR] = "vendor", +- [ND_CMD_CALL] = "cmd_call", +- }; +- +- if (cmd < ARRAY_SIZE(names) && names[cmd]) +- return names[cmd]; +- return "unknown"; ++ switch (cmd) { ++ case ND_CMD_SMART: return "smart"; ++ case ND_CMD_SMART_THRESHOLD: return "smart_thresh"; ++ case ND_CMD_DIMM_FLAGS: return "flags"; ++ case ND_CMD_GET_CONFIG_SIZE: return "get_size"; ++ case ND_CMD_GET_CONFIG_DATA: return "get_data"; ++ case ND_CMD_SET_CONFIG_DATA: return "set_data"; ++ case ND_CMD_VENDOR_EFFECT_LOG_SIZE: return "effect_size"; ++ case ND_CMD_VENDOR_EFFECT_LOG: return "effect_log"; ++ case ND_CMD_VENDOR: return "vendor"; ++ case ND_CMD_CALL: return "cmd_call"; ++ default: return "unknown"; ++ } + } + + #define ND_IOCTL 'N' +diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h +index 5d1a3685bea9..1aae2e4b8f10 100644 +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -225,8 +225,8 @@ enum v4l2_colorspace { + /* For RGB colorspaces such as produces by most webcams. */ + V4L2_COLORSPACE_SRGB = 8, + +- /* AdobeRGB colorspace */ +- V4L2_COLORSPACE_ADOBERGB = 9, ++ /* opRGB colorspace */ ++ V4L2_COLORSPACE_OPRGB = 9, + + /* BT.2020 colorspace, used for UHDTV. */ + V4L2_COLORSPACE_BT2020 = 10, +@@ -258,7 +258,7 @@ enum v4l2_xfer_func { + * + * V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_JPEG: V4L2_XFER_FUNC_SRGB + * +- * V4L2_COLORSPACE_ADOBERGB: V4L2_XFER_FUNC_ADOBERGB ++ * V4L2_COLORSPACE_OPRGB: V4L2_XFER_FUNC_OPRGB + * + * V4L2_COLORSPACE_SMPTE240M: V4L2_XFER_FUNC_SMPTE240M + * +@@ -269,7 +269,7 @@ enum v4l2_xfer_func { + V4L2_XFER_FUNC_DEFAULT = 0, + V4L2_XFER_FUNC_709 = 1, + V4L2_XFER_FUNC_SRGB = 2, +- V4L2_XFER_FUNC_ADOBERGB = 3, ++ V4L2_XFER_FUNC_OPRGB = 3, + V4L2_XFER_FUNC_SMPTE240M = 4, + V4L2_XFER_FUNC_NONE = 5, + V4L2_XFER_FUNC_DCI_P3 = 6, +@@ -281,7 +281,7 @@ enum v4l2_xfer_func { + * This depends on the colorspace. + */ + #define V4L2_MAP_XFER_FUNC_DEFAULT(colsp) \ +- ((colsp) == V4L2_COLORSPACE_ADOBERGB ? V4L2_XFER_FUNC_ADOBERGB : \ ++ ((colsp) == V4L2_COLORSPACE_OPRGB ? V4L2_XFER_FUNC_OPRGB : \ + ((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_XFER_FUNC_SMPTE240M : \ + ((colsp) == V4L2_COLORSPACE_DCI_P3 ? V4L2_XFER_FUNC_DCI_P3 : \ + ((colsp) == V4L2_COLORSPACE_RAW ? V4L2_XFER_FUNC_NONE : \ +@@ -295,7 +295,7 @@ enum v4l2_ycbcr_encoding { + * + * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M, + * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_SRGB, +- * V4L2_COLORSPACE_ADOBERGB and V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601 ++ * V4L2_COLORSPACE_OPRGB and V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601 + * + * V4L2_COLORSPACE_REC709 and V4L2_COLORSPACE_DCI_P3: V4L2_YCBCR_ENC_709 + * +@@ -382,6 +382,17 @@ enum v4l2_quantization { + (((is_rgb_or_hsv) || (colsp) == V4L2_COLORSPACE_JPEG) ? \ + V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE)) + ++/* ++ * Deprecated names for opRGB colorspace (IEC 61966-2-5) ++ * ++ * WARNING: Please don't use these deprecated defines in your code, as ++ * there is a chance we have to remove them in the future. ++ */ ++#ifndef __KERNEL__ ++#define V4L2_COLORSPACE_ADOBERGB V4L2_COLORSPACE_OPRGB ++#define V4L2_XFER_FUNC_ADOBERGB V4L2_XFER_FUNC_OPRGB ++#endif ++ + enum v4l2_priority { + V4L2_PRIORITY_UNSET = 0, /* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, +diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h +index 25a16760de2a..1254b51a551a 100644 +--- a/include/uapi/rdma/ib_user_verbs.h ++++ b/include/uapi/rdma/ib_user_verbs.h +@@ -763,10 +763,28 @@ struct ib_uverbs_sge { + __u32 lkey; + }; + ++enum ib_uverbs_wr_opcode { ++ IB_UVERBS_WR_RDMA_WRITE = 0, ++ IB_UVERBS_WR_RDMA_WRITE_WITH_IMM = 1, ++ IB_UVERBS_WR_SEND = 2, ++ IB_UVERBS_WR_SEND_WITH_IMM = 3, ++ IB_UVERBS_WR_RDMA_READ = 4, ++ IB_UVERBS_WR_ATOMIC_CMP_AND_SWP = 5, ++ IB_UVERBS_WR_ATOMIC_FETCH_AND_ADD = 6, ++ IB_UVERBS_WR_LOCAL_INV = 7, ++ IB_UVERBS_WR_BIND_MW = 8, ++ IB_UVERBS_WR_SEND_WITH_INV = 9, ++ IB_UVERBS_WR_TSO = 10, ++ IB_UVERBS_WR_RDMA_READ_WITH_INV = 11, ++ IB_UVERBS_WR_MASKED_ATOMIC_CMP_AND_SWP = 12, ++ IB_UVERBS_WR_MASKED_ATOMIC_FETCH_AND_ADD = 13, ++ /* Review enum ib_wr_opcode before modifying this */ ++}; ++ + struct ib_uverbs_send_wr { + __aligned_u64 wr_id; + __u32 num_sge; +- __u32 opcode; ++ __u32 opcode; /* see enum ib_uverbs_wr_opcode */ + __u32 send_flags; + union { + __be32 imm_data; +diff --git a/kernel/bounds.c b/kernel/bounds.c +index c373e887c066..9795d75b09b2 100644 +--- a/kernel/bounds.c ++++ b/kernel/bounds.c +@@ -13,7 +13,7 @@ + #include + #include + +-void foo(void) ++int main(void) + { + /* The enum constants to put into include/generated/bounds.h */ + DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS); +@@ -23,4 +23,6 @@ void foo(void) + #endif + DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t)); + /* End of constants */ ++ ++ return 0; + } +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 8339d81cba1d..675eb6d36e47 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -741,6 +741,17 @@ err_put: + return err; + } + ++static void maybe_wait_bpf_programs(struct bpf_map *map) ++{ ++ /* Wait for any running BPF programs to complete so that ++ * userspace, when we return to it, knows that all programs ++ * that could be running use the new map value. ++ */ ++ if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS || ++ map->map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS) ++ synchronize_rcu(); ++} ++ + #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags + + static int map_update_elem(union bpf_attr *attr) +@@ -831,6 +842,7 @@ static int map_update_elem(union bpf_attr *attr) + } + __this_cpu_dec(bpf_prog_active); + preempt_enable(); ++ maybe_wait_bpf_programs(map); + out: + free_value: + kfree(value); +@@ -883,6 +895,7 @@ static int map_delete_elem(union bpf_attr *attr) + rcu_read_unlock(); + __this_cpu_dec(bpf_prog_active); + preempt_enable(); ++ maybe_wait_bpf_programs(map); + out: + kfree(key); + err_put: +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 465952a8e465..5780876ac81a 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -553,7 +553,9 @@ static void __mark_reg_not_init(struct bpf_reg_state *reg); + */ + static void __mark_reg_known(struct bpf_reg_state *reg, u64 imm) + { +- reg->id = 0; ++ /* Clear id, off, and union(map_ptr, range) */ ++ memset(((u8 *)reg) + sizeof(reg->type), 0, ++ offsetof(struct bpf_reg_state, var_off) - sizeof(reg->type)); + reg->var_off = tnum_const(imm); + reg->smin_value = (s64)imm; + reg->smax_value = (s64)imm; +@@ -572,7 +574,6 @@ static void __mark_reg_known_zero(struct bpf_reg_state *reg) + static void __mark_reg_const_zero(struct bpf_reg_state *reg) + { + __mark_reg_known(reg, 0); +- reg->off = 0; + reg->type = SCALAR_VALUE; + } + +@@ -683,9 +684,12 @@ static void __mark_reg_unbounded(struct bpf_reg_state *reg) + /* Mark a register as having a completely unknown (scalar) value. */ + static void __mark_reg_unknown(struct bpf_reg_state *reg) + { ++ /* ++ * Clear type, id, off, and union(map_ptr, range) and ++ * padding between 'type' and union ++ */ ++ memset(reg, 0, offsetof(struct bpf_reg_state, var_off)); + reg->type = SCALAR_VALUE; +- reg->id = 0; +- reg->off = 0; + reg->var_off = tnum_unknown; + reg->frameno = 0; + __mark_reg_unbounded(reg); +@@ -1727,9 +1731,6 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn + else + mark_reg_known_zero(env, regs, + value_regno); +- regs[value_regno].id = 0; +- regs[value_regno].off = 0; +- regs[value_regno].range = 0; + regs[value_regno].type = reg_type; + } + +@@ -2580,7 +2581,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn + regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; + /* There is no offset yet applied, variable or fixed */ + mark_reg_known_zero(env, regs, BPF_REG_0); +- regs[BPF_REG_0].off = 0; + /* remember map_ptr, so that check_map_access() + * can check 'value_size' boundary of memory access + * to map element returned from bpf_map_lookup_elem() +@@ -2762,7 +2762,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + dst_reg->umax_value = umax_ptr; + dst_reg->var_off = ptr_reg->var_off; + dst_reg->off = ptr_reg->off + smin_val; +- dst_reg->range = ptr_reg->range; ++ dst_reg->raw = ptr_reg->raw; + break; + } + /* A new variable offset is created. Note that off_reg->off +@@ -2792,10 +2792,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + } + dst_reg->var_off = tnum_add(ptr_reg->var_off, off_reg->var_off); + dst_reg->off = ptr_reg->off; ++ dst_reg->raw = ptr_reg->raw; + if (reg_is_pkt_pointer(ptr_reg)) { + dst_reg->id = ++env->id_gen; + /* something was added to pkt_ptr, set range to zero */ +- dst_reg->range = 0; ++ dst_reg->raw = 0; + } + break; + case BPF_SUB: +@@ -2824,7 +2825,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + dst_reg->var_off = ptr_reg->var_off; + dst_reg->id = ptr_reg->id; + dst_reg->off = ptr_reg->off - smin_val; +- dst_reg->range = ptr_reg->range; ++ dst_reg->raw = ptr_reg->raw; + break; + } + /* A new variable offset is created. If the subtrahend is known +@@ -2850,11 +2851,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, + } + dst_reg->var_off = tnum_sub(ptr_reg->var_off, off_reg->var_off); + dst_reg->off = ptr_reg->off; ++ dst_reg->raw = ptr_reg->raw; + if (reg_is_pkt_pointer(ptr_reg)) { + dst_reg->id = ++env->id_gen; + /* something was added to pkt_ptr, set range to zero */ + if (smin_val < 0) +- dst_reg->range = 0; ++ dst_reg->raw = 0; + } + break; + case BPF_AND: +diff --git a/kernel/cpu.c b/kernel/cpu.c +index 0097acec1c71..3adecda21444 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -2026,6 +2026,12 @@ static void cpuhp_online_cpu_device(unsigned int cpu) + kobject_uevent(&dev->kobj, KOBJ_ONLINE); + } + ++/* ++ * Architectures that need SMT-specific errata handling during SMT hotplug ++ * should override this. ++ */ ++void __weak arch_smt_update(void) { }; ++ + static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) + { + int cpu, ret = 0; +@@ -2052,8 +2058,10 @@ static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) + */ + cpuhp_offline_cpu_device(cpu); + } +- if (!ret) ++ if (!ret) { + cpu_smt_control = ctrlval; ++ arch_smt_update(); ++ } + cpu_maps_update_done(); + return ret; + } +@@ -2064,6 +2072,7 @@ static int cpuhp_smt_enable(void) + + cpu_maps_update_begin(); + cpu_smt_control = CPU_SMT_ENABLED; ++ arch_smt_update(); + for_each_present_cpu(cpu) { + /* Skip online CPUs and CPUs on offline nodes */ + if (cpu_online(cpu) || !node_online(cpu_to_node(cpu))) +diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c +index 286d82329eb0..b2a87905846d 100644 +--- a/kernel/dma/contiguous.c ++++ b/kernel/dma/contiguous.c +@@ -49,7 +49,11 @@ static phys_addr_t limit_cmdline; + + static int __init early_cma(char *p) + { +- pr_debug("%s(%s)\n", __func__, p); ++ if (!p) { ++ pr_err("Config string not provided\n"); ++ return -EINVAL; ++ } ++ + size_cmdline = memparse(p, &p); + if (*p != '@') + return 0; +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index fb86146037a7..9dbdccab3b6a 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -927,6 +927,9 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) + + local_bh_disable(); + ret = action->thread_fn(action->irq, action->dev_id); ++ if (ret == IRQ_HANDLED) ++ atomic_inc(&desc->threads_handled); ++ + irq_finalize_oneshot(desc, action); + local_bh_enable(); + return ret; +@@ -943,6 +946,9 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc, + irqreturn_t ret; + + ret = action->thread_fn(action->irq, action->dev_id); ++ if (ret == IRQ_HANDLED) ++ atomic_inc(&desc->threads_handled); ++ + irq_finalize_oneshot(desc, action); + return ret; + } +@@ -1020,8 +1026,6 @@ static int irq_thread(void *data) + irq_thread_check_affinity(desc, action); + + action_ret = handler_fn(desc, action); +- if (action_ret == IRQ_HANDLED) +- atomic_inc(&desc->threads_handled); + if (action_ret == IRQ_WAKE_THREAD) + irq_wake_secondary(desc, action); + +diff --git a/kernel/kprobes.c b/kernel/kprobes.c +index ab257be4d924..4344381664cc 100644 +--- a/kernel/kprobes.c ++++ b/kernel/kprobes.c +@@ -700,9 +700,10 @@ static void unoptimize_kprobe(struct kprobe *p, bool force) + } + + /* Cancel unoptimizing for reusing */ +-static void reuse_unused_kprobe(struct kprobe *ap) ++static int reuse_unused_kprobe(struct kprobe *ap) + { + struct optimized_kprobe *op; ++ int ret; + + BUG_ON(!kprobe_unused(ap)); + /* +@@ -714,8 +715,12 @@ static void reuse_unused_kprobe(struct kprobe *ap) + /* Enable the probe again */ + ap->flags &= ~KPROBE_FLAG_DISABLED; + /* Optimize it again (remove from op->list) */ +- BUG_ON(!kprobe_optready(ap)); ++ ret = kprobe_optready(ap); ++ if (ret) ++ return ret; ++ + optimize_kprobe(ap); ++ return 0; + } + + /* Remove optimized instructions */ +@@ -940,11 +945,16 @@ static void __disarm_kprobe(struct kprobe *p, bool reopt) + #define kprobe_disarmed(p) kprobe_disabled(p) + #define wait_for_kprobe_optimizer() do {} while (0) + +-/* There should be no unused kprobes can be reused without optimization */ +-static void reuse_unused_kprobe(struct kprobe *ap) ++static int reuse_unused_kprobe(struct kprobe *ap) + { ++ /* ++ * If the optimized kprobe is NOT supported, the aggr kprobe is ++ * released at the same time that the last aggregated kprobe is ++ * unregistered. ++ * Thus there should be no chance to reuse unused kprobe. ++ */ + printk(KERN_ERR "Error: There should be no unused kprobe here.\n"); +- BUG_ON(kprobe_unused(ap)); ++ return -EINVAL; + } + + static void free_aggr_kprobe(struct kprobe *p) +@@ -1318,9 +1328,12 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p) + goto out; + } + init_aggr_kprobe(ap, orig_p); +- } else if (kprobe_unused(ap)) ++ } else if (kprobe_unused(ap)) { + /* This probe is going to die. Rescue it */ +- reuse_unused_kprobe(ap); ++ ret = reuse_unused_kprobe(ap); ++ if (ret) ++ goto out; ++ } + + if (kprobe_gone(ap)) { + /* +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index dd13f865ad40..26b57e24476f 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -4122,7 +4122,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip) + { + unsigned long flags; + +- if (unlikely(!lock_stat)) ++ if (unlikely(!lock_stat || !debug_locks)) + return; + + if (unlikely(current->lockdep_recursion)) +@@ -4142,7 +4142,7 @@ void lock_acquired(struct lockdep_map *lock, unsigned long ip) + { + unsigned long flags; + +- if (unlikely(!lock_stat)) ++ if (unlikely(!lock_stat || !debug_locks)) + return; + + if (unlikely(current->lockdep_recursion)) +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 9bf5404397e0..06045abd1887 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -1048,7 +1048,12 @@ static void __init log_buf_len_update(unsigned size) + /* save requested log_buf_len since it's too early to process it */ + static int __init log_buf_len_setup(char *str) + { +- unsigned size = memparse(str, &str); ++ unsigned int size; ++ ++ if (!str) ++ return -EINVAL; ++ ++ size = memparse(str, &str); + + log_buf_len_update(size); + +diff --git a/kernel/signal.c b/kernel/signal.c +index 5843c541fda9..edc28afc9fb4 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1035,7 +1035,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, + + result = TRACE_SIGNAL_IGNORED; + if (!prepare_signal(sig, t, +- from_ancestor_ns || (info == SEND_SIG_FORCED))) ++ from_ancestor_ns || (info == SEND_SIG_PRIV) || (info == SEND_SIG_FORCED))) + goto ret; + + pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending; +@@ -2847,7 +2847,7 @@ COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, + } + #endif + +-enum siginfo_layout siginfo_layout(int sig, int si_code) ++enum siginfo_layout siginfo_layout(unsigned sig, int si_code) + { + enum siginfo_layout layout = SIL_KILL; + if ((si_code > SI_USER) && (si_code < SI_KERNEL)) { +@@ -3460,7 +3460,8 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) + } + + static int +-do_sigaltstack (const stack_t *ss, stack_t *oss, unsigned long sp) ++do_sigaltstack (const stack_t *ss, stack_t *oss, unsigned long sp, ++ size_t min_ss_size) + { + struct task_struct *t = current; + +@@ -3490,7 +3491,7 @@ do_sigaltstack (const stack_t *ss, stack_t *oss, unsigned long sp) + ss_size = 0; + ss_sp = NULL; + } else { +- if (unlikely(ss_size < MINSIGSTKSZ)) ++ if (unlikely(ss_size < min_ss_size)) + return -ENOMEM; + } + +@@ -3508,7 +3509,8 @@ SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) + if (uss && copy_from_user(&new, uss, sizeof(stack_t))) + return -EFAULT; + err = do_sigaltstack(uss ? &new : NULL, uoss ? &old : NULL, +- current_user_stack_pointer()); ++ current_user_stack_pointer(), ++ MINSIGSTKSZ); + if (!err && uoss && copy_to_user(uoss, &old, sizeof(stack_t))) + err = -EFAULT; + return err; +@@ -3519,7 +3521,8 @@ int restore_altstack(const stack_t __user *uss) + stack_t new; + if (copy_from_user(&new, uss, sizeof(stack_t))) + return -EFAULT; +- (void)do_sigaltstack(&new, NULL, current_user_stack_pointer()); ++ (void)do_sigaltstack(&new, NULL, current_user_stack_pointer(), ++ MINSIGSTKSZ); + /* squash all but EFAULT for now */ + return 0; + } +@@ -3553,7 +3556,8 @@ static int do_compat_sigaltstack(const compat_stack_t __user *uss_ptr, + uss.ss_size = uss32.ss_size; + } + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, +- compat_user_stack_pointer()); ++ compat_user_stack_pointer(), ++ COMPAT_MINSIGSTKSZ); + if (ret >= 0 && uoss_ptr) { + compat_stack_t old; + memset(&old, 0, sizeof(old)); +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index d239004aaf29..eb908ef2ecec 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -1063,8 +1063,10 @@ static int create_synth_event(int argc, char **argv) + event = NULL; + ret = -EEXIST; + goto out; +- } else if (delete_event) ++ } else if (delete_event) { ++ ret = -ENOENT; + goto out; ++ } + + if (argc < 2) { + ret = -EINVAL; +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index e5222b5fb4fe..923414a246e9 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -974,10 +974,6 @@ static ssize_t map_write(struct file *file, const char __user *buf, + if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) + goto out; + +- ret = sort_idmaps(&new_map); +- if (ret < 0) +- goto out; +- + ret = -EPERM; + /* Map the lower ids from the parent user namespace to the + * kernel global id space. +@@ -1004,6 +1000,14 @@ static ssize_t map_write(struct file *file, const char __user *buf, + e->lower_first = lower_first; + } + ++ /* ++ * If we want to use binary search for lookup, this clones the extent ++ * array and sorts both copies. ++ */ ++ ret = sort_idmaps(&new_map); ++ if (ret < 0) ++ goto out; ++ + /* Install the map */ + if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) { + memcpy(map->extent, new_map.extent, +diff --git a/lib/debug_locks.c b/lib/debug_locks.c +index 96c4c633d95e..124fdf238b3d 100644 +--- a/lib/debug_locks.c ++++ b/lib/debug_locks.c +@@ -37,7 +37,7 @@ EXPORT_SYMBOL_GPL(debug_locks_silent); + */ + int debug_locks_off(void) + { +- if (__debug_locks_off()) { ++ if (debug_locks && __debug_locks_off()) { + if (!debug_locks_silent) { + console_verbose(); + return 1; +diff --git a/mm/hmm.c b/mm/hmm.c +index c968e49f7a0c..90193a7fabce 100644 +--- a/mm/hmm.c ++++ b/mm/hmm.c +@@ -91,16 +91,6 @@ static struct hmm *hmm_register(struct mm_struct *mm) + spin_lock_init(&hmm->lock); + hmm->mm = mm; + +- /* +- * We should only get here if hold the mmap_sem in write mode ie on +- * registration of first mirror through hmm_mirror_register() +- */ +- hmm->mmu_notifier.ops = &hmm_mmu_notifier_ops; +- if (__mmu_notifier_register(&hmm->mmu_notifier, mm)) { +- kfree(hmm); +- return NULL; +- } +- + spin_lock(&mm->page_table_lock); + if (!mm->hmm) + mm->hmm = hmm; +@@ -108,12 +98,27 @@ static struct hmm *hmm_register(struct mm_struct *mm) + cleanup = true; + spin_unlock(&mm->page_table_lock); + +- if (cleanup) { +- mmu_notifier_unregister(&hmm->mmu_notifier, mm); +- kfree(hmm); +- } ++ if (cleanup) ++ goto error; ++ ++ /* ++ * We should only get here if hold the mmap_sem in write mode ie on ++ * registration of first mirror through hmm_mirror_register() ++ */ ++ hmm->mmu_notifier.ops = &hmm_mmu_notifier_ops; ++ if (__mmu_notifier_register(&hmm->mmu_notifier, mm)) ++ goto error_mm; + + return mm->hmm; ++ ++error_mm: ++ spin_lock(&mm->page_table_lock); ++ if (mm->hmm == hmm) ++ mm->hmm = NULL; ++ spin_unlock(&mm->page_table_lock); ++error: ++ kfree(hmm); ++ return NULL; + } + + void hmm_mm_destroy(struct mm_struct *mm) +@@ -278,12 +283,13 @@ void hmm_mirror_unregister(struct hmm_mirror *mirror) + if (!should_unregister || mm == NULL) + return; + ++ mmu_notifier_unregister_no_release(&hmm->mmu_notifier, mm); ++ + spin_lock(&mm->page_table_lock); + if (mm->hmm == hmm) + mm->hmm = NULL; + spin_unlock(&mm->page_table_lock); + +- mmu_notifier_unregister_no_release(&hmm->mmu_notifier, mm); + kfree(hmm); + } + EXPORT_SYMBOL(hmm_mirror_unregister); +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 5c390f5a5207..7b5c0ad9a6bd 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -3690,6 +3690,12 @@ int huge_add_to_page_cache(struct page *page, struct address_space *mapping, + return err; + ClearPagePrivate(page); + ++ /* ++ * set page dirty so that it will not be removed from cache/file ++ * by non-hugetlbfs specific code paths. ++ */ ++ set_page_dirty(page); ++ + spin_lock(&inode->i_lock); + inode->i_blocks += blocks_per_huge_page(h); + spin_unlock(&inode->i_lock); +diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c +index ae3c2a35d61b..11df03e71288 100644 +--- a/mm/page_vma_mapped.c ++++ b/mm/page_vma_mapped.c +@@ -21,7 +21,29 @@ static bool map_pte(struct page_vma_mapped_walk *pvmw) + if (!is_swap_pte(*pvmw->pte)) + return false; + } else { +- if (!pte_present(*pvmw->pte)) ++ /* ++ * We get here when we are trying to unmap a private ++ * device page from the process address space. Such ++ * page is not CPU accessible and thus is mapped as ++ * a special swap entry, nonetheless it still does ++ * count as a valid regular mapping for the page (and ++ * is accounted as such in page maps count). ++ * ++ * So handle this special case as if it was a normal ++ * page mapping ie lock CPU page table and returns ++ * true. ++ * ++ * For more details on device private memory see HMM ++ * (include/linux/hmm.h or mm/hmm.c). ++ */ ++ if (is_swap_pte(*pvmw->pte)) { ++ swp_entry_t entry; ++ ++ /* Handle un-addressable ZONE_DEVICE memory */ ++ entry = pte_to_swp_entry(*pvmw->pte); ++ if (!is_device_private_entry(entry)) ++ return false; ++ } else if (!pte_present(*pvmw->pte)) + return false; + } + } +diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c +index 5e4f04004a49..7bf833598615 100644 +--- a/net/core/netclassid_cgroup.c ++++ b/net/core/netclassid_cgroup.c +@@ -106,6 +106,7 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, + iterate_fd(p->files, 0, update_classid_sock, + (void *)(unsigned long)cs->classid); + task_unlock(p); ++ cond_resched(); + } + css_task_iter_end(&it); + +diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c +index 82178cc69c96..777fa3b7fb13 100644 +--- a/net/ipv4/cipso_ipv4.c ++++ b/net/ipv4/cipso_ipv4.c +@@ -1512,7 +1512,7 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def, + * + * Description: + * Parse the packet's IP header looking for a CIPSO option. Returns a pointer +- * to the start of the CIPSO option on success, NULL if one if not found. ++ * to the start of the CIPSO option on success, NULL if one is not found. + * + */ + unsigned char *cipso_v4_optptr(const struct sk_buff *skb) +@@ -1522,10 +1522,8 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb) + int optlen; + int taglen; + +- for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) { ++ for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 1; ) { + switch (optptr[0]) { +- case IPOPT_CIPSO: +- return optptr; + case IPOPT_END: + return NULL; + case IPOPT_NOOP: +@@ -1534,6 +1532,11 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb) + default: + taglen = optptr[1]; + } ++ if (!taglen || taglen > optlen) ++ return NULL; ++ if (optptr[0] == IPOPT_CIPSO) ++ return optptr; ++ + optlen -= taglen; + optptr += taglen; + } +diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c +index 8af9707f8789..ac91170fc8c8 100644 +--- a/net/netfilter/xt_nat.c ++++ b/net/netfilter/xt_nat.c +@@ -216,6 +216,8 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { + { + .name = "DNAT", + .revision = 2, ++ .checkentry = xt_nat_checkentry, ++ .destroy = xt_nat_destroy, + .target = xt_dnat_target_v2, + .targetsize = sizeof(struct nf_nat_range2), + .table = "nat", +diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c +index 3dc0acf54245..be7cd140b2a3 100644 +--- a/net/sched/sch_api.c ++++ b/net/sched/sch_api.c +@@ -1309,7 +1309,6 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w) + + const struct nla_policy rtm_tca_policy[TCA_MAX + 1] = { + [TCA_KIND] = { .type = NLA_STRING }, +- [TCA_OPTIONS] = { .type = NLA_NESTED }, + [TCA_RATE] = { .type = NLA_BINARY, + .len = sizeof(struct tc_estimator) }, + [TCA_STAB] = { .type = NLA_NESTED }, +diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c +index 5185efb9027b..83ccd0221c98 100644 +--- a/net/sunrpc/svc_xprt.c ++++ b/net/sunrpc/svc_xprt.c +@@ -989,7 +989,7 @@ static void call_xpt_users(struct svc_xprt *xprt) + spin_lock(&xprt->xpt_lock); + while (!list_empty(&xprt->xpt_users)) { + u = list_first_entry(&xprt->xpt_users, struct svc_xpt_user, list); +- list_del(&u->list); ++ list_del_init(&u->list); + u->callback(u); + } + spin_unlock(&xprt->xpt_lock); +diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +index a68180090554..b9827665ff35 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c ++++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +@@ -248,6 +248,7 @@ static void + xprt_rdma_bc_close(struct rpc_xprt *xprt) + { + dprintk("svcrdma: %s: xprt %p\n", __func__, xprt); ++ xprt->cwnd = RPC_CWNDSHIFT; + } + + static void +diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c +index 143ce2579ba9..98cbc7b060ba 100644 +--- a/net/sunrpc/xprtrdma/transport.c ++++ b/net/sunrpc/xprtrdma/transport.c +@@ -468,6 +468,12 @@ xprt_rdma_close(struct rpc_xprt *xprt) + xprt->reestablish_timeout = 0; + xprt_disconnect_done(xprt); + rpcrdma_ep_disconnect(ep, ia); ++ ++ /* Prepare @xprt for the next connection by reinitializing ++ * its credit grant to one (see RFC 8166, Section 3.3.3). ++ */ ++ r_xprt->rx_buf.rb_credits = 1; ++ xprt->cwnd = RPC_CWNDSHIFT; + } + + /** +diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c +index 7e7e7e7c250a..d9e7728027c6 100644 +--- a/security/integrity/ima/ima_crypto.c ++++ b/security/integrity/ima/ima_crypto.c +@@ -210,7 +210,7 @@ static int ima_calc_file_hash_atfm(struct file *file, + { + loff_t i_size, offset; + char *rbuf[2] = { NULL, }; +- int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0; ++ int rc, rbuf_len, active = 0, ahash_rc = 0; + struct ahash_request *req; + struct scatterlist sg[1]; + struct crypto_wait wait; +@@ -257,11 +257,6 @@ static int ima_calc_file_hash_atfm(struct file *file, + &rbuf_size[1], 0); + } + +- if (!(file->f_mode & FMODE_READ)) { +- file->f_mode |= FMODE_READ; +- read = 1; +- } +- + for (offset = 0; offset < i_size; offset += rbuf_len) { + if (!rbuf[1] && offset) { + /* Not using two buffers, and it is not the first +@@ -300,8 +295,6 @@ static int ima_calc_file_hash_atfm(struct file *file, + /* wait for the last update request to complete */ + rc = ahash_wait(ahash_rc, &wait); + out3: +- if (read) +- file->f_mode &= ~FMODE_READ; + ima_free_pages(rbuf[0], rbuf_size[0]); + ima_free_pages(rbuf[1], rbuf_size[1]); + out2: +@@ -336,7 +329,7 @@ static int ima_calc_file_hash_tfm(struct file *file, + { + loff_t i_size, offset = 0; + char *rbuf; +- int rc, read = 0; ++ int rc; + SHASH_DESC_ON_STACK(shash, tfm); + + shash->tfm = tfm; +@@ -357,11 +350,6 @@ static int ima_calc_file_hash_tfm(struct file *file, + if (!rbuf) + return -ENOMEM; + +- if (!(file->f_mode & FMODE_READ)) { +- file->f_mode |= FMODE_READ; +- read = 1; +- } +- + while (offset < i_size) { + int rbuf_len; + +@@ -378,8 +366,6 @@ static int ima_calc_file_hash_tfm(struct file *file, + if (rc) + break; + } +- if (read) +- file->f_mode &= ~FMODE_READ; + kfree(rbuf); + out: + if (!rc) +@@ -420,6 +406,8 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) + { + loff_t i_size; + int rc; ++ struct file *f = file; ++ bool new_file_instance = false, modified_flags = false; + + /* + * For consistency, fail file's opened with the O_DIRECT flag on +@@ -431,15 +419,41 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) + return -EINVAL; + } + +- i_size = i_size_read(file_inode(file)); ++ /* Open a new file instance in O_RDONLY if we cannot read */ ++ if (!(file->f_mode & FMODE_READ)) { ++ int flags = file->f_flags & ~(O_WRONLY | O_APPEND | ++ O_TRUNC | O_CREAT | O_NOCTTY | O_EXCL); ++ flags |= O_RDONLY; ++ f = dentry_open(&file->f_path, flags, file->f_cred); ++ if (IS_ERR(f)) { ++ /* ++ * Cannot open the file again, lets modify f_flags ++ * of original and continue ++ */ ++ pr_info_ratelimited("Unable to reopen file for reading.\n"); ++ f = file; ++ f->f_flags |= FMODE_READ; ++ modified_flags = true; ++ } else { ++ new_file_instance = true; ++ } ++ } ++ ++ i_size = i_size_read(file_inode(f)); + + if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { +- rc = ima_calc_file_ahash(file, hash); ++ rc = ima_calc_file_ahash(f, hash); + if (!rc) +- return 0; ++ goto out; + } + +- return ima_calc_file_shash(file, hash); ++ rc = ima_calc_file_shash(f, hash); ++out: ++ if (new_file_instance) ++ fput(f); ++ else if (modified_flags) ++ f->f_flags &= ~FMODE_READ; ++ return rc; + } + + /* +diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c +index ae9d5c766a3c..cfb8cc3b975e 100644 +--- a/security/integrity/ima/ima_fs.c ++++ b/security/integrity/ima/ima_fs.c +@@ -42,14 +42,14 @@ static int __init default_canonical_fmt_setup(char *str) + __setup("ima_canonical_fmt", default_canonical_fmt_setup); + + static int valid_policy = 1; +-#define TMPBUFLEN 12 ++ + static ssize_t ima_show_htable_value(char __user *buf, size_t count, + loff_t *ppos, atomic_long_t *val) + { +- char tmpbuf[TMPBUFLEN]; ++ char tmpbuf[32]; /* greater than largest 'long' string value */ + ssize_t len; + +- len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val)); ++ len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", atomic_long_read(val)); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); + } + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index ad9a9b8e9979..18b98b5e1e3c 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -1508,6 +1508,11 @@ static int selinux_genfs_get_sid(struct dentry *dentry, + } + rc = security_genfs_sid(&selinux_state, sb->s_type->name, + path, tclass, sid); ++ if (rc == -ENOENT) { ++ /* No match in policy, mark as unlabeled. */ ++ *sid = SECINITSID_UNLABELED; ++ rc = 0; ++ } + } + free_page((unsigned long)buffer); + return rc; +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 340fc30ad85d..70d3066e69fe 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -421,6 +421,7 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, + struct smk_audit_info ad, *saip = NULL; + struct task_smack *tsp; + struct smack_known *tracer_known; ++ const struct cred *tracercred; + + if ((mode & PTRACE_MODE_NOAUDIT) == 0) { + smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); +@@ -429,7 +430,8 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, + } + + rcu_read_lock(); +- tsp = __task_cred(tracer)->security; ++ tracercred = __task_cred(tracer); ++ tsp = tracercred->security; + tracer_known = smk_of_task(tsp); + + if ((mode & PTRACE_MODE_ATTACH) && +@@ -439,7 +441,7 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, + rc = 0; + else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) + rc = -EACCES; +- else if (capable(CAP_SYS_PTRACE)) ++ else if (smack_privileged_cred(CAP_SYS_PTRACE, tracercred)) + rc = 0; + else + rc = -EACCES; +@@ -1841,6 +1843,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, + { + struct smack_known *skp; + struct smack_known *tkp = smk_of_task(tsk->cred->security); ++ const struct cred *tcred; + struct file *file; + int rc; + struct smk_audit_info ad; +@@ -1854,8 +1857,12 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, + skp = file->f_security; + rc = smk_access(skp, tkp, MAY_DELIVER, NULL); + rc = smk_bu_note("sigiotask", skp, tkp, MAY_DELIVER, rc); +- if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) ++ ++ rcu_read_lock(); ++ tcred = __task_cred(tsk); ++ if (rc != 0 && smack_privileged_cred(CAP_MAC_OVERRIDE, tcred)) + rc = 0; ++ rcu_read_unlock(); + + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); + smk_ad_setfield_u_tsk(&ad, tsk); +diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h +index 04402c14cb23..9847b669cf3c 100644 +--- a/sound/pci/ca0106/ca0106.h ++++ b/sound/pci/ca0106/ca0106.h +@@ -582,7 +582,7 @@ + #define SPI_PL_BIT_R_R (2<<7) /* right channel = right */ + #define SPI_PL_BIT_R_C (3<<7) /* right channel = (L+R)/2 */ + #define SPI_IZD_REG 2 +-#define SPI_IZD_BIT (1<<4) /* infinite zero detect */ ++#define SPI_IZD_BIT (0<<4) /* infinite zero detect */ + + #define SPI_FMT_REG 3 + #define SPI_FMT_BIT_RJ (0<<0) /* right justified mode */ +diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h +index a68e75b00ea3..53c3cd28bc99 100644 +--- a/sound/pci/hda/hda_controller.h ++++ b/sound/pci/hda/hda_controller.h +@@ -160,6 +160,7 @@ struct azx { + unsigned int msi:1; + unsigned int probing:1; /* codec probing phase */ + unsigned int snoop:1; ++ unsigned int uc_buffer:1; /* non-cached pages for stream buffers */ + unsigned int align_buffer_size:1; + unsigned int region_requested:1; + unsigned int disabled:1; /* disabled by vga_switcheroo */ +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index aa4c672dbaf7..625cb6c7b7d6 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -412,7 +412,7 @@ static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool + #ifdef CONFIG_SND_DMA_SGBUF + if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) { + struct snd_sg_buf *sgbuf = dmab->private_data; +- if (chip->driver_type == AZX_DRIVER_CMEDIA) ++ if (!chip->uc_buffer) + return; /* deal with only CORB/RIRB buffers */ + if (on) + set_pages_array_wc(sgbuf->page_table, sgbuf->pages); +@@ -1678,6 +1678,7 @@ static void azx_check_snoop_available(struct azx *chip) + dev_info(chip->card->dev, "Force to %s mode by module option\n", + snoop ? "snoop" : "non-snoop"); + chip->snoop = snoop; ++ chip->uc_buffer = !snoop; + return; + } + +@@ -1698,8 +1699,12 @@ static void azx_check_snoop_available(struct azx *chip) + snoop = false; + + chip->snoop = snoop; +- if (!snoop) ++ if (!snoop) { + dev_info(chip->card->dev, "Force to non-snoop mode\n"); ++ /* C-Media requires non-cached pages only for CORB/RIRB */ ++ if (chip->driver_type != AZX_DRIVER_CMEDIA) ++ chip->uc_buffer = true; ++ } + } + + static void azx_probe_work(struct work_struct *work) +@@ -2138,7 +2143,7 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream, + #ifdef CONFIG_X86 + struct azx_pcm *apcm = snd_pcm_substream_chip(substream); + struct azx *chip = apcm->chip; +- if (!azx_snoop(chip) && chip->driver_type != AZX_DRIVER_CMEDIA) ++ if (chip->uc_buffer) + area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); + #endif + } +@@ -2257,8 +2262,12 @@ static struct snd_pci_quirk power_save_blacklist[] = { + /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */ + SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0), + /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ ++ SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0), ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ + /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */ + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P55A-UD3 / Z87-D3HP", 0), ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ ++ SND_PCI_QUIRK(0x8086, 0x2040, "Intel DZ77BH-55K", 0), + /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */ + SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0), + /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */ +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index cfd4e4f97f8f..3c5f2a603754 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -943,6 +943,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { + SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD), ++ SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 3ac7ba9b342d..1070749c3cf4 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6841,6 +6841,12 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { + {0x1a, 0x02a11040}, + {0x1b, 0x01014020}, + {0x21, 0x0221101f}), ++ SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION, ++ {0x14, 0x90170110}, ++ {0x19, 0x02a11030}, ++ {0x1a, 0x02a11040}, ++ {0x1b, 0x01011020}, ++ {0x21, 0x0221101f}), + SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC294_FIXUP_LENOVO_MIC_LOCATION, + {0x14, 0x90170110}, + {0x19, 0x02a11020}, +@@ -7738,6 +7744,8 @@ enum { + ALC662_FIXUP_ASUS_Nx50, + ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE, + ALC668_FIXUP_ASUS_Nx51, ++ ALC668_FIXUP_MIC_COEF, ++ ALC668_FIXUP_ASUS_G751, + ALC891_FIXUP_HEADSET_MODE, + ALC891_FIXUP_DELL_MIC_NO_PRESENCE, + ALC662_FIXUP_ACER_VERITON, +@@ -8007,6 +8015,23 @@ static const struct hda_fixup alc662_fixups[] = { + .chained = true, + .chain_id = ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE, + }, ++ [ALC668_FIXUP_MIC_COEF] = { ++ .type = HDA_FIXUP_VERBS, ++ .v.verbs = (const struct hda_verb[]) { ++ { 0x20, AC_VERB_SET_COEF_INDEX, 0xc3 }, ++ { 0x20, AC_VERB_SET_PROC_COEF, 0x4000 }, ++ {} ++ }, ++ }, ++ [ALC668_FIXUP_ASUS_G751] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x16, 0x0421101f }, /* HP */ ++ {} ++ }, ++ .chained = true, ++ .chain_id = ALC668_FIXUP_MIC_COEF ++ }, + [ALC891_FIXUP_HEADSET_MODE] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_headset_mode, +@@ -8080,6 +8105,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50), + SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), + SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50), ++ SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751), + SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), + SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), + SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51), +diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c +index 97f49b751e6e..568575b72f2f 100644 +--- a/sound/pci/hda/thinkpad_helper.c ++++ b/sound/pci/hda/thinkpad_helper.c +@@ -58,8 +58,8 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, + removefunc = false; + } + if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0 && +- snd_hda_gen_add_micmute_led(codec, +- update_tpacpi_micmute) > 0) ++ !snd_hda_gen_add_micmute_led(codec, ++ update_tpacpi_micmute)) + removefunc = false; + } + +diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c +index 77b265bd0505..3135e9eafd18 100644 +--- a/sound/soc/amd/acp-pcm-dma.c ++++ b/sound/soc/amd/acp-pcm-dma.c +@@ -1036,16 +1036,22 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + period_bytes = frames_to_bytes(runtime, runtime->period_size); +- dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr); +- if (dscr == rtd->dma_dscr_idx_1) +- pos = period_bytes; +- else +- pos = 0; + bytescount = acp_get_byte_count(rtd); +- if (bytescount > rtd->bytescount) ++ if (bytescount >= rtd->bytescount) + bytescount -= rtd->bytescount; +- delay = do_div(bytescount, period_bytes); +- runtime->delay = bytes_to_frames(runtime, delay); ++ if (bytescount < period_bytes) { ++ pos = 0; ++ } else { ++ dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr); ++ if (dscr == rtd->dma_dscr_idx_1) ++ pos = period_bytes; ++ else ++ pos = 0; ++ } ++ if (bytescount > 0) { ++ delay = do_div(bytescount, period_bytes); ++ runtime->delay = bytes_to_frames(runtime, delay); ++ } + } else { + buffersize = frames_to_bytes(runtime, runtime->buffer_size); + bytescount = acp_get_byte_count(rtd); +diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c +index d5035f2f2b2b..ce508b4cc85c 100644 +--- a/sound/soc/codecs/sta32x.c ++++ b/sound/soc/codecs/sta32x.c +@@ -879,6 +879,9 @@ static int sta32x_probe(struct snd_soc_component *component) + struct sta32x_priv *sta32x = snd_soc_component_get_drvdata(component); + struct sta32x_platform_data *pdata = sta32x->pdata; + int i, ret = 0, thermal = 0; ++ ++ sta32x->component = component; ++ + ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), + sta32x->supplies); + if (ret != 0) { +diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c +index 2620d77729c5..f99c600f86e4 100644 +--- a/sound/soc/intel/skylake/skl-topology.c ++++ b/sound/soc/intel/skylake/skl-topology.c +@@ -2461,6 +2461,7 @@ static int skl_tplg_get_token(struct device *dev, + + case SKL_TKN_U8_CORE_ID: + mconfig->core_id = tkn_elem->value; ++ break; + + case SKL_TKN_U8_MOD_TYPE: + mconfig->m_type = tkn_elem->value; +diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh +index 3013ac8f83d0..cab7b0aea6ea 100755 +--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh ++++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh +@@ -48,7 +48,7 @@ trace_libc_inet_pton_backtrace() { + *) + eventattr='max-stack=3' + echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected +- echo ".*\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected ++ echo ".*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$" >> $expected + ;; + esac + +diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c +index 3d1cf5bf7f18..9005fbe0780e 100644 +--- a/tools/perf/util/strbuf.c ++++ b/tools/perf/util/strbuf.c +@@ -98,19 +98,25 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) + + va_copy(ap_saved, ap); + len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); +- if (len < 0) ++ if (len < 0) { ++ va_end(ap_saved); + return len; ++ } + if (len > strbuf_avail(sb)) { + ret = strbuf_grow(sb, len); +- if (ret) ++ if (ret) { ++ va_end(ap_saved); + return ret; ++ } + len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); + va_end(ap_saved); + if (len > strbuf_avail(sb)) { + pr_debug("this should not happen, your vsnprintf is broken"); ++ va_end(ap_saved); + return -EINVAL; + } + } ++ va_end(ap_saved); + return strbuf_setlen(sb, sb->len + len); + } + +diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c +index 7b0ca7cbb7de..8ad8e755127b 100644 +--- a/tools/perf/util/trace-event-info.c ++++ b/tools/perf/util/trace-event-info.c +@@ -531,12 +531,14 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs, + "/tmp/perf-XXXXXX"); + if (!mkstemp(tdata->temp_file)) { + pr_debug("Can't make temp file"); ++ free(tdata); + return NULL; + } + + temp_fd = open(tdata->temp_file, O_RDWR); + if (temp_fd < 0) { + pr_debug("Can't read '%s'", tdata->temp_file); ++ free(tdata); + return NULL; + } + +diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c +index e76214f8d596..b15a9bf1837b 100644 +--- a/tools/perf/util/trace-event-parse.c ++++ b/tools/perf/util/trace-event-parse.c +@@ -158,6 +158,7 @@ void parse_ftrace_printk(struct tep_handle *pevent, + printk = strdup(fmt+1); + line = strtok_r(NULL, "\n", &next); + tep_register_print_string(pevent, printk, addr); ++ free(printk); + } + } + +diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c +index 3dfc1db6b25b..5eb1b2469bba 100644 +--- a/tools/perf/util/trace-event-read.c ++++ b/tools/perf/util/trace-event-read.c +@@ -349,9 +349,12 @@ static int read_event_files(struct tep_handle *pevent) + for (x=0; x < count; x++) { + size = read8(pevent); + ret = read_event_file(pevent, sys, size); +- if (ret) ++ if (ret) { ++ free(sys); + return ret; ++ } + } ++ free(sys); + } + return 0; + } +diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c +index df43cd45d810..ccd08dd00996 100644 +--- a/tools/power/cpupower/utils/cpufreq-info.c ++++ b/tools/power/cpupower/utils/cpufreq-info.c +@@ -200,6 +200,8 @@ static int get_boost_mode(unsigned int cpu) + printf(_(" Boost States: %d\n"), b_states); + printf(_(" Total States: %d\n"), pstate_no); + for (i = 0; i < pstate_no; i++) { ++ if (!pstates[i]) ++ continue; + if (i < b_states) + printf(_(" Pstate-Pb%d: %luMHz (boost state)" + "\n"), i, pstates[i]); +diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c +index bb41cdd0df6b..9607ada5b29a 100644 +--- a/tools/power/cpupower/utils/helpers/amd.c ++++ b/tools/power/cpupower/utils/helpers/amd.c +@@ -33,7 +33,7 @@ union msr_pstate { + unsigned vid:8; + unsigned iddval:8; + unsigned idddiv:2; +- unsigned res1:30; ++ unsigned res1:31; + unsigned en:1; + } fam17h_bits; + unsigned long long val; +@@ -119,6 +119,11 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family, + } + if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val)) + return -1; ++ if ((cpu_family == 0x17) && (!pstate.fam17h_bits.en)) ++ continue; ++ else if (!pstate.bits.en) ++ continue; ++ + pstates[i] = get_cof(cpu_family, pstate); + } + *no = i; +diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc +index cef11377dcbd..c604438df13b 100644 +--- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc ++++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc +@@ -35,18 +35,18 @@ fi + + reset_trigger + +-echo "Test create synthetic event with an error" +-echo 'wakeup_latency u64 lat pid_t pid char' > synthetic_events > /dev/null ++echo "Test remove synthetic event" ++echo '!wakeup_latency u64 lat pid_t pid char comm[16]' >> synthetic_events + if [ -d events/synthetic/wakeup_latency ]; then +- fail "Created wakeup_latency synthetic event with an invalid format" ++ fail "Failed to delete wakeup_latency synthetic event" + fi + + reset_trigger + +-echo "Test remove synthetic event" +-echo '!wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events ++echo "Test create synthetic event with an error" ++echo 'wakeup_latency u64 lat pid_t pid char' > synthetic_events > /dev/null + if [ -d events/synthetic/wakeup_latency ]; then +- fail "Failed to delete wakeup_latency synthetic event" ++ fail "Created wakeup_latency synthetic event with an invalid format" + fi + + do_reset +diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c +index 327fa943c7f3..dbdffa2e2c82 100644 +--- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c ++++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c +@@ -67,8 +67,8 @@ trans: + "3: ;" + : [res] "=r" (result), [texasr] "=r" (texasr) + : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), [gpr_4]"i"(GPR_4), +- [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "r" (&a), +- [flt_2] "r" (&b), [flt_4] "r" (&d) ++ [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "b" (&a), ++ [flt_4] "b" (&d) + : "memory", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", +diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c +index c92053bc3f96..8fb31a7cc22c 100644 +--- a/virt/kvm/arm/arm.c ++++ b/virt/kvm/arm/arm.c +@@ -1295,8 +1295,6 @@ static void cpu_init_hyp_mode(void *dummy) + + __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr); + __cpu_init_stage2(); +- +- kvm_arm_init_debug(); + } + + static void cpu_hyp_reset(void) +@@ -1320,6 +1318,8 @@ static void cpu_hyp_reinit(void) + cpu_init_hyp_mode(NULL); + } + ++ kvm_arm_init_debug(); ++ + if (vgic_present) + kvm_vgic_init_cpu_hardware(); + } +diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c +index ed162a6c57c5..2f405b0be25c 100644 +--- a/virt/kvm/arm/mmu.c ++++ b/virt/kvm/arm/mmu.c +@@ -1230,8 +1230,14 @@ static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap) + { + kvm_pfn_t pfn = *pfnp; + gfn_t gfn = *ipap >> PAGE_SHIFT; ++ struct page *page = pfn_to_page(pfn); + +- if (PageTransCompoundMap(pfn_to_page(pfn))) { ++ /* ++ * PageTransCompoungMap() returns true for THP and ++ * hugetlbfs. Make sure the adjustment is done only for THP ++ * pages. ++ */ ++ if (!PageHuge(page) && PageTransCompoundMap(page)) { + unsigned long mask; + /* + * The address we faulted on is backed by a transparent huge diff --git a/patch/kernel/sunxi-dev/ths-21-sun4i-gpadc-iio-add-split-sun8i.patch b/patch/kernel/sunxi-dev/ths-21-sun4i-gpadc-iio-add-split-sun8i.patch deleted file mode 100644 index 71192541c..000000000 --- a/patch/kernel/sunxi-dev/ths-21-sun4i-gpadc-iio-add-split-sun8i.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c -index 81d4c39e414a..41769bc6a429 100644 ---- a/drivers/iio/adc/sun4i-gpadc-iio.c -+++ b/drivers/iio/adc/sun4i-gpadc-iio.c -@@ -88,7 +88,7 @@ static const struct gpadc_data sun6i_gpadc_data = { - static const struct gpadc_data sun8i_a33_gpadc_data = { - .temp_offset = -1662, - .temp_scale = 162, -- .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN, -+ .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN, - }; - - struct sun4i_gpadc_iio { -diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h -index 139872c2e0fe..d31d962bb7d8 100644 ---- a/include/linux/mfd/sun4i-gpadc.h -+++ b/include/linux/mfd/sun4i-gpadc.h -@@ -38,9 +38,9 @@ - #define SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(x) (GENMASK(3, 0) & BIT(x)) - #define SUN6I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(3, 0) - --/* TP_CTRL1 bits for sun8i SoCs */ --#define SUN8I_GPADC_CTRL1_CHOP_TEMP_EN BIT(8) --#define SUN8I_GPADC_CTRL1_GPADC_CALI_EN BIT(7) -+/* TP_CTRL1 bits for sun8i A23/A33 SoCs */ -+#define SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN BIT(8) -+#define SUN8I_A23_GPADC_CTRL1_GPADC_CALI_EN BIT(7) - - #define SUN4I_GPADC_CTRL2 0x08 - diff --git a/patch/kernel/sunxi-dev/ths-22-sun4i-gpadc-iio-add-H3-support.patch b/patch/kernel/sunxi-dev/ths-22-sun4i-gpadc-iio-add-H3-support.patch deleted file mode 100644 index e92345475..000000000 --- a/patch/kernel/sunxi-dev/ths-22-sun4i-gpadc-iio-add-H3-support.patch +++ /dev/null @@ -1,392 +0,0 @@ -diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c -index 75cb089..d7089b7 100644 ---- a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c -+++ b/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c -@@ -22,6 +22,7 @@ - * shutdown for not being used. - */ - -+#include - #include - #include - #include -@@ -31,6 +32,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -49,6 +51,8 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan) - return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan); - } - -+struct sun4i_gpadc_iio; -+ - struct gpadc_data { - int temp_offset; - int temp_scale; -@@ -56,39 +60,12 @@ struct gpadc_data { - unsigned int tp_adc_select; - unsigned int (*adc_chan_select)(unsigned int chan); - unsigned int adc_chan_mask; --}; -- --static const struct gpadc_data sun4i_gpadc_data = { -- .temp_offset = -1932, -- .temp_scale = 133, -- .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, -- .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, -- .adc_chan_select = &sun4i_gpadc_chan_select, -- .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, --}; -- --static const struct gpadc_data sun5i_gpadc_data = { -- .temp_offset = -1447, -- .temp_scale = 100, -- .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, -- .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, -- .adc_chan_select = &sun4i_gpadc_chan_select, -- .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, --}; -- --static const struct gpadc_data sun6i_gpadc_data = { -- .temp_offset = -1623, -- .temp_scale = 167, -- .tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN, -- .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, -- .adc_chan_select = &sun6i_gpadc_chan_select, -- .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, --}; -- --static const struct gpadc_data sun8i_a33_gpadc_data = { -- .temp_offset = -1662, -- .temp_scale = 162, -- .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN, -+ unsigned int temp_data; -+ int (*sample_start)(struct sun4i_gpadc_iio *info); -+ int (*sample_end)(struct sun4i_gpadc_iio *info); -+ bool has_bus_clk; -+ bool has_bus_rst; -+ bool has_mod_clk; - }; - - struct sun4i_gpadc_iio { -@@ -103,6 +80,9 @@ struct sun4i_gpadc_iio { - atomic_t ignore_temp_data_irq; - const struct gpadc_data *data; - bool no_irq; -+ struct clk *ths_bus_clk; -+ struct clk *mod_clk; -+ struct reset_control *reset; - /* prevents concurrent reads of temperature and ADC */ - struct mutex mutex; - struct thermal_zone_device *tzd; -@@ -277,7 +257,7 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val) - if (info->no_irq) { - pm_runtime_get_sync(indio_dev->dev.parent); - -- regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); -+ regmap_read(info->regmap, info->data->temp_data, val); - - pm_runtime_mark_last_busy(indio_dev->dev.parent); - pm_runtime_put_autosuspend(indio_dev->dev.parent); -@@ -385,10 +365,8 @@ out: - return IRQ_HANDLED; - } - --static int sun4i_gpadc_runtime_suspend(struct device *dev) -+static int sun4i_gpadc_sample_end(struct sun4i_gpadc_iio *info) - { -- struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); -- - /* Disable the ADC on IP */ - regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0); - /* Disable temperature sensor on IP */ -@@ -397,10 +375,23 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev) - return 0; - } - --static int sun4i_gpadc_runtime_resume(struct device *dev) -+static int sun8i_h3_gpadc_sample_end(struct sun4i_gpadc_iio *info) -+{ -+ /* Disable temperature sensor */ -+ regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2, 0); -+ -+ return 0; -+} -+ -+static int sun4i_gpadc_runtime_suspend(struct device *dev) - { - struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); - -+ return info->data->sample_end(info); -+} -+ -+static int sun4i_gpadc_sample_start(struct sun4i_gpadc_iio *info) -+{ - /* clkin = 6MHz */ - regmap_write(info->regmap, SUN4I_GPADC_CTRL0, - SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) | -@@ -418,6 +409,29 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) - return 0; - } - -+static int sun8i_h3_gpadc_sample_start(struct sun4i_gpadc_iio *info) -+{ -+ regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2, -+ SUN8I_H3_GPADC_CTRL2_TEMP_SENSE_EN | -+ SUN8I_H3_GPADC_CTRL2_T_ACQ1(31)); -+ regmap_write(info->regmap, SUN4I_GPADC_CTRL0, -+ SUN4I_GPADC_CTRL0_T_ACQ(31)); -+ regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL3, -+ SUN4I_GPADC_CTRL3_FILTER_EN | -+ SUN4I_GPADC_CTRL3_FILTER_TYPE(1)); -+ regmap_write(info->regmap, SUN8I_H3_GPADC_INTC, -+ SUN8I_H3_GPADC_INTC_TEMP_PERIOD(800)); -+ -+ return 0; -+} -+ -+static int sun4i_gpadc_runtime_resume(struct device *dev) -+{ -+ struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); -+ -+ return info->data->sample_start(info); -+} -+ - static int sun4i_gpadc_get_temp(void *data, int *temp) - { - struct sun4i_gpadc_iio *info = data; -@@ -492,11 +506,78 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, - return 0; - } - -+static const struct gpadc_data sun4i_gpadc_data = { -+ .temp_offset = -1932, -+ .temp_scale = 133, -+ .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, -+ .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, -+ .adc_chan_select = &sun4i_gpadc_chan_select, -+ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, -+ .temp_data = SUN4I_GPADC_TEMP_DATA, -+ .sample_start = sun4i_gpadc_sample_start, -+ .sample_end = sun4i_gpadc_sample_end, -+}; -+ -+static const struct gpadc_data sun5i_gpadc_data = { -+ .temp_offset = -1447, -+ .temp_scale = 100, -+ .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, -+ .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, -+ .adc_chan_select = &sun4i_gpadc_chan_select, -+ .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, -+ .temp_data = SUN4I_GPADC_TEMP_DATA, -+ .sample_start = sun4i_gpadc_sample_start, -+ .sample_end = sun4i_gpadc_sample_end, -+}; -+ -+static const struct gpadc_data sun6i_gpadc_data = { -+ .temp_offset = -1623, -+ .temp_scale = 167, -+ .tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN, -+ .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, -+ .adc_chan_select = &sun6i_gpadc_chan_select, -+ .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, -+ .temp_data = SUN4I_GPADC_TEMP_DATA, -+ .sample_start = sun4i_gpadc_sample_start, -+ .sample_end = sun4i_gpadc_sample_end, -+}; -+ -+static const struct gpadc_data sun8i_a33_gpadc_data = { -+ .temp_offset = -1662, -+ .temp_scale = 162, -+ .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN, -+ .temp_data = SUN4I_GPADC_TEMP_DATA, -+ .sample_start = sun4i_gpadc_sample_start, -+ .sample_end = sun4i_gpadc_sample_end, -+}; -+ -+static const struct gpadc_data sun8i_h3_gpadc_data = { -+ /* -+ * The original formula on the datasheet seems to be wrong. -+ * These factors are calculated based on the formula in the BSP -+ * kernel, which is originally Tem = 217 - (T / 8.253), in which Tem -+ * is the temperature in Celsius degree and T is the raw value -+ * from the sensor. -+ */ -+ .temp_offset = -1791, -+ .temp_scale = -121, -+ .temp_data = SUN8I_H3_GPADC_TEMP_DATA, -+ .sample_start = sun8i_h3_gpadc_sample_start, -+ .sample_end = sun8i_h3_gpadc_sample_end, -+ .has_bus_clk = true, -+ .has_bus_rst = true, -+ .has_mod_clk = true, -+}; -+ - static const struct of_device_id sun4i_gpadc_of_id[] = { - { - .compatible = "allwinner,sun8i-a33-ths", - .data = &sun8i_a33_gpadc_data, - }, -+ { -+ .compatible = "allwinner,sun8i-h3-ths", -+ .data = &sun8i_h3_gpadc_data, -+ }, - { /* sentinel */ } - }; - -@@ -529,10 +610,72 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, - return ret; - } - -+ if (info->data->has_bus_rst) { -+ info->reset = devm_reset_control_get(&pdev->dev, NULL); -+ if (IS_ERR(info->reset)) { -+ ret = PTR_ERR(info->reset); -+ return ret; -+ } -+ -+ ret = reset_control_deassert(info->reset); -+ if (ret) -+ return ret; -+ } -+ -+ if (info->data->has_bus_clk) { -+ info->ths_bus_clk = devm_clk_get(&pdev->dev, "bus"); -+ if (IS_ERR(info->ths_bus_clk)) { -+ ret = PTR_ERR(info->ths_bus_clk); -+ goto assert_reset; -+ } -+ -+ ret = clk_prepare_enable(info->ths_bus_clk); -+ if (ret) -+ goto assert_reset; -+ } -+ -+ if (info->data->has_mod_clk) { -+ info->mod_clk = devm_clk_get(&pdev->dev, "mod"); -+ if (IS_ERR(info->mod_clk)) { -+ ret = PTR_ERR(info->mod_clk); -+ goto disable_bus_clk; -+ } -+ -+ /* Running at 6MHz */ -+ ret = clk_set_rate(info->mod_clk, 6000000); -+ if (ret) -+ goto disable_bus_clk; -+ -+ ret = clk_prepare_enable(info->mod_clk); -+ if (ret) -+ goto disable_bus_clk; -+ } -+ - if (IS_ENABLED(CONFIG_THERMAL_OF)) - info->sensor_device = &pdev->dev; - -+ if (IS_ERR(info->tzd)) { -+ dev_err(&pdev->dev, "could not register thermal sensor: %ld\n", -+ PTR_ERR(info->tzd)); -+ ret = PTR_ERR(info->tzd); -+ goto disable_mod_clk; -+ } -+ - return 0; -+ -+disable_mod_clk: -+ if (info->data->has_mod_clk) -+ clk_disable_unprepare(info->mod_clk); -+ -+disable_bus_clk: -+ if (info->data->has_bus_clk) -+ clk_disable_unprepare(info->ths_bus_clk); -+ -+assert_reset: -+ if (info->data->has_bus_rst) -+ reset_control_assert(info->reset); -+ -+ return ret; - } - - static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, -@@ -698,6 +841,15 @@ static int sun4i_gpadc_remove(struct platform_device *pdev) - if (!info->no_irq) - iio_map_array_unregister(indio_dev); - -+ if (info->data->has_mod_clk) -+ clk_disable_unprepare(info->mod_clk); -+ -+ if (info->data->has_bus_clk) -+ clk_disable_unprepare(info->ths_bus_clk); -+ -+ if (info->data->has_bus_rst) -+ reset_control_assert(info->reset); -+ - return 0; - } - -diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd2/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd2/sun4i-gpadc.h -index d31d962..f794a29 100644 ---- a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd2/sun4i-gpadc.h -+++ b/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd2/sun4i-gpadc.h -@@ -42,6 +42,9 @@ - #define SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN BIT(8) - #define SUN8I_A23_GPADC_CTRL1_GPADC_CALI_EN BIT(7) - -+/* TP_CTRL1 bits for SoCs after H3 */ -+#define SUN8I_H3_GPADC_CTRL1_GPADC_CALI_EN BIT(17) -+ - #define SUN4I_GPADC_CTRL2 0x08 - - #define SUN4I_GPADC_CTRL2_TP_SENSITIVE_ADJUST(x) ((GENMASK(3, 0) & (x)) << 28) -@@ -49,7 +52,17 @@ - #define SUN4I_GPADC_CTRL2_PRE_MEA_EN BIT(24) - #define SUN4I_GPADC_CTRL2_PRE_MEA_THRE_CNT(x) (GENMASK(23, 0) & (x)) - -+#define SUN8I_H3_GPADC_CTRL2 0x40 -+ -+#define SUN8I_H3_GPADC_CTRL2_TEMP_SENSE_EN BIT(0) -+#define SUN8I_H3_GPADC_CTRL2_T_ACQ1(x) ((GENMASK(15, 0) * (x)) << 16) -+ - #define SUN4I_GPADC_CTRL3 0x0c -+/* -+ * This register is named "Average filter Control Register" in H3 Datasheet, -+ * but the register's definition is the same as the old CTRL3 register. -+ */ -+#define SUN8I_H3_GPADC_CTRL3 0x70 - - #define SUN4I_GPADC_CTRL3_FILTER_EN BIT(2) - #define SUN4I_GPADC_CTRL3_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) -@@ -71,6 +84,13 @@ - #define SUN4I_GPADC_INT_FIFOC_TP_UP_IRQ_EN BIT(1) - #define SUN4I_GPADC_INT_FIFOC_TP_DOWN_IRQ_EN BIT(0) - -+#define SUN8I_H3_GPADC_INTC 0x44 -+ -+#define SUN8I_H3_GPADC_INTC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12) -+#define SUN8I_H3_GPADC_INTC_TEMP_DATA BIT(8) -+#define SUN8I_H3_GPADC_INTC_TEMP_SHUT BIT(4) -+#define SUN8I_H3_GPADC_INTC_TEMP_ALARM BIT(0) -+ - #define SUN4I_GPADC_INT_FIFOS 0x14 - - #define SUN4I_GPADC_INT_FIFOS_TEMP_DATA_PENDING BIT(18) -@@ -80,9 +100,16 @@ - #define SUN4I_GPADC_INT_FIFOS_TP_UP_PENDING BIT(1) - #define SUN4I_GPADC_INT_FIFOS_TP_DOWN_PENDING BIT(0) - -+#define SUN8I_H3_GPADC_INTS 0x44 -+ -+#define SUN8I_H3_GPADC_INTS_TEMP_DATA BIT(8) -+#define SUN8I_H3_GPADC_INTS_TEMP_SHUT BIT(4) -+#define SUN8I_H3_GPADC_INTS_TEMP_ALARM BIT(0) -+ - #define SUN4I_GPADC_CDAT 0x1c - #define SUN4I_GPADC_TEMP_DATA 0x20 - #define SUN4I_GPADC_DATA 0x24 -+#define SUN8I_H3_GPADC_TEMP_DATA 0x80 - - #define SUN4I_GPADC_IRQ_FIFO_DATA 0 - #define SUN4I_GPADC_IRQ_TEMP_DATA 1 diff --git a/patch/kernel/sunxi-dev/ths-23-sun4i-gpadc-iio-add-H3-thermal-sensor-DT.patch b/patch/kernel/sunxi-dev/ths-23-sun4i-gpadc-iio-add-H3-thermal-sensor-DT.patch deleted file mode 100644 index 985438292..000000000 --- a/patch/kernel/sunxi-dev/ths-23-sun4i-gpadc-iio-add-H3-thermal-sensor-DT.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi -index a0cee17fe44b..efe3a8e4f2af 100644 ---- a/arch/arm/boot/dts/sun8i-h3.dtsi -+++ b/arch/arm/boot/dts/sun8i-h3.dtsi -@@ -108,6 +108,23 @@ - }; - }; - -+ iio-hwmon { -+ compatible = "iio-hwmon"; -+ io-channels = <&ths>; -+ }; -+ -+ soc { -+ ths: thermal-sensor@1c25000 { -+ compatible = "allwinner,sun8i-h3-ths"; -+ reg = <0x01c25000 0x100>; -+ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; -+ clock-names = "bus", "mod"; -+ resets = <&ccu RST_BUS_THS>; -+ #thermal-sensor-cells = <0>; -+ #io-channel-cells = <0>; -+ }; -+ }; -+ - timer { - compatible = "arm,armv7-timer"; - interrupts = , diff --git a/patch/kernel/sunxi-dev/ths-24-sun4i-gpadc-iio-add-H3-CPU-thermal-zone.patch b/patch/kernel/sunxi-dev/ths-24-sun4i-gpadc-iio-add-H3-CPU-thermal-zone.patch deleted file mode 100644 index 35e135b16..000000000 --- a/patch/kernel/sunxi-dev/ths-24-sun4i-gpadc-iio-add-H3-CPU-thermal-zone.patch +++ /dev/null @@ -1,93 +0,0 @@ -diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi -index b36f9f423..0ad8e3e80 100644 ---- a/arch/arm/boot/dts/sun8i-h3.dtsi -+++ b/arch/arm/boot/dts/sun8i-h3.dtsi -@@ -41,6 +41,7 @@ - */ - - #include "sunxi-h3-h5.dtsi" -+#include - - / { - cpus { -@@ -72,6 +73,80 @@ - }; - }; - -+ thermal-zones { -+ cpu-thermal { -+ /* milliseconds */ -+ polling-delay-passive = <250>; -+ polling-delay = <1000>; -+ thermal-sensors = <&ths>; -+ -+ trips { -+ cpu_warm: cpu_warm { -+ temperature = <65000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ -+ cpu_hot_pre: cpu_hot_pre { -+ temperature = <70000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ -+ cpu_hot: cpu_hot { -+ temperature = <75000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ -+ cpu_very_hot_pre: cpu_very_hot_pre { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ -+ cpu_very_hot: cpu_very_hot { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ -+ cpu_crit: cpu_crit { -+ temperature = <105000>; -+ hysteresis = <2000>; -+ type = "critical"; -+ }; -+ }; -+ -+ cooling-maps { -+ cpu_warm_limit_cpu { -+ trip = <&cpu_warm>; -+ cooling-device = <&cpu0 THERMAL_NO_LIMIT 2>; -+ }; -+ -+ cpu_hot_pre_limit_cpu { -+ trip = <&cpu_hot_pre>; -+ cooling-device = <&cpu0 2 3>; -+ }; -+ -+ cpu_hot_limit_cpu { -+ trip = <&cpu_hot>; -+ cooling-device = <&cpu0 3 4>; -+ }; -+ -+ cpu_very_hot_pre_limit_cpu { -+ trip = <&cpu_very_hot>; -+ cooling-device = <&cpu0 5 6>; -+ }; -+ -+ cpu_very_hot_limit_cpu { -+ trip = <&cpu_very_hot>; -+ cooling-device = <&cpu0 7 THERMAL_NO_LIMIT>; -+ }; -+ }; -+ }; -+ }; -+ - timer { - compatible = "arm,armv7-timer"; - interrupts = , diff --git a/patch/kernel/sunxi-dev/ths-25-sun4i-gpadc-iio-workaround-for-raw-0-read.patch b/patch/kernel/sunxi-dev/ths-25-sun4i-gpadc-iio-workaround-for-raw-0-read.patch deleted file mode 100644 index cdb8c3960..000000000 --- a/patch/kernel/sunxi-dev/ths-25-sun4i-gpadc-iio-workaround-for-raw-0-read.patch +++ /dev/null @@ -1,34 +0,0 @@ -From e42ea77a5f2b389eed2c9004eab80bf6589ebf5a Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Tue, 1 Aug 2017 23:42:12 +0800 -Subject: [PATCH] iio: adc: sun4i-gpadc: workaroud bogus THS raw value 0 - readout - -When booting the system, the THS may read out a bogus false value which -is raw value 0. - -On H3 it represents a extremely high temperature and can shutdown the -system immediately. - -Workaround it by make it return -EINVAL when the raw value is 0 (which -is unlikely to happen). - -Signed-off-by: Icenowy Zheng ---- - drivers/iio/adc/sun4i-gpadc-iio.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c -index f378ca0bc0b30..a89dcb6fba4ec 100644 ---- a/drivers/iio/adc/sun4i-gpadc-iio.c -+++ b/drivers/iio/adc/sun4i-gpadc-iio.c -@@ -262,6 +262,9 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val) - pm_runtime_mark_last_busy(indio_dev->dev.parent); - pm_runtime_put_autosuspend(indio_dev->dev.parent); - -+ if (!*val) -+ return -EINVAL; -+ - return 0; - } - diff --git a/patch/kernel/sunxi-dev/ths-26-sun4i-gpadc-iio-add-h5-a64-support.patch b/patch/kernel/sunxi-dev/ths-26-sun4i-gpadc-iio-add-h5-a64-support.patch deleted file mode 100644 index f96280896..000000000 --- a/patch/kernel/sunxi-dev/ths-26-sun4i-gpadc-iio-add-h5-a64-support.patch +++ /dev/null @@ -1,153 +0,0 @@ -diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c -index a89dcb6fb..dbe41fdf2 100644 ---- a/drivers/iio/adc/sun4i-gpadc-iio.c -+++ b/drivers/iio/adc/sun4i-gpadc-iio.c -@@ -56,6 +56,7 @@ struct sun4i_gpadc_iio; - struct gpadc_data { - int temp_offset; - int temp_scale; -+ int temp_divider; - unsigned int tp_mode_en; - unsigned int tp_adc_select; - unsigned int (*adc_chan_select)(unsigned int chan); -@@ -63,6 +64,7 @@ struct gpadc_data { - unsigned int temp_data; - int (*sample_start)(struct sun4i_gpadc_iio *info); - int (*sample_end)(struct sun4i_gpadc_iio *info); -+ void (*reg_to_temp)(int val, int *temp); - bool has_bus_clk; - bool has_bus_rst; - bool has_mod_clk; -@@ -289,6 +291,15 @@ static int sun4i_gpadc_temp_scale(struct iio_dev *indio_dev, int *val) - return 0; - } - -+static int sun4i_gpadc_temp_divider(struct iio_dev *indio_dev, int *val) -+{ -+ struct sun4i_gpadc_iio *info = iio_priv(indio_dev); -+ -+ *val = info->data->temp_divider; -+ -+ return 0; -+} -+ - static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, - int *val2, long mask) -@@ -436,19 +447,32 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) - static int sun4i_gpadc_get_temp(void *data, int *temp) - { - struct sun4i_gpadc_iio *info = data; -- int val, scale, offset; -+ int val, scale, offset, divider; - - if (sun4i_gpadc_temp_read(info->indio_dev, &val)) - return -ETIMEDOUT; - - sun4i_gpadc_temp_scale(info->indio_dev, &scale); - sun4i_gpadc_temp_offset(info->indio_dev, &offset); -+ sun4i_gpadc_temp_divider(info->indio_dev, ÷r); - -- *temp = (val + offset) * scale; -+ if (info->data->reg_to_temp) -+ info->data->reg_to_temp(val, temp); -+ else -+ *temp = ((val + offset) * scale) / divider; - - return 0; - } - -+void sun50i_h5_reg_to_temp(int val, int *temp) -+{ -+ u32 data = (u32)val; -+ if (data <= 0x500) -+ *temp = (2590000 - 1452 * data) / 10000; -+ else -+ *temp = (2230000 - 1191 * data) / 10000; -+} -+ - static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = { - .get_temp = &sun4i_gpadc_get_temp, - }; -@@ -510,6 +534,7 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, - static const struct gpadc_data sun4i_gpadc_data = { - .temp_offset = -1932, - .temp_scale = 133, -+ .temp_divider = 1, - .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, - .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, - .adc_chan_select = &sun4i_gpadc_chan_select, -@@ -522,6 +547,7 @@ static const struct gpadc_data sun4i_gpadc_data = { - static const struct gpadc_data sun5i_gpadc_data = { - .temp_offset = -1447, - .temp_scale = 100, -+ .temp_divider = 1, - .tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN, - .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, - .adc_chan_select = &sun4i_gpadc_chan_select, -@@ -534,6 +560,7 @@ static const struct gpadc_data sun5i_gpadc_data = { - static const struct gpadc_data sun6i_gpadc_data = { - .temp_offset = -1623, - .temp_scale = 167, -+ .temp_divider = 1, - .tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN, - .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, - .adc_chan_select = &sun6i_gpadc_chan_select, -@@ -546,6 +573,7 @@ static const struct gpadc_data sun6i_gpadc_data = { - static const struct gpadc_data sun8i_a33_gpadc_data = { - .temp_offset = -1662, - .temp_scale = 162, -+ .temp_divider = 1, - .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN, - .temp_data = SUN4I_GPADC_TEMP_DATA, - .sample_start = sun4i_gpadc_sample_start, -@@ -562,6 +590,34 @@ static const struct gpadc_data sun8i_h3_gpadc_data = { - */ - .temp_offset = -1791, - .temp_scale = -121, -+ .temp_divider = 1, -+ .temp_data = SUN8I_H3_GPADC_TEMP_DATA, -+ .sample_start = sun8i_h3_gpadc_sample_start, -+ .sample_end = sun8i_h3_gpadc_sample_end, -+ .has_bus_clk = true, -+ .has_bus_rst = true, -+ .has_mod_clk = true, -+}; -+ -+static const struct gpadc_data sun50i_a64_gpadc_data = { -+ .temp_offset = -2170, -+ .temp_scale = -1000, -+ .temp_divider = 8560, -+ .temp_data = SUN8I_H3_GPADC_TEMP_DATA, -+ .sample_start = sun8i_h3_gpadc_sample_start, -+ .sample_end = sun8i_h3_gpadc_sample_end, -+ .has_bus_clk = true, -+ .has_bus_rst = true, -+ .has_mod_clk = true, -+}; -+ -+static const struct gpadc_data sun50i_h5_gpadc_data = { -+ /* Not done for now since requires 3 extra fields -+ and/or a custom temperature conversion function -+ */ -+ .temp_offset = -1791, -+ .temp_scale = -121, -+ .temp_divider = 1, - .temp_data = SUN8I_H3_GPADC_TEMP_DATA, - .sample_start = sun8i_h3_gpadc_sample_start, - .sample_end = sun8i_h3_gpadc_sample_end, -@@ -579,6 +635,14 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { - .compatible = "allwinner,sun8i-h3-ths", - .data = &sun8i_h3_gpadc_data, - }, -+ { -+ .compatible = "allwinner,sun50i-a64-ths", -+ .data = &sun50i_a64_gpadc_data, -+ }, -+ { -+ .compatible = "allwinner,sun50i-h5-ths", -+ .data = &sun50i_h5_gpadc_data, -+ }, - { /* sentinel */ } - }; - diff --git a/patch/kernel/sunxi-dev/ths-27-sun4i-gpadc-iio-add-h5-DT.patch b/patch/kernel/sunxi-dev/ths-27-sun4i-gpadc-iio-add-h5-DT.patch deleted file mode 100644 index 719b93a64..000000000 --- a/patch/kernel/sunxi-dev/ths-27-sun4i-gpadc-iio-add-h5-DT.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -index d9a720bf..55b95569 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi -@@ -76,6 +76,23 @@ - }; - }; - -+ iio-hwmon { -+ compatible = "iio-hwmon"; -+ io-channels = <&ths>; -+ }; -+ -+ soc { -+ ths: thermal-sensor@1c25000 { -+ compatible = "allwinner,sun50i-h5-ths"; -+ reg = <0x01c25000 0x100>; -+ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>; -+ clock-names = "bus", "mod"; -+ resets = <&ccu RST_BUS_THS>; -+ #thermal-sensor-cells = <0>; -+ #io-channel-cells = <0>; -+ }; -+ }; -+ - psci { - compatible = "arm,psci-0.2"; - method = "smc"; diff --git a/patch/kernel/sunxi-dev/ths-49-add-h5-cpu-opp-table.patch b/patch/kernel/sunxi-dev/ths-49-add-h5-cpu-opp-table.patch.disabled similarity index 100% rename from patch/kernel/sunxi-dev/ths-49-add-h5-cpu-opp-table.patch rename to patch/kernel/sunxi-dev/ths-49-add-h5-cpu-opp-table.patch.disabled diff --git a/patch/kernel/sunxi-dev/ths-50-add-h5-opp-table-to-cpu.patch b/patch/kernel/sunxi-dev/ths-50-add-h5-opp-table-to-cpu.patch.disabled similarity index 100% rename from patch/kernel/sunxi-dev/ths-50-add-h5-opp-table-to-cpu.patch rename to patch/kernel/sunxi-dev/ths-50-add-h5-opp-table-to-cpu.patch.disabled diff --git a/patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-3001-add-realtek-8189es-kconfig-makefile.patch b/patch/kernel/sunxi-dev/wifi-3001-add-realtek-8189es-kconfig-makefile.patch similarity index 100% rename from patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-3001-add-realtek-8189es-kconfig-makefile.patch rename to patch/kernel/sunxi-dev/wifi-3001-add-realtek-8189es-kconfig-makefile.patch diff --git a/patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-3002-add-realtek-8189es.patch b/patch/kernel/sunxi-dev/wifi-3002-add-realtek-8189es.patch similarity index 98% rename from patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-3002-add-realtek-8189es.patch rename to patch/kernel/sunxi-dev/wifi-3002-add-realtek-8189es.patch index 623ff1a76..33f57ec99 100644 --- a/patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-3002-add-realtek-8189es.patch +++ b/patch/kernel/sunxi-dev/wifi-3002-add-realtek-8189es.patch @@ -340697,7 +340697,7 @@ new file mode 100644 index 0000000..c688861 --- /dev/null +++ b/drivers/net/wireless/rtl8189es/os_dep/linux/os_intfs.c -@@ -0,0 +1,4334 @@ +@@ -0,0 +1,4335 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. @@ -341398,13 +341398,14 @@ index 0000000..c688861 + + +static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) ++ ,struct net_device *sb_dev ++ ,select_queue_fallback_t fallback ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) + , void *accel_priv -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + , select_queue_fallback_t fallback +#endif -+ -+#endif +) +{ + _adapter *padapter = rtw_netdev_priv(dev); diff --git a/patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-4001-add-realtek-8723cs-kconfig-makefile.patch b/patch/kernel/sunxi-dev/wifi-4001-add-realtek-8723cs-kconfig-makefile.patch similarity index 100% rename from patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-4001-add-realtek-8723cs-kconfig-makefile.patch rename to patch/kernel/sunxi-dev/wifi-4001-add-realtek-8723cs-kconfig-makefile.patch diff --git a/patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-4002-add-realtek-8723cs.patch b/patch/kernel/sunxi-dev/wifi-4002-add-realtek-8723cs.patch similarity index 99% rename from patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-4002-add-realtek-8723cs.patch rename to patch/kernel/sunxi-dev/wifi-4002-add-realtek-8723cs.patch index 79fb7b9e4..73eceac86 100644 --- a/patch/kernel/sunxi-dev/wireless_need_adjustement_for_4.19_TBD/wifi-4002-add-realtek-8723cs.patch +++ b/patch/kernel/sunxi-dev/wifi-4002-add-realtek-8723cs.patch @@ -332228,7 +332228,7 @@ new file mode 100644 index 00000000..748a4096 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8723cs/os_dep/linux/os_intfs.c -@@ -0,0 +1,4470 @@ +@@ -0,0 +1,4471 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. @@ -333079,13 +333079,14 @@ index 00000000..748a4096 + + +static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) ++ ,struct net_device *sb_dev ++ ,select_queue_fallback_t fallback ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) + , void *accel_priv -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + , select_queue_fallback_t fallback +#endif -+ -+#endif +) +{ + _adapter *padapter = rtw_netdev_priv(dev); diff --git a/patch/kernel/sunxi-dev/wifi-add-realtek-8189fs.patch b/patch/kernel/sunxi-dev/wifi-add-realtek-8189fs.patch index f39dcd5b7..9a0aaae13 100644 --- a/patch/kernel/sunxi-dev/wifi-add-realtek-8189fs.patch +++ b/patch/kernel/sunxi-dev/wifi-add-realtek-8189fs.patch @@ -15,13 +15,13 @@ index 9c78deb..e4de960 100644 --- a/drivers/net/wireless/realtek/Makefile +++ b/drivers/net/wireless/realtek/Makefile @@ -4,6 +4,7 @@ - - obj-$(CONFIG_RTL8180) += rtl818x/ + obj-$(CONFIG_RTL8187) += rtl818x/ -+obj-$(CONFIG_RTL8189FS) += rtl8189fs/ + obj-$(CONFIG_RTL8723CS) += rtl8723cs/ ++obj-$(CONFIG_RTL8189FS) += rtl8189fs/ obj-$(CONFIG_RTLWIFI) += rtlwifi/ obj-$(CONFIG_RTL8XXXU) += rtl8xxxu/ - + diff --git a/drivers/net/wireless/realtek/rtl8189fs/Kconfig b/drivers/net/wireless/realtek/rtl8189fs/Kconfig new file mode 100644 index 0000000..0684b59 diff --git a/patch/kernel/sunxi64-dev/arm64_increasing_DMA_block_memory_allocation_to_2048.patch b/patch/kernel/sunxi64-dev/arm64_increasing_DMA_block_memory_allocation_to_2048.patch deleted file mode 100644 index 652c75bd3..000000000 --- a/patch/kernel/sunxi64-dev/arm64_increasing_DMA_block_memory_allocation_to_2048.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c -index 3216e09..21bce28 ---- a/arch/arm64/mm/dma-mapping.c -+++ b/arch/arm64/mm/dma-mapping.c -@@ -44,7 +44,7 @@ static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot, - - static struct gen_pool *atomic_pool; - --#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K -+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_2M - static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE; - - static int __init early_coherent_pool(char *p) diff --git a/patch/kernel/sunxi64-dev/packaging-4.x-DEV-with-postinstall-scripts.patch b/patch/kernel/sunxi64-dev/packaging-4.x-DEV-with-postinstall-scripts.patch deleted file mode 100644 index d9ca44db5..000000000 --- a/patch/kernel/sunxi64-dev/packaging-4.x-DEV-with-postinstall-scripts.patch +++ /dev/null @@ -1,197 +0,0 @@ -diff --git a/scripts/package/builddeb b/scripts/package/builddeb -index 1845c5d..9dab810 100755 ---- a/scripts/package/builddeb -+++ b/scripts/package/builddeb -@@ -29,6 +29,28 @@ create_package() { - # in case we are in a restrictive umask environment like 0077 - chmod -R a+rX "$pdir" - -+ # Create preinstall and post install script to remove dtb -+ if [[ "$1" == *dtb* ]]; then -+ echo "if [ -d /boot/dtb-$version ]; then mv /boot/dtb-$version /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/preinst -+ echo "if [ -d /boot/dtb.old ]; then rm -rf /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst -+ echo "if [ -d /dtb ]; then mv /dtb /dtb.old; fi" >> $pdir/DEBIAN/preinst -+ echo "if [ -d /boot/dtb ]; then mv /boot/dtb /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst -+ echo "exit 0" >> $pdir/DEBIAN/preinst -+ chmod 775 $pdir/DEBIAN/preinst -+ # -+ echo "if [ -d /boot/dtb-$version.old ]; then rm -rf /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/postinst -+ echo "ln -sf dtb-$version /boot/dtb > /dev/null 2>&1 || mv /boot/dtb-$version /boot/dtb" >> $pdir/DEBIAN/postinst -+ echo "exit 0" >> $pdir/DEBIAN/postinst -+ chmod 775 $pdir/DEBIAN/postinst -+ fi -+ -+ # Create postinstall script for headers -+ if [[ "$1" == *headers* ]]; then -+ echo "cd /usr/src/linux-headers-$version; echo \"Compiling headers - please wait ...\"; find -type f -exec touch {} +;make -s scripts >/dev/null 2>&1" >> $pdir/DEBIAN/postinst -+ echo "exit 0" >> $pdir/DEBIAN/postinst -+ chmod 775 $pdir/DEBIAN/postinst -+ fi -+ - # Create the package - dpkg-gencontrol $forcearch -Vkernel:debarch="${debarch}" -p$pname -P"$pdir" - dpkg --build "$pdir" .. -@@ -94,10 +116,13 @@ sourcename=$KDEB_SOURCENAME - tmpdir="$objtree/debian/tmp" - kernel_headers_dir="$objtree/debian/hdrtmp" - libc_headers_dir="$objtree/debian/headertmp" -+dtb_dir="$objtree/debian/dtbtmp" - dbg_dir="$objtree/debian/dbgtmp" --packagename=linux-image-$version --kernel_headers_packagename=linux-headers-$version --libc_headers_packagename=linux-libc-dev -+packagename=linux-image-dev"$LOCALVERSION" -+fwpackagename=linux-firmware-image-dev"$LOCALVERSION" -+kernel_headers_packagename=linux-headers-dev"$LOCALVERSION" -+dtb_packagename=linux-dtb-dev"$LOCALVERSION" -+libc_headers_packagename=linux-libc-dev-dev"$LOCALVERSION" - dbg_packagename=$packagename-dbg - debarch= - forcearch= -@@ -124,7 +149,9 @@ esac - BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)" - - # Setup the directory structure --rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files -+rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" $objtree/debian/files -+mkdir -m 755 -p "$dtb_dir/DEBIAN" -+mkdir -p "$dtb_dir/boot/dtb-$version" "$dtb_dir/usr/share/doc/$dtb_packagename" - mkdir -m 755 -p "$tmpdir/DEBIAN" - mkdir -p "$tmpdir/lib" "$tmpdir/boot" - mkdir -p "$kernel_headers_dir/lib/modules/$version/" -@@ -177,6 +204,11 @@ if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then - fi - fi - -+if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then -+ #mkdir -p "$tmpdir/boot/dtb" -+ INSTALL_DTBS_PATH="$dtb_dir/boot/dtb-$version" $MAKE KBUILD_SRC= dtbs_install -+fi -+ - if [ "$ARCH" != "um" ]; then - $MAKE headers_check KBUILD_SRC= - $MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr" -@@ -189,7 +221,7 @@ fi - # so do we; recent versions of dracut and initramfs-tools will obey this. - debhookdir=${KDEB_HOOKDIR:-/etc/kernel} - if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then -- want_initrd=Yes -+ want_initrd=Yes - else - want_initrd=No - fi -@@ -201,9 +233,11 @@ for script in postinst postrm preinst prerm ; do - set -e - - # Pass maintainer script parameters to hook scripts -+ - export DEB_MAINT_PARAMS="\$*" - - # Tell initramfs builder whether it's wanted -+ - export INITRD=$want_initrd - - test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d -@@ -212,6 +246,55 @@ EOF - chmod 755 "$tmpdir/DEBIAN/$script" - done - -+## -+## Create sym link to kernel image -+## -+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/postinst -+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst -+cat >> $tmpdir/DEBIAN/postinst < /dev/null 2>&1 -+cp /boot/uImage /tmp/uImage -+sync -+mountpoint -q /boot || mount /boot -+cp /tmp/uImage /boot/uImage -+rm -f /$installed_image_path -+else -+ln -sf $(basename $installed_image_path) /boot/Image > /dev/null 2>&1 || mv /$installed_image_path /boot/Image -+fi -+touch /boot/.next -+exit 0 -+EOT -+## -+## FAT install workaround -+## -+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/preinst -+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst -+cat >> $tmpdir/DEBIAN/preinst <> $tmpdir/DEBIAN/preinst -+ - # Try to determine maintainer and email values - if [ -n "$DEBEMAIL" ]; then - email=$DEBEMAIL -@@ -325,12 +408,20 @@ if grep -q '^CONFIG_GCC_PLUGINS=y' $KCONFIG_CONFIG ; then - fi - destdir=$kernel_headers_dir/usr/src/linux-headers-$version - mkdir -p "$destdir" -+######################## headers patch -+ZACNI=$(pwd) -+cd $destdir -+patch -p1 < /tmp/headers-debian-byteshift.patch -+cd $ZACNI -+######################## headers patch - (cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -) - (cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -) - (cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be - ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build" - rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" - -+(cd "$destdir"; make M=scripts clean) -+ - cat <> debian/control - - Package: $kernel_headers_packagename -@@ -343,6 +434,16 @@ EOF - - cat <> debian/control - -+Package: $dtb_packagename -+Architecture: any -+Description: Linux DTB, version $version -+ This package contains device blobs from the Linux kernel, version $version. -+EOF -+ -+create_package "$dtb_packagename" "$dtb_dir" -+ -+cat <> debian/control -+ - Package: $libc_headers_packagename - Section: devel - Provides: linux-kernel-headers -@@ -354,7 +455,7 @@ EOF - - if [ "$ARCH" != "um" ]; then - create_package "$kernel_headers_packagename" "$kernel_headers_dir" -- create_package "$libc_headers_packagename" "$libc_headers_dir" -+# create_package "$libc_headers_packagename" "$libc_headers_dir" - fi - - create_package "$packagename" "$tmpdir"